Win32工具栏下拉按钮消息处理

时间:2014-01-09 00:24:04

标签: c++ winapi notifications messages

我的应用程序中有一个窗口的工具栏。我已阅读 MSDN docs 并可以处理命令和通知消息。我的问题是附加到工具栏上的按钮的下拉菜单。菜单项打开模式对话框并等待用户完成设置更改。在用户单击“确定”或“取消”后,焦点返回到主窗口,但是,工具栏仍然是鼠标左键按下的印象所以每次我将鼠标拖到单击按钮所需的工具栏按钮上'按钮被检查'状态和'出现'被按下。

问题是否与跟踪鼠标事件有关?

这是窗口过程中的通知消息处理:

case WM_NOTIFY:
        {
            LPNMHDR lpnm = ( ( LPNMHDR )lParam );
            LPNMTOOLBAR lpnmTB = ( ( LPNMTOOLBAR )lParam );

            switch( lpnm->code )
            {
            case TBN_DROPDOWN:
                {
                    // Get the coordinates of the button.
                    RECT rc;
                    SendMessage( lpnmTB->hdr.hwndFrom, TB_GETRECT, ( WPARAM )lpnmTB->iItem, ( LPARAM )&rc );

                    // Convert to screen coordinates.            
                    MapWindowPoints( lpnmTB->hdr.hwndFrom, HWND_DESKTOP, ( LPPOINT )&rc, 2 );                         

                    // handle dropdown menus
                    return HandleTexEditDropdown( hWnd, lpnmTB, rc );
                }
            default:
                break;
            }
            break;
        }

这是处理TexEditDropdown():

LRESULT CALLBACK CWindowManager::HandleTexEditDropdown( HWND hWnd, LPNMTOOLBAR lpnm, RECT &rc )
{
    HRESULT hr = S_OK;

    switch( lpnm->iItem )
    {
    case IDM_EDITTEXTURE_FILL:
        {
            // Get the menu.
            HMENU hMenuLoaded = LoadMenu( GetModuleHandle( NULL ), MAKEINTRESOURCE( IDR_BUCKETFILL ) ); 

            // Get the submenu for the first menu item.
            HMENU hPopupMenu = GetSubMenu( hMenuLoaded, 0 );

            // Set up the pop-up menu.
            // In case the toolbar is too close to the bottom of the screen, 
            // set rcExclude equal to the button rectangle and the menu will appear above 
            // the button, and not below it.
            TPMPARAMS tpm;

            tpm.cbSize    = sizeof( TPMPARAMS );
            tpm.rcExclude = rc;

            // Show the menu and wait for input. 
            // If the user selects an item, its WM_COMMAND is sent.

            INT nCmd = TrackPopupMenuEx( hPopupMenu, 
                TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_VERTICAL | TPM_RETURNCMD, 
                rc.left, rc.bottom, hWnd, &tpm );

            DestroyMenu( hMenuLoaded );
            switch( nCmd )
            {
            case IDM_BUCKETFILLSETTINGS:
                DialogBox( GetModuleHandle( NULL ), 
                    MAKEINTRESOURCE( IDD_TEXEDITBUCKETFILL ), 
                    hWnd, 
                    ( DLGPROC )TexEditSettingsProc );
                break;
            default:
                return 0;
            }

            SendMessage( ( HWND )lpnm->hdr.hwndFrom, TB_MARKBUTTON, lpnm->iItem, MAKELPARAM( FALSE, 0 ) );
            UpdateWindow( hWnd );
            SetStateChange();
            return 1;
        }
    case IDM_EDITTEXTURE_RECOVER:
        {
            // Get the menu.
            HMENU hMenuLoaded = LoadMenu( GetModuleHandle( NULL ), MAKEINTRESOURCE( IDR_RECOVER ) ); 

            // Get the submenu for the first menu item.
            HMENU hPopupMenu = GetSubMenu( hMenuLoaded, 0 );

            // Set up the pop-up menu.
            // In case the toolbar is too close to the bottom of the screen, 
            // set rcExclude equal to the button rectangle and the menu will appear above 
            // the button, and not below it.
            TPMPARAMS tpm;

            tpm.cbSize    = sizeof( TPMPARAMS );
            tpm.rcExclude = rc;

            // Show the menu and wait for input. 
            // If the user selects an item, its WM_COMMAND is sent.

            INT nCmd = TrackPopupMenuEx( hPopupMenu, 
                TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_VERTICAL | TPM_RETURNCMD, 
                rc.left, rc.bottom, hWnd, &tpm );

            DestroyMenu( hMenuLoaded );

            switch( nCmd )
            {
            case IDM_RECOVERFILE:
                {
                    WCHAR wcs[ MAX_PATH ] = L"",
                        wcsFiletype[ MAX_PATH ] = L"",
                        wcsFilename[ MAX_PATH ] = L"";
                    D3DXIMAGE_INFO info;

                    // get currently loaded image info
                    if( FAILED( hr = CTextureEditor::GetImageInfo( &info ) ) )
                    {
                        DebugStringDX( ClassName, "Failed to CTextureEditor::GetImageInfo() at AuxiliaryViewportProcess()", __LINE__, hr );
                        break;
                    }

                    if( !CTextureEditor::CatImageFileType( info.ImageFileFormat, wcsFiletype ) )
                    {
                        DebugStringDX( ClassName, "Invalid image filetype at AuxiliaryViewportProcess()", __LINE__, hr );
                        break;
                    }

                    wsprintf( wcs, L"GDEImage Filetype (*%s)", wcsFiletype );
                    memcpy( &wcs[ 26 ], L"*", sizeof( WCHAR ) );
                    memcpy( &wcs[ 27 ], wcsFiletype, 4 * sizeof( WCHAR ) );

                    // Declare and initialize an OPENFILENAME struct to use for OpenFile Dialog
                    OPENFILENAME ofn;
                    ZeroMemory( ( void* )&ofn, sizeof( OPENFILENAME ) );

                    ofn.lStructSize = sizeof( ofn ); // SEE NOTE BELOW
                    ofn.hwndOwner = hWnd;
                    ofn.lpstrTitle = L"Recover Image From File";
                    ofn.lpstrFilter = wcs;
                    ofn.lpstrFile = wcsFilename;
                    ofn.nMaxFile = MAX_PATH;
                    ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
                    ofn.lpstrDefExt = L"image file";
                    ofn.lpstrInitialDir = app.GetBinDirectory();

                    // OpenFile Dialog
                    if( GetOpenFileName( &ofn ) )
                    {                                       
                        if( FAILED( hr = CTextureEditor::Recover( 0, wcsFilename ) ) )
                        {
                            DebugStringDX( ClassName, "Failed to CTextureEditor::Recover() at AuxiliaryViewportProc()", __LINE__, hr );
                            break;
                        }
                    }
                    break;
                }
            default:
                return 0;
            }

            SendMessage( ( HWND )lpnm->hdr.hwndFrom, TB_MARKBUTTON, lpnm->iItem, MAKELPARAM( FALSE, 0 ) );
            UpdateWindow( hWnd );
            SetStateChange();
            return 1;
        }
    default:
        return 0;
    }
    return 0;
}

1 个答案:

答案 0 :(得分:2)

我认为TBN_DROPDOWN的返回值不正确 - 您返回的1映射到TBDDRET_NODEFAULT,意思是“下拉列表未处理”,您需要返回TBDDRET_DEFAULTTBDDRET_TREATPRESSED