写的将是Win32程序设计中的Windows消息机制。
消息就是一个用户对电脑的‘请求’。我想放点音乐,我就对电脑大声喊:“Hey!伙计,放点音乐吧!”,结果显然是我将被冷落。我不能这样发‘请求’,我应该用电脑懂的语言,再用‘友好’的方式请求。我只能选择按鼠标或者敲键盘,于是消息便从这里产生了。
消息的原来形式是你手指的‘动能’,结果导致了某些特定电信号,电信号再到达计算机电路系统,系统再将信号反应到操作系统,操作系统再将信号变成消息形式 发到线程,到线程的消息再进入消息队列排队,最终到达消息处理函数,此时电脑就明白你的请求是什么意思了,再通过消息处理函数工作。
与其说消息是发到电脑,还不如说是发到了线程,如果没有线程在那里‘听’,你发再多的消息,也不会有反应。
线程要怎么‘听’,还得从GUI入口函数说起。
一个GUI用户程序的入口函数将不是main(),而是WinMain(),原形是:
int APIENTRY WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
}
APIENTRY是__stdcall的宏,意思是用Windows标准调用方式,hInstance是本身的实例句柄,lpCmdLine是命令行参数。
光一个WinMain()是不会等待消息的(‘听’),我可以加入一个::MessageBox();简单的弹一个窗口出来,然后默默的结束。
问题是我们需要先建一个窗体出来,建主窗体的过程比较复杂,详细的情况参看书本。过程大致是,先设置窗体句柄的参数,然后建立窗体,然后注册窗体,最后更新窗体。
完了之后这个窗体就会‘挂’在桌面上,‘等待’用户发消息。
事实上,‘等待’还需要‘消息循环’,如果WinMain()进程一旦结束,那窗体挂着也没用,消息还没到达就自己退出了。
所以必须让主线程‘挂’起来,同时‘等待’消息的到达。
接下来就进入‘无限’的‘消息循环’:
代码像这样:
MSG msg;
while(::GetMessage(&msg,NULL,0,0))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
这里的无限循环,不是说这段代码将一直运行,事实上::GetMessage()将使这个线程挂起,只有当消息到来时再被再次激活。
::DispatchMessage()将把消息发送到消息处理函数,或者叫窗口函数,它是窗口建立的时候指定的,形如:
LRESULT CALLBACK MainWndProc(HWND,UINT,WPARAM,LPARAM);
第二个参数就是消息,可以理解为大的消息,后面两个参数是附带的消息参数,而第一个是所属的窗口句柄。
无限的消息循环使主线程一直在等待消息的到达,然后再通知消息处理函数,直到得到一个WM_QUIT消息返回0才结束程序。
另外有两个发送消息的API函数:
::SendMessage();参数同消息处理函数的参数。
::PostMessage();
前者是直接的调用消息处理函数,同时自己挂起,等待消息处理的结束,再继续运行。
而后者是直接向句柄所在消息队列中发一个消息,同时继续运行。
消息就是一个用户对电脑的‘请求’。我想放点音乐,我就对电脑大声喊:“Hey!伙计,放点音乐吧!”,结果显然是我将被冷落。我不能这样发‘请求’,我应该用电脑懂的语言,再用‘友好’的方式请求。我只能选择按鼠标或者敲键盘,于是消息便从这里产生了。
消息的原来形式是你手指的‘动能’,结果导致了某些特定电信号,电信号再到达计算机电路系统,系统再将信号反应到操作系统,操作系统再将信号变成消息形式 发到线程,到线程的消息再进入消息队列排队,最终到达消息处理函数,此时电脑就明白你的请求是什么意思了,再通过消息处理函数工作。
与其说消息是发到电脑,还不如说是发到了线程,如果没有线程在那里‘听’,你发再多的消息,也不会有反应。
线程要怎么‘听’,还得从GUI入口函数说起。
一个GUI用户程序的入口函数将不是main(),而是WinMain(),原形是:
int APIENTRY WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
}
APIENTRY是__stdcall的宏,意思是用Windows标准调用方式,hInstance是本身的实例句柄,lpCmdLine是命令行参数。
光一个WinMain()是不会等待消息的(‘听’),我可以加入一个::MessageBox();简单的弹一个窗口出来,然后默默的结束。
问题是我们需要先建一个窗体出来,建主窗体的过程比较复杂,详细的情况参看书本。过程大致是,先设置窗体句柄的参数,然后建立窗体,然后注册窗体,最后更新窗体。
完了之后这个窗体就会‘挂’在桌面上,‘等待’用户发消息。
事实上,‘等待’还需要‘消息循环’,如果WinMain()进程一旦结束,那窗体挂着也没用,消息还没到达就自己退出了。
所以必须让主线程‘挂’起来,同时‘等待’消息的到达。
接下来就进入‘无限’的‘消息循环’:
代码像这样:
MSG msg;
while(::GetMessage(&msg,NULL,0,0))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
这里的无限循环,不是说这段代码将一直运行,事实上::GetMessage()将使这个线程挂起,只有当消息到来时再被再次激活。
::DispatchMessage()将把消息发送到消息处理函数,或者叫窗口函数,它是窗口建立的时候指定的,形如:
LRESULT CALLBACK MainWndProc(HWND,UINT,WPARAM,LPARAM);
第二个参数就是消息,可以理解为大的消息,后面两个参数是附带的消息参数,而第一个是所属的窗口句柄。
无限的消息循环使主线程一直在等待消息的到达,然后再通知消息处理函数,直到得到一个WM_QUIT消息返回0才结束程序。
另外有两个发送消息的API函数:
::SendMessage();参数同消息处理函数的参数。
::PostMessage();
前者是直接的调用消息处理函数,同时自己挂起,等待消息处理的结束,再继续运行。
而后者是直接向句柄所在消息队列中发一个消息,同时继续运行。