In eine RichEditBox ohne MFC ein Icon ?
-
Da mein alter Thread nach meinem letzten post anscheinend defekt ist, nochmal hier:
Nu hab ich schon das nächste mir unerklärliche Problem...
Und zwar habe ich zum verdeutlichen einfach mal das Funktionierende Beispiel
von Trolli genommen und abgeändert.Ich habe nichts weiter gemacht als folgendes Global Declariert:
IRichEditOle* pRichEditOle; HBITMAP hBitmap; HANDLE hThread; DWORD hThreadID; HWND hRichEdit;Somit müste ich ja alle Funktionen in jeder Funktion benutzen können.
Dann habe ich das Adden des Smilies in einen Tread verpackt und Sekündlich
einen Smilie adden lassen...Doch da hört es auf... Sobald er den Smilie adden will, kommt der selbe fehler wie bei mir in meinem Programm ( Der Speicher Fehler )
Kann mir das jemand erklären ?
Vielen Dank soweit !
-
So sieht der gesamte Code aus (in 2 Posts da sonst der Thread nimmer funktioniert aus mir unergründlichen Problemen):
#include <windows.h> #include <Richedit.h> #include <richole.h> IRichEditOle* pRichEditOle; HBITMAP hBitmap; HANDLE hThread; DWORD hThreadID; HWND hRichEdit; class CImageDataObject : IDataObject { public: // This static function accepts a pointer to IRochEditOle // and the bitmap handle. // After that the function insert the image in the current // position of the RichEdit // static void InsertBitmap(IRichEditOle* pRichEditOle, HBITMAP hBitmap) { SCODE sc; // Get the image data object // CImageDataObject *pods = new CImageDataObject; LPDATAOBJECT lpDataObject; pods->QueryInterface(IID_IDataObject, (void **)&lpDataObject); pods->SetBitmap(hBitmap); // Get the RichEdit container site // IOleClientSite *pOleClientSite; pRichEditOle->GetClientSite(&pOleClientSite); // Initialize a Storage Object // IStorage *pStorage; LPLOCKBYTES lpLockBytes = NULL; sc = ::CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes); sc = ::StgCreateDocfileOnILockBytes(lpLockBytes, STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, &pStorage); if (sc != S_OK) { lpLockBytes = NULL; } // The final ole object which will be inserted in the richedit control // IOleObject *pOleObject; pOleObject = pods->GetOleObject(pOleClientSite, pStorage); // all items are "contained" -- this makes our reference to this object // weak -- which is needed for links to embedding silent update. OleSetContainedObject(pOleObject, TRUE); // Now Add the object to the RichEdit // REOBJECT reobject; ZeroMemory(&reobject, sizeof(REOBJECT)); reobject.cbStruct = sizeof(REOBJECT); CLSID clsid; sc = pOleObject->GetUserClassID(&clsid); reobject.clsid = clsid; reobject.cp = REO_CP_SELECTION; reobject.dvaspect = DVASPECT_CONTENT; reobject.poleobj = pOleObject; reobject.polesite = pOleClientSite; reobject.pstg = pStorage; // Insert the bitmap at the current location in the richedit control // pRichEditOle->InsertObject(&reobject); // Release all unnecessary interfaces // pOleObject->Release(); pOleClientSite->Release(); pStorage->Release(); lpDataObject->Release(); } private: ULONG m_ulRefCnt; BOOL m_bRelease; // The data being bassed to the richedit // STGMEDIUM m_stgmed; FORMATETC m_fromat; public: CImageDataObject() : m_ulRefCnt(0) { m_bRelease = FALSE; } ~CImageDataObject() { if (m_bRelease) ::ReleaseStgMedium(&m_stgmed); } // Methods of the IUnknown interface // STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject) { if (iid == IID_IUnknown || iid == IID_IDataObject) { *ppvObject = this; AddRef(); return S_OK; } else return E_NOINTERFACE; }Zum testen ob der Tread funktioniert, einfach mal das InsertBitmap
auskommentieren und die MessageBox wieder beifügen !
-
STDMETHOD_(ULONG, AddRef)(void) { m_ulRefCnt++; return m_ulRefCnt; } STDMETHOD_(ULONG, Release)(void) { if (--m_ulRefCnt == 0) { delete this; } return m_ulRefCnt; } // Methods of the IDataObject Interface // STDMETHOD(GetData)(FORMATETC *pformatetcIn, STGMEDIUM *pmedium) { HANDLE hDst; hDst = ::OleDuplicateData(m_stgmed.hBitmap, CF_BITMAP, NULL); if (hDst == NULL) { return E_HANDLE; } pmedium->tymed = TYMED_GDI; pmedium->hBitmap = (HBITMAP)hDst; pmedium->pUnkForRelease = NULL; return S_OK; } STDMETHOD(GetDataHere)(FORMATETC* pformatetc, STGMEDIUM* pmedium) { return E_NOTIMPL; } STDMETHOD(QueryGetData)(FORMATETC* pformatetc ) { return E_NOTIMPL; } STDMETHOD(GetCanonicalFormatEtc)(FORMATETC* pformatectIn, FORMATETC* pformatetcOut) { return E_NOTIMPL; } STDMETHOD(SetData)(FORMATETC* pformatetc , STGMEDIUM* pmedium , BOOL fRelease) { m_fromat = *pformatetc; m_stgmed = *pmedium; return S_OK; } STDMETHOD(EnumFormatEtc)(DWORD dwDirection , IEnumFORMATETC** ppenumFormatEtc) { return E_NOTIMPL; } STDMETHOD(DAdvise)(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection) { return E_NOTIMPL; } STDMETHOD(DUnadvise)(DWORD dwConnection) { return E_NOTIMPL; } STDMETHOD(EnumDAdvise)(IEnumSTATDATA **ppenumAdvise) { return E_NOTIMPL; } // Some Other helper functions // void SetBitmap(HBITMAP hBitmap) { STGMEDIUM stgm; stgm.tymed = TYMED_GDI; // Storage medium = HBITMAP handle stgm.hBitmap = hBitmap; stgm.pUnkForRelease = NULL; // Use ReleaseStgMedium FORMATETC fm; fm.cfFormat = CF_BITMAP; // Clipboard format = CF_BITMAP fm.ptd = NULL; // Target Device = Screen fm.dwAspect = DVASPECT_CONTENT; // Level of detail = Full content fm.lindex = -1; // Index = Not applicaple fm.tymed = TYMED_GDI; // Storage medium = HBITMAP handle this->SetData(&fm, &stgm, TRUE); } IOleObject *GetOleObject(IOleClientSite *pOleClientSite, IStorage *pStorage) { SCODE sc; IOleObject *pOleObject; sc = ::OleCreateStaticFromData(this, IID_IOleObject, OLERENDER_FORMAT, &m_fromat, pOleClientSite, pStorage, (void **)&pOleObject); return pOleObject; } }; LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT ("Klassenname"); HWND hwnd; MSG msg; WNDCLASSEX wndclassex = {0}; wndclassex.cbSize = sizeof(WNDCLASSEX); wndclassex.style = CS_HREDRAW | CS_VREDRAW; wndclassex.lpfnWndProc = WndProc; wndclassex.cbClsExtra = 0; wndclassex.cbWndExtra = 0; wndclassex.hInstance = hInstance; wndclassex.hIcon = LoadIcon (NULL, IDI_APPLICATION); wndclassex.hCursor = LoadCursor (NULL, IDC_ARROW); wndclassex.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); wndclassex.lpszMenuName = NULL; wndclassex.lpszClassName = szAppName; wndclassex.hIconSm = wndclassex.hIcon; if (!RegisterClassEx (&wndclassex)) { MessageBox (NULL, TEXT ("RegisterClassEx fehlgeschlagen!"), szAppName, MB_ICONERROR); return 0; } hwnd = CreateWindowEx (WS_EX_OVERLAPPEDWINDOW, // erweiterter Fensterstil szAppName, // Name der Fensterklasse TEXT ("Fenstertitel"), // Fenstertitel WS_OVERLAPPEDWINDOW, // Fensterstil CW_USEDEFAULT, // X-Position des Fensters CW_USEDEFAULT, // Y-Position des Fensters CW_USEDEFAULT, // Fensterbreite CW_USEDEFAULT, // Fensterhöhe NULL, // übergeordnetes Fenster NULL, // Menü hInstance, // Programm-Kopiezähler (Programm-ID) NULL); // zusätzliche Parameter ShowWindow (hwnd, iCmdShow); UpdateWindow (hwnd); while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg); DispatchMessage (&msg); } return msg.wParam; } DWORD WINAPI Smilie(LPVOID lpParam) { while( 1 ) { pRichEditOle = NULL; ::SendMessage(hRichEdit, EM_GETOLEINTERFACE, 0, (LPARAM)&pRichEditOle); hBitmap = (HBITMAP) LoadImage(NULL, TEXT("D:\\C++ Projeckte\\RatMod Chat\\Client\\bitmap1.bmp"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); // MessageBox( NULL, "TREAD", "", MB_OK ); CImageDataObject::InsertBitmap(pRichEditOle, hBitmap); Sleep( 1000 ); } return(0); } // Die Hauptnachrichtenschleife LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_CREATE: { LoadLibrary("riched20.dll"); hRichEdit = CreateWindowEx(0, RICHEDIT_CLASS, NULL, WS_CHILD | WS_VISIBLE | WS_BORDER, 0, 0, 200, 200, hwnd, (HMENU) 0, GetModuleHandle(NULL), NULL); hThread = CreateThread(NULL, 0, Smilie, 0, 0, &hThreadID); } return (0); case WM_DESTROY: PostQuitMessage (0); return (0); } return DefWindowProc (hwnd, message, wParam, lParam); }
-
Wenn du im Thread am Anfang CoInitialize aufrufst dann wird ein leeres weißes Bitmap in der richtigen Größe eingefügt.

Ich hatte auch die ganze Fehlerbehandlung rausgenommen, vielleicht solltest du die wieder einfügen. (ASSERT / AfxThrowOleException)
-
Ach ja, und FormatMesage sollte dir auch helfen. Damit bekommst du die Fehlermeldung als String aus nem HRESULT/SCODE.
So habe ich auch rausgefunden, das CoInitialize benötigt wird.
-
Bei dem ES_READONLY Problem hilft CoInitialize auch. *lol*
-
ASSERT / AfxThrowOleException kann ich nicht benutzen, da es kein MFC ist

-
Jo, dann benutzt du eben überall das assert aus der Standard-Library (assert.h) oder du schreibst dir kurz eine eigene assert-Funktion die dir dann auch den Fehlerstring von FormatMessage ausgibt.
-
Also die InsertBitmap sieht nun so aus:
static void InsertBitmap(IRichEditOle* pRichEditOle, HBITMAP hBitmap) { SCODE sc; // Get the image data object // CImageDataObject *pods = new CImageDataObject; LPDATAOBJECT lpDataObject; pods->QueryInterface(IID_IDataObject, (void **)&lpDataObject); pods->SetBitmap(hBitmap); // Get the RichEdit container site // IOleClientSite *pOleClientSite; pRichEditOle->GetClientSite(&pOleClientSite); // Initialize a Storage Object // IStorage *pStorage; LPLOCKBYTES lpLockBytes = NULL; sc = ::CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes); assert(lpLockBytes != NULL); sc = ::StgCreateDocfileOnILockBytes(lpLockBytes, STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, &pStorage); if (sc != S_OK) { lpLockBytes = NULL; } assert(pStorage != NULL); // The final ole object which will be inserted in the richedit control // IOleObject *pOleObject; pOleObject = pods->GetOleObject(pOleClientSite, pStorage); // all items are "contained" -- this makes our reference to this object // weak -- which is needed for links to embedding silent update. OleSetContainedObject(pOleObject, TRUE); // Now Add the object to the RichEdit // REOBJECT reobject; ZeroMemory(&reobject, sizeof(REOBJECT)); reobject.cbStruct = sizeof(REOBJECT); CLSID clsid; sc = pOleObject->GetUserClassID(&clsid); reobject.clsid = clsid; reobject.cp = REO_CP_SELECTION; reobject.dvaspect = DVASPECT_CONTENT; reobject.poleobj = pOleObject; reobject.polesite = pOleClientSite; reobject.pstg = pStorage; // Insert the bitmap at the current location in the richedit control // pRichEditOle->InsertObject(&reobject); // Release all unnecessary interfaces // pOleObject->Release(); pOleClientSite->Release(); pStorage->Release(); lpDataObject->Release(); }Aber der Fehler erscheint immer noch ganz genau so

-
Keiner eine Idee was ich machen kann, damit es funktioniert ?
-
Wenn ich das richtig sehe liegt es daran, dass m_fromat beim Aufruf von OleCreateStaticFromData NULL ist, dies aber nicht sein darf.
The client will pull one format from the object using IDataObject::GetData(). The format of the data to be cached is passed in pFormatEtc, which may not in this case be NULL.
Allerdings habe ich leider auch keine Ahnung, wie man das genau anstellen muss, damit es klappt
- gibt es hier niemanden, der da Erfahrung hat? -King-?
-
Also es geht bis:
sc = pOleObject->GetUserClassID(&clsid);
Dort wird das pOleObject erst auf 0x000000
gesetzt (hoffe irre mich jetz nicht)
-
lol...ich hatte doch jetzt in 3 Beiträgen erwähnt wie du *diesen* Fehler beheben kannst. Allerdings ergibt sich als nächstes Problem das nur ein leeres Bitmap (aber in der richtigen Größe) eingefügt wird.
-
Da hab ich ja gefragt, wie das verwendet wird

-
OLE doesn't work with multiple threads. As far as I know, you have to
do all OLE-related stuff from the same thread.
-
Hi there,
i have defined my AddIcon Sub Routine, so that i can Add Icons from all Routines...
This Sub Gets the Ole Handle and Calls then the InsertBitmap Class.
But then i become an error.
When i call the AddIcon from the WndProc than all right.
Now i have done it.
I Send an Userdefined UserMessage ( SendMessage( hWndMain, WM_INSERTSMILIE, NULL, NULL ); )
And this WM_INSERTSMILIE i check in my WndProc.
So its all Right now.