windows 程序设计 第三章(中)
2013-05-22 23:44
302 查看
今天啥都别说了,分了21个bug,而且有两个新功能要做,我的心哇凉哇凉的了,感叹生不逢时,要是大家伙都还在树上吃香蕉的时候就出生就不用每天忙得跟狗一样写码子了,擦,实在不行摊上个李刚爹也行啊!!
第三章上篇当中,哥说过,第三章主要可以用两句话来展开“创建和显示窗口,接受和处理消息”,并且以创建什么窗口为疑问介绍了WNDCLASS结构变量各个字段的含义。
创建和显示窗口,接受和处理消息”中的创建什么样的窗口讲完了,初始化了WNDCLASS变量之后需要注册,可能有人问,为什么要注册?直接拽过来用不就好了?这他娘的也不怪我,人家就那么设计的,这就相当于,他娘的都是高中生,你学 数理化,人家也学数理化 ,但临高考的时候你不能说你学过数理化都能直接参加高考,丫的要报名啊,自教育局注册一下,就是这个道理,你要让windows知道你要用这个类型创建窗口,RegisterClass(&wndClass);
接下来就该是怎么创建窗口了,CreateWindow。CreateWindw的参数很多,比他娘的WNDCLASS还多一个,WNDCLASS只是指定了窗口的一般样式,在创建窗口到时候你需要指定另外的一些窗口细节,比如窗口的大小了,在桌面上的位置等,HWND hWnd = CreateWindow(className,//窗口类名称
TEXT("title"),//窗口标题
WS_OVERLAPPEDWINOW, //窗口样式
CW_USEDEFAULT, //x坐标
CW_USEDEFAULT, //y坐标
CW_USEDEFAULT, //宽度
CW_USEDEFAULT, //高度
NULL, //父窗口句柄
NULL, //菜单
hInstance, //程序实例
NULL ,
)
最后一个参数说一下,最后一个参数是一个指向一个值得指针,这个值就是CreateWindow产生WM_CREATE消息的时候传递给回调函数的,通过回调函数的lparam参数传递。
好了,窗口创建好了,创建好了只是在系统中创建好了,在内存中存在了,但是跟屏幕没半毛钱关系,因为你只是在系统中注册了,在内存中创建了,你又没搞在屏幕上,所以你要用UpdateWindow,你可以这样理解,UpdateWindow就是通过你在WNDCLASS和CreateWindow中设置的那些值映射到屏幕上屏幕上,在屏幕上无效的区域映射为有效,还有窗口位置,大小,背景色等,UpdateWindow(hWnd)。
映射完了要干嘛?要显示,ShowWindow。首先要指定show哪个window,其次我们知道窗口有最大化,最小化等,所以要指定show成什么样子,所以ShowWindow有两个参数ShowWindow(hWnd,SW_SHOWNORMAL),SW_SHOWNORMAL就是根据CreateWindow中设置的窗口大小和位置显示,我们用的是CW_USEDEFAULT,也就是使用系统默认值,其次还可以用SW_SHOWMAXIMIZED和SW_SHOWMINNOACTIVE表示最大化和只在任务栏显示。
好了,现在是窗口既创建了,又显示了,接着该处理消息了。这个消息其实要说的非常多,所谓的面向事件的处理机制,说白了就是他娘的兵来将挡,水来土掩,你对窗口干了什么,窗口就根据你对它干了啥来处理,比如你丫用鼠标点了它,或者关闭了它,但是我们要清楚一点,你不管对它做了什么,操作系统都会向这个窗口发送你对它干了什么的消息,系统默认处理了一部分消息,但是如果你想搞的不一样,不使用默认处理,那你就需要自己重新处理这些消息。
消息处理之一:在窗口创建的时候,操作系统就会为该窗口生成一个消息队列,记住是队列!先进去先被搞!你在这个窗口上点击鼠标,或者敲键盘等,操作系统都会捕获到你在这个窗口范围内干了这些事,从而生成对应的消息放到你这个窗口的消息队列里。
消息处理之二:除了上面说的,操作系统会捕获消息放到对应窗口的消息队列之外,操作系统还能直接绕过这个队列将一些消息直接发送个窗口处理过程,至于什么是窗口处理过程,下面马上就说。
现在先来看放到消息对列里的消息,要知道你的爪子可能一直在点窗口,所以消息就一直往队列里加,你就需要一直检索队列, 所以需要用while。
MSG msg;
while(GetMessage(&msg, NULL ,0 ,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
MSG:就是个结构体,用来存储获取从队列里获取的消息;
BOOL GetMessage(LPMSG lpMsg,HWND hWnd,UINT wMsgFilterMin,UINT wMsgFilterMax)
lpMsg:指向MSG结构的指针,该结构从线程的消息队列里接收消息信息。
hWnd:取得其消息的窗口的句柄。当其值取NULL时,GetMessage为任何属于调用线程的窗口检索。
wMsgFilterMin:指定被检索的最小消息值的整数。
wMsgFilterMax:指定被检索的最大消息值的整数。
所以在程序中我们用GetMessage(&msg, NULL ,0 ,0),就检索属于该窗口的所有消息。
有人说,都他娘的检索到了,直接发送给窗口过程过程不就行了,不行你检索到的消息还需要处理,比如如果你按键,需要把消息转换成字符,再传给窗口过程处理,就需要用TranslateMessage(&msg);
处理完了就要把这个处理过的消息返回给windows系统,他娘的为啥不给窗口过程? 对呀。good question!,因为窗口过程是操作系统调用的,不是你程序自己调用的,还记得你在WNDCLASS中设置的窗口过程函数了吗?就是向系统表明,在处理这里窗口的消息的时候,系统要调用那个特定的函数来处理,这个函数有特定的格式,下面我们会介绍到,我们在这里就仅需要知道,消息处理完了要用DispatchMessage(&msg)返回给系统,让系统调用窗口过程来处理这个消息。
好了,不管是放到消息队列里,还是直接发送给窗口,都需要有个函数来处理这些消息,这个函数就是传说中的窗口过程函数,也叫回调函数,这个函数不是随便写的,有固定的格式,当然,我指的是返回值和参数名字没什么特殊,可以随便起,操,说的随便起是指符合规范的前提下随便起,我们这里就叫callBackWndProc吧。
这个函数的固定格式为 LRESULT CALLBACK XXX(HWND hWnd, UINT message, WPARAM wparam, LPARAM lparam)
LRESULT :指的是从窗口程序或者回调函数返回的32位值。
CALLBACK :作用跟WINAPI其实是一样的,但是WINAPI一般用于修饰动态链接库中导出函数,CALLBACK仅用于修饰回调函数 。
HWND hWnd, UINT message, WPARAM wparam, LPARAM lparam 这四个参数跟MSG结构中的四个字段是一个含义。
妈的,心情不好,今晚早点睡了,明天写第三章最后一部分---窗口过程函数
到现在为止,进行的代码如下:
第三章上篇当中,哥说过,第三章主要可以用两句话来展开“创建和显示窗口,接受和处理消息”,并且以创建什么窗口为疑问介绍了WNDCLASS结构变量各个字段的含义。
创建和显示窗口,接受和处理消息”中的创建什么样的窗口讲完了,初始化了WNDCLASS变量之后需要注册,可能有人问,为什么要注册?直接拽过来用不就好了?这他娘的也不怪我,人家就那么设计的,这就相当于,他娘的都是高中生,你学 数理化,人家也学数理化 ,但临高考的时候你不能说你学过数理化都能直接参加高考,丫的要报名啊,自教育局注册一下,就是这个道理,你要让windows知道你要用这个类型创建窗口,RegisterClass(&wndClass);
接下来就该是怎么创建窗口了,CreateWindow。CreateWindw的参数很多,比他娘的WNDCLASS还多一个,WNDCLASS只是指定了窗口的一般样式,在创建窗口到时候你需要指定另外的一些窗口细节,比如窗口的大小了,在桌面上的位置等,HWND hWnd = CreateWindow(className,//窗口类名称
TEXT("title"),//窗口标题
WS_OVERLAPPEDWINOW, //窗口样式
CW_USEDEFAULT, //x坐标
CW_USEDEFAULT, //y坐标
CW_USEDEFAULT, //宽度
CW_USEDEFAULT, //高度
NULL, //父窗口句柄
NULL, //菜单
hInstance, //程序实例
NULL ,
)
最后一个参数说一下,最后一个参数是一个指向一个值得指针,这个值就是CreateWindow产生WM_CREATE消息的时候传递给回调函数的,通过回调函数的lparam参数传递。
好了,窗口创建好了,创建好了只是在系统中创建好了,在内存中存在了,但是跟屏幕没半毛钱关系,因为你只是在系统中注册了,在内存中创建了,你又没搞在屏幕上,所以你要用UpdateWindow,你可以这样理解,UpdateWindow就是通过你在WNDCLASS和CreateWindow中设置的那些值映射到屏幕上屏幕上,在屏幕上无效的区域映射为有效,还有窗口位置,大小,背景色等,UpdateWindow(hWnd)。
映射完了要干嘛?要显示,ShowWindow。首先要指定show哪个window,其次我们知道窗口有最大化,最小化等,所以要指定show成什么样子,所以ShowWindow有两个参数ShowWindow(hWnd,SW_SHOWNORMAL),SW_SHOWNORMAL就是根据CreateWindow中设置的窗口大小和位置显示,我们用的是CW_USEDEFAULT,也就是使用系统默认值,其次还可以用SW_SHOWMAXIMIZED和SW_SHOWMINNOACTIVE表示最大化和只在任务栏显示。
好了,现在是窗口既创建了,又显示了,接着该处理消息了。这个消息其实要说的非常多,所谓的面向事件的处理机制,说白了就是他娘的兵来将挡,水来土掩,你对窗口干了什么,窗口就根据你对它干了啥来处理,比如你丫用鼠标点了它,或者关闭了它,但是我们要清楚一点,你不管对它做了什么,操作系统都会向这个窗口发送你对它干了什么的消息,系统默认处理了一部分消息,但是如果你想搞的不一样,不使用默认处理,那你就需要自己重新处理这些消息。
消息处理之一:在窗口创建的时候,操作系统就会为该窗口生成一个消息队列,记住是队列!先进去先被搞!你在这个窗口上点击鼠标,或者敲键盘等,操作系统都会捕获到你在这个窗口范围内干了这些事,从而生成对应的消息放到你这个窗口的消息队列里。
消息处理之二:除了上面说的,操作系统会捕获消息放到对应窗口的消息队列之外,操作系统还能直接绕过这个队列将一些消息直接发送个窗口处理过程,至于什么是窗口处理过程,下面马上就说。
现在先来看放到消息对列里的消息,要知道你的爪子可能一直在点窗口,所以消息就一直往队列里加,你就需要一直检索队列, 所以需要用while。
MSG msg;
while(GetMessage(&msg, NULL ,0 ,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
MSG:就是个结构体,用来存储获取从队列里获取的消息;
typedef struct tagMSg { HWND hwnd; //窗口句柄 UINT message; //系统预定义好了的消息标识符,比如WM_PAINT WPARAM wparam; //消息参数,取决于具体消息 LPARAM lparam; //消息参数,取决于具体消息 DWORD time; //消息进入消息队列的时间 POINT point; //消息发生时候,鼠标的位置 }
BOOL GetMessage(LPMSG lpMsg,HWND hWnd,UINT wMsgFilterMin,UINT wMsgFilterMax)
lpMsg:指向MSG结构的指针,该结构从线程的消息队列里接收消息信息。
hWnd:取得其消息的窗口的句柄。当其值取NULL时,GetMessage为任何属于调用线程的窗口检索。
wMsgFilterMin:指定被检索的最小消息值的整数。
wMsgFilterMax:指定被检索的最大消息值的整数。
所以在程序中我们用GetMessage(&msg, NULL ,0 ,0),就检索属于该窗口的所有消息。
有人说,都他娘的检索到了,直接发送给窗口过程过程不就行了,不行你检索到的消息还需要处理,比如如果你按键,需要把消息转换成字符,再传给窗口过程处理,就需要用TranslateMessage(&msg);
处理完了就要把这个处理过的消息返回给windows系统,他娘的为啥不给窗口过程? 对呀。good question!,因为窗口过程是操作系统调用的,不是你程序自己调用的,还记得你在WNDCLASS中设置的窗口过程函数了吗?就是向系统表明,在处理这里窗口的消息的时候,系统要调用那个特定的函数来处理,这个函数有特定的格式,下面我们会介绍到,我们在这里就仅需要知道,消息处理完了要用DispatchMessage(&msg)返回给系统,让系统调用窗口过程来处理这个消息。
好了,不管是放到消息队列里,还是直接发送给窗口,都需要有个函数来处理这些消息,这个函数就是传说中的窗口过程函数,也叫回调函数,这个函数不是随便写的,有固定的格式,当然,我指的是返回值和参数名字没什么特殊,可以随便起,操,说的随便起是指符合规范的前提下随便起,我们这里就叫callBackWndProc吧。
这个函数的固定格式为 LRESULT CALLBACK XXX(HWND hWnd, UINT message, WPARAM wparam, LPARAM lparam)
LRESULT :指的是从窗口程序或者回调函数返回的32位值。
CALLBACK :作用跟WINAPI其实是一样的,但是WINAPI一般用于修饰动态链接库中导出函数,CALLBACK仅用于修饰回调函数 。
HWND hWnd, UINT message, WPARAM wparam, LPARAM lparam 这四个参数跟MSG结构中的四个字段是一个含义。
妈的,心情不好,今晚早点睡了,明天写第三章最后一部分---窗口过程函数
到现在为止,进行的代码如下:
#include <windows.h> int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdLine) { TCHAR* className = "firstWindow"; WNDCLASS wndClass; wndClass.hInstance = hInstance; wndClass.style = CS_HREDRAW|CS_VREDRAW; wndClass.lpszClassName = className; wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndClass.cbClsExtra = 0; wndClass.cbWndExtra = 0; wndClass.lpszMenuName = NULL; wndClass.lpfnWndProc = callBackWndProc //暂时假设回调函数名字为callBackWndProc RegisterClass(&wndClass); HWND hwnd = CreateWindow(className, TEXT("title"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL ); UpdateWindow(hwnd); ShowWindow(hwnd, SW_SHOWNORMAL); MSG msg; while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } }
相关文章推荐
- 第三章 事件 windows程序设计 王艳平版
- 第三章 线程局部存储 windows程序设计 王艳平版
- Windows程序设计第三章 (建立一个窗口)
- 第三章 设计自己TLS类_AFXTLS_.H文件 windows程序设计 王艳平版
- windows程序设计第三章-Windows和消息
- 第三章 设计自己TLS类CPP文件 Windows程序设计 王艳平版
- windows程序设计:第三章:窗口与消息
- 第三章 设置线程的优先级 windows程序设计 王艳平版
- Windows程序设计——第三章《窗口和事件》
- 第三章 windows程序设计 王艳平版
- MFC Windows 程序设计 第三章 鼠标与键盘
- windows 程序设计 第三章(上)
- 消息函数windows 程序设计 第三章 (下)
- 第三章 同步 Windows程序设计 王艳平版
- windows 程序设计 第三章 (下)
- Windows程序设计第三章总结
- windows程序设计——子视窗控制项
- Windows程序设计:GetSystemMetrics函数介绍
- [windows程序设计]-消息弹框,messagebox---ShinePans
- Windows程序设计之子窗口设计