いつもお世話になっております。
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関数は子ウィンドウを表示するときに実行されます。
全て載せられないので追加した部分のみプログラムを載せましたが、
この部分だけでも、プログラムの間違い等はありませんでしょうか。
ご教授お願いいたします。
No.7ベストアンサー
- 回答日時:
>実はさらにグローバルにhWndが宣言されてて
本当はその可能性も考えなくもありませんでしたが、まさかそんな事はしないだろう、あり得ないだろうと、否定していました。
あり得るとして、その考えを推し進めると。
コンパイルエラーが起こる→hWndが宣言されていませんと出る。
それならば、hWndをグローバルで宣言してしまえと HWND hWnd;を記述
コンパイルエラーはなくなる。
※hChdWnd等はコピらず、コンパイルエラーが出なくなった事で満足していると仮定
で以下の個所では hWndに対して描画、初期化されていないウィンドウハンドルなので、実際にはどこに描画されているのかは不明。
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
ShowMyBMP(hWnd, hdc);
break;
そもそも有効なウィンドウハンドルではないため、エラーを返している可能性もあるのだが、エラー判定もしていないためそのことに気付いていない?
あるいは、以下のように=0として宣言しているため、デスクトップのウィンドウハンドルとして有効な値となっている。
HWND hWnd=0;
※VC++って、初期化されていない変数を参照しましたとかのWarningって出ましたっけ?出るなら適当な値で初期化するってあり得るかなと。
しかし、EndPaint(hWnd , &ps)を呼び出していないため、描画が更新されずにデスクトップ(あるいは偶然ウィンドウハンドルが一致したどこか別の場所)に描画されている事に気付いていない?
LongSecretさんの指摘や、aaaaaさんの答え見て、質問者様の力量を推測してみると、『あり得るぞ、大いにあり得るぞ』と思えてきたんですが。
まさかこんなことしてませんよね?と確認の意味で。
LongSecretさんのお礼欄にも書かせて頂いたとおり、
BellBellさんが指摘してくださった部分のミスでした。
まさかのまさかでした。ご指摘ありがとうございます。
・・・と共に、確認をするべきでした。ごめんなさい。
でも今回のことで、とても勉強になりました。
BellBellさんわかりやすいご回答、本当にありがとうございました。
No.6
- 回答日時:
苦戦してそうですね~。
> WS_CHILD | WS_SYSMENU | WS_THICKFRAME | WS_CAPTION
普通、子ウィンドウを作成する時はスタイルにこんなに必要無いですよ。
WS_CHILD と WS_VISIBLE くらいなものです。
ところでデバッガを使えるようになるといろいろな問題を解決できるようになりますよ。
まずは、OutputDebugString("bbb\n");
とかで、デバッグウィンドウに何か出力できるようになるべきですね。
私の初歩的なミスによったものでした。
これからもっと勉強・確認をします。
また、子ウィンドウスタイルについてご指摘ありがとうございました。
訂正しておきます。
そして、デバッガを使いなれるようにしたいと思います。
ご教授ありがとうございました。
No.5
- 回答日時:
あ、ほんとだw
どうせそうだろうと思ってそこは見てなかったですが
となると、正確には
case WM_PAINT:
hdc = BeginPaint(hChdWnd, &ps);
ShowMyBMP(hChdWnd, hdc);
EndPaint(hChdWnd , &ps);
break;
が推奨、となりますかw
BellBellさんナイス指摘ですw
…とみせかけて、実はさらにグローバルにhWndが宣言されてて、そこにhChdWnd をコピってるので実はコンパイルエラーになってないとか?(笑)
書き忘れましたが
>右クリック・左クリックをすると子ウィンドウは閉じます
ということはプロシージャはちゃんと呼び出されています。
また、WM_PAINTは、ウインドウが表示されている時点で、呼び出されているはずです。
現状だと、他のウインドウに隠れて再度表示されるときとか、サイズ変更するときとかも何度も呼び出されてるはずです。
こんばんは。
わかりやすいご説明、本当に感謝いたします。
>case WM_PAINT:
>hdc = BeginPaint(hChdWnd, &ps);
>ShowMyBMP(hChdWnd, hdc);
>EndPaint(hChdWnd , &ps);
>break;
はい、まさにここでした。
hChdWndと書き換えてEndPaintを追加することで画像の表示が可能となりました。
ん~
こんな初歩的なところでミスをしてしまうとは・・・
まだまだ自分は勉強・確認不足です。情けない。
しかし今回はLongSecretさんをはじめ皆さんのおかげで勉強になしました。
もっともっとプログラミングの勉強頑張ります!
本当にありがとうございました。
No.4
- 回答日時:
ちょっと気になっただけなんだけど、
#1の方のお礼欄に書かれたソースコードの以下の部分。
~~~~~~~~
//ビットマップ画像表示
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);←ココ
ShowMyBMP(hWnd, hdc);←ココも
break;
~~~~~~~~
hWndってなってるのは、本当のソースではhChdWndとなってるのを写し間違えただけですよね?
普通ならコンパイルエラーになるわけだし。
No.2
- 回答日時:
私の環境でもリソースを使うと出来るときと出来ないときがあり、それがなぜなのかよく分かりませんが、とりあえずそれとは関係なしに
hdc = BeginPaint(hWnd, &ps);
ではじめたら
EndPaint(hw , &ps);
で終了しておくほうが無難(おそらくそれが基本)と思います。
そしてもし「リソースが」うまく働かないならば、実行ファイルに埋め込むのをやめてLoadImage等でファイルからの読み込みを試してみてください。(それでもできなければ、提示していただいたコードの範囲内だとちょっとわかりません。)
概要としては、一例としてこんな感じになります。
HBITMAP hBitmap = (HBITMAP)LoadImage(0, "ファイルのパス",IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
HDC 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);
こういうイメージになります☆
これでできましたら
ここから先はパフォーマンスを追求する場合の余談(?)です
//////////////
現在「埋め込むという前提」なことから考えると、ファイルを動的に変更しない、ということになりますから、この場合は毎回サイズを求めずに
static const int BMP_W = 幅, BMP_H = 高さ;
とか、あるいはもっとシンプルに#defineなどで先に決め打ちしてしまって良いと思います。
(いずれも、毎回算出されないことが保証されます)
また、現在の状態だと毎回ロードされて…という具合になってしまいまが、WM_PAINT内では基本的にはBitBltのみだとかなりサクサクです。
(DDBのBitBltのみだと激速です
※ http://lamoo.s53.xrea.com/develop/gdiplus/gdiplu … など)
その場合、CreateCompatibleDCで作るHDC hmdc;
はローカルではなく別に長い寿命(staticなど)を持つように保持させておき、たとえばアプリケーション起動時に生成、その時一回だけビットマップをロードする、そして終了時にDeleteDC(hmdc);
などといった具合にすれば、実現可能です。
後から描画内容を変更する場合でも、そちらのHDCに対して書き換えし、あくまでWM_PAINT内ではそこからBitBltするようにしておけば、最小限の負荷でOKと思われます。(マルチバッファリング)
また、真っ白ということは、ウィンドウクラス登録時にhbrBackgroundに何かを指定していると思いますが、もし画面全部を自分で描画する場合は、そこにNULLを指定しておくとなおGOODと思います。
(どの道上書きされる部分に対して何も処理しないことが保証されるはず)
No.1
- 回答日時:
ぱっと見たところ、間違ってなさそうに見えます。
引数は有効ですか?
その子ウィンドウがまだ作成されてない段階で呼んでませんか?
その子ウィンドウがまだ表示されていない段階で呼んでませんか?
ShowMyBMPが初期化ルーチンで呼ばれるようならば怪しいです。
この回答への補足
---------------------------------------
InitApp(g_hInst, ChildProc, "child");
hChdWnd = CreateWindow("child",
"子供ウィンドウ",
WS_CHILD | WS_SYSMENU | WS_THICKFRAME | WS_CAPTION,
(rec.right - 650) / 2, //X座標
(rec.bottom - 450) / 2, //Y座標
650, //幅
450, //高さ
hWnd, //親ウィンドウのハンドル
NULL, //メニューハンドル、子供のID
g_hInst, //インスタンスハンドル
NULL);
ShowWindow(hChdWnd, SW_SHOW);
UpdateWindow(hChdWnd);
---------------------------------------
早速プログラムを見ていただきありがとうございます。
文字制限のため、aaaaaさんの補足部分にもまたがって関数を載せます。
ごめんなさい。
ShowMyBMPは子ウィンドウプロシージャ内で使用しています。
以下にプログラムを載せます。
---------------------------------------
LRESULT CALLBACK ChildProc(HWND hChdWnd, UINT msg, WPARAM wp, LPARAM lp){
HDC hdc;
PAINTSTRUCT ps;
switch (msg) {
//ビットマップ画像表示
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
ShowMyBMP(hWnd, hdc);
break;
//以下の操作が行われたらウィンドウを閉じる
case WM_LBUTTONDOWN://左クリック
case WM_RBUTTONDOWN://右クリック
case WM_KEYDOWN://キーボードのキー押す
DestroyWindow(hChdWnd);
break;
default:
return (DefWindowProc(hChdWnd, msg, wp, lp));
}
return 0L;
}
---------------------------------------
また、子ウィンドウを表示する際のメインウィンドウプロシージャ内の
プログラムをaaaaaさんの補足部分に載せます。
InitApp関数では、ウィンドウクラス登録を行っています。
第1引数にインスタンス、第2引数にプロシージャ名、第3引数にクラス名です。
CreateWindowで作成したウィンドウは表示されるのですが真っ白なんです。
とても初歩的な質問かもしれないのですが、
この場合、ChildProcはいつ呼び出される?のでしょうか。
右クリック・左クリックをすると子ウィンドウは閉じますが、
見てみるとWM_PAINTが呼び出されてないような・・・?
勉強不足でごめんなさい。
ご教授お願いします。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) 【VBA】写真の貼り付けコードがうまく機能しません。 5 2022/09/01 18:43
- その他(プログラミング・Web制作) uwscのCHKING関数の画像の認識がうまくいかない。 1 2022/06/18 20:55
- その他(プログラミング・Web制作) uwscとWinShotを使いスクリーンショットを撮る 1 2022/06/30 21:15
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
- 英語 Thus, PTH may be used to promote bone regeneration 1 2022/07/26 08:15
- C言語・C++・C# C言語の質問です。バイナリ形式で保存されたWindows Bitmap形式の画像ファイルを読み込み、 3 2023/07/19 14:58
- Visual Basic(VBA) Vba LongPtrについて教えてください 2 2022/08/19 11:14
- C言語・C++・C# C言語 プログラミング 4 2022/05/22 11:53
- Windows 10 2つのウィンドウ選択時の表示について 10 2023/07/25 08:48
- C言語・C++・C# C言語 3 2022/11/09 13:27
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
エクセルで作った新しいウイン...
-
「アイテムは収集されました」...
-
検索の画面がでなくなってしま...
-
勝手にウィンドウが開いて止ま...
-
ゲームでは結局どっちが良いの?
-
EnumChildWindowsの使い方(VBA)
-
親ウインドウにあるOKボタンを...
-
C言語でWin32APIを使い、子ウィ...
-
Msgboxの変数の表示につ...
-
「&HFFFF」「&H1A」とは?
-
クリスタルレポートからPDFを作...
-
[VBA] UserForm を Excel の W...
-
他のアプリケーションの終了処理
-
エクセルで複数のウィンドウ枠...
-
VBで作成したフォーム上に電卓...
-
Excelの上下を固定したい
-
Console.WriteLine で表示されない
-
java sevlet でウィンドウ表示
-
ウィンドウのサイズ変更について
-
ExcelのBOOKが消えた!
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
エクセルで作った新しいウイン...
-
「アイテムは収集されました」...
-
勝手にウィンドウが開いて止ま...
-
検索の画面がでなくなってしま...
-
ゲームでは結局どっちが良いの?
-
VBA .Value=.Value ?
-
Excelの上下を固定したい
-
[VBA] UserForm を Excel の W...
-
EnumChildWindowsの使い方(VBA)
-
Vba LongPtrについて教えてくだ...
-
ExcelのBOOKが消えた!
-
他のアプリケーションの終了処理
-
ラジオボタンの初期指定
-
ExcelVBAでAPIを使って外部ウイ...
-
作成したウインドウのサイズを...
-
UWSCで特定のChromeのタブをア...
-
隠れたウィンドウの画面をキャ...
-
「&HFFFF」「&H1A」とは?
-
名前を付けて保存のウィンドウ...
-
最大化と最小化ボタン
おすすめ情報