miniGUI通过接收消息来和外界交互。消息由系统或应用程序产生,系统对输入事件产生消息,系统对应用程序的响应也会产生消息,应用程序可以通过产生消息来完成某个任务,或者与其它应用程序的窗口进行通讯。总而言之,miniGUI 是消息驱动的系统,一切运作都围绕着消息进行。
MSG 消息结构
MSG 消息结构的成员包括该消息所属的窗口(hwnd)、消息标识(message)、消息的WPARAM 型参数(wParam)、消息的 LPARAM 型参数(lParam)以及消息发生的时间。
typedef struct _MSG
{
HWND hwnd;
int message;
WPARAM wParam;
LPARAM lParam;
unsigned int time;
}MSG;
typedef MSG* PMSG;
窗口句柄决定消息所发送的目标窗口。消息标识是一个整数常量,由它来标明消息的类型,每一个消息均有一个对应的预定义标识符。消息的参数对消息的内容作进一步的说明,它的意义通常取决于消息本身,可以是一个整数、位标志或数据结构指针等。
MSGQUEUE消息队列
miniGUI 是消息驱动的系统,消息驱动的含义就是,程序的流程不再是只有一个入口和若干个出口的串行执行线路;相反,程序会一直处于一个循环状态,在这个循环当中,程序不断从外部或内部获取某些事件,比如用户的按键或者鼠标的移动,然后根据这些事件作出某种响应,并完成一定的功能,这个循环直到程序接收到某个消息为止。它的底层实现就是靠消息队列。
typedef struct _QMSG
{
MSG Msg;
struct _QMSG* next;
}QMSG;
typedef QMSG* PQMSG
struct _MSGQUEUE
{
LWORD dwState;
PQMSG pFirstNotifyMsg;
PQMSG pLastNotifyMsg;
MSG* msg;
int len;
int readpos, writepos;
WORD TimerMask;
int loop_depth;
}
消息队列结构_MSGQUEUE的成员包含消息队列类型(dwState)、NOTIFY消息链表表头(pFirstNotifyMsg)、NOTIFY消息链表表尾(pLastNotifyMsg)、POST消息缓冲区(msg)、POST消息缓冲区大小(len)、消息队列读写标志位(readpos, writepos)。
初始化消息队列
BOOL InitMsgQueue (PMSGQUEUE pMsgQueue, int iBufferLen)
{
memset (pMsgQueue, 0, sizeof(MSGQUEUE));
pMsgQueue->dwState = QS_EMPTY;
if (iBufferLen <= 0)
iBufferLen = DEF_MSGQUEUE_LEN;
pMsgQueue->msg = malloc (sizeof (MSG) * iBufferLen);
if (pMsgQueue->msg)
{
memset(pMsgQueue->msg, 0, sizeof (MSG) * iBufferLen);
}
pMsgQueue->len = iBufferLen;
pMsgQueue->TimerMask = 0;
return TRUE;
}
消息队列的初始化主要将dwState赋值为QS_EMPTY类型,并开辟iBufferLen大小的缓冲区,DEF_MSGQUEUE_LEN默认值为16。
发送消息
miniGUI 有两种向窗口过程发送消息的办法:
- 把消息投递到一个先进先出的消息队列中,它是系统中用于存储消息的一块内存区域,每个消息存储在一个消息结构中。
- 或是把消息直接发送给窗口过程,也就是通过消息发送函数直接调用窗口过程函数。
miniGUI有三个主要的发送消息函数
- PostMessage
该函数将消息放到指定窗口的消息队列后立即返回。这种发送方式称为“邮寄”消息。如果消息队列中的邮寄消息缓冲区已满,则该函数返回错误值。PostMessage 一般用于发送一些非关键性的消息。比如在 MiniGUI 中,鼠标和键盘消息就是通过PostMessage 函数发送的。
PostMessage通过调用GetMsgQueue获取消息队列,并调用QueueMessage将消息写入消息队列。消息队列的读取会记录readpos和writepos标志位,当写入一个消息writepos就加1,读了一个消息readpos就加1,如果readpos和writepos相等就表示没有新消息,默认消息队列一次最多存msg_que->len的消息,通常为默认值DEF_MSGQUEUE_LEN,消息满了的话就会丢弃。QueueMessage函数把消息写入队列中,writepos加1,超过最大数之后就归零。
int GUIAPI PostMessage (HWND hWnd

本文围绕miniGUI展开,它是消息驱动系统,一切运作围绕消息。介绍了MSG消息结构成员,阐述MSGQUEUE消息队列底层实现。还说明了消息队列初始化、发送消息的两种方式及三个主要发送函数,最后讲解程序从消息队列获取并处理消息,直至接收到退出消息。
968

被折叠的 条评论
为什么被折叠?



