- ベストアンサー
Desktopイメージをメモリに取り込む方法
- Visual C++のMFCを使って、デスクトップイメージをメモリに取り込むプログラムを作成しています。しかし、作成したプログラムで取得したColorBufの内容がすべてゼロになってしまいます。
- MFCのAppWizardを使用し、SDIのスケルトンを作成しました。メニューバーにViewTestという項目を追加し、ここでデスクトップイメージをキャプチャしようとしています。
- プログラム内でDesktopWindowのClient領域の座標を取得し、CreateCompatibleBitmap関数でbitmapを作成しています。しかし、bitmapの内容を取得するGetBitmapBits関数で取得したcolorBufの内容がすべてゼロになってしまいます。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
こんばんは。 デスクトップイメージをbmに対して描画していないのが原因なのではないでしょうか。 CreateCompatibleBitmap()と言うのは、あくまで指定したデバイスコンテキストと同一のフォーマットを持ったビットマップを作成するだけですので、イメージまで複写してくれる訳ではありません。 自前でビットブロック転送をしてイメージを複写する必要があります。 以下で改善しませんか。 void CMainFrame::OnViewTest() { CRect rect; CWnd* pwWnd = GetDesktopWindow(); pwWnd->GetClientRect( &rect ); CDC* pwDC = pwWnd->GetDC(); CBitmap bm; bm.CreateCompatibleBitmap( pwDC, rect.Width(), rect.Height() ); //デスクトップイメージをbmへ描写する CDC memDC; memDC.CreateCompatibleDC(pwDC); CGdiObject* pOld = memDC.SelectObject(&bm); memDC.BitBlt(0, 0, rect.Width(), rect.Height(), pwDC, 0, 0, SRCCOPY); memDC.SelectObject(pOld); memDC.DeleteDC(); //受け取りバッファに必要なバイトサイズを受け取る const DWORD dwBytes = bm.GetBitmapBits( 0, NULL ); //実際に割り当てる unsigned char *colorBuf = (unsigned char *)malloc(dwBytes); //イメージをバッファに受け取る bm.GetBitmapBits( dwBytes, colorBuf ); pwWnd->ReleaseDC( pwDC ); for(DWORD dw = 0; dw < dwBytes; ++dw) { if(colorBuf[dw] != 0) { //此処で確認 } } }
その他の回答 (3)
- machongola
- ベストアンサー率60% (434/720)
こんにちは。御礼頂きました。 以下で試してみましたが、確かに失敗します。 CRect rect; CWnd* pwWnd = GetDesktopWindow(); pwWnd->GetClientRect( &rect ); //デスクトップウィンドウのデバイスコンテキストを取る CDC* pwDC = pwWnd->GetDC(); //ディスプレイのデバイスコンテキストを取る HDC hDC = ::CreateDC("DISPLAY", NULL, NULL, NULL); for(int y = 0; y < rect.Height(); ++y) { for(int x = 0; x < rect.Width(); ++x) { //成功 const COLORREF color = ::GetPixel(hDC, x, y); //失敗 const COLORREF color2= pwDC->GetPixel(x, y); } } デスクトップウィンドウのデバイスコンテキストとディスプレイのデバイスコンテキストは別物の様に見えます。 流石に此の辺りの詳細を説明してくれる書籍を見つけた事が無い為、此れに関しては当方の理解範囲を超えているので何故だかは分かりません。 海外から輸入されたwindowsプログラム専門の書籍であればこの辺りの事情が書かれているかもしれません。
お礼
早速のお返事ありがとうございました。 ほんと、CDCに関しては、いつもややこしくて、勉強をするのもめんどくさく、なかなか深く掘り下げて勉強していないので、苦労しております。 ちゃんと勉強しろよ、と自分にいいながら、、、 でも、hDCをとって、成功した、というのは、大変興味深く、勉強になりました。 ありがとうございました。 わたしは、実は、マルチモニタでの画面キャプチャがしたいのです。 このプログラムでは、マルチモニタには対応していないようです。 これもわかりません。 近く、また別途、質問させていただきますので、ご縁があれば、またよろしくお願いいたします。
- neKo_deux
- ベストアンサー率44% (5541/12319)
良く良く考えたら、手元にMFCどころか開発環境自体無かった…。 うろ覚えですが、DCに対してビットマップオブジェクトを選択していないような。 pwDC->SelectObject(&bm) とかがGetBitmapBitsの前に要らなかったか?って気がします。 古いオブジェクトは保存しておき、処理後に戻す方が良いです。
お礼
お返事ありがとうございます。 関係なさそうです。 CDC* pwDC = pwWnd->GetDC(); で、pwDCを作った後、GetPixelを使ってカラー値をみようと思い、 COLORREF px[10000]; long lx, ly, l; lx = ly = 0; for( l = 0; l < 10000; l++ ) { px[l] = pwDC->GetPixel( lx++, ly ); if( lx >= 500 ) { lx = 0; ly++; } } というソフトを追加してみました。 すると、pxの配列の中身はすべて、0xFFFFFFFFになっていました。 pwDCの取り方に問題があるのかもしれません。
- neKo_deux
- ベストアンサー率44% (5541/12319)
> rectには、ちゃんとデスクトップサイズが入っています。 であればその後の、 pwDCにデバイスコンテキストの値が入っているか? bmにCreateCompatibleBitmapした結果は成功しているか? colorBufへのmallocは成功しているか? bmにGetBitmapBitsした結果は成功しているか? など確認するのが一般的なデバッグ方法です。
お礼
お返事ありがとうございました。 pwDC, pwWndには、ちゃんと中身も入っています。 CreateCompatibleBitmapは、TRUEを返しています。 mallocは成功しているかどうかわかりませんが、colorBufにはちゃんとアドレスが入っているので大丈夫でしょう。 GetBitmapBitsは、取得したバイト数、3072000を返り値として、返しています。 つまり、とりあえず、すべてのコマンドはちゃんと成功しているように見えます。 なので、何かが抜けているのか、Bitmapへのコピーでどこかが間違っているのか、pwDCの取り方が間違っているのか、、、 わたしもいろいろ調べてみましたが、よくわかりません。
お礼
お返事ありがとうございました。 とりあえず、このプログラムでやってみたら、colorBufに値が入っていますね。 正しい値かどうか、ちょっとじっくり調べてみます。 それにしても、 CDC* pwDC = pwWnd->GetDC(); の直後にためしに、pwDC->GetPixel(x, y) で値をとってみても、FFFFFFFFしか返ってこなかったのは、なぜなのでしょうか。
補足
確認してみました。 colorBuf内に入っている値をもとに、SDIの画面に描画させてみたら、ちゃんと、デスクトップの絵が表示されました。 ありがとうございました。 CDC* pwDC = pwWnd->GetDC(); の直後にためしに、pwDC->GetPixel(x, y) で値をとってみても、FFFFFFFFしか返ってこなかったのはなぜなのでしょうか。 もしよろしければ、教えてください。