一点关于最简单的Win32应用程序的研究

这篇博客详细剖析了一个最简单的Win32应用程序的启动流程,包括窗口结构体创建、窗口注册、窗口创建以及一系列WM_消息的处理,展示了Windows程序设计的基本原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这里有一个最简单的Win32应用程序,下面是对他的分析,也就是调用全过程,代码来自Windows程序设计第三版(人民邮电出版社)

#include<windows.h>
// 窗口函数的函数原形
LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
    char szClassName[] = "MainWClass";  
    WNDCLASSEX wndclass;
    // 用描述主窗口的参数填充WNDCLASSEX结构
    wndclass.cbSize = sizeof(wndclass); // 结构的大小
    wndclass.style = CS_HREDRAW|CS_VREDRAW; // 指定如果大小改变就重画
    wndclass.lpfnWndProc = MainWndProc; // 窗口函数指针
    wndclass.cbClsExtra = 0;        // 没有额外的类内存
    wndclass.cbWndExtra = 0;        // 没有额外的窗口内存
    wndclass.hInstance = hInstance;     // 实例句柄 
    wndclass.hIcon = ::LoadIcon(NULL, 
            IDI_APPLICATION);   // 使用预定义图标
    wndclass.hCursor = ::LoadCursor(NULL,
            IDC_ARROW);     // 使用预定义的光标
    wndclass.hbrBackground = (HBRUSH)
        ::GetStockObject(WHITE_BRUSH);  // 使用白色背景画刷
    wndclass.lpszMenuName = NULL;       // 不指定菜单
    wndclass.lpszClassName = szClassName ;  // 窗口类的名称   
    wndclass.hIconSm = NULL;        // 没有类的小图标
    // 注册这个窗口类
    ::RegisterClassEx(&wndclass); 
    // 创建主窗口
    HWND hwnd = ::CreateWindowEx( 
        0,          // dwExStyle,扩展样式   
        szClassName,        // lpClassName,类名           
        "My first Window!", // lpWindowName,标题      
        WS_OVERLAPPEDWINDOW,    // dwStyle,窗口风格 
        CW_USEDEFAULT,      // X,初始 X 坐标        
        CW_USEDEFAULT,      // Y,初始 Y 坐标        
        CW_USEDEFAULT,      // nWidth,宽度            
        CW_USEDEFAULT,      // nHeight,高度           
        NULL,           // hWndParent,父窗口句柄         
        NULL,           // hMenu,菜单句柄       
        hInstance,      // hlnstance,程序实例句柄     
        NULL) ;         // lpParam,用户数据         
    if(hwnd == NULL)
    {
        ::MessageBox(NULL, "创建窗口出错!", "error", MB_OK);
        return -1;
    }
    // 显示窗口,刷新窗口客户区
    ::ShowWindow(hwnd, nCmdShow);
    ::UpdateWindow(hwnd);
    // 从消息堆中取出消息
    MSG msg;    
    while(::GetMessage(&msg, NULL, 0, 0))
    {
        // 转化键盘消息
        ::TranslateMessage(&msg);
        // 将消息发送到相应的窗口函数
        ::DispatchMessage(&msg);
    }
    // 当GetMessage返回0时程序结束
    return msg.wParam;
}
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    char szText[] = "最简单的窗口程序!";
    switch (message)
    {       
    case WM_PAINT: // 窗口客户区需要重画
        {
            HDC hdc;
            PAINTSTRUCT ps;
            // 使无效的客户区变的有效,并取得设备环境句柄
            hdc = ::BeginPaint (hwnd, &ps) ;    
            // 显示文字
            ::TextOut(hdc, 10, 10, szText, strlen(szText));
            ::EndPaint(hwnd, &ps);
            return 0;
        }   
    case WM_DESTROY: // 正在销毁窗口
        // 向消息队列投递一个WM_QUIT消息,促使GetMessage函数返回0,结束消息循环
        ::PostQuitMessage(0) ;
        return 0 ;
    }
    // 将我们不处理的消息交给系统做默认处理
    return ::DefWindowProc(hwnd, message, wParam, lParam);
}

以下是其运行日志:
创建窗口结构体
指定结构大小
指定如果大小改变就重画
指定窗口函数指针
指定没有额外的类内存
指定没有额外的窗口内存
指定实例句柄
指定预定义图标
指定预定义的光标
指定白色背景画刷
不指定菜单
指定窗口类的名称
指定没有类的小图标
调用RegisterClassEx
窗口注册完成
创建窗口

MainWndProc()第0次调用

调用Windows的默认消息处理函数DefWindowProc(),消息:
36:WM_GETMINMAXINFO

MainWndProc()第1次调用

调用Windows的默认消息处理函数DefWindowProc(),消息:
129:WM_NCCREATE

MainWndProc()第2次调用

调用Windows的默认消息处理函数DefWindowProc(),消息:
131:WM_NCCALCSIZE

MainWndProc()第3次调用

调用Windows的默认消息处理函数DefWindowProc(),消息:
1:WM_CREATE
窗口创建完成
调用ShowWindow()

MainWndProc()第4次调用

调用Windows的默认消息处理函数DefWindowProc(),消息:
24:WM_SHOWWINDOW

MainWndProc()第5次调用

调用Windows的默认消息处理函数DefWindowProc(),消息:
70:WM_WINDOWPOSCHANGING

MainWndProc()第6次调用

调用Windows的默认消息处理函数DefWindowProc(),消息:
70:WM_WINDOWPOSCHANGING

MainWndProc()第7次调用

调用Windows的默认消息处理函数DefWindowProc(),消息:
28:WM_ACTIVATEAPP

MainWndProc()第8次调用

MainWndProc()第9次调用

调用Windows的默认消息处理函数DefWindowProc(),消息:
127:WM_GETICON

MainWndProc()第10次调用

调用Windows的默认消息处理函数DefWindowProc(),消息:
127:WM_GETICON

MainWndProc()第11次调用

调用Windows的默认消息处理函数DefWindowProc(),消息:
127:WM_GETICON
调用Windows的默认消息处理函数DefWindowProc(),消息:
134:WM_NCACTIVATE

MainWndProc()第12次调用

MainWndProc()第13次调用

MainWndProc()第14次调用

调用Windows的默认消息处理函数DefWindowProc(),消息:
642:WM_IME_NOTIFY
调用Windows的默认消息处理函数DefWindowProc(),消息:
641:WM_IME_SETCONTEXT

MainWndProc()第15次调用

调用Windows的默认消息处理函数DefWindowProc(),消息:
7:PBT_APMRESUMESUSPEND
调用Windows的默认消息处理函数DefWindowProc(),消息:
6:PBT_APMRESUMECRITICAL

MainWndProc()第16次调用

调用Windows的默认消息处理函数DefWindowProc(),消息:
133:WM_NCPAINT

MainWndProc()第17次调用

调用Windows的默认消息处理函数DefWindowProc(),消息:
20:WM_ERASEBKGND

MainWndProc()第18次调用

调用Windows的默认消息处理函数DefWindowProc(),消息:
71:WM_WINDOWPOSCHANGED

MainWndProc()第19次调用

调用Windows的默认消息处理函数DefWindowProc(),消息:
5:WM_SIZE

MainWndProc()第20次调用

调用Windows的默认消息处理函数DefWindowProc(),消息:
3:WM_MOVE
调用UpdateWindow

MainWndProc()第21次调用

创建设备图形句柄
创建画布结构
调用TextOutW
调用EndPaint()
绘画完成
创建MSG实例句柄
调用GetMessgae()

MainWndProc()第21次调用

调用Windows的默认消息处理函数DefWindowProc(),消息:
136:WM_SYNCPAINT

MainWndProc()第22次调用

调用Windows的默认消息处理函数DefWindowProc(),消息:
127:WM_GETICON

MainWndProc()第23次调用

调用Windows的默认消息处理函数DefWindowProc(),消息:
127:WM_GETICON

MainWndProc()第24次调用

调用Windows的默认消息处理函数DefWindowProc(),消息:
127:WM_GETICON
调用TranslateMessage
调用DispatchMessage

MainWndProc()第25次调用

调用Windows的默认消息处理函数DefWindowProc(),消息:
799:WM_DWMNCRENDERINGCHANGED
调用PostQuitMessage()
调用TranslateMessage
调用DispatchMessage

MainWndProc()第26次调用

调用Windows的默认消息处理函数DefWindowProc(),消息:
49338
调用PostQuitMessage()
调用TranslateMessage
调用DispatchMessage
调用PostQuitMessage()
调用TranslateMessage
调用DispatchMessage
调用PostQuitMessage()
WinMain调用结束
从上面的运行日志我们可以看出:
MainWindowsProc函数从创建好窗口之后就被Windows一直调用,而且调用过程及每一步做过什么都可以看的很清楚。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值