📄 基于 linux 和 minigui 的嵌入式系统软件开发指南(二).htm
字号:
<TBODY>
<TR><!-- Sidebar Gutter -->
<TD width=8><IMG height=21 alt=""
src="基于 Linux 和 MiniGUI 的嵌入式系统软件开发指南(二).files/c.gif" width=5></TD>
<TD width=160><!-- Start TOC -->
<TABLE cellSpacing=0 cellPadding=0 width=160 border=0>
<TBODY>
<TR>
<TD width=160 bgColor=#000000 height=1><IMG height=1 alt=""
src="基于 Linux 和 MiniGUI 的嵌入式系统软件开发指南(二).files/c.gif"
width=160></TD></TR>
<TR>
<TD align=middle
background="基于 Linux 和 MiniGUI 的嵌入式系统软件开发指南(二).files/bg-gold.gif"
height=5><B>内容:</B></TD></TR>
<TR>
<TD width=160 bgColor=#666666 height=1><IMG height=1 alt=""
src="基于 Linux 和 MiniGUI 的嵌入式系统软件开发指南(二).files/c.gif"
width=160></TD></TR>
<TR>
<TD align=right>
<TABLE cellSpacing=0 cellPadding=3 width="98%" border=0>
<TBODY>
<TR>
<TD><A
href="http://www-900.ibm.com/developerWorks/cn/linux/embed/minigui/guide/part2/index.shtml#1">引言</A></TD></TR>
<TR>
<TD><A
href="http://www-900.ibm.com/developerWorks/cn/linux/embed/minigui/guide/part2/index.shtml#2">消息和消息循环</A></TD></TR>
<TR>
<TD><A
href="http://www-900.ibm.com/developerWorks/cn/linux/embed/minigui/guide/part2/index.shtml#3">几个重要的消息处理函数</A></TD></TR>
<TR>
<TD><A
href="http://www-900.ibm.com/developerWorks/cn/linux/embed/minigui/guide/part2/index.shtml#4">MiniGUI-Threads
和 MiniGUI-Lite 在消息处理上的不同</A> </TD></TR>
<TR>
<TD><A
href="http://www-900.ibm.com/developerWorks/cn/linux/embed/minigui/guide/part2/index.shtml#5">窗口的建立和销毁</A></TD></TR>
<TR>
<TD><A
href="http://www-900.ibm.com/developerWorks/cn/linux/embed/minigui/guide/part2/index.shtml#6">几个重要消息</A></TD></TR>
<TR>
<TD><A
href="http://www-900.ibm.com/developerWorks/cn/linux/embed/minigui/guide/part2/index.shtml#7">Hello,
World</A></TD></TR>
<TR>
<TD><A
href="http://www-900.ibm.com/developerWorks/cn/linux/embed/minigui/guide/part2/index.shtml#8">小结</A></TD></TR>
<TR>
<TD><A
href="http://www-900.ibm.com/developerWorks/cn/linux/embed/minigui/guide/part2/index.shtml#author1">关于作者</A></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><!-- End TOC --><!-- Start Related Content Area -->
<TABLE cellSpacing=0 cellPadding=0 width=160 border=0>
<TBODY>
<TR>
<TD width=160 bgColor=#000000 height=1><IMG height=1 alt=""
src="基于 Linux 和 MiniGUI 的嵌入式系统软件开发指南(二).files/c.gif"
width=160></TD></TR>
<TR>
<TD align=middle
background="基于 Linux 和 MiniGUI 的嵌入式系统软件开发指南(二).files/bg-gold.gif"
height=5><B>相关内容:</B></TD></TR>
<TR>
<TD width=160 bgColor=#666666 height=1><IMG height=1 alt=""
src="基于 Linux 和 MiniGUI 的嵌入式系统软件开发指南(二).files/c.gif"
width=160></TD></TR>
<TR>
<TD align=right>
<TABLE cellSpacing=0 cellPadding=3 width="98%" border=0>
<TBODY>
<TR>
<TD><A
href="http://www-900.ibm.com/developerWorks/cn/linux/embed/minigui/guide/part1/index.shtml">主题一:选择MiniGUI-Threads
或者 MiniGUI-Lite</A>
</TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><!-- End Related dW Content Area -->
<TABLE cellSpacing=0 cellPadding=0 width=160 border=0>
<TBODY>
<TR>
<TD width=150 bgColor=#000000 colSpan=2 height=2><IMG height=2
alt="" src="基于 Linux 和 MiniGUI 的嵌入式系统软件开发指南(二).files/c.gif"
width=160></TD></TR>
<TR>
<TD width=150 bgColor=#ffffff colSpan=2 height=2><IMG height=2
alt="" src="基于 Linux 和 MiniGUI 的嵌入式系统软件开发指南(二).files/c.gif"
width=160></TD></TR></TBODY></TABLE><!-- END STANDARD SIDEBAR AREA --></TD></TR></TBODY></TABLE><!-- START SUBTITLE AND CONTENT --><SPAN
class=atitle2>主题二:理解消息循环和窗口过程</SPAN>
<P><A
href="http://www-900.ibm.com/developerWorks/cn/linux/embed/minigui/guide/part2/index.shtml#author1">魏永明</A>
(<A
href="mailto:ymwei@minigui.org">ymwei@minigui.org</A>)<BR>自由撰稿人<BR>2001 年
7 月</P>
<BLOCKQUOTE>在利用 MiniGUI 开发应用程序之前,首先要理解的两个概念就是消息循环和窗口过程。消息循环是事件驱动的 GUI
编程之基础。而窗口则是图形用户界面的最基本交互元素。本文描述了 MiniGUI 中与消息相关的几个重要函数,也描述了
MiniGUI-Threads 和 MiniGUI-Lite 在消息循环实现上的几个不同。本文还讲述了在 MiniGUI
中的窗口建立和销毁过程,并解释了窗口过程的概念以及对一些重要消息的处理。</BLOCKQUOTE>
<P><A id=1 name=1><SPAN class=atitle2>引言</SPAN></A><BR>我们知道,流行的 GUI
编程都有一个重要的概念与之相关,即"事件驱动编程"。事件驱动的含义就是,程序的流程不再是只有一个入口和若干个出口的串行执行线路;相反,程序会一直处于一个循环状态,在这个循环当中,程序从外部输入设备获取某些事件,比如用户的按键或者鼠标的移动,然后根据这些事件作出某种的响应,并完成一定的功能,这个循环直到程序接受到某个消息为止。"事件驱动"的底层设施,就是常说的"消息队列"和"消息循环"。本文将具体描述
MiniGUI 中用来处理消息的几个重要函数,并描述 MiniGUI-Threads 和 MiniGUI-Lite
在消息循环实现上的一些不同。</P>
<P>窗口是 MiniGUI 当中最基本的 GUI
元素,一旦窗口建立之后,窗口就会从消息队列当中获取属于自己的消息,然后交由它的窗口过程进行处理。这些消息当中,有一些是基本的输入设备事件,而有一些则是与窗口管理相关的逻辑消息。本文将讲述
MiniGUI 中的窗口建立和销毁过程,并解释了窗口过程的概念以及对一些重要消息的处理。</P>
<P><A id=2 name=2><SPAN class=atitle2>2 消息和消息循环</SPAN></A><BR>在 MiniGUI
中,消息被如下定义(include/window.h):</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc
border=1><TBODY>
<TR>
<TD><PRE><CODE>352 typedef struct _MSG
353 {
354 HWND hwnd;
355 int message;
356 WPARAM wParam;
357 LPARAM lParam;
358 #ifdef _LITE_VERSION
359 unsigned int time;
360 #else
361 struct timeval time;
362 #endif
363 POINT pt;
364 #ifndef _LITE_VERSION
365 void* pAdd;
366 #endif
367 }MSG;
368 typedef MSG* PMSG;
</CODE>
</PRE></TD></TR></TBODY></TABLE><BR><BR>
<P>一个消息由该消息所属的窗口(hwnd)、消息编号(message)、消息的 WPARAM 型参数(wParam)以及消息的 LPARAM
型参数(lParam)组成。消息的两个参数中包含了重要的内容。比如,对鼠标消息而言,lParam 中一般包含鼠标的位置信息,而 wParam
参数中则包含发生该消息时,对应的 SHIFT 键的状态信息等。对其他不同的消息类型来讲,wParam 和 lParam
也具有明确的定义。当然,用户也可以自定义消息,并定义消息的 wParam 和 lParam 意义。为了用户能够自定义消息,MiniGUI 定义了
MSG_USER 宏,可如下定义自己的消息:</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc
border=1><TBODY>
<TR>
<TD><PRE><CODE>#define MSG_MYMESSAGE1 (MSG_USER + 1)
#define MSG_MYMESSAGE2 (MSG_USER + 2)
</CODE>
</PRE></TD></TR></TBODY></TABLE>用户可以在自己的程序中使用自定义消息,并利用自定义消息传递数据。<BR><BR>
<P>在理解消息之后,我们看消息循环。简而言之,消息循环就是一个循环体,在这个循环体中,程序利用 GetMessage
函数不停地从消息队列中获得消息,然后利用 DispatchMessage
函数将消息发送到指定的窗口,也就是调用指定窗口的窗口过程,并传递消息及其参数。典型的消息循环如下所示:</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc
border=1><TBODY>
<TR>
<TD><PRE><CODE>while (GetMessage (&Msg, hMainWnd)) {
TranslateMessage (&Msg);
DispatchMessage (&Msg);
}
</CODE>
</PRE></TD></TR></TBODY></TABLE>如上所示,GetMessage 函数从 hMainWnd
窗口所属的消息队列当中获得消息,然后调用 TranslateMessage 函数将 MSG_KEYDOWN 和 MSG_KEYUP 消息翻译成
MSG_CHAR 消息,最后调用 DispatchMessage 函数将消息发送到指定的窗口。<BR><BR>
<P>在 MiniGUI-Threads 版本中,每个建立有窗口的 GUI
线程有自己的消息队列,而且,所有属于同一线程的窗口共享同一个消息队列。因此,GetMessage 函数将获得所有与 hMainWnd
窗口在同一线程中的窗口的消息。</P>
<P>而在 MiniGUI-Lite 版本中,只有一个消息队列,GetMessage 将从该消息队列当中获得所有的消息,而忽略 hMainWnd
参数。</P>
<P><A id=3 name=3><SPAN class=atitle2>3 几个重要的消息处理函数</SPAN></A><BR>除了上面提到的
GetMessage 和 TranslateMessage、DispatchMessage 函数以外,MiniGUI
支持如下几个消息处理函数。</P>
<P><B>PostMessage:</B>该函数将消息放到指定窗口的消息队列后立即返回。这种发送方式称为"邮寄"消息。如果消息队列中的邮寄消息缓冲区已满,则该函数返回错误值。在下一个消息循环中,由
GetMessage 函数获得这个消息之后,窗口才会处理该消息。PostMessage 一般用于发送一些非关键性的消息。比如在 MiniGUI
中,鼠标和键盘消息就是通过 PostMessage 函数发送的。</P>
<P><B>SendMessage:</B>该函数和 PostMessage
函数不同,它在发送一条消息给指定窗口时,将等待该消息被处理之后才会返回。当需要知道某个消息的处理结果时,使用该函数发送消息,然后根据其返回值进行处理。在
MiniGUI-Threads
当中,如果发送消息的线程和接收消息的线程不是同一个线程,发送消息的线程将阻塞并等待另一个线程的处理结果,然后继续运行;否则,SendMessage
函数将直接调用接收消息窗口的窗口过程函数。MiniGUI-Lite 则和上面的第二种情况一样,直接调用接收消息窗口的窗口过程函数。</P>
<P><B>SendNotifyMessage:</B>该函数和 PostMessage 消息类似,也是不等待消息被处理即返回。但和
PostMessage
消息不同,通过该函数发送的消息不会因为缓冲区满而丢失,因为系统采用链表的形式处理这种消息。通过该函数发送的消息一般称为"通知消息",一般用来从控件向其父窗口发送通知消息。</P>
<P><B>PostQuitMessage:</B>该消息在消息队列中设置一个 QS_QUIT 标志。GetMessage
在从指定消息队列中获取消息时,会检查该标志,如果有 QS_QUIT 标志,GetMessage 消息将返回
FALSE,从而可以利用该返回值终止消息循环。</P>
<P><A id=4 name=4><SPAN class=atitle2>4 MiniGUI-Threads 和 MiniGUI-Lite
在消息处理上的不同</SPAN></A><BR>表 1 总结了 MiniGUI-Threads 和 MiniGUI-Lite
在消息处理上的不同</P>
<P>表 1 MiniGUI-Threads 和 MiniGUI-Lite 在消息处理上的不同</P>
<TABLE cellSpacing=0 cellPadding=5 border=1>
<TBODY>
<TR>
<TD></TD>
<TD>MiniGUI-Threads</TD>
<TD>MiniGUI-Lite</TD></TR>
<TR>
<TD>多消息队列</TD>
<TD>每个创建窗口的线程拥有独立的消息队列</TD>
<TD>只有一个消息队列。所有窗口共享一个消息队列。除非嵌套消息循环,否则一个程序中只有一个消息循环。</TD></TR>
<TR>
<TD>内建多线程处理</TD>
<TD>是。可以自动处理跨线程的消息传递</TD>
<TD>不能。从一个线程向另外一个线程发送或者邮寄消息时,必须通过互斥处理保护消息队列。</TD></TR>
<TR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -