Sam*_*Sam 6 c windows clipboard winapi bitmap
如何使用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;
}
Run Code Online (Sandbox Code Playgroud)
我不确定如何使用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;
}
Run Code Online (Sandbox Code Playgroud)
任何人都可以提供一些有关如何解决此问题的见解?
根据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;
}
Run Code Online (Sandbox Code Playgroud)
但它仍然有相同的结果.我究竟做错了什么?
工作代码:
#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;
}
Run Code Online (Sandbox Code Playgroud)
谢谢,马丁!
我认为 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 ):
“如果应用程序调用 OpenClipboard 并将 hwnd 设置为 NULL,则 EmptyClipboard 将剪贴板所有者设置为 NULL;这会导致 SetClipboardData 失败。”
你需要设置一个窗口;即使你没有做 WM_RENDERFORMAT 类型的事情。
我在 Windows API 中发现了很多这样的情况。我本身没有使用过剪贴板 API,但对于其他 API,我通常发现创建一个隐藏窗口并将该句柄传递给相关 API 就足以使其保持安静。如果您从 DLL 而不是 EXE 创建窗口,通常会有一些与此相关的问题的注释;阅读有关 DLL、消息循环和窗口创建的最新 Microsoft 文字。
至于BITMAPINFO,这不是剪贴板想要看到的流的开始:-您提供给 SetClipboardData 的缓冲区应该在 BITMAPFILEHEADER 停止之后立即开始。
| 归档时间: |
|
| 查看次数: |
7273 次 |
| 最近记录: |