<Previous> <Next> <SDK Top> <Top>
3章.2節.ツールバーにいくつかボタンを配置してみよう
今回はツールバーにボタンを3つ設けて,3つ目のボタンは少し間隔をとり配置してみましょう.
また,押されたボタンをテキストで表示するようにしましょう!
前回同様,ツールバーの3つのボタンのIDを決めてやりましょう.
IDの作り方を知らない方は,「別章.2節.ストリングテーブルを編集してみよう」を先に読んでください.
ID | キャプション |
IDC_BUTTON1 | ボタン1 |
IDC_BUTTON2 | ボタン2 |
IDC_BUTTON3 | ボタン3 |
としましょうか.
今回のポイントは,
@どうやってツールバーにボタンを複数個挿入し,間隔を開けて配置するか?
Aどうやって押されたボタン名をどうやってテキストにする?
というところですね.
では,プログラムを見ましょう.
#include "stdafx.h" #include <commctrl.h> #include "resource.h" #pragma comment(lib, "comctl32.lib") #define MAX_LOADSTRING 100 #define IDC_RICHEDIT (101) #define TOOL_HEIGHT (40) // グローバル変数: HINSTANCE hInst; // 現在のインスタンス TCHAR szTitle[MAX_LOADSTRING]; // タイトル バー テキスト TCHAR szWindowClass[MAX_LOADSTRING]; // タイトル バー テキスト // このコード モジュールに含まれる関数の前宣言: ATOM MyRegisterClass( HINSTANCE hInstance ); BOOL InitInstance( HINSTANCE, int ); LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ); HWND ToolBarCreate(HWND hWnd); void ToolBarAddButtons(int nBotton, TBBUTTON* tbb); void ToolBarAddButtonSpace(void); void DispText(HWND hWnd, char* pszBuf); HWND hToolBar; TBBUTTON tbb1[2] = { {0, IDC_BUTTON1, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0}, {1, IDC_BUTTON2, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0}, }; TBBUTTON tbb2[1] = { {2, IDC_BUTTON3, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0} }; int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { MSG msg; HACCEL hAccelTable; // グローバル ストリングを初期化します LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_SAMPLE, szWindowClass, MAX_LOADSTRING); MyRegisterClass( hInstance ); // アプリケーションの初期化を行います: if( !InitInstance( hInstance, nCmdShow ) ) { return FALSE; } hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_SAMPLE); // メイン メッセージ ループ: while( GetMessage(&msg, NULL, 0, 0) ) { if( !TranslateAccelerator (msg.hwnd, hAccelTable, &msg) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } } return msg.wParam; } ATOM MyRegisterClass( HINSTANCE hInstance ) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_SAMPLE); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = (LPCSTR)IDC_SAMPLE; wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL); return RegisterClassEx( &wcex ); } BOOL InitInstance( HINSTANCE hInstance, int nCmdShow ) { HWND hWnd; hInst = hInstance; // グローバル変数にインスタンス ハンドルを保存します hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if( !hWnd ) { return FALSE; } ShowWindow( hWnd, nCmdShow ); UpdateWindow( hWnd ); return TRUE; } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; static char szBuf[256]=""; switch( message ) { case WM_CREATE: // ツールバーを作る hToolBar = ToolBarCreate( hWnd ); // ツールバーにボタンを追加する ToolBarAddButtons( 2, tbb1 ); ToolBarAddButtonSpace( ); ToolBarAddButtons( 1, tbb2 ); break; case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); switch( wmId ) { case IDC_BUTTON1: lstrcpy( szBuf, "ボタン1が押されました"); break; case IDC_BUTTON2: lstrcpy( szBuf, "ボタン2が押されました"); break; case IDC_BUTTON3: lstrcpy( szBuf, "ボタン3が押されました"); break; default: return DefWindowProc( hWnd, message, wParam, lParam ); } InvalidateRect(hWnd, NULL, FALSE);//クライアント全体を再描画する命令 break; case WM_PAINT: DispText( hWnd, szBuf ); break; case WM_SIZE: MoveWindow(hToolBar, 0, 0, LOWORD(lParam), TOOL_HEIGHT, TRUE); break; case WM_DESTROY: PostQuitMessage( 0 ); break; default: return DefWindowProc( hWnd, message, wParam, lParam ); } return 0; } HWND ToolBarCreate(HWND hWnd) { HWND hTool; InitCommonControls(); hTool = CreateWindowEx( WS_EX_TOOLWINDOW, TOOLBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | CCS_ADJUSTABLE | CCS_NORESIZE, 0,0,0,0, hWnd, NULL, hInst, NULL); SendMessage(hTool, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0); return hTool; } void ToolBarAddButtons(int nBotton, TBBUTTON* tbb) { int i; char szBuf[256]; int nAddBotton[20]; for( i=0; i<nBotton; i++ ) { LoadString(hInst, tbb[i].idCommand, (LPSTR)&szBuf, sizeof(szBuf)); nAddBotton[i] = (int)SendMessage(hToolBar, TB_ADDSTRING, 0, (LPARAM)(LPSTR)szBuf); tbb[i].iString = nAddBotton[i]; } SendMessage(hToolBar, TB_ADDBUTTONS, (WPARAM)nBotton, (LPARAM)tbb); } void ToolBarAddButtonSpace(void) { TBBUTTON tbSpace = {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0}; SendMessage(hToolBar, TB_ADDBUTTONS, 1, (LPARAM)&tbSpace); } void DispText(HWND hWnd, char* pszBuf) { HDC hdc; PAINTSTRUCT ps; hdc = BeginPaint ( hWnd, &ps ); TextOut( hdc, 60, 100, (LPSTR)pszBuf, lstrlen(pszBuf) ); EndPaint( hWnd, &ps ); }
☆プログラムの解説☆ @どうやってツールバーにボタンを複数個挿入し,間隔を開けて配置するか? TBBUTTON tbb1[2] = { {0, IDC_BUTTON1, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0}, {1, IDC_BUTTON2, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0}, }; TBBUTTON tbb2[1] = { {2, IDC_BUTTON3, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0} }; 今度は,ボタン3つですね.ボタン2つ分と1つ分の要素を持つ配列を用意しています. // ツールバーにボタンを追加する ToolBarAddButtons( 2, tbb1 ); ToolBarAddButtonSpace( ); ToolBarAddButtons( 1, tbb2 ); ここで,ツールバーにボタンを配置(追加)しています. 始めは2つのボタンを挿入, そしてToolBarAddButtonSpace関数で間隔をとり(関数の中をみれば間隔のとり方はすぐにわかります), 最後に1つのボタンを追加しています. Aどうやって押されたボタン名をどうやってテキストにする? case IDC_BUTTON1: lstrcpy( szBuf, "ボタン1が押されました"); break; case IDC_BUTTON2: lstrcpy( szBuf, "ボタン2が押されました"); break; case IDC_BUTTON3: lstrcpy( szBuf, "ボタン3が押されました"); break; このケース文は,コントロールを処理するWM_COMMANDの中ですね.今までやってきたことからわかるように, 「コントロール(ボタンなどのこと)はIDを持ち,WM_COMMANDで処理される」 と覚えてもらって結構だと思います. IDC_BUTTON1やIDC_BUTTON2などはツールバーのボタンIDですよね. ボタンが押されると,lstrcpy関数を起こして,”ボタン〇が押されました”というテキストをszBuf配列に入れます. そして,最後に InvalidateRect(hWnd, NULL, FALSE);//クライアント全体を再描画する命令 で,クライアント画面を再描画させています. つまり,WM_PAINTメッセージをプロシージャーに送っているのです!! これは,よく使う手法ですね. WM_PAINT処理では, case WM_PAINT: DispText( hWnd, szBuf ); break; となっています.さきほど,”ボタン〇が押されました”というテキスト文(szBuf)が引数になっていますね! このDispText関数ですが,中身は void DispText(HWND hWnd, char* pszBuf) { HDC hdc; PAINTSTRUCT ps; hdc = BeginPaint( hWnd, &ps ); TextOut( hdc, 60, 100, (LPSTR)pszBuf, lstrlen(pszBuf) ); EndPaint( hWnd, &ps ); } となっています. ただ,ウィンドウに文字列を表示するだけでも,3つの関数が必要だということがわかります. BeginPaint関数とEndPaint関数は,もちろんAPIです. BeginPaint関数で,デバイスコンテキストへのハンドルを取得しています. EndPaint関数は,その終了処理(?)をしています. BeginPaintとEndPaintは必ずペアで使ってください!!! デバイスコンテキストについて,すっごい簡単に説明しますと, デバイスコンテキストとは, 画面やプリンタ(両方ともデバイスですね)に文字を表示させたり,線を引いたりするための仕組みであります. 実際に,文字を表示させたりしようとすると,そのハンドルが必要なんですね. TextOut関数は,そのハンドル(=変数はhdc)を使って文字列を出力しています.![]()
![]()
![]()
------------------------------------------------------------------------------------------------
当ページの一部または全部を転載、複写、複製することを禁じます。
また,当サイトを利用した結果に関するトラブル等は、一切関与いたしませんのでご容赦下さい。
Update 04/02/30 By 松本義弘
------------------------------------------------------------------------------------------------