?? 基于 linux 和 minigui 的嵌入式系統軟件開發指南(二).htm
字號:
<TD>其他</TD>
<TD>可以利用 PostSyncMessage 函數跨線程發送消息,并等待消息的處理結果</TD>
<TD>不能使用 PostSyncMessage、SendAsynMessage
等消息。</TD></TR></TBODY></TABLE><BR><BR>
<P><A id=5 name=5><SPAN class=atitle2>5 窗口的建立和銷毀</SPAN></A></P>
<P><SPAN class=atitle3>5.1 窗口的建立</SPAN><BR>我們知道,MiniGUI 的 API 類似 Win32 的
API。因此,窗口的建立過程和 Windows 程序基本類似。不過也有一些差別。首先我們回顧一下 Windows 應用程序的框架:</P>
<OL class=n01>
<LI>在 WinMain () 中創建窗口,使用以下步驟:創建窗口類、登記窗口類、創建并顯示窗口、啟動消息循環。
<LI>在 WndProc () 中,負責對發到窗口中的各種消息進行響應。 </LI></OL>在 MiniGUI
中也同樣要有這兩個函數。不過稍微有點不同。程序的入口函數名字叫MiniGUIMain
(),它負責創建程序的主窗口。在建立主窗口之后,程序進入消息循環。<BR><BR>
<P>在 Win32 程序中,在建立一個主窗口之前,程序首先要注冊一個窗口類,然后創建一個屬于該窗口類的主窗口。MiniGUI
卻沒有在主窗口中使用窗口類的概念。在 MiniGUI 程序中,首先初始化一個 MAINWINCREATE 結構,該結構中元素的含義是:</P>
<TABLE cellSpacing=0 cellPadding=5 border=0>
<TBODY>
<TR>
<TD>CreateInfo.dwStyle:</TD>
<TD>窗口風格</TD></TR>
<TR>
<TD>CreateInfo.spCaption:</TD>
<TD>窗口的標題</TD></TR>
<TR>
<TD>CreateInfo.dwExStyle :</TD>
<TD>窗口的附加風格</TD></TR>
<TR>
<TD>CreateInfo.hMenu:</TD>
<TD>附加在窗口上的菜單句柄</TD></TR>
<TR>
<TD>CreateInfo.hCursor:</TD>
<TD>在窗口中所使用的鼠標光標句柄</TD></TR>
<TR>
<TD>CreateInfo.hIcon:</TD>
<TD>程序的圖標</TD></TR>
<TR>
<TD>CreateInfo.MainWindowProc:</TD>
<TD>該窗口的消息處理函數指針</TD></TR>
<TR>
<TD>CreateInfo.lx:</TD>
<TD>窗口左上角相對屏幕的絕對橫坐標,以象素點表示</TD></TR>
<TR>
<TD>CreateInfo.ty:</TD>
<TD>窗口左上角相對屏幕的絕對縱坐標,以象素點表示</TD></TR>
<TR>
<TD>CreateInfo.rx:</TD>
<TD>窗口的長,以象素點表示</TD></TR>
<TR>
<TD>CreateInfo.by:</TD>
<TD>窗口的高,以象素點表示</TD></TR>
<TR>
<TD>CreateInfo.iBkColor:</TD>
<TD>窗口背景顏色</TD></TR>
<TR>
<TD>CreateInfo.dwAddData:</TD>
<TD>附帶給窗口的一個 32 位值</TD></TR>
<TR>
<TD>CreateInfo.hHosting:</TD>
<TD>窗口消息隊列所屬</TD></TR></TBODY></TABLE><BR><BR>
<P>其中有如下幾點要特別說明:</P>
<OL class=n01>
<LI>CreateInfo.dwAddData:在程序編制過程中,應該盡量減少靜態變量,但是如何不使用靜態變量而給窗口傳遞參數呢?這時可以使用這個域。該域是一個
32 位的值,因此可以把所有需要傳遞給窗口的參數編制成一個結構,而將結構的指針賦予該域。在窗口過程中,可以使用
GetWindowAdditionalData 函數獲取該指針,從而獲得所需要傳遞的參數。
<LI>CreateInfo.hHosting:該域表示的是將要建立的主窗口使用哪個主窗口的消息隊列。使用其他主窗口消息隊列的主窗口,我們稱為"被托管"的主窗口。當然,這只在
MiniGUI-Threads 版本中有效。
<LI>MainWinProc
函數負責處理窗口消息。這個函數就是主窗口的"窗口過程"。窗口過程一般有四個入口參數,第一個是窗口句柄,第二個是消息類型,第三個和第四個是消息的兩個參數。
</LI></OL><BR><BR>
<P>在準備好MAINWINCREATE 結構之后,就可以調用 CreateMainWindow
函數建立主窗口了。在建立主窗口之后,典型的程序將進入消息循環。如下所示:</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc
border=1><TBODY>
<TR>
<TD><PRE><CODE>int MiniGUIMain (int args, const char* arg[])
{
MSG Msg;
MAINWINCREATE CreateInfo;
HWND hWnd;
// 初始化 MAINWINCREATE 結構
CreateInfo.dwStyle = WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | WS_CAPTION;
CreateInfo.spCaption= "MiniGUI step three";
CreateInfo.dwExStyle = WS_EX_NONE;
CreateInfo.hMenu = createmenu();
CreateInfo.hCursor = GetSystemCursor(0);
CreateInfo.hIcon = 0;
CreateInfo.MainWindowProc = MainWinProc;
CreateInfo.lx = 0;
CreateInfo.ty = 0;
CreateInfo.rx = 640;
CreateInfo.by = 480;
CreateInfo.iBkColor = COLOR_lightwhite;
CreateInfo.dwAddData = 0;
CreateInfo.hHosting = HWND_DESKTOP;
// 建立主窗口
hWnd = CreateMainWindow(&CreateInfo);
if (hWnd == HWND_INVALID)
return 0;
// 顯示主窗口
ShowWindow (hWnd, SW_SHOWNORMAL);
// 進入消息循環
while (GetMessage(&Msg, hWnd)) {
TranslateMessage (&Msg);
DispatchMessage(&Msg);
}
MainWindowThreadCleanup (hWnd);
return 0;
}
</CODE>
</PRE></TD></TR></TBODY></TABLE>注意,和 Windows 程序不同的是,在退出消息循環之后,還要調用一個函數,即
MainWindowThreadCleaup 函數。該函數的工作是銷毀主窗口的消息隊列,一般在線程或者進程的最后調用。<BR><BR>
<P><SPAN class=atitle3>5.2 窗口的銷毀</SPAN><BR>要銷毀一個主窗口,可以利用 DestroyMainWindow
(hWnd) 函數。該函數將銷毀主窗口,但不會銷毀主窗口所使用的消息隊列,而要使用MainWindowThreadCleaup
最終清除主窗口所使用的消息隊列。</P>
<P>一般而言,一個主窗口過程在接收到 MSG_CLOSE 消息之后會銷毀主窗口,并調用 PostQuitMessage
消息終止消息循環。如下所示:</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc
border=1><TBODY>
<TR>
<TD><PRE><CODE>case MSG_CLOSE:
// 銷毀窗口使用的資源
DestroyLogFont (logfont1);
DestroyLogFont (logfont2);
DestroyLogFont (logfont3);
// 銷毀子窗口
DestroyWindow(hWndButton);
DestroyWindow(hWndEdit);
// 銷毀主窗口
DestroyMainWindow (hWnd);
// 發送 MSG_QUIT 消息
PostQuitMessage(hWnd);
return 0;
</CODE>
</PRE></TD></TR></TBODY></TABLE><BR><BR>
<P><A id=6 name=6><SPAN class=atitle2>6
幾個重要消息</SPAN></A><BR>在窗口(包括主窗口和子窗口在內)的生存周期當中,有幾個重要的消息需要仔細處理。下面描述這些消息的概念和典型處理。</P>
<P><SPAN class=atitle3>6.1 MSG_NCCREATE</SPAN><BR>該消息在 MiniGUI
建立主窗口的過程中發送到窗口過程。lParam 中包含了由 CreateMainWindow 傳遞進入的 pCreateInfo
結構指針。您可以在該消息的處理過程中修改 pCreateInfo 結構中的某些值。</P>
<P><SPAN class=atitle3>6.2
MSG_SIZECHANGING</SPAN><BR>該消息窗口尺寸發生變化時,或者建立窗口時發送到窗口過程,用來確定窗口大小。wParam
包含預期的窗口尺寸值,而 lParam 用來保存結果值。MiniGUI 的默認處理是,</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc
border=1><TBODY>
<TR>
<TD><PRE><CODE>case MSG_SIZECHANGING:
memcpy ((PRECT)lParam, (PRECT)wParam, sizeof (RECT));
return 0;
</CODE>
</PRE></TD></TR></TBODY></TABLE><BR><BR>
<P>你可以截獲該消息的處理,從而讓即將創建的窗口位于指定的位置,或者具有固定的大小,比如在 SPINBOX
控件中,就處理了該消息,使之具有固定的大小:</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc
border=1><TBODY>
<TR>
<TD><PRE><CODE>case MSG_SIZECHANGING:
{
const RECT* rcExpect = (const RECT*) wParam;
RECT* rcResult = (RECT*) lPraram;
rcResult->left = rcExpect->left;
rcResult->top = rcExpect->top;
rcResult->right = rcExpect->left + _WIDTH;
rcResult->bottom = rcExpect->left + _HEIGHT;
return 0;
}
</CODE>
</PRE></TD></TR></TBODY></TABLE><BR><BR>
<P><SPAN class=atitle3>6.3
MSG_CHANGESIZE</SPAN><BR>在確立窗口大小之后,該消息被發送到窗口過程,用來通知確定之后的窗口大小。wParam
包含了窗口大小 RECT 的指針。注意應用程序應該將該消息傳遞給 MiniGUI 進行默認處理。</P>
<P><SPAN class=atitle3>6.4 MSG_SIZECHANGED</SPAN><BR>該消息用來確定窗口客戶區的大小,和
MSG_SIZECHANGING 消息類似。wParam 參數包含窗口大小信息,lParam 參數是用來保存窗口客戶區大小的 RECT
指針,并且具有默認值。如果該消息的處理返回非零值,則將采用 lParam 當中包含的大小值作為客戶區的大小;否則,將忽略該消息的處理。比如在
SPINBOX 控件中,就處理了該消息,并使客戶區占具所有的窗口范圍:</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc
border=1><TBODY>
<TR>
<TD><PRE><CODE>case MSG_SIZECHANGED
{
RECT* rcClient = (RECT*) lPraram;
rcClient->right = rcClient->left + _WIDTH;
rcClient->bottom = rcClient->top + _HEIGHT;
return 0;
}
</CODE>
</PRE></TD></TR></TBODY></TABLE><BR><BR>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -