现在的位置: 首页 > 综合 > 正文

1_Windows程序运行机制_孙鑫老师VC++教程学习

2018年04月22日 ⁄ 综合 ⁄ 共 2990字 ⁄ 字号 评论关闭

Windows程序运行机制

1. Windows应用程序,OS,计算机硬件相互关系

2. 消息类型数据结构

typedef struct tagMSG
{
    HWND hwnd;
    UINT message;
    WPARAM wParam;
    LPARAM lParam;
    DWORD time;
    Point pt;
}MSG;

hwnd : 将要接受这个消息的窗口的句柄,实际上是窗口的WinProc函数接受这个消息。

message : 消息的类型,如WM_KEYDOWN , WM_CHAR , WM_LBUTTONDOWN 等。

wParam , lParam : 消息的附加参数,如WM_CHAR表键盘一字符按下,但具体哪个字符按下,则需附加信息才能确定。

time : 表示消息发生的时间。

pt : 表信息发生时,鼠标的位置。

3. Windows程序入口函数WinMain

int WINAPI WinMain(
    HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow);

hInstance : 当前窗口实例的句柄。如同一个程序,运行两次,产生两个窗口,则系统将为每个窗口生成不同的实例号。
hPrevInstance : 前一窗口实例的句柄,如同一MFC程序,运行一次产生窗口A1,再运行产生窗口A2,则A2的hPrevInstance将存放A1的hInstance。
lpCmdLine : 向程序传递命令行参数,类似于Win32 Console Application中Main函数中的int argc , char ** argv 。 。。。下面补充VS2008具体设置方法。。。。VC6中是,工程、设置、Debug、。。。
nCmdShow : 表示窗口初始显示时的状态,如最大化,最小化等。
4. 窗口的创建过程
1) 设计一个窗口类 WNDCLASS
typedef struct _WNDCLASS
{
    UINT stype;
    WNDPROC lpfnWndProc;
    int cbClsExtra;
    int cbWndExtra;
    HINSTANCE hInstance;
    HICON hIcon;
    HCURSOR hCursor;
    HBRUSH hbrBackground;
    LPCTSTR lpszMenuName;
    LPCTSTR lpszClassName;
} WNDCLASS , * PWNDCLASS;

style : 所设计窗口的类型 , 如 CS_HREDRAW | CS_VREDRAW 。
lpfnWndProc : 回调函数名 ,在应用程序接受消息时,将自动调用回调函数进行处理,这个调用回调函数的过程由OS进行处理,但用户需要自己在回调函数中确定如何处理消息。
cbClsExtra/cbWndExtra : 分别表示由用户给窗口类、窗口划定额外内存大小。一般可以设置为0,0并非表示不划定大小,而是表示默认大小。
hInstance : 表示该窗口属于哪个应用程序,其中这个实例号表征对应的应用程序。(有待改进)。
hIcon/hCursor : 表示窗口的左上角图标的类型 和 窗口内部鼠标的显示形式。
hbrBackground : 表窗口的背景画刷颜色 。 可以直接赋值,也可以通过GetStockObject()函数获取,注意,此时需要强制类型转换。
lpszMenuName : 当窗口中有菜单项时,用此参数指向菜单。无菜单时,设为NULL。
lpszClassName : 通过以上设置,一个个性化的窗口类便设计完成,此时,需要为这个个性化的窗口类命名,以便在后面程序中为此个性化窗口类实例化。

2) 注册窗口类 RegisterClass
3)创建窗口 CreateWindow
4) 显示、更新窗口 ShowWindow 、UpdateWindow
其中UpdateWindow()可有可无,具体原因,有待补充。

5. 消息循环 MSG

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

OS将为每个应用程序创建一个消息队列。

GetMessage() : 从消息队列中取一条消息。函数返回类型BOOL,当返回TRUE时,将一直进行消息循环,直至返回FALSE。

TranslateMessage() : 转换消息。如当用户按下键盘按键时,将产生WM_KEYDOWN和WM_KEYUP消息,但对于用户来说,需要知道具体按下哪一个键。此时,TranslateMessage()函数将结合消息的wParam和lParam参数,对消息进行转换,转换成WM_CHAR消息。TranslateMessage()函数是从消息队列中取出一条消息,对其转换之后,重新放置回消息队列。

DispatchMessage() : 分派消息。可以理解为,该函数将消息队列所取出并转换了的消息路由给OS,然后OS将调用该窗口实例的消息处理回调函数,从而响应消息。

6. 消息回调函数 WindowProc

在消息回调函数中,我们对感兴趣的消息进行处理。

switch(uMsg)
{
    case WM_PAINT: ...
    case WM_LBUTTONDOWN: ...
    case WM_CLOSE: ...
    case WM_DESTROY: ...
    default:
        return DefaultWindowProc(...);
}

常用消息:

WM_PAINT : 在窗口重绘时,产生此消息。如窗口水平重画、垂直重画、窗口初始显示时等。

WM_CLOSE : 在关闭窗口时,产生此消息。我们可以在回调函数此消息下,进行对话框MessageBox判定,判定是否确定要关闭窗口。如果是,则调用DestroyWindow()函数进行窗口销毁。其中DestroyWindow()函数将发送一个WM_DESTROY消息到消息队列中去。在WM_DESTROY消息个性化中,写上PostQuitMessage()函数,该函数控制程序是否退出。其将投递WM_QUIT消息到消息队列总,当消息队列中GetMessage()函数收到WM_QUIT消息,将终止消息循环,从而结束程序。

从以上过程我们可以看出,如果我们在WM_CLOSE消息下,填入DestroyWindow()函数,而在WM_DESTROY消息下,并不填入PostQuitMessage()函数的话,只是窗口被关闭,程序并未退出,而在后台运行。除非有特殊的目的,一般我们不这样去做。

7. 常用方法及数据结构说明

HDC : 设备上下文句柄。譬如我们需要在程序窗口画一个图形,这必然需要我们与显示设备的驱动程序打交道,而DC可以通过操作系统帮助我们做到这一点。

如在WM_PAINT消息中,如果需要在窗口一直显示些什么东西,就需要获取窗口的HDC,然后通过相关函数,以HDC作为参数,从而进行绘图。

HDC hdc = BeginPaint(...);
...
EndPaint(...);

其中BeginPaint()、EndPaint()要成对出现,并且这两个对HDC进行操作的函数只能用于WM_PAINT消息中,不能用于其他地方获取HDC。

而在其他地方,我们需要使用以下形式进行HDC的获取:

HDC hDC = GetDC(...);
...
ReleaseDC(...);

同样,GetDC()、ReleaseDC()也需要成对出现,并且这两个函数不能用于WM_PAINT消息中获取HDC。

抱歉!评论已关闭.