WINAPIで他のウインドウを重ねたときに画像やテキストが消える理由と解決方法

このQ&Aのポイント
  • C++とWINAPIで作成したウインドウに他のウインドウを重ねると、画像やテキストが消えてしまう問題が発生します。
  • この問題の原因は、再描画時に画像やテキストが上書きされてしまうことによります。
  • 解決方法としては、ウインドウの再描画を制御し、他のウインドウが被っても画像やテキストが消えないようにする必要があります。
回答を見る
  • ベストアンサー

WINAPI 他のウインドウを重ねると画像やテキストが消える

C++とWINAPIで、ウインドウを作成し、テキストや画像を表示しています。 このウインドウに他のウインドウを重ねて、再度、このウインドウを表示すると画像やテキストが消えてしまいます。 case WM_PAINT: BitBlt( hbtn0DC, 0, 0, 40, 40, hbtn0bmpDC, 0, 0, SRCCOPY ); return 0; 再描画するタイミングで表示するようにしています。 他のウインドウが被っても消えないようにする方法を教えてください。 もしくは、 他のウインドウが被っても画像が消えないようにする処理を説明しているページをどこかで見たような気がするのですが、見つかりません。 ご存知でしたら教えてください。

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

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

★『WM_PAINT』メッセージの中で hDC を取得します。 サンプル: case WM_PAINT: {  PAINTSTRUCT ps;  HDC hDC;    hDC = BeginPaint( hWnd, &ps );  BitBlt( hbtn0DC, 0, 0, 40, 40, hbtn0bmpDC, 0, 0, SRCCOPY );  EndPaint( hWnd, &ps );  return( 0 ); }

参考URL:
http://www.kumei.ne.jp/c_lang/sdk/sdk_05.htm
sterdust
質問者

お礼

ありがとうございます! できました!!!^^

関連するQ&A

  • WinAPIで画像を更新し続けるには

    本を見ながら、WindowsSDKを使ってビットマップを描画する 所まではできたのですが、動かそうとすると上手くいきません。 ソースを簡略かして載せますと、以下のようにしています。 case WM_KEYDOWN: x++; // static MyDrawBitMap( hWnd, x, 10 ); ------------------------------------------------ void MyDrawBitMap( HWND hWnd, int x, int y ) { hdc = BeginPaint(hWnd, &ps); BitBlt( hdc, x, y, bitmap.bmWidth, bitmap.bmHeight, hMemDC, 0, 0, SRCCOPY); EndPaint(hWnd, &ps); このように書いてますが、ボタンを押しても画面に変化が出ません。 PAINTSTRUCTは再描画が必要な情報に関する構造体だとは解っていま すが、特に変更の必要の無い画像も再描画したい場合の処理はどうす れば良いのでしょうか?よろしくお願いします。

  • WinAPIでの画像高速切り替え表示プログラム1

    WinAPIを使用して、ビットマップ画像を8枚読み込み、それを連続高速表示するプログラムを作成しています。 今はSetTimerを使ってWM_TIMERを受け取ったときに画像をInvalidateRect(再描画)しています。 以下のソースで動作はするのですが、WM_TIMERは整数ミリ秒でしか設定できず、精度も悪く優先順位も遅いようなので他の方法を考えています。 画像8枚を6.25msecで切り替えて表示するというのをESCAPEするまで繰り返したいのですが...。 リフレッシュレートは160Hzにあげています。 QueryPerformanceFrequencyというものを使えばいいのかなと思っていますが、どこでどう使えばいいのか、それをどう受け取って再描画すればいいのかわかりません。 どなたかご教授お願いします。ソースファイルを書いていただけたら嬉しいです。 #include<windows.h> #define BMP_SUM8//画像の総数 #define TIMER_ID (100) // 作成するタイマの識別ID #define TIMER_ELAPSE (6) // WM_TIMERの発生間隔 LRESULT CALLBACK WindowProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam){ HDC hdc; PAINTSTRUCT ps; HBITMAP hBitmap; int i; const char *filename[BMP_SUM]={"gazou0.bmp", "gazou1.bmp", "gazou2.bmp", "gazou3.bmp", "gazou4.bmp", "gazou5.bmp", "gazou6.bmp", "gazou7.bmp"}; static HDC hMemDC[BMP_SUM]; static BITMAP bmp; static int bmp_index;//現在の画像番号 LONG lResult; switch(uMsg) { case WM_CREATE: hdc=GetDC(hWnd); for(i=0;i<BMP_SUM;i++){ hBitmap=(HBITMAP)LoadImage(0,filename[i],IMAGE_BITMAP,0,0,LR_LOADFROMFILE); hMemDC[i]=CreateCompatibleDC(hdc); SelectObject(hMemDC[i],hBitmap); } GetObject(hBitmap,sizeof(BITMAP),&bmp); DeleteObject(hBitmap); ReleaseDC(hWnd,hdc); return 0; case WM_TIMER: if( wParam != TIMER_ID ) { break; // 識別IDが一致しないタイマメッセージはDefWindowProc()に任せる } if(++bmp_index >= BMP_SUM) bmp_index=0; for(i = 0; i < BMP_SUM; i++){ InvalidateRect( hWnd, NULL, FALSE ); } return 0; case WM_DESTROY: for(i=0;i<BMP_SUM;i++) DeleteDC(hMemDC[i]); PostQuitMessage(0); return 0; case WM_PAINT: hdc=BeginPaint(hWnd,&ps); BitBlt(hdc,0,0,bmp.bmWidth,bmp.bmHeight,hMemDC[bmp_index],0,0,SRCCOPY); EndPaint(hWnd,&ps); return 0; case WM_KEYDOWN: switch((CHAR)wParam) { case VK_ESCAPE: for(i=0;i<BMP_SUM;i++) DeleteDC(hMemDC[i]); PostQuitMessage(0); //WM_QUITメッセージを出す return 0; } } return DefWindowProc(hWnd,uMsg,wParam,lParam); } 入りきらないので2つに分けます。 続きは「WinAPIでの画像高速切り替え表示プログラム2」を見てください。

  • 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); }

  • BitBlt関数について

    お世話になっております。   またまた質問ですが、   画像を表示したいので、BitBlt関数を使ってみたんですが、   エラーもなく、実行できました。   しかし、画像が表示されません。   サイトや本を何回も見て、間違いがないか見たんですけど、間違いがまったく見当たりません。   LRESULT CALLBACK VisualProc ( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { switch(uMsg) { case WM_CREATE: memdc = CreateCompatibleDC( NULL ); hBitmap = ( HBITMAP )LoadImage( NULL , TEXT("player.bmp") , IMAGE_BITMAP , 0 , 0 , LR_LOADFROMFILE | LR_CREATEDIBSECTION ); SelectObject(memdc, hBitmap); return 0; case WM_PAINT: hdc = BeginPaint(VisualWnd,&ps); BitBlt(hdc, 30,30, 34, 32, memdc, 0, 0, SRCCOPY); EndPaint(VisualWnd,&ps); return 0; .............................................................................. 画像は、リソースで追加→既存の項目→ピクチャ でやりました。 それで、ピクチャからプロジェクトのファイルに移動させました。   それでもできません。     一体どのようにやればいいのでしょうか。 わかりやすく教えてください。

  • メモリデバイスコンテキストを用いた描画処理

    お世話になります。 Borland C++ 5.5.1 for Win32で簡易な画像ビュアーを開発しています。 基本的な動作は完成したのですが、ある条件下で発生する問題を回避するために、メモリデバイスコンテキストを用いようと考えています。 ところが、後述のように変更したところ、画像がまったく表示されなくなりました。(ウィンドウ背景色で塗りつぶされたままです。一瞬たりとも表示されません。) Windowsプログラムに慣れていないため解決に難儀しています。 どなたか原因と対策をご教示くださいますようよろしくお願いします。 ////////////////////////// //変更前 画像表示される// ////////////////////////// case WM_PAINT: hdc = BeginPaint(hWnd, &ps); /* ~省略(画像処理)~ */ StretchDIBits(hdc,~,SRCCOPY);//処理した画像をウィンドウへ EndPaint(hWnd, &ps); break; //////////////////////////// //変更後 画像表示されない// //////////////////////////// case WM_PAINT: hdc = BeginPaint(hWnd, &ps); hmemdc = CreateCompatibleDC(hdc); /* ~省略(画像処理)~ */ StretchDIBits(hdc,~,SRCCOPY);//処理した画像をMemoryDCへ BitBlt(hdc, 0, 0, rc.right, rc.bottom, hmemdc, 0, 0, SRCCOPY);//MemoryDCからウィンドウへ(rcはクライアント領域) DeleteDC(hmemdc); EndPaint(hWnd, &ps); break;

  • Win32APIを使って入力されたキーによって表示する画像を変えるプログラムについて

    Win32APIを使って入力されたキーによって表示する画像を変えるプログラムを今、VisualSutudio2005のVC++で作っている最中なのですが、 上手く画像が表示されず困っています。具体的には、キーボードからキーが入力されたらTranslateMessage関数でWM_CHARメッセージを送って、その値(wParam)をWM_CHARメッセージ内でTCHAR型の変数に代入し、InvalidateRect関数を使ってWM_PAINTメッセージを送って、再描画処理を行ってその中で、if(tchar == 'a') { hbitmap = (HBITMAP)LoadImage(NULL,BMP,IMAGE_BITMAP,0,0,LR_LOADFROMFILE); SelectObject(hMemdc,hbitmap); GetObject(hbitmap,sizeof(BITMAP),&bitmap); BitBlt(painthdc,0,0,350,467,hMemdc,0,0,SRCCOPY); } という処理をしてaが入力されたら読み込んだ画像を表示!という形にしたいのですが、実際ウィンドウには表示されなくて悩んでいます。わかりにくくて誠に申し訳ありませんが、どなたかどうかご教授願えないでしょうか。何卒よろしくお願い致します。

  • WM_PAINTとBitBlt

    レベルはWindowsプログラミングを始めて1月半、それ以前にプログラミング経験はありません。 環境は、VC++6.0 WindowsXP SP2です。 WINAPIしか使えません(MFCは分かりません)。 宜しくお願い致します。 定期的に図形を動かすプログラムを副スレッドを用いて作りました。 副スレッドにはSleep(5msスリープ)を入れてあり、スレッドの最後にInvalidateRectを実行し、WM_PAINTを発行して再描画させているのですが、動作は所望な通りなものの、画面がちらついてしまいます。 所持している参考書を読むと、図形を動かす処理を直接ディスプレイに出すのではなく、メモリDCに一度出力し、その後BitBltでディスプレイに出力すればよい(ダブルバッファのことらしい?)、と書いてありました。 また、あるサイトには、WM_PAINTが実行されるとOnEraseBkgndが走るからちらつくとも書いてあり、何だか良く分かりません。 (別のサイトにはOnPaintが走るとか、OnPaintBackgroundが走ると書いてあり、何が本当なのか???) 自分の知りたいことは以下の通りです。 1)WM_PAINTで画面の再描画を行うと画面が何故チラつくのですか? また、ちらつかない様にする方法はあるのでしょうか? 2)BitBltを用いるとチラつかないのは何故でしょうか? 3)参考までにですが、メモリDCでBitBltで転送、以外に画面をチラつかせずに画面を更新させる方法はあるでしょうか? 色々サイトを探してみてのですが、断片的にしか書いておらず、結局自分が所望する回答は得られませんでした。 初心者レベルなので、分かりやすく説明して頂けると大変嬉しいです。 以上、宜しくお願い致します。

  • 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); }

  • ウインドウ内全体を一定時間で更新したい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); }

  • 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; ...省略... }

専門家に質問してみよう