質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

8091閲覧

WinAPI子ウィンドウの再描画

Weapon

総合スコア106

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2018/07/20 09:08

編集2018/07/20 10:47

前提・実現したいこと

C++ととWinAPIで親ウィンドウに2分割で子ウィンドウを2つ配置しました。
しかし
(1)実行時は出ていないのですけどマウスでホバーすると最小化最大化終了ボタンが表示され、
(2)サイズの変更後、左の子ウィンドウの文字をクリックするとサイズ変更前の初期サイズの白い線が発生します。
どこか再描画のタイミングがおかしいのでしょうか
また(3)子ウィンドウのプロシージャのつなぎ方は親ウィンドウ同様WNDCLASSを再び使えばいいのでしょうか

発生している問題・エラーメッセージ

Broken Window

該当のソースコード

C++

1#define UNICODE 2#include <windows.h> 3#define ID_CHILD_1 10001 4#define ID_CHILD_2 10002 5 6LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM); 7LRESULT CALLBACK ChildWindowProc1(HWND, UINT, WPARAM, LPARAM); 8LRESULT CALLBACK ChildWindowProc2(HWND, UINT, WPARAM, LPARAM); 9 10HINSTANCE hInst; 11RECT rcWindow; 12const wchar_t CLASS_NAME[] = L"Main Window"; 13 14 15int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR pCmdLine, int nCmdShow) 16{ 17 WNDCLASSEX wcMain = {}; 18 wcMain.cbSize = sizeof(WNDCLASSEX); 19 wcMain.style = CS_HREDRAW | CS_VREDRAW; 20 wcMain.lpfnWndProc = WindowProc; 21 wcMain.cbClsExtra = 0; 22 wcMain.cbWndExtra = 0; 23 wcMain.hInstance = hInstance; 24 wcMain.hIcon = NULL; 25 wcMain.hIconSm = (HCURSOR)LoadImage( 26 NULL, 27 MAKEINTRESOURCE(IDC_ARROW), 28 IMAGE_CURSOR, 29 0, 0, 30 LR_DEFAULTSIZE | LR_SHARED 31 ); 32 wcMain.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); 33 wcMain.lpszMenuName = NULL; 34 wcMain.lpszClassName = CLASS_NAME; 35 wcMain.hIconSm = NULL; 36 37 RegisterClassEx(&wcMain); 38 39 HWND hMothWnd = CreateWindowEx 40 ( 41 0, 42 CLASS_NAME, 43 L"Mother Window", 44 WS_OVERLAPPEDWINDOW | WS_EX_TRANSPARENT, 45 CW_USEDEFAULT, 46 CW_USEDEFAULT, 47 CW_USEDEFAULT, 48 CW_USEDEFAULT, 49 NULL, 50 NULL, 51 hInstance, 52 NULL 53 ); 54 55 if (hMothWnd == NULL)return 0; 56 57 ShowWindow(hMothWnd, nCmdShow); 58 UpdateWindow(hMothWnd); 59 60 MSG msg = {}; 61 while (GetMessage(&msg, NULL, 0, 0)) 62 { 63 TranslateMessage(&msg); 64 DispatchMessage(&msg); 65 } 66 67 68 return 0; 69} 70 71LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 72{ 73 static HWND hChildWnd_L, hChildWnd_R; 74 switch (uMsg) 75 { 76 case WM_DESTROY: 77 PostQuitMessage(0); 78 return 0; 79 80 case WM_SIZE: 81 if (GetClientRect(hwnd, &rcWindow) == false) { 82 MessageBox(hwnd, L"Can't Get the ClientRect", L"Alert", IDOK); 83 break; 84 } 85 86 case WM_CREATE: 87 WNDCLASSEX cwlc; 88 cwlc.cbSize = sizeof(WNDCLASSEX); 89 cwlc.lpfnWndProc = ChildWindowProc1; 90 cwlc.hInstance = hInst; 91 cwlc.lpszClassName = L"Child Window 1"; 92 cwlc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); 93 cwlc.style = CS_HREDRAW | CS_VREDRAW; 94 95 cwlc.lpszMenuName = NULL; 96 RegisterClassEx(&cwlc); 97 98 hChildWnd_L = CreateWindowEx 99 ( 100 0, 101 L"EDIT", 102 L"Child Window 1", 103 WS_CHILD | WS_DLGFRAME | WS_VISIBLE, 104 0, 105 0, 106 (rcWindow.right-rcWindow.left)/2, 107 rcWindow.bottom-rcWindow.top, 108 hwnd, 109 (HMENU)ID_CHILD_1, 110 hInst, 111 NULL 112 ); 113 114 WNDCLASSEX cwlc2; 115 cwlc2.cbSize = sizeof(WNDCLASSEX); 116 cwlc2.lpfnWndProc = ChildWindowProc2; 117 cwlc2.hInstance = hInst; 118 cwlc2.lpszClassName = L"Child Window 2"; 119 cwlc2.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); 120 cwlc2.style = CS_HREDRAW | CS_VREDRAW; 121 122 cwlc2.lpszMenuName = NULL; 123 RegisterClassEx(&cwlc); 124 hChildWnd_R = CreateWindowEx 125 ( 126 0, 127 L"EDIT", 128 L"Child Window 2", 129 WS_CHILD | WS_THICKFRAME | WS_VISIBLE | ES_MULTILINE | 130 ES_WANTRETURN | ES_AUTOHSCROLL | ES_AUTOVSCROLL | WS_OVERLAPPEDWINDOW, 131 (rcWindow.right - rcWindow.left) / 2, 132 rcWindow.top, 133 (rcWindow.right - rcWindow.left) / 2, 134 rcWindow.bottom - rcWindow.top, 135 hwnd, 136 (HMENU)ID_CHILD_2, 137 hInst, 138 NULL 139 ); 140 break; 141 142 } 143 return DefWindowProc(hwnd, uMsg, wParam, lParam); 144} 145 146LRESULT CALLBACK ChildWindowProc1(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {return DefWindowProc(hwnd, uMsg, wParam, lParam);} 147 148LRESULT CALLBACK ChildWindowProc2(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {return DefWindowProc(hwnd, uMsg, wParam, lParam);}

コーディング上のご指摘もありがたいです。

補足情報

Windows10 Pro
VisualStudio2017Community

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

MotherWindowにはWS_CLIPCHILDREN、子ウィンドウにはそれぞれWS_CLIPCHILDREN | WS_CLIPSIBLINGSを付けてください。
そうしないとそれぞれの描画で重なっている別のウィンドウを塗りつぶしてしまいます。

WM_SIZEのFallThroughはダメです。WM_SIZEはサイズ変更の度に何回も発生します。
WM_CREATEの頭で別個にGetClientRectで取得してください。
閉じるボタンなどが表示されるのは手元では出ませんでしたがWM_SIZEが怪しすぎるのでとりあえずそれを直してからかと。

こう言ったウィンドウ構成ならMDIを使ったほうがいいと思います。

--------- 追記 ---------------------------

C

1 case WM_SIZE: 2 { 3 if (GetClientRect(hwnd, &rcWindow) == false) { 4 MessageBox(hwnd, L"Can't Get the ClientRect", L"Alert", IDOK); 5 break; 6 } 7 int w = rcWindow.right - rcWindow.left; 8 int h = rcWindow.bottom - rcWindow.top; 9 MoveWindow(hChildWnd_L, 0, 0, w/2, h, TRUE); 10 MoveWindow(hChildWnd_R, w/2, 0, w/2, h, TRUE); 11 break; 12 }

投稿2018/07/20 16:19

編集2018/07/21 05:27
toki_td

総合スコア2850

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Weapon

2018/07/21 03:56

WM_SIZEは消してWM_CREATEにGetClientRectは配置しました。 子ウィンドウのみでの子ウィンドウの移動やリサイズは想定していません(左右のウィンドウの枠が違うのはWindowstyleの比較用です)。親ウィンドウがリサイズされたとき子ウィンドウがそれぞれ左右中央2分割するようにしたいのです。親のWM_CREATEはCreateWindowが呼ばれたときのみ実行されるため親ウィンドウのリサイズ時に子ウィンドウの再描画が必要であると考えているのですがWM_SIZEでのなんらかの記述は不要でしょうか? 答えていただいた"WM_CREATEの頭で別個にGetClientRect"とは子ウィンドウのWM_CREATEのことでしょうか? MDIについては基本的なウィンドウ管理を覚えたら挑戦させていただきます。ありがとうございます。
toki_td

2018/07/21 05:32

あぁ、そういうことですか。ではMDIは気にしないでください。 単純に親のWM_SIZEで子を移動させればいいです。 コード追記したので確認してください。 MoveWindowの最後の引数がTRUEなら子は再描画されます(SetWindowPosでもいいです) WM_CREATEの直後にWM_SIZEも必ず発生するのでWM_CREATEでは子の位置は計算せずに 0, 0, 0, 0とかにしておいてもいいですよ。
guest

0

ChildWindowProc1(), ChildWindowProc2() の内容を
return DefWindowProc(hwnd, uMsg, wParam, lParam);
にしたら表示が改善されませんか?

投稿2018/07/20 10:39

fana

総合スコア11656

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Weapon

2018/07/20 10:46

省略してはいけないものまで省略で消してしまっていました。 実際のコードは書かれています。 修正しておきますね。ありがとうございます
fana

2018/07/20 11:01 編集

WM_SIZEからfall throughしてそのままWM_CREATE時のコードに行ってしまうのがまずいのでは. 一度,WM_SIZE:の内容を,WM_CREATE:の次に配置し,WM_SIZE:の部分をコメントアウトしてみたらどうでしょうか. (「case WM_CREATE:」の行をコメントアウトして,「case WM_SIZE:」を「case WM_CREATE:」に書き換えた感じに)
Weapon

2018/07/20 12:00

それをするとリサイズ時のメッセージが飛ばなくなるのでそのWM_CREATEをWM_PAINTにすればウィンドウの再描画はされます。しかしメッセージがWM_CREATEではなくWM_PAINTで描画していいのかということに違和感を感じているので効果的な解決法を求めています そして書き換えても最初の質問の(2)の白い線が残るんですがこれは子ウィンドウの再描画ですかね
fana

2018/07/20 13:31

(1)何が問題を引き起こしているのか? を明らかにすべきと思い,最初の回答を行った.一時的にでも試しに子ウィンドウのウィンドウプロシージャをデフォルト動作だけに差し替えたら現象が変化(改善)することは無いのか?という. それで問題の現象に変化があるなら,子ウィンドウのプロシージャの実装に問題がある可能性がある(→提示されているコードだけでは解決できない) (2)次に,それとは別に,提示されているメインウィンドウのプロシージャにも問題がありそうなのでコメントで追加指摘した.WM_SIZEメッセージ毎にウィンドウ生成処理が走るのは明らかにバグと思われ,それがどんな悪影響を与えるかわからないから,一旦その問題が起こらない状態の動作を確認したい(してほしい) 上記2点を修正した状態では,少なくともこちらの環境では,提示スクリーンショットのようなおかしな描画は成されない.(そりゃ確かにこの状態はあなたの意図した動作をするコードではないですが,仮に問題現象が起きなくなるなら,そこから必要な処理を再び足していけばよいのではないかと.)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問