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

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

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

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

Visual C++

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

ウィンドウ

コンピューター用語において、ウィンドウとはユーザとプログラムのやり取りを可能にするGUIの枠組みのことをいいます。

タブ

コンテンツの上下左右に参照用のメニューを設けることで、複数の要素やページの表示を可能にするユーザーインターフェイスパターンのこと。メニューをクリックすると、一つの要素が可視化され、他の要素は見えなくなる。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

Q&A

解決済

1回答

2080閲覧

WinAPIのウィンドウ親子関係を利用した描画

Maitz.

総合スコア12

Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

Visual C++

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

ウィンドウ

コンピューター用語において、ウィンドウとはユーザとプログラムのやり取りを可能にするGUIの枠組みのことをいいます。

タブ

コンテンツの上下左右に参照用のメニューを設けることで、複数の要素やページの表示を可能にするユーザーインターフェイスパターンのこと。メニューをクリックすると、一つの要素が可視化され、他の要素は見えなくなる。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

0グッド

0クリップ

投稿2021/03/05 15:25

前提・実現したいこと

windows の api を利用して、guiのアプリケーションを作成しています。
タブコントロールの利用について、ウィンドウの親子関係を利用して描画内容を変えようとしました。

┣メイン┳タブコントロール
┃   ┣その他
┃   ┣親1┳子1
┃   ┃  ┗子2
┃   ┗親2┳子3
┃      ┗子4

上記のような関係のウィンドウを作成しておき、
TCN_SELCHANGEメッセージに対応して、InvalidateRectShowWindowを親ウィンドウに送ることで、子ウィンドウの描画・非描画ををまとめて管理しようとしました。

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

想定した内容が描画できていません。コンパイル警告はなし。
親ウィンドウは描画を割り当てていないため確認できず。
描画したい子ウィンドウの内容が確認できないです。

該当のソースコード

c++

1#include <windows.h> 2#include <commctrl.h> 3#include "resource.h" 4 5#define X_MIN 240 6#define Y_MIN 177 7 8#pragma comment(lib, "comctl32.lib") // ステータスバーの作成に必要 9 10// グローバル変数: 11HINSTANCE hInst; // 現在のインターフェイス 12HWND hTab; // タブコントロールのハンドル 13HWND hTabgroup1, hTabgroup2; // タブの描画グループのハンドル 14WNDPROC OrgStaticProc; // スタティックコントロールのプロシージャ 15HWND hStatus; // ステータスバーのウィンドウハンドル 16HWND hButton1, hButton2; // ボタンのハンドル 17HWND hButtonchat; // チャット送信用ボタン 18 19// このコード モジュールに含まれる関数の宣言を転送します: 20ATOM MyRegisterClass(HINSTANCE hInstance); 21BOOL InitInstance(HINSTANCE, int); 22LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 23LRESULT CALLBACK MyStaticProc(HWND, UINT, WPARAM, LPARAM); 24 25//---------- 26 27int APIENTRY WinMain(HINSTANCE hInstance, 28 HINSTANCE hPrevInstance, 29 LPSTR lpCmdLine, 30 int nCmdShow) 31{ 32 MSG msg; 33 MyRegisterClass(hInstance); 34 35 // アプリケーションの初期化を実行します: 36 if (!InitInstance(hInstance, nCmdShow)) 37 { 38 return FALSE; 39 } 40 // メイン メッセージ ループ: 41 while (GetMessage(&msg, NULL, 0, 0)) 42 { 43 TranslateMessage(&msg); 44 DispatchMessage(&msg); 45 } 46 return (int)msg.wParam; 47} 48 49// 50// 関数: MyRegisterClass() 51// 52// 目的: ウィンドウ クラスを登録します。 53// 54ATOM MyRegisterClass(HINSTANCE hInstance) 55{ 56 WNDCLASSEX wcex; 57 58 wcex.cbSize = sizeof(WNDCLASSEX); 59 60 wcex.style = CS_HREDRAW | CS_VREDRAW; 61 wcex.lpfnWndProc = WndProc; 62 wcex.cbClsExtra = 0; 63 wcex.cbWndExtra = 0; 64 wcex.hInstance = hInstance; 65 wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION); 66 wcex.hCursor = LoadCursor(NULL, IDC_ARROW); 67 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); 68 wcex.lpszMenuName = MAKEINTRESOURCE(IDC_HP); 69 wcex.lpszClassName = TEXT("HP"); 70 wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION); 71 72 return RegisterClassEx(&wcex); 73} 74 75// 76// 関数: InitInstance(HINSTANCE, int) 77// 78// 目的: メイン ウィンドウを作成します。 79// 80BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) 81{* …… *\} 82 83// 84// 関数: WndProc(HWND, UINT, WPARAM, LPARAM) 85// 86// 目的: メイン ウィンドウのメッセージを処理します。 87// 88// WM_CREATE - ウインドウ作成時の処理 89// WM_SIZE - ウインドウサイズ変更時の処理 90// WM_GETMINMAXINFO - ウインドウサイズ・位置変更時の処理 91// WM_COMMAND - アプリケーション メニューの処理 92// WM_DESTROY - 中止メッセージを表示して戻る 93// 94// 95LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 96{ 97 int wmId, wmEvent; 98 int nTab; 99 static RECT rc; 100 TCITEM ti; 101 INITCOMMONCONTROLSEX ic; 102 LPMINMAXINFO lpmm; 103 static HWND hStatic, hEdit; 104 static TCHAR szStr[3][512]; 105 106 switch (message) 107 { 108 case WM_CREATE: 109 ic.dwSize = sizeof(INITCOMMONCONTROLSEX); 110 ic.dwICC = ICC_TAB_CLASSES; 111 InitCommonControlsEx(&ic); 112 GetClientRect(hWnd, &rc); 113 hTab = CreateWindowEx(0, WC_TABCONTROL, 114 TEXT(""), WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE, 0, 0, rc.right, rc.bottom, 115 hWnd, (HMENU)ID_TAB, hInst, NULL); 116 hStatic = CreateWindowEx(0, TEXT("Static"), 117 TEXT(""), WS_CHILD | WS_VISIBLE, 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 118 hWnd, (HMENU)ID_STATIC, hInst, NULL); 119 hEdit = CreateWindowEx(0, TEXT("Edit"), 120 TEXT(""), WS_CHILD | WS_VISIBLE | WS_BORDER | ES_MULTILINE, 20, 40, 150, 50, 121 hStatic, (HMENU)ID_EDIT, hInst, NULL); 122 SendMessage(hTab, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), 0); 123 ti.mask = TCIF_TEXT; 124 ti.pszText = (WCHAR*)(L"接続系"); 125 TabCtrl_InsertItem(hTab, 0, &ti); 126 ti.pszText = (WCHAR*)(L"ゲーム設定"); 127 TabCtrl_InsertItem(hTab, 1, &ti); 128 //スタティックコントロールのサブクラス化 129 OrgStaticProc = (WNDPROC)GetWindowLong(hStatic, GWL_WNDPROC); 130 SetWindowLong(hStatic, GWL_WNDPROC, (LONG)MyStaticProc); 131 //---------- 132 hStatus = CreateWindowEx(//ステータスバーの作成 133 0, STATUSCLASSNAME, NULL, WS_CHILD | SBARS_SIZEGRIP | CCS_BOTTOM | WS_VISIBLE, 134 0, 0, 0, 0, hWnd, (HMENU)ID_STATUS, hInst, NULL); 135 // シンプルモードを指定 136 SendMessage(hStatus, SB_SIMPLE, TRUE, 0); 137 // ステータスバーに文字を挿入 138 SendMessage(hStatus, SB_SETTEXT, SB_SIMPLEID | 0, (WPARAM)TEXT("ステータスバー")); 139 //---------- 140 hTabgroup1 = CreateWindowEx(0, 0, 141 TEXT("タブグループ1"), WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN, 142 10, 10, 1440, 810, hWnd, (HMENU)ID_Tabgroup1, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL); 143 hTabgroup2 = CreateWindowEx(0, 0, 144 TEXT("タブグループ2"), WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN, 145 10, 10, 1440, 810, hWnd, (HMENU)ID_Tabgroup2, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL); 146 //---------- 147 hButton1 = CreateWindowEx(0, TEXT("BUTTON"), 148 TEXT("Button1"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 149 10, 150, 80, 30, hWnd, (HMENU)ID_BUTTON1, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL); 150 hButton2 = CreateWindowEx(0, TEXT("BUTTON"), 151 TEXT("Button2"), WS_CHILD | WS_VISIBLE | BS_CHECKBOX, 152 150, 210, 100, 50, hTabgroup2, (HMENU)ID_BUTTON2, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL); 153 154 //---------- 155 break; 156 157 case WM_SIZE: 158 GetClientRect(hWnd, &rc); 159 TabCtrl_AdjustRect(hTab, FALSE, &rc); 160 MoveWindow(hTab, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE); 161 MoveWindow(hStatic, 162 rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE); 163 SendMessage(hStatus, WM_SIZE, wParam, lParam); //ステータスバーサンプル由来 164 break; 165 case WM_NOTIFY: 166 switch (((NMHDR*)lParam)->code) 167 { 168 case TCN_SELCHANGE: 169 InvalidateRect(hTab, NULL, TRUE); 170 InvalidateRect(hStatic, NULL, TRUE); 171 nTab = TabCtrl_GetCurSel(hTab); 172 SetWindowText(hEdit, szStr[nTab]); 173 //---------- 174 switch (nTab) 175 { 176 case 0: 177 UpdateWindow(hEdit); 178 SendMessage(hStatus, SB_SETTEXT, SB_SIMPLEID | 0, (WPARAM)TEXT("タブを0に変更")); 179 InvalidateRect(hStatus, NULL, FALSE); 180 InvalidateRect(hButton1, NULL, FALSE); 181 ShowWindow(hTabgroup1, SW_SHOW); 182 ShowWindow(hTabgroup2, SW_HIDE); 183 InvalidateRect(hTabgroup1, NULL, FALSE); 184 break; 185 case 1: 186 InvalidateRect(hEdit, NULL, TRUE); 187 SendMessage(hStatus, SB_SETTEXT, SB_SIMPLEID | 0, (WPARAM)TEXT("タブを1に変更")); 188 InvalidateRect(hStatus, NULL, FALSE); 189 ShowWindow(hTabgroup1, SW_HIDE); 190 ShowWindow(hTabgroup2, SW_SHOW); 191 InvalidateRect(hTabgroup2, NULL, FALSE); 192 InvalidateRect(hButton2, NULL, FALSE); 193 break; 194 default: 195 break; 196 } 197 break; 198 case TCN_SELCHANGING: 199 nTab = TabCtrl_GetCurSel(hTab); 200 GetWindowText(hEdit, szStr[nTab], sizeof(szStr[nTab])); 201 break; 202 } 203 break; 204 case WM_GETMINMAXINFO: 205 lpmm = (LPMINMAXINFO)lParam; 206 lpmm->ptMinTrackSize.x = X_MIN; 207 lpmm->ptMinTrackSize.y = Y_MIN; 208 break; 209 case WM_COMMAND: 210 wmId = LOWORD(wParam); 211 wmEvent = HIWORD(wParam); 212 // 選択されたメニューの解析: 213 switch (wmId) 214 { 215 //---------- 216 case ID_BUTTON1: 217 SendMessage(hStatus, SB_SETTEXT, SB_SIMPLEID | 0, (WPARAM)TEXT("ボタン1が押されました。")); 218 InvalidateRect(hStatus, NULL, FALSE); 219 220 break; 221 //---------- 222 case ID_BUTTON2: 223 SendMessage(hStatus, SB_SETTEXT, SB_SIMPLEID | 0, (WPARAM)TEXT("ボタン2が押されました。")); 224 InvalidateRect(hStatus, NULL, FALSE); 225 SendMessage(hButton2, BM_SETCHECK, 226 !SendMessage(hButton2, BM_GETCHECK, 0, 0), 0); 227 break; 228 //---------- 229 case IDM_EXIT: 230 DestroyWindow(hWnd); 231 break; 232 default: 233 return DefWindowProc(hWnd, message, wParam, lParam); 234 } 235 break; 236 case WM_DESTROY: 237 PostQuitMessage(0); 238 break; 239 default: 240 return DefWindowProc(hWnd, message, wParam, lParam); 241 } 242 return 0; 243} 244 245 246//サブクラス化されたスタティックコントロールのプロシージャ 247LRESULT CALLBACK MyStaticProc(HWND hStatic, UINT message, WPARAM wParam, LPARAM lParam) 248{* …… *\}

試したこと

言い訳ですが、なんか色々試してたらこうなりました。

補足情報(FW/ツールのバージョンなど)

以下のページを下地にしました。
http://gurigumi.s349.xrea.com/programming/visualcpp/sdk_treeview1.html

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

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

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

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

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

guest

回答1

0

自己解決

子ウィンドウのウィンドウプロシージャを作成して、孫ウィンドウの動作を移植することで解決しました。

投稿2021/03/19 05:57

Maitz.

総合スコア12

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問