プロが教える店舗&オフィスのセキュリティ対策術

ビットマップハンドルhBitmap の(x,y)の画素の色を読み取るプログラムに使うデバイスコンテキストとして、
 hDC = CreateCompatibleDC(NULL);
 SelectObject(hDC, hBitmap);
 rgb = GetPixel(hDC, x,y);
 DeleteDC(hDC);

のように、NULL を指定して、画面と互換性のあるメモリデバイスコンテキストを指定したのですが、正しい色が読み出せません。hDC = GetDC(NULL);でも同じく駄目でした。hDCはどのように作ったらよいのでしょう。
なお、関数の中でGetPixel()を使いたいので、hWnd などは使えません。

A 回答 (3件)

訂正です


ラストのパラメータはrgbQ.rgbRedではなくrgbQ.rgbBlueの間違えです。
失礼しました。

//文字の組み立て
::sprintf( arrBufMsg,
"カーソル位置の色は %X, %X, %X, %X, %X, です",
pt.x, pt.y,
rgbQ.rgbRed,
rgbQ.rgbGreen,
rgbQ.rgbRed/*←ココはrgbQ.Blueです・・・*/);
    • good
    • 0

今晩は。

目的は大体わかるのですが・・・

>>MSDNでは、「デバイスコンテキストの取得対象となるウィンドウのハンド ルを指定します。NULL を指定すると、GetDC は画面全体を表すデバイスコンテキストを取得します。」とありますが、使えないのですか?
 はい。NULLを指定するとデスクトップ(画面領域)のウィンドウハンドルが指定された事になる筈です。

<実行結果>
a = FF FF FF FF ←これはxの事ですか?
b = 80 80 80 ←これはyの事ですか?
c1 = 4F 70 9F ←これは赤の事ですか?
c2 = FF FF FF FF←これは緑の事ですか?
c3 = FF FF FF  ←これは青の事ですか?

(1)HBITMAPから直接色彩を取るのでしょうか?
(2)ウィンドウにHBITMAPを描写して、ウィンドウから色彩を取るのでしょうか?

(1)を目的にしているのなら、サンプルで動くはずです。
(2)を目的にしているのなら、WM_PAINTでHBITMAPを描写してからWM_LBUTTONDOWNでウィンドウのデバイスコンテキストを作成して、そちらから色彩を取り出します。

//以下サンプル
//グローバル変数
static const LPCSTR OBMP= "bitmap.bmp";//ビットマップファイル名
static HBITMAPg_hBitmap= 0;

//色彩を取る
static void GetMyColor(const HBITMAP hBitmapIn, const POINT& pt, LPRGBQUAD pOut)
{
//メモリデバイスコンテクストを作成します
HDC hDC = ::CreateCompatibleDC(NULL);

//選択します
::SelectObject(hDC, hBitmapIn);

//x, yに対応する色彩をゲットします
const COLORREF rgb = ::GetPixel(hDC, pt.x, pt.y);

//メモリデバイスコンテキストを消去します
::DeleteDC(hDC);

//色彩の分解です
pOut->rgbRed= GetRValue(rgb);//赤です
pOut->rgbGreen= GetGValue(rgb);//緑です
pOut->rgbBlue= GetBValue(rgb);//青です
}

int CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wP, LPARAM lP)
{
switch(uMsg)
{
case WM_CREATE:
{
//モジュールハンドルを取る
HINSTANCE hInst = ::GetModuleHandle(0);

//ビットマップをロードします
g_hBitmap = (HBITMAP)LoadImage(hInst, OBMP, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);

return TRUE;
}

case WM_LBUTTONDOWN:
{
//色彩の受け取りデータ
RGBQUAD rgbQ = {0};

//望む座標
const POINT pt = {2, 0};

//受け取る
::GetMyColor(g_hBitmap, pt, &rgbQ);

//文字のバッファ
char arrBufMsg[256];

//初期化
::ZeroMemory(arrBufMsg, 256);

//文字の組み立て
::sprintf(arrBufMsg,
"カーソル位置の色は %X, %X, %X, %X, %X, です",
pt.x, pt.y,
rgbQ.rgbRed,
rgbQ.rgbGreen,
rgbQ.rgbRed);

//メッセージボックスに出す
::MessageBox(hWnd , arrBufMsg, NULL, MB_OK);

return TRUE;
}

case WM_CLOSE:
{
::DestroyWindow(hWnd);
return FALSE;
}

case WM_DESTROY:
{
//ビットマップが不要なので消去します
::DeleteObject(g_hBitmap);
return FALSE;
}

default:;
}

return ::DefWindowProc(hWnd, uMsg, wP, lP);
}
    • good
    • 0
この回答へのお礼

machongolaさん、再度、回答ありがとうございます。

><実行結果>
>a = FF FF FF FF ←これはxの事ですか?
>b = 80 80 80 ←これはyの事ですか?
>c1 = 4F 70 9F ←これは赤の事ですか?
>c2 = FF FF FF FF←これは緑の事ですか?
>c3 = FF FF FF  ←これは青の事ですか?
誤解を招く表示ですいません。
<実行結果>は、関数で得られた値の16進表示出力を、手動で2桁ずつに区切って表示したです。つまり、
  ? B G R
a = FF FF FF FF ← rgbA()で求めた値
b = -- 80 80 80 ← rgbB()で求めた値
c1 = -- 4F 70 9F ← case WM_CREATE:で取得したhDC、rgbC()で求めた値
c2 = FF FF FF FF ← CreateCompatibleDC(NULL);で取得したhDC、rgbC()で求めた値
c3 = FF FF FF ← GetDC(hWnd);で取得したhDC、rgbCB()で求めた値
です。

>(1)HBITMAPから直接色彩を取るのでしょうか?
>(2)ウィンドウにHBITMAPを描写して、ウィンドウから色彩を取るのでしょうか?
(1)です。おっしゃるとおり、(2)を目的とする可能性もありますね。穴だらけの質問で失礼しました。

>(1)を目的にしているのなら、サンプルで動くはずです。
お教えいただいたサンプルは、C++なのですが、私はC言語なので、そのまま動かせませんでした。しかしCに書き直しましたが、結局、これは、先の関数rgbA()と同じになってしまいました。
この方法ですと、得られる値は-1(FFFFFFFF、無理にRGBに分けると、FF FF FF FF)となり、明らかにエラーになってしまうのです。

お礼日時:2008/06/19 08:35

うーむ。

一見すると問題がないように見えますな。

ちょっと確認

(1)hBitmapはしっかりと作成されてますか?
(2)x, yがあさっての数値を指しているとか?
(3)rgbからr,g,bへの分解で書き間違えたとか?

HBITMAPに対するデバイスコンテキストはCreateCompatibleDC()で良いはずです。
GetDC()はHWNDに対してしか使えないはずです。
hBitmapがDIBであるならば無理やりイメージのポインタをつまみ出してしまったら如何でしょう?

この回答への補足

回答ありがとうございます。
>(1)hBitmapはしっかりと作成されてますか?
>(2)x, yがあさっての数値を指しているとか?
>(3)rgbからr,g,bへの分解で書き間違えたとか?
そのようなことは無いと思います。

>GetDC()はHWNDに対してしか使えないはずです。
MSDNでは、「デバイスコンテキストの取得対象となるウィンドウのハンドルを指定します。NULL を指定すると、GetDC は画面全体を表すデバイスコンテキストを取得します。」とありますが、使えないのですか?
http://msdn.microsoft.com/ja-jp/library/cc428664 …

確認のためのプログラムを作成したところ、やはり、hDCを確保する方法、場所により結果が異なります。
CreateCompatibleDC(NULL);で確保した場合は、
 case WM_CREATE:で確保すると正常、そのほかの場所で確保するとFF FF FF FFとなり、明らかにエラーです。
GetDC(NULL); で確保した場合は、
 一見まともな値ですが、関数の中で確保する場合と、case WM_LBUTTONDOWN:内で、使う直前に確保する場合で値が違います。
引き続き、ご教示お願いいたします。

<実行結果>
a = FF FF FF FF
b = 80 80 80
c1 = 4F 70 9F
c2 = FF FF FF FF
c3 = FF FF FF

<動作確認プログラム>
int rgbA(HBITMAP hBitmap, int x, int y) {
 int rgb;
 HDC hDC;
 hDC = CreateCompatibleDC(NULL);
 SelectObject(hDC, hBitmap);
 rgb = GetPixel(hDC, x,y);
 DeleteDC(hDC);
 return rgb;
}

int rgbB(HBITMAP hBitmap, int x, int y) {
 int rgb;
 HDC hDC;
 hDC = GetDC(NULL);
 SelectObject(hDC, hBitmap);
 rgb = GetPixel(hDC, x,y);
 ReleaseDC(NULL,hDC);
 return rgb;
}

int rgbC(HDC hDC, HBITMAP hBitmap, int x, int y) {
 int rgb;
 SelectObject(hDC, hBitmap);
 rgb = GetPixel(hDC, x,y);
 return rgb;
}

case WM_LBUTTONDOWN:
 x=100; y=100;

 a = rgbA(hBitmap, x,y);
 b = rgbB(hBitmap, x,y);
 c1 = rgbC(hMin,hBitmap, x,y);

 hDC = CreateCompatibleDC(NULL);
 c2 = rgbC(hDC, hBitmap, x,y);
 DeleteDC(hDC);

 hDC = GetDC(hWnd);
 c3 = rgbC(hDC, hBitmap, x,y);
 ReleaseDC(hWnd,hDC);

 sprintf(msg,"カーソル位置の色は %X, %X, %X, %X, %X です",a,b,c1,c2,c3);
 MessageBox(hWnd,msg,NULL,MB_OK);
 break;

case WM_CREATE:
 hMin =CreateCompatibleDC(NULL);
 hBitmap=(HINSTANCE)LoadImage(hInst,OBMP,IMAGE_BITMAP,0,0,LR_LOADFROMFILE);

補足日時:2008/06/18 10:44
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!