ウインドウの境界をドラッグする

二枚の List Box の境界をマウスでドラッグして左右の幅を変更します。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プロジェクトの作成

  1. このプログラムは Window を左右に分割して表示する の続きです。
    g_hListL, g_hListR は ListBox のハンドルです。
    g_LS,g_RS は左右の ListBox の幅で、g_H は高さです。
    境界の変更は左側の ListBox に WS_THICKFRAME を設定して WM_EXITSIZEMOVE: を検出します。
    Org_EWnd は g_hListL の元の CALLBACK 関数のエントリを退避する領域です。
        /***************************************/
        /*★ Split Window Program    前田 稔 ★*/
        /***************************************/
        #define     NAME    "Split Window"
        #include    <windows.h>
    
        LPCTSTR     ListStr[]=
        { "愛知  真唯子",   "青森  孝雄",   "秋田  景子",   "石川  雅夫",   "神戸  真美",
          "名古屋  美幸",   "愛媛  和子",   "和歌山  絢子", "大阪  恵",     "岡山  英子",
          "沖縄  妙子",     "香川  祐子",   "鹿児島  浩司", "神奈川  真路", "岐阜  真実",
          "京都  智史",     "熊本  志保",   "滋賀  佳奈子", "静岡  志依",   "千葉  泉",
          "東京  拓生",     "長崎  英明",   "長野  政則",   "奈良  憲彦",   "兵庫  美佐子",
          "広島  まい",     "福井  真実",   "福岡  大樹",   "北海道  静",   "三重  由香理",
        };
    
        // Defines, constants, and global variables
        HINSTANCE   g_hInst;            //Instance Handle
        HWND        g_hWnd;             //MainWindow Handle
        HWND        g_hListL;           //List Handle
        HWND        g_hListR;           //List Handle
        WNDPROC     Org_EWnd;           //g_hListL の元の CALLBACK
        long        g_LS,g_RS;          //List の左右の幅
        long        g_H;                //List の高さ
        
  2. WM_CREATE: で左右二枚の ListBox を Window に貼り付けます。
    実際のサイズは WM_SIZE: で設定されるのですが、チェックも兼ねてここでも計算しています。
    起動時のウインドウのサイズは「幅=800, 高さ=600」に設定して下さい。
    g_hListL をサブクラス化して、境界線のドラッグを捕まえます。
    GetWindowLong() で規定の CALLBACK 関数のエントリを退避します。
    SetWindowLong() で g_hListL の CALLBACK 関数を設定します。
            case WM_CREATE:
                g_LS=g_RS= (800-20)/2;
                g_H= 600-30;
                g_hListL = CreateWindow("LISTBOX", NULL,
                        WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_THICKFRAME,
                        4, 4, g_LS, g_H, hWnd, NULL, g_hInst, NULL);
                g_hListR = CreateWindow("LISTBOX", NULL,
                        WS_CHILD | WS_VISIBLE | WS_VSCROLL,
                        g_LS+8, 4, g_RS, g_H, hWnd, NULL, g_hInst, NULL);
                SetInitialData(g_hListL);
                SetInitialData(g_hListR);
                Org_EWnd= (WNDPROC)GetWindowLong(g_hListL,GWL_WNDPROC);
                SetWindowLong(g_hListL,GWL_WNDPROC,(LONG)MySubProc);
                break;
        
  3. Window のサイズが変更されたときや、中央の境界がドラッグされたときは、ListBox のサイズを変更します。
    LOWORD(lp) が Window の幅で、HIWORD(lp) が高さです。
    g_LS が左側の ListBox のサイズで、これに合わせて右側のサイズを計算します。
    左側の ListBox の幅が 80 ピクセル以下にならないように制限してみました。
            case WM_SIZE:
                w= LOWORD(lp);
                h= HIWORD(lp);
                GetWindowRect(g_hListL,&rc);
                g_LS= rc.right-rc.left;
                if (g_LS<80)    g_LS= 80;
                g_RS= (w-20)-g_LS;
                g_H= h-8;
                MoveWindow(g_hListL,4,4,g_LS,g_H,TRUE);
                MoveWindow(g_hListR,g_LS+8,4,g_RS,g_H,TRUE);
                break;
        
  4. g_hListL の CallBack 関数です。
    中央の境界線がドラッグされたとき WM_EXITSIZEMOVE: がポストされてきます。
    g_hWnd にパラメータを設定して WM_SIZE をポストします。
        //★ g_hListL の Call Back Procedure
        LRESULT CALLBACK MySubProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
        {   RECT    rc;
    
            switch (msg)
            {   case WM_EXITSIZEMOVE:
                    GetWindowRect(g_hWnd,&rc);
                    PostMessage(g_hWnd,WM_SIZE,SIZE_RESTORED,
                                ((rc.bottom-rc.top)<<16)|(rc.right-rc.left));
                    return 0L;
            }
            //自分で処理しないものは元のプロシージャにやってもらう
            return(CallWindowProc(Org_EWnd,hWnd,msg,wp,lp));
        }
        
  5. プログラムの終了前に g_hListL の CallBack 関数を元に戻して下さい。
            case WM_DESTROY:
                SetWindowLong(g_hListL,GWL_WNDPROC,(LONG)Org_EWnd);
                PostQuitMessage(0);
                break;
        
  6. 中央の境界線をマウスでドラッグすると、左右の境界が変わります。
    Window サイズを変更すると、どうなるか確かめて下さい。
  7. C# でも同様のプログラムを作成しています。
    超初心者のプログラム入門(C#)から SplitContainer を参照して下さい。

超初心者のプログラム入門(Win32API C++)