Verwijderd schreef op 19 oktober 2002 @ 19:07:
Nou het kan wel. Maar ik moet mijn eigen IOleObject schrijven... ik ben al even bezig geweest, en bij CodeGuru stond dit stukkie code van een headerfile wat mij mogelijk een heel eind op weg helpt

Maar tja nou zitten we weer in de APIES...
Uhm als je niet extreem vloeiend bent in de API's zou ik dit hele onderwerp maar vergeten als ik jou was... maja ik heb toevallig een maand of 2 terug BCB code geschreven voor het gevraagde onderwerp, dus hierbij wat gestripte code-snippets... alleen te gebruiken natuurlijk met bedankje aan naam en toenaam
De volledige code doet ook complete drag&drop en alles, maar a) het is copyrighted code van me werk, b) daarbij gebruik ik allerhande custom classes die ik er niet bij wil geven en c) we zijn hier geen
www.codevault.com waar je alles voorgekauwd krijgt
Allereerst moet je zorgen dat je een RichEdit 2.0 of hoger opent, VCL standaard doet alleen 1.0. Hiervoor leid ik als volgt een class af:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| //---------------------------------------------------------------------------
// TRichEdit20 class definition
//---------------------------------------------------------------------------
class TRichEdit20 : public TRichEdit
{
public: // Methods
__fastcall TRichEdit20(TComponent* p_Owner);
virtual __fastcall ~TRichEdit20();
void InsertObjectAtCursor(const WideString &p_FileName);
protected: // Methods
virtual void __fastcall CreateParams(Controls::TCreateParams &Params);
virtual void __fastcall CreateWnd(void);
private: // Methods
void HandleDropFiles(HDROP p_DropHandle);
private: // Properties
RIRichEditOle m_RichEditOle;
}; |
RIRichEditOle is een custom class die ik je niet cadeau doe, maar het is iig een reference class naar een IRichEditOle* die automatisch opruiming en reference counting doet. Je kunt dat ook handmatig doen.
De class wordt als volgt geimplementeerd:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
| //---------------------------------------------------------------------------
// TRichEdit20 class implementation (empty constructor)
//---------------------------------------------------------------------------
__fastcall TRichEdit20::TRichEdit20(TComponent* p_Owner)
:TRichEdit(p_Owner)
{
}
//---------------------------------------------------------------------------
// CreateParams: Patches creation to invoke RichEdit 2.0
//---------------------------------------------------------------------------
void __fastcall TRichEdit20::CreateParams(Controls::TCreateParams &Params)
{
try
{
// Hack away at VCL to ensure RichEdit 2.0
TCustomMemo::CreateParams(Params);
CreateSubClass(Params, "RICHEDIT20A");
Params.WindowClass.style &= ~(CS_HREDRAW | CS_VREDRAW);
}
catch(...)
{
// Call direct base implementation if anything goes wrong to create a v1.0
TRichEdit::CreateParams(Params);
}
}
//---------------------------------------------------------------------------
// CreateWnd: Handles control creation and initializes OLE behaviours
//---------------------------------------------------------------------------
void __fastcall TRichEdit20::CreateWnd(void)
{
// Call inherited functionality
TRichEdit::CreateWnd();
// Retrieve the required COM interface
SendMessage(Handle, EM_GETOLEINTERFACE, 0, (LPARAM)&m_RichEditOle);
} |
Dit was allemaal redelijk straightforward, hier komt de spannendste (wederom met een hoop reference classes naar OLE-interfaces, leef je uit

). De filename mag naar ieder soort file wijzen dat automatisch OLE-embedded kan worden, ergo BMP's, GIF's, text files, Word-document, Excel-sheets en gaat u maar door:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
| //---------------------------------------------------------------------------
// InsertObjectAtCursor: Inserts named file at cursor position
//---------------------------------------------------------------------------
void TRichEdit20::InsertObjectAtCursor(const WideString &p_FileName)
{
RIStorage l_Storage;
RIOleObject l_OleObject;
RIOleClientSite l_ClientSite;
RILockBytes l_LockBytes;
FORMATETC l_FormatEtc = {0};
BSTR l_FileName;
// Create an IStorage implementation for the given file
if(CreateILockBytesOnHGlobal(NULL, TRUE, &l_LockBytes) != S_OK)
return;
if(StgCreateDocfileOnILockBytes(l_LockBytes, STGM_SHARE_EXCLUSIVE | STGM_CREATE |
STGM_READWRITE, 0, &l_Storage) != S_OK)
return;
// Fill the format structure and retrieve the client site
l_FormatEtc.cfFormat = 0;
l_FormatEtc.ptd = NULL;
l_FormatEtc.dwAspect = DVASPECT_CONTENT;
l_FormatEtc.lindex = -1;
l_FormatEtc.tymed = TYMED_NULL;
m_RichEditOle->GetClientSite(&l_ClientSite);
// Attempt to create the object
l_FileName = p_FileName.bstr();
if(OleCreateFromFile(CLSID_NULL, l_FileName, IID_IOleObject, OLERENDER_DRAW,
&l_FormatEtc, l_ClientSite, l_Storage, (void**)&l_OleObject) == S_OK)
{
REOBJECT l_ReObject = { sizeof(REOBJECT), 0 };
// Set the object mode to be contained then fill the RichEditObject struct
OleSetContainedObject(l_OleObject, TRUE);
l_OleObject->GetUserClassID(&l_ReObject.clsid);
l_ReObject.cp = REO_CP_SELECTION;
l_ReObject.dvaspect = DVASPECT_CONTENT;
l_ReObject.dwFlags = REO_RESIZABLE | REO_BELOWBASELINE;
l_ReObject.poleobj = l_OleObject;
l_ReObject.polesite = l_ClientSite;
l_ReObject.pstg = l_Storage;
// Actually insert the object
m_RichEditOle->InsertObject(&l_ReObject);
}
} |
Kijk, dit is het echte feesten... U was bang voor API's zei u?
Verder kun je nog wat dingetjes doen met de IRichEditOleCallback interface zoals automatisch gegeneerde contextmenu's afhankelijk van het embedded object, wat ik hier tactisch uit heb gesneden (we zijn wederom geen codevault.com

). Een van de andere dingen die je daarmee goed kunt doen is external drag&drops afhandelen om bestanden in te kunnen leggen, echter dit kun je via standaard messages (even WndProc overloaden) ook doen, dan krijg je bij WM_DROPFILES een HDROP naar de files. Om deze vervolgens in te voegen:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| //---------------------------------------------------------------------------
// HandleDropFiles: Implementation for WM_DROPFILES messages
//---------------------------------------------------------------------------
void TRichEdit20::HandleDropFiles(HDROP p_DropHandle)
{
t_Char* l_String;
t_UInt4 l_Count;
t_UInt4 l_Size;
// Retrieve the amount of files dropped
l_Count = DragQueryFile(p_DropHandle, 0xFFFFFFFF, NULL, 0);
while(l_Count--)
{
// Retrieve and add each dropped file
l_Size = DragQueryFile(p_DropHandle, l_Count, NULL, 0) + 1;
l_String = new t_Char[l_Size];
DragQueryFile(p_DropHandle, l_Count, l_String, l_Size);
InsertObjectAtCursor(l_String);
delete [] l_String;
}
// Release the drop handle
DragFinish(p_DropHandle);
} |
Nu heb je wel weer genoeg code gehad, ik hoor het wel als er verder problemen zijn
ps. zodra je dit weg hebt gekopieerd wijzig ik deze post zodat alle code weg is, ik hou er niet zo van om semi-copyrighted code te laten slingeren