uC_GUI 窗體管理及消息處理機(jī)制分析_第1頁
uC_GUI 窗體管理及消息處理機(jī)制分析_第2頁
uC_GUI 窗體管理及消息處理機(jī)制分析_第3頁
uC_GUI 窗體管理及消息處理機(jī)制分析_第4頁
uC_GUI 窗體管理及消息處理機(jī)制分析_第5頁
已閱讀5頁,還剩12頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、UCGUI 窗體管理及消息處理機(jī)制分析1各種基本消息介紹及處理流程2UCGUI 中一些基本的消息如下:2WM_CREATE-窗體創(chuàng)建消息2WM_SHOW-顯示窗體消息2WM_SET_ENABLE-設(shè)置窗體不能使用消息2WM_PAINT -窗體重畫消息3WM_TOUCH3WM_KEY3WM_SET_FOCUS3WM_NOTIFY_PARENT4WM_DELETE4WIDGET_HandleActive()4WM_DefaultProc()5WM_TOUCH 消息的處理流程如下:14GUI_PID_Load14GUI_PID_GetState14UCGUI 窗體管理及消息處理機(jī)制分析-多對(duì)話框/模

2、態(tài)窗體/透明窗體支持分析 問題的提出:求助關(guān)于對(duì)話框處理程序中,想在 OK 按鈕按下后想彈出一個(gè)消息框,該怎么做?直接加在程序中好像不行,如何讓消息框彈出后成為模態(tài)窗體呢? 請(qǐng)版主幫幫忙。解析在 UCGUI 中,對(duì)話框只支持單個(gè)對(duì)話框窗體,不支持多個(gè)獨(dú)立的對(duì)話框,現(xiàn)在我們從其源碼來分析一下它為什么支持單個(gè)對(duì)話框窗體以及如何改進(jìn)它以支持多個(gè)獨(dú)立對(duì)話框,要講解這個(gè)問題我們必須首先理解 UCGUI中的窗體消息 LOOP,沒有消息 LOOP 窗體就是死水一潭,不能接受任何外界的輸 入,只是一個(gè)畫在那里的圖畫而已。聲明本文中提到的源碼均為 UCGUI3.24 版源碼,新版 UCGUI 源碼會(huì)有改動(dòng), 請(qǐng)

3、下載本文示例代碼來結(jié)合閱讀本文。摘要: 本文主要介紹了 UCGUI 中的對(duì)話框的消息處理機(jī)制,并指出在現(xiàn)有 UCGUI 上如何增加多窗體支持,并在分析解決問題時(shí)著重介紹了其輸入設(shè)備消息 WM_TOUTCH 及 WM_KEY 兩類消息處理方法,并同時(shí)初步指出一種在 UCGUI 中實(shí)現(xiàn)模UCGUI 窗體管理及消息處理機(jī)制分析態(tài)對(duì)話框以及透明窗體的原理說明,不還有窗體重畫消息 WM_PAINT 消息處理原理。各種基本消息介紹及處理流程對(duì)話框內(nèi)部消息流轉(zhuǎn)及外部消息 LOOP 分 析.UCGUI 是采用的消息驅(qū)動(dòng)的,它專門有對(duì)外的一套收集消息的接口, 在模擬器中, 就是通過 LCD 模擬顯示屏窗口的 M

4、OUSE 消息,將 MOUSE 消息傳入到這個(gè) 接口中, 以驅(qū)動(dòng) UCGUI 中的窗體的。UCGUI 中的消息驅(qū)動(dòng)其實(shí)與 WINDOWS 的是類似的,幾種基本的消息與 WINDOWS 是一樣的,但 UCGUI 的更簡單且消息更少,對(duì)于一些消息的處理得也很簡化,沒有 WINDOWS 那么多的消息種類及復(fù)雜處理。在 WINDOWS 中,如我們處理按鈕控件的點(diǎn)擊事件的是在 WM_COMMAND 消息中,通過按鈕的標(biāo)志 ID 來區(qū)分不同的按鈕,所以 按鈕標(biāo)志 ID 必須不同的,否則無法區(qū)別開(除非不在父窗體的 WM_COMMAND 消息 中處理)。UCGUI 中一些基本的消息如下:WM_CREATE-

5、窗體創(chuàng)建消息每創(chuàng)建一個(gè)窗體完后都會(huì)向該窗體發(fā)送此 消息,如 WM_CreateWindowAsChild 創(chuàng)建完窗體均會(huì)發(fā)一此消息,但在 UCGUI 中對(duì)于此消息的很少處理,如果用戶想在對(duì)話框之后做些初始化 操作或是創(chuàng)建其它子窗體的動(dòng)作,可以處理此消息,不過對(duì)話框一般有專門的初始化消息 WM_INIT_DIALOG,它是在創(chuàng)建對(duì)話框后發(fā)送的。WM_SHOW-顯示窗體消息此消息在 UCGUI 中各控件窗體內(nèi)均未作處 理,如果你通過消息發(fā)送函數(shù)來發(fā)送這類沒有在 UCGUI 中各窗體中處理 的消息,是沒有有什么響應(yīng)的,不要感到奇怪。要顯示窗體一般是通過 WM_ShowWindow()函數(shù)實(shí)現(xiàn)的,這個(gè)

6、函數(shù)做的也就是改變窗體顯示標(biāo)志 WM_SF_ISVIS,并使窗體矩形區(qū)域無效WM_InvalidateWindow()以產(chǎn)生重畫消息。WM_SET_ENABLE-設(shè)置窗體不能使用消息UCGUI 中有一種復(fù)選框?yàn)椴?可改變的,但是這個(gè)功能也不完全,如果你對(duì)著 UCGUI 中的按鈕使用 WM_DisableWindow()來設(shè)置其無效,按鈕照樣還是可以使用,不過要改進(jìn)這些小毛病還是很容易的,這里只是提醒大家 UCGUI 中很多沒有實(shí)現(xiàn) 的小地方,不要到時(shí)候使用時(shí)感到很奇怪,感覺到奇怪時(shí)最好去看看源碼,看看源碼中是否實(shí)現(xiàn)了此功能,不要郁悶。WM_PAINT -窗體重畫消息當(dāng)窗體所在區(qū)域全部或是部分區(qū)

7、域無效 時(shí),系統(tǒng)將會(huì)發(fā)出該重畫消息,將無效區(qū)域重畫,但 UCGUI 中的處理比 較簡單,都是將窗體全部區(qū)域重畫;如果用戶自己想在窗體上畫上一些 信息,一般都在在該消息當(dāng)中畫,UCGUI 中的各種提供的系統(tǒng)控件都必須 在其系統(tǒng)的提供的消息回調(diào)函數(shù)中處理此消息來畫出控件。當(dāng)由外部輸 入操作引起無效窗體區(qū)域產(chǎn)生時(shí),系統(tǒng)都會(huì)在消息處理中發(fā)送該消息到 窗體消息回調(diào)函數(shù)中,以重畫此窗體,在下面講解消息循環(huán)機(jī)制時(shí)將會(huì)著重講解到該消息的產(chǎn)生。透明窗體-經(jīng)常有朋友想知道在 UCGUI 中如何實(shí)現(xiàn)透明窗體,透明窗 窗體顯示在前臺(tái)時(shí),可以看到部分位于其窗體后的內(nèi)容,即透過窗體可以看到窗體背后的圖象。在 UCGUI

8、中有關(guān)于透明窗體的設(shè)置選項(xiàng),可是 沒有實(shí)現(xiàn)此功能,其實(shí)要實(shí)現(xiàn)原理如下:第一透明窗體及其所有子窗體 都必須透明處理;第二是對(duì)于所有有透明屬性的窗體,在繪圖時(shí)必須使 用透明填充功能的矩形填充函數(shù),主要是修改窗體的 WM_PAINT 消息中畫 窗體時(shí)的矩形填充函數(shù)為透明的矩形填充;第三透明的矩形填充函數(shù)的 實(shí)現(xiàn),通常情況下的矩形填充是以當(dāng)前前景色來填充,那么關(guān)鍵就是實(shí) 現(xiàn)畫點(diǎn)函數(shù)的透明填充,要使一個(gè)透明,可以取當(dāng)前顯存中存點(diǎn)的點(diǎn)的 RGB 顏色,然后再與當(dāng)前要畫的顏色按照一個(gè)比例進(jìn)行混合得一個(gè)新的 RGB 值,再將此值畫以屏幕上就可能實(shí)現(xiàn)透明填充的效果。WM_TOUCH-處理類似 MOUSE 的滑動(dòng)

9、操作方式的輸入外設(shè)的消息,如觸 摸屏一般都是將其消息從硬件接收到后轉(zhuǎn)化為該消息形式發(fā)送出去,該 消息中必須包含消息在屏幕中的發(fā)生位置坐標(biāo)及輸入設(shè)備狀態(tài)(按下狀 態(tài)或彈起狀態(tài)),此消息在任務(wù)消息循環(huán)中循環(huán)處理,一旦產(chǎn)生就會(huì)發(fā)送 給當(dāng)前焦點(diǎn)窗體,在后面將詳細(xì)講解該消息的處理機(jī)制。WM_KEY-處理類似 KEY 的按鍵式操作的輸入外設(shè)的消息,消息中必須包含按鍵的按下或彈起狀態(tài),此消息也是在任務(wù)消息循環(huán)中循環(huán)處理, 一旦產(chǎn)生就會(huì)發(fā)送給當(dāng)前焦點(diǎn)窗體,講解消息 LOOP 時(shí)再詳細(xì)介紹。WM_SET_FOCUS-講到剛才上面的兩個(gè)消息時(shí),就反復(fù)提到了當(dāng)前焦點(diǎn) 窗體的概念,所有外部輸入設(shè)備消息都是發(fā)送給當(dāng)前焦

10、點(diǎn)窗體的,用戶 可以通過此消息來設(shè)定當(dāng)前的焦點(diǎn)窗體。外部輸入操作也會(huì)改變當(dāng)前焦 點(diǎn)窗體,如點(diǎn)擊某窗體時(shí)會(huì)在該窗體的 WM_TOUCH 消息處理中設(shè)置該窗體 本身為當(dāng)前焦點(diǎn)窗體;當(dāng)在對(duì)話框中按鍵 TAB 鍵時(shí),同樣也可以將焦點(diǎn) 在對(duì)話框上各控件間切換,這是在對(duì)話框的 WM_KEY 消息中處理實(shí)現(xiàn)的 了解一下 WM_SetFocusOnNextChild()函數(shù),是根據(jù)創(chuàng)建對(duì)話框時(shí)指定 的資源定義數(shù)組中的順序來切換的,并沒有 WIN 下面指定的 TabIndex 這樣一個(gè)值來指定次序的值。WM_NOTIFY_PARENT-這個(gè)消息將子窗體的外設(shè)輸入的消息傳送到它的父窗體,因?yàn)橐话愕那闆r下消息都是在

11、父窗體中統(tǒng)一處理的,如對(duì)話框 中的按鈕點(diǎn)擊事件,一般都是在用戶自定義的窗體消息處理函數(shù)中處理, 所以就必須要子窗體將獲取的輸入外設(shè)的消息傳送給父窗體,這樣才能 在父窗體中進(jìn)行子窗體的點(diǎn)擊事件消息的處理,這個(gè)消息的機(jī)制類似 WIN 下面的 WM_COMMAND 消息,處理該消息時(shí)通過控件 ID 來區(qū)別不同的 控件,通過消息中的通知碼來區(qū)別控件被操作的各種狀態(tài),具體這個(gè)消 息的詳細(xì)說明請(qǐng)參見后面的分析。WM_DELETE-要?jiǎng)h除窗體時(shí)發(fā)送的消息,主要清除窗體數(shù)據(jù)結(jié)構(gòu)所占用 內(nèi)存,此消息主要由 WM_DeleteWindow()函數(shù)發(fā)送了,如點(diǎn)擊 OK 按鈕關(guān) 閉對(duì)話框時(shí),最終會(huì)調(diào)用此函數(shù)來刪除窗體

12、,不過 UCGUI 中沒有最大化 最小化關(guān)閉等系統(tǒng)功能按鈕。最基礎(chǔ)窗體結(jié)構(gòu)注解如下,在該結(jié)構(gòu)中有兩個(gè)很重要的成員,hNextLin 是記載窗體的下一個(gè)窗體,這個(gè)成員用于 遍歷所有已經(jīng)創(chuàng)建的窗體;hNext 是記載窗體下一個(gè)兄弟窗體,這個(gè)成 員用于遍歷每個(gè)窗體對(duì)應(yīng)的子窗體;這個(gè)結(jié)構(gòu)是最基礎(chǔ),一般的控件在 這個(gè)結(jié)構(gòu)之上還會(huì)有一些擴(kuò)展的結(jié)構(gòu),如按鈕對(duì)應(yīng)有 BUTTON_Obj 結(jié)構(gòu)。 typedef struct WM_OBJ_struct WM_Obj;struct WM_OBJ_struct GUI_RECT Rect;/* 窗體矩形區(qū)域 */ GUI_RECT InvalidRect;/* 窗

13、體無效矩形區(qū)域 */WM_CALLBACK* cb;/* 窗體消息回調(diào)函數(shù) */ WM_HWIN hNextLin;/* 窗體下一個(gè)窗體句柄*/WM_HWIN hParent; /* 父窗體句柄*/WM_HWIN hFirstChild; /* 第一子窗體句柄*/ WM_HWIN hNext; /* 下一個(gè)兄弟窗體句柄 */ U16 Status;/* 窗體當(dāng)前狀態(tài) */;WIDGET_HandleActive()基礎(chǔ)控件共通消息處理,在大部分的 UCGUI 控件中都會(huì)在消息回調(diào)函數(shù)的頭部進(jìn)行這個(gè)調(diào)用,如果處理了消息后,就直 接退出消息回調(diào)函數(shù)的調(diào)用。這個(gè)函數(shù)中處理如下消息:WM_GET_ID

14、返窗體控件標(biāo)志 ID.WM_SET_FOCUS設(shè)置當(dāng)前窗體為焦點(diǎn)窗體,設(shè)置完后還必須向該 窗體的父窗體發(fā)送一個(gè) WM_NOTIFY_CHILD_HAS_FOCUS 消息讓其 父窗體更新它記載的當(dāng)前焦點(diǎn)子窗體.WM_GET_HAS_FOCUS獲取當(dāng)前窗體是否為焦點(diǎn)窗體.WM_SET_ENABLE設(shè)置窗體為不可用窗體 .WM_GET_ACCEPT_FOCUS獲取當(dāng)前窗體是否可設(shè)置為焦點(diǎn)窗體.WM_GET_INSIDE_RECT返回窗體內(nèi)框矩形,如按鈕有 3D 效果時(shí)會(huì) 有效果邊框?qū)挾?,?nèi)框矩形就是窗體矩形被邊框剪裁后的矩形.WM_DefaultProc()-窗體默認(rèn)消息處理函數(shù),UCGUI 中提供

15、一些基礎(chǔ)的 控件,這些控件有些共通的消息均在此處理,如下:WM_GETCLIENTRECT獲取窗體矩形區(qū)域,相對(duì)于矩形自身WM_GETORG獲取窗體矩形左上角坐標(biāo).WM_GET_INSIDE_RECT獲取窗體矩形區(qū)域,相對(duì)屏幕.WM_GET_CLIENT_WINDOW獲取窗體客戶區(qū)子窗體句柄,如對(duì)話框 的中的子窗體 FrameWin 即為此種窗體.WM_KEY銨鍵消息處理,通知父窗體子窗體的按鍵消息,有些控件 自己要處理這個(gè)消息,如 Edit 控件處理完此消息后就沒有再調(diào) 用 WM_DefaultProc(),從而沒有將 WM_KEY 消息通父窗體;如 Button 控件,根本沒有對(duì)此消息進(jìn)行

16、處理,直接是通過默認(rèn)處 理發(fā)給了父窗體處理;有些控件如 Checkbox 自己處理該消息, 同時(shí)也調(diào)用默認(rèn)消息處量將此消息通知父窗本,此種消息源窗體 為子控件,目標(biāo)窗體為父窗體。如此處理 WM_KEY 消息完全是UCGUI 中如此做,在 WIN 中并沒有這樣做.WM_GET_BKCOLOR獲取窗體背景色,在此未實(shí)現(xiàn),返回 0xfffffff值,但 FrameWin 窗體實(shí)現(xiàn)了此消息處理.在 UCGUI 的對(duì)話框的窗口消息處理函數(shù)中 OK 按鈕的點(diǎn)擊事件, UCGUI 的處理 方法與 WIN 下面是不同, 它在 WM_NOTIFY_PARENT 消息中處理片段如下:case WM_NOTIFY_

17、PARENT:Id= WM_GetId(pMsg->hWinSrc);/* Id of widget */NCode = pMsg->Data.v;/* Notification code */switch (NCode) case WM_NOTIFICATION_RELEASED:/* React only if released */if (Id = GUI_ID_OK) /* OK Button */ GUI_MessageBox("This text is shownn in a message box","Caption/Title"

18、;, GUI_MESSAGEBOX_CF_MOVEABLE);if (Id = GUI_ID_CANCEL) /* Cancel Button */ GUI_EndDialog(hWin, 1);break;break;UCGUI 中的消息種類不多, 只有差不多不到二十種,但對(duì)于嵌入式系統(tǒng)來說 已經(jīng)完全足夠了,用戶可以自定義消息(從 WM_USER 起)。 WM_NOTIFY_PARENT 這 個(gè)消息是由子窗體傳送給父窗體的, 由消息的名字也可以看出這一點(diǎn),OK 按鈕 也是一個(gè)窗體,當(dāng) MOUSE 點(diǎn)擊在它上面時(shí),UCGUI 首先會(huì)傳遞一個(gè) WM_TOUCH 消 息到 OK 按鈕的窗口消息處理

19、函數(shù),OK 按鈕是一個(gè)系統(tǒng)提供的控件,系統(tǒng)已經(jīng)提 供了一個(gè)默認(rèn)的消息的窗口消息處理函數(shù),這個(gè)函數(shù)會(huì)處理大部分的默認(rèn)窗口消 息并隨后將此消息轉(zhuǎn)發(fā)給父窗體,即 WM_NOTIFY_PARENT 消息,它是由函數(shù) WM_NotifyParent(hObj, Notification)實(shí)現(xiàn)的.WM_TOUCH 消息在按鈕的消息處理函數(shù)_BUTTON_Callback 中的_OnTouch 函數(shù) 中處理,在處理過程完后會(huì)調(diào)用 WM_NotifyParent 向 按 鈕 的父窗體 發(fā) WM_NOTIFY_PARENT 消息告訴對(duì)話框回調(diào)函數(shù)按鈕被點(diǎn)擊了,這個(gè)過程再說詳細(xì) 一點(diǎn)是這樣的: 點(diǎn)擊 OK 按鈕.

20、 產(chǎn)生按鈕 WM_TOUCH 消息.UCGUI 中 的 消 息 LOOP 調(diào) 用 按鈕默認(rèn)的按鈕窗口消息處理函數(shù) _BUTTON_Callback. _OnTouch 默認(rèn)處理按鈕點(diǎn)擊并發(fā)送給父窗體 WM_NOTIFY_PARENT 消息, 這里要注意 MOUSE 點(diǎn)擊后,有三種情況:第一種是點(diǎn)擊后在按鈕范圍內(nèi) 彈 出 MOUSE,這種情況下,會(huì)送的消息中還有一個(gè)通知碼就是 WM_NOTIFICATION_RELEASED;第二種情況是點(diǎn)擊拖到按鈕范圍外彈起 MOUSE,此時(shí)通知碼是 WM_NOTIFICATION_MOVED_OUT;第三種情況是點(diǎn)擊后一直未彈起 MOUSE 的過程中消息通知

21、碼為 WM_NOTIFICATION_CLICKED; 在這個(gè)函數(shù)中還會(huì)處理設(shè)置按鈕點(diǎn)擊后 MOUSE 至未彈起前的按下狀態(tài), 這樣在按鈕下一次畫出時(shí)就會(huì)以按下的狀態(tài)顯示出來.默認(rèn)的對(duì)話框窗體消息處理函數(shù) _FRAMEWIN_Callback收 到 WM_NOTIFY_PARENT 消息并最終傳送該消息到用戶自己定義的對(duì)話框消 息處理函數(shù),這里要注意的一點(diǎn)是,其實(shí)對(duì)話框?qū)υ捒蛑饕怯梢粋€(gè) FrameWin 子窗體構(gòu)成的,這個(gè)子窗體大小為對(duì)話框指定的大小,對(duì)話框 上的其它控件是都是 FrameWin 的子窗體,由_FRAMEWIN_Callback 傳送 的消息首先是傳送到對(duì)話框的默認(rèn)窗體消息回

22、調(diào)函數(shù)_cbDialog,然后再 經(jīng)它傳送到用戶自定義的窗體回調(diào)函數(shù)當(dāng)中。 用戶在自己的對(duì)話框消息處理函數(shù)中處理 WM_NOTIFY_PARENT 消息,即按 鈕的點(diǎn)擊消息,該消息參數(shù)中含有按鈕的 ID 及操作狀態(tài),如果通知碼是 WM_NOTIFICATION_RELEASED,此時(shí)證明一次點(diǎn)擊事件完成。void WM_NotifyParent(WM_HWIN hWin, int Notification) WM_MESSAGE Msg;Msg.MsgId= WM_NOTIFY_PARENT; Msg.Data.v= Notification; WM_SendToParent(hWin, &a

23、mp;Msg);這個(gè)函數(shù)相當(dāng)簡單, 其主要還是 WM_SendToParent 這個(gè)函數(shù)的調(diào)用, 這個(gè)函 數(shù)再調(diào)用 void WM_SendMessage(WM_HWIN hWin, WM_MESSAGE* pMsg), 這個(gè)函數(shù) 是最基本的一個(gè)消息發(fā)送處理函數(shù), 它的第一個(gè)參數(shù)指定了接受這個(gè)要處理的 消息的句柄, 第二個(gè)指定了是什么消息。這個(gè)函數(shù)的主要作用是調(diào)用相應(yīng)窗口的 消息處理函數(shù)來處理消息,如果你有消息要發(fā)送給指定的窗體處理,那么也可以 使用這個(gè)函數(shù)。在上面, 我們剛剛分析了在對(duì)話框內(nèi)部消息處理的流轉(zhuǎn),其中分析了我們?cè)?自己指定的對(duì)話框消息處理函數(shù)當(dāng)中是如何可以獲得按鈕的點(diǎn)擊消息并進(jìn)行

24、處 理的,現(xiàn)在我們就再來分析一下對(duì)話框外面的消息接收:首先是來了解一下 GUI_ExecDialogBox 函數(shù),這個(gè)函數(shù)有幾個(gè)參數(shù): 第一個(gè)是對(duì)話框的資源定義數(shù)組,這個(gè)數(shù)組定義了對(duì)話框的組成子窗體, 其中數(shù)組第一個(gè)成員必須是 FrameWin 窗體,數(shù)組每一個(gè)成員記載了創(chuàng)建 子窗體所用函數(shù)/子窗體 Caption/子窗體標(biāo)志 ID/子窗體的位置及寬高/ 創(chuàng)建窗體時(shí)樣式標(biāo)志/額外傳送的參數(shù). 第二個(gè)參數(shù)是上述的數(shù)組的大小. 第三個(gè)參數(shù)是用戶指定的對(duì)話框窗體消息回調(diào)函數(shù)指針. 第四個(gè)參數(shù)是對(duì)話框的父窗體,默認(rèn)為 0. 第五、六參數(shù)指定對(duì)話框的左上角屏幕位置.GUI_ExecDialogBox 主

25、要完成如下幾件事:根據(jù)傳進(jìn)來的對(duì)話框資源定義數(shù)組創(chuàng)建對(duì)話框及對(duì)話框中的子窗體.根據(jù)傳進(jìn)來的窗口消息處理函數(shù),記載到一全局變量保存,當(dāng)這個(gè)全局 變量中記載的函數(shù)指針為非空時(shí),執(zhí)行消息 LOOP,消息 LOOP 中會(huì)將當(dāng) 前的 MOUSE 及 KEY 消息發(fā)送給當(dāng)前焦點(diǎn)窗體. 當(dāng)對(duì)話框關(guān)閉時(shí),記載對(duì)話窗體消息回調(diào)函數(shù)的全局變量會(huì)被清為 0, 此時(shí)消息 LOOP 就會(huì)退出,對(duì)話框結(jié)束.二、發(fā)現(xiàn)存在的問題-點(diǎn)擊 OK 后無論先關(guān)閉消息框還是對(duì)話框,另一個(gè)不再 響應(yīng).點(diǎn)擊對(duì)話框的 OK 后彈出消息框, 會(huì)出現(xiàn)當(dāng)按下對(duì)話框的 Cancel 關(guān)閉對(duì)話框 后, 彈出的消息框就沒有任何響應(yīng)的情況. 或者是關(guān)閉掉

26、彈出的消息框, 對(duì)話 框就沒有任何響應(yīng)的情形:從外部粗步分析的原因是調(diào)用 MainTask 的線程已經(jīng) 退出了, 這個(gè)線程是在模擬器中開啟的專門用于運(yùn)行 GUI 任務(wù)的線程,它的線程 函數(shù)是 Thread, Thread 函數(shù)里調(diào)用 main,main 中再調(diào)用 MainTask,所以該線 程退出后也就代表 UCGUI 任務(wù)已經(jīng)結(jié)束了。這是從模擬器的角度來分析, 現(xiàn)在我 們分析一下為什么 MainTask 的調(diào)用線程會(huì)這么早退出呢?由我們第一節(jié)中關(guān)于 GUI_ExecDialogBox 所做的幾件中可以分析到, 當(dāng) UCGUI 中有一個(gè)獨(dú)立的窗體退出后_cb 會(huì)被清為 0, 此時(shí)退出 GUI

27、窗口 LOOP. 即 結(jié)束了 UCGUI 窗口消息處理。其實(shí), GUI_MessageBox 彈出的消息框其實(shí)也是一種對(duì)話框, 這最終調(diào)用的 還是 GUI_ExecDialogBox,開始我們就分析過,進(jìn)入這個(gè)函數(shù)后,會(huì)有一個(gè)全局 變量記錄當(dāng)前對(duì)話框窗體的消息處理函數(shù)指針,但是目前的問題如下: 已經(jīng)建立了兩個(gè)這樣的對(duì)話框窗體,這樣一個(gè)全局變量來記載當(dāng)前對(duì)話框的 窗體消息處理函數(shù)指針顯然不夠,而且先前打開的對(duì)話框的的用戶指定的窗 體消息回調(diào)函數(shù)已經(jīng)不再被調(diào)用了,此時(shí)第一個(gè)對(duì)話框的由子窗體回傳到父 窗體的消息均會(huì)傳到第二次打開的對(duì)話框的用戶指定的窗體消息回調(diào)函數(shù)中第二次彈出消息框再次進(jìn)入 GUI_

28、ExecDialogBox 中的 while 循環(huán)后,先前的 對(duì)話框中的 while 循環(huán)就被掛起了,直至第二次的 GUI_ExecDialogBox 中 的 while 循環(huán)退出,無論關(guān)閉消息框還是對(duì)話框,都會(huì)導(dǎo)致知退出第二次消 息 LOOP。第二次消息 LOOP 退出后返回點(diǎn)為彈出消息框后的下一句,直至返 回到第一個(gè)對(duì)話框的 while 循環(huán)后退出 GUI_ExecDialogBox.但我們期待的結(jié)果是,點(diǎn)擊對(duì)話框的 OK 彈出消息框, 關(guān)閉掉對(duì)話框或是消 息框,其它的都要對(duì)話框繼續(xù)有反應(yīng),下面我們就來分析一下如何達(dá)到這個(gè)目標(biāo), 看看要做些什么具體的改動(dòng):三、UCGUI 中的消息 LOOP

29、 處理分析-尋找問題的解決辦法.在我們發(fā)現(xiàn)這個(gè)問題, 我們已經(jīng)粗步分析了,問題不是出在我們編寫程序上, 而上 UCGUI 的內(nèi)部,那么要解決這個(gè)問題, 我們就要進(jìn)一步了解 UCGUI 的窗口體 系。其實(shí)換一句話說,在嵌入式應(yīng)用中,窗口的強(qiáng)大直接決定到 GUI 系統(tǒng)的體積 大小,并不是所有的情況都要有這種支持,當(dāng)然我們希望在下一版本可以有多個(gè) 對(duì)話框的直接支持。創(chuàng)建對(duì)話框:void MainTask(void)GUI_Init(); WM_SetDesktopColor(GUI_RED); WM_SetCreateFlags(WM_CF_MEMDEV);GUI_ExecDialogBox(_aD

30、ialogCreate,GUI_COUNTOF(_aDialogCreate),&_cbCallback, 0, 0, 0);上面是我們創(chuàng)建對(duì)話框的程序,是我們編寫的代碼, GUI_ExecDialogBox()這 個(gè)函數(shù)的作用我們已經(jīng)分析過了,它所做的事用一句話來說就是創(chuàng)建對(duì)話框并進(jìn) 入窗體消息 LOOP 處理,下面將詳細(xì)分析一下 LOOP 消息的處理流程:int GUI_ExecDialogBox(const GUI_WIDGET_CREATE_INFO* paWidget,int NumWidgets, WM_CALLBACK* cb, WM_HWIN hParent, int

31、x0, int y0)_cb = cb;GUI_CreateDialogBox(paWidget, NumWidgets, _cbDialog,hParent, x0, y0);while(_cb)if (!GUI_Exec() GUI_X_ExecIdle();return _r;這個(gè) LOOP 類似我們非常熟悉的 WIN 下面的消息 LOOP, 其原理是一致的.GUI_CreateDialogBox 負(fù)責(zé)創(chuàng)建對(duì)話框的所有子窗體,特別注意它其中一個(gè)參數(shù) 傳入是 Dialog.c 中定義的_cbDialog,這個(gè)函數(shù)什么也沒做,基本上是轉(zhuǎn)而調(diào)用_cb,后面我們會(huì)提到關(guān)于它的修改。_cb 是對(duì)話

32、框的用戶定義窗口消息處理函 數(shù),這里面有一個(gè)判斷,就是_cb 非空時(shí),才進(jìn)行消息 LOOP, _cb 在 Dialog.c 中 的定義為:static WM_CALLBACK* _cb; _cb 是一個(gè)全局變量,我們程序中創(chuàng) 建對(duì)話框與彈出消息框時(shí)兩次調(diào)用了 GUI_ExecDialogBox,后一次的_cb 將會(huì)把 前面的值沖,它是用戶自定義的窗口消息處理函數(shù)。在 while 中有判斷, 那么可見_cb 是在 GUI_Exec 之中是有使用的,對(duì)話框的 FrameWin 子窗體消息流轉(zhuǎn)調(diào)如下面的所示,窗 口消息處理函數(shù)是在 WM_SendMessage 中通過函數(shù)指針的調(diào)用中, 注意內(nèi)部的就

33、是真正被調(diào)用來處 理消息的函數(shù):GUI_Exec->GUI_Exec1->WM_Exec->WM_Exec1->WM_HandlePID->WM_SendMes sage->(*pWin->cb)(pMsg)_FRAMEWIN_Callback->_OnTouch()->(*cb)(pMs g)_cbDialog-> *_cb)(pMsg)_MESSAGEBOX_cbCallback WM_HandlePID()-專門處理類似 MOUSE 的滑動(dòng)操作外設(shè)消息的函數(shù). WM_SendMessage()-基層的發(fā)送消息的函數(shù),即調(diào)用相對(duì)應(yīng)

34、的窗體的消息 回調(diào)函數(shù)來處理消息.現(xiàn)在講到了窗體消息 LOOP,在窗體系統(tǒng)中最根本一點(diǎn)的就是對(duì)外部輸入消息 的處理,窗體就是靠消息驅(qū)動(dòng)的,其處理代碼如下:int WM_Exec1(void)if(WM_pfPollPID)/* Poll PID if necessary */ WM_pfPollPID();if(WM_pfHandlePID)if (WM_pfHandlePID()return 1;/* We have done something . */if(GUI_PollKeyMsg()return 1;/* We have done something . */if(WM_IsAct

35、ive && WM NumInvalidWindows) WM_LOCK();_DrawNext(); WM_UNLOCK();return 1;/* We have done something . */return 0;/* There was nothing to do . */它主要完成如下幾件事: Poll PID中Poll個(gè)詞準(zhǔn)確的意思應(yīng)該是統(tǒng)計(jì)/測(cè)試的意思,這里是調(diào)用用戶 的統(tǒng)計(jì)測(cè)試滑動(dòng)操作外設(shè)的一個(gè)接口,用戶可以通過WM_SetpfPollPID()函 數(shù)來設(shè)置自己用于統(tǒng)計(jì)/測(cè)試滑動(dòng)操作外設(shè)的具體函數(shù)。 處理滑動(dòng)操作外設(shè) WM_TOUCH消息,真正的處理是在函數(shù)

36、WM_HandlePID()中 處理的,在后面滑動(dòng)外設(shè)消息處理流程時(shí)有詳細(xì)說明,在新版中更細(xì)分此消 息為WM_PID_STATE_CHANGED/ WM_MOUSEOVER/ WM_TOUCH三種消息,其實(shí)在WIN下面類似消息的處理更為復(fù)雜,有移動(dòng)/滾動(dòng)/單擊DOWN及UP左右鍵/雙擊 左右鍵等七八種MOUSE消息,而且這些消息又分為窗體體客戶區(qū)與標(biāo)題區(qū) 的差別,標(biāo)題區(qū)的都會(huì)在消息上加上NC的前輟,如WM_NCLBUTTONUP標(biāo)題區(qū)單 擊彈起消息。從這里我們也可以看到UCGUI中非常簡化的處理,簡單得不能 再簡單了,的確是一個(gè)微型的GUI圖形支持系統(tǒng)。 按鍵式外設(shè)消息處理,GUI_PollK

37、eyMsg()函數(shù)在發(fā)現(xiàn)有新的按鍵消息生時(shí)會(huì) 調(diào)用WM_OnKey()將消息發(fā)送到當(dāng)前焦點(diǎn)窗體處理,如果一直處于按鍵按下狀 態(tài)時(shí)則會(huì)將前按鈕的虛擬碼存在一全部變量中,以供GUI_GetKey()調(diào)用來返 回當(dāng)前按下鍵值。UCGUI中有一個(gè)外部的鍵盤接口,外界通過 GUI_StoreKeyMsg()發(fā)送鍵盤消息給UCGUI以驅(qū)動(dòng)鍵盤,在我的模擬器當(dāng)中就 是將LCD模擬顯示屏窗口的所有鍵盤消息通過GUI_StoreKeyMsg()傳送到 UCGUI中以驅(qū)動(dòng)鍵盤消息處理,關(guān)于鍵盤消息的處理UCGUI中也是來一個(gè)處理 一個(gè),沒有任何緩沖處理,如果某些按鈕消息處理用時(shí)過長,就會(huì)造成其后 的一些按鍵消息丟

38、失。static int _Key;/記載當(dāng)前按鍵,GUI_GetKey時(shí)返回此值static int _KeyMsgCnt;/當(dāng)前鍵盤消息數(shù)量static struct int Key;/鍵盤虛擬碼int PressedCnt;/按鍵次數(shù) _KeyMsg;上面是鍵盤消息結(jié)構(gòu),UCGUI中以一個(gè)全局的_KeyMsg鍵盤變量記載當(dāng)前最新 鍵盤消息,當(dāng)前按鍵值用_Key,每產(chǎn)生按下鍵時(shí)用GUI_StoreKey更新一次此 值,UCGUI中沒有按鍵彈起消息的處理。 檢測(cè)是否有無效窗體,如果有無效窗體,則向該無效窗體發(fā)送重畫消息,有 一個(gè)全局變量WM NumInvalidWindows用于記載當(dāng)前無效

39、窗體的數(shù)目,在函 數(shù)_DrawNext()中每次重畫一個(gè)無效窗體,查找無效窗體時(shí)是通過遍歷查找 的方法,先前說過窗體基本結(jié)構(gòu)中有一個(gè)成員hNextLin記載下一個(gè)窗體,就 在是此處用于遍歷所有窗體,找出無效的窗體,發(fā)送WM_PAINT消息給窗體。 注意這里每次畫一個(gè)窗體的原因就是為了不影響窗體的消息處理,如果在此 處用時(shí)太多,會(huì)嚴(yán)重影響消息處理的反應(yīng)速度。了解了 UCGUI 中消息處理的具體流程,那么再來分析這個(gè)先前提到的問題:無 論是消息框還是對(duì)話框哪一個(gè)先被關(guān)掉, 都會(huì)掉用 GUI_EndDialog,將_cb 被清 為零,也就意味著消息 LOOP 到此結(jié)束了,所以后面另外一個(gè)未被關(guān)掉的當(dāng)

40、然不 會(huì)再有任何響應(yīng)了!void GUI_EndDialog(WM_HWIN hWin, int r) _cb = NULL;_r = r;/通知 WM_Exec 等消息 LOOP 返回 WM_DeleteWindow(hWin);/free 該窗體結(jié)構(gòu)占用的內(nèi)存現(xiàn)在我們可以得出一個(gè)結(jié)論:UCGUI 中對(duì)話框的設(shè)計(jì)只支持單窗口的消息處 理,如果要多窗口的支持,可以如同示例中一樣,啟用多任務(wù)支持,不然在單任 務(wù)下一個(gè) MainTask 中只能支持一個(gè)獨(dú)立窗體,但是如果我們只是為了要彈出一 個(gè)消息框而啟動(dòng)一個(gè)任務(wù), 這未免太不實(shí)際。了解 UCGUI 后初步修改路分析如下: 消息傳送-經(jīng)過詳細(xì)的分析

41、,認(rèn)識(shí)到在消息處理中創(chuàng)建一個(gè)對(duì)話框窗 體后,必須建立一個(gè)消息 LOOP 處理,來向 UCGUI 中的窗口捕捉并傳送外 設(shè)的輸入消息,消息的處理實(shí)質(zhì)上是通過 WM_SendMessage 函數(shù)來調(diào)用相 應(yīng)的窗口的消息回調(diào)函數(shù)。 消息 LOOP-如果創(chuàng)建多個(gè)對(duì)話框窗體,則會(huì)進(jìn)入一個(gè)新的消息 LOOP 處理層而掛起原來的消息 LOOP 處理,要避免這種情況發(fā)生必須將消息 LOOP 移到 MainTask 之外,并在創(chuàng)建完所有對(duì)話框之后執(zhí)行消息 LOOP 處 理。 消息分發(fā)-用一個(gè)數(shù)組將所有創(chuàng)建對(duì)話框的自定義消息回調(diào)函數(shù)存 放起來,然后在對(duì)話框消息分布處(_cbDialog 函數(shù)處)對(duì)應(yīng)分發(fā)各個(gè)對(duì) 話

42、框的消息,要注意和解決的問題是,必須根據(jù)消息所對(duì)應(yīng)用窗體來正 確分布。 刪除窗體-在清除獨(dú)立窗體時(shí),必須將此對(duì)話框?qū)?yīng)的用戶自定義的 窗體消息回調(diào)函數(shù)清零,并清除該窗體與其它窗體的數(shù)據(jù)關(guān)系及其占用 資源,使其退出消息處理。四、對(duì) UCGUI 源碼做出部分修改以實(shí)現(xiàn)多獨(dú)立窗口支持. 在第三節(jié)當(dāng)中,我們通過進(jìn)一步的分析源碼,大致找到了解決問題的辦法,但那只是理論上的指導(dǎo),實(shí)際上的修改其實(shí)還會(huì)帶來其它的很多問題,因?yàn)樵赨CGUI 體系中,對(duì)其源碼作出改動(dòng),一定都會(huì)影響到其它的地方,現(xiàn)在我們就實(shí) 際的源碼修改說明幾點(diǎn)要注意的問題:實(shí)際上這個(gè)問題有兩種決辦法,第一種改動(dòng)很小,只須進(jìn)行很小的幾處改動(dòng), 是

43、在之后想到的方法,最先采用的是第二種方法,對(duì) Dialog.c 進(jìn)行多處比較大 的改動(dòng),比較復(fù)雜,但是之所以還在此處列出,其原因是為了讓大家更加清楚的 了解 UCGUI 中的外設(shè)輸入消息處理機(jī)制,只有在了解了第二種方法的基礎(chǔ)上才能 更好的理解第一種方法,否則對(duì)于第一種方法不能理解透。下面分別描述這兩種 修改辦法:第一種辦法: 將 GUI_ExecDialogBox 中的消息 LOOP 提出到 MainTask 這個(gè) UCGUI 應(yīng)用 當(dāng)中,放在所有的對(duì)話框創(chuàng)建之后進(jìn)行;并將在它當(dāng)中增加一個(gè)創(chuàng)建對(duì) 話框個(gè)數(shù)的變量用于統(tǒng)計(jì)當(dāng)前已經(jīng)創(chuàng)建的對(duì)話框數(shù)量,在 Dialog.c 當(dāng)中有一個(gè)現(xiàn)成沒作什么用的全

44、局變量 static int _r;可以改做此用. 將 GUI_ExecDialogBox 中建對(duì)話框時(shí)中調(diào)用 GUI_CreateDialogBox 所傳 的窗體消息回調(diào)函數(shù)改成用戶自定義指定的,而非 Dialog.c 中中默認(rèn)的_cbDialog,這個(gè)函數(shù)的作用就是調(diào)用用戶指定的對(duì)話框窗體消息回調(diào)函 數(shù),所以可以在創(chuàng)建對(duì)話框中直接傳用戶指定的消息回調(diào)函數(shù)。 在 GUI_EndDialog 當(dāng)中相應(yīng)的將當(dāng)前對(duì)話框個(gè)數(shù)減少,每關(guān)閉一個(gè)對(duì)話 框減一. 在 Dialog.c 增加一個(gè)函數(shù)用于返回當(dāng)前已經(jīng)創(chuàng)建的對(duì)話框個(gè)數(shù) GUI_ExecDialogNum(),用于判斷是否應(yīng)該繼續(xù)進(jìn)行消息 LOOP

45、 處理。須要修改的幾個(gè)函數(shù)修改成如下所示:int GUI_ExecDialogBox(const GUI_WIDGET_CREATE_INFO* paWidget,int NumWidgets, WM_CALLBACK* cb, WM_HWIN hParent, int x0, int y0)GUI_CreateDialogBox(paWidget, NumWidgets, cb, hParent, x0, y0);return +_r;void GUI_EndDialog(WM_HWIN hWin, int r) _cb = NULL;_r-; WM_DeleteWindow(hWin);i

46、nt GUI_ExecDialogNum()return _r;void MainTask(void)GUI_Init(); WM_SetDesktopColor(GUI_RED); WM_SetCreateFlags(WM_CF_MEMDEV);GUI_ExecDialogBox(_aDialogCreate,GUI_COUNTOF(_aDialogCreate),&_cbCallback, 0, 0, 0);while(GUI_ExecDialogNum() if (!GUI_Exec() GUI_X_ExecIdle();第二種辦法:1、將原來的_cb 修改成一個(gè)結(jié)構(gòu)為 new_

47、cb 的結(jié)構(gòu)數(shù)組,首設(shè)定最多可創(chuàng)建 10 個(gè)對(duì)話框窗體:typedef struct win_cbWM_CALLBACK* _cb; /用戶自定義消息回調(diào)函數(shù). WM_HWIN hwin;/_cb 消息函數(shù)對(duì)應(yīng)的對(duì)話框窗口.WM_HWIN hclient; /_cb 消息函數(shù)對(duì)應(yīng)的對(duì)話框 FrameWin 窗口客戶區(qū).new_cb,*lpnew_cb;/在_cb 數(shù)組中當(dāng)前可用元素位置. static int dialog_pos = 0;/最多可創(chuàng)建對(duì)話框窗體數(shù)目,其實(shí)可以改成支持無數(shù)個(gè),但這里作簡單處理static int MAX_DIALOG = 10;/檢查是否還有獨(dú)立窗體存在, 以決

48、定是否退出消息 LOOP. int checkHasDialog();/獲取當(dāng)前可用于存放對(duì)話框的位置索引, 創(chuàng)建新對(duì)話框時(shí)調(diào)用. int getDialogIndex(lpnew_cb lp_cb);/對(duì)話框窗口數(shù)組,創(chuàng)建對(duì)話框后, 將其相關(guān)信息記載到該數(shù)組當(dāng)中時(shí),其成員/賦值必須注意幾個(gè)問題,在下面具體代碼中說明:static new_cb _cb10;/新修改后的創(chuàng)建對(duì)話框的函數(shù).int GUI_ExecDialogBox(const GUI_WIDGET_CREATE_INFO* paWidget,int NumWidgets, WM_CALLBACK* cb, WM_HWIN hPa

49、rent, int x0, int y0)dialog_pos = getDialogIndex(_cb);if(dialog_pos != -1) _cbdialog_pos._cb = cb; else return _r; GUI_CreateDialogBox(paWidget,NumWidgets,_cbDialog,hParent,x0, y0);return _r;WM_HWIN GUI_CreateDialogBox(constGUI_WIDGET_CREATE_INFO* paWidget,intNumWidgets, WM_CALLBACK* cb, WM_HWIN hPa

50、rent,int x0, int y0)WM_HWIN hDialog = paWidget->pfCreateIndirect(paWidget,hParent,x0, y0,cb);WM_HWIN hDialogClient = WM_GetClientWindow(hDialog);/加到 GUI_CreateDialogBox 中的,其余不變._cbdialog_pos.hwin = hDialog;_cbdialog_pos+.hclient = hDialogClient;. getDialogIndex(_cb)-創(chuàng)建新的對(duì)話框窗體前,首先必須在對(duì)話框數(shù) 組中查找空位置,如

51、果對(duì)話框窗體已達(dá)最大數(shù),則不可再創(chuàng)建對(duì)話框窗 體,這里只做的是簡單處理,沒有用到動(dòng)態(tài)內(nèi)存分配,主要是因?yàn)槭茄?示,讀者自己可以嘗試支持無限創(chuàng)建對(duì)話框窗體。 _cbdialog_pos._cb = cb-對(duì)話框窗口的窗口消息處理函數(shù)必須在 GUI_CreateDialogBox 調(diào)用之前賦值,因?yàn)樵?GUI_CreateDialogBox 中 就會(huì)用到這個(gè)窗口消息處理函數(shù)。 _cbdialog_pos中的 hwin 等窗口句柄的處理加到創(chuàng)建對(duì)話框函數(shù)當(dāng) 中,千萬不要在調(diào)用創(chuàng)建對(duì)話框函數(shù)后再根據(jù)返回的對(duì)話框句柄來賦這 個(gè)值,因?yàn)樵趧?chuàng)建對(duì)話框函數(shù)中創(chuàng)建子窗體時(shí)就會(huì)調(diào)用到對(duì)話框消息處 理函數(shù),如果 h

52、win 此時(shí)未初始化,則在_cDialog()中就無法分發(fā)消息, 這樣對(duì)話框中的子窗體都無法正確顯示的。 GUI_ExecDialogBox 中的窗口消息 LOOP 改為放到 MainTask 中調(diào)用,因 為當(dāng)我們把窗體都創(chuàng)建了之后,再來執(zhí)行消息 LOOP 的話,可以避免前面 創(chuàng)建獨(dú)立窗體的消息 LOOP 被后面創(chuàng)建的消息 LOOP 中斷的作用。如果我 們要?jiǎng)?chuàng)建多個(gè)對(duì)話框窗體,那么 LOOP 當(dāng)中要分發(fā)消息的對(duì)象也就是多個(gè) 窗體而不是其中的一個(gè),所以要從執(zhí)行單個(gè)對(duì)話框函數(shù)中拿出,由用戶 來寫在圖形應(yīng)用任務(wù)當(dāng)中,如同 WIN 中主窗體的消息 LOOP 處理類似。抽 出后如下代碼所示:void M

53、ainTask(void)GUI_Init(); WM_SetDesktopColor(GUI_RED); WM_SetCreateFlags(WM_CF_MEMDEV);GUI_ExecDialogBox(_aDialogCreate,GUI_COUNTOF(_aDialogCreate),&_cbCallback, 0, 0, 0);while(checkHasDialog()if(!GUI_Exec() GUI_X_ExecIdle();2、在第三節(jié)中第 2 點(diǎn)還說到,要分別調(diào)用各個(gè)對(duì)話框窗體的用戶自定義的窗口 消息函數(shù),必須注意消息的分發(fā),也就根據(jù)消息中的窗體句柄在對(duì)應(yīng)的對(duì)話框

54、數(shù) 組中查找并調(diào)用相應(yīng)窗體的回調(diào)函數(shù),下面我們看一下具體分發(fā)的代碼:static void _cbDialog(WM_MESSAGE* pMsg)char buf100; int i = 0; WM_LOCK(); for(i = 0; i < MAX_DIALOG; i+)if(_cbi._cb != (WM_CALLBACK*)0)if (WM IsWindow(pMsg->hWin)if(pMsg->hWin=_cbi.hwin|_cbi.hclient=pMsg->hWin) (*(_cbi._cb)(pMsg);WM_UNLOCK();_cbDialog 是在

55、對(duì)話框的 FRAMEWIN_cbClient 中調(diào)用的形式如下:if(cb)pMsg->hWin = hParent; (*cb)(pMsg);每個(gè)獨(dú)立對(duì)話框窗體均是這樣,通過其 FrameWin 子窗體來調(diào)用用戶自定義的 窗口消息處理函數(shù),在分發(fā)消息時(shí),其實(shí)只須要根據(jù)消息中的窗體句柄來分發(fā), 因?yàn)槲覀儗?duì)于每個(gè)對(duì)話框,均記載了它的窗體句柄及 FrameWin 子窗體句柄。所 有創(chuàng)建的獨(dú)立窗體的消息均是在_cbDialog 中順序進(jìn)行處理的。3、第三節(jié)中所說的第 3 點(diǎn),獨(dú)立窗體退出的處理:void GUI_EndDialog(WM_HWIN hWin, int r) int i = 0;

56、char buf255;if (!hWin) return; WM_LOCK();if (WM IsWindow(hWin)for(i = 0; i < MAX_DIALOG; i+)if(hWin = _cbi.hwin | _cbi.hclient = hWin)_cbi._cb = NULL;_cbi.hwin = 0;_cbi.hclient = 0;WM_UNLOCK();_r = r; WM_DeleteWindow(hWin);4、關(guān)于類似 MOUSE 的滑動(dòng)操作外設(shè)消息的處理函數(shù) WM_HandlePID().消息 LOOP 中做的最重要的一件事是獲取消息并分發(fā)到相應(yīng)窗體進(jìn)行處理, 這當(dāng)中當(dāng)然包括外設(shè)輸入消息的獲取與處理,WM_HandlePID()函數(shù)就是做這種處 理的,它在 WM_Exec1 中調(diào)用。這個(gè)函數(shù)是專門負(fù)責(zé)處理類似 MOUSE 的滑動(dòng)操作外設(shè)消息,UCGUI 中統(tǒng)稱為 WM_TOUCH 消息,在 GUICoreWMTouch.c 文件當(dāng)中,當(dāng)你點(diǎn)擊或是在觸摸屏上按 下時(shí)均會(huì)產(chǎn)生此消息。它當(dāng)中有兩個(gè)變量:一個(gè)靜態(tài)的舊消息變量;一個(gè)是局部 新消息變量。每次均從消息獲取接口 GUI_PID_GetState()中取當(dāng)前 WM

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論