概要


このプログラムは、分割ウィンドウを作成するものです。
分割ウィンドウはメインウィンドウのWM_CREATEで、左側はサイズ変更境界線付きの子ウィンドウ、右側は境界線なしの子ウィンドウを作成しています。
メインウィンドウのサイズが変更された場合は、WM_SIZEの中で、左側と右側の子ウィンドウサイズを変更します。分割線を移動させた場合は、左側の子ウィンドウのWM_SIZEで右側の子ウィンドウの大きさを調整しています。なお、親ウィンドウのサイズが変更された場合は、親ウィンドウで左右の子ウィンドウのサイズの調整を行うので、ParentSizeChangeをTRUEにセットし、左側の子ウィンドウでは右側の子ウィンドウの大きさの調整は行わないようにしています。なお、分割線を左側に移動させすぎると左側の子ウィンドウの横幅が0になってしまい、親ウィンドウの境界線と区別がつかなくなり、分割線を移動させることができなくなります。よって、左側の子ウィンドウのWM_GETMINMAXINFOメッセージを処理して、左側の子ウィンドウの横幅が境界線*2+スクロールバーの矢印以下の幅にならないように制限しています。
子ウィンドウの大きさ等を管理する変数は、親ウィンドウの中で動的に管理するようにしています。(グローバル変数は使わない)よって、サンプルでは2つの親ウィンドウのプロシージャーを共用しています。子ウィンドウ作成時には、親ウィンドウで動的に作成された変数を引き渡し、子ウィンドウ内の動的メモリに保存しています。

ソースと実行ファイルのダウンロード

ソース

//  横分割ウィンドウのサンプル

#include <windows.h>
#include <commctrl.h>
#include <tchar.h>

//      フレーム管理用の構造体

struct FreamWindowClass{
        int all_x, all_y;       //      ウィンドウ全体の大きさ
        int left_x, left_y;     //      左側のウィンドウの大きさ
        int right_x, right_y;   //      右側のウィンドウの大きさ
        int frame;      //      フレームの幅
    HWND hLeftChild;    //      左側のウィンドウハンドル
        HWND hRightChild;       //      右側のウィンドウハンドル
        BOOL ParentSizeChange;  //      親ウィンドウでWM_SIZEが呼び出されたときTRUEにセットされる。
        FreamWindowClass(){
                left_x=200;
                ParentSizeChange=FALSE;

        }
};

#ifdef _WIN64
        #define TRANS_PTR_CAST(p) ((LONG PTR)(p))
#else
        #define TRANS_PTR_CAST(p) ((LONG)(LONG_PTR)(p))
#endif


LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK LeftChildProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK RightChildProc(HWND, UINT, WPARAM, LPARAM);
BOOL InitApp(HINSTANCE, WNDPROC, LPCTSTR,int cbWndExtra=0);
BOOL InitInstance(HINSTANCE, int );

TCHAR szClassName[] = TEXT("fream_window");

int WINAPI _tWinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst,
                  TCHAR* lpsCmdLine, int nCmdShow){
    MSG msg;
    
    if (!InitApp(hCurInst, WndProc, szClassName,sizeof(FreamWindowClass*)))
        return FALSE;
    if (!InitInstance(hCurInst, nCmdShow)) 
        return FALSE;
    if (!InitInstance(hCurInst, nCmdShow)) 
        return FALSE;
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return (int)msg.wParam;
}


// メインウィンドウプロシージャ

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp){
    HINSTANCE hInst;
    RECT rc;
    switch (msg) {
        case WM_CREATE:{
                        FreamWindowClass* fwc=new FreamWindowClass;
                        SetWindowLongPtr(hWnd,0,TRANS_PTR_CAST(fwc));
            fwc->frame = GetSystemMetrics(SM_CXSIZEFRAME);

            hInst = ((LPCREATESTRUCT)lp)->hInstance;
            GetWindowRect(hWnd, &rc);
            fwc->all_x = rc.right - rc.left;
            fwc->all_y = rc.bottom - rc.top;
            GetClientRect(hWnd, &rc);
            fwc->left_y = rc.bottom + fwc->frame*2;
            TCHAR* szLeftClassName=TEXT("LeftWindow");
            TCHAR* szRightClassName=TEXT("RightWindow");
            InitApp(hInst, LeftChildProc,szLeftClassName,sizeof(FreamWindowClass*) );
            fwc->hLeftChild = CreateWindowEx(WS_EX_CLIENTEDGE,
                szLeftClassName,
                TEXT(""),
                WS_CHILD | WS_VISIBLE | WS_THICKFRAME,
                -fwc->frame,
                -fwc->frame,
                fwc->left_x,
                fwc->left_y,
                hWnd, 
                (HMENU)1,
                hInst,
                (LPVOID)fwc);
            GetClientRect(hWnd, &rc);
            fwc->right_x = rc.right - fwc->left_x + fwc->frame;
            fwc->right_y = rc.bottom;
            InitApp(hInst, RightChildProc,szRightClassName,sizeof(FreamWindowClass*) );
            fwc->hRightChild = CreateWindow(szRightClassName,
                TEXT(""),
                WS_CHILD | WS_VISIBLE,
                fwc->left_x - fwc->frame,
                0,
                fwc->right_x,
                fwc->right_y,
                hWnd,
                (HMENU)2,
                hInst,
                (LPVOID)fwc);
            break;
                }
                case WM_SIZE:{
                        FreamWindowClass* fwc=(FreamWindowClass*)(LONG_PTR)GetWindowLongPtr(hWnd,0);
                                
            fwc->ParentSizeChange = TRUE;
            GetWindowRect(hWnd, &rc);
            fwc->all_x = rc.right - rc.left;
            if (fwc->all_x <= fwc->left_x)
                fwc->left_x = fwc->all_x - fwc->frame;
            fwc->all_y = rc.bottom - rc.top;
            GetClientRect(hWnd, &rc);
            fwc->left_y = rc.bottom + fwc->frame*2;
            fwc->right_x = rc.right - fwc->left_x + fwc->frame;
            fwc->right_y = rc.bottom;
            
            MoveWindow(fwc->hLeftChild, -fwc->frame, -fwc->frame, fwc->left_x, fwc->left_y, TRUE);
            MoveWindow(fwc->hRightChild, fwc->left_x - fwc->frame , 0, fwc->right_x, fwc->right_y, TRUE);
            fwc->ParentSizeChange = FALSE;
            break;
                }
                case WM_CLOSE:{
                        FreamWindowClass* fwc=(FreamWindowClass*)(LONG_PTR)GetWindowLongPtr(hWnd,0);
                        delete fwc;
                        DestroyWindow(hWnd);
            break;
                }
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return (DefWindowProc(hWnd, msg, wp, lp));
    }
    return 0;
}

//      左側のウィンドウプロシージャー

LRESULT CALLBACK LeftChildProc(HWND hChild, UINT msg, WPARAM wp, LPARAM lp){
    RECT rc;
    HWND hParent;
    switch (msg) {
        case WM_CREATE:{
            FreamWindowClass* fwc = (FreamWindowClass*)((LPCREATESTRUCT)lp)->lpCreateParams;
                        SetWindowLongPtr(hChild,0,TRANS_PTR_CAST(fwc));
            break;
                }
                case WM_GETMINMAXINFO:{
            FreamWindowClass* fwc = (FreamWindowClass*)(LONG_PTR)GetWindowLongPtr(GetParent(hChild),0);
                        LPMINMAXINFO lpmmi;

            lpmmi = (LPMINMAXINFO)lp;
                        lpmmi->ptMinTrackSize.x = fwc->frame * 2+GetSystemMetrics(SM_CXHSCROLL);
            return 0;
                }
                break;
                case WM_SIZE:{
            FreamWindowClass* fwc = (FreamWindowClass*)(LONG_PTR)GetWindowLongPtr(hChild,0);
            if (fwc->ParentSizeChange == FALSE) {
                hParent = GetParent(hChild);
                GetWindowRect(hChild, &rc);
                fwc->left_x = rc.right - rc.left;
                                if(fwc->left_x < fwc->frame)
                                        fwc->left_x=fwc->frame*2;
                fwc->left_y = rc.bottom - rc.top;

                MoveWindow(fwc->hRightChild, fwc->left_x - fwc->frame, 0, fwc->right_x, fwc->right_y, TRUE);

                                GetClientRect(hParent, &rc);
                fwc->right_x =  rc.right- fwc->left_x + fwc->frame;
                fwc->right_y = rc.bottom;
                MoveWindow(fwc->hRightChild, fwc->left_x - fwc->frame, 0, fwc->right_x, fwc->right_y, TRUE);
            }
            break;
                }
        default:
            return (DefWindowProc(hChild, msg, wp, lp));
    }
    return 0;
}

//      右側のウィンドウプロシージャ

LRESULT CALLBACK RightChildProc(HWND hChild, UINT msg, WPARAM wp, LPARAM lp){
    return (DefWindowProc(hChild, msg, wp, lp));
}

//ウィンドウ・クラスの登録

BOOL InitApp(HINSTANCE hInst, WNDPROC fnWndProc, LPCTSTR szClassNm,int cbWndExtra){
    WNDCLASSEX wc;
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = fnWndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = cbWndExtra; //      拡張メモリ取得サイズ
    wc.hInstance = hInst;
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = (TCHAR*)szClassNm;
    wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    return (RegisterClassEx(&wc));
}

//ウィンドウの生成

BOOL InitInstance(HINSTANCE hInst, int nCmdShow){
    HWND hWnd;

    hWnd = CreateWindow(szClassName,
            TEXT("分割ウィンドウサンプル"),
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            NULL,
            NULL,
            hInst,
            NULL);
    if(!hWnd)
        return FALSE;
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);
    return TRUE;
}