win32应用程序创建流程

窗口创建过程


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

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;
}

运行初始结果



posted @ 2016-08-21 16:49  小怪兽&奥特曼  阅读(441)  评论(0编辑  收藏  举报