Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/codeigniter/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何仅使用direct WinAPI将独立于设备的位图放入Windows剪贴板?(无MFC或其他包装)_C++_Bitmap_Clipboard_Alpha_Dib - Fatal编程技术网

C++ 如何仅使用direct WinAPI将独立于设备的位图放入Windows剪贴板?(无MFC或其他包装)

C++ 如何仅使用direct WinAPI将独立于设备的位图放入Windows剪贴板?(无MFC或其他包装),c++,bitmap,clipboard,alpha,dib,C++,Bitmap,Clipboard,Alpha,Dib,我已经试着让它发挥作用有一段时间了,但我似乎还没有弄明白,几个小时的谷歌搜索还没有显示出任何有用的结果 我有一个以RGBA顺序排列的32位像素阵列,我想用它们创建一个独立于设备的位图,并使用SetClipboardData(CF_DIBV5,dib)或类似方法将其放在剪贴板上(理想情况下,我想保留alpha通道)。注册自定义剪贴板类型不是一个选项,因为将其放在剪贴板上的目的是为了将其粘贴到另一个程序中。如果我不必手动将像素数据转换为其他格式(如平面BGRA),则可获得额外积分 我当前的代码是这样

我已经试着让它发挥作用有一段时间了,但我似乎还没有弄明白,几个小时的谷歌搜索还没有显示出任何有用的结果

我有一个以RGBA顺序排列的32位像素阵列,我想用它们创建一个独立于设备的位图,并使用
SetClipboardData(CF_DIBV5,dib)
或类似方法将其放在剪贴板上(理想情况下,我想保留alpha通道)。注册自定义剪贴板类型不是一个选项,因为将其放在剪贴板上的目的是为了将其粘贴到另一个程序中。如果我不必手动将像素数据转换为其他格式(如平面BGRA),则可获得额外积分

我当前的代码是这样的(都在set\u clipboard\u img函数中):

if(!OpenClipboard(hwnd))返回;
BITMAPV5HEADER*信息=(BITMAPV5HEADER*)全局Alloc(GMEM_可移动,sizeof(BITMAPV5HEADER));
信息->bV5Size=sizeof(BITMAPV5HEADER);
信息->bV5Width=img_宽度;
信息->bV5Height=-img_高度;
信息->bV5Planes=1;//文档说这是这里唯一有效的值。
信息->bV5BitCount=32;
信息->bV5Compression=BI_位字段;
信息->bV5SizeImage=img_宽度*img_高度*4;
信息->bV5RedMask=0xff000000;
信息->bV5GreenMask=0x00ff0000;
信息->bV5BlueMask=0x0000ff00;
信息->bV5AlphaMask=0x000000ff;
无符号字符*buf;
//我找到的一个来源说,我可以传递一个BitMapV5头来代替BITMAPINFO,因此第一次重新解释了_转换。
HBITMAP dib=CreateDIBSection(空,重新解释投影(信息),dib\u RGB\u颜色,重新解释投影(&buf),空,0);
如果(dib==NULL){
CloseClipboard();
返回;
}
//img_pixels_ptr是非平面RGBA格式像素的无符号字符*
标准:复制(图像像素ptr,信息->bV5SizeImage,buf);
清空电路板();
自动结果=设置剪贴板数据(CF_DIBV5,dib);
如果(结果==NULL){
char-str[256];
str[255]=0;
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM,NULL,GetLastError(),0,str,255,NULL);

std::cerr您无法将
HBITMAP
传递给
SetClipboardData()
。它需要
hglobalalloc()
HGLOBAL
。这就是
SetClipboardData()
失败并出现
错误的原因

您需要将您的
Bitmapv5头文件
和像素数据直接放入分配的
HGLOBAL
中,并将其原样放入剪贴板,完全忘记使用
CreateDIBSection()

CF_DIBV5
17
一种内存对象,包含BitMapV5头结构,后跟位图颜色空间信息和位图位

尝试类似以下内容:

void printErr(const char *msg)
{
    char str[256] = {0};
    FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, str, 255, NULL);
    std::cerr << msg << ": " << str << std::endl;
}

...

DWORD size_pixels = img_width * img_height * 4;

HGLOBAL hMem = GlobalAlloc(GHND, sizeof(BITMAPV5HEADER) + size_pixels);
if (!hMem)
{
    printErr("Error allocating memory for bitmap data");
    return;
}

BITMAPV5HEADER* hdr = (BITMAPV5HEADER*) GlobalLock(hMem);
if (!hdr)
{
    printErr("Error accessing memory for bitmap data");
    GlobalFree(hMem);
    return;
}

hdr->bV5Size = sizeof(BITMAPV5HEADER);
hdr->bV5Width = img_width;
hdr->bV5Height = -img_height;
hdr->bV5Planes = 1;
hdr->bV5BitCount = 32;
hdr->bV5Compression = BI_BITFIELDS;
hdr->bV5SizeImage = size_pixels;
hdr->bV5RedMask   = 0xff000000;
hdr->bV5GreenMask = 0x00ff0000;
hdr->bV5BlueMask  = 0x0000ff00;
hdr->bV5AlphaMask = 0x000000ff;

// img_pixels_ptr is a unsigned char* to the pixels in non-planar RGBA format
CopyMemory(hdr+1, img_pixels_ptr, size_pixels);
GlobalUnlock(hMem);

if (!OpenClipboard(hwnd))
{
    printErr("Error opening clipboard");
}
else
{
    if (!EmptyClipboard())
        printErr("Error emptying clipboard");

    else if (!SetClipboardData(CF_DIBV5, hMem))
        printErr("Error setting bitmap on clipboard");

    else
        hMem = NULL; // clipboard now owns the memory

    CloseClipboard();
}

if (hMem)
    GlobalFree(hMem);
void printErr(const char*msg)
{
char str[256]={0};
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM,NULL,GetLastError(),0,str,255,NULL);
标准:cerr BV5平面=1;
hdr->BV5BITCUNT=32;
hdr->bV5Compression=BI_位字段;
hdr->bV5SizeImage=大小_像素;
hdr->bV5RedMask=0xff000000;
hdr->bV5GreenMask=0x00ff0000;
hdr->bV5BlueMask=0x0000ff00;
hdr->bV5AlphaMask=0x000000ff;
//img_pixels_ptr是非平面RGBA格式像素的无符号字符*
CopyMemory(hdr+1,img\u像素\u ptr,大小\u像素);
GlobalUnlock(hMem);
如果(!OpenClipboard(hwnd))
{
printErr(“打开剪贴板时出错”);
}
其他的
{
如果(!EmptyClipboard())
printErr(“清空剪贴板时出错”);
else如果(!SetClipboardData(CF_DIBV5,hMem))
printErr(“在剪贴板上设置位图时出错”);
其他的
hMem=NULL;//剪贴板现在拥有内存
CloseClipboard();
}
如果(hMem)
全球自由度(hMem);

谢谢!稍作调整后,效果似乎很好(我只需颠倒四个掩码参数的顺序)。不幸的是,许多程序在从剪贴板获取数据时似乎不读取alpha通道(GIMP甚至不知道有图像).哦,好吧!不过,我可以用alpha将paste从Paint.net复制到GIMP,所以一定有办法。我必须继续查找。
void printErr(const char *msg)
{
    char str[256] = {0};
    FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, str, 255, NULL);
    std::cerr << msg << ": " << str << std::endl;
}

...

DWORD size_pixels = img_width * img_height * 4;

HGLOBAL hMem = GlobalAlloc(GHND, sizeof(BITMAPV5HEADER) + size_pixels);
if (!hMem)
{
    printErr("Error allocating memory for bitmap data");
    return;
}

BITMAPV5HEADER* hdr = (BITMAPV5HEADER*) GlobalLock(hMem);
if (!hdr)
{
    printErr("Error accessing memory for bitmap data");
    GlobalFree(hMem);
    return;
}

hdr->bV5Size = sizeof(BITMAPV5HEADER);
hdr->bV5Width = img_width;
hdr->bV5Height = -img_height;
hdr->bV5Planes = 1;
hdr->bV5BitCount = 32;
hdr->bV5Compression = BI_BITFIELDS;
hdr->bV5SizeImage = size_pixels;
hdr->bV5RedMask   = 0xff000000;
hdr->bV5GreenMask = 0x00ff0000;
hdr->bV5BlueMask  = 0x0000ff00;
hdr->bV5AlphaMask = 0x000000ff;

// img_pixels_ptr is a unsigned char* to the pixels in non-planar RGBA format
CopyMemory(hdr+1, img_pixels_ptr, size_pixels);
GlobalUnlock(hMem);

if (!OpenClipboard(hwnd))
{
    printErr("Error opening clipboard");
}
else
{
    if (!EmptyClipboard())
        printErr("Error emptying clipboard");

    else if (!SetClipboardData(CF_DIBV5, hMem))
        printErr("Error setting bitmap on clipboard");

    else
        hMem = NULL; // clipboard now owns the memory

    CloseClipboard();
}

if (hMem)
    GlobalFree(hMem);