DESC
ボタン、ウィンドウなどを GUI の部品のことを Control という。
作成をするには CreateWindow() で種類を指定してつくる。
部品は階層構造になっていて、ボタンはウィンドウの子供になる。
Window( Control でない ) の子供に Window を作成できる
ボタンなどは定義すみのシステムクラスになる
■ 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
正しく動作する例
■ コントロールの種類
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
ボタン
#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
コンボボックス
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 に通知されない