如何使用Win32API将位图复制到剪贴板? [英] How to copy bitmap to clipboard using the win32 API?

查看:0
本文介绍了如何使用Win32API将位图复制到剪贴板?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何使用Win32 API将保存为&.bmp&qot;文件的缓冲区复制到剪贴板?也就是说,我有一个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;
}

我不确定如何使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆