Win32 工具栏下拉按钮消息处理
Win32 Toolbar Dropdown Button Message Handling
我的应用程序中有一个窗口的工具栏。我已经阅读了MSDN文档,可以处理命令和通知消息。我的问题是附加到工具栏上的按钮的下拉菜单。菜单项将打开模式对话框,并等待用户完成设置更改。但是,在用户单击"确定"或"取消"焦点后,工具栏仍然以鼠标左键已按下的印象,因此每次我将鼠标拖动到单击的工具栏按钮上时,该按钮都会处于"按钮已选中"状态并"似乎"被按下。
问题是否与鼠标事件的跟踪有关?
以下是窗口进程中的通知消息处理:
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;
}
我认为TBN_DROPDOWN的返回值不正确 - 您返回1
映射到TBDDRET_NODEFAULT
意思是"下拉列表未处理",您需要返回TBDDRET_DEFAULT
或TBDDRET_TREATPRESSED
。
相关文章:
- 设计帮助 - 为不同类型的消息处理通用接口的设计模式
- 如何在winApi上正确创建按钮以及处理其消息
- 为什么调用单例类 Qt 消息处理程序成员函数会出现错误:缺少参数列表
- MFC编辑控制消息处理访问文档对象
- 使用非静态消息处理程序获取GSTREAMER总线消息
- MFC单选按钮组消息处理程序
- Win32 工具栏下拉按钮消息处理
- 如何在Windows中进行正确的顺序异步消息处理
- 主对话框在命令消息处理程序返回之前销毁
- 正在安装消息处理程序
- 如何在 wndproc 消息处理程序中在窗口下触发 jit 调试器
- 消息处理程序中的 RAND_event() 会导致 UI 中的小冻结吗?
- 并发消息处理按时间顺序排序
- 使用消息处理程序将 c++ dll 调用转换为 delphi
- 了解 Windows API 中消息处理的不同策略
- 如果对象将在消息处理程序中使用,如何解决内存泄漏问题
- 如果安装在单独的类上,Qt消息处理程序将崩溃
- Win32:更多"object oriented"窗口消息处理系统
- 按钮事件处理程序
- 未能安装按钮消息处理程序