windows api 创建mdi程序

C语言实现的MDI程序带Tab切换

复制代码
#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include <stdlib.h>

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

// 常量定义
#define IDC_TAB 1001
#define IDC_BUTTON 1002
#define IDM_NEW_WINDOW 40001
#define IDM_CLOSE_WINDOW 40002
#define IDM_CLOSE_ALL 40003
#define IDM_EXIT 40004
#define MAX_CHILD_WINDOWS 50
#define MAX_TITLE_LENGTH 256

// 全局变量
HINSTANCE hInst = NULL;
HWND hwndTab = NULL;
HWND hwndMDIClient = NULL;
HWND childWindows[MAX_CHILD_WINDOWS];
int childWindowCount = 0;
int childCounter = 0;
HFONT hButtonFont = NULL;

// 函数声明
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK MDIChildProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
void CreateMDIChild(HWND hwndParent);
void UpdateTabControl(void);
void OnTabSelectionChanged(void);
int GetTabIndexFromChild(HWND hwndChild);
HWND GetChildFromTabIndex(int index);
void AddChildWindow(HWND hwndChild);
void RemoveChildWindow(HWND hwndChild);
void OnButtonClick(HWND hwndChild);
void UpdateButtonPosition(HWND hwndChild);

// 应用程序入口点
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    // 初始化公共控件
    INITCOMMONCONTROLSEX icex;
    icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
    icex.dwICC = ICC_TAB_CLASSES;
    InitCommonControlsEx(&icex);
    
    // 注册主窗口类
    WNDCLASSEX wc = {0};
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hInstance;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1);
    wc.lpszClassName = TEXT("MDIMainWindow");
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    
    if (!RegisterClassEx(&wc)) {
        MessageBox(NULL, TEXT("主窗口注册失败!"), TEXT("错误"), MB_ICONERROR);
        return 0;
    }
    
    // 注册MDI子窗口类
    WNDCLASSEX wcChild = {0};
    wcChild.cbSize = sizeof(WNDCLASSEX);
    wcChild.style = CS_HREDRAW | CS_VREDRAW;
    wcChild.lpfnWndProc = MDIChildProc;
    wcChild.hInstance = hInstance;
    wcChild.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcChild.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wcChild.lpszClassName = TEXT("MDIChildWindow");
    wcChild.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wcChild.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    
    if (!RegisterClassEx(&wcChild)) {
        MessageBox(NULL, TEXT("子窗口注册失败!"), TEXT("错误"), MB_ICONERROR);
        return 0;
    }
    
    hInst = hInstance;
    
    // 创建主窗口
    HWND hwnd = CreateWindowEx(
        0,
        TEXT("MDIMainWindow"),
        TEXT("C语言 MDI程序 - Tab控制子窗口 (带按钮)"),
        WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
        CW_USEDEFAULT, CW_USEDEFAULT, 800, 600,
        NULL, NULL, hInstance, NULL
    );
    
    if (!hwnd) {
        MessageBox(NULL, TEXT("主窗口创建失败!"), TEXT("错误"), MB_ICONERROR);
        return 0;
    }
    
    // 显示窗口
    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);
    
    // 消息循环
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
        if (!TranslateMDISysAccel(hwndMDIClient, &msg)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    
    return (int)msg.wParam;
}

// 主窗口过程
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch (msg) {
        case WM_CREATE: {
            // 创建菜单
            HMENU hMenu = CreateMenu();
            HMENU hFileMenu = CreatePopupMenu();
            AppendMenu(hFileMenu, MF_STRING, IDM_NEW_WINDOW, TEXT("新建窗口(&N)"));
            AppendMenu(hFileMenu, MF_STRING, IDM_CLOSE_WINDOW, TEXT("关闭当前窗口(&C)"));
            AppendMenu(hFileMenu, MF_STRING, IDM_CLOSE_ALL, TEXT("关闭所有窗口(&A)"));
            AppendMenu(hFileMenu, MF_SEPARATOR, 0, NULL);
            AppendMenu(hFileMenu, MF_STRING, IDM_EXIT, TEXT("退出(&X)"));
            AppendMenu(hMenu, MF_POPUP, (UINT_PTR)hFileMenu, TEXT("文件(&F)"));
            
            HMENU hWindowMenu = CreatePopupMenu();
            AppendMenu(hWindowMenu, MF_STRING, 50001, TEXT("层叠窗口(&C)"));
            AppendMenu(hWindowMenu, MF_STRING, 50002, TEXT("平铺窗口(&T)"));
            AppendMenu(hWindowMenu, MF_STRING, 50003, TEXT("排列图标(&A)"));
            AppendMenu(hMenu, MF_POPUP, (UINT_PTR)hWindowMenu, TEXT("窗口(&W)"));
            
            SetMenu(hwnd, hMenu);
            
            // 创建Tab控件
            hwndTab = CreateWindowEx(
                0, WC_TABCONTROL, TEXT(""),
                WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | TCS_FOCUSNEVER | TCS_TOOLTIPS,
                0, 0, 0, 0,
                hwnd, (HMENU)IDC_TAB, hInst, NULL
            );
            
            // 设置Tab控件字体
            HFONT hFont = CreateFont(
                16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
                DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
                DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, TEXT("微软雅黑")
            );
            if (hFont) {
                SendMessage(hwndTab, WM_SETFONT, (WPARAM)hFont, TRUE);
            }
            
            // 创建MDI客户端窗口
            CLIENTCREATESTRUCT ccs = {0};
            ccs.hWindowMenu = hWindowMenu;
            ccs.idFirstChild = 50000;
            
            hwndMDIClient = CreateWindowEx(
                WS_EX_CLIENTEDGE,
                TEXT("MDICLIENT"), NULL,
                WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL | WS_VISIBLE,
                0, 0, 0, 0,
                hwnd, NULL, hInst, (LPVOID)&ccs
            );
            
            // 创建按钮字体
            hButtonFont = CreateFont(
                18, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
                DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
                DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, TEXT("微软雅黑")
            );
            
            // 创建初始子窗口
            for (int i = 0; i < 3; i++) {
                CreateMDIChild(hwnd);
            }
            
            return 0;
        }
        
        case WM_SIZE: {
            int width = LOWORD(lParam);
            int height = HIWORD(lParam);
            
            // 调整Tab控件大小
            if (hwndTab) {
                MoveWindow(hwndTab, 0, 0, width, 30, TRUE);
            }
            
            // 调整MDI客户端窗口大小
            if (hwndMDIClient) {
                MoveWindow(hwndMDIClient, 0, 30, width, height - 30, TRUE);
            }
            
            return 0;
        }
        
        case WM_COMMAND: {
            switch (LOWORD(wParam)) {
                case IDM_NEW_WINDOW:
                    CreateMDIChild(hwnd);
                    break;
                    
                case IDM_CLOSE_WINDOW: {
                    HWND hwndActiveChild = (HWND)SendMessage(hwndMDIClient, WM_MDIGETACTIVE, 0, 0);
                    if (hwndActiveChild) {
                        SendMessage(hwndMDIClient, WM_MDIDESTROY, (WPARAM)hwndActiveChild, 0);
                    }
                    break;
                }
                    
                case IDM_CLOSE_ALL:
                    while (childWindowCount > 0) {
                        HWND hwndChild = childWindows[childWindowCount - 1];
                        SendMessage(hwndMDIClient, WM_MDIDESTROY, (WPARAM)hwndChild, 0);
                    }
                    break;
                    
                case IDM_EXIT:
                    DestroyWindow(hwnd);
                    break;
                    
                // 窗口排列命令
                case 50001:  // 层叠窗口
                    SendMessage(hwndMDIClient, WM_MDICASCADE, 0, 0);
                    break;
                    
                case 50002:  // 平铺窗口
                    SendMessage(hwndMDIClient, WM_MDITILE, MDITILE_HORIZONTAL, 0);
                    break;
                    
                case 50003:  // 排列图标
                    SendMessage(hwndMDIClient, WM_MDIICONARRANGE, 0, 0);
                    break;
            }
            return 0;
        }
        
        case WM_NOTIFY: {
            LPNMHDR lpnmh = (LPNMHDR)lParam;
            if (lpnmh->idFrom == IDC_TAB) {
                if (lpnmh->code == TCN_SELCHANGE) {
                    OnTabSelectionChanged();
                }
            }
            return 0;
        }
        
        case WM_DESTROY:
            if (hButtonFont) {
                DeleteObject(hButtonFont);
            }
            PostQuitMessage(0);
            return 0;
    }
    
    return DefFrameProc(hwnd, hwndMDIClient, msg, wParam, lParam);
}

// MDI子窗口过程
LRESULT CALLBACK MDIChildProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    static TCHAR szTitle[MAX_TITLE_LENGTH];
    static HWND hwndButton = NULL;
    
    switch (msg) {
        case WM_CREATE: {
            LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
            lstrcpyn(szTitle, (LPCTSTR)lpcs->lpszName, MAX_TITLE_LENGTH);
            
            // 添加到子窗口数组
            AddChildWindow(hwnd);
            UpdateTabControl();
            return 0;
        }
        
        case WM_MDIACTIVATE: {
            if (lParam == (LPARAM)hwnd) {
                // 窗口被激活,更新Tab选择
                int index = GetTabIndexFromChild(hwnd);
                if (index != -1 && hwndTab) {
                    TabCtrl_SetCurSel(hwndTab, index);
                }
            }
            return 0;
        }
        
        case WM_SIZE: {
            UpdateButtonPosition(hwnd);
            return 0;
        }
        
        case WM_COMMAND: {
            if (LOWORD(wParam) == IDC_BUTTON) {
                OnButtonClick(hwnd);
            }
            return 0;
        }
        
        case WM_DESTROY: {
            // 从子窗口数组中移除
            RemoveChildWindow(hwnd);
            
            // 更新Tab控件
            UpdateTabControl();
            return 0;
        }
    }
    
    return DefMDIChildProc(hwnd, msg, wParam, lParam);
}

// 创建MDI子窗口
void CreateMDIChild(HWND hwndParent) {
    if (childWindowCount >= MAX_CHILD_WINDOWS) {
        MessageBox(NULL, TEXT("已达到最大子窗口数量限制!"), TEXT("警告"), MB_ICONWARNING);
        return;
    }
    
    childCounter++;
    
    TCHAR szTitle[100];
    wsprintf(szTitle, TEXT("子窗口 %d"), childCounter);
    
    MDICREATESTRUCT mcs = {0};
    mcs.szTitle = szTitle;
    mcs.szClass = TEXT("MDIChildWindow");
    mcs.hOwner = hInst;
    mcs.x = mcs.cx = CW_USEDEFAULT;
    mcs.y = mcs.cy = CW_USEDEFAULT;
    mcs.style = WS_OVERLAPPEDWINDOW | WS_VISIBLE;
    
    SendMessage(hwndMDIClient, WM_MDICREATE, 0, (LPARAM)&mcs);
}

// 更新Tab控件
void UpdateTabControl(void) {
    if (!hwndTab) return;
    
    // 清除所有Tab项
    TabCtrl_DeleteAllItems(hwndTab);
    
    // 添加所有子窗口到Tab控件
    TCITEM tie = {0};
    tie.mask = TCIF_TEXT;
    
    for (int i = 0; i < childWindowCount; i++) {
        TCHAR szTitle[MAX_TITLE_LENGTH];
        GetWindowText(childWindows[i], szTitle, MAX_TITLE_LENGTH);
        
        tie.pszText = szTitle;
        TabCtrl_InsertItem(hwndTab, i, &tie);
    }
    
    // 如果有活动的子窗口,设置对应的Tab项为选中状态
    HWND hwndActiveChild = (HWND)SendMessage(hwndMDIClient, WM_MDIGETACTIVE, 0, 0);
    if (hwndActiveChild) {
        int index = GetTabIndexFromChild(hwndActiveChild);
        if (index != -1) {
            TabCtrl_SetCurSel(hwndTab, index);
        }
    }
}

// Tab选择改变时的处理
void OnTabSelectionChanged(void) {
    if (!hwndTab) return;
    
    int selected = TabCtrl_GetCurSel(hwndTab);
    if (selected != -1) {
        HWND hwndChild = GetChildFromTabIndex(selected);
        if (hwndChild) {
            // 激活选中的子窗口
            SendMessage(hwndMDIClient, WM_MDIACTIVATE, (WPARAM)hwndChild, 0);
        }
    }
}

// 通过子窗口句柄获取Tab索引
int GetTabIndexFromChild(HWND hwndChild) {
    for (int i = 0; i < childWindowCount; i++) {
        if (childWindows[i] == hwndChild) {
            return i;
        }
    }
    return -1;
}

// 通过Tab索引获取子窗口句柄
HWND GetChildFromTabIndex(int index) {
    if (index >= 0 && index < childWindowCount) {
        return childWindows[index];
    }
    return NULL;
}

// 添加子窗口到数组
void AddChildWindow(HWND hwndChild) {
    if (childWindowCount < MAX_CHILD_WINDOWS) {
        childWindows[childWindowCount++] = hwndChild;
    }
}

// 从数组中移除子窗口
void RemoveChildWindow(HWND hwndChild) {
    int index = -1;
    
    // 查找窗口在数组中的位置
    for (int i = 0; i < childWindowCount; i++) {
        if (childWindows[i] == hwndChild) {
            index = i;
            break;
        }
    }
    
    if (index != -1) {
        // 将后面的元素向前移动
        for (int i = index; i < childWindowCount - 1; i++) {
            childWindows[i] = childWindows[i + 1];
        }
        childWindowCount--;
    }
}

// 按钮点击事件处理函数
void OnButtonClick(HWND hwndChild) {
    TCHAR szTitle[MAX_TITLE_LENGTH];
    TCHAR szMessage[512];
    int childIndex = GetTabIndexFromChild(hwndChild) + 1;
    
    // 获取窗口标题
    GetWindowText(hwndChild, szTitle, MAX_TITLE_LENGTH);
    
    // 创建消息
    wsprintf(szMessage, 
        TEXT("您点击了子窗口的按钮!\n\n")
        TEXT("窗口标题: %s\n")
        TEXT("窗口编号: %d\n")
        TEXT("总窗口数: %d\n")
        TEXT("窗口句柄: 0x%p"),
        szTitle, childIndex, childWindowCount, hwndChild
    );
    
    // 显示消息框
    MessageBox(hwndChild, szMessage, TEXT("按钮点击事件"), MB_OK | MB_ICONINFORMATION);
}

// 更新按钮位置(在子窗口大小改变时调用)
void UpdateButtonPosition(HWND hwndChild) {
    RECT rcClient;
    GetClientRect(hwndChild, &rcClient);
    
    // 获取或创建静态文本控件
    HWND hwndStatic = GetDlgItem(hwndChild, 1000);
    if (!hwndStatic) {
        TCHAR szTitle[MAX_TITLE_LENGTH];
        GetWindowText(hwndChild, szTitle, MAX_TITLE_LENGTH);
        
        // 创建静态文本
        hwndStatic = CreateWindow(
            TEXT("STATIC"), szTitle,
            WS_CHILD | WS_VISIBLE | SS_CENTER | SS_CENTERIMAGE,
            10, 10, rcClient.right - 20, 100,
            hwndChild, (HMENU)1000, hInst, NULL
        );
        
        // 设置字体
        HFONT hFont = CreateFont(
            24, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
            DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
            DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, TEXT("微软雅黑")
        );
        if (hFont) {
            SendMessage(hwndStatic, WM_SETFONT, (WPARAM)hFont, TRUE);
        }
    } else {
        MoveWindow(hwndStatic, 10, 10, rcClient.right - 20, 100, TRUE);
    }
    
    // 获取或创建按钮
    HWND hwndButton = GetDlgItem(hwndChild, IDC_BUTTON);
    if (!hwndButton) {
        // 创建按钮
        hwndButton = CreateWindow(
            TEXT("BUTTON"), TEXT("点击我!"),
            WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP,
            0, 0, 0, 0,
            hwndChild, (HMENU)IDC_BUTTON, hInst, NULL
        );
        
        // 设置按钮字体
        if (hButtonFont) {
            SendMessage(hwndButton, WM_SETFONT, (WPARAM)hButtonFont, TRUE);
        }
    }
    
    // 计算按钮位置(在静态文本下方)
    int buttonWidth = 200;
    int buttonHeight = 50;
    int buttonX = (rcClient.right - buttonWidth) / 2;
    int buttonY = 120;  // 在静态文本下方
    
    MoveWindow(hwndButton, buttonX, buttonY, buttonWidth, buttonHeight, TRUE);
}

c++

MDI程序带Tab切换

cpp 复制代码
#include <windows.h>
#include <commctrl.h>
#include <vector>
#include <string>

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

// 常量定义
#define IDC_TAB 1001
#define IDM_NEW_WINDOW 40001
#define IDM_CLOSE_WINDOW 40002
#define IDM_CLOSE_ALL 40003
#define IDM_EXIT 40004

// 全局变量
HINSTANCE hInst;
HWND hwndTab = NULL;
HWND hwndMDIClient = NULL;
std::vector<HWND> childWindows;
int childCounter = 0;

// 函数声明
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK MDIChildProc(HWND, UINT, WPARAM, LPARAM);
void CreateMDIChild(HWND hwndParent);
void UpdateTabControl();
void OnTabSelectionChanged();
int GetTabIndexFromChild(HWND hwndChild);
HWND GetChildFromTabIndex(int index);

// 应用程序入口点
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {
    // 初始化公共控件
    INITCOMMONCONTROLSEX icex;
    icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
    icex.dwICC = ICC_TAB_CLASSES;
    InitCommonControlsEx(&icex);
    
    // 注册主窗口类
    WNDCLASSEX wc = {};
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hInstance;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1);
    wc.lpszClassName = L"MDIMainWindow";
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    
    if (!RegisterClassEx(&wc)) {
        MessageBox(NULL, L"主窗口注册失败!", L"错误", MB_ICONERROR);
        return 0;
    }
    
    // 注册MDI子窗口类
    WNDCLASSEX wcChild = {};
    wcChild.cbSize = sizeof(WNDCLASSEX);
    wcChild.style = CS_HREDRAW | CS_VREDRAW;
    wcChild.lpfnWndProc = MDIChildProc;
    wcChild.hInstance = hInstance;
    wcChild.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcChild.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wcChild.lpszClassName = L"MDIChildWindow";
    wcChild.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wcChild.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    
    if (!RegisterClassEx(&wcChild)) {
        MessageBox(NULL, L"子窗口注册失败!", L"错误", MB_ICONERROR);
        return 0;
    }
    
    hInst = hInstance;
    
    // 创建主窗口
    HWND hwnd = CreateWindowEx(
        0,
        L"MDIMainWindow",
        L"MDI程序 - Tab控制子窗口",
        WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
        CW_USEDEFAULT, CW_USEDEFAULT, 800, 600,
        NULL, NULL, hInstance, NULL
    );
    
    if (!hwnd) {
        MessageBox(NULL, L"主窗口创建失败!", L"错误", MB_ICONERROR);
        return 0;
    }
    
    // 显示窗口
    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);
    
    // 消息循环
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
        if (!TranslateMDISysAccel(hwndMDIClient, &msg)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    
    return (int)msg.wParam;
}

// 主窗口过程
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch (msg) {
        case WM_CREATE: {
            // 创建菜单
            HMENU hMenu = CreateMenu();
            HMENU hFileMenu = CreatePopupMenu();
            AppendMenu(hFileMenu, MF_STRING, IDM_NEW_WINDOW, L"新建窗口(&N)");
            AppendMenu(hFileMenu, MF_STRING, IDM_CLOSE_WINDOW, L"关闭当前窗口(&C)");
            AppendMenu(hFileMenu, MF_STRING, IDM_CLOSE_ALL, L"关闭所有窗口(&A)");
            AppendMenu(hFileMenu, MF_SEPARATOR, 0, NULL);
            AppendMenu(hFileMenu, MF_STRING, IDM_EXIT, L"退出(&X)");
            AppendMenu(hMenu, MF_POPUP, (UINT_PTR)hFileMenu, L"文件(&F)");
            
            SetMenu(hwnd, hMenu);
            
            // 创建Tab控件
            hwndTab = CreateWindowEx(
                0, WC_TABCONTROL, L"",
                WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | TCS_FOCUSNEVER | TCS_FIXEDWIDTH | TCS_TOOLTIPS,
                0, 0, 0, 0,
                hwnd, (HMENU)IDC_TAB, hInst, NULL
            );
            
            // 设置Tab控件字体
            HFONT hFont = CreateFont(
                16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
                DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
                DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, L"微软雅黑"
            );
            if (hFont) {
                SendMessage(hwndTab, WM_SETFONT, (WPARAM)hFont, TRUE);
            }
            
            // 创建MDI客户端窗口
            CLIENTCREATESTRUCT ccs = {};
            ccs.hWindowMenu = NULL;
            ccs.idFirstChild = 50000;
            
            hwndMDIClient = CreateWindowEx(
                WS_EX_CLIENTEDGE,
                L"MDICLIENT", NULL,
                WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL | WS_VISIBLE,
                0, 0, 0, 0,
                hwnd, NULL, hInst, (LPVOID)&ccs
            );
            
            // 创建几个初始子窗口
            for (int i = 0; i < 3; i++) {
                CreateMDIChild(hwnd);
            }
            
            return 0;
        }
        
        case WM_SIZE: {
            int width = LOWORD(lParam);
            int height = HIWORD(lParam);
            
            // 调整Tab控件大小
            MoveWindow(hwndTab, 0, 0, width, 30, TRUE);
            
            // 调整MDI客户端窗口大小
            MoveWindow(hwndMDIClient, 0, 30, width, height - 30, TRUE);
            
            return 0;
        }
        
        case WM_COMMAND: {
            switch (LOWORD(wParam)) {
                case IDM_NEW_WINDOW:
                    CreateMDIChild(hwnd);
                    break;
                    
                case IDM_CLOSE_WINDOW: {
                    HWND hwndActiveChild = (HWND)SendMessage(hwndMDIClient, WM_MDIGETACTIVE, 0, 0);
                    if (hwndActiveChild) {
                        SendMessage(hwndMDIClient, WM_MDIDESTROY, (WPARAM)hwndActiveChild, 0);
                    }
                    break;
                }
                    
                case IDM_CLOSE_ALL:
                    while (!childWindows.empty()) {
                        HWND hwndChild = childWindows.back();
                        SendMessage(hwndMDIClient, WM_MDIDESTROY, (WPARAM)hwndChild, 0);
                    }
                    break;
                    
                case IDM_EXIT:
                    DestroyWindow(hwnd);
                    break;
            }
            return 0;
        }
        
        case WM_NOTIFY: {
            LPNMHDR lpnmh = (LPNMHDR)lParam;
            if (lpnmh->idFrom == IDC_TAB) {
                if (lpnmh->code == TCN_SELCHANGE) {
                    OnTabSelectionChanged();
                }
            }
            return 0;
        }
        
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
    }
    
    return DefFrameProc(hwnd, hwndMDIClient, msg, wParam, lParam);
}

// MDI子窗口过程
LRESULT CALLBACK MDIChildProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    static wchar_t szTitle[256];
    
    switch (msg) {
        case WM_CREATE: {
            LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
            lstrcpyn(szTitle, (LPCWSTR)lpcs->lpszName, 256);
            
            // 添加到子窗口列表
            childWindows.push_back(hwnd);
            UpdateTabControl();
            return 0;
        }
        
        case WM_MDIACTIVATE: {
            if (lParam == (LPARAM)hwnd) {
                // 窗口被激活,更新Tab选择
                int index = GetTabIndexFromChild(hwnd);
                if (index != -1 && hwndTab) {
                    TabCtrl_SetCurSel(hwndTab, index);
                }
            }
            return 0;
        }
        
        case WM_SIZE: {
            RECT rcClient;
            GetClientRect(hwnd, &rcClient);
            
            // 创建或更新子窗口中的控件
            HWND hwndStatic = GetDlgItem(hwnd, 1000);
            if (!hwndStatic) {
                hwndStatic = CreateWindow(
                    L"STATIC", szTitle,
                    WS_CHILD | WS_VISIBLE | SS_CENTER | SS_CENTERIMAGE,
                    10, 10, rcClient.right - 20, rcClient.bottom - 20,
                    hwnd, (HMENU)1000, hInst, NULL
                );
                
                // 设置字体
                HFONT hFont = CreateFont(
                    24, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
                    DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
                    DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, L"微软雅黑"
                );
                if (hFont) {
                    SendMessage(hwndStatic, WM_SETFONT, (WPARAM)hFont, TRUE);
                }
            } else {
                MoveWindow(hwndStatic, 10, 10, rcClient.right - 20, rcClient.bottom - 20, TRUE);
            }
            return 0;
        }
        
        case WM_DESTROY: {
            // 从子窗口列表中移除
            auto it = std::find(childWindows.begin(), childWindows.end(), hwnd);
            if (it != childWindows.end()) {
                childWindows.erase(it);
            }
            
            // 更新Tab控件
            UpdateTabControl();
            return 0;
        }
    }
    
    return DefMDIChildProc(hwnd, msg, wParam, lParam);
}

// 创建MDI子窗口
void CreateMDIChild(HWND hwndParent) {
    childCounter++;
    
    wchar_t szTitle[100];
    wsprintf(szTitle, L"子窗口 %d", childCounter);
    
    MDICREATESTRUCT mcs = {};
    mcs.szTitle = szTitle;
    mcs.szClass = L"MDIChildWindow";
    mcs.hOwner = hInst;
    mcs.x = mcs.cx = CW_USEDEFAULT;
    mcs.y = mcs.cy = CW_USEDEFAULT;
    mcs.style = WS_OVERLAPPEDWINDOW | WS_VISIBLE;
    
    SendMessage(hwndMDIClient, WM_MDICREATE, 0, (LPARAM)&mcs);
}

// 更新Tab控件
void UpdateTabControl() {
    if (!hwndTab) return;
    
    // 清除所有Tab项
    TabCtrl_DeleteAllItems(hwndTab);
    
    // 添加所有子窗口到Tab控件
    TCITEM tie = {};
    tie.mask = TCIF_TEXT;
    
    for (size_t i = 0; i < childWindows.size(); i++) {
        wchar_t szTitle[256];
        GetWindowText(childWindows[i], szTitle, 256);
        
        tie.pszText = szTitle;
        TabCtrl_InsertItem(hwndTab, i, &tie);
    }
    
    // 如果有活动的子窗口,设置对应的Tab项为选中状态
    HWND hwndActiveChild = (HWND)SendMessage(hwndMDIClient, WM_MDIGETACTIVE, 0, 0);
    if (hwndActiveChild) {
        int index = GetTabIndexFromChild(hwndActiveChild);
        if (index != -1) {
            TabCtrl_SetCurSel(hwndTab, index);
        }
    }
}

// Tab选择改变时的处理
void OnTabSelectionChanged() {
    if (!hwndTab) return;
    
    int selected = TabCtrl_GetCurSel(hwndTab);
    if (selected != -1) {
        HWND hwndChild = GetChildFromTabIndex(selected);
        if (hwndChild) {
            // 激活选中的子窗口
            SendMessage(hwndMDIClient, WM_MDIACTIVATE, (WPARAM)hwndChild, 0);
        }
    }
}

// 通过子窗口句柄获取Tab索引
int GetTabIndexFromChild(HWND hwndChild) {
    for (size_t i = 0; i < childWindows.size(); i++) {
        if (childWindows[i] == hwndChild) {
            return (int)i;
        }
    }
    return -1;
}

// 通过Tab索引获取子窗口句柄
HWND GetChildFromTabIndex(int index) {
    if (index >= 0 && index < (int)childWindows.size()) {
        return childWindows[index];
    }
    return NULL;
}
相关推荐
JERRY. LIU2 小时前
PV 光电(光伏技术)
单片机·嵌入式硬件
Traced back2 小时前
三层架构的补充
windows·架构
破晓单片机2 小时前
STM32单片机分享:智能洗碗机系统
stm32·单片机·嵌入式硬件
首席拯救HMI官2 小时前
【拯救HMI】AR技术与HMI融合:工业现场的可视化新范式
网络·stm32·单片机·网络协议·ar·设计规范
List<String> error_P9 小时前
STM32 Systick定时器介绍
stm32·定时器·systick
蓑衣客VS索尼克9 小时前
STM32G4针对串口通信异常的操作
stm32·单片机·嵌入式硬件
小康小小涵10 小时前
STM32F103RCT6编写iNav1.7.3飞控固件底层开发
stm32·单片机·嵌入式硬件
爱潜水的小L14 小时前
自学嵌入式day49,arm led、蜂鸣器和bsp
arm开发·单片机·嵌入式硬件
物联网牛七七15 小时前
stm32内核寄存器和外设寄存器
stm32·单片机·嵌入式硬件