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

このQ&Aのポイント
  • Win32APIを使用してキー入力に応じて画像を変更するプログラムを作成中ですが、画像が表示されません。
  • 具体的には、キーボードからの入力を受け取り、WM_CHARメッセージを処理して画像を再描画する処理を実装しています。
  • しかし、ウィンドウに画像が表示されないため、問題に困っています。助言いただけると幸いです。
回答を見る
  • ベストアンサー

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が入力されたら読み込んだ画像を表示!という形にしたいのですが、実際ウィンドウには表示されなくて悩んでいます。わかりにくくて誠に申し訳ありませんが、どなたかどうかご教授願えないでしょうか。何卒よろしくお願い致します。

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

  • ベストアンサー
  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.1

hbitmapにビットマップのハンドルは取得できているのでしょうか どこまで実行が期待通りになっているのかを確かめましょう 普通は WndProcのswitch(message)のWM_KEYDOWNの処理でwParamが'A'ならば hbitmap = LoadImage( NULL, "ファイルパス", IMAGE_BITMAP,   0, 0, LR_LOADFROMFILE ); を実行 WM_PAINTの処理で if ( hbitmap != NULL ) {   hOld= (HBITMAP)SelectObject( hMemdc, hbitmap );   BitBlt( paintdc, 0, 0, 350, 476, hMemdc, 0, 0, SRCCOPY );   SelectObject( hMemdc, hOld ); } といった具合で 使うオブジェクトのハンドルを確かめて使いましょう

dfjews
質問者

お礼

教えてgooで質問したのは初めてですが、こんなに早くお返事が頂けるとは思ってもいませんでした!感激です;;アドバイスされた通りWM_KEYDOWNメッセージ内でLoadImage関数を使って画像を読み込み、WM_PAINTメッセージ内でSelectObjectや、BitBlt関数を使うと、入力されたキーによって画像が表示されましたT_T WM_PAINT内で描画処理をまとめたほうが良いと本で読んでいたので、そうするものなのかと思っていましたが、そうもいかないのですね。本当に助かりました!ありがとうございました^-^

その他の回答 (1)

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.2

本来ならWindowクラスを生成する段階(WinMainなど)で hbitmapをNULLで初期化 WM_KEYDOWN内のLoadImageを実行した後で if ( hbitmap == NULL ) {   // エラーの場合の処理 } といった記述をします 機能ごとに処理をまとめたほうが後でメンテナンスする場合分りやすいと思います KEYDOWNイベントで描画もしてしまうと描画処理がばらばらになって どこで処理されて今の結果になるのかが分らなくなってしまうことがあります 一時的な描画必要な場合はこの限りではありませんが ・・・

dfjews
質問者

お礼

ふむふむ。なるほど。まだWindowsアプリケーションの勉強歴が短いので、効率のよい(保守性や整合性?と呼ばれるもの)コードの書き方などがよくわかっていませんでした>< redfox63さんのような専門家の方に言っていただくと安心してそういうものだと納得できます^-^2度も答えていただき誠にありがとうございました!助かりました。

関連するQ&A

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

  • Active Basic 画像表示 添削願い

    AB4.23.00を使っています。 複数画像を表示しようと頑張っているのですが、どうやっても出来ません。 すみませんが、コードの添削の方をお願いします。 '----------------------------------------------------------------------------- ' イベント プロシージャ '----------------------------------------------------------------------------- ' このファイルには、ウィンドウ [MainWnd] に関するイベントをコーディングします。 ' ウィンドウ ハンドル: hMainWnd ' TODO: この位置にグローバルな変数、構造体、定数、関数を定義します。 /*全体*/ Dim hMemDC As HDC /*背景*/ Dim hBackDC As HDC Dim hBackBmp As HBITMAP /*自機*/ Dim hMyDC As HDC Dim hMyBmp As HBITMAP /*プログラムの設定など*/ Dim Dir As String '----------------------------------------------------------------------------- ' ウィンドウメッセージを処理するためのコールバック関数 Function MainWndProc(hWnd As HWND, dwMsg As DWord, wParam As WPARAM, lParam As LPARAM) As DWord ' TODO: この位置にウィンドウメッセージを処理するためのコードを記述します。 ' イベントプロシージャの呼び出しを行います。 MainWndProc=EventCall_MainWnd(hWnd,dwMsg,wParam,lParam) End Function '----------------------------------------------------------------------------- ' ここから下は、イベントプロシージャを記述するための領域になります。 Sub MainWnd_Destroy() stg_DestroyObjects() PostQuitMessage(0) End Sub Sub MainWnd_Create(ByRef CreateStruct As CREATESTRUCT) Dim hDC As HDC Dim OldBmp As HBITMAP SetWindowText(hMainWnd,"しゅーてぃんぐ") 'ディレクトリ取得 Dim path[MAX_PATH+1] As Byte GetCurrentDirectory(MAX_PATH,path) Dir=path 'MainWndのDC取得 hDC=GetDC(hMainWnd) '全体DCメモリ作成 hMemDC=CreateCompatibleDC(hDC) '背景 hBackBmp=LoadImage(0,back.bmp",IMAGE_BITMAP,0,0,LR_DEFAULTSIZE or LR_LOADFROMFILE) hBackDC=CreateCompatibleDC(hDC) 'キャラクター hMyBmp=LoadImage(0,A.bmp",IMAGE_BITMAP,0,0,LR_DEFAULTSIZE or LR_LOADFROMFILE) hMyDC=CreateCompatibleDC(hBackDC) '描写 SelectObject(hMemDC,hBackBmp) BitBlt(hMemDC,0,0,640,480,hBackDC,0,0,SRCCOPY) SelectObject(hMemDC,hMyBmp) BitBlt(hMemDC,0,0,40,50,hMyDC,0,0,SRCCOPY) ReleaseDC(hMainWnd,hDC) End Sub Sub MainWnd_Paint(hDC As HDC) BitBlt(hDC,0,0,640,480,hMemDC,0,0,SRCCOPY) End Sub back.bmpの上にA.bmpを描写したいです。 透過処理などはいらないので、どうすれば表示することが出来るかを教えてください。 今は、どちらか片一方しか表示されません。 また、 http://www.geocities.jp/debu0510/basic/main17.html を参考にさせていただいたのですが、CreateCompatibleBitmap関数の使い方が分かりません。 これは、どのようにして使用するのでしょうか。 こちらもご教授お願いします。

  • 【VC++6.0 MFC】画像表示について

    お世話になっております。C++初心者です。 とある開発でVC++6.0のMFCを利用して画像表示を行う作業をしています。 リソースファイルを使用せず、 外部の画像ファイルを読み込みピクチャーボックスに表示しなければならないのですが、 下記の関数を呼び、BMPファイルを読み込み、 NULLの場合はエラーメッセージを表示するようにしているのですが、 必ずNULLが返ってきてしまいます。 何が問題なのかもわからず苦戦しております。 知識不足で申し訳ないのですが、お願いします。 【疑問点】 ・画像ファイルの指定は絶対パス?相対パス? ***問題の箇所*** HBITMAP hBmp; // ビットマップハンドル // ビットマップのハンドル取得 hBmp = (HBITMAP)::LoadImage(AfxGetInstanceHandle(),"1.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE); // ハンドルのチェック if(hBmp == NULL) {   AfxMessageBox("読み込みに失敗しました");   return ; }

  • VC++でシューティングゲームを作っているのですが・・・

    下のコードをビルドすると、 自分の意図としては、ウィンドウの左上に自機ビットマップが表示されてほしいのですが、 真っ黒な画面になってしまいます。 正確に言うと、背景が黒、自機ビットマップの画像が真っ黒、自機ビットマップの領域にあたる四角が白くなります。 症状に見当がつかないので、手を貸して頂きたいです。 よろしくお願いします。 ちなみに、wc.hdrBackgroundは(HBRUSH)(COLOR_WINDOW+1)となっています。 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; static RECT sizeWnd; static HDC hDC; PAINTSTRUCT ps; static HDC hMemDC; static HBITMAP hMemBmp; static HDC hMjDC; static HBITMAP hMjBmp; static BITMAP infoMjBmp; static POINT posMj; static int flagMjShot; static POINT posMjShot; switch (message) { case WM_CREATE: GetClientRect(hWnd, &sizeWnd); // クライアント領域の大きさをsizeWndに格納 // フロントバッファの初期処理 hDC = GetDC(hWnd); // バックバッファの初期処理 hMemDC = CreateCompatibleDC(hDC); // hDCと互換性をとるメモリデバイスコンテキストhMemDCを構築 hMemBmp = CreateCompatibleBitmap(hMemDC, sizeWnd.right, sizeWnd.bottom); // hMemDCと互換性のあるビットマップhMemBmpをsizeWndの大きさで生成 SelectObject(hMemDC, hMemBmp); // 自機ビットマップの初期処理 hMjDC = CreateCompatibleDC(hMemDC); // hMemDCと互換性をとるメモリデバイスコンテキストhMjDCを構築 hMjBmp = (HBITMAP)LoadImage( // ビットマップイメージMYJET(リソース)をhMjBmpに設定 (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), MAKEINTRESOURCE(IDB_MYJET), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR ); SelectObject(hMjDC, hMjBmp); // hMjDCにhMjBmpを設定 GetObject(hMjBmp, sizeof(BITMAP), &infoMjBmp); // hMjBmpのビットマップ情報をBITMAP構造体infoMjBmpに格納 SetTimer(hWnd, 1, 10, NULL); // 100分の1秒毎にWM_TIMERメッセージを送るタイマー1をセット break; case WM_PAINT: hDC = BeginPaint(hWnd, &ps); // hDCにディスプレイのデバイスコンテキストのハンドルを格納 BitBlt( // hDCにバックバッファhMemDCを転送 hDC, 0, 0, sizeWnd.right, sizeWnd.bottom, hMemDC, 0, 0, SRCCOPY ); EndPaint(hWnd, &ps); break; case WM_TIMER: // 一定時間毎の処理 // 自機ビットマップをバックバッファhMemDCに描画 StretchBlt( // hMjDCを、posMjを左上の座標として縦横を3倍に引き伸ばしてhMemDCに転送 hMemDC, posMj.x, posMj.y, infoMjBmp.bmWidth * 3, infoMjBmp.bmHeight * 3, hMjDC, 0, 0, infoMjBmp.bmWidth, infoMjBmp.bmHeight, SRCCOPY ); InvalidateRect(hWnd, NULL, FALSE); break;

  • デバイスコンテキストの宣言に関するエラー?について

    Run-Time Check Failure #3 - The variable 'hMemDC' is being used without being defined. というエラーが出ます。 自分としては、WM_CREATEの処理で、初期化を行っているつもりなのですが・・・ 力を貸して頂ければ有難いです。よろしくお願いします。 ちなみに、関係のありそうな部分だけ掲載しています。 この部分だけ残して、他の部分をコメントアウトしてコンパイルしても、同じエラーメッセージが出ました。 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; RECT rect; HDC hDC; PAINTSTRUCT ps; HDC hMemDC; HBITMAP hMemBmp; HDC hMjDC; HBITMAP hMjBmp; BITMAP MjBmp; /* POINT posMJ; int MJshot; POINT posMJshot;*/ switch (message) { case WM_CREATE: GetClientRect(hWnd, &rect); // クライアント領域の大きさをrectに格納 hDC = GetDC(hWnd); hMemDC = CreateCompatibleDC(hDC); // hDCと互換性をとるメモリデバイスコンテキストhMemDCを構築 hMemBmp = CreateCompatibleBitmap(hMemDC, rect.right, rect.bottom); hMjDC = CreateCompatibleDC(hMemDC); // hMemDCと互換性をとるメモリデバイスコンテキストhMjDCを構築 hMjBmp = (HBITMAP)LoadImage( // ビットマップイメージMYJET(リソース)をhMjBmpに設定 (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), MAKEINTRESOURCE(IDB_MYJET), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR ); SetTimer(hWnd, 1, 10, NULL); // 100分の1秒毎にWM_TIMERメッセージを送るタイマー1をセット break; case WM_PAINT: hDC = BeginPaint(hWnd, &ps); // hDCにディスプレイのデバイスコンテキストのハンドルを格納 BitBlt( // hDCにバックバッファhMemDCを転送 hDC, 0, 0, rect.right, rect.bottom, hMemDC, 0, 0, SRCCOPY ); EndPaint(hWnd, &ps); break;

  • ダイアログベースでのキー入力について

    現在Win2000、VC++6.0でダイアログベースのアプリを作っています。 ボタンの存在しないダイアログにしているので、 終了するにはタスクバーから閉じるか、ALT+F4キーだけしかないと思っていましたが、 Enterキーを押すと終了してしまうことに気づきました。 このEnterキーを押すと終了してしまうのを回避するには どうしればいいのでしょうか? それと、もう一つ質問なのですが、 WM_CHARメッセージハンドラを追加しましたが、 キーを入力してもOnChar関数にやってきません。 (デバッグでブレークポインタを置いてみたのですが・・・) なにを間違えているのかが分かりません。 どうぞよろしくおねがいします。

  • win32apiでbmpを表示する関数についてです

    bmpを表示する関数と処理する関数を別々のファイルにしたいのですが、表示されません・・・。エラー、警告はありませんでした。VC++2008を使用しています。ソースは以下のようになっています。よろしくお願い致します。 ~ 処理部分 load_bmp.cpp ~ #include <windows.h> #include <stdio.h> #include <tchar.h> extern HINSTANCE hinst; extern HWND hwnd; int Load_Bmp( HDC hdc, char *f_name_of_BMP) { HBITMAP hbmp; HDC work_DC; hbmp=(HBITMAP)LoadImage(hinst,_T ("f_name_of_BMP"),IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION | LR_LOADFROMFILE); if( hbmp == NULL ){ MessageBox(hwnd, _T("ビットマップを表示できません"), _T("エラー"),MB_OK | MB_ICONWARNING); return 0; } work_DC = CreateCompatibleDC( hdc ); SelectObject( work_DC, hbmp ); BitBlt(hdc,0,0,640,480,work_DC,0,0,SRCCOPY); ReleaseDC( hwnd,work_DC ); DeleteObject( hbmp ); return 0; } ~ヘッダファイル load_bmp.h ~ int Load_Bmp( HDC hdc,char *f_name_of_BMP); ~処理部分 main.cpp ~ #include <windows.h> #include <tchar.h> #include "load_bmp.h" HWND hwnd; HDC win_hdc; HINSTANCE hinst; void init_game() { Load_Bmp( win_hdc,"test.bmp"); } LRESULT WndProc(HWND hwnd,UINT msg,WPARAM wprm,LPARAM lprm) { switch(msg){ case WM_CREATE: break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd,msg,wprm,lprm); } return 0; } int APIENTRY WinMain(HINSTANCE hIns,HINSTANCE hPI,LPSTR lpArg,int nCmdShow) { MSG msg; WNDCLASS wc; hinst=hIns; wc.hInstance=hIns; wc.lpszClassName=_T("test"); wc.lpfnWndProc=(WNDPROC)WndProc; wc.style=0; wc.hIcon=LoadIcon((HINSTANCE)NULL,IDI_APPLICATION); wc.hCursor=LoadCursor((HINSTANCE)NULL,IDC_ARROW); wc.lpszMenuName=0; wc.cbClsExtra=0; wc.cbWndExtra=0; wc.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH); if(RegisterClass(&wc)==0)return 0; hwnd=CreateWindowEx( 0, wc.lpszClassName, _T("test"), WS_OVERLAPPEDWINDOW, 20,20,640,480, NULL, NULL, hIns, NULL     ); if(!hwnd) return 0; ShowWindow(hwnd,nCmdShow); UpdateWindow(hwnd); win_hdc=GetDC(hwnd); init_game(); while(1){  if(PeekMessage(&msg,NULL,0,0,PM_NOREMOVE)){ (!GetMessage(&msg,(HWND)NULL,0,0));break; TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; }

  • ビットマップボタンを押したときの処理についてなんですが

    環境はVC++6.0 MFC ダイアログベースです。 MFC初心者なんですが、 HBITMAP hBitmap; hBitmap = (HBITMAP)::LoadImage(AfxGetInstanceHandle(), (LPCTSTR)csBMPFile,      IMAGE_BITMAP, 0, 0,LR_LOADFROMFILE|LR_CREATEDIBSECTION); を使いビットマップハンドルをし取得しました。 ビットマップの貼り付けは出来たのですが、ボタンを押したときにビットマップの画像を変える処理の仕方がわかりません>< loadbitmapsなら容易に出来るのですが、どうしてもloadimageを使って表示したいのですが、どのようにすれば良いでしょうか? 御教授よろしくお願いします><

  • APIのメッセージループの流れとTranslateMessage

    while(GetMessage(&msg, NULL, 0, 0) > 0){ TranslateMessage(&msg); DispatchMessage(&msg); } もしも「a」が押されたときは、 GetMessageで受け取って TranslateMessageでWM_CHARに変換され DispatchMessageでWM_CHARとしてのメッセージが送られる という流れになるはずです。 けど、実際には一度プロシージャにWM_KEYDOWNが送られます。 TranslateMessageが先にメッセージを変換してるので、WM_KEYDOWNが送られることはありえないと思うのですが、なぜでしょうか。 何か重大な思い違いをしているのでしょうか・・?

  • ビットマップ画像表示

    いつもお世話になっております。 VS2005でC++を用いてWindowsアプリケーションの作成をしています。 子ウィンドウにビットマップ画像(ファイル名:HELP.bmp)を 表示させようとプログラムを組んだのですが、 子ウィンドウを出してもビットマップ画像が表示されません。 以下のようなプログラムを追加しました。 --------------------------------- ///リソーススクリプト/////////////////////////////////  IDB_BITMAP1  BITMAP DISCARDABLE  "HELP.bmp" ///ヘッダースクリプト/////////////////////////////////  #define IDB_BITMAP1   3000 ///ソーススクリプト/////////////////////////////////// void ShowMyBMP(HWND hWnd, HDC hdc){   HDC hmdc;   HBITMAP hBitmap;   BITMAP bmp;   HINSTANCE hInst;   int BMP_W, BMP_H;   hInst = (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE);   hBitmap = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP1));  //インスタンスハンドル取得   GetObject(hBitmap, sizeof(BITMAP), &bmp);  //ビットマップの情報を得る   BMP_W = (int)bmp.bmWidth;  //画像の幅   BMP_H = (int)bmp.bmHeight;  //画像の高さ   hmdc = CreateCompatibleDC(hdc);  //メモリデバイスコンテキストハンドルを取得   SelectObject(hmdc, hBitmap);   BitBlt(hdc, 0, 0, BMP_W, BMP_H, hmdc, 0, 0, SRCCOPY);   StretchBlt(hdc, 0, BMP_H, BMP_W / 2, BMP_H / 2, hmdc, 0, 0, BMP_W, BMP_H, SRCCOPY);   DeleteDC(hmdc); //デバイスコンテキストハンドルを開放   DeleteObject(hBitmap);   return; } --------------------------------- ShowMyBMP関数は子ウィンドウを表示するときに実行されます。 全て載せられないので追加した部分のみプログラムを載せましたが、 この部分だけでも、プログラムの間違い等はありませんでしょうか。 ご教授お願いいたします。