IWICBitmapSource を クリップボードに転送するのがうまくいかなかった話

単純にIWICBitmapSource をClipboardに転送しようと思ったら HBITMAPに変換して
SetClipboardData(CF_BITMAP, hBitmap)
実行すればいいものだと思ってました。

最初に参考にしたサイトは、地道に データ作って CreateBitmapするものだった。
HBitmap 自体はちゃんとしたデータなのだけど、コピーできませんでした。

次に参考にしたのが GdiPlus::GetHBITMAPを使うものだったのだけどこれもNG。

試しに、適当な BMPファイルをLoadImageで取り出してみたらコピーできたので
GdiPlus::Saveで前述の Bitmap を保存してからLoadImageで試してみたところ、コピーに失敗した。

どうやら、クリップボードに転送できない BMPデータがあるようだ ・ω・

void SetBitmapSourceonClipboard(IWICBitmapSource* pImage)
{
    HANDLE tt;
    HBITMAP bitmap;
    WICPixelFormatGUID format; 
    UINT width = 0, height = 0;
    pImage->GetSize(&width, &height);
    HRESULT hr = pImage->GetPixelFormat(&format);
    UINT bpp = GetBpp(&format);
    IWICBitmap* copyBMP;
    int sz = (width * bpp) / 8;
    BITMAPV5HEADER bi = { 0 };
    HGLOBAL global = GlobalAlloc(GMEM_MOVEABLE, sizeof(bi) +  height * (sz + 3)/4 * 4 );
    bi.bV5Size = sizeof(BITMAPV5HEADER),
    bi.bV5Width = width;
    bi.bV5Height = height;
    bi.bV5Planes = 1;
    bi.bV5BitCount = (WORD)bpp;
    bi.bV5Compression = BI_RGB;
    bi.bV5SizeImage = bpp / 8 * width * height;
    bi.bV5RedMask = 0x000000ff;
    bi.bV5GreenMask = 0x0000ff00;
    bi.bV5BlueMask = 0x00ff0000;
    bi.bV5AlphaMask = 0xff000000;
    bi.bV5CSType = LCS_WINDOWS_COLOR_SPACE;
    bi.bV5Intent = LCS_GM_GRAPHICS;
    bi.bV5ClrUsed = 0;
    if (global)
    {
        BYTE* buffer = (BYTE*)GlobalLock(global);
        if (buffer)
        {
            WICRect rc;
            CopyMemory(buffer, &bi, sizeof(bi));
            rc.X = 0;
            rc.Width = width;
            rc.Height = 1;
            for(int h=0;h<height;h++) {
                rc.Y = height - h - 1;
                pImage->CopyPixels( &rc, sz, sz * 1, buffer + (sz + 3) /4 * 4  * h + sizeof(bi));
            }
            GlobalUnlock(global);
            EmptyClipboard();
            tt=SetClipboardData(CF_DIBV5, global);
        }
        GlobalFree(global);
    }
}

最期に試したのが、DIBV5で転送する方法。
これはうまくいった

おすすめ

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です