私はこれをしばらくの間機能させようとしてきましたが、理解できないようで、何時間ものグーグル検索ではまだ有用な結果が得られていません.
RGBA 順の 32 ビット ピクセルの配列があり、それらからデバイスに依存しないビットマップを作成し、SetClipboardData(CF_DIBV5, dib)
または同様の方法でクリップボードに配置したい (理想的には、アルファ チャネルを保持したい)。カスタム クリップボード タイプを登録することはオプションではありません。クリップボードに配置するポイントは、別のプログラムに貼り付けられるようにするためです。ピクセル データを他の形式 (平面 BGRA など) に手動で変換する必要がない場合のボーナス ポイント。
私の現在のコードは次のようになります (すべて set_clipboard_img 関数内にあります):
if(!OpenClipboard(hwnd)) return;
BITMAPV5HEADER* info = (BITMAPV5HEADER*) GlobalAlloc(GMEM_MOVEABLE, sizeof(BITMAPV5HEADER));
info->bV5Size = sizeof(BITMAPV5HEADER);
info->bV5Width = img_width;
info->bV5Height = -img_height;
info->bV5Planes = 1; // The docs say this is the only valid value here.
info->bV5BitCount = 32;
info->bV5Compression = BI_BITFIELDS;
info->bV5SizeImage = img_width * img_height * 4;
info->bV5RedMask = 0xff000000;
info->bV5GreenMask = 0x00ff0000;
info->bV5BlueMask = 0x0000ff00;
info->bV5AlphaMask = 0x000000ff;
unsigned char* buf;
// One of the sources I found said that I can pass a BITMAPV5HEADER in place of the BITMAPINFO, hence the first reinterpret_cast.
HBITMAP dib = CreateDIBSection(NULL, reinterpret_cast<BITMAPINFO*>(info), DIB_RGB_COLORS, reinterpret_cast<void**>(&buf), NULL, 0);
if(dib == NULL) {
CloseClipboard();
return;
}
// img_pixels_ptr is a unsigned char* to the pixels in non-planar RGBA format
std::copy_n(img_pixels_ptr, info->bV5SizeImage, buf);
EmptyClipboard();
auto result = SetClipboardData(CF_DIBV5, dib);
if(result == NULL) {
char str[256];
str[255] = 0;
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, str, 255, NULL);
std::cerr << "Error setting clipboard: " << str << std::endl;
// Here I get "handle not valid". I have no idea _why_ it's not valid, though.
}
CloseClipboard();
最終的には、プロセスを元に戻す (クリップボードから潜在的に透明なビットマップを取得する) ことも必要になりますが、一度に 1 つずつ行う必要があります。