GUI(Control)


DESC ボタン、ウィンドウなどを GUI の部品のことを Control という。 作成をするには CreateWindow() で種類を指定してつくる。 部品は階層構造になっていて、ボタンはウィンドウの子供になる。 Window( Control でない ) の子供に Window を作成できる ボタンなどは定義すみのシステムクラスになる
[.] BUTTON [.] COMBOBOX [.] EDIT [.] LISTBOX [.] MDICLIENT [.] RichEdit [.] SCROLLBAR [.] STATIC



Control( GUI ) の操作


DESC hWnd が Control の ハンドル( Pointer )にあたる Window に個別につけられる番号が Window Handle になる。 各コントロールを操作するには, このハンドルを渡す。
HWND hEdit = CreateWindow( "EDIT", ... ); // EditBox の文字をカラにする GetWindowText( hEdit, buf, sizeof(buf) ); // EditBox の文字をカラにする SetWindowText( hEdit, "" );



GUI の構造


DeskTop も Window のひとつ。階層の最上位にあたる。 HWND_DESKTOP を一番したにして 複数の 自作 Window を作成することもできてしまう 自作の Window を 親子つけすることも可能 ( 終了を押すとすべて終わる ? ) WS_OVERLAPPEDWINDOW : 親 Window の外に表示される. 属性を次のように分類する 親の外にでるかどうか ? : WS_CHILD | WS_POPUP | WS_OVERLAPPED Window 枠の指定 : WS_BORDER | WS_DLGFRAME | WS_CAPTION SystemMenu の有無の指定 : WS_SYSMENU 正しく動作する例
[.] WS_OVERLAPPED [.] WS_POPUP



コントロールの種類


Window の構成要素 標準コントロール : Button などの基本要素 Button ( BS_RADIOBUTTON | BS_CHECKBOX | BS_PUSHBUTTON ) ComboBox Edit ListBox Scrollbar Static コモンコントロール : Windows95 で追加された部品 CrientArea : Window 上で文字 Graphic を描画できる領域 Window : Window Program の土台. 各 Control を配置 MessageBox : 機能限定の Window. 動作確認に使う DialogBox : 機能限定の Window. 入力の確認に使う Window, Dialog には Control( 部品 )をはれる WS_CHILD にしなければ, 部品も外にだせる Window へはりつける際は, Resource を指定することができない. Dialog は Menu は不可能


コントロールのイベントの取得


多くの Control は WM_COMMAND を発行をする。 Control への Message は ParentWindow にも届く( 通知Message ) 発生元コントロールを判別するには, CreateWindow() を利用して作成した Control を指定する。 ARG9 で ID を指定する POINT 生成された control は window と寿命を同期するので、 明示的に破棄する必要はない。


Button


DESC ボタンを作成する。 押されると, WM_COMMAND が送信される。 押されたボタンを判別するには CreateWindow の引数に id を指定する。 SAMPLE https://www.dropbox.com/s/rfot7671n4co24a/button.exe( ボタン )
# define ID_BUTTON_0 1001 // ウィンドウを作成。 HWND hWnd = CreateWindow( ... ); CreateWindow( // システムで用意されている "BUTTON" クラスを指定 "BUTTON", // ボタンに表示される文字 "押す" WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON , 0, 0, 100, 20, // ボタンを貼り付ける親ウィンドウを指定 hWnd, // Button の ID の指定をする。指定をしない場合は 0 (HMENU)ID_BUTTON_0, hInst, NULL );
MESSAGE WM_COMMAND lp LO(wp): ChildWindow ID ( 子供であることが重要 ) HI(wp):
if ( msg == WM_COMMAND ) { // Button がおされたときの処理 if ( LOWORD(wp) == ID_BUTTON_0 ) { MessageBox( NULL, "ボタンおした", "ボタンおした", MB_OK ); } return 0; }
コントロールからのメッセージであれば通知コード( BN_CLICKED ) 1: 1: アクセラレータ 1: メニュー ret 0


CheckBox


DESC checkbox も button の一種 BS_AUTOCHECKBOX にすることで, check mark を自動で作成する ( -> BS_CHECKBOX ならば, BM_SETCHECK を送信する必要あり ) checkbox を click すると WM_COMMAND が送られてくる ( 誰からの message かという情報はない ) checkbox を操作するには, button 同様 message を送信する msg (BM_SETCHECK | BM_GETCHECK) wp (BST_CHECKED | BST_UNCHECKED) ret 0


TextEdit(EditControl)


DESC CUI のように scanf のような 文字入出力 のかわりに Control に代用させる default : 1行入力 また右クリックメニューも作成できる。 スクロールバーは, WS_HSCROLL | WS_VSCROLL で OK 子供 Window は Menu をもてない 親Window に message を送信することが可能 LOWORD( wp ) : ID HIWORD( wp ) : 通知コード 1: EN_CHANGE : かわったよ lp : 子window のハンドルが格納されている. POINT EditControl を利用すれば, 簡易版 notepad を作成できる。 クライアント領域の文字描画よりEdit.Control, StaticControl の方が便利 再描画はシステムが自動でしてくれる。 WARNING 32 Kb の容量しかない
CreateWindow( "EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_MULTILINE | ES_AUTOHSCROLL // ( 自動改行 ) | ES_LEFT | ES_RIGHT | WS_THICKFRAME, // Resize 可能 ( emacs みたいに利用可能 ) 0, 0, 200, 200, hWnd, // 適当な ID (HMENU)(1003), // (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE ) , NULL , NULL );
EditControl には次の操作ができる。
// 文字列数を取得する。 DWORD len = SendMessage( hEdit, WM_GETTEXTLENGTH,0,0); // 最後にカーソルを移動 SendMessage( hEdit, EM_SETSEL,(WPARAM)len,(LPARAM)len); // 最後の位置に文字を追加 SendMessage( hEdit, EM_REPLACESEL, (WPARAM)false,(LPARAM)("test") );



StaticText(StaticControl)


DESC 入出力はサポートしない GUI デフォルトは文字がはられるが, 画像も貼ることができる。 POINT 描画自体は DrawText() が利用される( 基本は同じ ) WARNING 矩形サイズが小さいと, 文字が自動改行される


ListBox


DESC file, 選択項目の列挙に使用すると便利
WM_CREATE: { h = CreateWindow( "LISTBOX" , "開く", WS_CHILD | WS_VISIBLE | WS_BORDER, 10 , 10 , 200 , 200 , hWnd , (HMENU)2 , hInst , NULL ); // リストにテキストを追加する。 SendMessage( h, LB_ADDSTRING, 0, (LPARAM )"test1" ); SendMessage( h, LB_ADDSTRING, 0, (LPARAM )"test2" );
リストボックスでのイベントを親ウィンドウで受けるには LBS_NOTIFYを指定する必要がある。
case WM_COMMAND: { if (HIWORD(wp) == LBN_DBLCLK) { MessageBox(hWnd , "ダブルクリック" , "" , MB_OK); } else if (HIWORD(wp) == LBN_SETFOCUS) { MessageBox(hWnd , "ダブルクリック" , "" , MB_OK); } break; }
POINT Notify( お知らせ ) とは Control からの変更の通知のこと LBS_NOTIFY WM_COMMAND を送信, 選択した瞬間に飛んでくる 通知 code を知ることで, ListBox の現在の状態を知ることが可能 // 以下 ある意味で, ListBox 君の Event だな - // Control の Event とは どういう操作をされたかという意味。 LBN_KILLFOCUS: LBN_SETFOCUS: kb focus を得た LBS_SORT: item 内容の sort LB_INSERTSTRING を送信することで Item 追加 wp : idx lp : string ret LB_ERR | LB_ERRSPACE LB_GETCOUNT wp 0 lp 0 ret nrItem LB_GETCURSEL : 選択項目 idx wp 0 lp 0 ret idx LB_GETTEXTLEN : 文字列 wp idx lp 0 ret nrStr LB_DELETESTRING : 指定 index 削除 wp idx lp 0 ret nrStr LB_RESETCONTENT: contents 削除 wp 0 lp 0 ret nrStr LB_SETCURSEL: contents 選択 wp idx lp 0 ret nrStr LB_SELECTSTRING: 文字列から contens 選択 wp idx // 開始 index lp 検索文字列 ret 0 WARNING combobox ではないので注意, WS_VSCROLL を指定すること


combobox


SAMPLE https://www.dropbox.com/s/dyldvn6lqgfw3nt/combobox.exe( コンボボックス ) DESC リストボックスと同じように変更があった場合は 親ウィンドウに通知メッセージが届く。 msg: CB_GETDROPPEDSTATE: dropdown wp 0 lp string 初期化のタイミングで、 COMBOBOX を作成する。
static HWND hCombo; case WM_CREATE: { hCombo = CreateWindow( "COMBOBOX" , NULL , WS_CHILD | WS_VISIBLE | CBS_SORT | CBS_DROPDOWNLIST , 0 , 0 , 300 , 300 , hwnd , (HMENU)1 , ((LPCREATESTRUCT)(lp))->hInstance , NULL ); // リストに項目を追加する。 for ( int i=0 ; i < 5 ; i++) { SendMessage( hCombo , CB_ADDSTRING , 0 , "test combo"); } break; }
コンボボックスの項目が変更されると、親ウィンドウに通知メッセージが届く。 選択された項目のインデックスを取得するには CB_GETCURSEL で調べる。
case WM_COMMAND: if (HIWORD(wp) == CBN_SELCHANGE) { char s[256]; sprintf( s, "アイテム数 = %d\n選択項目 = %d", SendMessage( hCombo , CB_GETCOUNT , 0 , 0) , SendMessage( hCombo , CB_GETCURSEL , 0 , 0) ); MessageBox( NULL, s, s, MB_OK ); }



Scrollbar


POINT WindowScroll と ScrollControl は異なる。 ScrollControl : ClientArea 内ならばどこでも作成できる。 WindowScroll : WS_VSCROLL で作成
hScl = CreateWindow( "SCROLLBAR", SBS_VERT ); SCROLLINFO si; // 場所を指定 SetScrollInfo( hScl, SB_CTL, &si, FALSE ); wndProc() { // WM_VSCROLL が送信 POINT 他の Control とは異なり WM_COMMAND が送信されない // Scroll の操作内容 LOWORD( wp ) // Scroll 位置 HIWORD( wp ) [▲] SB_LINEUP ( DOWN ) [ ] SB_PAGEUP ( DOWN ) [ ] [□] SB_THUMTRACK ( Drag 中) [□] SB_THUMPOSITION [□] [ ] }



GUIの操作





SetWindowText


SYNTAX BOOL SetWindowText( HWND hWnd , LPCTSTR text ); DESC コントロールの名前の変更をする。


ShowWindow


SYNTAX BOOL ShowWindow( HWND hWnd, // ウィンドウのハンドル int nCmdShow // 表示状態 ); DESC ウィンドウの表示状態を変更する。
SW_HIDE : Hides the window and activates another window. SW_MINIMIZE : ウィンドウを最小化 && Z オーダーが次のウィンドウをアクティブ SW_SHOWNA : Not Active && Show



MoveWindow


SYNTAX void MoveWindow( HWND, x, y, w, h, bool bRepaint // ウィンドウを再描画するかどうかを指定する ); DESC 位置と大きさを変更する WM_SIZE の時に利用すると便利 POINT x, y は - 指定可能


GetParent


GetParent();


SetForegroundWindow


// Window を Foreground にして Active に SetForegroundWindow();


GetWindowLong


SYNTAX LONG GetWindowLong( HWND hWnd, // int nIndex // 知りたい情報 Index ); DESC 追加情報を設定する control を作成するときのお話( CreateWindow() ) program 中に動的に作成が必要 Instance ハンドルを, winmain 以外で使用したい場合は, WM_CREATE: lp を利用する // Window 情報を任意のタイミングで取得する
// WindowProc を取得 GetWindowLong( hWnd, GWL_WNDPROC ); // Process のハンドルをとる GetWindowLong( hWnd, GWL_HINSTANCE )
WARNING
// ここで返す値は CreateWindow() で指定した HINSTANCE の値 // もし NULL を指定していれば, NULL がかえる // ICON, Toolbar などで Resource から取得するときは HINSTANCE を指定しないとだめ HINSTANCE hInst = GetWindowLong( hWnd, GWL_HINSTANCE ); assert( hInst != NULL ); CreateToolbarEx( ... hInst );
nIndex : GWL_HINSTANCE : インスタンス GWL_USERDATA : Window に関連つけられた data ( ここで使用する ) RET !0 : 知りたい情報 0 : ERR


SetWindowLong


SYNTAX LONG SetWindowLong( HWND hWnd, // window( control ) int nIndex, // 設定パラメータ定数 LONG dwNewLong // 新しい値 ); DESC Window の属性を設定する 拡張ウィンドウメモリ内の指定されたオフセット位置にある long データ(32 ビット値)も設定できる RET 0: ERR !0: 前の値 // 興味のない msg を元の wndProc に転送 LRESULT CallWindowProc( WNDPROC lpPrevWndFunc, // 呼び出す wndProc HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam ); WARNING 子 Control の Event は親 Window に通知されない