WINAPIのスレッドについて教えてください

このQ&Aのポイント
  • WINAPIのスレッドを使用して写真のスライドショウを作成する際、正しいウィンドウサイズを取得できない問題が発生しています。
  • デバッグ時に表示されない変数についても教えてください。
  • 環境はMicrosoft Visual C++ 2008 Express Editionです。
回答を見る
  • ベストアンサー

WINAPIのスレッドについて教えてください

WINAPIのスレッドについて教えてください スレッドを作成して写真をスライドショウー的に表示しようしていますが、 上手くいきません。 typedef struct _dataparam{ HWND hWnd; HDC hSlidDC; int iFileCount; TCHAR szFile[100][MAX_PATH]; HBITMAP hBitmap[100]; }DataParam; という構造体を作成して、各変数に必要な値を代入した後 BIT_SLIDというメッセージが来た場合Threadを作成。 LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wp,LPARAM lp) { static DataParam data={0}; case WM_CREATE: data.hWnd=hWnd; ・ ・ case BIT_SLID: slidCheck=TRUE; CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)SlidThread, (LPVOID)&data,0,&dwThreadId); return 0; Thread関数内でGetClientRectにより下記のように Windowのサイズを測ろうとしましたが rcには正しいWindowのサイズ格納されていません。 DWORD WINAPI SlidThread(LPVOID vdParam) { DataParam *SlidData; RECT rc={0}; SlidData=(DataParam *)vdParam; GetClientRect(SlidData->hWnd,&rc); ・ ・ ・ hWnd以外のiFileCountやszFile[100][MAX_PATH]の値を調べると 問題なく引き渡しているようなのですが、 rcのleft=0 light=459 top=760 bottom=-2142242063となっていました。 けれどThread関数内で InvalidateRect(SlidData->hWnd,NULL,TRUE); 再描画を行います。 ちなみに下記の自作関数では問題なくWindowサイズを取得しております。 int MySetBitmap(HDC hNormalDC,DataParam *data) { GetClientRect(data->hWnd,&rc); ・ ・ ・ 環境はMicrosoft Visual C++ 2008 Express Editionです それと別件なのですが、デバックでローカルに表示される変数と 表示されない変数がありますがその違いを教えていただければ幸いです。 今回SlidDataは表示されません。 ご教授お願いします。

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

  • ベストアンサー
  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.3

>Cランタイムライブラリの意味を理解してないです。 scanf()やprintf()等です。 が、GUIなのでscanf()やprintf()は無意味でしょう。 strtok()を使用していたりすると、マルチスレッドで問題が発生する場合もありますが。 CreateThread()の代わりに_beginthreadex()を使用して下さい。 >dataはstaticな変数です。 >調べましたが、dataもSlidDataも同じアドレスでした。 であるとすると…少々不明です。 ちなみに、期待している本来の値ってどうなるのでしょう?

scanfprintf
質問者

お礼

お答えいただきありがとうございました。 申し訳ありません・・・ デバック時にrcの値を調べると不正確なものでしたが、 MessageBoxに表示すると正確な値でした。 バグなのでしょうか? ちなみに質問文の下部のデバック時に表示されない変数についてはご存知でしょうか?

その他の回答 (2)

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.2

>どうもThread関数に構造体dataを渡すと値が変わってしまうようです。 ・DataParam構造体型のdataは間違いなくstatic変数ですか? ・スレッド起動前のDataParam構造体型のdataのアドレスと、SlidThread()内のSlidDataが指しているアドレスは間違いなく同じですか? ・Cランタイムライブラリを使っている場合はCreateThread()では問題になる場合がありますが、ソコは大丈夫ですか?

scanfprintf
質問者

お礼

dataはstaticな変数です。 調べましたが、dataもSlidDataも同じアドレスでした。 Cランタイムライブラリは使用していません。 dataの中でも他の変数の値は問題無いですし、 InvalidateRect(SlidData->hWnd,NULL,TRUE)で行えるので、 SlidData->hWndの値自体は間違っていないと思うんですが???

scanfprintf
質問者

補足

申し訳ないです。 使用してないと書いてしまいましたが、 Cランタイムライブラリの意味を理解してないです。

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.1

・WndProc()内でdata.hWnd(およびdata自体)を書き換えている箇所はありませんか? ・SlidThread()内でSlidData->hWnd(および*SlidData自体)を書き換えている箇所はありませんか? ・GetClientRect()の戻り値はどうなっていますか?エラーだった場合GetLastError()はなんと言っていますか?

scanfprintf
質問者

お礼

ありがとうございます。 data.hWndもSlidData->hWndも変更しておりません。 GetClientRectもエラーではありませんでした。 試しにParamData構造体にRECT型のrcを作成して、 CreateThreadの直前でdata.hWndのサイズを格納すると、 ここでは問題ありませんでしたが、Thread関数内ですぐに SlidData.rcを調べるとやはり値は変更されていました。 どうもThread関数に構造体dataを渡すと値が変わってしまうようです。 どこが間違っているのでしょうか?

関連するQ&A

  • SDKでウィンドウの中央に文字列を表示させる方法

    ウィンドウの中央に文字列sを表示させる方法を教えて下さい。 /********************************** WM_PAINTで TCHAR s[80]; HDC hDC; PAINTSTRUCT ps; RECT rc; GetClientRect(hWnd, &rc); hDC = BeginPaint(hWnd, &ps); TextOut(hDC, rc.right / 2, rc.bottom / 2, tcDayTime, lstrlen(s)); EndPaint(hWnd, &ps); return FALSE; ***********************************/ GetClientRect(hWnd, &rc);でウィンドウのサイズを取得し、 TextOutの第2、第3引数で ウィンドウ幅/2、ウィンドウ高さ/2 としていますが、これだと中央から表示されてしまいます。 できれば、ウィンドウのサイズを変更してもウィンドウの中央に表示させたいです。 #VC ++ 6.0 & Win98 & SDK で作成してます。

  • StretchBlt関数について

    StretchBlt関数について 画像を縮小して表示しようとしていますが、上手くいきません。 beforeはint型の変数で現在「0」が入っていますので、 無視していただきたいと思います。 まず、テストでStretchBlt関数で縮小しない状態で画面縦幅の中央に表示しようと 下記コードで試みましたが、横は問題ないようですが、 縦に拡大1.5倍くらい拡大されてしまいました。 int MyBitOpen(HWND hWnd,HDC hNormalDC,DataParam *data){ HBITMAP hBitmap; BITMAP bmpInfo={0}; HDC hBitDC; RECT rc; hBitDC=CreateCompatibleDC(NULL); hBitmap=(HBITMAP)LoadImage(NULL,data->szFile[data->iFileCount], IMAGE_BITMAP,0,0,LR_LOADFROMFILE); GetObject(hBitmap,sizeof(BITMAP),&bmpInfo); SelectObject(hBitDC,hBitmap); GetClientRect(hWnd,&rc); StretchBlt(hNormalDC,before+5,(rc.bottom-bmpInfo.bmHeight)/2, (before+5)+bmpInfo.bmWidth,((rc.bottom-bmpInfo.bmHeight)/2)+bmpInfo.bmHeight, hBitDC,0,0,bmpInfo.bmWidth,bmpInfo.bmHeight,SRCCOPY); 関数から戻り BitBlt(hdc,0,0,rc.right,rc.bottom,hNormalDC,0,0,SRCCOPY); で画面出力しております。 これがうまくいかない理由もわかりませんが、 下記のように(1)StretchBltを使用せずBitBltに書き換えただけのものと (2)StretchBltを使用しても描画開始座標を(0、0)に変更したものは 拡大されず上手くいってしまいます。 (1) BitBlt(hNormalDC,before+5,(rc.bottom-bmpInfo.bmHeight)/2, (before+5)+bmpInfo.bmWidth,((rc.bottom-bmpInfo.bmHeight)/2)+bmpInfo.bmHeight, hBitDC,0,0,SRCCOPY); (2) StretchBlt(hNormalDC,0,0,bmpInfo.bmWidth,bmpInfo.bmHeight, hBitDC,0,0,bmpInfo.bmWidth,bmpInfo.bmHeight,SRCCOPY); 座標の取得は間違っていないと思うのですが・・ 本来は画面中央に縦横1/2に縮小した下記のコードでしたが まず上記がうまくいっていないので・・・ 初心者のためシンプルに書けませんでした↓ StretchBlt(hNormalDC,((before+5)+(bmpInfo.bmWidth/4)), (((rc.bottom-bmpInfo.bmHeight)/2)+(bmpInfo.bmHeight/4)), (((before+5)+bmpInfo.bmWidth)-(bmpInfo.bmWidth/4)), ((((rc.bottom-bmpInfo.bmHeight)/2)+bmpInfo.bmHeight)-(bmpInfo.bmHeight/4)), hBitDC,0,0,bmpInfo.bmWidth,bmpInfo.bmHeight,SRCCOPY); ご教授よろしくお願いします。

  • ダブルバッファの作り方

    画面に描画するBCC5.5 のCプログラムがあります。画面がちらつくので、ダブルバッファにしたいのですが、具体的に、どの関数を呼んで実装したらよいのかわかりません。WEB検索をしますと結構情報がヒットしますが、解決に至ってませんので、よろしくお願いします。 具体的にやったことは、現在動いているプログラムの case WM_PAINT:  hdc=BeginPaint(hWnd,&ps);  paint(hdc); // 自作の描画プログラム本体  ReleaseDC(hWnd,hdc);  EndPaint(hWnd,&ps);  break; の部分を、「画面サイズのビットマップイメージhBitmapをつくり、そこにpaint関数で描き込み、最終画面を一気に出力する」というつもりで以下のプログラムに書き換えたのですが、表示すらしなくなってしまいました。何が悪いのかお教えください。 case WM_PAINT:  GetClientRect(hWnd,&rt);   h = (int)rt.bottom;   w = (int)rt.right;  hBuffer = CreateCompatibleDC(NULL);  hBitmap = CreateCompatibleBitmap(hBuffer, w, h);  SelectObject(hBuffer, hBitmap);  paint(hBuffer);  hdc=BeginPaint(hWnd,&ps);   BitBlt(hdc, 0,0,w,h, hBuffer,0,0, SRCCOPY);  ReleaseDC(hWnd,hdc);  EndPaint(hWnd,&ps);  DeleteDC(hBuffer);  DeleteObject(hBitmap);  break;

  • WinAPIでRECT構造体の宣言について

    PAINTSTRUCT ps; HDC hdc; RECT rct={200,200,200,200}; char *szStr = "あけまして\n\tおめでとう"; switch (msg) { case WM_PAINT: GetClientRect(hWnd, &rct); hdc = BeginPaint(hWnd, &ps); DrawText(hdc, (LPCTSTR)szStr, -1, &rct, DT_CENTER | DT_WORDBREAK); EndPaint(hWnd, &ps); break; のようにしているのですが文字列が表示される場所が中央上部です。 何故なのでしょう? 自分としてはど真ん中辺りから表示されるようにしているつもりなのですが

  • 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」を見てください。

  • メモリデバイスコンテキストについて(画像が表示されない)

    VisualC++.netのWindowsSDKでゲームを作ろうと思っている者です。 現在、キー入力により、主人公の画像をウィンドウ上で動かすことまでいきましたが、画面のチラつきが気になったため、メモリデバイスコンテキストを導入することにしました。 しかし、画像が表示されません。画面は初期状態のままです。 現在のソースは以下の通りです。 // ウィンドウプロシージャ内 case WM_CREATE: … GetClientRect(hWnd, &rc); hmdc = CreateCompatibleDC( NULL ); hdc = GetDC( hWnd ); hbgr = CreateCompatibleBitmap( hdc, rc.right, rc.bottom ); ReleaseDC( hWnd, hdc ); SelectObject( hmdc, hbgr ); … case WM_PAINT: … hDefBrush = (HBRUSH)SelectObject( hmdc, GetStockObject( WHITE_BRUSH ) ); PatBlt( hmdc, 0, 0, rc.right, rc.bottom, PATCOPY ); SelectObject( hmdc, hDefBrush ); ShowLife(hmdc); // 自作関数 ShowHero(hWnd, hmdc); // 自作関数 hdc = BeginPaint(hWnd, &ps); BitBlt(hdc, 0, 0, rc.right, rc.bottom, hmdc, 0, 0, SRCCOPY); EndPaint(hWnd, &ps); 自作関数ShowLifeやShowHeroは引数のDCに主人公の画像などを出力する関数です。これの引数をhdcにして、BeginPaintの下に置くとちゃんと画面に主人公が現れて、キー入力にも従ってくれます。 何かヒントになるようなことでも教えてくださると幸いです。情報が少ない場合は補足にて説明します。ヨロシクお願いしますm(_ _)m

  • ビットマップ表示とSetTimer関数を同居させる方法

    ビットマップ表示とSetTimer関数を同居させる方法 現在、vc++2005を使用して、簡易的なGUIアプリケーションを作成しようとしているのですが、自分では解決ができない問題が発生してしまったので、質問させていただきます。 それはビットマップ表示とSetTimer関数を同居させる方法についてです。 ビットマップを読み込んで表示させる機能を追加してから、SetTimer関数が反応しなくなってしまい困っています。 ちなみにビットマップ表示の機能を追加する前まではSetTimer関数が正常に機能していました。 ウィンドウのハンドルhWndが何か関係しているのかと思ったのですが、解決方法がわからず・・・・・・ ご存知の方がいらっしゃましたら御教授いただけると幸いです。 ↓ ソースの一部です case WM_CREATE: //ビットマップファイル読み込み + 表示の準備 static HBITMAP hbitmap,prebitmap; static HDC hDC, hcomDC;      hbitmap = (HBITMAP)LoadImage(NULL,_T("kouen.bmp"),IMAGE_BITMAP,0,0, LR_LOADFROMFILE); if( hbitmap == NULL ) { MessageBox(hWnd, _T("ビットマップのロードに失敗しました"), _T("エラー"),MB_OK | MB_ICONWARNING); return 0; } hDC =GetDC(hWnd); hcomDC =CreateCompatibleDC(hDC); prebitmap= (HBITMAP)SelectObject(hcomDC,hbitmap);            (中略) break;                     case WM_LBUTTONDOWN: //2連続のシングルクリック防止 EnableWindow(hWnd,FALSE); SetTimer(hWnd, ID_TIMER1, 500, NULL); ← これが機能していない          (中略) break; case WM_PAINT: BitBlt( hDC, 0, 0, 1024, 690, hcomDC, 0, 0, SRCCOPY ); break; case WM_TIMER://機能しなくなってしまった部分 if(wParam==ID_TIMER1){ KillTimer(hWnd,ID_TIMER1); EnableWindow(hWnd,TRUE); }

  • マルチスレッド

    ウインドウズプログラミングを始めて1ヶ月弱の初心者です。 色々探してみたのですが、結局良く分かりませんでした。 宜しくお願いします。 以下のリンクにおいて、 http://wisdom.sakura.ne.jp/system/winapi/win32/win143.html 1)主スレッドとは、具体的にソースファイルのどこからどこまでのことを言うのでしょうか? そもそもスレッドとは何でしょうか?関数のことでしょうか? また、タスクとは、実行ファイルと考えて良いのでしょうか? 2)副スレッド(ThreadFunc)を作成すると、主スレッド(WinMain?)と副スレッドで並列処理をするとのことですが、CPUは普通一つしかないので、実際は、主スレッド(WinMain?)と副スレッドを常に切り替えながら動作すると思います。が、ここで疑問なのですが、主スレッドと副スレッドの切り替えはいつ誰が行うのでしょうか?また、切り替えタイミング(例えば1ms毎に切り替えたいとか)は自由に設定出来るのでしょうか? 3)"マルチスレッドは親プロセスのメモリ空間を共有します" とあるのですが、これは CreateThread(NULL , 0 , ThreadFunc , (LPVOID)hWnd , 0 , &dwID) の(LPVOID)hWnd を、副スレッド(ThreadFunc)に引数として渡しているから、つまり、主スレッドと副スレッドは、(LPVOID)hWnd だけがメモリを共有する、ということでしょうか? 主スレッドと副スレッドでメモリを共有すると、どんなメリットがあるのでしょうか? 4)マルチスレッドはこういう時に使うとよい、 というような大まかな判断基準があれば教えて下さい。 分かり辛い質問で申し訳有りません。宜しくお願い致します。

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

専門家に質問してみよう