如何使用Win32API将位图复制到剪贴板? [英] How to copy bitmap to clipboard using the win32 API?
问题描述
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;
}
我不确定如何使用Win32API来实现这一点。这就是我所得到的,但它似乎静默失败(即,该函数返回一个成功的错误代码,但在尝试粘贴时,菜单项被禁用)。
#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的建议,我现在已将代码修改为:
#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需要是本地分配的返回值,是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设置为空的情况下调用OpenClipboard,则EmptyClipboard会将剪贴板所有者设置为空;这会导致SetClipboardData失败。"
您需要设置一个窗口;即使您没有执行WM_RENDERFORMAT类型的操作。
我在Windows API中经常发现这一点。我没有使用过剪贴板API本身,但对于其他API,我通常发现创建一个隐藏窗口并将该句柄传递给相关API就足以使其保持安静。如果您从DLL而不是EXE创建窗口,则通常有一些关于问题的注释;请阅读有关DLL、消息循环和窗口创建的最新Microsoft Word。
关于BITMAPINFO
,这不是剪贴板希望看到的流的开始:-您提供给SetClipboardData的缓冲区应该在BITMAPFILEHEADER停止的位置之后立即开始。
这篇关于如何使用Win32API将位图复制到剪贴板?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!