gpt4 book ai didi

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

转载 作者:可可西里 更新时间:2023-11-01 13:25:53 24 4
gpt4 key购买 nike

如何使用 win32 API 将要保存为“.BMP”文件的缓冲区复制到剪贴板?即,我有一个 Windows V3 位图(包括 header )的原始缓冲区,我可以从字面上 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 的建议,我现在将代码修改为以下内容:

#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 而不是指针。

编辑

抱歉,是的,需要带有 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 停止的位置之后立即开始。

关于c - 如何使用 win32 API 将位图复制到剪贴板?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1977363/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com