使用消息和消息队列

Using Messages and Message Queues
使用消息和消息队列
--------------------------------------------------------------------------------
The following code examples demonstrate how to perform the following tasks associated with Microsoft Windows messages and message queues.
下面的代码示例演示如何执行以下任务与微软的Windows消息和消息队列相关。

Creating a Message Loop
创建一个消息循环
Examining a Message Queue
检查消息队列
Posting a Message
发布一条消息
Sending a Message
发送消息
Creating a Message Loop
创建一个消息循环

The system automatically creates a message queue for each thread.
该系统会自动为每个线程创建一个消息队列。
If the thread creates one or more windows, a message loop must be provided;
如果线程创建一个或多个窗口,必须提供一个消息循环;
this message loop retrieves messages from the thread's message queue and dispatches them to the appropriate window procedures.
这个消息循环检索消息从线程的消息队列和调度它们到相应的窗口程序。

Because the system directs messages to individual windows in an application, a thread must create at least one window before starting its message loop.
因为该系统在应用程序中的各个窗口指导的消息,一个线程启动的消息循环之前必须创建至少一个窗口。
Most applications contain a single thread that creates windows.
大多数应用程序都包含一个单独的线程创建的窗口。
A typical application registers the window class for its main window, creates and shows the main window, and then starts its message loop — all in the WinMain function.
一个典型的应用程序注册为它的主窗口的窗口类,创建和显示主窗口,然后启动它的消息循环 - 在WinMain函数。

You create a message loop by using the GetMessage and DispatchMessage functions.
您创建一个消息循环使用GetMessage和DispatchMessage函数。
If your application must obtain character input from the user, include the TranslateMessage function in the loop.
如果您的应用程序必须获得用户输入的字符,包括循环中的TranslateMessage函数。
TranslateMessage translates virtual-key messages into character messages.
TranslateMessage虚拟键消息转换成字符消息。
The following example shows the message loop in the WinMain function of a simple Windows-based application.
下面的例子显示了在一个简单的基于Windows的应用程序的WinMain函数的消息循环。

HINSTANCE hinst;
HWND hwndMain;
 
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpszCmdLine, int nCmdShow)
{
    MSG msg;
    BOOL bRet;
    WNDCLASS wc;
    UNREFERENCED_PARAMETER(lpszCmdLine);
 
    // Register the window class for the main window.
 
    if (!hPrevInstance)
    {
        wc.style = 0;
        wc.lpfnWndProc = (WNDPROC) WndProc;
        wc.cbClsExtra = 0;
        wc.cbWndExtra = 0;
        wc.hInstance = hInstance;
        wc.hIcon = LoadIcon((HINSTANCE) NULL,
            IDI_APPLICATION);
        wc.hCursor = LoadCursor((HINSTANCE) NULL,
            IDC_ARROW);
        wc.hbrBackground = GetStockObject(WHITE_BRUSH);
        wc.lpszMenuName =  "MainMenu";
        wc.lpszClassName = "MainWndClass";
 
        if (!RegisterClass(&wc))
            return FALSE;
    }
 
    hinst = hInstance;  // save instance handle
 
    // Create the main window.
 
    hwndMain = CreateWindow("MainWndClass", "Sample",
        WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
        CW_USEDEFAULT, CW_USEDEFAULT, (HWND) NULL,
        (HMENU) NULL, hinst, (LPVOID) NULL);
 
    // If the main window cannot be created, terminate
    // the application.
 
    if (!hwndMain)
        return FALSE;
 
    // Show the window and paint its contents.
 
    ShowWindow(hwndMain, nCmdShow);
    UpdateWindow(hwndMain);
 
    // Start the message loop.
 
    while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
    {
        if (bRet == -1)
        {
            // handle the error and possibly exit
        }
        else
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
 
    // Return the exit code to the system.
 
    return msg.wParam;
}
The following example shows a message loop for a thread that uses accelerators and displays a modeless dialog box.
下面的例子显示了一个线程,使用加速器和显示一个无模式对话框的消息循环。
When TranslateAccelerator or IsDialogMessage returns TRUE (indicating that the message has been processed), TranslateMessage and DispatchMessage are not called.
当TranslateAccelerator或IsDialogMessage返回TRUE(表示该消息已处理),TranslateMessage和DispatchMessage不叫。
The reason for this is that TranslateAccelerator and IsDialogMessage perform all necessary translating and dispatching of messages.
这样做的原因是,TranslateAccelerator,IsDialogMessage执行所有必要的翻译和调度消息。

HWND hwndMain;
HWND hwndDlgModeless = NULL;
MSG msg;
BOOL bRet;
HACCEL haccel;
//
// Perform initialization and create a main window.
//
 
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
    if (bRet == -1)
    {
        // handle the error and possibly exit
    }
    else
    {
        if (hwndDlgModeless == (HWND) NULL ||
                !IsDialogMessage(hwndDlgModeless, &msg) &&
                !TranslateAccelerator(hwndMain, haccel,
                    &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
}

Examining a Message Queue
检查消息队列
Occasionally, an application needs to examine the contents of a thread's message queue from outside the thread's message loop.
有时,应用程序需要检查的内容以外的线程的消息循环线程的消息队列。
For example, if an application's window procedure performs a lengthy drawing operation, you may want the user to be able to interrupt the operation.
例如,如果应用程序的窗口过程执行一个漫长的绘图操作,您可能希望用户能够以中断操作。
Unless your application periodically examines the message queue during the operation for mouse and keyboard messages, it will not respond to user input until after the operation has completed.
除非你的应用程序,定期检查消息队列在操作鼠标和键盘消息,它不会响应用户的输入,直到手术后已完成。
The reason for this is that the DispatchMessage function in the thread's message loop does not return until the window procedure finishes processing a message.
这样做的原因是,线程的消息循环中DispatchMessage函数不返回,直到窗口过程处理完消息。

You can use the PeekMessage function to examine a message queue during a lengthy operation.
您可以使用PeekMessage函数来检查一个漫长的操作过程中的一个消息队列。
PeekMessage is similar to the GetMessage function;
PeekMessage的是类似的GetMessage函数;
both check a message queue for a message that matches the filter criteria and then copy the message to an MSG structure.
检查消息队列的消息相匹配的过滤条件,然后复制消息到MSG结构。
The main difference between the two functions is that GetMessage does not return until a message matching the filter criteria is placed in the queue, whereas PeekMessage returns immediately regardless of whether a message is in the queue.
这两个函数之间的主要区别在于,GetMessage函数不返回直到符合筛选条件的消息被放置在队列中,而PeekMessage的立即返回,不管消息是否是队列中。

The following example shows how to use PeekMessage to examine a message queue for mouse clicks and keyboard input during a lengthy operation.
下面的示例演示如何使用PeekMessage来检查一个漫长的操作过程中的鼠标点击和键盘输入的消息队列。


HWND hwnd;
BOOL fDone;
MSG msg;
 
// Begin the operation and continue until it is complete
// or until the user clicks the mouse or presses a key.
 
fDone = FALSE;
while (!fDone)
{
    fDone = DoLengthyOperation(); // application-defined function
 
    // Remove any messages that may be in the queue. If the
    // queue contains any mouse or keyboard
    // messages, end the operation.
 
    while (PeekMessage(&msg, hwnd,  0, 0, PM_REMOVE))
    {
        switch(msg.message)
        {
            case WM_LBUTTONDOWN:
            case WM_RBUTTONDOWN:
            case WM_KEYDOWN:
                //
                // Perform any required cleanup.
                //
                fDone = TRUE;
        }
    }
}
Other functions, including GetQueueStatus and GetInputState, also allow you to examine the contents of a thread's message queue.
其他功能,包括GetQueueStatus和GetInputState,也让你来检查线程的消息队列的内容。
GetQueueStatus returns an array of flags that indicates the types of messages in the queue;
GetQueueStatus返回一个数组,表示队列中的消息类型的标志;
using it is the fastest way to discover whether the queue contains any messages.
使用它是最快的方式来发现队列中是否包含任何消息。
GetInputState returns TRUE if the queue contains mouse or keyboard messages.
GetInputState返回TRUE,如果队列中包含鼠标或键盘消息。
Both of these functions can be used to determine whether the queue contains messages that need to be processed.
这些功能都可以用来判断队列是否包含需要处理的消息。

Posting a Message
发布一条消息
You can post a message to a message queue by using the PostMessage function.
你可以发布消息到消息队列使用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.
PostMessage的放置在一个线程的消息队列的消息,并立即返回,无需等待的线程来处理消息。
The function's parameters include a window handle, a message identifier, and two message parameters.
函数的参数包括一个窗口句柄,消息标识符和两个消息参数。
The system copies these parameters to an MSG structure, fills the time and pt members of the structure, and places the structure in the message queue.
系统会将这些参数MSG结构,填补了时间和PT成员结构,并将其放置在消息队列中的结构。

The system uses the window handle passed with the PostMessage function to determine which thread message queue should receive the message.
该系统使用PostMessage函数来确定哪个线程消息队列收到消息的窗口句柄传递。
If the handle is HWND_TOPMOST, the system posts the message to the thread message queues of all top-level windows.
如果句柄是HWND_TOPMOST,系统职位的所有顶层窗口的线程消息队列的消息。

You can use the PostThreadMessage function to post a message to a specific thread message queue.
你可以使用PostThreadMessage函数发布消息到一个特定的线程消息队列。
PostThreadMessage is similar to PostMessage, except the first parameter is a thread identifier rather than a window handle.
PostThreadMessage和PostMessage类似,除了第一个参数是线程标识符,而不是一个窗口句柄。
You can retrieve the thread identifier by calling the GetCurrentThreadId function.
你可以检索GetCurrentThreadId函数调用的线程标识符。

Use the PostQuitMessage function to exit a message loop.
使用PostQuitMessage函数退出消息循环。
PostQuitMessage posts the WM_QUIT message to the currently executing thread.
调用PostQuitMessage职位当前执行的线程WM_QUIT消息。
The thread's message loop terminates and returns control to the system when it encounters the WM_QUIT message.
线程的消息循环的终止和返回控制系统,当它遇到WM_QUIT消息。
An application usually calls PostQuitMessage in response to the WM_DESTROY message, as shown in the following example.
应用程序通常调用响应WM_DESTROY消息中调用PostQuitMessage,在下面的例子所示。

case WM_DESTROY:
 
    // Perform cleanup tasks.
 
    PostQuitMessage(0);
    break;

Sending a Message
发送消息
The SendMessage function is used to send a message directly to a window procedure.
SendMessage函数用来直接将消息发送到窗口过程。
SendMessage calls a window procedure and waits for that procedure to process the message and return a result.
SendMessage函数调用窗口过程,并等待该程序处理该消息,并返回结果。

A message can be sent to any window in the system;
消息可以被发送到任何窗口系统;
all that is required is a window handle.
所有需要的是一个窗口句柄。
The system uses the handle to determine which window procedure should receive the message.
该系统采用手柄,以确定窗口过程应该收到的消息。

Before processing a message that may have been sent from another thread, a window procedure should first call the InSendMessage function.
窗口过程处理,可能已经从另一个线程发送消息之前,应先致电InSendMessage功能。
If this function returns TRUE, the window procedure should call ReplyMessage before any function that causes the thread to yield control, as shown in the following example.
如果这个函数返回TRUE,窗口过程之前调用任何函数会导致线程产量控制ReplyMessage,在下面的例子所示。

case WM_USER + 5:
    if (InSendMessage())
        ReplyMessage(TRUE);
 
    DialogBox(hInst, "MyDialogBox", hwndMain, (DLGPROC) MyDlgProc);
    break;

A number of messages can be sent to controls in a dialog box.
可以发送的邮件数量控制在一个对话框。
These control messages set the appearance, behavior, and content of controls or retrieve information about controls.
这些控制消息的外观,行为,内容和控制设置或检索有关控件的信息。
For example, the CB_ADDSTRING message can add a string to a combo box, and the BM_SETCHECK message can set the check state of a check box or radio button.
例如,CB_ADDSTRING消息可以添加一个字符串到一个组合框,,和“BM_SETCHECK消息可以设置一个复选框或单选按钮的选中状态。

Use the SendDlgItemMessage function to send a message to a control, specifying the identifier of the control and the handle of the dialog box window that contains the control.
使用子控件函数将消息发送到控制,指定标识符的控制和对话框窗口,其中包含控制手柄。
The following example, taken from a dialog box procedure, copies a string from a combo box's edit control into its list box.
下面的例子,从一个对话框程序,从一个组合框的编辑控件,将其列表框中的字符串复制。
The example uses SendDlgItemMessage to send a CB_ADDSTRING message to the combo box.
例如使用子控件,,发送CB_ADDSTRING的组合框的消息。

HWND hwndCombo;
int cTxtLen;
PSTR pszMem;
 
switch (uMsg)
{
    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
            case IDD_ADDCBITEM:
                // Get the handle of the combo box and the
                // length of the string in the edit control
                // of the combo box.
 
                hwndCombo = GetDlgItem(hwndDlg, IDD_COMBO);
                cTxtLen = GetWindowTextLength(hwndCombo);
 
                // Allocate memory for the string and copy
                // the string into the memory.
 
                pszMem = (PSTR) VirtualAlloc((LPVOID) NULL,
                    (DWORD) (cTxtLen + 1), MEM_COMMIT,
                    PAGE_READWRITE);
                GetWindowText(hwndCombo, pszMem,
                    cTxtLen + 1);
 
                // Add the string to the list box of the
                // combo box and remove the string from the
                // edit control of the combo box.
 
                if (pszMem != NULL)
                {
                    SendDlgItemMessage(hwndDlg, IDD_COMBO,
                        CB_ADDSTRING, 0,
                        (DWORD) ((LPSTR) pszMem));
                    SetWindowText(hwndCombo, (LPSTR) NULL);
                }
 
                // Free the memory and return.
 
                VirtualFree(pszMem, 0, MEM_RELEASE);
                return TRUE;
            //
            // Process other dialog box commands.
            //
 
        }
    //
    // Process other dialog box messages.
    //
 
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值