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
    );
    if ( msg == WM_COMMAND ) {
      // Button がおされたときの処理
      if ( LOWORD(wp) == ID_BUTTON_0 ) {
        MessageBox( NULL, "ボタンおした", "ボタンおした", MB_OK );
      }
      return 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
       );
    // 文字列数を取得する。
    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" );
    case WM_COMMAND:
    {
      if (HIWORD(wp) == LBN_DBLCLK) {
        MessageBox(hWnd , "ダブルクリック" , "" , MB_OK);    
      }
      else if (HIWORD(wp) == LBN_SETFOCUS) {
        MessageBox(hWnd , "ダブルクリック" , "" , MB_OK);    
      }
      break;
    }
■ 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;
    }
    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 )
    // ここで返す値は CreateWindow() で指定した HINSTANCE の値
    // もし NULL を指定していれば, NULL がかえる
    // ICON, Toolbar などで Resource から取得するときは HINSTANCE を指定しないとだめ
    HINSTANCE hInst = GetWindowLong( hWnd, GWL_HINSTANCE );
    assert( hInst != NULL );
    CreateToolbarEx( ... hInst );
■ 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 に通知されない