UI线程消息处理过程

只有在使用MFC框架时才有UI线程和工作者线程之分。UI线程与工作者线程的区别是操作系统为UI线程创建并维护了一个消息队列。

其实线程在创建时(无论是API还是MFC),都是工作者线程。当线程调用发送消息或提取消息或图形用户界面相关的函数时,系统才为其创建一个消息队列THREADINFO结构,这时的线程才称为UI线程。

VC开发的控制台程序的主线程是工作线程,其他程序的主线程为UI线程。_beginthreadex/CreateThread等函数创建的线程默认为工作线程,AfxBeginThread可以根据参数创建工作者线程和UI线程。

 

1 从用户输入到系统消息队列

操作系统会监视计算机的键盘和鼠标等输入设备,为每一个输入事件生成一个消息,将消息统一临时放到“系统消息队列”内。其中消息的窗口句柄由系统根据鼠标或光标所在区域计算出的。

 

2 从系统消息队列到线程消息队列

系统有专门的线程负责从系统消息队列中取出消息,根据消息的目标对象(窗口句柄),将消息投递到创建它的UI线程对应的消息队列中。每个UI线程有且仅有一个消息队列。

 

3 UI线程处理消息

UI线程启动一个消息循环(Message Loop),每次从本线程所对应的消息队列中取出一条消息,然后根据消息所包容的信息,将其转发给特定的窗体对象,此窗体对象所对应的“窗体过程”函数被调用以处理这些消息。

    MSG msg; // 代表一条消息

    BOOL bRet;

    // UI线程消息队列中取出一条消息

    while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)

    {

        if (bRet == -1)

        {

            // 错误处理代码,通常是直接退出程序

        }

        else

        {

            TranslateMessage(&msg); // 转换消息格式

            DispatchMessage(&msg); // 分发消息给相应的窗体

        }

    }

 

GetMessage()等到有消息才返回,peekmessage()则马上返回消息或空值;GetMessage()获得消息后从队列中删除(WM_PAINT除外),peekmessage()则根据参数PM_NOREMOVEPM_REMOVE来决定要不要删除。

TranslateMessage()函数主要用于将WM_KEYDOWNWM_KEYUP消息转换WM_CHAR消息。所以如果要截获WM_KEYDOWNWM_KEYUP消息,需要重载窗体类的PreTranslateMessage()函数进行分析。

DispatchMessage()函数根据取出的消息中所包含的窗体句柄,将这一消息转发给引此句柄所对应的窗体对象。负责响应消息的函数称为窗体过程(Window Procedure)。如果需要自定义处理,则重载窗体类的DefWindowProc()函数。窗体过程是一个函数,每个窗体一个,形式如下:

LRESULT CALLBACK MainWndProc(……)

    {

        //……

        switch (uMsg) // 依据消息标识符进行分类处理

        {

            case WM_CREATE:

                // 初始化窗体.

                return 0;

            case WM_PAINT:

                // 绘制窗体

                return 0;

            //

            // 处理其他消息

            //

            default:

                // 转去调用系统默认的消息处理函数

                return DefWindowProc(hwnd, uMsg, wParam, lParam);

        }

        //……

    }

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值