获取RichEditCtrl图片及如何使用在你的程序中~
来源:互联网 发布:php pdo sqlserver 编辑:程序博客网 时间:2024/05/29 04:46
1. How To Get Image Out of RichEditCtrl (Plus writing to bitmap file):
//Suppose you are using MFC, You doIRichEditOle* pReo = m_pRichEdit->GetIRichEditOle( );//If you use Platform SDK directlyIRichEditOle* pReo;::SendMessage(g_hYourRichEdit, EM_GETOLEINTERFACE, 0, (LPARAM)(LPVOID*)&pReo);//Note: in both cases, inside pReo's AddRef got called, so//remember to release it laterLONG nNumber = pReo->GetObjectCount(); //Your Images' Number//Handle Error yourself, code simplified for space limitationfor(int i = 0; i < nNumber; i++){ REOBJECT* ro = new REOBJECT; ro->cbStruct = sizeof(REOBJECT); HRESULT hr = pReo->GetObject(i, ro, REO_GETOBJ_ALL_INTERFACES); if(FAILED(hr)) continue; //caller should released the inner object IDataObject* lpDataObject; hr = (ro->poleobj)->QueryInterface(IID_IDataObject, (void **)&lpDataObject); if(FAILED(hr)) continue; STGMEDIUM stgm; //out FORMATETC fm; //in fm.cfFormat = CF_DIB; // Clipboard format fm.ptd = NULL; // Target Device = Screen fm.dwAspect = DVASPECT_CONTENT; // Level of detail = Full content fm.lindex = -1; // Index = Not applicaple fm.tymed = TYMED_HGLOBAL ; hr = lpDataObject->GetData(&fm, &stgm); if(FAILED(hr)) continue; ASSERT(::GlobalSize(stgm.hGlobal)); HANDLE hFile = ::CreateFile(_T("c:\\img.bmp"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if(hFile == INVALID_HANDLE_VALUE) { continie; } DWORD dwWritten; //Writing Bitmap File header BITMAPFILEHEADER bmfh; bmfh.bfType = 0x4d42; //'BM' int nColorTableEntries = 0; int nSizeHdr = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * nColorTableEntries; bmfh.bfSize = 0; bmfh.bfReserved1 = bmfh.bfReserved2 = 0; bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * nColorTableEntries; ::WriteFile(hFile, (LPVOID)&bmfh, sizeof(BITMAPFILEHEADER), &dwWritten, NULL); DWORD dwGlobalSize = ::GlobalSize(stgm.hGlobal); LPVOID lpMem = ::VirtualAlloc(NULL, dwGlobalSize, MEM_COMMIT, PAGE_READWRITE); ::CopyMemory(lpMem, (LPVOID)::GlobalLock(stgm.hGlobal), dwGlobalSize); BITMAPINFOHEADER* pInfoHead = (BITMAPINFOHEADER*)lpMem; pInfoHead->biXPelsPerMeter = pInfoHead->biYPelsPerMeter = 0; //Special Careful Here!!! Discard the Color Mask, //We need TRUE COLOR image //I bellieve you guys running Win2X/Xp use true color //screen setting if(pInfoHead->biCompression == BI_BITFIELDS) { pInfoHead->biCompression = BI_RGB; dwGlobalSize -= 3 * sizeof(RGBQUAD); //delete the 3 DWORD //color mask LPBYTE pSrc, pDst; pSrc = (LPBYTE)lpMem; pSrc += sizeof(BITMAPINFOHEADER); pDst = pSrc; pSrc += 3 * sizeof(RGBQUAD); ::MoveMemory(pDst, pSrc, dwGlobalSize - sizeof(BITMAPINFOHEADER)); } //Write Image Data ::WriteFile(hFile, lpMem, dwGlobalSize, &dwWritten, NULL); ::GlobalUnlock(stgm.hGlobal); //You may find good if all image are same size, keeping the //memory for performance ::VirtualFree(lpMem, 0, MEM_RELEASE); ::CloseHandle(hFile); lpDataObject->Release(); delete ro;}pReo->Release();
2. How Do You Transfer Data from Messenger to Your Own Program?
To achieve best performance, I use 2 Memory Map File and 4 Events to synchronize the RTF data and the image data respectively. All these kernel objects are named as a GUID to avoid name confliction. In the program side, when the frame starts, I make all initializations like these:
m_hMMF = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, MsnPage, GUID_MMF_NAME);if (m_hMMF == NULL){ // handle error here}LPVOID pView = MapViewOfFile(m_hMMF, FILE_MAP_WRITE, 0, 0, 0);DWORD dwSize = YourMMFSize;DWORD dwUsed = 0;LPBYTE lpByte = (LPBYTE)pView;::memcpy(lpByte, &dwSize, 4);::memcpy(lpByte + 4, &dwUsed, 4); //Now both sides knows the MMF size::UnmapViewOfFile(pView);m_hReadEvent = ::CreateEvent(NULL, TRUE, FALSE, GUID_READ_EVENT_NAME);if(m_hReadEvent == NULL){ //handle error}m_hWriteEvent = ::CreateEvent(NULL, TRUE, FALSE, GUID_WRITE_EVENT_NAME);if(m_hWriteEvent == NULL){ //handle error}::ResetEvent(m_hReadEvent);::SetEvent(m_hWriteEvent); //Important Here, If not set, //you get deadlock forever//Note: data is unidirectional from DLL to frame, so DLL//can begin to write now//create my frame thread ...
In frame side thread, it reads data sent from Hook DLL only:
//in thread part:__try{ hMMF = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, GUID_MSG_MMF_NAME); if (hMMF == NULL) //error __leave; hWriteEvent = ::OpenEvent(EVENT_ALL_ACCESS, FALSE,GUID_MSG_WRITE_EVENT_NAME); if(hWriteEvent == NULL) __leave; hReadEvent = ::OpenEvent(EVENT_ALL_ACCESS, FALSE,g_MSG_READ_EVENT_NAME); if(hReadEvent == NULL) __leave; ::SetEvent(hWriteEvent); //Just a reminder HANDLE hReadArr[2]; hReadArr[0] = hKillThreadEvent; hReadArr[1] = hReadEvent; while(1) { DWORD dwRet = ::WaitForMultipleObjects(2, hReadArr, FALSE, 1000); if(WAIT_OBJECT_0 == dwRet) __leave; if(dwRet == WAIT_TIMEOUT) continue; if(dwRet == WAIT_ABANDONED_0 || dwRet == WAIT_ABANDONED_0 + 1) __leave; ASSERT((WAIT_OBJECT_0 + 1) == dwRet); ::ResetEvent(hReadEvent); LPVOID pView = MapViewOfFile(hMMF, FILE_MAP_ALL_ACCESS, 0, 0, 0); if(pView == NULL) __leave; LPBYTE lpByte = (LPBYTE)pView; //Enjoy Your Data here!!!! ::UnmapViewOfFile(pView); ::SetEvent(hWriteEvent); }}__finally { ::CloseHandle(hMMF); ::CloseHandle(hWriteEvent); ::CloseHandle(hReadEvent); // and other stuff....}
In the Hook DLL part, you just exchange the position of the read and write event, and you do not need the loop because the DLL is message driven; besides, you set the wait time in the DLL to zero because the data is sent passively from the DLL while the frame thread running in wait loop. This structure will ensure the MMF is accessed by only one thread at one time. And in my point of view, WM_COPYMESSAGE (Spy++ uses this method), though theoretically able to realize the data transferring functionality, should be avoided; the reason is compatibility and portablity. In my case, this program has been ported to an NT Service to monitor the Messenger, which has no window at all to pursue maximum stability and performance. Besides, even in a Windows application like this, considering the performance, if my frame thread is blocked temporarily by some GUI action, the DLL thread can still write data to the MMF until it is full, and once the frame thread gets a chance to run, it can fetch all the previous data and empty the MMF. Actually, in my last project, the DLL can make a larger MMF and copy the data there, free the old MMF, and wait the receiving thread to wake. All this means better fault tolerance, stability, and performance of the program.
- 获取RichEditCtrl图片及如何使用在你的程序中~
- RichEditCtrl的使用经验
- RichEditCtrl的使用经验
- 在你的程序中如何使用CButtonST类
- 美工制作的图片在程序中如何使用呢?
- 如何在程序中获取系统语言及修改value-的语言
- 向RichEditCtrl中添加图片和URL功能
- 如何在你做的JAVA程序中加音乐
- Silverlight:如何在程序中获取网站的根目录
- VS2010使用richeditctrl
- 如何在程序中加载JPG图片?
- 在VC中使用 Flash 美化你的程序
- 在VC中使用 Flash 美化你的程序
- 在VC中使用 Flash 美化你的程序
- 在VC中使用 Flash 美化你的程序
- 在VC中使用 Flash 美化你的程序
- 在VC中使用 Flash 美化你的程序
- 在VC中使用 Flash 美化你的程序
- 数据结构课程设计 表达式类型的实现
- 查看数据库死锁的进程及清除sleeping进程(Kill__Sleeping_Processes)
- php中array_multisort()对多维数组进行排序,相当于数据库查询是order by多字段排序。。超好用
- QWidget,QMainWindow和QDialog的区别
- gdb里面的堆栈调试命令
- 获取RichEditCtrl图片及如何使用在你的程序中~
- 自定义JavaScript类
- Sql Server内存瓶颈(读书笔记)
- js处理年月日下拉菜单变化
- Java学习笔记四
- IBOutlet和IBAction到底是什么?
- 程序员职业发展的绊脚石-思想的枷锁
- hdu 3952 计算几何
- zoj 1091 Knight Moves (BFS)(情况用循环控制,值得学习啊)