国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
windows消息處理機(jī)制

編輯本段簡(jiǎn)介

  消息,就是指Windows發(fā)出的一個(gè)通知,告訴應(yīng)用程序某個(gè)事情發(fā)生了。例如,單擊鼠標(biāo)、改變窗口尺寸、按下鍵盤(pán)上的一個(gè)鍵都會(huì)使Windows發(fā)送一個(gè)消息給應(yīng)用程序。消息本身是作為一個(gè)記錄傳遞給應(yīng)用程序的,這個(gè)記錄(一般在 C/Java/匯編 中稱為“結(jié)構(gòu)體”)中包含了消息的類型以及其他信息。例如,對(duì)單擊鼠標(biāo)所產(chǎn)生的消息來(lái)說(shuō),這個(gè)記錄(結(jié)構(gòu)體)中包含了單擊鼠標(biāo)的消息號(hào)(WM_LBUTTONDOWN)、單擊鼠標(biāo)時(shí)的坐標(biāo)(由X,Y值連接而成的一個(gè)32位整數(shù))。這個(gè)記錄類型叫做TMsg。

  在Delphi的Windows單元中是這樣聲明的:

  type

  TMsg = packed record

  hwnd: HWND; / /窗口句柄

  message: UINT; / /消息常量標(biāo)識(shí)符

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

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

  time: DWORD; / /消息創(chuàng)建時(shí)的時(shí)間

  pt: TPoint; / /消息創(chuàng)建時(shí)的鼠標(biāo)位置

  end ;

  其中TPoint定義是:

  TPoint= record

  x:integer;

  y:integer;

  end;

  在C語(yǔ)言中的定義是:

  typedef struct Msg

  {

  HWND hwnd; / /窗口句柄

  UINT message; / /消息常量標(biāo)識(shí)符

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

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

  DWORD time; / /消息創(chuàng)建時(shí)的時(shí)間

  TPoint pt; / /消息創(chuàng)建時(shí)的鼠標(biāo)位置

  } TMsg;

  typedef struct TPoint

  {

  int x;

  int y;

  }TPoint;

編輯本段消息內(nèi)容

  hwnd

  32位的窗口句柄。窗口可以是任何類型的屏幕對(duì)象,因?yàn)閃in32能夠維護(hù)大多數(shù)可視對(duì)象的句柄(窗口、對(duì)話框、按鈕、編輯框等)。

  message

  用于區(qū)別其他消息的常量值,這些常量可以是Windows單元中預(yù)定義的常量,也可以是自定義的常量。

  wParam

  通常是一個(gè)與消息有關(guān)的常量值,也可能是窗口或控件的句柄。

  lParam

  通常是一個(gè)指向內(nèi)存中數(shù)據(jù)的指針。

  由于WParam、lParam和Pointer都是32位的,即等同于DWORD。因此,它們之間可以相互轉(zhuǎn)換。

編輯本段消息系統(tǒng)

  Windows的消息系統(tǒng)是由3個(gè)部分組成的:

  消息隊(duì)列。Windows能夠?yàn)樗械膽?yīng)用程序維護(hù)一個(gè)消息隊(duì)列。應(yīng)用程序必須從消息隊(duì)列中獲取

  消息,然后分派給某個(gè)窗口。

  消息循環(huán)。通過(guò)這個(gè)循環(huán)機(jī)制應(yīng)用程序從消息隊(duì)列中檢索消息,再把它分派給適當(dāng)?shù)拇翱?,?/p>

  后繼續(xù)從消息隊(duì)列中檢索下一條消息,再分派給適當(dāng)?shù)拇翱?,依次進(jìn)行。

   窗口過(guò)程。每個(gè)窗口都有一個(gè)窗口過(guò)程來(lái)接收傳遞給窗口的消息,它的任務(wù)就是獲取消息然后

  響應(yīng)它。窗口過(guò)程是一個(gè)回調(diào)函數(shù);處理了一個(gè)消息后,它通常要返回一個(gè)值給Windows。

  注意回調(diào)函數(shù)是程序中的一種函數(shù),它是由Windows或外部模塊調(diào)用的。

  一個(gè)消息從產(chǎn)生到被一個(gè)窗口響應(yīng),其中有5個(gè)步驟:

  1) 系統(tǒng)中發(fā)生了某個(gè)事件。

  2) Windows把這個(gè)事件翻譯為消息,然后把它放到消息隊(duì)列中。

  3)應(yīng)用程序從消息隊(duì)列中接收到這個(gè)消息,把它存放在TMsg記錄中。

  4)應(yīng)用程序把消息傳遞給一個(gè)適當(dāng)?shù)拇翱诘拇翱谶^(guò)程。

  5) 窗口過(guò)程響應(yīng)這個(gè)消息并進(jìn)行處理。

  步驟3和4構(gòu)成了應(yīng)用程序的消息循環(huán)。消息循環(huán)往往是Windows應(yīng)用程序的核心,因?yàn)橄⒀h(huán)

  使一個(gè)應(yīng)用程序能夠響應(yīng)外部的事件。消息循環(huán)的任務(wù)就是從消息隊(duì)列中檢索消息,然后把消息傳遞給適當(dāng)?shù)拇翱凇H绻㈥?duì)列中沒(méi)有消息,Windows就允許其他應(yīng)用程序處理它們的消息。

  Windows操作系統(tǒng)最大的特點(diǎn)就是其圖形化的操作界面,其圖形化界面是建立在其消息處理機(jī)制這個(gè)基礎(chǔ)之上的。如果不理解Windows消息處理機(jī)制,肯定無(wú)法深入的理解Windows編程??上Ш芏喑绦騿T對(duì)Windows消息只是略有所聞,對(duì)其使用知之甚少,更不了解其內(nèi)部實(shí)現(xiàn)原理,本文試著一步一步向大家披露我理解的Windows消息機(jī)制。可以說(shuō),掌握了這一部分知識(shí),就是掌握了Windows編程中的神兵利器,靈活運(yùn)用它,將會(huì)極大的提高我們的編程能力。

編輯本段消息實(shí)現(xiàn)Windows

  消息概述

  Windows窗體是怎樣展現(xiàn)在屏幕上的呢?眾所周知,是通過(guò)API繪制實(shí)現(xiàn)的。Windows操作系統(tǒng)提供了一系列的API函數(shù)來(lái)實(shí)現(xiàn)界面的繪制功能,例如:

  DrawText 繪制文字

  DrawEdge 繪制邊框

  DrawIcon 繪制圖標(biāo)

  BitBlt 繪制位圖

  Rectangle 繪制矩形

  …

  再?gòu)?fù)雜的程序界面都是通過(guò)這些函數(shù)來(lái)實(shí)現(xiàn)的。

  那什么時(shí)候調(diào)用這些函數(shù)呢?顯然我們需要一個(gè)控制中心,用來(lái)進(jìn)行“發(fā)號(hào)施令”,我們還需要一個(gè)命令傳達(dá)機(jī)制,將命令即時(shí)的傳達(dá)到目的地。這個(gè)控制中心,就是一個(gè)動(dòng)力源,就像一顆心臟,源源不斷地將血液送往各處。這個(gè)命令傳達(dá)機(jī)制就是Windows消息機(jī)制,Windows消息就好比是身體中的血液,它是命令傳達(dá)的使者。

  Windows消息控制中心一般是三層結(jié)構(gòu),其頂端就是Windows內(nèi)核。Windows內(nèi)核維護(hù)著一個(gè)消息隊(duì)列,第二級(jí)控制中心從這個(gè)消息隊(duì)列中獲取屬于自己管轄的消息,后做出處理,有些消息直接處理掉,有些還要發(fā)送給下一級(jí)窗體(Window)或控件(Control)。第二級(jí)控制中心一般是各Windows應(yīng)用程序的Application對(duì)象。第三級(jí)控制中心就是Windows窗體對(duì)象,每一個(gè)窗體都有一個(gè)默認(rèn)的窗體過(guò)程,這個(gè)過(guò)程負(fù)責(zé)處理各種接收到的消息。如下圖所示:

  說(shuō)明圖(注:windows指windows操作系統(tǒng);窗口:即windows窗口;窗體:包括窗口,以及有句柄的控件;control指控件,控件本身也可能是一個(gè)window,也可能不是;Application即應(yīng)用程序,應(yīng)用程序也可能不會(huì)用到Windows消息機(jī)制,這里我們專門(mén)討論有消息循環(huán)的應(yīng)用程序)

  消息是以固定的結(jié)構(gòu)傳送給應(yīng)用程序的,結(jié)構(gòu)如下:

  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是一個(gè)消息常量,用來(lái)表示消息的類型,wParam和lParam都是32位的附加信息,具體表示什么內(nèi)容,要視消息的類型而定,time是消息發(fā)送的時(shí)間,pt是消息發(fā)送時(shí)鼠標(biāo)所在的位置。

  Windows操作系統(tǒng)中包括以下幾種消息:

  1、標(biāo)準(zhǔn)Windows消息:

  這種消息以WM_打頭。

  2、通知消息

  通知消息是針對(duì)標(biāo)準(zhǔn)Windows控件的消息。這些控件包括:按鈕(Button)、組合框(ComboBox)、編輯框(TextBox)、列表框(ListBox)、ListView控件、Treeview控件、工具條(Toolbar)、菜單(Menu)等。每種消息以不同的字符串打頭。

  3、自定義消息

  編程人員還可以自定義消息。

關(guān)于Windows句柄

  不是每個(gè)控件都能接收消息,轉(zhuǎn)發(fā)消息和繪制自身,只有具有句柄(handle)的控件才能做到。有句柄的控件本質(zhì)上都是一個(gè)窗體(window),它們可以獨(dú)立存在,可以作為其它控件的容器,而沒(méi)有句柄的控件,如Label,是不能獨(dú)立存在的,只能作為窗口控件的子控件,它不能繪制自身,只能依靠父窗體將它繪制來(lái)。

  句柄的本質(zhì)是一個(gè)系統(tǒng)自動(dòng)維護(hù)的32位的數(shù)值,在整個(gè)操作系統(tǒng)的任一時(shí)刻,這個(gè)數(shù)值是唯一的。但該句柄代表的窗體釋放后,句柄也會(huì)被釋放,這個(gè)數(shù)值又可能被其它窗體使用。也就是說(shuō),句柄的數(shù)值是動(dòng)態(tài)的,它本身只是一個(gè)唯一性標(biāo)識(shí),操作系統(tǒng)通過(guò)句柄來(lái)識(shí)別和查找它所代表的對(duì)象。

  然而,并非所有的句柄都是窗體的句柄,Windows系統(tǒng)中還中很多其它類型的句柄,如畫(huà)布(hdc)句柄,畫(huà)筆句柄,畫(huà)刷句柄,應(yīng)用程序句柄(hInstance)等。這種句柄是不能接收消息的。但不管是哪種句柄,都是系統(tǒng)中對(duì)象的唯一標(biāo)識(shí)。本文只討論窗體句柄。

  那為什么句柄使窗口具有了如此獨(dú)特的特性呢?實(shí)際是都是由于消息的原因。由于有了句柄,窗體能夠接收消息,也就知道了該什么時(shí)候繪制自己,繪制子控件,知道了鼠標(biāo)在什么時(shí)候點(diǎn)擊了窗口的哪個(gè)部分,從而作出相應(yīng)的處理。句柄就好像是一個(gè)人的身份證,有了它,你就可以從事各種社會(huì)活動(dòng);否則的話,你要么是一個(gè)社會(huì)看不到的黑戶,要么跟在別人后面,通過(guò)別人來(lái)證明你的存在。

消息的傳送

  1、從消息隊(duì)列獲取消息:

  可以通過(guò)PeekMessage或GetMessage函數(shù)從Windows消息隊(duì)列中獲取消息。Windows保存的消息隊(duì)列是以線程(Thread)來(lái)分組的,也就是說(shuō)每個(gè)線程都有自己的消息隊(duì)列。

  2、發(fā)送消息

  發(fā)送消息到指定窗體一般通過(guò)以下兩個(gè)函數(shù)完成:SendMessage和PostMessage。兩個(gè)函數(shù)的區(qū)別在于:PostMessage函數(shù)只是向線程消息隊(duì)列中添加消息,如果添加成功,則返回True,否則返回False,消息是否被處理,或處理的結(jié)果,就不知道了。而SendMessage則有些不同,它并不是把消息加入到隊(duì)列里,而是直接翻譯消息和調(diào)用消息處理(線程向自己發(fā)送消息才是這樣),直到消息處理完成后才返回。所以,如果我們希望發(fā)送的消息立即被執(zhí)行,就應(yīng)該調(diào)用SendMessage。

  還有一點(diǎn),就是SendMessage發(fā)送的消息由于不會(huì)被加入到消息隊(duì)列中(錯(cuò):線程向其他線程發(fā)送消息也是追加到其他線程的發(fā)送消息隊(duì)列的,即使這兩個(gè)線程在同一個(gè)進(jìn)程也是如此),所以通過(guò)PeekMessage或GetMessage是不能獲取到由SendMessage發(fā)送的消息。

  另外,有些消息用PostMessage不會(huì)成功,比如wm_settext。所以不是所有的消息都能夠用PostMessage的。

  還有一些其它的發(fā)送消息API函數(shù),如PostThreadMessage,SendMessageCallback,SendMessageTimeout,SendNotifyMessage等。

消息循環(huán)與窗體過(guò)程

  消息循環(huán)是應(yīng)用程序能夠持續(xù)存在的根本原因。如果循環(huán)退出,則應(yīng)用程序就結(jié)束了。

  我們來(lái)看一看Delphi中封裝的消息循環(huán)是怎樣的:

  第一步:程序開(kāi)始運(yùn)行(Run)

  Application.Initialize; //初始化

  Application.CreateForm(TForm1, Form1); //創(chuàng)建主窗體

  Application.Run; //開(kāi)始運(yùn)行,準(zhǔn)備進(jìn)行消息循環(huán)

  如果不創(chuàng)建主窗體,應(yīng)用程序同樣可以存在和運(yùn)行。

  第二步:開(kāi)始調(diào)用消息循環(huán)(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  //注:循環(huán)開(kāi)始

  try

  HandleMessage;

  except

  HandleException(Self);

  end;

  until Terminated; //循環(huán)結(jié)束條件

  end;

  finally

  FRunning := False;

  end;

  end;

  第三步:消息循環(huán)中對(duì)消息的處理。

  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;

  窗體過(guò)程實(shí)際上是一個(gè)回調(diào)函數(shù)。所謂的回調(diào)函數(shù),實(shí)際上就是由Windows操作系統(tǒng)或外部程序調(diào)用的函數(shù)。回調(diào)函數(shù)一般都有規(guī)定的參數(shù)格式,以地址方式傳遞給調(diào)用者。窗口過(guò)程中是Windows操作系統(tǒng)調(diào)用了,在一個(gè)窗口創(chuàng)建的時(shí)候,在分配窗體句柄的時(shí)候就需要傳入回調(diào)函數(shù)地址。那為什么我們平時(shí)編程看不到這個(gè)回調(diào)函數(shù)呢?這是由于我們的編程工具已經(jīng)為我們生成了默認(rèn)的窗體過(guò)程,這個(gè)過(guò)程的要做的事情就是判斷不同的消息類型,然后做出不同的處理。例如可以為鍵盤(pán)或鼠標(biāo)輸入生成事件等。

消息與事件

  事件本質(zhì)上是對(duì)消息的封裝,是IDE編程環(huán)境為了簡(jiǎn)化編程而提供的有用的工具。這個(gè)封裝是在窗體過(guò)程中實(shí)現(xiàn)的。每種IDE封裝了許多Windows的消息,[1]

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
用Win32 application建立窗體_入門(mén)
孫鑫VC視頻教程筆記之第一課“Windows程序的內(nèi)部運(yùn)行原理”
windows窗口的創(chuàng)建
理解Windows消息機(jī)制2
Windows消息機(jī)制
一些WIN32編程的總結(jié)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服