每日一贴,今天的内容关键字为消息函数
上周末真他娘的废,刚花了200大元买了辆拉风的二手自行车,结果今天就下雨,我一路追风逐电骑到公司,连蛋蛋都湿透了, 太逊了!周末跟女朋友去看了场片子,去美国大爷家吃了个汉堡,甚是惬意.
第三章上篇当中,哥说过,第三章主要可以用两句话来展开“创立和显示窗口,接受和处置消息”,最后就剩下了个处置消息了,处置消息这是个很大的棋啊,搞不好就给绕进去了.
首先,你说处置什么的消息?那肯定是你创立的窗口的消息,着他娘的绝对准确.
其次, 是谁调用的这个窗口 处置函数? 你创立的窗口? 妈的错误, 是操纵系统,为啥是操纵系统, 狗日的微软就那么设计的,还记得在WNDCLASS中指定的lpfnWndProc字段吗?赋值的就是这个回调函数名.
第三,什么是回调函数? 就是这个函数! 我操,祝贺你,脱了裤子放屁,答对了,但是准确的理解应该是:这个函数不是直接由你生成的那个窗口直接调用的,而是操纵系统调用的,操纵系统什么时候调用?记得那个DispatchMessage函数吗?就是那个时候。
ok, 下面扯完了, 既然是操纵系统调用的,所以回调函数有牢固的格式:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
这里说的格式牢固指的是函数返回值( LRESULT),调用标准(CALLBACK)和参数列表(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam),而不是函数名!你丫违心起啥名就起啥,只要符合标准。
下面看看回调函数的代码:
#include <windows.h> #include <mmsystem.h> #pragma comment(lib,"winmm.lib") LRESULT CALLBACK callBackWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); 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); } return msg.wParam; } LRESULT CALLBACK callBackWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch(message) { case WM_CREATE: PlaySound(TEXT("陈奕迅-好久不见.wav"), NULL, SND_FILENAME|SND_ASYNC); return 0; case WM_PAINT: PAINTSTRUCT ps; RECT rect; HDC hdc = BeginPaint(hWnd, &ps); GetClientRect(hWnd, &rect); DrawText(hdc, TEXT("HELLO 凤姐!"),lstrlen(TEXT("HELLO 凤姐!")), &rect, DT_SINGLELINE|DT_CENTER|DT_VCENTER); EndPaint(hWnd, &ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, message, wParam, lParam); }
回调函数callBackWndProc中我们处置了三种消息,WM_CREATE, WM_PAINT, WM_DESTROY, 还 记得我们后面说过,消息分为两种,第一种是操纵系统放在每个窗口的消息循环中,等待GetMessage消息循环从里面获得,另一种是操纵系统直接把消息发送给回调函数,而不放到消息循环中.
这里可能有哥们问什么情况下系统会直接把消息发送给回调函数而不通过消息堆栈, 一般情况下,通过直接调用系统API函数产生的消息是直接发送给回调函数的,比如创立窗口的时候UpdateWindow产生第一条WM_CREATE,这个就是直接发送给回调函数.
case WM_CREATE:这个里面就一个PlaySound函数,使用这个函数要注意,工程要包括mmsystem.h和winmm.lib,所以在开头的代码中包括了#include <mmsystem.h> #pragma comment(lib,"winmm.lib")两行代码.
PlaySound有三个参数,第一个是 wav文件目录,有的草包可能使用了说"妈的,基本不能播放", 我操,你首先要确定目录
是不是准确,其主要确定是不是wav文件,别弄成mp3的了, 第二个参数,只要不是资源文件,都设成NULL,如果是资源文件就设置成应用程序的实例句柄,至于怎么获得这个句柄,要么你自己baidu,要么等以后再说,因为再展开,老子今晚就不用睡觉了.
分析WM_PAINT之前,我想问问你丫看A片的电脑是啥牌子的? DELL? 三星? iMac?...总值他娘的很多牌子的显示器,你想,那么多牌子的显示设备,那么多不同的分辨率, 都是雷同的windows操纵系统运行在下面, 你说在显示之前,操纵系统是不是要判断以及获得以下我们的显示设备的信息? 这个货色就叫做设备环境,在操纵系统中我们一般用句柄表现这个对象,HDC,设备环境句柄, 怎么获得设备环境句柄? BeginPaint,这个函数须要两个参数,其中一个是HWND,废话,当然要处置哪个窗口,就要获得这个窗口地点环境的设备句柄,第二个是PAINTSTRUCT结构体,用来存储设备环境的一些信息,这个不是BeginPaint都是与EndPaint同时使用的,并且只在同一个消息处置中使用,你丫不能在WM_CREATE中写一个BeginPaint,在WM_Paint中写一个EndPaint。
其次,你想要在窗口上显示信息,你显示在窗口的什么地方? 旁边?还是两边?不管显示在哪,你总要晓得窗口大小才能盘算旁边在哪吧?这就要获得窗口大小。RECT ,上下左右四部分界定大小,这个用GetClientRect函数获得。
好了再看看WM_PAINT,就只有一个DrawText函数没说了,这个也不说了,因为大部分人都爱好用TextOut。
最后一个WM_DESTROY,这个就是你关闭窗口时发送的消息,有的娘们可能又要问,既然已经关闭了,为什么还要扯淡的写个PostQuitMessage(0);,你可以试一下,如果不写这个函数,窗口是能关闭,但是,你在资源管理器中仍然可以看到进程仍在运行, why? 草,因为GetMessage函数还在那浪荡,没有退出循环, 我们曾提到过当GetMessage函数获得WM_QUIT的时候就会返回0值,于是循环就中止啦。
文章结束给大家分享下程序员的一些笑话语录: Bphone之你们聊,我先走了!移动说:我在phone前加o,我叫o缝;苹果说:我在phone前i,我是i缝;微软说:我在phone前加w,我叫w缝;三星说:你们聊,我先走了!
将来王建宙写回忆录的时候,一定要有一句“常小兵为中国移动的发展做出了不可磨灭的贡献”。
--------------------------------- 原创文章 By
消息和函数
---------------------------------