欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

win32应用程序创建流程(消息处理)

程序员文章站 2024-03-01 13:17:40
...

窗口创建过程

 

创建一个完整的窗口,需要经过下面几个操作步骤:

1.编写WinMain函数(可以查看MSDN)。

2.设计窗口类(WNDCLASS)。

3.注册窗口类。

4.创建窗口。

5.显示并更新窗口。

6.编写消息循环。

7.编程窗口过程函数。

 

编写WinMain函数

 

WinMain是Windows程序的入口点函数,当操作系统启动一个程序时,它就调用该程序的WinMain函数。它和DOS程序的入口点函数main是一样的作用。

WinMain函数的原型声明如下:

 

int WINAPI WinMain(HINSTANCE hInstance,   
                   HINSTANCE hPrevInstance, 
                   LPWSTR lpCmdLine,   
                   int nShowCmd
                   ); 

参数说明:

  • hInstance 表示该程序当前运行的实例句柄,这是一个数值,操作系统会为每个运行中的实例分配句柄值。
  • hPrevInstance 当前实例的前一个句柄的实例。
  • lpCmdLine 指定给应用程序的命令行参数。
  • nShowCmd 指定程序的窗口应该如何显示。

 

设计窗口类

 

一个完整的窗口类具有许多特征,包括光标(鼠标进入该窗口时的形状)、图标、背景颜色等,在创建一个窗口前,需要对一个窗口进行设计,在windows中,窗口的特征有WNDCLASS结构体来定义,WNDCLASS结构体的定义如下:

 

typedef struct 
{
    UINT style;             //这一类型窗口的样式
    WNDPROC lpfnWndProc;    //指向窗口过程的函数指针
    int cbClsExtra;         //类附加内存
    int cbWndExtra;         //窗口附加内存
    HINSTANCE hInstance;    //实例句柄
    HICON hIcon;            //窗口类的图标句柄
    HCURSOR hCursor;        //窗口类的光标句柄
    HBRUSH hbrBackground;   //窗口类的背景    
    LPCTSTR lpszMenuName;   //菜单名字
    LPCTSTR lpszClassName;  //窗口类名字
} WNDCLASS;

 

 

注册窗口

 

设计完窗口类后,需要调用RegisterClass函数对其注册,注册成功后,才可以创建该类型的窗口。函数声明如下:

 

ATOM RegisterClass(const WNDCLASS* lpWndClass); 

 

创建窗口

 

设计好窗口类并进行注册成功之后,就可以利用CreateWindow函数产生这种类型的窗口了,其函数声明如下:

 

HWND CreateWindow(LPCTSTR lpClassName,  //指定窗口类的名称,需要和WNDCLASS的className一样。
                  LPCTSTR lpWindowName, //窗口的名字
                  DWORD dwStyle,   		//创建的窗口样式
                  int x,   				//窗口左上角的x坐标
                  int y,   				//窗口左上角的y坐标
                  int nWidth,   		//窗口宽度
                  int nHeight, 			//窗口高度
                  HWND hWndParent,   	//父窗口句柄
                  HMENU hMenu,   		//窗口菜单的句柄
                  HANDLE hInstance,   	//应用程序句柄
                  PVOID lpParam ); 		//附件参数,多文档窗口为CLIENTCREATESTRUCT结构体,其余多是NULL

 

显示窗口

 

 

窗口创建成功之后,我们要让它显示出来,调用函数ShowWindow来显示窗口,函数原型如下:

 

BOOL ShowWindow(HWND hWnd,   int nCmdShow);

nCmdShow指定了窗口显示的状态,具体窗口状态可以查看MSDN

 

 

更新窗口

 

被调用ShowWindow函数之后,我们需要紧接调用UpdateWindow来刷新窗口。UpdateWindow函数声明如下:

 

BOOL UpdateWindow(HWND hWnd// handle to window);

其参数是创建成功后的窗口句柄,UpdateWindow函数通过发送一个WM_PAINT消息来刷新窗口,UpdateWindow将WM_PAINT消息直接发送给了窗口过程函数进行消息处理,而没有放到消息队列中去。

 

 

消息循环

 

在创建窗口、显示窗口、更新窗口后,我们需要编写一个消息循环,不断地从消息队列中取出消息,并进行响应。获取消息可以调用GetMessage()函数,消息循环常见代码如下:

 

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

更多内容见“windows消息处理机制”。

 

编程窗口过程函数

 

在完成上述步骤后,剩下的工作主要是编写一个窗口过程函数,用于处理发送给窗口的消息。一个Windows应用程序的主要代码部分就隐藏在窗口过程,其函数声明如下:

 

LRESULT CALLBACK WindowProc(HWND hwnd,
                            UINT uMsg,
                            WPARAM wParam,
                            LPARAM lParam
                            );

窗口过程函数的名字是可随便命名的,但函数定义的形式必须和上述声明保持一致。WindowProc函数的4个参数分别对应消息的窗口句柄。消息代码、消息代码的两个附加参数。

一个程序可以有多个窗口,窗口过程函数的hwnd就标识了接收消息的特定窗口。在窗口过程函数内部使用switch/case语句来确定窗口过程接收消息类型以及消息的处理。例如:

 

 

//编写窗口过程函数
LRESULT CALLBACK WindProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_CHAR:
        {
            char szMsg[20] = {0};
            sprintf_s(szMsg,"char code is %d", wParam);
            MessageBox(hWnd,szMsg, "char", 0);
            break;
        }
    case WM_PAINT:
			...
	case WM_CLOSE:
			...
	case WM_DESTROY:
			...
    default:    
        return DefWindowProc(hWnd,uMsg,wParam,lParam);
    }
}

 

 

完整代码

#include <Windows.h>
#include <stdio.h>

//窗口过程函数声明
LRESULT CALLBACK WndProcess(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

/****************************************************************
*函数名称:WinMain
*功    能:winddow应用程序入口
*作    者:Jin
*日    期:2016年8月10日
****************************************************************/
int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,
                   int nCmdShow
                   )
{

    //设计窗口类
    WNDCLASS wndcls;
    wndcls.cbClsExtra       = 0;
    wndcls.cbWndExtra       = 0;
    wndcls.hbrBackground    = (HBRUSH)GetStockObject(BLACK_BRUSH);
    wndcls.hCursor          = LoadCursor(NULL, IDC_ARROW);
    wndcls.hIcon            = LoadIcon(NULL, IDI_APPLICATION);
    wndcls.hInstance        = hInstance;
    wndcls.lpfnWndProc      = WndProcess;
    wndcls.lpszClassName    = "Jin";
    wndcls.lpszMenuName     = NULL;
    //垂直和横轴大小发生变化,窗口重绘
    wndcls.style            = CS_HREDRAW | CS_VREDRAW; 
    
    //注册窗口
    RegisterClass(&wndcls);
    HWND hWnd = NULL;

    //创建窗口
    hWnd = CreateWindow("Jin", "Jin Win32", WS_OVERLAPPEDWINDOW, 0, 0,\
                        600, 400, NULL, NULL, hInstance, NULL);

    //显示&刷新
    ShowWindow(hWnd,SW_SHOWNORMAL);
    UpdateWindow(hWnd);

    //定义消息循环
    MSG msgInfo;
    while (GetMessage(&msgInfo, NULL/*所有窗口*/, 0, 0))
    {
        TranslateMessage(&msgInfo); //换字符消息
        DispatchMessage(&msgInfo);  //分发消息
    }
    
    return msgInfo.wParam;
}

/****************************************************************
*函数名称:WndProcess
*功    能:窗口过程消对应的消息处理
*作    者:Jin
*日    期:2016年8月21日
****************************************************************/
LRESULT CALLBACK WndProcess(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_CHAR:
        {
            char szChar[20] = {0};
            sprintf_s(szChar,"char code is %d", wParam);
            MessageBox(hWnd,szChar, "char", MB_OK);
            break;
        }
    case  WM_LBUTTONDOWN:
        {
            MessageBox(hWnd, "mouse clicked", "mouse", MB_OK);
            HDC hDc;
            hDc = GetDC(hWnd);
            TextOut(hDc, 0, 50, "hello world", strlen("hello world"));
            ReleaseDC(hWnd,hDc);
            break;
        }
    case WM_PAINT:
        {
            HDC hDC;
            PAINTSTRUCT ps;
            hDC = BeginPaint(hWnd, &ps);
            TextOut(hDC,0,0,"CSDN", strlen("CSDN"));
            EndPaint(hWnd, &ps);
            break;
        }
    case  WM_CLOSE:
        {
            if (IDYES == MessageBox(hWnd, "are you sure to exit?", "message", MB_YESNO))
            {
                DestroyWindow(hWnd);//窗口消失,产生WM_DESTROY新消息
            }
            break;
        }
    case  WM_DESTROY:
        {
            PostQuitMessage(0);//产生WM_QUIT消息,然后程序退出
            break;
        }
    default:    
        return DefWindowProc(hWnd,uMsg,wParam,lParam);
    }

    return 0;
}

运行初始结果

win32应用程序创建流程(消息处理)