如何使用win32 API将位图复制到剪贴板?

如何将保存到“.BMP”文件的缓冲区复制到使用win32 API的剪贴板? 也就是说,我有一个Windows V3位图的原始缓冲区(包括标题),我可以从字面上write()到一个文件,并将导致一个有效的.BMP文件,但我想将其复制到剪贴板。

在OS X上,在普通的C中,代码看起来像这样(按预期工作):

 #include <ApplicationServices/ApplicationServices.h> int copyBitmapToClipboard(char *bitmapBuffer, size_t buflen) { PasteboardRef clipboard; CFDataRef data; if (PasteboardCreate(kPasteboardClipboard, &clipboard) != noErr) { return PASTE_OPEN_ERROR; } if (PasteboardClear(clipboard) != noErr) return PASTE_CLEAR_ERROR; data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, bitmapBuffer, buflen, kCFAllocatorNull); if (data == NULL) { CFRelease(clipboard); return PASTE_DATA_ERROR; } if (PasteboardPutItemFlavor(clipboard, 42, kUTTypeBMP, data, 0) != noErr) { CFRelease(data); CFRelease(clipboard); return PASTE_PASTE_ERROR; } CFRelease(data); CFRelease(clipboard); return PASTE_WE_DID_IT_YAY; } 

我不确定如何使用win32 API完成此操作。 这就像我已经得到,但它似乎沉默地失败(即,该函数返回一个成功的错误代码,但是当试图粘贴,菜单项被禁用)。

 #include <windows/windows.h> int copyBitmapToClipboard(char *bitmapBuffer, size_t buflen) { if (!OpenClipboard(NULL)) return PASTE_OPEN_ERROR; if (!EmptyClipboard()) return PASTE_CLEAR_ERROR; if (SetClipboardData(CF_DSPBITMAP, bitmapBuffer) == NULL) { CloseClipboard(); return PASTE_PASTE_ERROR; } CloseClipboard(); return PASTE_WE_DID_IT_YAY; } 

任何人都可以提供一些见解,如何解决这个问题?

编辑

按照Aaron和martinr的build议,我现在修改了以下代码:

 #include <windows/windows.h> int copyBitmapToClipboard(char *bitmapBuffer, size_t buflen) { HGLOBAL hResult; if (!OpenClipboard(NULL)) return PASTE_OPEN_ERROR; if (!EmptyClipboard()) return PASTE_CLEAR_ERROR; hResult = GlobalAlloc(GMEM_MOVEABLE, buflen); if (hResult == NULL) return PASTE_DATA_ERROR; memcpy(GlobalLock(hResult), bitmapBuffer, buflen); GlobalUnlock(hResult); if (SetClipboardData(CF_DSPBITMAP, hResult) == NULL) { CloseClipboard(); return PASTE_PASTE_ERROR; } CloseClipboard(); return PASTE_WE_DID_IT_YAY; } 

但它仍然有同样的结果。 我究竟做错了什么?

最终编辑

工作代码:

 #include <windows/windows.h> int copyBitmapToClipboard(char *bitmapBuffer, size_t buflen) { HGLOBAL hResult; if (!OpenClipboard(NULL)) return PASTE_OPEN_ERROR; if (!EmptyClipboard()) return PASTE_CLEAR_ERROR; buflen -= sizeof(BITMAPFILEHEADER); hResult = GlobalAlloc(GMEM_MOVEABLE, buflen); if (hResult == NULL) return PASTE_DATA_ERROR; memcpy(GlobalLock(hResult), bitmapBuffer + sizeof(BITMAPFILEHEADER), buflen); GlobalUnlock(hResult); if (SetClipboardData(CF_DIB, hResult) == NULL) { CloseClipboard(); return PASTE_PASTE_ERROR; } CloseClipboard(); GlobalFree(hResult); return PASTE_WE_DID_IT_YAY; } 

谢谢,马丁!

我认为hMem需要是LocalAlloc的一个返回值,一个HMEMORY而不是一个指针。

编辑

对不起,是的,GlobalAlloc与GMEM_MOVEABLE是必需的,而不是LocalAlloc。

编辑

我建议你使用CF_DIB剪贴板数据格式类型。

除了没有BITMAPFILEHEADER之外,DIB与BMP相同,因此除了第一个sizeof(BITMAPFILEHEADER)字节之外,复制源字节。

编辑

从OpenClipboard()文档( http://msdn.microsoft.com/en-us/library/ms649048(VS.85).aspx ):

“如果应用程序调用OpenLipboard与hwnd设置为NULL,EmptyClipboard将剪贴板所有者设置为NULL;这将导致SetClipboardData失败。

你需要设置一个窗口; 即使你没有做WM_RENDERFORMAT类型的东西。

我发现Windows API很多。 我没有使用剪贴板API本身,但与其他API我通常发现,创建一个隐藏的窗口,并将该句柄传递给相关的API足以保持安静。 如果你是从DLL而不是EXE创建一个窗口的话,通常会有一些关于这个问题的注释。 阅读关于DLL,消息循环和窗口创建的最新微软词汇。

至于BITMAPINFO ,这不是剪贴板想要看到的流的开始部分: – 你给SetClipboardData的缓冲区应该在BITMAPFILEHEADER停止之后开始。

你需要传递一个句柄给SetClipboard()(即 – 分配给GlobalAlloc()的内存),而不是传递一个直接的指针到你的位图。

回声亚伦和马丁。 这里举例,关键部分:

  // Allocate a global memory object for the text. hglbCopy = GlobalAlloc(GMEM_MOVEABLE, (cch + 1) * sizeof(TCHAR)); if (hglbCopy == NULL) { CloseClipboard(); return FALSE; } // Lock the handle and copy the text to the buffer. lptstrCopy = GlobalLock(hglbCopy); memcpy(lptstrCopy, &pbox->atchLabel[ich1], cch * sizeof(TCHAR)); lptstrCopy[cch] = (TCHAR) 0; // null character GlobalUnlock(hglbCopy); // Place the handle on the clipboard. SetClipboardData(CF_TEXT, hglbCopy);