[ATL/WTL]_[初级]_[Windows消息循环初解]

来源:互联网 发布:知乐百度网盘 编辑:程序博客网 时间:2024/04/30 16:54

Windows 消息循环初解

场景

  1. Win32窗口编程, 肯定涉及到消息循环. Win32编程基本就是通过处理消息来处理系统任务, 所以Win32窗口编程, 弄懂消息循环是必然的.

说明

1.对于GUI线程,Win32消息循环使用两个队列来来存储消息, 一个是系统消息队列, 一个线程指定的队列. 消息队列是fifo的队列.

 The system maintains a single system message queue and one thread-specific message     queue for each GUI thread.

2.系统在创建线程时不会自动创建一个消息队列, 因为这样会浪费资源,并不是每个线程都需要响应系统消息的. 只有用户执行了一个需要消息队列的操作时系统才会创建消息队列. 比如GetMessage(),PeekMessage().

The system does not automatically create a message queue for each thread. Instead, the system creates a message queue only for threads that perform operations which require a message queue. 

3.线程指定的消息循环是自己创建的, 消息队列是系统创建的, 一般的格式如下.

MSG msg;BOOL bRet;while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0){     if (bRet == -1)    {        // handle the error and possibly exit    }    else    {        TranslateMessage(&msg);         DispatchMessage(&msg);     }}

4.PostMessage 会发送一个消息到消息队列末尾,并立即返回.

 PostMessage places a message at the end of a thread's message queue and returns immediately, without waiting for the thread to process the message. 

5.SendMessage 发送消息MSDN没说是发送到队列末尾, 但应该不会违反规则. SendMessage 发送消息到队列末尾并等待消息循环执行完消息才返回. 窗口过程仍旧是在GUI线程里执行,不是在其他线程里执行.

The SendMessage function is used to send a message directly to a window procedure. SendMessage calls a window procedure and waits for that procedure to process the message and return a result.

6.注意, 线程指定的消息循环不一定需要创建窗口. 我们也可以利用线程消息循环来处理非窗口任务, 看以下例子, 可以使用线程指定内置的消息队列来线程安全的执行消息任务. 这样就不需要自己写临界区或加锁在queue上了.

// test_message_loop1.cpp : 定义应用程序的入口点。//#include "stdafx.h"#include <windows.h>  #include <assert.h>#include <iostream>#include "test_message_loop1.h"int PressAnyKey( const wchar_t *prompt )  {    DWORD        mode;    HANDLE       hstdin;    INPUT_RECORD inrec;    DWORD        count;    wchar_t         default_prompt[] = L"Press a key to continue...\n";    /* Set the console mode to no-echo, raw input, */    /* and no window or mouse events.              */    hstdin = GetStdHandle( STD_INPUT_HANDLE );    if (hstdin == INVALID_HANDLE_VALUE      || !GetConsoleMode( hstdin, &mode )      || !SetConsoleMode( hstdin, 0 ))      return 0;    if (!prompt) prompt = default_prompt;    /* Instruct the user */    WriteConsole(      GetStdHandle( STD_OUTPUT_HANDLE ),      prompt,      lstrlen( prompt ),      &count,      NULL      );    FlushConsoleInputBuffer( hstdin );    /* Get a single key RELEASE */    do ReadConsoleInput( hstdin, &inrec, 1, &count );    while ((inrec.EventType != KEY_EVENT) || inrec.Event.KeyEvent.bKeyDown);    /* Restore the original console mode */    SetConsoleMode( hstdin, mode );    return inrec.Event.KeyEvent.uChar.AsciiChar;  }  typedef enum MyMessage1{    kMessageCopyFile = WM_USER+100}MyMessage;DWORD WINAPI StartThread(void* data){    MSG msg;    BOOL bRet;    std::cout << "StartThread: " << ::GetCurrentThreadId() << std::endl;    while( (bRet = GetMessage( &msg, (HWND)-1, 0, 0 )) != 0)    {        std::cout << "GetMessage: " << msg.message                   << " ThreadID: " << ::GetCurrentThreadId()                   << " wParam: " << msg.wParam                  << " lParam: " << msg.lParam                  << std::endl;        Sleep(2000);        if (bRet == -1)        {            // handle the error and possibly exit        }        else        {            //TranslateMessage(&msg);             //DispatchMessage(&msg);         }    }    std::cout << "StartThread END: " << ::GetCurrentThreadId() << std::endl;    return 0;}class A{public:    virtual ~A(){std::cout << "~A" << std::endl;}};class B : public A{public:    ~B(){std::cout << "~B" << std::endl;}};int main(int argv,char* args[]){    std::cout << "main: " << ::GetCurrentThreadId() << std::endl;    DWORD IDThread;    HANDLE h1 = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) StartThread,NULL,0,&IDThread);    assert(h1);    DWORD IDThread2;    HANDLE h2 = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) StartThread,NULL,0,&IDThread2);    assert(h2);    int code = 0;    while((code = PressAnyKey(NULL))!= 'q')    {        std::cout << code << std::endl;        if(code == 'c')        {            PostThreadMessage(IDThread,WM_QUIT,8,9);            PostThreadMessage(IDThread2,WM_QUIT,8,9);        }else        {            PostThreadMessage(IDThread,kMessageCopyFile,8,9);            PostThreadMessage(IDThread2,kMessageCopyFile,8,9);        }    }    return 0;}

参考

About Messages and Message Queues

Using Messages and Message Queues

0 0
原创粉丝点击