【问题标题】:WM_COMMAND message not being received by the Windows ProcedureWindows 过程未收到 WM_COMMAND 消息
【发布时间】:2012-02-27 02:41:56
【问题描述】:

我正在使用快捷方式/上下文菜单创建系统托盘程序,但我似乎无法在 Windows 过程中接收 WM_COMMAND 消息。当我单击菜单项时它根本不会发送,并且我一直在检查我是否正确设置了菜单。

这是我的代码:

#include <Windows.h>
#include <stdio.h>
#include "resource.h"
#define WM_TRAYICON (WM_USER + 0x0001) //a custom message for the notification icon

HWND hwnd; //window handle
HINSTANCE hinst; //module handle
WNDCLASSEX wnd; //window class
MSG msg; //event message or notification
NOTIFYICONDATA nid; //notification icon object
HMENU cmenu;
MENUITEMINFO menuitem1;
MENUITEMINFO menuitem2;
CURSORINFO cursor;

LRESULT CALLBACK MainWProc ( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
    switch( uMsg )
    {
    case WM_COMMAND:
        printf("asfd\r\n");
        break;
    case WM_CREATE:
        printf("just created\r\n");
        break;
    case WM_TRAYICON:
        switch( LOWORD(lParam) )
        {
        case WM_CONTEXTMENU:
            GetCursorInfo( &cursor );
            //printf("xPos: %d\r\nyPos = %d\r\n\r\n", xPos, yPos );
            TrackPopupMenuEx( cmenu, TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_NOANIMATION | TPM_HORIZONTAL | TPM_VERTICAL, cursor.ptScreenPos.x, cursor.ptScreenPos.y,  hwnd, NULL );
            //DestroyMenu(
            break;
        }
        break;
    case WM_INITMENU:
        printf("open menu\r\n");
        break;
    case WM_DESTROY:
        //clean things up
        Shell_NotifyIcon( NIM_DELETE, &nid );
        break;
    default:
        break;
    }

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

void main()
{
    int result;

    hinst = GetModuleHandle( NULL );
    cursor.cbSize = sizeof( cursor );

    memset( &wnd, 0, sizeof( wnd ) );
    wnd.cbSize = sizeof( wnd );
    wnd.lpszClassName = "MainWClass";
    wnd.lpfnWndProc = MainWProc;
    wnd.hInstance = hinst;
    result = RegisterClassEx( &wnd );

    hwnd = CreateWindowEx
        (
        0, //extended styles
        wnd.lpszClassName, //class name
        "Main Window", //window name
        WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL | WS_MINIMIZEBOX, //style tags
        CW_USEDEFAULT, //horizontal position
        CW_USEDEFAULT, //vertical position
        CW_USEDEFAULT, //width
        CW_USEDEFAULT, //height
        (HWND) NULL, //parent window
        (HMENU) NULL, //class menu
        (HINSTANCE) wnd.hInstance, //some HINSTANCE pointer
        NULL //Create Window Data?
        );
    if( !hwnd )
    {
        printf("CreateWindowEx failed: %d\n", GetLastError() );
        Sleep( INFINITE );
    }

    nid.cbSize = sizeof( nid );
    nid.hWnd = hwnd;
    nid.uID = 1;
    nid.uVersion = NOTIFYICON_VERSION_4;
    nid.uCallbackMessage = WM_TRAYICON;
    nid.hIcon = LoadIcon( hinst, MAKEINTRESOURCE( IDI_ICON1 ) );
    strcpy( nid.szTip, "My Tooltip!" );
    nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP | NIF_SHOWTIP;

    cmenu = CreatePopupMenu();
    menuitem1.cbSize = sizeof( menuitem1 );
    menuitem1.fMask = MIIM_TYPE;
    menuitem1.fType = MFT_STRING;
    menuitem1.hSubMenu = NULL;
    //menuitem1.cch = ;
    menuitem1.dwTypeData = "Open a world of wonder!";
    InsertMenuItem( cmenu, 0, true, &menuitem1 );

    if( ! Shell_NotifyIcon( NIM_ADD, &nid ) )
    {
        printf("Shell_NotifyIcon( NIM_ADD, &nid ) failed.\r\n");
        Sleep( INFINITE );
    }
    if( ! Shell_NotifyIcon( NIM_SETVERSION, &nid ) )
    {
        printf("Shell_NotifyIcon( NIM_SETVERSION, &nid ) failed.\r\n");
        Sleep( INFINITE );
    }

    UpdateWindow( hwnd );
    for( ; ; )
    {
        if( GetMessage(&msg, hwnd, 0, 0) )
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
}

【问题讨论】:

  • 为什么在基于 GUI 的应用程序中使用 printf?使用 TRACE 宏在调试窗口中查看输出。
  • 嗯,我更喜欢在控制台上看到它。
  • 这是您的选择。但对我来说没有意义。 Debug-Windows 只不过是一个控制台。为 GUI 启动另一个控制台并不意味着合乎逻辑。您的 GUI 程序应该以WinMain 开头,而不是main(有很多原因)。因此,如果您的程序以WinMain 开头,printf 将无法工作。
  • 您可以从 Windows 程序中获取 printf 输出,前提是您使用 STDOUT 集显式启动它:c:\users\yourname&gt; program.exe &gt; output.txt 2&gt;&amp;1 或从 start->run 或快捷方式 cmd.exe /s /c " program.exe &gt; output.txt 2&gt;&amp;1 "。 Windows 子系统程序可以有一个 STDOUT,它只是默认没有一个。相反,Console 子系统程序默认有一个,但也可以不创建。
  • @Ajay 完成后我将转换到 WinMain,但现在我可以享受控制台。我没有使用 MFC,所以我认为我不能使用 TRACE。

标签: winapi visual-c++ user-interface contextmenu message-queue


【解决方案1】:

嗯,你传递了TPM_RETURNCMD 标志,意思是“不要发布WM_COMMAND 消息。只需返回你会发布的值。”

【讨论】:

  • 哦该死....我认为“返回菜单项标识符”意味着将其返回给 wndproc。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-21
  • 1970-01-01
  • 1970-01-01
  • 2014-02-26
  • 1970-01-01
  • 2018-05-15
相关资源
最近更新 更多