Win32 多文档多视图

#include<Windows.h>
#include<tchar.h>
#include"resource.h"


//全局变量
LPSTR g_MainFrame = "主框架";
LPSTR  g_ClientFrame = "客户区框架";
LPSTR g_ChildFrame[] = { "子框架1","子框架2" };

//主窗口和子窗口回调函数,本程序子窗口公用一个子窗口回调函数
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK ChildProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);

//函数执行的入口函数
int WINAPI WinMain(
    _In_         HINSTANCE hInstance,
    _In_opt_  HINSTANCE hPrevInstance,
    _In_         LPSTR lpCmdLine,
    _In_         int nShowCmd)
{

    //1.初始化需要注册的窗口信息
    WNDCLASS MainFrame = { 0 };
    MainFrame.hbrBackground = (HBRUSH)::GetStockObject(GRAY_BRUSH);//背景
    MainFrame.hCursor = ::LoadCursor(NULL, IDC_ARROW);
    MainFrame.hInstance = hInstance;
    MainFrame.lpfnWndProc = WndProc;
    MainFrame.lpszClassName = g_MainFrame;
    MainFrame.lpszMenuName = MAKEINTRESOURCE(IDR_MainFrame);//主菜单ID
    MainFrame.style = CS_VREDRAW | CS_HREDRAW;

    //2.注册MainFrame窗口类
    if (!RegisterClass(&MainFrame))
    {
        MessageBox(NULL, _T("主框架注册失败!"), _T("Error"), MB_OK | MB_ICONERROR);//_T() 需用用到tchar.h头文件
    }

    //附:注册俩个子窗口类,在子窗口中通过类名来调度
    MainFrame.lpfnWndProc = ChildProc;
    MainFrame.lpszClassName = g_ChildFrame[0];
    MainFrame.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH);
    MainFrame.lpszMenuName = MAKEINTRESOURCE(IDR_ChildMenu);//子菜单

    if (!RegisterClass(&MainFrame))
    {
        MessageBox(NULL, _T("子窗口1注册失败!"), _T("Error"), MB_OK | MB_ICONERROR);//_T() 需用用到tchar.h头文件
    }
    
    MainFrame.lpfnWndProc = ChildProc;
    MainFrame.lpszClassName = g_ChildFrame[1];
    MainFrame.hbrBackground = (HBRUSH)::GetStockObject(BLACK_BRUSH);
    MainFrame.lpszMenuName = MAKEINTRESOURCE(IDR_ChildMenu);;

    if (!RegisterClass(&MainFrame))
    {
        MessageBox(NULL, _T("子窗口2注册失败!"), _T("Error"), MB_OK | MB_ICONERROR);//_T() 需用用到tchar.h头文件
    }
    //3.创建窗口    
        HWND mainframe_hwnd;
        mainframe_hwnd= CreateWindow(
            g_MainFrame,
            g_MainFrame,
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT, 
            CW_USEDEFAULT, 
            CW_USEDEFAULT, 
            CW_USEDEFAULT,
            NULL, 
            NULL, 
            hInstance,
            NULL);
        if(!mainframe_hwnd)
            MessageBox(NULL, _T("主框架创建失败!"), _T("Error"), MB_OK | MB_ICONERROR);
    //4.显示窗口
        ShowWindow(mainframe_hwnd, nShowCmd);

    //5.刷新窗口
        UpdateWindow(mainframe_hwnd);

    //6.信息捕获
        MSG mainframe_msg;
        while (::GetMessage(&mainframe_msg, NULL, 0, 0))
        {
            ::TranslateMessage(&mainframe_msg);//TranslateMessage是用来把虚拟键消息转换为字符消息。
            ::DispatchMessage(&mainframe_msg);//消息调度
        }
        return mainframe_msg.wParam;
}


LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    //处理消息
    static  HWND hClient = NULL,hChild=NULL;
    static HINSTANCE hInstance = NULL;
    CLIENTCREATESTRUCT cs = { 0 };
    switch (message)
    {
        /*1.关不窗口时,会收到该消息,PostQuitMessage()像系统表明终止当前线程,没有这个函数的话,窗口不会关闭*/
    case WM_DESTROY:
        PostQuitMessage(0);//用于相应关闭消息,否则线程不会关闭,导致系统阻塞
        return 0;

    case WM_CREATE:     
        
        cs.hWindowMenu =  GetSubMenu(GetMenu(hwnd), 10);
        cs.idFirstChild = 10;//第一个子窗口与之关联的菜单项ID
        hInstance = GetModuleHandle(NULL);
        hClient = CreateWindow(_T("MDICLIENT"), g_ClientFrame, WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,
            0, 0,100,100,
            hwnd, (HMENU)IDR_ClientMenu, hInstance, &cs);//第一个参数为MDICLIENT
        if (!hClient)
            MessageBox(NULL, _T("客户区创建失败!"), _T("Error"), MB_OK | MB_ICONERROR);
        return 0;
    case WM_COMMAND:
    {
            switch (LOWORD(wParam))
            {
                case ID_MCS1:
                {
                    //创建子窗口
                   MDICREATESTRUCT mcs = { 0 };
                   mcs.x = CW_USEDEFAULT;
                   mcs.y =  CW_USEDEFAULT;
                   mcs.cx =CW_USEDEFAULT;
                   mcs.cy =  CW_USEDEFAULT;//设置子窗口的大小
                    mcs.hOwner = hInstance;
                    mcs.style = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN;//设置了为子窗口WS_CHILD
                    mcs.szClass = g_ChildFrame[0];
                    mcs.szTitle = g_ChildFrame[0];

                    hChild = (HWND)::SendMessage(hClient, WM_MDICREATE,
                        0, (LPARAM)(LPMDICREATESTRUCT)&mcs);
                    if (!hChild)
                            MessageBox(NULL, _T(" 子窗口创建失败!"), _T("Error"), MB_OK | MB_ICONERROR);
                    
                    return 0;
                }
                return 0;
                default: return 0;
            }
        }
    return 0;
    }
    //将不需要处理的消息传递给系统作默认处理
    return DefFrameProc(hwnd, hClient,message, wParam, lParam);
    //return DefWindowProc(hwnd, message, wParam, lParam);在窗口程序中使用
}

LRESULT CALLBACK ChildProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     HINSTANCE hInstance;
    HMENU hMenu, hSubMenu;
    switch (message)
    {
    case WM_CREATE:
    {
        //关联对应的菜单,本程序只拥有一个菜单,如果想每个子文档关联不同的菜单也是可以的,最后需要重绘菜单 DrawMenu
        hInstance = ::GetModuleHandle(NULL);
        hMenu = ::LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MainFrame));
        hSubMenu = ::GetSubMenu(hMenu, 0);
        SendMessage(GetParent(hwnd), WM_MDISETMENU, (WPARAM)hMenu, (LPARAM)hSubMenu);
        
    }
    return 0;

    case WM_QUERYENDSESSION:
    case WM_CLOSE:
    {
        if (IDOK == MessageBox(hwnd, _T("确定?"), _T("关闭"), MB_ICONQUESTION | MB_OK))
        {
            break;
        }
    }
    return 0;

    default:
        break;
    }
    return DefMDIChildProc(hwnd, message, wParam, lParam);
}
 

注意:程序需要添加菜单资源,将本程序加黑的菜单ID更改为添加的菜单ID值。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秘境之眼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值