MFC基础:Windows内部程序运行原理

本文详细介绍了一个简单的Windows程序设计流程,包括窗口类的设计、注册、创建、显示和消息处理等核心步骤,并解释了关键函数和数据结构的作用。

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

#include <windows.h>
#include <stdio.h>


LRESULT CALLBACK WinSunProc(
  HWND hwnd,      // handle to window
  UINT uMsg,      // message identifier
  WPARAM wParam,  // first message parameter
  LPARAM lParam   // second message parameter
);

int WINAPI WinMain(
  HINSTANCE hInstance,      // handle to current instance
  HINSTANCE hPrevInstance,  // handle to previous instance
  LPSTR lpCmdLine,          // command line
  int nCmdShow              // show state
) 
{
    WNDCLASS wndcls;
    wndcls.cbClsExtra=0;
    wndcls.cbWndExtra=0;
    wndcls.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
    wndcls.hCursor=LoadCursor(NULL,IDC_CROSS);
    wndcls.hIcon=LoadIcon(NULL,IDI_ERROR);
    wndcls.hInstance=hInstance;
    wndcls.lpfnWndProc=WinSunProc;//回调函数,自己编写,用于处理消息
    wndcls.lpszClassName="Weixin2003";//窗口类的名字
    wndcls.lpszMenuName=NULL;
    wndcls.style=CS_HREDRAW | CS_VREDRAW;
    RegisterClass(&wndcls);

    HWND hwnd;
    hwnd=CreateWindow("Weixin2003","北京维新科学技术培训中心",WS_OVERLAPPEDWINDOW,
        0,0,600,400,NULL,NULL,hInstance,NULL);

    ShowWindow(hwnd,SW_SHOWNORMAL);
    UpdateWindow(hwnd);

    MSG msg;
    while(GetMessage(&msg,NULL,0,0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return 0;
}

LRESULT CALLBACK WinSunProc(
  HWND hwnd,      // handle to window
  UINT uMsg,      // message identifier
  WPARAM wParam,  // first message parameter
  LPARAM lParam   // second message parameter
)
{
    switch(uMsg)
    {
    case WM_CHAR:
        char szChar[20];
        sprintf(szChar,"char is %d",wParam);
        MessageBox(hwnd,szChar,"weixin",0);
        break;
    case WM_LBUTTONDOWN:
        MessageBox(hwnd,"mouse clicked","weixin",0);
        HDC hdc;
        hdc=GetDC(hwnd);
        TextOut(hdc,0,50,"计算机编程语言培训",strlen("计算机编程语言培训"));
        ReleaseDC(hwnd,hdc);
        break;
    case WM_PAINT:
        HDC hDC;
        PAINTSTRUCT ps;
        hDC=BeginPaint(hwnd,&ps);
        TextOut(hDC,0,0,"维新培训",strlen("维新培训"));
        EndPaint(hwnd,&ps);
        break;
    case WM_CLOSE:
        if(IDYES==MessageBox(hwnd,"是否真的结束?","weixin",MB_YESNO))
        {
            DestroyWindow(hwnd);
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hwnd,uMsg,wParam,lParam);
    }
    return 0;
}

以下是程序解读

typedef struct tagMSG
{
    HWND hwnd;        //窗口句柄(句柄HANDLE:资源标识)
    UINT message;     //UNIT:unsinged int;消息以整型的方式表示
                      //实际中,用大量的宏(WM:window message)来表示,方便记忆
                      //例如:WM_LBUTTONDOWN表示鼠标左键按下,为一个十六进制数
    WPARAM wPaream;   //整数,消息的附加信息,例如:WM_CHAR 表示按下一个字母,其附加信息中的WPARAM为该字母的ASCII
    LPARAM lParam;    //整数,消息的附加信息
    DWORD time;       //WORD:十六位整数,D:double,即32位,表示消息的传递时间
    POINT pt;         //POINT:结构体,点的坐标,表示当消息被投递的时候光标的位置
}MSG, *PMSG;

//WinMain函数,Windows程序入口函数
int WINAPI WinMain(
    HINSTANCE hInstance,   //当前实例句柄,(实例:当前运行的程序)
    HINSTANCE HPreInstance,//先前实例句柄,一般为NULL,不需要
    LPSTR lpCmdLine,       //命令行参数,LP:long pointer,STR :string
    int nCmdShow           //显示状态:最大/小化,隐藏
    );
 //WinMain 函数在程序启动是由操作系统调用,参数也是由操作系统进行赋值

//窗口的创建步骤
//1.设计窗口类;2.注册窗口类;3.创建窗口;4.显示及更新窗口

//1.设计窗口类,对窗口类的各个成员变量进行赋值
typedef struct _WNDCLASS
{
    UINT style;             //窗口类的类型,也是大量的宏定义,以 CS_ 开头
                            //例如:wndcls.style=CS_HREDRAW | CS_VREDRAW
                            //代表当窗口的水平坐标或垂直坐标发生变化时,窗口要发生重画
    WNDPROC lpfnWndProc;    //指定该类型窗口的过程函数,也称回调函数。
                            //当应用程序接受到消息时, 需调用某一函数来处理该消息
                            //这个调用函数的过程由操作系统完成,
                            //但是对消息进行处理的函数的代码要由我们编写
                            //所需要调用的函数就是由lpfnWndProc成员指定的
    int cbClsExtra;         //类附加内存,一般为0
    int cbWndExtra;         //窗口附加内存,一般为0
    HANDLE hInsatance;      //实例句柄
    HICON hIcon;            //图标句柄, 用LoadIcon(HINSTANCE hInstance,LPCTSTR lpIconName)进行赋值
                            //当采用由微软提供的标准图标(如:IDI_ERROR)时,hInstance 为NULL
    HCURSOR hCursor;        //光标句柄,用LoadCursor(HINSTANCE hInstance,LPCTSTR lpCursorName)进行赋值
                            //当采用由微软提供的标准光标(如:IDC_ARROW)时,hInstance 为NULL
    HBRUSH hbrBackground;   //画刷句柄,用GetStockObject(int fnObject),其返回值为画刷、笔等的句柄(HGDIOBJ)
                            //但是和HBRUSH不同,所以要加上强制类型转换,
    LPCTSTR lpszMenuName;   //32位指针,指向常量字符串(CT:const),用于设定菜单的名字,没有为NULL 
    LPCTSTR lpszClassName;  //窗口类的实例的名字
}WNDCLASS;                  //窗口类的名字

//2.注册窗口类
//使用RegisterClass(CONST WNDCLASS *lpWndClass)
//其中lpWndClass为要被注册的窗口类的指针
RegisterClass(&wndclass);
//其中,wndclass为WNDCLASS结构体变量,就是已经定义好的窗口类

//3.创建窗口
HWND hwnd;  //窗口句柄,保存新创建的窗口标识
//创建窗口的函数定义如下:
HWND CreateWindow(
    LPCTSTR lpClassName,    //窗口类的实例的名字,在设计窗口类时已经指定,即lpszClassName
                            //Attention:必须一样,否则不会产生窗口,只会运行程序
                            //因为该名字的窗口类并没有定义
    LPCTSTR lpWindowName,   //窗口的名字,位于窗口左上角
    DWORD dwStyle,          //窗口的类型,(用WS_...表示)注意区别于类的类型
    int x,                  //窗口的水平坐标,一般为CW_USEDEFAULT
    int y,                  //窗口的垂直坐标,左上角为坐标原点,向右为x轴,向下为y轴
    int nWidth,             //窗口的宽度
    int nHeight,            //窗口的高度
    HWND HWndParent,        //父窗口的句柄,没有为NULL
    HMENU hMenu,            //菜单的句柄,没有为NULL
    HINSTANCE hInstance,    //当前实例的句柄
    LPVOID lpParam          //指针,暂时用不上,设为NULL
);


//4.显示窗口
BOOL ShowWindow(            //指定窗口的显示状态
    HWND hWnd,              //句柄,要显示的窗口的句柄
    int nCmdShow            //显示状态,如SW_SHOWMAXIMIZED,最大化显示
);

//5.更新窗口
UpdateWindow(hwnd);         //可有可无

//6.消息循环
MSG msg
while (GetMessage(&msg, NULL, 0, 0))
{
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}
//函数说明:
BOOL GetMessage(
    LPMSG lpMsg,        
    HWND hWnd,          //获取消息的窗口,为NULL时,获取所有窗口的消息
    UINT wMsgFilterMin, //消息的最小值,为0时,返回所有的消息
    UINT wMsgFilterMax  //消息的最大值,为0时,返回所有的消息
);
//返回值:如果没有收到WM_QUIT,返回值非零,否则为零

TranslateMessage()      //转换消息
DispatchMessage()       //将消息传给回调函数

//至此窗口创建的过程基本完成,还缺一个函数,要由我们自己来编写,即回调函数
LRESULT CALLBACK WindoWProc( //CALLBACK会在后面进行介绍
    HWND hwnd,
    UINT uMsg,
    WPARAM wParam,
    LPARAM lParam
);
//以上为窗口过程函数的定义和基本格式,函数的名字可以更改

int MessageBox(
    HWND hWnd,
    LPCTSTR lpText,   //消息显示的文本
    LPCTSTR lpCaption,//标题
    UINT uType        //消息框的类型,如:MB_YESNO,为宏定义
);
//返回值为:IDOK,IDNO,IDYES,IDRETRY等等

HDC :句柄
//DC:Device Context 设备上下文或设别描述表或设备环境,一种数据结构 
//作用:用于应用程序和物理设备之间进行交互,从而提供了应用程序设计的平台无关性
//访问:只能由各种相关的API函数通过HDC访问该结构,如GetDC(hwnd)和ReleaseDC(hwnd,hDC)要搭配使用


BOOL TextOut(
    HDC hDC,
    int nXStart,        //输出文本的开始坐标
    int nYStart,
    LPCTSTR lpString,   //输出的文本内容   
    int cbString        //文本字符数
);

WM_PAINT:窗口重绘;
BeginPaint()和EndPaint()搭配使用,且只能用于相应WM_PAINT的消息响应

HDC BeginPaint(
    HWND hwnd,           //窗口句柄 
    LPPAINTSTRUCT lpPaint//结构体指针,由PAINTSTRUCT定义
);

BOOL DestroyWindow(      //调用函数时会发送WM_DESTROY消息,并销毁窗口,但是它并不负责退出程序,即终止while循环
    HWND hwnd
);

VOID PostQuitMessage(int nExitCode) 
//会发送WM_QUIT消息到消息队列,于是GetMessage得到WM_QUIT

//退出while循环的过程分析:
//1).通过GetMessage得到WM_CLOSE,不是WM_QUIT,返回值非零,循环继续,由DispatchMessage传递给回调函数
//2).选择IDYES——>DestroyWindow,同时发送WM_DESTROY到消息队列中
//3).再次经过步骤1),回到函数收到WM_DESTROY,发送WM_QUIT到消息队列
//4).此时GetMessage收到WM_QUIT,返回值为零,while循环结束,退出WinMain。

消息缺省处理:Default
//DefWindowProc(hwnd,uMsg,wParam,lParam) ,参数与回调函数的参数一致。

对回调函数中 CALLBACK 的解释:
//#define CALLBACK __stdcall   标准调用约定

对于上面的理解,还有两个问题
Question1:窗口的名字和窗口类的名字辨析??
Question2:hWnd 和 hInstanced 有什么区别???

在另外两篇文章中有解释。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值