Windows消息机制

Windows消息机制

Windows是一个消息(Message)驱动式系统。Windows消息提供在应用程序与应用程序之间、应用程序与Windows系统之间进行通信的手段。应用程序想要实现的功能由消息触发,通过对消息的响应和处理完成。

消息处理过程

Windows先将输入的消息放入消息队列,在将输入的消息复制到相应的应用程序队列中,应用程序中的消息循环在它的消息队列中检索每个消息并发送相应的窗口函数。一个事件从发生到达处理它的窗口函数必须经历以上过程。值得注意的是消息的非抢先性,即不论事件的即与缓,总是按到达的先后排队(一些系统消息除外)

Windows系统中有两种消息队列

系统消息队列

应用程序消息队列

Windows消息函数

  • SendMessage函数:调用一个窗口的窗口函数,将一条消息发送给那个窗口。除非消息处理完毕,否则该函数不会返回
LRESULT SendMessage(
HWND hWnd,  //目的窗口的句柄
UINT Msg,  //消息标识符
WPARM wParam,//消息的WPARAM域
LPARAM lParam//消息的LPARAM域名
);

返回值:由具体的消息决定。如果消息投递成成功,则返回"TRUE"(非零)

  • WM_COMMAND消息
    当用户从菜单或按钮中选择一条命令或者一个控件时该消息被发送给它的父窗口,或者当一个快捷键被释放时。VisualC++的WINUSER.H文件定义,WM_COMMAND消息所对应的十六进制数时0111h
WM_COMMAND
  wNotifyCode = HIWORD(wParam);  //通告代码
  wID = LOWORD(wParam); // 菜单条目、控件或者快捷键的标识符
  hwndCtl = (HWND)lParam; //控件句柄

返回值:如果应用程序处理这条消息,则返回值为零。

  • WM_DESTROY消息
    当一个窗口被销毁时发送该消息。该消息的十六进制数是02,没有参数。
    返回值:如果应用程序处理这条消息,则返回值为零。
  • WM_GETTEXT消息
    应用程序发送一条WM_GETTEXT消息,将一个对应窗口的文本复制到一个由呼叫程序提供的缓冲区中,示例如下。WM_GETTEXT消息的十六进制数是0Dh
WM_GETTEXT
 wParam = (WPARAM) cchTextMax; //需要复制的字符数
LParam = (LPARAM) lpszText; //接受文本的缓冲区地址
  • WM_QUIT消息
    当应用程序调用PostQuitMessage函数,生成WM_QUIT消息,示例如下。WM_QUIT的消息的十六进制数是012h
WM_QUIT
    nExitCode =(int) wParam; // 退出代码

返回值:这条消息没有返回值。

  • WM_LBUTTONDOWN消息
    当光标停在一个窗口的客户区且用户按下鼠标左键时,WM_LBUTTONDOWN消息将被发送,示例如下。如果鼠标动作未被捕获,这条消息将被发送给光标下的窗口;否则,将被发送已经捕获鼠标动作的窗口。WM_LBUTTONDOWN消息的十六进制数是0201h
WM_LBUTTONDOWN
fwKeys = wParam;  //key旗标
xPos = LOWORD(lParam) //光标的水平位置
yPos = HIWORD(lParam) //光标的垂直位置

返回值:如果应用程序处理了这条消息,则返回值为零

虚拟内存

32位Windows操作系统的地址空间在4GB以内。Win32的平坦内存模式使每个进程都拥有自己的虚拟空间。对32位进程来说,这个地址空间是4GB,因为32位指针拥有00000000h~FFFFFFFFh的任何值。此时,程序的代码和数据都放在同一地址空间中,不必区分代码段和数据段。
虚拟内存(Virtual Memory)不是真正的内存,它通过映射(Map)的方法使可用虚拟地址(Virtual Address)达到4GB,每个应用程序可以获得2GB的虚拟地址,剩下的2GB留给操作系统自用。在WindowsNT中,应用程序甚至可以获得3GB的虚拟地址。
Windows是一个分时的多任务操作系统,CPU时间被分成一个个时间片后分配给不同的程序。在一个时间片里,与这个程序的执行无关的内容不会映射到线性地址中。因此,每个程序都有自己的4GB寻址空间,互不干扰。在物理内存中,操作系统和系统DLL代码需要供每个应用程序调用,所以它们在任意时刻必须被映射。用户的EXE程序只在自己所属的时间片内被映射,用户DLL则有选择地被映射。

虚拟内存的实现方法和过程如下:

  1. 当一个应用程序启动时,操作系统就创建一个进程,并给该进程分配2GB的虚拟地址(不是内存,只是地址)。
  2. 虚拟内存管理器将应用程序的代码映射到那个应用的虚拟地址中的某个位置,并把当前需要的代码读入物理地址(注意:虚拟地址与应用程序代码在物理内存中的位置是没有关系的)。
  3. 如果使用DLL,DLL也会被映射到进程的虚拟地址空间中,在需要的时候才会被读入物理内存。
  4. 其他项目(数据、堆栈等)的空间是从物理内存中分配的,并被映射到虚拟地址空间中。
  5. 应用程序通过使用虚拟地址空间中的地址开始执行。然后,虚拟内存管理器把每次内存访问映射到物理地址。

注意点

  • 应用程序不会直接访问物理地址。
  • 虚拟内存管理通过虚拟地址的访问请求控制所有的物理地访问。
  • 每个应用程序都有独立的4GB寻址空间,不用应用程序的地址空间是彼此隔离的。
  • DLL程序没有"私有"空间,它们总是被映射到其他应用程序的地址空间中,作为其他应用程序的一部分运行。其原因是:如果DLL不与其他程序处于同一地址空间,应用程序就无法调用它。
    使用虚拟内存的好处就是:简化内存的管理,弥补五i内存的不足,可以防止多任务环境下应用程序之间的冲突。
posted @ 2022-01-06 10:11  不会笑的孩子  阅读(458)  评论(0编辑  收藏  举报