トップページ
ひらく | たたむ | ページトップ
↓マウスで反転選択した文字を検索
Win32API
   
ページ内検索 ページ外検索
検索したい文字を入力して
ENTERを押すと移動します。
\n
[ トップページ ]
[ ____CommandPrompt ] [ ____JScript ] [ ____MySQL ] [ ____Cygwin ] [ ____Java ] [ ____Emacs ] [ ____Make ] [ ____Perl ] [ ____Python ] [ ____OpenGL ] [ ____C# ] [ ____StyleSheet ] [ ____C++ ] [ ____Winsock ] [ ____Thread ] [ ____VisualStudio ] [ ____C ] [ ____Win32API ] [ ____Lua ] [ ____PhotoShop ]
ヘッダ検索
___

■ チュートリアル


  SAMPLE
     シンプルウィンドウ サンプル 

___

■ ウィンドウをつくる

おおまかには次の流れになる
  // 擬似コード
  int main() {

      // Window の種類とメッセージに対する処理内容を登録
      registerClass();

      // 登録した Window をつくる
      HWND hWnd = CreateWindow();

      // メッセージループ
      while ( true ) {
        GetMessage();
        DispatchMessage();
      }
      
      return 0;
  }

___

■ Windowクラスの登録

最低限必要なのは以下の設定。 WNDCLASS構造体型変数 に登録する SYNTAX ATOM RegisterClass( const WNDCLASS *wndCls ); ( typedef WORD ATOM ) cs.dwExStyle = WS_EX_LAYERED | WS_EX_TRANSPARENT; SetLayeredWindowAttributes POINT window procedure は [ window 内 ]で発生したイベント( 入力 )を処理する関数 callback を呼び出すのは WINDOWS

// シンプルなウィンドウを登録
ATOM  registerClass()
{
  WNDCLASSEX cls;

  //
  cls.cbSize = sizeof(WNDCLASSEX);

  //  CS_HREDRAW( リサイズ時の 再描画 )
  cls.style     = CS_HREDRAW | CS_VREDRAW;

  // WindowProcedure の指定
  //  DefWindowProc を指定する。
  cls.lpfnWndProc = WndProc;


  // 予約領域( byte サイズ )はいらない
  cls.cbClsExtra    = 0;
  cls.cbWndExtra    = 0;
  cls.hInstance   = NULL;


  // window 上部の Icon Object のハンドル( LoadIcon() で Resource から読む )
  // ICON, Cursor の指定なし
  cls.hIcon     = NULL;
  cls.hCursor   = NULL;

  // pointer の値を代入しているのか
  //   背景色の指定 ブラシオブジェクト
  cls.hbrBackground = (HBRUSH)(17);

  // Menu の指定もなし
  cls.lpszMenuName  = NULL;

  // 登録するクラス名を MyWindow にする
  // ウィンドウクラスの名前
  cls.lpszClassName = "MyWindow";

  cls.hIconSm   = LoadIcon(0, IDI_WINLOGO);

  // 登録
  return RegisterClassEx(&cls);
}

      ATOM registerClass(HINSTANCE hInst)
      {
          WNDCLASSEX c;

          c.cbSize = sizeof(WNDCLASSEX);

          c.style     = CS_HREDRAW | CS_VREDRAW;
          c.lpfnWndProc = WndProc;
          c.cbCExtra    = 0;
          c.cbWndExtra    = 0;
          c.hInstance   = hInst;
          //c.hIcon     = LoadIcon(hInst, MAKEINTRESOURCE(IDI___TPLVC__));
          c.hIcon     = LoadIcon(0, IDI_APPLICATION);
          c.hCursor   = LoadCursor(NULL, IDC_ARROW);
          c.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
          c.lpszMenuName  = MAKEINTRESOURCE(IDC___TPLVC__);
          c.lpszClassName = strWndCls;
          //cls.hIconSm   = LoadIcon(c.hInstance, MAKEINTRESOURCE(IDI_SMALL));
          c.hIconSm   = LoadIcon(0, IDI_WINLOGO);

          // 登録
          return RegisterClassEx(&cls);
      }

___

■ Window.をつくる

SYNTAX HWND CreateWindow( LPCTSTR classname, // registerClass で登録したクラス名 LPCTSTR name, // タイトルバーに表示される文字 DWORD style, // WS_OVERLAPPEDWINDOW いつもの int x, y, w, h, // 位置と大きさ HWND hParent, // 親Window HMENU hMenu , HANDLE hInst, // このプロセスのハンドル LPVOID lpParam // LPVOID CREATESTRUCT::lpCreateParams にわたす 付加的なメモリ領域 );
    CreateWindow(

    // 登録したクラス名, タイトル
     "MyWindow", "Title",

    // Window スタイル(見た目) ( WS_VISIBLE で表示 )
    // WS_OVERLAPPEDWINDOW で通常のウィンドウになる。
     WS_OVERLAPPEDWINDOW | WS_VISIBLE,

    // 表示位置 と 大きさ
     0, 0, 600, 400,

    // 親とメニューの指定はなし。
    NULL,  NULL,
    hInst, 
    NULL);
___

■ イベントの処理(Event)


  POINT
    ウィンドウズアプリケーションの動作内容はイベントによって何をするかを決めることできまる。
    システム上でおきたイベントをキッカケにして処理が実行される。

    マウスがクリックされたら   -> これをする。
    マウスが右クリックされたら -> これをする。
といった流れになり、 逐次処理のように直線的な流れのプログラムにはならない。 アプリケーションごとに MessageQ があり、 GetMessage() で取りにいく。 CallBack は Windows に呼んでもらい, Windows が返り値を取得する。 SAMPLE マウスで動くウィンドウ
___

■ Window の動作内容を決める

イベントごとに処理をコールバックしてもらう。 System から Call される 自分で処理しないものは DefWindowProc() になげる
___

■ Message.をうけとる

DESC win32 API ではメッセージという概念を使用する message は キューに格納されている Application はキューから Message を取得する。 typedef struct tagMSG { HWND hwnd; // message の宛先 UINT message; // Message の種類 WPARAM wParam; // 追加パラメータ LPARAM lParam; DWORD time; // message がポストされた時間 POINT pt; // message がポストされた時のカーソル位置 } MSG , * PMSG; SYNTAX BOOL GetMessage( LPMSG lpMsg, // msg のポインタを渡してうけとる HWND hWnd , // message をうけとる window ( ある window に送られた message がたまっているのをもらう ) // NULL にすると 自分のThreadでつくった 全window 宛の取得可能 UINT wMsgFilterMax, // msg のフィルタ ( ともに 0 を指定すると Message の Filter がかからない ) UINT wMsgFilterMin ); 呼び出し側スレッドのメッセージキューからメッセージを取得し 指定された構造体にそのメッセージを格納する ポストされたメッセージが取得可能になるまで 着信した送信済みメッセージをディスパッチする。 GetMessage() とは異なり PeekMessage() は 何かメッセージがポストされるのを待たずに制御を返す 関数から制御が返ると この構造体に、呼び出し側スレッドのメッセージキューから取得したメッセージ情報がセットされる。 RET 0(FALSE) : WM_QUIT 1>0(TRUE) : WM_QUIT 以外 -1 : ERROR POINT message をうけとるためには, 常時 message をうけとる必要あり( loop を作成 ) DispatchMessage( &msg ); は自分以外( APP ) にも message を割り振るために使用する GetMessage() で message を取得してしまうので, 他人あての message かもしれないので再度割り振る作業をするだけ さらにいえば, これをしないと wndProc に送られない DispatchMessage() は送られた msg( 伝言 )を処理する対象に送るための処理 message は window 宛でなく 直接 window に送られるケースもあり Windows は ハードウェアイベントが発生するとシステムが管理するメッセージキューにメッセージを追加する アプリケーションの要求に従ってキューの先頭にあるメッセージをわたす GetMessage() でキューから次のメッセージを取得する Windows アプリケーションは繰り返し文で GetMessage() を呼び出し メッセージの受信を監視する( メッセージループという ) うけ取るべきメッセージがキューに存在しないとき GetMessage() は制御を返さずにメッセージの受信をまつ そのため繰り返し処理が無意味に連続して CPU の負荷を高めることはない

  int cnt = 0;
  while ( cnt ++ < = ( 100 * 10 ) ) {

    // Message を取得
    MSG msg;
    GetMessage( &msg, hWnd, 0, 0 );

    // 自分宛 しかきていないような
    // 自分の子供のことかも
    printf( "hwnd(self)  %d hwnd %d msg %d \n" , hWnd, msg.hwnd, msg.message  );

    printf( "msg %d \n" , msg.message  );

    // 適当な時間ねる
    Sleep( 5 );
  }

___

■ message を割り振る( dispatch )

DESC WindowProc で message を処理する LRESULT CALLBACK WndProc(HWND hWnd , UINT Msg , WPARAM wParam , LPARAM lParam); HWND : message が発生した window ハンドル POINT message proc の最後には, DefWindowProc() を呼び出すことで, default の window のふるまいをする 描画処理したり message を処理するという object の基底クラスにあたる
___

■ WindowProcedureを定義する

POINT 処理をしたら 0 をかえすこと

    // マウスクリックされたら、メッセージボックスを表示する。
    LRESULT ndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
    {
      swtich(msg) {

        WM_LBUTTONDOWN:
        {
          WORD y = HIWORD( lp );
          WORD x = LOWORD( lp );

          char s[256];
          sprintf( s, "x = %d y = %d", x, y );
          MessageBox( NULL, s, s, MB_OK );
          break;
        }

        default:
          // 興味のないイベントはデフォルトの処理におまかせする。
          return DefWindowProc( );
      }

      // 自分で処理をしたら 0
      return 0;
    }
___

■ PeekMessage

SYNTAX BOOL PeekMessage( LPMSG msg , HWND hWnd , UINT wMsgFilterMin , UINT wMsgFilterMax , UINT wRemoveMsg // Message を削除するかどうか ( GetMessage() == PM_REMOVE ) ); POINT メッセージがポストにあるか覗くために使用すると思えばよい。 GetMessage() を構造がにてる RET 0 : メッセージがなかった !0 : メッセージがあった

    // PM_REMOVE を指定しないときは,
    //  Message があるかどうかチェックする時に利用する

    // 通常は POST をのぞいて あれば取得する
DESC Window Procedure 内に 無限 LOOP を作成することは禁止 一定時間内に処理を返して, 制御をメッセージループに返す必要あり デッドタイムとは window くんが, user からの入力をまつ無駄な時間 公式DOC の要約 hWnd で Message のあて先を指定する( 子供も含まれる ) Message の種類を絞り込みたいときは, wMsgFilterMax, Min で範囲を指定する hWnd は , Thread( Application ) で作成したものに限るはず もし 2 個以上 Window をつくっていれば, 効果があるということ NULL を指定すると, PeekMessage() を呼び出した現在のスレッドに所属する任意のウィンドウ宛のメッセージを取得する WARNING wMsgFilterMin と wMsgFilterMax の各パラメータでどのような値を指定したときでも PeekMessage は必ず WM_QUIT メッセージを取得する POINT Message を絞り込みたいときに便利
    // マウス関連のメッセージのみを取得する
    if ( PeekMessage( &msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ) ){

    }

    // キーボード入力に関係するメッセージだけ
    if ( PeekMessage( &msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE ) ){

    }
___

■ マウスイベント(MouseEvent)

___

■ Click.(WM_LBUTTONDOWN.WM_RBUTTONDOWN)

DESC 図形の描画の際に使用 矩形選択の使用にはよいサンプル Client 領域内でクリックしたときに発生する DESC mouse 関連情報を取得する関数あり -> GetSystemMetrics retval 0 wp mouse button + ctrl shift lp ClientArea 左上原点からの位置 MOVE も含めてすべてのマウスイベントで共通。 POINT Client 領域のみの Mouse のみ有効. MSG // 押された WM_LBUTTONDOWN WM_MBUTTONDOWN WM_RBUTTONDOWN // 離された WM_LBUTTONUP WM_MBUTTONUP WM_RBUTTONUP // 動いた / マウスがクライアント領域を移動すると発生。 WM_MOUSEMOVE lp // Mouse 位置 ( Client 領域の座標系 ) y = HIWORD( lp ); x = LOWORD( lp ); POINT DD している状態で,クライアントエリア の外で button を離すとmsgはそのwindowに送信されない ( マウスが離されことが通知されない ) -> ならば, window にマウス情報の制御権を与えてあげれるということで MouseCapture -> call する Timing は WM_LBUTTONDOWN | UP を利用する.
___

■ 非クライアントエリアのマウスメッセージ

DESC title bar などでの mouse click を取得する時に利用 DefWindowProc() で処理される MSG WM_NCLBUTTONDOWN WM_NCMOUSEMOVE wp HTBORDER : 位置ではなく どの component かを表す 列挙定数 lp POINT Screen 全体からの位置

  // TitleBar がない Window には WM_LBUTTONDOWN がきたら
  自分自身に WM_NCLBUTTONDOWN を POST すること DragDrop できるようになる

  if ( msg == WM_LBUTTONDOWN ) {
    PostMessage( hWnd, WM_NCLBUTTONDOWN, (WPARAM)HTCAPTION, lp );
    return 0;
  }

___

■ マウス移動

MESSAGE WM_MOUSEMOVE POINT mouse move は Windows が処理した回数に応じて message が届く WM_MOUSEMOVE は window が非アクティブでも message が届く Mouse が [ ClientArea ] で動いた場合にくる. SetCapture() した場合は CrientArea の外からも届くよ. x = LOWORD( lp ) y = HIWORD( lp )
___

■ WindowEvent

___

■ サイズ変更

DESC ユーザーによってウィンドウのサイズが変更された時もメッセージが発生します GetClientRect() を描画毎に設定するのは都合が悪い WM_SIZE: ret 0 wp サイズ変更タイプ( ) lp x, y POINT CS_HREDRAW | CS_VREDRAW を設定することで, 自動で再描画される
___

■ 移動

DESC ユーザーによってウィンドウのサイズが変更された時もメッセージが発生します GetClientRect() を描画毎に設定するのは都合が悪い msg WM_MOVE: ret 0 wp サイズ変更タイプ( ) lp x, y POINT lp は screen 座標系での値 親 window がある場合は , client 領域
___

■ キーボードイベント(KeyboardEvent)

WM_KEYDOWN SystemKey == [Alt-F10] DESC Windows のイベントの基本 他のアプリとの関係も把握可能 キーボードイベントは押された瞬間に発生する すぐにメッセージキューにははいらずシステムメッセージキューにはいる SystemMsgQ ---> AppMsgQ キーボードイベントは Window とその子供コントロールに対して有効。 キーボードからの入力をうける権利を kb forcus という。 keyborad を押すと入力フォーカスをもつ Application に WM_KEYDOWN, WM_KEYUP が転送される MESSAGE WM_KEYUP // Key が押された WM_KEYDOWN // SYS 以外の Key WM_SYSKEYUP WM_SYSKEYDOWN // F1 - F10 // ここが抽象化されている ( 任意のパラメータ ) wp 仮想キーコード( VirtualKey ) lp キーボードが押されると WM_KEYDOWN が発行される
    case: WM_KEYDOWN:
    {
      char str[256];
      sprintf(str, "kb val = %xh", wp );
      MessageBox( NULL, str, str, MB_OK );
      break;
    }

___

■ TranslateMessage

SYNTAX BOOL TranslateMessage( const MSG *lpMsg ); DESC 仮想キーコードを実際の文字に変換する。 仮想キーメッセージを文字メッセージへ変換する 文字メッセージは 呼び出し側スレッドのメッセージキューにポストされ 次にそのスレッドが GetMessage(), PeekMessage() を呼び出すと 文字メッセージを取得する。 RET !0 : messageQ に 文字メッセージがポストされたとき 0 : されなかったとき この関数をコールすることで WM_CHAR がよばれる POINT キーコードではなく文字の入力をとるにはこの関数を メッセージループで呼ぶ必要がある。
    WM_KEYDOWN -> WM_CHAR ( wparam に文字コード )
    while ( GetMessage ) {
      TranslateMessage( &msg );

    }
メッセージハンドラに WM_CHAR が届くようになるので 押された文字を wparam から取得して好きな処理をする。
    case WM_CHAR:
      {
        char buf[256];
        sprintf( buf, "%c", wp );
        MessageBox( NULL, buf, buf, MB_OK );
        return 0;
      }

WM_KEYDOWN -> WM_CHAR ( wparam に文字コード ) -> WM_CHAR は WM_KEYDOWN の後に生成される WARNING この処理をしないと EditControl には文字を入力できない。 TIP ALT key を押しながらの system key を処理する時は WM_SYSKEY を利用すること TIP key コードは 仮想キーコード値を利用することで Device に依存しない ( CPU は IO から値をとることを忘れずに ) KeyBoard には ScanCode という値が割りあてられているが この値を Program でとると HW 依存になるため VK を利用することで抽象化する lparam は 6 つの field data が格納される 0 - 15 : リピート情報 ( Program の処理速度以上で key が押されている場合 1 より大きい値になる ) -> 処理が間に合わない場合は, windows が入力をまとめてしまい, repeat をセット [ 1 1 1 1 1 1 ] -> [ 1 ] 一回にすればいいやという発想 24 : Alt, Ctl の値がくる 29 : Alt 30 : 直前のキーの値を取得可能 -> trg に使用できる 31 : 押した 1, 離した 0 Alt key は WM_KEYUP | KEYDOWN を発行しない( windows 自体が alt + tab などに使用するため ) 代わりに WM_SYSKEYDOWN | WM_SYSKEYUP を利用すること POINT // cast を使う wsprintf( str , "%d" , (short)lp); // 下位 16 bit でrepeat を使う
___

■ WM_CHAR

___

■ TimerEvent

SYNTAX UINT SetTimer( HWND hWnd , // 送信先ウィンドウ UINT id, // タイマー ID( 0 でない任意の数値 ) && hWnd が異なれば ID が同じでも OK UINT elapse , // 間隔 ( msec ) TIMERPROC timerFunc // callback() ); BOOL KillTimer( HWND hWnd, UINT id ); SAMPLE タイマー DESC アニメーションを実現するには 毎ループの間隔を均等にする必要がある。 ( -> CPU 依存になるのはだめ ) Timer は非同期処理ではなく, Mouse, Keyboard のようにメッセージ扱いであり、 割り込みではない MSG WM_TIMER wp Timer ID RET 0 タイマーのセットは初期設定のタイミングでしておく。
    WM_CREATE:
    {
        // 2000 msec 間隔のタイマーを id 100 という名前でセット
        SetTimer( hWnd, 100, 2000, 0 );
        break;
    }
時間になると WM_TIMER メッセージが届くため、ここで適当な処理をする。
    case WM_TIMER:
    {
      MessageBox( NULL, "タイマーテスト", "タイマーテスト", MB_OK );
      break;
    }
    static int x = 0;
    static int t = 0;

    case WM_TIMER:
    {
      // 自分の Timer かどうかチェック
      if ( wp == IDT_TEST ) {
        // Animation させるには 背景をクリアする


        // 動かす絵などを描画
        x = 100 * sin( t++ / 60.0f ) + 100;

        // 背景色でクリア
        HDC hDC = GetDC( hWnd );

        RECT rc;
        GetClientRect( hWnd, &rc );
        Rectangle( hDC, 0, 0, rc.right, rc.bottom );

        BitBlt( hDC, x, 100, 64, 64, hDCBmp, 0, 0, SRCCOPY );

        break;
      }
    }
___

■ 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 ボタン
    #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 に通知されない
___

■ メニュー(Menu)


  SAMPLE
     ポップアップメニュー 


___

■ リソーススクリプトで定義

Menu // ID なし subMenu // ID あり POINT Window に指定できる 唯一のリソース。 WNDCLASSEX.lpszMenuName で Resource と関連づける ( WindowClass に登録した Menu を ClassMenu という ) SYNTAX id MENU [[optional-statements]] { item-definitions... } id : 識別子 item-definitions... : menuItem 定義 // menu の直下の POPUP menu 作成 POPUP text, [[optionlist]] { item-definitions . . . } MENUITEM text id optional list : menu item の外見を決定するパラメータ メニューの内容を Resource Script にかく メモ帳でかいて VisualStudio の Project に追加すれば 自動でコンパイルしてくれる
    ID_MENU_0  MENU
    {
      POPUP "test"
      {
        MENUITEM  "sub menu test",   ID_MENUITEM_0  // id は WM_COMMAND に送信される
      }
    }
ウィンドウクラスの設定時にリソースのメニューを設定しておく。

  WNDCLASSEX c;

  // ResourceScript のメニューを指定する
  c.lpszMenuName = MAKEINTRESOURCE( ID_MENU_0 );
  c.lpszMenuName = "MyMenu";

  RegisterClassEx( &cls );

WndProc でメニューが選択された場合の処理を記述する

  if ( msg == WM_COMMAND ) {
    // リソーススクリプトで指定した ID を選択する
    if ( LOWORD(wp) == IDM_TEST ) {
      MessageBox( NULL, "menu test", "menu test", MB_OK );
    }
    return 0;
  }
-> CreateWindow( ARG9 ) は NULL で OK
___

■ LoadMenu

SYNTAX HMENU LoadMenu( HINSTANCE hInstance, // モジュールのハンドル LPCTSTR name // メニュー名またはリソースの識別子 ); DESC アプリケーションのインスタンスに関連付けられている実行可能ファイルから 指定されたメニューリソースをロードする アプリケーションが終了する前に DestroyMenu() 使ってメニューを破棄し、ロード済みのメモリが利用していたメモリを解放する ClassMenu と違って動的に読み込むことができる

    LoadMenu( hInstance, MAKEINTRESOURCE( IDC_D ) ),
    BOOL DestroyMenu( HMENU ); // メモリ解放

    BOOL SetMenu( HWND, HMENU );

    ShortCutKey は (&C) で設定.
    AcceleratorKey ( HotKey )をセットする.

    AcceleratorKeyTable を ResourceScript に記述.
    LoadAccelerators() で Load
    MessageLoop で TranslateAccelerator() で
        AcceleratorKey -> WM_COMMAND | WM_SYSCOMMAND に変換.


-> とると WM_COMMAND こない SE > リソースファイル > RMB > 追加 > 新しい項目の追加 作成された xxx.rc file に対して,
___

■ menu を消去する

SYNTAX BOOL DeleteMenu( HMENU hMenu, // メニュー項目を持つメニューのハンドル UINT uPosition, // UINT uFlags // MF_BYCOMMAND | MF_BYPOSITION ); BOOL DestroyMenu( HMENU hMenu ); DESC Program からメニューオブジェクトを削除する。 メニューオブジェクトを解放する windowにbindされないmenuは消去する必要がある。 RET !0 : 成功 0 : 失敗
___

■ SetMenu

SYNTAX SetMenu( HWND, HMENU ); DESC メニューをきりかえる
___

■ 右クリックメニュー(Popup.RightClick)

SYNTAX HMENU GetSubMenu( HMENU hMenu, // 親メニューのハンドル int nPos // DropDown Menu の サブ項目のインデックス ); DESC クライアント領域で右クリックすると, 表示されるメニュー 単一のポップアップメニュー表示される。
___

■ TrackPopupMenu

SYNTAX BOOL TrackPopupMenu( HMENU hMenu , UINT uFlags , int x, y , // Screen座標系での位置 int nReserved, // 指定は不要 HWND hWnd, CONST RECT *prcRect // 指定は不要 ); DESC PopUp Menu を表示 初期化でメニュー(サブメニュー)をロードして、ハンドルを保持しておく。
    static HMENU hMenu, hSubMenu;

    case: WM_CREATE:
    {
      hMenu = LoadMenu( (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE ), "ID_MENU_0" );
      hSubMenu = GetSubMenu( hMenu, 0 );
      break;
    }
右クリックを押したら、スクリーン座標系の位置でメニューを表示。
    case WM_RBUTTONDOWN:
    {

      // Click 位置を Screen 座標に変換
      POINT pt;
      pt.x = LOWORD( lp );      pt.y = HIWORD( lp );
      ClientToScreen( hWnd, &pt );

      TrackPopupMenu( hSubMenu, TPM_LEFTALIGN, pt.x, pt.y, 0, hWnd, NULL );
      break;
    }
メニューが選択されと WM_COMMAND が届くので処理をする。
    case WM_COMMAND:
    {
      MessageBox( hWnd, "ポップアップメニュー", "ポップアップメニュー", MB_OK );
      break;
    }
___

■ GetMenu

SYNTAX HMENU GetMenu( HWND ); // ChildWindow は Menu をもたないので禁止. POINT MENU 項目を動的に変化させる 状態によって Menu 項目を禁止したい場合に使う DESC HMENU 取得. WM_INITMENU ( Menu 項目が選択された瞬間に変化 ) // 確認すみ Dialog が開いてる -> OPENMENU OFF Dialog が閉じている -> CLOSEMENU OFF
___

■ Graphic(GDI)


  POINT
    current state の影響をうける( GL 同様 )
    デバイスコンテキストは 描画ステートの集合。

    各描画 API ( TextOut,  )は関数をコールした時点のステートを使って描画される。

  SAMPLE
     ペンで描画   右クリック : 色を取得  

  DESC
    LineXXX : 現在のペンの影響をうける
    window を隠して再描画すると, 影響がわかる

    GDI を使うには DC への Handle を取得する必要がある
    Programmer は 描画対象 の違いを意識しなくてもよくなる

    描画対象であるDeviceContextの Handle をとるには
    GetDC(), BeginPaint() をつかう

    GetDC();
    BeginPaint();
    
    BeginPaint
      Window で設定されている BgColor で塗られ, Control が再描画される
    GetDC
      ClientArea すべてが描画される
      Window 前面に上書きされる

  POINT
    次の使い分けをする

      WM_PAINT
        BeginPaint()

      その他
        GetDC()

    int ReleaseDC();

  


___

■ 描画処理の流れ

POINT 描画処理は ひとつの関数にまとめてバックバッファ(にしておき) WM_PAINT イベントをキッカケにして画面にコピーするだけにしておく。 WM_PAINT がくるのは system から 無効領域 が発生したという Message WARNING InvalidateRect() を WM_PAINT でコールしてはダメ
    draw() {
      // 見えない画面にかく
    }

    wndProc() {
     case WM_PAINT:
      BitBlt();
    }

___

■ 文字を表示する

SYNTAX bool TextOut( HDC hdc, // 描画対象の DeviceContext int x, y, // 位置 LPCTSTR str, // 文字 ( \0 terminate してなくてもいい ) int nrStr // 文字数 ); DESC window の クライアント領域に文字を表示する フォント、背景色、文字色のステートの影響をうける windows の text は console に文字を表示することは異なる 文字も [ 画像 ]として扱う GDI とは Graphic 専門の sub system ( win32 API の描画担当 ) これらは window に関連つけられる HDC GetDC( HWND ); 解放も必要 void ReleaseDC( HDC, HWND );
    HDC hdc = GetDC( hwnd );
    TextOut( hdc, 10, 10, str, lstrlen( str ) );
    ReleaseDC(hwnd , hdc);
POINT 自前でするならば, font を記述することになる GDI の座標系は左上原点

    WndProc () {

      // System から再描画要求があったら描画する
      if ( msg == WM_PAINT ) {

        HDC hDC = GetDC( hWnd );
        TextOut( hDC, 100, 0, "aiueo", strlen( "aiueo" ) );
      }

    }

___

■ DrawText

SYNTAX int DrawText( HDC hDC, LPCTSTR str, int nr, // 文字数 ( -1 : NULL 終端文字とみなす ) RECT rc, // テキストを描画する長方形領域 UINT fmt // DT_XXX ( DT_WORDBREAK ) );
    typedef struct tagRECT
    {
        LONG    left;
        LONG    top;
        LONG    right;
        LONG    bottom;
    } RECT

    if ( msg == WM_PAINT ) {

      RECT rc;
       GetClientRect( hWnd, &rc );

      // 画面中央に表示
      //  VCENTER を利用する場合は DT_SINGLELINE のみ有効
      DrawText( hDC, "test", -1, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);

    }

___

■ 文字色

SYNTAX COLORREF SetTextColor( HDC hdc, COLORREF col, // == unsigned int RGB(255 255 255) ) COLORREF SetTextColor( HDC hdc, COLORREF col, // == unsigned int RGB(255 255 255) ) DESC TextOut() では色を設定できない -> 使いまわしがききそうな値は, GDI は DC へのハンドルを利用する ( 現在の state を参照する ) current state を保持できない ? // MACRO COLORREF RGB(BYTE bRed , BYTE bGreen , BYTE bBlue);
    // 赤に変更
    SetTextColor( hDC, RGB(0xff, 0x0, 0x0) );
    SetTextColor( hDC, RGB(255, 0, 0) );

    // Brush の設定に使う
    SetBkMode ( HDC, int bkMode ); 
DESC win32 API は文字を描画する前に 背景色で塗りつぶしてから描画している( clear color ) COLORREF SetBkColor( HDC hDC, COLORREF color // 塗りつぶしに使用される背景色 ); int SetBkMode( HDC hDC, int mode // 背景モード ); TIP 文字を描画すると, default の白で描画される 白い□ と黒い文字になる

  // 背景は塗りつぶされなくなる
  //  glBlendMode() と同じ
  SetBkMode(hDC , TRANSPARENT);
  TextOut( hDC, x, y+30, str, lstrlen(str) );

___

■ SetBkMode

SYNTAX int SetBkMode( HDC hDC, // デバイスコンテキストのハンドル int iBkMode // 背景モード ); DESC デバイスコンテキストの背景モードを設定する 背景モードは テキスト( TextOut() ) ハッチブラシ、(点線や鎖線など)実線ではないペンで使う

  // 背景をそのまま残す
  SetBkMode( hDC, TRANSPARENT );


___

■ GDI.Object

POINT 作成( Create ) したら 破棄( Delete ) すること DeviceContext は描画のステートをもつ。 各GDIオブジェクト ( Pen, brush )を作成したら、 DeviceContext に SetObject() で関連づけることで描画APIで反映される。 Bitmap 画像を 画面に表示するには MemoryDC に関連づけてから Copy することで対応する
___

■ Brush

DESC Rectangle(), Ellipse(), 背景塗りつぶしに使用される属性 WHITE_BRUSH | BLACK_BRUSH | GRAY_BRUSH // Brush を作成する -> 破棄忘れずに HBRUSH CreateSolidBrush(COLORREF crColor); HBRUSH CreateHatchBrush(int fnStyle , COLORREF clrref); HBRUSH CreateBrushIndirect(CONST LOGBRUSH *lplb); HS_CROSS | typedef struct tagLOGBRUSH { UINT lbStyle; // BS_SOLID | BS_HATCHED COLORREF lbColor; LONG lbHatch; } LOGBRUSH;
___

■ Pen

SYNTAX HPEN CreatePen( int style, // 線の種類 ( 実線 | 点線 ) int width, // 太さ COLORREF color // 色 ); RET 0 : 失敗 N : 前に指定されていたペンのハンドル DESC ペンオブジェクトを作成する。 作成したペンをデバイスコンテキストに指定することで 直線( LineTo ), 曲線を描くときに利用できる。 POINT default obj ( BLACK_PEN | WHITE_PEN | NULL_PEN ) 取得可能 HGDIOBJ GetStockObject(); // GDIOBJ( 画材 )を選択 HGDIOBJ SelectObject(HDC hdc , HGDIOBJ hgdiobj);
    hPen = CreatePen(PS_SOLID , 5 , RGB(255, 0, 0 ) );
___

■ Font

SYNTAX HGDIOBJ GetStockObject( int IDObj // ストックオブジェクトのタイプ ); DESC 用意された(ストック)のペン、ブラシ、フォント、パレットのハンドルを取得 HGDIOBJ を返すので適当な型に cast すること. DeleteObject() を呼び出してストックオブジェクトを削除しなくてもいい
    // 組み込み font を利用
     GetStockObject( ANSI_FIXED_FONT );
DKGRAY_BRUSH GRAY_BRUSH LTGRAY_BRUSH の各ストックオブジェクトは CS_HREDRAW, CS_VREDRAW スタイルを指定しているウィンドウでのみ使える 他のスタイルを指定しているウィンドウで灰色のストックブラシを使うと ウィンドウの移動やサイズ変更をした後で ブラシのパターンがずれることがあります これらのストックブラシの原点は調整できません HOLLOW_BRUSH と NULL_BRUSH ストックオブジェクトは同じ DEFAULT_GUI_FONT のストックオブジェクトで使われているフォントは 他のフォントへ変更できる メニュー ダイアログボックス 他のユーザーインターフェイスオブジェクトの表示に特定のフォントを使いたいときは このストックオブジェクトを利用して指定をする HGDIOBJ SelectObject( HDC hdc, HGDIOBJ hgdiobj ); bool DeleteObject( HGDIOBJ hObj ); // カスタムの際は必要.
___

■ CreateFont

SYNTAX HFONT CreateFont( int h, // フォントの高さ int w, // 平均文字幅 int nEscapement, // 文字送り方向の角度 int nOrientation, // ベースラインの角度 int fnWeight, // フォントの太さ DWORD fdwItalic, // 斜体にするかどうか DWORD fdwUnderline, // 下線を付けるかどうか DWORD fdwStrikeOut, // 取り消し線を付けるかどうか DWORD fdwCharSet, // 文字セットの識別子 DWORD fdwOutputPrecision, // 出力精度 DWORD fdwClipPrecision, // クリッピング精度 DWORD fdwQuality, // 出力品質 DWORD fdwPitchAndFamily, // ピッチとファミリ LPCTSTR lpszFace // フォント名 );

    if ( msg == WM_CREATE ) {

    hDC = GetDC( hWnd );

    // Font Object の作成
    HFONT hFont = CreateFont(
        30,
        0, 0, 0,
        FW_BOLD,
        FALSE, FALSE, FALSE,
        SHIFTJIS_CHARSET,
        OUT_DEFAULT_PRECIS,  CLIP_DEFAULT_PRECIS, PROOF_QUALITY,
        FIXED_PITCH | FF_MODERN,
        "MS ゴシック"
    );

    // Font を選択
    SelectObject( hDC, hFont );

    return 0;
    }

___

■ 図形(Primitive)の描画

DESC PEN , BRUSH 属性で描画( pen : 外側, brush 内側 )
___

■ 点.線

SYNTAX COLORREF SetPixel( HDC hDC, int X, int Y, COLORREF col ); BOOL MoveToEx( HDC hdc, int x, int y, LPPOINT point ); BOOL LineTo( HDC hdc , int x , int y ); DESC 指定した位置に点を描画する。 ペンの属性の影響をうける。 GetPixel(HDC hdc , int XPos , int nYPos);
  for( unsigned int i=0; i< 100; i++ ){
    SetPixel( hdc, i, 150, COL_GRN );
  }
POINT 大きな点をうつには PEN を利用する。 SetPixel() では 1 pixel の点だけが描画できる。
    HDC hDC = GetDC( hWnd );

    // 毎回ペンの設定をしないと描画に反映されないらしい
    HANDLE hPen = CreatePen( PS_SOLID , 50 , RGB(255, 0, 0 ) );

    // 位置を移動( lpPoint : 前の位置 )
    BOOL MoveToEx( hDC , x, y, NULL );

    // 指定位置まで線をひく。( 現在地も移動 )
    BOOL LineTo( hDC, x , y );

    DeleteObject( hPen );
    ReleaseDC( hWnd, hDC );
// カレント位置から N line 描画 BOOL PolylineTo(HDC hdc , CONST POINT *lppt , DWORD cCount); // 複数のラインを描画 ( index で指定できないので不便 ) BOOL PolyPolyline( HDC hdc, CONST POINT *lppt, CONST DWORD *lpdwPolyPoints, DWORD cCount);
___

■ GetPixel . ピクセルの色を取得

COLORREF GetPixel( HDC hDC, int x, int y, ); DESC 指定した座標のピクセルを取得する。
___

■ 多角形(Polygon)

SYNTAX BOOL Polygon(HDC hdc , CONST POINT *lpPoints , int nCount); DESC 内部を brush で塗って描画 int SetPolyFillMode(HDC hdc , int iPolyFillMode); ALTERNATE : 交互に塗る WINDING : 全域を塗る
___

■ Rectangle

SYNTAX BOOL Rectangle( HDC hdc, int nLeftRect, int nTopRect, // 左上 int nRightRect , int nBottomRect // 右下 ); DESC 現在の Brush Object で矩形領域を塗りつぶす BOOL Ellipse( HDC hdc , int nLeftRect , int nTopRect , int nRightRect , int nBottomRect); BOOL RoundRect( HDC hdc, int nLeftRect, int nTopRect, int nRightRect , int nBottomRect, int nWidth , int nHeight ); // API がメンドイので省略 BOOL Arc( HDC hdc, int nLeftRect , int nTopRect , int nRightRect , int nBottomRect , int nXStartArc , int nYStartArc , int nXEndArc , int nYEndArc ); WARNING Button などの子供 Window があると消えるかも POINT カレント位置の影響はなし 右下の 1 pixel は描画されない
___

■ CreateCompatibleDC

DESC 指定したデバイスと互換性のあるメモリデバイスコンテキストをつくる Application は Bitmap を画面に表示するには MemoryDC に選択すること SYNTAX HDC CreateCompatibleDC( HDC hdc // 互換性をもたせる DC Handle );
    // NULL を指定するとアプリケーションの現在の画面と互換性のあるものが作成される
    HDC CreateCompatibleDC( NULL );
hDCMem = CreateCompatibleDC( hDC ); //hBMP = CreateCompatibleBitmap( hDC, 300, 300 ); //SelectObject( hDCMem, hBMP ); SelectObject( hDCMem , hBmp ); で bitmap の大きさにあった Backbuffer にする. // 転送元の bitmap を拡縮して転送. // HDC 間ならば, FrontBuffer でなくても OK
___

■ BitBlt

SYNTAX BOOL BitBlt( HDC hdcDest, // コピー先デバイスコンテキストのハンドル int xDest, yDest // コピー先長方形の左上隅の x, y 座標と int w, y // 幅, 高さ HDC hdcSrc, // コピー元デバイスコンテキストのハンドル int x, y, // コピー元の左上の x , y 座標 DWORD dwRop // ラスタオペレーションコード ); DESC ビットブロック転送をする コピー元からコピー先のデバイスコンテキストへ 指定された長方形内の各ピクセルデータをコピーする
       SRCCOPY   : コピー元の色をそのままコピー先へ上書き ( 通常はこれ )
    NOTSRCCOPY   : コピー元の反転色をコピー先へ上書き

    SRCAND       : 論理 AND 演算子を使って、src, dst 色を混ぜる。
    SRCPAINT     : 論理  OR 演算子を使って、src, dst 色を混ぜる。


___

■ StretchBlt

SYNTAX StretchBlt( HDC dst, x, y, w, h, HDC src, x, y, w, h, DWORD dwRop // ラスタオペレーションコード ); DESC コピー元の長方形からコピー先へビットマップを拡縮コピー システムは コピー先のデバイスコンテキストで設定されている伸縮モードを使う
___

■ TransparentBlt

DEP msimg32.lib #pragma comment(lib,"msimg32.lib") SYNTAX TransparentBlt( HDC dst, x, y, w, h, HDC src, x, y, w, h, UINT crTransparent // 透明扱いにする色 ); DESC 4 bpp , 8 bpp (ビット/ピクセル) の送信元ビットマップに関してサポート

      // RGB マクロで指定する
      // 透明色の指定以外は , BitBlt と同じ
      TransparentBlt( ... , RGB(255, 0, 0) );

___

■ PatBlt

SYNTAX PatBlt( HDC hDCMem, x, y, w, h, UINT ); DESC 矩形を描画 PatBlt( hDCMem, 0, 0, 300, 300, WHITENESS );
___

■ BeginPaint

SYNTAX BeginPaint( HWND, PAINTSTRUCT *ps ); DESC GDI は Window 全体に対してではなく, 無効領域にのみ描画される PAINTSTRUCT に描画の情報をいれる
___

■ SelectObject

SYNTAX HGDIOBJ SelectObject( HDC hdc, // デバイスコンテキストのハンドル HGDIOBJ hgdiobj // オブジェクトのハンドル ); DESC 指定されたデバイスコンテキストで 指定された 1 個のオブジェクトを選択します 新しいオブジェクトは、同じタイプの以前のオブジェクトを置き換える 指定されたのと同じタイプで それまで選択されていたオブジェクトを返す アプリケーションは新しいオブジェクトを使い終えたら 必ず元の(既定)オブジェクトに置き換えるべき アプリケーションは 1 つのビットマップを一度に複数のデバイスコンテキストで選択することはできない
___

■ GetObject

SYNTAX int GetObject( HGDIOBJ hgdiobj, // グラフィックオブジェクトのハンドル int cbBuffer, // オブジェクト情報を格納するバッファのサイズ LPVOID lpvObject // オブジェクト情報を格納するバッファ ); DESC GDIオブジェクトの情報を取得する。 BITMAP のハンドルを指定すれば、画面のサイズなどを取得できる。

    BITMAP bitmap;
    GetObject( hBitmap, sizeof(BITMAP), &bitmap);

___

■ InvalidateRect

SYNTAX BOOL InvalidateRect( HWND hWnd, // 対象となる Window ( NULL ならばすべて ) CONST RECT *lpRect, // NULL ならば クライアント領域すべて BOOL bErase // true : BeginPaint() 時に clearColor() // false : 背景はそのまま残る );
      // WM_PAINT を POST して Window の Client 領域をすべて再描画する
      InvalidateRect( hWnd, NULL, false );

      // これでも同じ。
      PostMessage( hWnd, WM_PAINT, 0, 0 );
___

■ CommonControl


___

■ CommonDialog を利用する( 共通の Dialog )

DESC Windows95 から追加されたプリセットのコントロール( GUI部品 )のこと OPENFILENAME work set GetOpenFileName(); TrackBar ProgressBar CreateWindow(), 専用の作成 API でつくる Event の通知は WM_NOTIFY でされる WARNING Resource として記述できない DEP commctrl.h // DLL を呼ぶための ImportLibrary comctl32.lib // 実装のある場所 comctl32.dll

  if ( msg == WM_CREATE ) {

    INITCOMMONCONTROLSEX cc;

    cc.dwSize = sizeof( INITCOMMONCONTROLSEX );
    cc.dwICC = ICC_DATE_CLASSES;

    // Common Control DLL の初期化
    InitCommonControlsEx( &cc );

    // TB_
  }

  MyDialog DIALOG 300, 300, 200, 200
      CAPTION "タイトル"
      FONT 9, "MS UI Gothic"

  {

    // デフォルトボタン
    DEFPUSHBUTTON  "ボタンを押してね", 101, 10, 10, 100, 20, WS_GROUP
    EDITTEXT 102, 95, 56, 30, 11, ES_NUMBER

    // カレンダー コントロール
    CONTROL "", 1072, "SysMonthCal32", MCS_NOTODAY | MCS_NOTODAYCIRCLE | WS_TABSTOP, 10, 50, 117, 89
  }

___

■ InitCommonControlsEx

SYNTAX BOOL InitCommonControlsEx( LPINITCOMMONCONTROLSEX lpInitCtrls // 登録対象のクラスの情報 ); DESC コモンコントロールのダイナミックリンクライブラリ(DLL)に含まれている 特定のコモンコントロールクラスを登録する WARNING InitCommonControlsEx() を呼び出すたびに、その効果は累積する
    ICC_UPDOWN_CLASSフラグを指定して InitCommonControlsEx 関数を呼び出し
    次に ICC_HOTKEY_CLASSフラグを指定してこの関数を呼び出すと
    アップダウンとホットキーの各コモンコントロールクラスが登録され
    アプリケーションから利用できるようになる。
___

■ ファイルダイアログ

SYNTAX GetOpenFileName( OPENFILENAME *on ); GetSaveFileName( OPENFILENAME *on ); RET !0 : SUCCESS 0 : ERROR | Cancel | Close | Buffer が小さすぎる. DESC [ファイルを開く]ダイアログボックスを作成する。 OPENFILENAME にパラメータをセットして利用する 構造体は memset で 0 にしておくのが無難。
    // WARNING : init "" しないと ERROR
    char str[ NAME_SIZE ] = "";

    OPENFILENAME fn;
    memset( &fn, 0, sizeof(OPENFILENAME) );

    fn.lStructSize  = sizeof( OPENFILENAME );

    // ParentWindow < -> Edit でいい
    // なくても OK
    fn.hwndOwner = HWND_DESKTOP;

    // Filter 文字列
    //    区切り文字[\0] : [\0\0] 終了マーク
    fn.lpstrFilter =   "Text files {*  .txt}\0*.txt\0"
                      "HTML files {*.htm}\0*.htm;*.html\0"
                      "All  files {*.*}\0*.*\0\0";

    // うけとる File 名( Path つき ) sz 指定
    fn.lpstrFile = str;
    fn.nMaxFile = NAME_SIZE;

    // タイトル名と大きさ
    fn.lpstrTitle = TEXT("タイトル 自分で開く");
    fn.nMaxFileTitle = NAME_SIZE;

    // FILE は存在しないといけない
    fn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;

    // Default 拡張子( 必須ではない )
    fn.lpstrDefExt = TEXT("txt");

    // == 0 で Cancell
    if ( GetOpenFileName( &fn ) == 0 ) return 0;
    else {
      // File の FullPath がかえる
      MessageBox( NULL, str, str, MB_OK );
    }


___

■ GetFileInformationByHandle

___

■ リソーススクリプト(ResourceScript)


___

■ Resource 文のつくりかた

SYNTAX (unsigned short | string) ICON file nameID ICON filename DESC resource とは 実行ファイルに埋め込まれたデータ 種類としては 文字列 | Bitmap画像 | ボタン, アイコン, サウンド 作成するには resource script を利用する POINT リソースのメリット
     Data(見た目) と Program(ロジック) の記述を分離できるので, 変更はリソーススクリプトのコンパイルだけでよくなる
     見た目の編集を Program 内に記述しなくてよくなる
     ファイルをバイナリの中に埋め込みたいときに使う( 見せたくないとき )
     Program 本体と独立しているため再利用できる。
     多言語対応をする時に文字リソースだけを言語ごとに変更するだけですむ。
___

■ リソーススクリプトのかきかた

テキスト文なので、適当なエディターで以下の構文で利用したいGUI部品を定義する。
    //  id      :  固有の適当な数値
    //  GUI     :  リソースの種類
    //  param   :  リソースの設定情報

    id  GUI  param
ICON を "test.ico" というファイルから ID_ICON_0 という名前で作成する。
    ID_ICON_0   ICON   DISCARDABLE  "test.ico"
id はソースコードからも参照するため, resource.h などで定義して共有しておく。 数値、または文字列で固有の値をつけておく。
    // resource.h
    #define  ID_ICON_0   1001


    #include resource.h
    ID_ICON_0   ICON   DISCARDABLE  "test.ico"
ソースコードでは id からリソースを検索して読み込む
      winc.hIcon    = LoadIcon(hInst , "ID_ICON_0" );
      winc.hIcon    = LoadIcon( hInst , MAKEINTRESOURCE( IDI_ICON ) );
// unsigned short -> string cast( 型変換 ) // #define MAKEINTRESOURCE(i) (LPTSTR) ( (DWORD)( (WORD)(i) ) ) MyICON : 識別文字列( "" 必要なし, cmp が自動認識 ) resource script は resource compiler で コンパイルされる ( static な Text がバイナリに埋め込まれているのと同じ ) ICON を埋め込む( ICON 文を使用する )

        ICON        : ICON 文
        DISCARDABLE : icon 破棄可能であることを windows に通知
                    ( Dialog なら 未使用なら Memory 上から破棄する )
___

■ リソースをコンパイルして実行ファイルに埋め込む

rc.exe を利用してリソーススクリプトをコンパイルしてバイナリを作成。
    $vc/VC/bin/rc.exe    /out:"test.res"    test.rc   
後は Objectファイルと同じように link.exe に渡すだけで完了。
    link  main.obj  test.res   user32.lib  gdi32.lib
// ID の指定は 文字列でもよい。 "xxx" ["] を忘れずに ----------------- ID | IDC_1 ----------------- ----------------- ID | "MyMenu" -----------------
___

■ リソースの種類


   // Menu
   ID_MENU_0   MENU  
   Window と BIND
   wcex.lpszMenuName = MAKEINTRESOURCE(IDC_D);

   // Dialog
    DIALOG 文記述. || ( RE > RMB > Dialog を挿入 )
    DialogBox( ID_DLG ); で作成

    // BITMAP
    //        LoadImage( ID_BMP_0 ); で指定する
    ID_BMP_0  BITMAP   "d:/test.bmp"

___

■ Dialog(DialogBox)

SAMPLE HTTP クライアント GUI SYNTAX id DIALOG x, y, w, h [optional-statements] { control-statement . . . }
    #include< window.h>

    // x, y は ClientArea の場所
    ID_DIALOG DIALOG 0, 0, 100, 100

    // OPTION
    STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
    CAPTION "タイトル"
    // Font
    FONT 9, "MS UI Gothic"

    // ダイアログ上に配置する子コントロール
    {
     // デフォルトボタン
     DEFPUSHBUTTON  "ボタンを押す", 101, 10, 10, 100, 20

     // 属性つき
     DEFPUSHBUTTON  "ボタンを押す", 101, 10, 10, 100, 20, WS_GROUP

     // スタティック文字列
      LTEXT "文字" IDC_STATIC 0 0 200 107

      // エディットボックス( 数字キーのみ )
      EDITTEXT ID_EDIT, 95, 56, 30, 11,  ES_NUMBER
    }

___

■ DialogBox

SYNTAX int DialogBox( HINSTANCE hInstance , LPCTSTR lpTemplate , // ダイアログリソースの ID HWND hWnd , // 親ウィンドウのハンドル DLGPROC lpDialogFunc // ダイアログのプロシージャ ); RET -1 : FAIL nResult : EndDialog() がかえす値 DESC モーダルダイアログを作成する。 Modeless なら CreateDialog() メッセージループを Windows が行うため DialogBox() の呼び出しだけになる。
    int main() {
      HANDLE  hInst = GetModuleHandle( NULL );

      DialogBox( hInst, MAKEINTRESOURCE( IDD_1 ), HWND_DESKTOP, DlgProc );
      return 0;
    }
ダイアログに送られるメッセージを処理するハンドラを用意する。 自分でメッセージを処理したときは TRUE 処理をしない( 無視する )ときは FALSE を返す。
  BOOL CALLBACK DlgProc( HWND hWnd , UINT msg , WPARAM wp , LPARAM lp )
  {
      switch ( msg ) {
        // ボタンがおされたらダイアログを終了
        case WM_COMMAND:
          if ( wp == ID_BUTTON_CLOSE ) {
             EndDialog( hWnd, 0 );
             return TRUE;
          }
          break;          


        default:
          break;
        }

      return FALSE;
   }
POINT 初期化のタイミングは WM_INITDIALOG でする。WM_CREATE に相当する。 ダイアログ上のコントロールへの参照は GetDlgItem() でとっておく。
    case WM_INITDIALOG:    
    {
      HWND hEdit = GetDlgItem( hWnd, ID_EDIT_0 );      
      SetWindowText( hEdit, "www.google.com"  );
      break;
    }
WARNING BAD return DefWindowProc(); すると正しく動作しない OD return 0; Dialog 内の Control の値を取得 | Set する // この window の この Control の値を 符号つきでくれ GetDlgItemInt( hDlg, IDC_ANGLE, &ret, TRUE ); SetDlgItemInt( hDlg, IDC_ANGLE, val, TRUE );
___

■ EndDialog

SYNTAX BOOL EndDialog( HWND hDlg, // 破棄するダイアログのウィンドウハンドルを指定 int nResult // DialogBox() 関数の戻り値を指定 ); DESC Modal Dialog を終了する RET !0 : OK 0 : FAIL
___

■ GetModuleHandle

SYNTAX HANDLE GetModuleHandle( LPCTSTR lpModuleName // モジュール名 ) DESC 指定したモジュール名のハンドルを取得する。 モジュール名( 実行ファイル, DLL )の指定はファイル名、パスで指定する。
    GetModuleHandle( "test.dll" );

    GetModuleHandle( "test.exe" );
    
    // パスは \ 区切りらしい
    GetModuleHandle( "d:\test.exe" );
NULL を指定すると、現在のプロセスの作成に使われたファイルハンドルが返る。
    HANDLE  hInst = GetModuleHandle( NULL );
___

■ GetDlgItem

SYNTAX HWND GetDlgItem( HWND hDlg, // ダイアログボックスのハンドル int nIDDlgItem // コントロールの識別子 ); DESC ダイアログ上の配置したコントロールのハンドルを取得する。 ダイアログリソーススクリプトで指定した ID から参照をとる。
    HWND hEdit = GetDlgItem( hWnd, ID_EDIT_0 );
___

■ Dialog コントロール

desc Dialog に文字を表示するには, resource 文を利用する POINT menu 項目の更新は Windows によって再描画されるまでは, 更新されない -> BOOL DrawMenuBar(HWND hWnd); DeleteMenu( GetMenu(hwnd) , LOWORD(wp), MF_BYCOMMAND); // 選択した menu を消去 DrawMenuBar(hwnd);
___

■ DeviceContext


___

■ GetDC

SYNTAX HDC GetDC( HWND hWnd ) DESC 指定されたウィンドウのクライアント領域, 画面全体を表すディスプレイデバイスコンテキストのハンドルを取得する 指定されたウィンドウで指定されているクラススタイルに応じて 共通, クラス, プライベートいずれかのデバイスコンテキストを取得する GetDC は 共通デバイスコンテキストを取得するたびにデフォルトの属性を割り当てる。 クラスデバイスコンテキスト, プライベートデバイスコンテキスト には 以前の属性をそのまま割り当てる 共通デバイスコンテキスト が不要になったら ReleaseDC() を呼び出して解放すること クラスデバイスコンテキスト, プライベートデバイスコンテキストは ReleaseDC() を呼び出して解放しなくてもよい ReleaseDC() は GetDC を呼び出したのと同じスレッドから呼び出さなければなりません デバイスコンテキストの数は 利用可能なメモリの量で制限される 共通デバイスコンテキスト POINT リソースを節約するため共有するということ。 だからリセットされる。 システム上の特殊なキャッシュ領域に保持される画面DCのこと。 共通デバイスコンテキストは, 描画処理をそれほど頻繁に実行しないようなアプリケーションで使われる。 システムは,DCのハンドルを返す前に,DCをデフォルトのオブジェクト,属性,モードで初期化する。 アプリケーションが実行する描画処理には,これらのデフォルト値が使われる。 デフォルト以外の値を使いたければ, GDI関数を使って新しいオブジェクトを選択したり 既存のオブジェクトの属性を変更したり,あるいは別のモードを選択する必要がある。 POINT 共通デバイスコンテキストはごく限られた数しか存在できないため, 描画を終えたらDCを解放するようにしてください。 共通デバイスコンテキストを解放すると,デフォルトデータに対して加えられた変更はすべて破棄される。 プライベートデバイスコンテキスト POINT 高速化のために、固有にもつということ。 プライベートデバイスコンテキストも画面デバイスコンテキストの一種ですが 共通デバイスコンテキストとは異なり いったんデフォルトデータが変更されると DCを解放したあとでも変更点は保持される。 プライベートデバイスコンテキストを使うのは 描画頻度が非常に高いアプリケーションです。 たとえば,CAD, DTP, ドローイング、ペインティングアプリケーションなど。 プライベートデバイスコンテキストはシステムキャッシュの一部ではなく 使い終わったあとで解放する必要はない。 あるウィンドウクラスのウィンドウがすべて破棄されると それに対応するプライベートコンテキストもシステムが自動的に破棄する。 プライベートデバイスコンテキストを作成するには WNDCLASS構造体のstyleメンバを CS_OWNDC というウィンドウクラススタイルで初期化して RegisterClass() を呼び出す。 CS_OWNDCスタイルを指定してウィンドウを作成したら,GetDC,GetDCEx,またはBeginPaint関数を一度呼び出せば, プライベートデバイスコンテキストを識別するハンドルを取得することができます このハンドル(とそれに結び付けられたDC)は そのクラスのウィンドウが削除されるまで使い続けることができる。 グラフィックオブジェクトやその属性を変更したり,グラフィックモードを変えたりした場合, ウィンドウが削除されるまでそれらの変更点は保持される。 ウィンドウデバイスコンテキスト ウィンドウデバイスコンテキストを使うと たとえクライアント領域外であっても,ウィンドウの好きな場所を描画できる。 通常,ウィンドウデバイスコンテキストが使われるのは,特殊な非クライアント領域を持つ ウィンドウでWM_NCPAINTやWM_NCACTIVATEメッセージを処理するような場合。 それ以外の目的でウィンドウデバイスコンテキストを使用することはお勧めしません。 詳細についてはGetWindowDCを参照。 親デバイスコンテキスト 親デバイスコンテキストを使うと,ウィンドウのクリッピング領域のセットアップに必要な時間を最小限にできる。 通常,親デバイスコンテキストを使う目的は,プライベートやクラスデバイスコンテキストを 使わずにコントロールウィンドウの描画を高速化すること。 たとえば, システムがプッシュボタンやエディットコントロールを描画する際は親デバイスコンテキストを使います。 親デバイスコンテキストは子ウィンドウで使うことだけを目的としていますので,トップレベル, あるいはポップアップウィンドウでは絶対に使わないでください。 詳細についてはParent Display Device Contextsを参照してください。
    // NULL を指定すると, Window外の画面全体に描画対象にできる
    HDC hDC = GetDC( NULL );


    WARNING
      Local 変数にすると問題あるかも

      // static で共有するとうまくいく
      static HDC hDC;

      if ( msg == WM_CREATE )
      {
        HDC hDC = GetDC( hWnd );

        hFont = CreateFont();
        SelectObject( hDC, hFont );

      }
      if ( msg == WM_PAINT )
      {
        // Font が Default に戻る
        HDC hDC = GetDC( hWnd );

        TextOut( hDC );
      }
___

■ ReleaseDC

SYNTAX int ReleaseDC( HWND hWnd, // ウィンドウハンドル HDC hDC // デバイスコンテキストハンドル ); DESC デバイスコンテキストを解放し 他のアプリケーションが利用できるようにする ReleaseDC() の効果は デバイスコンテキストのタイプによって異なる POINT 共通デバイスコンテキスト, ウィンドウデバイスコンテキストだけを解放します クラスデバイスコンテキスト, プライベートデバイスコンテキストには効果がない ( 意味がないということ )
___

■ CreateDC

SYNTAX HDC CreateDC( LPCTSTR lpszDriver, // ドライバ名 LPCTSTR lpszDevice, // デバイス名 LPCTSTR lpszOutput, // 未使用 NULL にする CONST DEVMODE *lpInitData // オプションのプリンタデータ ); DESC 指定されたデバイスのデバイスコンテキストを、指定の名前で作成 NULL で終わる文字列へのポインタを指定 この文字列は 「DISPLAY」または 1 個のプリンタプロバイダの名前(通常は「WINSPOOL」)を保持
___

■ DeleteDC

SYNTAX BOOL DeleteDC( HDC hdc // デバイスコンテキストのハンドル ); DESC 指定されたデバイスコンテキストを削除 WARNING アプリケーションは GetDC() を使ってデバイスコンテキストのハンドルを取得した場合 DeleteDC() を呼び出してそのハンドルを削除してはなりません 代わりに ReleaseDC() を呼びデバイスコンテキストを解放すること
___

■ Bitmap


    DDB : DeviceDependentBitmap   : Device に依存する Bitmap
    DIB : DeviceIndependentBitmap : Device に依存しない Bitmap


  


  POINT
    現在の OS では 違いを意識する必要はない.
    file に保存する場合はDIB


  WARNING
    Bitmap を描画するには MemoryDevice 間を Copy しないとだめ


  if ( msg == WM_CREATE )
  {
    HANDLE hBmp;

    // ファイルからロード
    hBmp = (HBITMAP)LoadImage( 0, "test.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE  );

    // リソースからロード
    HINSTANCE hInst = (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE );
    hBmp = (HBITMAP)LoadImage( hInst, MAKEINTRESOURCE( ID_BMP_0 ), IMAGE_BITMAP, 0, 0, 0  );


    // 現在の Device と同じ Format の MemoryDeviceContext( Memory 上の領域 ) を作成
    // [ BackBuffer ] のこと

    hDCBmp = CreateCompatibleDC( NULL );

    // Bitmap Data を設定
    SelectObject( hDCBmp, hBmp );

    return 0;
  }

  if ( msg == WM_PAINT )
  {

    // BackBuffer から FrontBuffer へ Copy
    HDC hDC = GetDC( hWnd );
    BitBlt( hDC, 0, 0, 64, 64, hDCBmp, 0, 0, SRCCOPY );

    return 0;
  }

   CreateCompatibleDC( 0 ); // NULL 指定では  1*1 monoclome

    BMP を Load しないで work を作成する場合は,
    HBITMAP CreateCompatibleBitmap( HDC, w, h );

POINT 解放・削除の処理には注意が必要 特にDeleteDC(), ReleaseDC()の使い分けには注意 「Create〜」で始まる関数で「作成」したら「Delete〜」で「削除」 「Get〜」で「取得」 したら、「Release〜」で「解放」
___

■ CreateCompatibleBitmap

SYNTAX HBITMAP CreateCompatibleBitmap( HDC hCD, // デバイスコンテキストのハンドル int w, h // ビットマップの幅, 高さ ( ピクセル単位 ) ); DESC デバイスコンテキストに関連付けられているデバイスと互換性のあるビットマップを作成 作成されるビットマップの色形式は hdc パラメータで指定したデバイスの色形式と同じになる このビットマップは 元のデバイスと互換性のあるどの メモリデバイスコンテキストでも選択できる。 メモリデバイスコンテキストでは カラーとモノクロのどちらのビットマップも利用できるので 指定されたデバイスコンテキストがメモリデバイスコンテキストであった場合と それ以外の場合では CreateCompatibleBitmap() が返すビットマップの形式は異なる。 メモリデバイスコンテキスト以外のデバイスコンテキスト用に作成された互換ビットマップは常に 指定されたデバイスコンテキストと同じ色形式、同じカラーパレットを使う。 w, h を 0 を指定した場合は 1 × 1 のモノクロビットマップが作成される。 WARNING CreateCompatibleDC() でメモリデバイスコンテキストを作成すると 最初は 1×1 モノクロームのビットマップが選択されている。 カラーのビットマップを作成するには そのメモリデバイスコンテキストを作成するために使われた hDC を指定すること

    // Memory DC は最初は 1*1 の BMP をもつ
    HDC hDCMem = CreateCompatibleDC (hDC);

    // hDCMem ではなく、生成元の hDC を指定することでカラー構成のビットマップを作成する。
    HBITMAP memBM = CreateCompatibleBitmap (hDC, w, h );

    // DC に指定する
    SelectObject ( hDCMem, memBM);
___

■ LoadImage

SYNTAX HANDLE LoadImage( HINSTANCE hinst, // インスタンスのハンドル LPCTSTR lpszName, // イメージの名前( 識別子 ) UINT uType, // イメージのタイプ int cxDesired, // 希望する幅 int cyDesired, // 希望する高さ UINT fuLoad // ロードのオプション ); DESC アイコン, カーソル アニメーションカーソル, ビットマップをロードする LoadImage() のような多機能な関数では ビットマップ以外のハンドルを返す必要もあるので HANDLE 型のような ものが必要になる
___

■ ユーティリティ


___

■ ClientToScreen

SYNTAX ClientToScreen( hWnd, &pt );
___

■ ツールバー(ToolBar)


___

■ ToolBar

POINT CommonControl なので, 読み込みと初期化必要 Menu より操作が早い
    #include < commctrl.h>
    #pragma comment(lib,"comctl32.lib")
( 初期化のタイミングでDLLを初期化して、ツールバーを作成

    WM_CREATE:
    {
      INITCOMMONCONTROLSEX cc;
      cc.dwSize = sizeof( INITCOMMONCONTROLSEX );
      cc.dwICC = ICC_BAR_CLASSES;

      // Common Control の初期化
      InitCommonControlsEx( &cc );

      // 作成するボタンオブジェクトの配列
      //  ボタンがクリックされると 2 番目で指定した ID が WM_COMMAND に届く。
      static TBBUTTON a[] = {
            { 0 , ID_TB_0 , TBSTATE_ENABLED , TBSTYLE_BUTTON , 0 , 0 , 0},
            { 1 , ID_TB_1 , TBSTATE_ENABLED , TBSTYLE_BUTTON , 0 , 0 , 0},
            { 2 , ID_TB_2 , TBSTATE_ENABLED , TBSTYLE_BUTTON , 0 , 0 , 0},
            { 3 , ID_TB_3 , TBSTATE_ENABLED , TBSTYLE_BUTTON , 0 , 0 , 0},
          };

      // ツールバーを生成
      //    32*32 のサイズのボタンを4個作成
      HANDLE hToolbar = CreateToolbarEx(
                                     hWnd, 
                                     WS_CHILD | WS_VISIBLE,
                                     ID_TOOLBAR_0, 
                                     4,

                                     (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE ),
                                     ID_BITMAP_TOOLBAR ,
                                     a, 

                                     4, 
                                     32, 32, 
                                     32, 32,
                                     sizeof(a)
                                     );
      break;                                     
    }

ボタンが押されたら WM_COMMAND で処理をする。
    WM_COMMAND:
    {
      if ( LOWORD(wp) == ID_TB_0 ) {
        MessageBox( NULL, "ツールバー", "ツールバー", MB_OK );
        return 0;
      }
      
      break;
    }
コモンコントロールの位置を指定する。デフォルトは上部。
    CreateToolbarEx(  WS_VISIBLE | CCS_BOTTOM )
___

■ ツールバーに文字を表示する

SAMPLE 文字つきツールバー DESC ツールバーボタンに文字を表示するには TB_ADDSTRING メッセージを送る。 ツールバーは文字のリストを管理している。 次のように \0, \0\0 という形式でツールバーに送る。 TB_ADDSTRING はこのリストへ順番に追加して、新しく追加された最初のインデックスを返す。 各ボタンは iString メンバにこのインデックスを指定する。 ボタン構造体には iString メンバに文字列のポインタを指定する。 ツールバーのスタイルには TBSTYLE_LIST を必ず指定する。
      static TBBUTTON tbButton[] = {
          { 0 , 1 , TBSTATE_ENABLED , BTNS_CHECK, 0, 0, 0, (DWORD_PTR)"BOO" },
          { 1 , 2 , TBSTATE_ENABLED , BTNS_CHECK, 0, 0, 0, (DWORD_PTR)"GOO" },
          { 2 , 3 , TBSTATE_ENABLED , BTNS_CHECK, 0, 0, 0, (DWORD_PTR)"TES" },
          { 3 , 4 , TBSTATE_ENABLED , BTNS_CHECK, 0, 0, 0, (DWORD_PTR)"AAA" },
      };

      HWND hToolbar = CreateToolbarEx(
                                      hWnd, 
                                      WS_CHILD | WS_VISIBLE | TBSTYLE_LIST,
                                      ID_TOOLBAR_0,

                                      4,
                                      hInst, 
                                      ID_TOOLBAR ,
                                      tbButton, 
                                      
                                      0, // ボタンの数は0個にしておく。
                                      32, 32, 32, 32, sizeof (TBBUTTON)
                                      );
ボタンに文字を追加するには TB_ADDBUTTONS 経由でボタンを作成する必要がある。
    SendMessage( hToolbar , TB_ADDBUTTONS, 4, (LPARAM)tbButton );
別の方法として TB_ADDSTRING で文字列のリストだけをツールバーに設定できる。

    // ボタン構造体の iString には文字列リストのインデックスを指定しておく。
      static TBBUTTON tbButton[] = {
          { 0 , 1 , TBSTATE_ENABLED , BTNS_CHECK, 0, 0, 0, 0 },
          { 1 , 2 , TBSTATE_ENABLED , BTNS_CHECK, 0, 0, 0, 1 },
          { 2 , 3 , TBSTATE_ENABLED , BTNS_CHECK, 0, 0, 0, 2 },
          { 3 , 4 , TBSTATE_ENABLED , BTNS_CHECK, 0, 0, 0, 3 },
      };

      HWND hToolbar = CreateToolbarEx(
                                      hWnd, 
                                      WS_CHILD | WS_VISIBLE | TBSTYLE_LIST,
                                      ID_TOOLBAR_0,

                                      4,
                                      hInst, 
                                      ID_TOOLBAR,
                                      tbButton, 
                                      
                                      4,
                                      32, 32,  32, 32,  sizeof (TBBUTTON)
                                      );

    // ツールバー作成後に文字列リストへ登録。
    // \0 が区切りで \0\0 が終端記号
    char str[] = "aaa\0bbb\0ccc\0ddd\0\0";
    SendMessage(hToolbar, TB_ADDSTRING, 0, (LPARAM)str );
___

■ CreateToolbarEx

SYNTAX HWND CreateToolbarEx( HWND hwnd, // ツールバーの親ウィンドウ DWORD ws, // ツールバーのウィンドウスタイル UINT wID, // ツールバー のID int nBitmaps, // ボタンの画像の数 HINSTANCE hBMInst, // インスタンス UINT wBMID, // ビットマップリソースの識別子 LPCTBBUTTON lpButtons, // ボタン情報 int num, // ボタンの数 int w, h, // ボタンの幅と高さ( Pixel ) int dx, dy, // ボタン画像の幅と高さ ( Pixel ) UINT uStructSize // TBBUTTON 構造体のサイズ ); RET N : ツールバーのウィンドウハンドル NULL : 失敗 DESC 1 つのツールバーウィンドウを作成し 指定されたボタンをツールバーへ追加する TIP ボタンの絵を横一列に並べた1つのビットマップ画像を用意する。 すると、関数は1つのボタンのビットマップの横幅 dxBitmap メンバを参考に nBitmap 分だけ分割して、各ボタンに割り当てる Toolbar をつくるときのルール
    Size は 2 べきでなくても良い。
    { 64*4 , 22 }
  
  WARNING
      bmp は index color 形式でないと CreateToolbarEx() で落ちる。

typedef struct _TBBUTTON { int iBitmap; // ボタンイメージの 0 から数えるインデックスを指定します // このインデックスは、生成されるボタンとビットマップを関連付けるもので // ツールバーは、内部でビットマップにインデックスをつけて画像保有している int idCommand; // ボタンが押されたときの識別ID BYTE fsState; // 初期状態のフラグ BYTE fsStyle; // スタイル DWORD dwData; // アプリケーション用のメモリ領域 int iString; } TBBUTTON, NEAR* PTBBUTTON, FAR* LPTBBUTTON;
___

■ TB_ADDSTRING

DESC ToolBar の String Pool に文字列を追加 wp String Resource をもつ Instance のハンドル ( lp で 文字列のポインタを指定するなら NULL にしておく ) lp String Resource の識別子 OR 文字列のポインタ
___

■ タスクトレイ(TaskTray)


  SAMPLE
     右クリックでタスクトレイに格納  
    
    

  SYNTAX
    BOOL Shell_NotifyIcon(
                        DWORD dwMessage,
                        PNOTIFYICONDATA lpdata
                        );

  DESC
    タスクバーのステータスエリアにメッセージを送る。
    必要事項は NOTIFYICONDATA にセットする



  DESC
    16, 32, 64 のサイズは確認すみ
    ( bmp 形式はだめかも )

  #pragma comment(lib,"Shell32.lib")

    case WM_RBUTTONDOWN:
    {
       NOTIFYICONDATA ni;
       memset( &ni, 0, sizeof(NOTIFYICONDATA) );

       ni.cbSize = sizeof( NOTIFYICONDATA );
       ni.hWnd = hWnd;

       ni.uID = 1001;

       ni.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;

       // icon ファイルを読み込む
       ni.hIcon = (HICON)LoadImage( 0, "test.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE  );

       // タスクトレイのアイコンにマウスイベントが発生したときにくるアプリケーション定義のメッセージ
       // WARNING
       //   WM_APP 以上の数値でないと message が通知されない
       ni.uCallbackMessage = WM_APP + 1;

       // タスクトレイにアイコンを追加したら自分のウィンドウを隠す。
       Shell_NotifyIcon( NIM_ADD, &ni );
       ShowWindow( hWnd, SW_HIDE );

       return 0;
    }
タスクトレイのアイコンがクリックされたら、ウィンドウを表示する。

  // Application 定義のメッセージをうける
  case WM_APP + 1:
  {
    // lp にマウスイベントの情報がはいっている
    if ( lp == WM_LBUTTONDOWN ) {
      MessageBox( NULL, "left mouse button", "left mouse button", MB_OK );

      // タスクトレイからアイコンを消す。
      // 消す対象を特定するため NIM_ADD で指定した ID と同じ番号をつける。
      NOTIFYICONDATA ni;
      memset( &ni, 0, sizeof(NOTIFYICONDATA) );
      ni.uID = 1001;      
      Shell_NotifyIcon( NIM_DELETE, &ni );

      // ウィンドウを表示する。
      ShowWindow( hWnd, SW_SHOW );
    }

  }


___

■ TaskBar にいれる

SYNTAX CloseWindow( HWND ); DESC Window を最小化する

  // マウスをクリックしたら, Window を最小化してタスクバーにいれる
  if ( msg == WM_LBUTTONDOWN ) {
    CloseWindow( hWnd );
    return 0;
  }

___

■ IsIconic


  if ( msg == WM_TIMER ) {

    // タスクバーにあるときは TitleBar を 最小化中 にする
    if ( IsIconic(hWnd) ) {
      SetWindowText( hWnd, "最小化中" );
    }
    else {
      SetWindowText( hWnd, "ふつう" );
    }

  }


___

■ ステータスバー(StatusBar)


  SAMPLE
     ステータスバー 
    

___

■ CreateStatusWindow

SYNTAX HWND CreateStatusWindowA( LONG style, // ウィンドウスタイル PCTSTR pszText, // 最初の区画に表示する文字列 HWND hWndParent, // 親ウィンドウのハンドル UINT wID // コントロールID ); DESC ステータスウィンドウは親ウィンドウの下端に表示され、指定された文字列を表示する

    static HWND hStatus;

    case WM_CREATE:
      hStatus = CreateStatusWindow(
                                   WS_CHILD | WS_VISIBLE           // 必須
                                   | CCS_BOTTOM | SBARS_SIZEGRIP,
                                   "test",
                                   hWnd,
                                   ID_STATUS_0
                                   );
  }

    case WM_SIZE:
    {
      // Status Window にも通知することで, リサイズするようにする
      SendMessage(hStatus , msg , wp , lp);
      break;
    }


    case WM_RBUTTONDOWN:
    {
       // 文字を変更するには SetWindowText() で指定する。
       または SB_SETTEXT メッセージを送信する。
       SendMessage(hStatus , SB_SETTEXT, 255, (LPARAM)"change text" );
       break;       
    }
___

■ DragDropをうけつける


  SAMPLE
     ドラッグドロップしたパスを表示 
    


    DragDropを受信可能にする。
    ウィンドウ以外でもコントロールならば、Dialogでも何でも受け付けることができる。

    #include< ShellAPI.h>
    #pragma comment( lib, "Shell32.lib" )

    HWND  hWnd = CreateWindowEx(
                                WS_EX_ACCEPTFILES,  // スタイルにこのフラグをたてる
                                "test" , title,
                                WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                                100, 100,
                                w, h ,
                                NULL , NULL , hInstance , NULL
                                );


    dlgProc() {

      case WM_INITDIALOG:
        DragAcceptFiles( hWnd, TRUE );
        return TRUE;


        // ドロップされた時のイベントコールバック
      case WM_DROPFILES:
        {        
          // ドロップされたファイル数を取得して
          int nr = DragQueryFile( wp, -1, NULL, 0 );

          // そのパスを取得する。
          char buf[256];
          for( int i=0; i< nr; i++ ){
            DragQueryFile( wp, i, buf, sizeof(buf) );
          } 

          DragFinish( wp );
        }
        return TRUE;
    }

___

■ DragAcceptFiles

SYNTAX DragAcceptFiles( HWND, BOOL ); DESC 指定 wnd に対して, DD の受理を設定 WM_DROPFILES が届く
     DragAcceptFiles( hWnd, true );
TCHAR str[NAME_SIZE ]; DragQueryFile( (HDROP)wp, 0, str, sizeof(str) ); DragFinish( (HDROP)wp );
___

■ DragQueryFile

SYNTAX UINT DragQueryFile( HDROP, // file 情報を含む構造体ID. WM_DROPFILES::wp にある. UINT iFile, // query する file idx ( 複数の場合 ) LPSTR str, UINT szBuf // ); RET File の個数 || Buffer DESC filepath, 個数を取得する
     DragQueryFile( (HDROP)wp, 0, str, sizeof(str) );

    // 解放
    DragFinish();
___

■ DragFinish

SYNTAX void DragFinish( HDROP hDrop ); DESC Windows が file 名転送のために 確保した Memory を開放 Resource が Interface を超える例

    wndProc() {

      case WM_DROPFILES:
        SetForegroundWindow( hWnd );

        DragQueryFile();

        DragFinish();
    }

___

■ CreateWindowEx

SYNTAX hWndClient = CreateWindowEx( WS_EX_CLIENTEDGE, // 追加パラメータ "MDICLIENT", NULL, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN, 0, 0, 0, 0, // 意味なし hWnd, (HMENU)0, hInst, &ccs );
___

■ FileSystem


  POINT
    Win32API は GUI を提供するのが Main だが
    OS 本体の機能も提供する
    
    ( Directory Entry の検索 )
    
    GetOpenFileName(); GetSaveFileName(); を利用する
    ( fopen, fread, fwrite とかでも代用可能 )


  DESC
    listbox の使いどころは, file の列挙( default でこの機能をサポートしている )
   Exe のある directory のみが注意

      msg
  LB_DIR ( これ Event|Condition の ID みたいだな...  )
      wp
  表示ファイルの属性( DDL_DIRECTORY | DDL_READWRITE )
      lp
  file 名( wildcard OK * )


___

■ ReadFile

SYNTAX bool ReadFile( HANDLE hFile, LPVOID buf, DWORD sz, // 読み込むサイズ LPDWORD szRead, // 読んだサイズ LPOVERLAPPED p // OVERLAPPED ptr ); RET !0 : SUCCESS 0 : FAIL DESC fread() のように stream タイプ 読んだ分だけ 前に進む

  char buf[1024];

  DWORD szRead;
  ReadFile( hFile, buf, sz, &szRead, 0 );

  // 必ず閉じること. アクセス権限をとられるらしい
  CloseHandle( hFile );


___

■ ファイルの時間を調べる

___

■ GetFileTime

SYNTAX BOOL GetFileTime( HANDLE hFile, // ファイルのハンドル LPFILETIME lpCreationTime, // 作成日時 LPFILETIME lpLastAccessTime, // 最終アクセス日時 LPFILETIME lpLastWriteTime // 最終更新日時 );

    // 不要な情報は 0 をセットする
    // 書き込みをしたら W.r.i.t.e.Time が更新される
    FILETIME time;
    GetFileTime( hFile, 0, 0, &time );

___

■ CompareFileTime

  // 比較する
  // ret = ( file1 - file2 )  と考えるとわかりやすい
  LONG ret = CompareFileTime( file1, file2 );

___

■ File に保存する

CreateFile(); WriteFile(); ReadFile(); CloseHandle(); SYNTAX HANDLE CreateFile( LPCTSTR file, DWORD modeAcc, // AccessMode 0 : file情報のみ取得 GENERIC_READ | GENERIC_WRITE DWORD modeShr, // 共有 mode LPSECURITY_ATTRIBUTE s, DWORD flagCreate, // 生成条件 (CREATE_NEW | CREATE_ALWAYS | OPEN_EXISTING | OPEN_ALWAYS ) DWORD flag, HANDLE file );
    HANDLE hFile = CreateFile(
                     str,              // Path
                     GENERIC_READ,
                     0,
                     NULL,
                     //OPEN_ALWAYS,   // ない場合は空ファイルができる
                     OPEN_EXISTING, // INVALID_HANDLE_VALUE をかえす
                     FILE_ATTRIBUTE_NORMAL,
                     0
                     );
]
___

■ Directory.検索

___

■ FindFirstFile

SYNTAX HANDLE FindFirstFile( LPCTSTR file, // 検索 path LPWIN32_FIND_DATA y // 結果 ); RET !0 : SUCCESS 0 : ERR DESC 指定 ptn と一致する file(directory) Handle を取得する. file 名は [*?] 使用 OK

    HANDLE h = FindFirstFile("D:/data/*", &wfd );

WARNING
      BAD
    HANDLE h = FindFirstFile("D:/data", &wfd );
      OD
    HANDLE h = FindFirstFile("D:/data/*", &wfd );
      HANDLE h = FindFirstFile( ".\tmp\data", &wfd );
      if ( h == INVALID_HANDLE_VALUE ) {
          myas(0, "");
      }
      struct WIN32_FIND_DATA {


  // FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY ...
  DWORD dwFileAttributes;
  FILETIME ftCreationTime;
  FILETIME ftLastAccessTime;
  FILETIME ftLastWriteTime;
  DWORD  nFileSizeHigh;
  DWORD  nFileSizeLow;

  TCHAR cFileName[ MAX_PATH ];
  TCHAR cAlternateFileName[ 14 ];
      };

___

■ FindNextFile

SYNTAX HANDLE FindNextFile( HANDLE h, LPWIN32_FIND_DATA y ); RET !0 : SUCCESS 0 : ERR

    // Directory を iterate する
    while ( FindNextFile(h, &i) ) {
    
      if ( y.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
        
      }
      
      printf( y.cFileName );
      sz += y.nFileSizeLow;

    }  

___

■ FindClose

SYNTAX BOOL FindClose( HANDLE h ); DESC 不要になった HANDLE を削除 WARNING CloseHandle( h ) と間違えないでね
___

■ GetCurrentDirectory

SYNTAX GetCurrentDirectory( int, // buf size ( 文字数( TCHAR )単位 ) LPTSTR // buf ( FULLPATH でかえる ) );
___

■ GetFileInformationByHandle

SYNTAX GetFileInformationByHandle( HANDLE, BY_HANDLE_FILE_INFORMATION ); DESC File に関連する情報をえる File Size をもとめて ReadFile() の Buffer を用意するために使う
    GetFileInformationByHandle( h, &i );
    i.nFileSizeLow;
]
___

■ パスの存在チェック


    #pragma comment(lib,"Shlwapi.lib")
    #include< Shlwapi.h> 

    BOOL PathFileExists(
                          LPCTSTR path
                       );
___

■ 画面のキャプチャ(Capture) . ScreenCapture . Save


  SAMPLE
     ツールバーのボタンを押して画面をBMP画像として保存 
    

___

■ GetDIBits

SYNTAX int GetDIBits( HDC hDC, // デバイスコンテキストのハンドル HBITMAP hBmp, // ビットマップのハンドル UINT uStartScan, // 取得対象の最初の走査行のオフセット( 通常は 0 ) UINT h, // 取得対象の走査行の数 ( 縦の長さ ) LPVOID pBuf, // コピー先ののバッファ LPBITMAPINFO pBmpInfo, // BITMAPINFO構造体へのポインタ UINT uUsage // RGB とパレットインデックスのどちらか ); RET N : 成功 ( 変換された画像データの行数 ) 0 : 失敗 DESC ビットマップオブジェクトのビット配列を取得し 指定された形式でバッファへコピーする。 pvBits パラメータに有効なポインタを指定する場合は BITMAPINFOHEADER 構造体の最初の 6 つのメンバに DIB のサイズやデータ形式を設定する必要がある。
___

■ OS


___

■ ShellExecute

SYNTAX HINSTANCE ShellExecute( HWND hwnd, // 親ウィンドウのハンドル LPCTSTR lpVerb, // 操作 LPCTSTR lpFile, // 操作するファイル LPCTSTR lpParameters, // 操作のパラメータ LPCTSTR lpDirectory, // 既定のディレクトリ INT nShowCmd // 表示状態 ); Windows で wclk したときと同じことがおきる REF http://hp.vector.co.jp/authors/VA024411/vbtips02.html 使いどころは 指定したファイルを「オープン」 他のプログラムを引数付きで起動する この機能を使うと インストールプログラムでインストール完了時にドキュメントを自動的に表示する ランチャーソフトを作る
    // lpszFn を開く
    ShellExecute(NULL,"open",lpszFn,NULL,NULL,SW_SHOWNORMAL);

    // lpszFn をノートパッドで開く
    ShellExecute(NULL,NULL,"notepad",lpszFn,NULL,SW_SHOWNORMAL);

___

■ ShellExecuteEx

  SHELLEXECUTEINFO s;
  memset( &s, 0, sizeof(SHELLEXECUTEINFO) );
  s.cbSize = sizeof(SHELLEXECUTEINFO);
  s.fMask = SEE_MASK_NOCLOSEPROCESS;
  s.hwnd = HWND_DESKTOP;

  s.lpParameters = NULL;
  s.lpDirectory = NULL;
  s.nShow = SW_SHOWNORMAL;

  s.lpFile = L"d:/foo.txt";
  ShellExecuteEx( &s );

  // Notepad が閉じるのを待つ       
  WaitForSingleObject( s.hProcess, INFINITE );


___

■ MyDocument.をえる

{ #include "ShFolder.h" char s[MAX_PATH]; SHGetFolderPath( NULL, CSIDL_PERSONAL, NULL, 0, s ); }
___

■ time(時刻)


___

■ GetTickCount

SYNTAX DWORD GetTickCount() DESC システムを起動した後の経過時間を msec 単位でかえす。 System の時間なので Debugger でとめると当然その間も進む
    DWORD s = GetTickCount();

    // 5 秒ビジーループする。
    while (true) {
      if ( GetTickCount() - s >=  5*1000 ) {
        break;
      }
    }
___

■ DLL


___

■ LoadLibrary

SYNTAX HMODULE LoadLibrary( LPCTSTR path // DLL file PATH ( FullPath || FileName ) ); DESC DLL を呼び出し Process の Address 空間に map する CntRef をひとつ増やす Program は { data, 命令 }.( Instruction )でできていることの証明 変数: data の置かれている, Memory のアドレスへの Label( 名前 ) 関数: 命令の置かれている, Memory のアドレスへの Label( 名前 ) -> やはり, 基本は何もかわっていない POINT Address が UserAdress にあることに注目 -> OS 本体に App が直接アクセスさせないための安全措置 Program を Rebuild しなくても動的に機能の追加が可能 POINT 取得したアドレスを適切な関数型に変換
    typedef int (*FN)( HWND, LPCTSTR, LPCTSTR, UINT );
    {
      // File 名なら 検索順どおり
      HINSTANCE h = LoadLibrary( "user32.dll" );
      // FullPath
      HINSTANCE h = LoadLibrary( "c:/windows/user32.dll" );

      FN f;
      f = (FN)(GetProcAddress( h, "MessageBoxA"));
      (*f)( 0, "koreha", "yoberu", MB_OK );
    }

    {
      hDll = LoadLibrary(_T("libcgc.dll"));
      COMPILE_PS3 DllCompile;
      DllCompile = (COMPILE_PS3)GetProcAddress( hDll, "compile_program_from_string" );
      uint32_t ret = DllCompile( source.c_str(), "sce_fp_rsx", 0, option, &buffer );
    }
// 0x77d3058a // 2G 以下 TCHAR str[NAME_SIZE]; wsprintf( str, "adr %08x", f); dws( str ); void func(){ .... } { int adr = ( (int)func ); ( *( (FN)adr ) )(); } SYNTAX BOOL FreeLibrary( HMODULE ); DESC refcnt をひとつ減らす. ( 0 ならば ProcessSpace から unmap ) RET 0 : SUCCESS
___

■ GetProcAddress

SYNTAX HINSTNCE GetProcAddress( HMODULE, LPCTSTR ); DESC DLL がもつ Export された関数の Address をえる WARNING C Linkage extern "C" をしないと, 名前修飾 のため検索に失敗する
    // dll.cpp
    // ERROR
    __declspec( dllexport ) func();

    // OK
    extern "C" __declspec( dllexport ) func();

    // main.cpp
    GetProcAddress( h, "func" );
POINT __declspec( dllexport )宣言で DLL file 内に 関数名が記録される extern "C" で 名前修飾 をふせぐ ( func )という名前で記録させる
___

■ メッセージの送信


___

■ SendMessage

SYNTAX LRESULT SendMessage( HWND hWnd , // メッセージの送信先のコントロール UINT Msg , WPARAM wp, // Message ごとに追記する 32 bit の追加情報 LPARAM lp ); RET Message 処理の結果 POINT SendDlgItemMessage() は SendMessage() と同じ Dialog Item は Resource で作成できるため ID 指定もするという意味 TIP HWND_BROADCAST を指定すると, TOP LEVEL の window に送信する SendMessage は message 処理が終わるまで, 制御を返さない 子供に送信したい場合は, CreateWindow の返した handle をもっておく SendMessage は同期をとる -> つまり 同期をとるとは, 相手にだした依頼内容が処理されてから, 次の処理をすることが できるので、[ 同期 ]がとれているという
___

■ PostMessage

SYNTAX BOOL PostMessage( HWND hWnd , UINT Msg , WPARAM wp , LPARAM lp ); DESC 非同期メッセージを送信する。 メッセージをポストするだけで、制御はすぐに返る。
___

■ 機能限定のウィンドウをつくる(DialogBox MessageBox)


  POINT
    Window Program は Window と Proc のペアでひとつ
    これを簡単に提供するのが
    DialogBox, MessageBox

    機能が限定された Window のこと

    Application
    -----------------------------------------
      DialogBox 
                DlgProc()
    -----------------------------------------
                  |
      MessageLoop --   // メッセージループはシステムが行う。

    Windows
    -----------------------------------------
SYNTAX int DialogBox ( DialogBox() 作成時に Proc Address を登録する ) DialogBox() の構造 Windows は 複数の Proc Address をもつ. Message を送信する Window から Proc を選ぶ. DialogBox の RetVal は Windows が処理する. ( App にはかえらない ) -> Message を処理しない場合は, false を返してね -> 終わるわけではない -> false == [ Message 無視 ]といいかえよう. Windows が DialogBox の MessageLoop を管理する. -> 別に Menu から呼ばないといけないわけではない. DialogBox() は制御がかえらない IDCANCEL は固定値 ? -> [X] を押すと WM_CLOSE が送信. 無視すると, WM_COMMAND + IDCANCEL が送信. DialogBox(); は内部で次のような処理をする. CreateWindowEx(); WM_SETFONT, WM_INITDIALOG,
___

■ MessageBox

DESC window の生成なしで, Dialog の生成が可能 POINT MessageBox は DialogBox よりもさらに簡略化した Window Callback してもらう関数を登録することもできないため ボタンを押した結果をもらうという決められた操作に限定される。 SYNTAX int MessageBox( HWND hWnd , // 親ウィンドウ LPCTSTR lpText , // メッセージ LPCTSTR lpCaption , UINT uType ); POINT ARG1 は 制御をとめたい Window に利用できる。 RET 押されたボタン表す整数 IDYES | IDNO | IDOK | IDRETRY | IDIGNORE | IDCANCEL | IDABORT
    MessageBox( NULL, "message", "title", MB_OK );
// 次のように切り替える #ifdef UNICODE #define wsprintf wsprintfW #else #define wsprintf wsprintfA #endif // !UNICODE Win32 が Unicode の関係で、ANSI C 標準の文字列関数を使用できない( 移植が難しくなる ) LPTSTR lstrcat( LPTSTR lpString1, LPCTSTR lpString2 ); int lstrlen( LPCTSTR lpString ) UNICODE 設定にすると文字化けしてしまうな - ( しかし 切り替えは動作する ) 日本語を表示する project file を開けば 設定を見ることができる LPTSTR GetCommandLine(VOID); からも取得可能 ------------------------------------------------------- Application MessageBox() ------------------------------------------------------- Windows MessageLoop WindowProc( 用意すみの Proc が利用される ) | | | | --- Window から Proc を選択 --- -------------------------------------------------------
___

■ DialogBox( Modeless ) は MessageQ に送られるので 自分で Dialog 用か判定する

Dispatch とは Windows からの Message を 対応する Control にお届すること. IsDialogMessage() は 実は tag 移動の際の対象になるだけ. -> MouseEvent とかは関係ないので, あってもなくても OK Tread を利用して 複数の MessageBox を呼んでも動くようにする。 MB_APPLMODAL : MessageBox に応答しないと, hWnd 指定の Window で作業できない -> default : ->
___

■ Resource を利用する

Dialog の 指定数値は Font のサイズで決まる Dialog には ToolBox から Control をはりつけること可能 Control は [ ChildWindow ] Shift + F7 で Control の大きさを 文字列にあわせること可能 Dialog を[ 破棄 ]する EndDialog( HWND, INT_PTR ); // ARG2 は適当な値で OK TIP DialogProc でしか利用しない WARNING DefWindowProc を利用禁止
___

■ ModeLessDialog(CreateDialog() < -> DialogBox() )

DESC ResourceScript は ModelDialog と同じ内容でよい。 CreateDialog(); DestroyWindow(); MessageLoop::isDialogMessage();
___

■ メッセージに関係なく取得する


___

■ GetCursorPos

SYNTAX BOOL GetCursorPos(LPPOINT lpPoint); BOOL BOOL SetCursorPos(int X , int Y); DESC メッセージに関係なくマウスカーソルを知りたい mouse なしでも kb で エミュレート可能 WARNING screen 全体における座標 // Mouse カーソル 表示トグル int ShowCursor( BOOL bShow );
___

■ 時間の取得

SYNTAX VOID GetLocalTime(LPSYSTEMTIME lpSystemTime); DESC ANSI C ならば 時間を取得する API あり typedef struct _SYSTEMTIME { WORD wYear; WORD wMonth; WORD wDayOfWeek; WORD wDay; WORD wHour; WORD wMinute; WORD wSecond; WORD wMilliseconds; } SYSTEMTIME;

  // 取得した時間を Title に表示する
  SYSTEMTIME t;
  GetLocalTime( &t );
  char buf[32];
  spritnf( buf, "%02d/%02d %02d", t.wMonth, tWDay, t.wSecond );

  SetWindowText( hWnd, buf );

___

■ 色々遊ぶ


___

■ Windowを常に最前面に表示する

SYNTAX DESC オーバーラップウィンドウ ポップアップウィンドウ 子ウィンドウのいずれかを拡張スタイル付きで作成します 拡張スタイルが指定できること以外は CreateWindow 関数と同じ

  HWND hWnd = CreateWindowEx(
                    // Style に "WS_EX_TOPMOST" を指定
                    WS_EX_TOPMOST,

                    // 後は同じ
                    ...

___

■ 透明なWindow.をつくる


  typedef BOOL __stdcall SETLAYER( HWND hwnd, COLORREF crKey, BYTE bAlpha, DWORD dwFlags );


  SETLAYER    *SetLayeredWindowAttributes;


  HINSTANCE   hDllInst;

  // USER32.DLLからWindows2000で拡張された関数を取得する
  hDllInst = LoadLibrary("user32.dll");

  if( hDllInst == NULL ){
    MessageBox( NULL, "USER32.DLL の読み込みエラー","Error", MB_OK );
    return( FALSE );
  }

  SetLayeredWindowAttributes =
    (SETLAYER *)GetProcAddress( hDllInst, "SetLayeredWindowAttributes" );

  if( SetLayeredWindowAttributes == NULL ){
    MessageBox( NULL, "SetLayeredWindowAttributes()関数のポインタが取得できませんでした。
                      Windows2000ではない可能性があります","Error", MB_OK );
    return( FALSE );
  }


  // 作成した Window を透明にする
  HWND hWnd = CreateWindow( ... );

  long sty = GetWindowLong( hWnd, GWL_EXSTYLE );
  sty |= 0x00080000;
  SetWindowLong( hWnd, GWL_EXSTYLE, sty );

  SetLayeredWindowAttributes( hWnd, 0, 128, 2 );

___

■ WinMain


  POINT
    WinMain() の引数
    hInstance の Address は複数起動しても等しい.

    Windows95 以降では [ 仮想的に独立 ]した MemorySpace が与えられるので, 常に値がひとつになる。
    Global な空間としてみれば複数起動すれば当然 アドレスは変わる.
    Instance とは Application の実体(プロセス)のアドレスのこと


  POINT
    Win32 Application の EntryPoint
    Windows System が呼び出す。
    

  SYNTAX
    
    int WINAPI WinMain(
        HINSTANCE hInst,   // Application の Instance Handle
        HINSTANCE hPrev,   // WIN32 では常に NULL
        LPSTR args,
        int nr
    );
    
  RET
    0  : MessageLoop 前に終了したとき
    wp : WM_QUIT をもらって終了したとき

  DESC
    Windows Program は API だけではなく, Windows の仕組みが必要
    Windows 95 以前は DOS 上で Windows という Program が動作していた.
    Windows( OS ) は Memory 管理. FileIO, GUI, HW 制御を提供する
    すべての Program が共通して利用する機能を提供するだけ
    Windows 上の Program は Windows に対して、命令すること

    Windows Program では 他の App の影響をうける ( 窓が重なったり ... )
    System から通知をうけるには Message を利用する.

    Windows
    Message は自分で用意することも可能

    WINAPI は呼び出し規約

    WinMain(
           HINSTANCE hInst,
           HINSTANCE hInstPrev,  // 16 bit 時代の名残. ( 自分が起動すみか check )
           LPSTR cmdLine,        // cmdline 引数.
           int nCmdShow          //
           )
___

■ WIN32APIの不便なところ



  DESC
    C で記述されているため すべてのシンボルがグローバルにあるため
    マクロなどの名前の付け方が煩雑。

    大量の API と操作対象のオブジェクトの結びつきがわかりずらい。

  
  POINT
    なんで, OO が有効か ? 
    SetDlgItemText() を 例にとって考える

    どれが, どの Object (もの)に Bind されているか不明
    そのため 操作対象に 近いところにあると便利
    

  WARNING
    ShowWindow( hWnd, nCmdShow ); とすること.


  Windows 固有の型が多い。

  HBRUSH
  #define DECLARE_HANDLE( HBRUSH ) struct name##__ { int unused; }; typedef struct name##__ *name

     // 実体は int 型をもつ struct
      struct HBRUSH__{
        int unused;
      };

      typedef struct HBRUSH__ *HBRUSH;

      HICON も同じ ( 任意のポインタと同じ。 )

    DECLARE_HANDLE( HINSTANCE );
    #define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name
      struct HINSTANCE__{
        int unused;
      };
      typedef struct HINSTANCE__ *HINSTANCE

___

■ WindowsProgram.の基本

C で [ 直接 ] WIN32API を呼ぶ. OO , Class を学ぶには Java の方がよい. -> Java で学ぶ. GUI の Design わかりやすさ == 認知的要素. Sequence( 処理手順 ) を設計する. Affordance ( 促進 ) -> Buttton が 押すことを 促進する. -> Affordance が高いと, 説明が不要. Mapping( 対応つけ ), Controler と Model(View)の関連づけ. HeuristicEvaluation( わかりやすい GUI のために ) 簡単な会話( 最小限の用語で ) User の言葉を利用( User の知っている 概念. 言葉を使用 ) 一貫性( 慣例 )に従うこと. EtrorCode ではなく, [ 建設的 ]な解決策を示すこと. 誤りを防ぐこと.
___

■ dst


VOID CopyMemory(
  PVOID Destination,   // コピー先
  CONST VOID *Source,  // コピー元メモリブロック
  SIZE_T Length        // メモリブロックのサイズ
);

___

■ Clipboard.クリップボード


  


___

■ クリップボードに文字列をセット


        char str[] = "test";
 
        //(A)クリップデータへ格納するデータは共有メモリに格納する必要があります。
        //   必要なだけの共有メモリを獲得してそこにデータをコピーします

        int len = strlen(str)+1;
        HGLOBAL hData = (HGLOBAL)::GlobalAlloc(GHND, (DWORD)len);
        char *pData = (char *)GlobalLock( hData );
        strcpy(pData, str);
        GlobalUnlock(hData);

 

        ::OpenClipboard(NULL);
        //今クリップボードに入っているデータを廃棄します。
        ::EmptyClipboard();


        //(D)クリップボードへグローバルメモリを登録する
        if (::SetClipboardData(CF_TEXT, hData) == NULL) {
                // 登録失敗の場合は、自分で共有メモリを開放する必要があります。
                ::GlobalFree(hData);
        }

        // クリップボードをクローズする
        ::CloseClipboard();
___

■ クリップボードにあるテキストデータを表示

GetClipboardDataを使用して、クリップボードにあるテキストデータを取得し表示する。
{
  OpenClipboard(NULL);

  HANDLE  hText = GetClipboardData(CF_TEXT);
  if(hText == NULL) {
    printf("クリップボードにテキストデータはない。\n");
  } else {
    char *pText = GlobalLock( hText );
    printf("%s\n", pText);
    GlobalUnlock(hText);
  }

  CloseClipboard();
}
___

■ GlobalLock

DESC グローバルメモリオブジェクトをロックし メモリブロックの最初の 1 バイトへのポインタを返します。 SYNTAX LPVOID GlobalLock( HGLOBAL hMem // グローバルメモリオブジェクトのハンドル ); POINT ロックというのは メモリのアドレスが移動することをロックするらしい。
___

■ CloseClipboard

SYNTAX BOOL CloseClipboard(); RETURN !0 : 失敗 0 : 成功
___

■ GetClipboardData

HANDLE GetClipboardData( UINT uFormat // クリップボードのデータ形式 ); RETURN 指定したデータ形式のクリップボードオブジェクトのハンドルが返ります。 NULL : 失敗
___

■ SetClipboardData

HANDLE SetClipboardData( UINT uFormat, // クリップボードのデータ形式 HANDLE hMem // データのハンドル );
___

■ FILE_TYPE

http://www.sage-p.com/b/public_vml/dragdrop.html CF_TYPE CF_BITMAP http://blog.goo.ne.jp/masaki_goo_2006/e/c051af6aa9c44b5cd8cd7ac97b1c5057
___

■ getdesktopwindow



  HWND  GetDesktopWindow();

___

■ EndPaint



___

■ AlphaBlend . アルファブレンド


AlphaBlend(
  HDC hdcDest,
  int x, y, w, h
  HDC hdcSrc,
  int xs, yx, ws, hs,
  BLENDFUNCTION  fn
);

BLENDFUNCTION fn = {0};

fn.BlendOp = AC_SRC_OVER;
fn.SourceConstantAlpha = 128;
  msimg32.lib

___

■ SetCursor


  hCursor = ::LoadCursor( NULL, IDC_WAIT );
  SetCursor( )
___

■ WM_SETCURSOR



  RETURN
    If an application processes this message, 
    it should return TRUE to halt further processing 
    or FALSE to continue.


___

■ CustomCursor . カーソル


   // icon ファイルを読み込む

   nconvert

   nconvert を使って icon ファイルを作成する。
   nconvert -overwrite  -resize 64px 64px  -out ico   D:/work/art/icon/cursor.png

   nconvert -overwrite  -resize 128px 128px  -out ico   D:/work/art/icon/cursor.png
以下のツールで、任意の画像からカーソルファイルを作成する。 http://www.wsims.com/cweissha/iconconverter/index.php?page=download カーソル画像サイズと ホットポイント を指定して カーソル形式で出力する。
  HICON  hIcon = (HICON)LoadImage( 0, "d:/test.cur", IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE  );

  case WM_SETCURSOR: 
  {
    SetCursor( hIcon );
    break;
  }
___

■ icon ファイル構造体

   ---------------------------------------------------------------------------------------------
   ファイルヘッダ  IconFileHeader  6バイト
   ---------------------------------------------------------------------------------------------
   0x0000 (2)  icoReserved  予約 常に0
   0x0002 (2)  icoResourceType  リソースタイプ   1 - アイコン  2 - カーソル
   0x0004 (2)  icoResourceCount  アイコンの数
   ---------------------------------------------------------------------------------------------
   IconInfoHeader (ICONDIRENTRY構造体)
   ---------------------------------------------------------------------------------------------
   0x0006 (1)  Width  アイコンの幅 (0の場合は256ピクセル)
   0x0007 (1)  Height  アイコンの高さ (0の場合は256ピクセル)
   0x0008 (1)  ColorCount  カラー数 (256色以上なら0)
   0x0009 (1)  Reserved1  予約
   0x000A (2)  Reserved2  予約 (ホットスポットx座標)
   0x000C (2)  Reserved3  予約 (ホットスポットy座標)
   0x000E (4)  icoDIBSize  アイコンファイルのサイズ
   0x0012 (4)  icoDIBOffset  BitmapInfoHeaderまでのバイト数
   ---------------------------------------------------------------------------------------------
___

■ Sleep


  3 秒寝る
  Sleep( 3000 );
___

■ DoubleClick . ダブルクリック


  case WM_LBUTTONDBLCLK:
  {

  }
ダブルクリックを取得するには以下のスタイルが必要。
          wndClass.style = CS_DBLCLKS;
Only windows that have the CS_DBLCLKS style can receive WM_LBUTTONDBLCLK messages, which the OS generates when the user presses, releases, and again presses the left mouse button within the time limit for double-clicks for the system. Double-clicking the left mouse button actually generates the following series of four messages:
___

■ 最小化と非表示


  http://pcnetbeginners.seesaa.net/article/122968741.html

  SW_SHOWMINIMIZE
  SW_HIDE


___

■ alt tab アイコン


  キャプションバーのアイコンを変更する
 HICON hIcon = LoadImage( hInstance, MAKEINTRESOURCE( IDI_ICON ), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR );
 SendMessage( hWnd, WM_SETICON, ICON_SMALL, (LPARAM)hIcon );
 SendMessage( hWnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon );





NINJAIDX 17