`
wsql
  • 浏览: 11754299 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
文章分类
社区版块
存档分类
最新评论

windows消息处理机制

 
阅读更多

SendMessage

The SendMessage function sends the specified message to a window or windows. The function calls the window procedure for the specified window and does not return until the window procedure has processed the message. The PostMessage function, in contrast, posts a message to a thread's message queue and returns immediately.

LRESULT SendMessage(

HWND hWnd, // handle of destination window

UINT Msg, // message to send

WPARAM wParam, // first message parameter

LPARAM lParam // second message parameter

);

Parameters

hWnd

Identifies the window whose window procedure will receive the message. If this parameter is HWND_BROADCAST, the message is sent to all top-level windows in the system, including disabled or invisible unowned windows, overlapped windows, and pop-up windows; but the message is not sent to child windows.

Msg

Specifies the message to be sent.

wParam

Specifies additional message-specific information.

lParam

Specifies additional message-specific information.

Return Values

The return value specifies the result of the message processing and depends on the message sent.

Remarks

Applications that need to communicate using HWND_BROADCAST should use the RegisterWindowMessage function to obtain a unique message for inter-application communication.

If the specified window was created by the calling thread, the window procedure is called immediately as a subroutine. If the specified window was created by a different thread, Windows switches to that thread and calls the appropriate window procedure. Messages sent between threads are processed only when the receiving thread executes message retrieval code. The sending thread is blocked until the receiving thread processes the message.

windows消息处理机制

消息,就是指Windows发出的一个通知,告诉应用程序某个事情发生了。例如,单击鼠标、改变窗口尺寸、按下键盘上的一个键都会使Windows发送一个消息给应用程序。消息本身是作为一个记录传递给应用程序的,这个记录(一般在 C/Java/汇编 中称为“结构体”)中包含了消息的类型以及其他信息。例如,对单击鼠标所产生的消息来说,这个记录(结构体)中包含了单击鼠标的消息号(WM_LBUTTONDOWN)、单击鼠标时的坐标(由X,Y值连接而成的一个32位整数)。这个记录类型叫做TMsg。

  在Delphi的Windows单元中是这样声明的:

  type

  TMsg = packed record

  hwnd: HWND; / /窗口句柄

  message: UINT; / /消息常量标识符

  wParam: WPARAM ; // 32位消息的特定附加信息

  lParam: LPARAM ; // 32位消息的特定附加信息

  time: DWORD; / /消息创建时的时间

  pt: TPoint; / /消息创建时的鼠标位置

end ;

消息中有什么?

hwnd

  32位的窗口句柄。窗口可以是任何类型的屏幕对象,因为Win32能够维护大多数可视对象的句柄(窗口、对话框、按钮、编辑框等)。

  message

  用于区别其他消息的常量值,这些常量可以是Windows单元中预定义的常量,也可以是自定义的常量。

  wParam

  通常是一个与消息有关的常量值,也可能是窗口或控件的句柄。

  lParam

  通常是一个指向内存中数据的指针。

  由于WParam、lParam和Pointer都是32位的,即等同于DWORD。因此,它们之间可以相互转换。

Windows的消息系统

Windows的消息系统是由3个部分组成的:

  • 消息队列。Windows能够为所有的应用程序维护一个消息队列。应用程序必须从消息队列中获取

  消息,然后分派给某个窗口。

  • 消息循环。通过这个循环机制应用程序从消息队列中检索消息,再把它分派给适当的窗口,然

  后继续从消息队列中检索下一条消息,再分派给适当的窗口,依次进行。

  • 窗口过程。每个窗口都有一个窗口过程来接收传递给窗口的消息,它的任务就是获取消息然后

  响应它。窗口过程是一个回调函数;处理了一个消息后,它通常要返回一个值给Windows。

  注意回调函数是程序中的一种函数,它是由Windows或外部模块调用的。

  一个消息从产生到被一个窗口响应,其中有5个步骤:

  1) 系统中发生了某个事件。

  2) Windows把这个事件翻译为消息,然后把它放到消息队列中。

  3) 应用程序从消息队列中接收到这个消息,把它存放在TMsg记录中。

  4) 应用程序把消息传递给一个适当的窗口的窗口过程。

  5) 窗口过程响应这个消息并进行处理。

  步骤3和4构成了应用程序的消息循环。消息循环往往是Windows应用程序的核心,因为消息循环

  使一个应用程序能够响应外部的事件。消息循环的任务就是从消息队列中检索消息,然后把消息传递给适当的窗口。如果消息队列中没有消息,Windows就允许其他应用程序处理它们的消息。

  Windows操作系统最大的特点就是其图形化的操作界面,其图形化界面是建立在其消息处理机制这个基础之上的。如果不理解Windows消息处理机制,肯定无法深入的理解Windows编程。可惜很多程序员对Windows消息只是略有所闻,对其使用知之甚少,更不了解其内部实现原理,本文试着一步一步向大家披露我理解的Windows消息机制。可以说,掌握了这一部分知识,就是掌握了Windows编程中的神兵利器,灵活运用它,将会极大的提高我们的编程能力。

消息实现概述

一、Windows消息概述

  Windows窗体是怎样展现在屏幕上的呢?众所周知,是通过API绘制实现的。Windows操作系统提供了一系列的API函数来实现界面的绘制功能,例如:

  DrawText 绘制文字

  DrawEdge 绘制边框

  DrawIcon 绘制图标

  BitBlt 绘制位图

  Rectangle 绘制矩形

  …

  再复杂的程序界面都是通过这些函数来实现的。

  那什么时候调用这些函数呢?显然我们需要一个控制中心,用来进行“发号施令”,我们还需要一个命令传达机制,将命令即时的传达到目的地。这个控制中心,就是一个动力源,就像一颗心脏,源源不断地将血液送往各处。这个命令传达机制就是Windows消息机制,Windows消息就好比是身体中的血液,它是命令传达的使者。

  Windows消息控制中心一般是三层结构,其顶端就是Windows内核。Windows内核维护着一个消息队列,第二级控制中心从这个消息队列中获取属于自己管辖的消息,后做出处理,有些消息直接处理掉,有些还要发送给下一级窗体(Window)或控件(Control)。第二级控制中心一般是各Windows应用程序的Application对象。第三级控制中心就是Windows窗体对象,每一个窗体都有一个默认的窗体过程,这个过程负责处理各种接收到的消息。如下图所示:

说明图

  (注:windows指windows操作系统;窗口:即windows窗口;窗体:包括窗口,以及有句柄的控件;control指控件,控件本身也可能是一个window,也可能不是;Application即应用程序,应用程序也可能不会用到Windows消息机制,这里我们专门讨论有消息循环的应用程序)

  消息是以固定的结构传送给应用程序的,结构如下:

  Public Type MSG

  hwnd As Long

  message As Long

  wParam As Long

  lParam As Long

  time As Long

  pt As POINTAPI

  End Type

  其中hwnd是窗体的句柄,message是一个消息常量,用来表示消息的类型,wParam和lParam都是32位的附加信息,具体表示什么内容,要视消息的类型而定,time是消息发送的时间,pt是消息发送时鼠标所在的位置。

  Windows操作系统中包括以下几种消息:

  1、标准Windows消息:

  这种消息以WM_打头。

  2、通知消息

  通知消息是针对标准Windows控件的消息。这些控个包括:按钮(Button)、组合框(ComboBox)、编辑框(TextBox)、列表框(ListBox)、ListView控件、Treeview控件、工具条(Toolbar)、菜单(Menu)等。每种消息以不同的字符串打头。

  3、自定义消息

编程人员还可以自定义消息。

二、关于Windows句柄

不是每个控件都能接收消息,转发消息和绘制自身,只有具有句柄(handle)的控件才能做到。有句柄的控件本质上都是一个窗体(window),它们可以独立存在,可以作为其它控件的容器,而没有句柄的控件,如Label,是不能独立存在的,只能作为窗口控件的子控件,它不能绘制自身,只能依靠父窗体将它绘制来。

  句柄的本质是一个系统自动维护的32位的数值,在整个操作系统的任一时刻,这个数值是唯一的。但该句柄代表的窗体释放后,句柄也会被释放,这个数值又可能被其它窗体使用。也就是说,句柄的数值是动态的,它本身只是一个唯一性标识,操作系统通过句柄来识别和查找它所代表的对象。

  然而,并非所有的句柄都是窗体的句柄,Windows系统中还中很多其它类型的句柄,如画布(hdc)句柄,画笔句柄,画刷句柄,应用程序句柄(hInstance)等。这种句柄是不能接收消息的。但不管是哪种句柄,都是系统中对象的唯一标识。本文只讨论窗体句柄。

  那为什么句柄使窗口具有了如此独特的特性呢?实际是都是由于消息的原因。由于有了句柄,窗体能够接收消息,也就知道了该什么时候绘制自己,绘制子控件,知道了鼠标在什么时候点击了窗口的哪个部分,从而作出相应的处理。句柄就好像是一个人的身份证,有了它,你就可以从事各种社会活动;否则的话,你要么是一个社会看不到的黑户,要么跟在别人后面,通过别人来证明你的存在。

三、消息的传送

  1、从消息队列获取消息:

  可以通过PeekMessage或GetMessage函数从Windows消息队列中获取消息。Windows保存的消息队列是以线程(Thread)来分组的,也就是说每个线程都有自己的消息队列。

  2、发送消息

  发送消息到指定窗体一般通过以下两个函数完成:SendMessage和PostMessage。两个函数的区别在于:PostMessage函数只是向线程消息队列中添加消息,如果添加成功,则返回True,否则返回False,消息是否被处理,或处理的结果,就不知道了。而SendMessage则有些不同,它并不是把消息加入到队列里,而是直接翻译消息和调用消息处理(线程向自己发送消息才是这样),直到消息处理完成后才返回。所以,如果我们希望发送的消息立即被执行,就应该调用SendMessage。

  还有一点,就是SendMessage发送的消息由于不会被加入到消息队列中(错:线程向其他线程发送消息也是追加到其他线程的发送消息队列的,即使这两个线程在同一个进程也是如此),所以通过PeekMessage或GetMessage是不能获取到由SendMessage发送的消息。

  另外,有些消息用PostMessage不会成功,比如wm_settext。所以不是所有的消息都能够用PostMessage的。

  还有一些其它的发送消息API函数,如PostThreadMessage,SendMessageCallback,SendMessageTimeout,SendNotifyMessage等。

四、消息循环与窗体过程

  消息循环是应用程序能够持续存在的根本原因。如果循环退出,则应用程序就结束了。

  我们来看一看Delphi中封装的消息循环是怎样的:

  第一步:程序开始运行(Run)

  Application.Initialize; //初始化

  Application.CreateForm(TForm1, Form1); //创建主窗体

  Application.Run; //开始运行,准备进行消息循环

  如果不创建主窗体,应用程序同样可以存在和运行。

  第二步:开始调用消息循环(HandleMessage)

  procedure TApplication.Run;

  begin

  FRunning := True;

  try

  AddExitProc(DoneApplication);

  if FMainForm <> nil then

  begin

  case CmdShow of

  SW_SHOWMINNOACTIVE: FMainForm.FWindowState := wsMinimized;

  SW_SHOWMAXIMIZED: MainForm.WindowState := wsMaximized;

  end;

  if FShowMainForm then

  if FMainForm.FWindowState = wsMinimized then

  Minimize else

  FMainForm.Visible := True;

  Repeat //注:循环开始

  try

  HandleMessage;

  except

  HandleException(Self);

  end;

  until Terminated; //循环结束条件

  end;

  finally

  FRunning := False;

  end;

  end;

  第三步:消息循环中对消息的处理。

  procedure TApplication.HandleMessage;

  var

  Msg: TMsg;

  begin

  if not ProcessMessage(Msg) then Idle(Msg);

  end;

  function TApplication.ProcessMessage(var Msg: TMsg): Boolean;

  var

  Handled: Boolean;

  begin

  Result := False;

  if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then

  begin

  Result := True;

  if Msg.Message <> WM_QUIT then

  begin

  Handled := False;

  if Assigned(FOnMessage) then FOnMessage(Msg, Handled);

  if not IsHintMsg(Msg) and not Handled and not IsMDIMsg(Msg) and

  not IsKeyMsg(Msg) and not IsDlgMsg(Msg) then

  begin

  TranslateMessage(Msg);

  DispatchMessage(Msg);

  end;

  end

  else

  FTerminate := True;

  end;

  end;

  窗体过程实际上是一个回调函数。所谓的回调函数,实际上就是由Windows操作系统或外部程序调用的函数。回调函数一般都有规定的参数格式,以地址方式传递给调用者。窗口过程中是Windows操作系统调用了,在一个窗口创建的时候,在分配窗体句柄的时候就需要传入回调函数地址。那为什么我们平时编程看不到这个回调函数呢?这是由于我们的编程工具已经为我们生成了默认的窗体过程,这个过程的要做的事情就是判断不同的消息类型,然后做出不同的处理。例如可以为键盘或鼠标输入生成事件等。

五、消息与事件

  事件本质上是对消息的封装,是IDE编程环境为了简化编程而提供的有用的工具。这个封装是在窗体过程中实现的。每种IDE封装了许多Windows的消息,例如:

  

事件

消息

OnActivate

WM_ACTIVATE

OnClick

WM_XBUTTONDOWN

OnCreate

WM_CREATE

OnDblClick

WM_XBUTTONDBLCLICK

OnKeyDown

WM_KEYDOWN

OnKeyPress

WM_CHAR

OnKeyUp

WIN_KEYUP

OnPaint

WM_PAINT

OnResize

WM_SIZE

OnTimer

WM_TIMER

分享到:
评论

相关推荐

    Windows消息处理机制--钩子实例

    钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序...

    windows消息处理机制.doc

    windows消息处理机制.doc

    深入剖析MFC中Windows消息处理机制

    深入剖析MFC中Windows消息处理机制的详细介绍,对理解windows消息处理有很大的帮助哦

    如何理解VC编程的windows消息处理机制

    包含个人工作日志,对初学者正确理解windows消息机制很有帮助

    Windows窗口消息机制

    简要讲述C语言编程中的Windows窗口消息机制,并附示例代码:LONG yourWndProc(HWND hWnd,UINT uMessageType,WPARAM wP,LPARAM) {  switch(uMessageType)  {//使用SWITCH语句将各种消息分开  case(WM_PAINT): ...

    Visual C++模态对话框消息处理机制的分析

    消息驱动机制是Windows操作系统的根本,模态对话框消息处理又是不同于一般消息处理的特殊形式。通过分析这种消息机制的原理,可用来处理类似的程序设计要求。

    anit.zip_message hook

    钩子(Hook)是Windows消息处理机制中的一个监视点,钩子提供一个回调函数。当在某个程序中安装钩子后,它将监视该程序的消息,在指定消息还没到达窗口之前钩子程序先捕获这个消息。这样就有机会对此消息进行过滤,...

    C#消息处理机制

    C#对消息重新进行了面对对象的封装,在C#中消息被封装成了事件。 System.Windows.Forms.Application类具有用于启动和停止应用程序和线程以及处理Windows消息的方法。

    C#设置键盘钩子屏蔽键盘信息

    钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序...

    VB高级钩子编程示例源码及指南

    钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序...

    Hook功能的实现

    钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序...

    WindowsMessage客户端之间相互监听消息demo

    两个桌面客户端在同一台电脑上相互监听信号发送与接受。windowsmessage。windows消息处理机制。一个应用程序发出通知告诉给另一个应用程序。

    SetWindowsHookEx: 全局钩子实现键盘记录器 Hook Steam

    SetWindowsHookEx 钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。...

    Windows系统的消息机制

    对诸如PowerBuilder(后文简写为PB)、Visual Basic和Dephi等大多数可视化程序设计语言来讲,程序设计的核心是对象的事件、属性和方法,但对Windows系统本身而言,却是以消息处理为其控制机制。Windows把系统中的...

    Windows消息传递机制详解

    所谓的Windows消息传递机制就类似于生活中的物流公司。当寄件人(例如鼠标、键盘)将包裹(消息)交给物流公司(Windows系统)时,物流公司(Windows系统)会进行整理并且派发(整理及派发主要由消息循环完成),...

    键盘钩子毕业设计

    1.Windows消息处理机制。 2.钩子函数的分类、使用、安装和卸载等。 3.Windows动态链接库的运行机制和使用方法。 4.SOCKET编程原理。 5.VC++ MFC编程基础。 6.Andorid应用开发。 7. 计算机信息安全管理与防范...

    论文研究-Windows消息机制的研究和应用 .pdf

    Windows消息机制的研究和应用,左春伟,,Windows 是基于消息的非可剥夺式操作系统,以事件为驱动。通过消息循环接收处理各种事件,深入理解消息运行机理对于Windows编程至关重

Global site tag (gtag.js) - Google Analytics