免费高清特黄a大片,九一h片在线免费看,a免费国产一级特黄aa大,国产精品国产主播在线观看,成人精品一区久久久久,一级特黄aa大片,俄罗斯无遮挡一级毛片

分享

Windows消息機(jī)制

 SamBookshelf 2013-12-05

Windows消息機(jī)制

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

 

一、      消息概述

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

2       DrawText 繪制文字

2       DrawEdge 繪制邊框

2       DrawIcon 繪制圖標(biāo)

2       BitBlt 繪制位圖

2       Rectangle 繪制矩形

2      

再復(fù)雜的程序界面都是通過這個(gè)函數(shù)來實(shí)現(xiàn)的。

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

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


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

1包含了Windows機(jī)制的大部分內(nèi)容,下面所講的所有內(nèi)容實(shí)際上都是對張圖的解釋或擴(kuò)充。

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

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

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

這種消息以WM_打頭。

2、通知消息

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

3、自定義消息

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

 

二、           關(guān)于Windows句柄

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

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

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

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

 

三、           消息的傳送

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

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

2、發(fā)送消息

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

還有一點(diǎn),就是SendMessage發(fā)送的消息由于不會被加入到消息隊(duì)列中,所以通過PeekMessageGetMessage是不能獲取到由SendMessage發(fā)送的消息。

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

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

 

四、           消息循環(huán)與窗體過程

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

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

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

  Application.Initialize;  //初始化

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

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

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

第二步:開始調(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)開始

        try

          HandleMessage;

        except

          HandleException(Self);

        end;

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

    end;

  finally

    FRunning := False;

  end;

end;

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

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;

 

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

 

五、           消息與事件

事件本質(zhì)上是對消息的封裝,是IDE編程環(huán)境為了簡化編程而提供的有用的工具。這個(gè)封裝是在窗體過程中實(shí)現(xiàn)的。每種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

了解了這一點(diǎn)后,我們完成可以封裝自己的事件。

通過上面的介紹,相信各位已經(jīng)對Windows消息機(jī)制有了一定的理解了。通過Windows消息編程,我們不但可以實(shí)現(xiàn)很多常規(guī)功能,而且可以實(shí)現(xiàn)很多IDE類庫沒有提供的功能;另外,我們還可以通過消息鉤子,對消息進(jìn)行截獲,改變其默認(rèn)的處理函數(shù),從而突破平臺或軟件功能的限制,極大的擴(kuò)展程序的功能;我們還可以修改默認(rèn)的窗體過程,按自己的要求來響應(yīng)消息;或者自定義消息,實(shí)現(xiàn)程序之間的即時(shí)通訊等等。通過更加深入的學(xué)習(xí),我們還會接觸到更多與Windows消息機(jī)制相關(guān)其它Windows相對比較底層的知識,如果能夠這樣,驀然回首,你會發(fā)現(xiàn)自己原來離“高手”不遠(yuǎn)了。

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多