码迷,mamicode.com
首页 > Windows程序 > 详细

浅谈windows消息机制

时间:2014-10-27 10:32:33      阅读:300      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   os   ar   sp   文件   数据   

首先来了解几个基本概念:

消息:在了解什么是消息先来了解什么是事件。事件可分为几种,由输入设备触发的,比如鼠标键盘等等。由窗体控件触发的,比如button控件,file菜单等。还有就是来自Windows内部的事件。这三种称为事件。而消息,是由事件翻译而来的。事件产生消息。

从数据结构角度来讲,消息是一种结构体。结构如下:

 1 typedef struct tagMSG
 2 
 3 {
 4 
 5     HWND hwnd;  //窗口句柄。
 6 
 7     UINT message;//消息类型。
 8 
 9     WPARAM wParam;//32位附加信息。
10 
11     LPARAM lParam;//32位附加信息。
12 
13     DWORD time;//消息发送时间。
14 
15     POINT pt;//消息发送时,鼠标所在位置。
16 
17 }MSG;

消息队列:消息队列有两种,分为系统消息队列和应用程序消息队列。产生的消息首先由Windows系统捕获,放在系统消息队列,再拷贝到对应的应用程序消息队列。32/64位系统为每一个应用程序维护一个消息队列。

消息循环:系统为每个应用程序维护一个消息循环,消息循环会不断检索自身的消息队列。每有一个消息,就用GetMessage()取出消息。

1 while(GetMessage (&msg, NULL, 0, 0))//Windows消息循环。
2 
3 {
4     TranslateMessage (&msg) ;//翻译消息,如按键消息,翻译为WM_CHAR
5 
6     DispatchMessage (&msg) ;//分发消息到对应窗口
7 
8 }

GetMessage具有阻塞机制。当消息队列中没有消息时,程序非忙等,而是让权等待。当收到WM_QUIT时,GetMessage返回false,循环停止,同时应用程序终止。

消息处理:DispatchMessage()把取出来的消息分配给相应的窗口或线程,由窗口过程处理函数DefWindowProc()处理。

==============================================================================================================================================================================割割割割割

以上简要地介绍了消息队列,消息循环与消息处理的概念。

Windows的应用程序靠消息驱动来实现功能。而消息驱动靠消息机制来处理。消息机制就是由消息队列,消息循环,消息处理构成的。

那么,消息机制是如何运作的呢?

当用户运行一个应用程序,通过对鼠标的点击或键盘按键,产生一些特定事件。由于Windows一直监控着I/O设备,该事件首先会被翻译成消息,由系统捕获,存放于系统消息队列。经分析,Windows知道该消息应由那个应用程序处理,则拷贝到相应的应用程序消息队列。由于消息循环不断检索自身的消息队列,当发现应用程序消息队列里有消息,就用GetMessage()取出消息,封装成Msg()结构。如果该消息是由键盘按键产生的,用TranslateMessage()翻译为WM_CHAR消息,否则,用DisPatchMessage()将取出的消息分发到相应的应用程序窗口,交由窗口处理程序处理。Windows为每个窗体预留了过程窗口函数,该函数是一个回掉函数,由系统调用,应用程序不能调用。程序员可以通过重载该函数处理我们”感兴趣”的消息。对于不感兴趣的消息,则由系统默认的窗口过程处理程序做出处理。

下面看这么一张图:

 bubuko.com,布布扣

这张图很好地解释了消息机制的运行原理。 

当运行程序->事件操作引发消息->消息先存在系统消息队列->再存入到应用程序消息队列->用消息循环提取消息->处理消息->再返回消息队列....

 

==============================================================================================================================================================以上是系统消息的产生与处理

 

同样,我们可以通过自定义用户消息,用SendMessage()函数向窗口模拟发送消息,再重载窗口过程处理函数DefWndProc()来接收用户自定义消息,并作出处理。

因为SendMessage()是系统的一个API函数。因此在.NET平台中调用API函数需要,涉及到动态链接库的概念。需用动态链接库声明一个类,该类表明,用到哪个.DLL文件,以及程序入口点。

例如:

1 int xxx1 = 0x520;
2 int xxx2 = 0x521; //用户自定义消息。
1 [DllImport("User32.dll",EntryPoint="SendMessage")]//EntryPoint 表示要调用的函数入口点是dll文件里的SendMessage()函数。
2 private static extern int SendMessage(
3   ntPtr hwnd,     //声明一个窗口句柄,所谓句柄,就是C#里的"指针",窗口或其他资源的一个引用,但此"指针"不可用于其他特殊操作。                              4                            //IntPtr是平台特定的int类型。就是在32跟64位系统上分别为32位和64位。一般用于声明一个句柄。
4   int Msg,    //表明要发送的消息。
5   int wParam,  //32位的附加信息。
6   int IPrarm  //32位的附加信息。(随消息的改变而改变)
7  );
8 // 此处由于SendMessage发送到本线程的窗口。所以发送的消息不会被加入到消息队列中,所以通过PeekMessage()或GetMessage()不能获取到由SendMessage发送的消息。
1 protected override void DefWndProc(ref Message m)//重载接收处理函数
2 {
3     switch (m.Msg)
4   {
5     case xxx1: label1.Text = "在吗"; break;
6     case xxx2: label1.Text = "没空"; break; //XXX1 /XXX2 用户自定义的消息。
7     default: base.DefWndProc(ref m); break;
8   }
9 }

什么是动态链接库?姑且看为”仓库”,里边放着一大堆待调用的函数。动态则表明随用随取,而不是程序用不用得上都要带上一大堆代码。C# 中用[DllImport]类声明调用API函数时,有三个条件,一是,函数名必须与原API函数名一致,二是参数也得一致,三是必须声明为”extern”。关于API函数的参数在MSDN上可以查到。这里不再赘述。

学过C/C++的朋友知道,写程序都要加个#include<xxx.h>的头文件,其实这就是动态链接。

====================================================================================================================================以上便是用户自定义消息,以及发送消息,和接收处理消息

下面由一个窗体的创建再讲一遍。Windows应用程序实际上具有相同的程序结构和执行控制流程。执行流程如下:

程序入口点(DOS下是main() ,windows下是_tWinMain())->注册窗口类(RegisterClass)->创建窗口(CreateWindow())->显示窗口(ShowWindow(hwnd,nCmdShow)->(UpdateWindow(hwnd))->消息循环(等待用户操作窗口产生消息)->放入消息队列->消息循环往复读取并执行相应代码->窗口函数(决定在窗口那里显示些什么,或者如何响应用户输入(如上面的SendMessage()函数))->消息处理(用来确定窗口函数接收的是什么消息以及如何处理(如上面的DefWndProc()函数)。

题外话:Windows和Dos编程,一个很大的区别就是,Windows编程是事件驱动,而Dos是过程驱动。所以,要学好Windows编程,起码要对消息机制有一个清楚的认识,否则很难编出多有用的程序来。

转载请注明出处:http://www.cnblogs.com/gu-zhan/p/4051284.html   博客园-夏日痴

浅谈windows消息机制

标签:style   blog   http   color   os   ar   sp   文件   数据   

原文地址:http://www.cnblogs.com/gu-zhan/p/4053439.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!