• ベストアンサー

WinAPIのGetDIBitsでディスプレイのビットを...

CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL) で、ディスプレイのHDCを収得したのですが、その後ある一定範囲のビットを調べたいです。 しかし、GetPixelだと処理が遅くなり、困っています。 GetDIBitsはあまり解説しているサイトが少なく、よくわかりません・・・。 また、第一パラメータはHDCを指定すればいいようですが、そのあとのビットマップハンドルをなぜ指定する必要があるのでしょうか。 それと、ディスプレイのビットマップハンドルを収得できますか?

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

  • ベストアンサー
  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.1

★『CreateDIBSection』関数を利用すると良い。 ・ディスプレイのデバイス・コンテキスト(HDC)などを 1 ピクセル 32 ビットの DWORD 型配列で  管理して扱う方法があります。この方法を使えば直接ピクセル値をアクセスするため GDI の  GetPixel() 関数よりは早くデータを取得(設定)できます。 ・下にそのサンプルを載せます。 サンプル: BITMAPINFO BmpInfo; HBITMAP hBMP, hBMPOLD; LPDWORD lpRGB; HDC hdcBMP; // ヘッダ情報の設定 ZeroMemory( &BmpInfo, sizeof(BITMAPINFO) ); BmpInfo.bmiHeader.biSize = sizeof( BITMAPINFOHEADER ); BmpInfo.bmiHeader.biWidth = XDOT; BmpInfo.bmiHeader.biHeight = YDOT; BmpInfo.bmiHeader.biPlanes = 1; BmpInfo.bmiHeader.biBitCount = 32; BmpInfo.bmiHeader.biCompression = BI_RGB; hBMP = CreateDIBSection( hDC, &BmpInfo, DIB_RGB_COLORS, (LPVOID*)(&lpRGB), NULL, 0 ); hdcBMP = CreateCompatibleDC( hDC ); hBMPOLD = SelectObject( hdcBMP, hBMP ); // GDIでアクセスする方法 SetPixel( hdcBMP, x, y, RGB(0xFF,0xCC,0x33) ); ←オレンジ色をセット GetPixel( hdcBMP, x, y ); ←座標(x,y)の点を取得 // DIBでアクセスする方法 lpRGB[ XDOT * y + x ] = 0xFFCC33; ←座標(x,y)にRGB(0xFF,0xCC,0x33)のオレンジ色を書き込む printf( "RGB=%d,%d,%d\n",  (BYTE)(lpRGB[XDOT * y + x] >> 8*2),  (BYTE)(lpRGB[XDOT * y + x] >> 8*1),  (BYTE)(lpRGB[XDOT * y + x] >> 8*0) ); // 後始末 SelectObject( hdcBMP, hBMPOLD ); DeleteObject( hdcBMP ); DeleteObject( hBMP ); その他: ・『hDC』がディスプレイのデバイス・コンテキストです。  あと XDOT、YDOT は横と縦のピクセル数を表した定数です。  サンプルを利用する際には、ピクセル数を記号定数や変数などで指定して下さい。 ・上記の方法ならば GetPixel() 関数を使わずに DWORD のピクセル配列で操作(取得)しますので、  アクセスが早くなります。ただし、注意点が1つあります。  それは GDI の GetPixel() 関数とは、座標指定が上下で逆転します。  つまり、GetPixel(hDC,0,0) は左上隅ですが、lpRGB[XDOT * 0 + 0] は左下隅になります。  この仕組みは、BMPファイルの構造と同じです。→むしろ、この構造にBMPファイルをあわせたのか? ・取得も設定も DWORD 型の lpRGB[] 配列でアクセスできます。  DWORD の構造は、下位から 8 ビット単位で B、G、R、未使用の順に並んでいます。  この構造のため、1 ピクセルを DWORD 変数1つで扱えてとっても便利です。  マクロ関数を作ってアクセスすれば分かり易いかもしれません。  『#define MacroGetPixel(x,y)  (lpRGB[XDOT * (y) + (x)])』  『#define MacroSetPixel(x,y,c) (lpRGB[XDOT * (y) + (x)]=(c))』  の2つです。変数名(lpRGB)、記号定数名(XDOT)を変える場合は注意して下さい。 ・以上。おわり。→参考にどうぞ。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (1)

noname#30727
noname#30727
回答No.2

>ある一定範囲のビットを調べたい 一般的には、BitBltやStretchBltを使用してディスプレイのDCから自分で作成したDCへ範囲指定でコピーし、そのコピーしたビットマップイメージを参照する事になります。 ディスプレイのDCにはビットマップ相当の何か(VRAMそのもの?)がSelectObjectされている状態になっています。自分で作成したDCには自分で作成したビットマップをSelectObjectしなければなりません。それぞれコピー元とコピー先に指定してBitBltなどを実行すると、デスクトップのビットマップイメージが自分で作成したビットマップにコピーされます。 DIB(デバイスに依存しないビットマップ)がSelectObjectされているDCをコピー先にすると、デスクトップの色数に関係なくDIBで指定した形式に変換しながらコピーされます。ハイカラーやフルカラーはもちろん、特殊なビデオカードの特殊な形式であっても意識する必要がなくなります。 DCやDIBの作成方法は#1さんが解説されている通りだと思います。 付け加えるなら、BITMAPINFOのbmiHeader.biHeightに負数を指定する(100ピクセルなら-100を指定する)と、上下が逆になったトップダウンビットマップが作成されるので、アドレスの計算が少し簡単になります。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • GetPixelに使うHDCの作り方

    ビットマップハンドルhBitmap の(x,y)の画素の色を読み取るプログラムに使うデバイスコンテキストとして、  hDC = CreateCompatibleDC(NULL);  SelectObject(hDC, hBitmap);  rgb = GetPixel(hDC, x,y);  DeleteDC(hDC); のように、NULL を指定して、画面と互換性のあるメモリデバイスコンテキストを指定したのですが、正しい色が読み出せません。hDC = GetDC(NULL);でも同じく駄目でした。hDCはどのように作ったらよいのでしょう。 なお、関数の中でGetPixel()を使いたいので、hWnd などは使えません。

  • WinAPI Directshow 動画

    WindowsプログラミングでDirectshowを使って動画処理をしています。 最終的には、動画処理した結果をウィンドウに順に表示させていくプログラムを作りたいです。 そのため、まずは、下の手順のようなプログラムを現在作っています。 (1) 動画を1フレームごとに取り込む (2) 情報をビットマップに書き出す (3) ビットマップを読み込む (4) ウィンドウに描画する (5) (1)~(4)を繰り返す プログラムはVisualStudio2005を使い、ウィンドウズアプリケーションで作成しています。 ウィンドウにビットマップが表示されてほしいのですが、何も表示されません。 2週間悩んでいますが、解決しません;; 以下にソースを貼らせていただきますので、アドバイスいただきたいです。 ※ソースの量が多いので、WM_TIMER, WM_PAINTの部分を中心に載せています。  (その他の部分は、最初から書かれているソースからほぼ変更していないです)  なお、WM_TIMER部分については、文字数の関係から別アカウントから回答1に書かせていただきます。 ----------------------- <追加グローバル宣言> int douga_flag=0; //メニューで動画処理を選ぶと1になります IGraphBuilder *pigb = NULL; /* フィルタグラフ用 */ IMediaControl *pimc = NULL; IMediaSeeking *pims = NULL; IBaseFilter *pibf = NULL; /* サンプルグラブ用 */ ISampleGrabber *pisg = NULL; IVideoWindow *pivw =NULL; AM_MEDIA_TYPE amt; HRESULT hr; OAFilterState fs; long n; LONGLONG nn1, flame_number; CImage1 gazou; /* ビットマップ画像のクラス */ // gazou.width(横サイズ), gazou.height(縦サイズ), gazou.bmmap_data(画像情報の入った配列) /* 動画→lpBmpDataに情報がはいる */ typedef struct { HINSTANCE hi; int x; // 表示開始位置 int y; HWND hwnd; // 自分のウィンドウハンドル BYTE *lpBmpData; // BMPのデータ部分 BITMAPINFOHEADER bih; } IMG0; IMG0 img00; ----------------------- <WndProc(主に WM_PAINT のソース)> LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; int id, ww, hh; PAINTSTRUCT ps; HBITMAP hBmp, hBmpOld; BITMAP bmp_info; HDC hdc, hdc_mem; switch (message) {  ...省略... case WM_TIMER: //文字数の関係から別アカウントから回答1に書きます break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); hdc_mem = CreateCompatibleDC(hdc); hBmp = LoadBitmap(hInst, TEXT("bitmap.bmp")); GetObject(hBmp, (int)sizeof(BITMAP), &bmp_info); ww = bmp_info.bmWidth; hh = bmp_info.bmHeight; hBmpOld = (HBITMAP)SelectObject(hdc_mem, hBmp); BitBlt(hdc, 0, 0, ww, hh, hdc_mem, 0, 0, SRCCOPY); SelectObject(hdc_mem, hBmpOld); DeleteDC(hdc_mem); DeleteObject( hBmp ); // ロードしたビットマップを削除する EndPaint(hWnd, &ps); break; ...省略... }

  • WinAPIでスクリーン画像を映し続けるプログラムその2

    タイマー1秒ごとに画面を更新させたいのですが、リージョンの範囲しか更新されないため、ウインドウを最上層に置いておくと、画面がかわりません。下記ソースはそれを確かめるため、タイマーで更新する画面を100×100pixlから1秒ごとに徐々に大きくしていったところ、やはりペイントが違う画面で覆った部分しかそのとおり更新されていませんでした。参考書だとこんな感じでできる気がするのですが、InvalidateRect( hwnd, NULL, TRUE );のところでウインドウ全体を更新しなければいけない範囲にするべきだと思うのですが、具体的な解決策がわかりません。 お力を貸していただけると助かります。 #include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); void getScreenShot(HBITMAP hBmpShot, int iX, int iY, int iWidth, int iHeight) ; /*ビットマップハンドル*/ static HBITMAP _bmpShot = 0; int popo=100; int _iWidth=1024, _iHeight=400; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow){ MSG msg; WNDCLASS wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW; /* ウインドウクラス設定 */ wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = "vcshot"; RegisterClass(&wndclass); /* メインウインドウ作成 */ HWND hwMain = CreateWindow("vcshot", "", WS_POPUP | WS_VISIBLE , 0,0, _iWidth, _iHeight, NULL, NULL, hInstance, NULL); ShowWindow(hwMain, iCmdShow); /* メッセージループ */ while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int)msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { switch (iMsg) { case WM_CREATE: { /*先に外側で作成してしまう方が得策かもしれない*/ HDC hDC = ::GetDC(0); _bmpShot = ::CreateCompatibleBitmap(hDC, _iWidth, _iHeight); ::ReleaseDC(0, hDC); /* スクリーンショット取得 */ getScreenShot(_bmpShot, 0, 0, _iWidth, _iHeight); SetTimer(hwnd , 1 , 1000 , NULL); return 0; } case WM_TIMER:{ popo=popo+20; getScreenShot(_bmpShot, 0, 0, popo, popo); InvalidateRect( hwnd, NULL, TRUE ); return 0;} case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); /* ビットマップが作成されていれば描画 */ if(_bmpShot != NULL) { BITMAP bmp; /*この関数でビットマップから、詳細を知る事が出来る*/ ::GetObject(_bmpShot, sizeof(BITMAP), &bmp); /*以下決まり文句*/ HDC _hdcShot = ::CreateCompatibleDC(0); ::SelectObject(_hdcShot, _bmpShot); BitBlt(hdc, 0, 0, _iWidth, _iHeight, _hdcShot, 0, 0, SRCCOPY); /*使い終えたら直に閉じる*/ ::DeleteDC(_hdcShot); } EndPaint(hwnd, &ps); return 0; } case WM_DESTROY : /* ビットマップが作成されていたら関連リソースを削除 */ if(_bmpShot != NULL) { /*SelectObject(_hdcShot, _bmpOld);*/ DeleteObject(_bmpShot); /*DeleteObject(_hdcShot);←よく見ると、デバイスコンテキストに対してDeleteObjectを使用しています。*/ } PostQuitMessage(0); return 0; } return DefWindowProc (hwnd, iMsg, wParam, lParam); } void getScreenShot(HBITMAP hBmpShot, int iX, int iY, int iWidth, int iHeight) { /* キャプチャサイズを保存 _iWidth = iWidth; _iHeight = iHeight; */ /* 画面のデバイスコンテキスト取得 */ HDC hdcScreen = GetDC(0); /* ビットマップ描画用デバイスコンテキスト作成 */ HDC _hdcShot = CreateCompatibleDC(hdcScreen); /* スクリーンショット保存用ビットマップ作成 */ /*_bmpShot = CreateCompatibleBitmap(hdcScreen, iWidth, iHeight);*/ /* デバイスコンテキストにビットマップを設定 */ /*_bmpOld = (HBITMAP)*/SelectObject(_hdcShot, hBmpShot); /* 画面上の領域をビットマップに描く */ BitBlt(_hdcShot, 0, 0, iWidth, iHeight, hdcScreen, 0, 0, SRCCOPY); /* 画面のデバイスコンテキスト解放 */ ReleaseDC(0, hdcScreen); /*使用したら直に閉じる*/ ::DeleteDC(_hdcShot); }

  • UNICODE指定のプロジェクトで関数Wの呼出し?

    .NET VC++で簡単な印刷プログラムを作りました hdc = CreateDC(TEXT("EPMJ3"), TEXT("Canon MP280 series Printer"), NULL, NULL);・・・(1) StartDoc(hdc, &docinfo);                           ・・・(2) StartPage(hdc); TextOut (hdc, 10, 200,L"テスト印刷の1行目です。", 12);           ・・・(3) TextOutW(hdc, 10, 100,L"テスト印刷の2行目です。", 12);           ・・・(4)  EndPage(hdc); EndDoc(hdc); DeleteDC(hdc); プロジェクトの文字コードはUNICODEを指定しております (1)はCreateDocW関数 (2)はStartDocW関数が呼ばれます (3)は当然TextOutW関数になるだろうと思っていたら、TextOutA関数が呼ばれいます 試しに(4)のように直接TextOutW関数を指定してみたら、これも結果に於いてTextOutA関数が呼ばれています    【以上の事柄はAPIフックを仕掛けて調べました】 なぜ私のコンパイラはUNICODE用のTextOut関数を呼出してくれないのですか????

  • ウインドウ内全体を一定時間で更新したいWinAPI

    ウインドウ内全体をWM_TIMERを使って一定時間毎に更新したいのですが、うまくいきません。資料・アドバイスを参考にここまで作ったのですが、おそらくWM_PAINTのところでリージョン領域しか更新していないのかと思います。そこでInvalidateRect( hwnd, NULL, NULL ); をウインドウ内全体をリージョンする関数、たとえはRedrawWindow などを使ってみたのですが、正しくできていないためか状況が変わりません。 毎度のことで申し訳ありませんがアドバイスお願いします。 #include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); void getScreenShot(HBITMAP hBmpShot, int iX, int iY, int iWidth, int iHeight) ; /*ビットマップハンドル*/ static HBITMAP _bmpShot = 0; int _iWidth=1024, _iHeight=400; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow){ MSG msg; WNDCLASS wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW; /* ウインドウクラス設定 */ wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = "vcshot"; RegisterClass(&wndclass); /* メインウインドウ作成 */ HWND hwMain = CreateWindow("vcshot", "", WS_POPUP | WS_VISIBLE , 0,0, _iWidth, _iHeight, NULL, NULL, hInstance, NULL); ShowWindow(hwMain, iCmdShow); /* メッセージループ */ while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int)msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { switch (iMsg) { case WM_CREATE: { /*先に外側で作成してしまう方が得策かもしれない*/ HDC hDC = ::GetDC(0); _bmpShot = ::CreateCompatibleBitmap(hDC, _iWidth, _iHeight); ::ReleaseDC(0, hDC); /* スクリーンショット取得 */ getScreenShot(_bmpShot, 0, 0, _iWidth, _iHeight); SetTimer(hwnd , 1 , 16 , NULL); return 0; } case WM_TIMER:{ getScreenShot(_bmpShot, 0, 0, _iWidth, _iHeight); InvalidateRect( hwnd, NULL, NULL ); return 0;} case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); /* ビットマップが作成されていれば描画 */ if(_bmpShot != NULL) { BITMAP bmp; /*この関数でビットマップから、詳細を知る事が出来る*/ ::GetObject(_bmpShot, sizeof(BITMAP), &bmp); /*以下決まり文句*/ HDC _hdcShot = ::CreateCompatibleDC(0); ::SelectObject(_hdcShot, _bmpShot); BitBlt(hdc, 0, 0, _iWidth, _iHeight, _hdcShot, 0, 0, SRCCOPY); /*使い終えたら直に閉じる*/ ::DeleteDC(_hdcShot); } EndPaint(hwnd, &ps); return 0; } case WM_DESTROY : /* ビットマップが作成されていたら関連リソースを削除 */ if(_bmpShot != NULL) { /*SelectObject(_hdcShot, _bmpOld);*/ DeleteObject(_bmpShot); /*DeleteObject(_hdcShot);←よく見ると、デバイスコンテキストに対してDeleteObjectを使用しています。*/ } PostQuitMessage(0); return 0; } return DefWindowProc (hwnd, iMsg, wParam, lParam); } void getScreenShot(HBITMAP hBmpShot, int iX, int iY, int iWidth, int iHeight) { /* キャプチャサイズを保存 _iWidth = iWidth; _iHeight = iHeight; */ /* 画面のデバイスコンテキスト取得 */ HDC hdcScreen = GetDC(0); /* ビットマップ描画用デバイスコンテキスト作成 */ HDC _hdcShot = CreateCompatibleDC(hdcScreen); /* スクリーンショット保存用ビットマップ作成 */ /*_bmpShot = CreateCompatibleBitmap(hdcScreen, iWidth, iHeight);*/ /* デバイスコンテキストにビットマップを設定 */ /*_bmpOld = (HBITMAP)*/SelectObject(_hdcShot, hBmpShot); /* 画面上の領域をビットマップに描く */ BitBlt(_hdcShot, 0, 0, iWidth, iHeight, hdcScreen, 0, 0, SRCCOPY); /* 画面のデバイスコンテキスト解放 */ ReleaseDC(0, hdcScreen); /*使用したら直に閉じる*/ ::DeleteDC(_hdcShot); }

  • メモリデバイスコンテキスト&ビットマップハンドル

    static VOID _SetSize(pLayer object, LONG w, LONG h) { LayerEx * obj; obj = (LayerEx *)object; obj->size.x = w; obj->size.y = h; if(obj->hBitmap){ HDC hdc , hNewDC; HBITMAP hNewBitmap; hdc = object->GetDC(object); hNewDC = CreateCompatibleDC(hdc); hNewBitmap = CreateCompatibleBitmap(hdc , w , h); SelectObject(hNewDC , hNewBitmap); BitBlt(hNewDC , 0 , 0 , w , h , hdc , 0 , 0 , SRCCOPY); DeleteObject(hNewDC); object->DeleteDC(object , hdc); DeleteObject(obj->hBitmap); obj->hBitmap = hNewBitmap; } 一度生成したビットマップのサイズを変更してもう一度ビットマップを生成するプログラムらしいのですが、 BitBlt(hNewDC , 0 , 0 , w , h , hdc , 0 , 0 , SRCCOPY); ↑なぜBitBltで転送しているのかわかりません。 新しく生成したビットマップをSelectObjectで登録したらいいような感じがするんですが・・・ DeleteObject(hNewDC); ↑あとこれはDeleteDC(hNewDC)の間違いなのでしょうか?ここも何しているか分かりません。 分かる人いたら教えてください。説明足りなかったらごめんなさい^^; ↓一応object->GetDC(object)のソースです。 static HDC _GetDC(pLayer layer) { LayerEx * obj; HDC hResult; obj = (LayerEx *)layer; if(obj->hBitmap == NULL){ HDC hdc; hdc = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL); obj->hBitmap = CreateCompatibleBitmap(hdc, obj->size.x, obj->size.y); hResult = CreateCompatibleDC(hdc); SelectObject(hResult, obj->hBitmap); DeleteDC(hdc); } else{ hResult = CreateCompatibleDC(NULL); SelectObject(hResult, obj->hBitmap); } return hResult; }

  • WinAPIでスクリーン画像を映し続けるプログラム

    通常のスクリーン画面を加工して更新し続ける、たとえば拡大ツールのようなプログラムを作るにあたりまして、 ひとまずスクリーンショットを1秒ごとに更新し続ける動作をさせたいのですが、うまくいきません。 下記のソースはWEBのサンプルをお借りし参考書を見ながら 作りました。 ずっと動かしているとメモリ使用量が上がってしまったりします。 ご指導いただけると助かります。 スクリーン画像を映し続けるプログラム/** 画面キャプチャし続ける */ #include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); void getScreenShot(int iX, int iY, int iWidth, int iHeight); HBITMAP _bmpShot = NULL, _bmpOld; HDC _hdcShot = NULL; int _iWidth, _iHeight; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow){ MSG msg; WNDCLASS wndclass; /* ウインドウクラス設定 */ wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = "vcshot"; RegisterClass(&wndclass); /* メインウインドウ作成 */ HWND hwMain = CreateWindow("vcshot", "", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 680, NULL, NULL, hInstance, NULL); ShowWindow(hwMain, iCmdShow); /* メッセージループ */ while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int)msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; switch (iMsg) { case WM_CREATE: /* スクリーンショット取得 */ getScreenShot(0, 0, 600, 480); SetTimer(hwnd , 1 , 100 , NULL); return 0; case WM_TIMER: getScreenShot(0, 0, 600, 480); return 0; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); /* ビットマップが作成されていれば描画 */ if (_bmpShot != NULL) { BitBlt(hdc, 0, 0, _iWidth, _iHeight, _hdcShot, 0, 0, SRCCOPY); } EndPaint(hwnd, &ps); return 0; case WM_DESTROY : /* ビットマップが作成されていたら関連リソースを削除 */ if (_bmpShot != NULL) { SelectObject(_hdcShot, _bmpOld); DeleteObject(_bmpShot); DeleteObject(_hdcShot); } PostQuitMessage(0); return 0; } return DefWindowProc (hwnd, iMsg, wParam, lParam); } void getScreenShot(int iX, int iY, int iWidth, int iHeight) { /* キャプチャサイズを保存 */ _iWidth = iWidth; _iHeight = iHeight; /* 画面のデバイスコンテキスト取得 */ HDC hdcScreen = GetDC(0); /* スクリーンショット保存用ビットマップ作成 */ _bmpShot = CreateCompatibleBitmap(hdcScreen, iWidth, iHeight); /* ビットマップ描画用デバイスコンテキスト作成 */ _hdcShot = CreateCompatibleDC(hdcScreen); /* デバイスコンテキストにビットマップを設定 */ _bmpOld = (HBITMAP)SelectObject(_hdcShot, _bmpShot); /* 画面上の領域をビットマップに描く */ BitBlt(_hdcShot, 0, 0, iWidth, iHeight, hdcScreen, 0, 0, SRCCOPY); /* 画面のデバイスコンテキスト解放 */ // ReleaseDC(NULL, hdcScreen); }

  • c言語を使いダイアログにbmpを表示したい 

    はじめまして、 私は、c言語は初心者なのでが、ダイアログボックスに、画像(bmp)が表示することができません。 ソースは、 hdc = BeginPaint(hDlg, &ps); //指定ウィンドウ内での描写準備 // ビットマップをファイルからロードする hBitmap = ::LoadBitmap( NULL, _T("test.bmp") ); // ウィンドウのデバイスコンテキストハンドルを取得する hDC = GetDC( hDlg ); // メモリデバイスコンテキストを作成する hCompatDC = CreateCompatibleDC( hDC ); // ロードしたビットマップを選択する GetObject(hBitmap, sizeof(BITMAP), &bmp); // ビットマップをウィンドウに転送する(表示する) if(hBitmap != NULL){ StretchBlt( hDC, 0, 0, 100, 100, hCompatDC, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY ); SendDlgItemMessage( hDlg, IDC_STATIC, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap); } なのですが、これはメインウィンドウでは動くのですが、ダイアログボックスでは動かずこまっています。 どうか、助言のほどよろしくお願いします。

  • マルチモニタのデスクトップイメージを取るには?

    VisualC++です。 デスクトップイメージを取得するため、 CMainFrm内で、 CRect rect; CWnd* pwWnd = GetDesktopWindow(); pwWnd->GetClientRect( &rect ); CDC* pwDC = pwWnd->GetDC(); とやって、このpwDCを使ってイメージを取得することに成功しました。 しかし、この方法では、シングルモニタの場合のみ成功し、マルチモニタでは、メインモニタのイメージのみが取れて、双方の画面のイメージはとれないようです。 わたしは今、モニタを2つ用意して、右側がメインモニタ、左側がサブモニタとしていますが、左側のモニタのイメージを取得するには、どうしたらよいでしょうか。 rectにも、メインモニタのサイズが入っています。 HDC hDC = ::CreateDC("DISPLAY", NULL, NULL, NULL); CDC* pwHDC = CDC::FromHandle( hDC ); とやって、このpwHDCを使っても、メインモニタのみのデスクトップイメージしかとれないようです。

  • PlgBltのマスク処理

    VC++2005、Win32APIで開発を行っています。 ビットマップを回転、反転させながら描画を行うときの処理について、画像の背景を透過させたいのですが、マスクの処理がうまくいきません。 BOOL PlgBlt( HDC hdcDest, // 転送先のデバイスコンテキストのハンドル CONST POINT *lpPoint, // 転送先平行四辺形の頂点 HDC hdcSrc, // 転送元のデバイスコンテキストのハンドル int nXSrc, // 転送元長方形の左上隅の x 座標 int nYSrc, // 転送元長方形の左上隅の y 座標 int nWidth, // 転送元長方形の幅 int nHeight, // 転送元長方形の高さ HBITMAP hbmMask, // ビットマスクのハンドル int xMask, // ビットマスク長方形の左上隅の x 座標 int yMask // ビットマスク長方形の左上隅の y 座標 ); 上記パラメータの、ビットマップマスク部分で指定したのですが、画像自体が表示されません。 用意したマスク画像の色の設定が間違っているような気がするのですが、元画像の背景および、マスク画像の背景と画像の下地部分は何色で設定するといったようなきまりはあるのでしょうか。 ご存知の方、よろしくお願いします。