繪制文本
DrawEdge繪制邊框
繪圖圖標繪圖圖標
位圖繪制位圖
矩形繪制矩形
…
無論程序界面多麽復雜,都是由這些函數實現的。
那麽什麽時候調用這些函數呢?顯然,我們需要壹個控制中心來下達命令,我們還需要壹個命令傳輸機制來將命令立即送達目的地。這個控制中心是壹個能量源,就像心臟壹樣,源源不斷地向各處輸送血液。這種命令傳輸機制就是Windows消息機制。Windows消息就像身體裏的血液,是命令傳遞的信使。
Windows消息控制中心通常是三層結構,最頂層是Windows內核。Windows內核維護壹個消息隊列,二級控制中心從這個消息隊列中獲取其管轄的消息,然後進行處理。壹些消息被直接處理,而其他消息被發送到下壹級窗口或控件。二級控制中心壹般是每個Windows應用程序的應用對象。第三級控制中心是Windows窗體對象,每個窗體都有壹個默認的窗體進程,負責處理收到的各種消息。如下圖所示:
(註:windows指windows操作系統;窗口:即windows窗口;窗體:包括帶有句柄的窗口和控件;控件是指壹個控件,它本身可能是也可能不是壹個窗口;應用程序是壹個應用程序,該應用程序可能不使用Windows消息機制。這裏我們討論消息循環的應用程序。)
消息以固定的結構傳輸到應用程序,如下所示:
公共類型消息
hwnd壹樣長
消息長度
wParam壹樣長
lParam壹樣長
時間壹樣長
pt As POINTAPI
結束類型
其中hwnd是表單的句柄,message是指示消息類型的消息常數,wParam和lParam都是32位的附加信息,這取決於消息的類型,time是發送消息的時間,pt是發送消息時鼠標的位置。
Windows操作系統包括以下消息:
1,標準Windows消息:
此消息以WM_開頭。
2.通知消息
通知消息是標準Windows控件的消息。這些控件包括:按鈕、組合框、編輯框、列表框、列表視圖控件、樹視圖控件、工具欄、菜單等。每條消息都以不同的字符串開頭。
3.自定義消息
程序員也可以定制消息。並非每個控件都可以接收消息、轉發消息和繪制自身。只有帶手柄的控件才能做到這壹點。有句柄的控件本質上是壹個窗口,它可以獨立存在,可以作為其他控件的容器,而沒有句柄的控件(如Label)不能獨立存在,只能作為窗口控件的子控件。他們自己不會畫,只能依靠父窗體來畫。
句柄的本質是壹個由系統自動維護的32位值,它在整個操作系統中的任何時刻都是唯壹的。但是,句柄所代表的表單被釋放後,句柄也將被釋放,並且該值可能會被其他表單使用。也就是說,句柄的值是動態的,並且它只是壹個唯壹的標識符。操作系統使用句柄來識別和查找它所代表的對象。
然而,並不是所有的句柄都是窗體的句柄,在Windows系統中還有許多其他類型的句柄,例如畫布(hdc)句柄、畫筆句柄、繪畫畫筆句柄和應用程序句柄。此句柄無法接收消息。但無論是哪種句柄,它都是對象在系統中的唯壹標識。本文只討論表單句柄。
那為什麽把手會讓窗戶如此獨特呢?其實都是因為新聞。由於有了句柄,窗體可以接收消息,因此它知道何時繪制自己,繪制子控件,並知道鼠標何時單擊了窗口的哪個部分,從而做出相應的處理。手柄就像人的身份證,有了它就可以從事各種社會活動;否則,妳要麽是社會看不到的黑戶,要麽妳可以追隨他人,通過他人證明自己的存在。1.從消息隊列中獲取消息:
您可以通過PeekMessage或GetMessage函數從Windows消息隊列中獲取消息。Windows保存的消息隊列按線程分組,這意味著每個線程都有自己的消息隊列。
2.發送消息
將消息發送到指定的表單通常是通過以下兩個函數完成的:SendMessage和PostMessage。這兩個函數的區別在於PostMessage函數只向線程消息隊列添加壹條消息。如果消息添加成功,則返回True,否則返回False,並且消息是否被處理或處理的結果是未知的。另壹方面,SendMessage有些不同。它不是將消息添加到隊列中,而是直接翻譯消息並調用消息處理(即線程將消息發送給自己),並且在消息處理完成之前不會返回。因此,如果我們希望立即執行發送的消息,我們應該調用SendMessage。
還有壹點是SendMessage發送的消息不會被添加到消息隊列中(錯誤:線程發送給其他線程的消息也會被添加到其他線程的消息隊列中,即使這兩個線程處於同壹進程中),因此無法通過PeekMessage或GetMessage獲取SendMessage發送的消息。
此外,有些消息無法成功處理PostMessage,例如wm_settext。所以不是所有的消息都可以使用PostMessage。
還有壹些其他用於發送消息的API函數,如PostThreadMessage、SendMessageCallback、SendMessageTimeout、SendNotifyMessage等。消息流通是應用程序能夠繼續存在的根本原因。如果循環退出,應用程序結束。
讓我們看看Delphi中封裝的消息循環:
第壹步:程序開始運行。
申請。初始化;//初始化
申請。create form(t form 1,form 1);//創建主窗體
申請。跑步;//開始運行,並準備消息循環。
如果沒有創建主窗體,應用程序也可以存在和運行。
步驟2:開始調用HandleMessage。
程序應用。跑步;
開始
f running:= True;
嘗試
AddExitProc(done application);
if FMainForm & lt& gt那就零
開始
案例展示
SW_SHOWMINNOACTIVE: FMainForm。FWindowState:= ws minimized;
SW_SHOWMAXIMIZED: MainFormwindow state:= ws maximized;
結束;
如果FShowMainForm那麽
如果FMainForm。FWindowState = wsMinimized then
最小化else
FMainForm。visible:= True;
重復//註意:循環開始。
嘗試
HandleMessage
除...之外
handle exception(Self);
結束;
直至終止;//循環結束條件
結束;
最後
f running:= False;
結束;
結束;
步驟3:在消息周期中處理消息。
程序應用。HandleMessage
定義變量
msg:TMsg;
開始
如果不是process message(Msg),則為Idle(Msg );
結束;
功能應用。process message(var Msg:TMsg):Boolean;
定義變量
handled:Boolean;
開始
結果:= False
如果PeekMessage(Msg,0,0,0,PM_REMOVE),則
開始
結果:= True
如果味精。消息& lt& gt那就退出吧
開始
已處理:= False
如果賦值(FOnMessage),則為FOnMessage(Msg,Handled);
如果不是is intmsg(Msg)且未處理,則不是IsMDIMsg(Msg),並且
not IsKeyMsg(Msg)和not IsDlgMsg(Msg)then
開始
TranslateMessage
DispatchMessage
結束;
結束
其他
f terminate:= True;
結束;
結束;
表單過程實際上是壹個回調函數。所謂回調函數實際上是Windows操作系統或外部程序調用的函數。回調函數通常具有指定的參數格式,並通過地址傳遞給調用者。窗口進程中調用的Windows操作系統。創建窗口時,需要在分配表單句柄時傳入回調函數的地址。那為什麽我們在編程中通常看不到這個回調函數呢?這是因為我們的編程工具已經為我們生成了壹個默認的表單過程。這個程序需要做的是判斷不同的消息類型,然後做出不同的處理。例如,可以為鍵盤或鼠標輸入等生成事件。事件本質上是消息的封裝,是IDE編程環境提供的簡化編程的有用工具。這種封裝在表單流程中實現。每個IDE都封裝了許多Windows消息,例如,關於激活WM _ activate onclick WM _ xbuttondowoncreate WM _ createondblclick WM _ xbuttonblclick onkeydownwm _ keydowonkeypress的事件消息。WM _ CHAR OnKeyUp WIN _ KEYUP OnPaint WM _ PAINT on resize WM _ SIZE on TIMER WM _ TIMER