• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:クリップボードから画像取得)

クリップボードから画像取得できない時の対処法とは?

このQ&Aのポイント
  • クリップボードから画像を取得する方法について質問します。前回の質問で試した方法がうまくいかず困っています。画像を表示せずにファイルに保存したいのですが、どこが問題なのでしょうか?
  • クリップボードから画像を取得してファイルに保存する方法についての質問です。前回の質問で試したコードがうまくいかず困っています。画像を表示せずに保存したいのですが、どこが間違っているのでしょうか?
  • クリップボードから画像を取得して保存する方法についての質問です。前回の質問で試したコードが上手く動かず困っています。画像を表示せずにファイルに保存したいのですが、何が原因なのでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

 こんばんは。  クリップボードから取り出したHBITMAPを、新たに作成したDIBのHBITMAPに複写し、DIBのHBITMAPをセーブに使用します。  以下は32bitの「screen shot.bmp」を作成します。参考程度に。 static void InitHDR(LPBITMAPINFOHEADER pbmih, DWORD width, DWORD height) { pbmih->biSize = sizeof(*pbmih); pbmih->biPlanes = 1; pbmih->biCompression = BI_BITFIELDS; pbmih->biBitCount = 32; pbmih->biWidth = width; pbmih->biHeight= height; } static void InitFields(LPDWORD p) { p[0] = 0xff0000; p[1] = 0xff00; p[2] = 0xff; } static HBITMAP CreateDIBFrom(HBITMAP hBitmap) { LPBITMAPINFO pbmi = static_cast<LPBITMAPINFO>(::calloc(1, sizeof(BITMAPINFOHEADER) + (sizeof(RGBQUAD) * 3))); BITMAP bitmap; ::GetObject(hBitmap, sizeof(bitmap), &bitmap); ::InitHDR(&pbmi->bmiHeader, bitmap.bmWidth, bitmap.bmHeight); ::InitFields(reinterpret_cast<LPDWORD>(&pbmi->bmiColors)); LPVOID pvBits = NULL; HBITMAP hDIB = ::CreateDIBSection(NULL, pbmi, DIB_RGB_COLORS, &pvBits, NULL, 0); if(hDIB) { HDC hDCDest = ::CreateCompatibleDC(NULL); HDC hDCSrc = ::CreateCompatibleDC(NULL); ::SelectObject(hDCDest, hDIB); ::SelectObject(hDCSrc, hBitmap); ::BitBlt(hDCDest, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hDCSrc, 0, 0, SRCCOPY); ::DeleteDC(hDCDest); ::DeleteDC(hDCSrc); } ::free(pbmi); return hDIB; } static BOOL SaveDIB(LPSTR strFileName, HBITMAP hBitmap) { DIBSECTION dib; ::GetObject(hBitmap, sizeof(dib), &dib); BITMAPFILEHEADER bmfh = {0}; bmfh.bfType = 0x4d42; bmfh.bfOffBits = sizeof(bmfh) + sizeof(dib.dsBmih) + sizeof(dib.dsBitfields); bmfh.bfSize = bmfh.bfOffBits + dib.dsBmih.biSizeImage; FILE* fp = ::fopen(strFileName, "wb"); if(fp == NULL)return FALSE; ::fwrite(&bmfh, sizeof(bmfh), 1, fp); ::fwrite(&dib.dsBmih, sizeof(dib.dsBmih), 1, fp); ::fwrite(dib.dsBitfields, sizeof(dib.dsBitfields), 1, fp); ::fwrite(dib.dsBm.bmBits, dib.dsBmih.biSizeImage, 1, fp); ::fclose(fp); return TRUE; } //ウィンドウプロシージャの中で、 case IDM_SAVE: if(!::IsClipboardFormatAvailable(CF_BITMAP)) break; ::OpenClipboard(hWnd); try { HBITMAP hBitmap = static_cast<HBITMAP>(::GetClipboardData(CF_BITMAP)); if(hBitmap == NULL) throw TEXT("クリップボードからビットマップを取れなかった"); HBITMAP hDIB = ::CreateDIBFrom(hBitmap); if(hDIB == NULL) throw TEXT("DIBへの変換に失敗した"); const BOOL bResult = ::SaveDIB("screen shot.bmp", hDIB); ::DeleteObject(hDIB); if(bResult == FALSE) throw TEXT("セーブに失敗した"); } catch(LPCTSTR lpctstrError) { ::MessageBox(hWnd, lpctstrError, TEXT("失敗しました"), IDOK); } ::CloseClipboard(); break;

ringist
質問者

お礼

こんばんは ソースコードありがとうございました。 上記ソースコードで実装したところうまくいきました! まさにもとめていたものそのものです。 本当にありがとうございました!

その他の回答 (1)

回答No.1

 こんにちは。  チョッと今は時間が御座いませんので、手短に書くと、bmp_info.bmBitsがNULLになっているのではないでしょうか。  クリップボードから取り出したHBITMAPはDDBの筈です。DDBはGetObject()APIで、画像データへのポインタを返さない様になっています。  クリップボードから取り出したHBITMAPと同じ「width x height」を持つDIBSectionを作成し、BitBltにてビットプロック転送をした後、DIBSectionのHBITMAPから画像データへのポインタを取り出してセーブしてみて下さい。  その他、パッと見で気付いた点を挙げますと、 (1)  bmih.biClrUsed=2;  ではなく  bmih.biClrUsed=0; (2)  bmih.biBitCount=32;  の時  bmih.biCompression=BI_BITFIELDS;  で、RGBQUAD x 3の拡張割り当てと、ビットフィールドの設定が必要です。  bmih.biBitCount=24;  の時  bmih.biCompression=BI_RGB;  とするのが望ましいです。 (3)  hdc = BeginPaint(hWnd, &ps);  EndPaint(hWnd, &ps);  は不要です。  と言ったところです。

ringist
質問者

お礼

ご指摘ありがとうございました 大変参考になりましたm(__)m

関連するQ&A