miniGUI源码分析:消息机制

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

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有三个主要的发送消息函数

  1. 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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值