如何使用win32 API将保存为“.BMP”文件的缓冲区复制到剪贴板?即,我有一个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;
}
有人能提供一些有关如何解决这个问题的见解吗?
Per Aaron和martinr的建议,我现在将代码修改为以下内容:
#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;
}
谢谢,马丁!“
答案 0 :(得分:3)
我认为hMem需要是LocalAlloc的返回值,一个HMEMORY而不是一个指针。
修改强>
很抱歉,需要使用GMEM_MOVEABLE的GlobalAlloc,而不是LocalAlloc。
修改强>
我建议您使用CF_DIB
剪贴板数据格式类型。
DIB与BMP相同,只是没有BITMAPFILEHEADER
,因此复制除第一个sizeof(BITMAPFILEHEADER)
字节之外的源字节。
修改强>
来自OpenClipboard()文档(http://msdn.microsoft.com/en-us/library/ms649048(VS.85).aspx):
“如果应用程序在hwnd设置为NULL的情况下调用OpenClipboard,则EmptyClipboard会将剪贴板所有者设置为NULL;这会导致SetClipboardData失败。”
你需要设置一个窗口;即使你没有做WM_RENDERFORMAT类型的东西。
我在Windows API中发现了很多。我没有使用剪贴板API本身,但我使用其他API,我通常发现创建一个隐藏的窗口并将该句柄传递给相关的API足以让它保持安静。如果您是从DLL而不是EXE创建窗口,那么通常会对问题做一些注释。阅读有关DLL,消息循环和窗口创建的最新Microsoft字样。
关于BITMAPINFO
,这不是剪贴板想要看到的流的开始: - 您给SetClipboardData的缓冲区应该在BITMAPFILEHEADER停止之后立即开始。
答案 1 :(得分:3)
您需要将HANDLE传递给SetClipboard()(即 - 使用GlobalAlloc()分配的内存),而不是将直指针传递给您的位图。
答案 2 :(得分:0)
// 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);