ウィンドウズプログラミング講座第5回:ツールバーとステータスバーと子ウィンドウ
概要
今回はツールバーとステータスバーと子ウィンドウを一気に追加します。
これでかなりアプリらしくなります。
まだまだ序盤なのでテヘペロっと行きます。
ソースファイル
ツールバー
初期化
class App : public Window { enum { TB_FILE_NEW, TB_FILE_OPEN, TB_FILE_SAVE, TB_HELP, MAX_TB_BUTTON }; HWND hToolBar; }; BOOL App :: Init( int nCmdShow ) { DWORD dwStyle; BOOL result; const TBBUTTON buttons[] = { { STD_FILENEW, ID_FILE_NEW, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 }, { STD_FILEOPEN, ID_FILE_OPEN, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 }, { STD_FILESAVE, ID_FILE_SAVE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 }, { 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0 }, { STD_HELP, ID_APP_ABOUT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0 }, }; dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | TBSTYLE_TOOLTIPS; hToolBar = CreateToolbarEx( hWnd, dwStyle, ID_TOOLBAR, MAX_TB_BUTTON, HINST_COMMCTRL, IDB_STD_SMALL_COLOR, buttons, sizeof buttons / sizeof ( TBBUTTON ), 0, 0, 15, 16, sizeof ( TBBUTTON ) ); dwStyle = GetWindowLong( hToolBar, GWL_STYLE ) | TBSTYLE_FLAT; result = SetWindowLong( hToolBar, GWL_STYLE, dwStyle ); }
解説
気になる点としては、ウィンドウスタイルとして作成時に TBSTYLE_FLAT を設定すると何故かうまく行かないこと。
作成後に SetWindowLong() で設定するとうまく行くのに。まあ気にしないでおこう。
処理
LRESULT App :: OnWmSize() { SendMessage( hToolBar, WM_SIZE, wparam, lparam ); return 0; } LRESULT App :: OnTtnGetDispInfo() { switch ( id ) { case ID_FILE_NEW : lpnmtdi->lpszText = _T( "新規作成" ); break; case ID_FILE_OPEN : lpnmtdi->lpszText = _T( "開く…" ); break; case ID_FILE_SAVE : lpnmtdi->lpszText = _T( "保存…" ); break; case ID_APP_ABOUT : lpnmtdi->lpszText = _T( "アバウト…" ); break; } return 0; }
ステータスバー
初期化
class App : public Window { HWND hStatBar; }; BOOL App :: Init( int nCmdShow ) { DWORD dwStyle; BOOL result; dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_BOTTOM; hStatBar = CreateStatusWindow( dwStyle, NULL, hWnd, ID_STATBAR ); result = SetWindowText( hStatBar, appName ); }
解説
ステータスバーはツールバーと違ってほとんど何もすることが無い。
処理
LRESULT App :: OnWmSize() { SendMessage( hStatBar, WM_SIZE, wparam, lparam ); }
解説
ツールバーと同じく親のサイズ変更に対応するだけ。
子ウィンドウ
ツールバーとステータスバーを追加すると、メインウィンドウの使えるクライアントエリアが狭くなるので、そこを子ウィンドウにしてしまおう。
そうすれば子ウィンドウは自分のクライアントエリアを全部使えるので分かりやすい。
初期化
class Child : public Window { public : static const LPCTSTR className; BOOL Init( Window * parent ); LRESULT OnWmPaint(); }; const LPCTSTR Child :: className = "ClassChild"; BOOL Child :: Init( Window * parent ) { WNDCLASSEX wcx; DWORD dwStyle; HWND hWnd; wcx.cbSize = sizeof ( WNDCLASSEX ); wcx.style = CS_HREDRAW | CS_VREDRAW; wcx.lpfnWndProc = WindowProc; wcx.cbClsExtra = 0; wcx.cbWndExtra = sizeof ( HANDLE ); wcx.hInstance = GetModuleHandle( NULL ); wcx.hIcon = NULL; wcx.hCursor = LoadCursor( NULL, IDC_ARROW ); wcx.hbrBackground = ( HBRUSH ) ( COLOR_WINDOW + 1 ); wcx.lpszMenuName = NULL; wcx.lpszClassName = className; wcx.hIconSm = NULL; RegisterClassEx( & wcx ); dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; hWnd = CreateWindowEx( WS_EX_CLIENTEDGE, className, NULL, dwStyle, 0, 0, 0, 0, parent->hwnd, NULL, GetModuleHandle( NULL ), this ); return TRUE; }
解説
初期化は親ウィンドウとほとんど一緒。
処理
LRESULT App :: OnWmSize() { RECT rc; RECT rc2; RECT rc3; GetClientRect( hwnd, & rc ); GetWindowRect( hToolBar, & rc2 ); GetWindowRect( hStatBar, & rc3 ); rc.top = ( rc2.bottom - rc2.top ); rc.bottom -= ( rc3.bottom - rc3.top ); MoveWindow( child.hwnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE ); return 0; } LRESULT Child :: OnWmPaint() { PAINTSTRUCT ps; HDC hdc = BeginPaint( hwnd, & ps ); LPCTSTR text = _T( "子ウィンドウ" ); TextOut( hdc, 0, 0, text, ( int ) strlen( text ) ); EndPaint( hwnd, & ps ); return 0; }
解説
子ウィンドウのサイズ変更は後々のことを考えて親ウィンドウ側で行います。
ツールバーとステータスバーのサイズ分を引いてフィットします。
あとなんとなくペイントメッセージにも対応しときました。
その他
ウィンドウクラスをかなり修正しましたけど詳しくはソースを見てね。
では、サイナラ。