i创建主窗口,并在其上创建一个子窗口和文件选择按钮。在选择过程中,双击文件会导致错误消息WM_MouseMove(带有GetKeyState(vk_lbutton((在子窗口的消息循环中。当单击点在子窗口上方时,这会发生这种情况。在这种情况下,单击点的坐标将转移到LPARAM。如果您通过打开按钮选择文件,则没有什么。
此消息不限于选择文件的那一刻:它进入队列并在选择后发射。这可能会导致大问题,特别是当子窗口图形时。
Windows 8,VS 2015,C 。
有人知道如何克服这一点吗?
#include <windows.h>
#include <windowsx.h>
#include <shobjidl_core.h>
#define IDI_ICON 110
#define IDC_OPEN_FILE_BUTTON 120
HWND g_hDwnd = NULL;
HWND g_hWnd = NULL;
HWND hwndOpenFile = NULL;
HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow );
LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM );
LRESULT CALLBACK ChildProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow )
{
UNREFERENCED_PARAMETER( hPrevInstance );
UNREFERENCED_PARAMETER( lpCmdLine );
if( FAILED( InitWindow( hInstance, nCmdShow ) ) )
return 0;
MSG msg = {0};
while( WM_QUIT != msg.message )
{
if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
return ( int )msg.wParam;
}
HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow )
{
WNDCLASSEX wcdex;
wcdex.cbSize = sizeof( WNDCLASSEX );
wcdex.style = CS_HREDRAW | CS_VREDRAW;
wcdex.lpfnWndProc = WndProc;
wcdex.cbClsExtra = 0;
wcdex.cbWndExtra = 0;
wcdex.hInstance = hInstance;
wcdex.hIcon = LoadIcon( hInstance, ( LPCTSTR )IDI_ICON );
wcdex.hCursor = LoadCursor( NULL, IDC_ARROW );
wcdex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 );
wcdex.lpszMenuName = NULL;
wcdex.lpszClassName = L"ParentWindowClass";
wcdex.hIconSm = LoadIcon( wcdex.hInstance, ( LPCTSTR )IDI_ICON );
if( !RegisterClassEx( &wcdex ) )
return E_FAIL;
g_hDwnd = CreateWindow( L"ParentWindowClass", L"Test", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 840, 480, NULL, NULL, hInstance, NULL );
if( !g_hDwnd )
return E_FAIL;
hwndOpenFile = CreateWindowEx(0, L"BUTTON", L"Open", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
560, 50, 100, 24, g_hDwnd, (HMENU)IDC_OPEN_FILE_BUTTON, hInstance, NULL);
ShowWindow( g_hDwnd, nCmdShow );
UpdateWindow(g_hDwnd);
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wcex.lpfnWndProc = ChildProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = NULL;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = CreateSolidBrush(RGB(200, 200, 205));
wcex.lpszMenuName = NULL;
wcex.lpszClassName = L"ChildWindowClass";
wcex.hIconSm = NULL;
if (!RegisterClassEx(&wcex))
return E_FAIL;
g_hWnd = CreateWindowEx(WS_EX_APPWINDOW, L"ChildWindowClass", L"test", WS_CHILD,
10, 10, 540, 460, g_hDwnd, NULL, hInstance, NULL);
if (!g_hWnd)
return E_FAIL;
ShowWindow(g_hWnd, nCmdShow);
UpdateWindow(g_hWnd);
return S_OK;
}
void OpenModelFile()
{
char input;
LPWSTR g_path = NULL;
LPWSTR szAPX = L"Model format";
COMDLG_FILTERSPEC rgSpec[] = { { szAPX, L"*.txt" } };
IFileDialog *pfd;
if (SUCCEEDED(CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfd))))
{
DWORD dwOptions;
if (SUCCEEDED(pfd->GetOptions(&dwOptions)))
{
pfd->SetOptions(dwOptions | FOS_STRICTFILETYPES);
}
if (SUCCEEDED(pfd->SetFileTypes(1, rgSpec)))
{
if (SUCCEEDED(pfd->SetDefaultExtension(L"txt")))
{
if (SUCCEEDED(pfd->SetFileName(L"Model.txt")))
{
if (SUCCEEDED(pfd->Show(NULL)))
{
IShellItem *psi;
if (SUCCEEDED(pfd->GetResult(&psi)))
{
if (SUCCEEDED(psi->GetDisplayName(SIGDN_NORMALDISPLAY, &g_path)))
{
LPCTSTR a = L"Path";
MessageBox(NULL, g_path, a, NULL);
}
psi->Release();
}
}
}
}
}
pfd->Release();
}
return;
}
LRESULT CALLBACK ChildProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
int x ;
int y ;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
break;
case WM_MOUSEMOVE:
if (GetKeyState(VK_LBUTTON) < 0)
{
x = GET_X_LPARAM(lParam) ;
y = GET_Y_LPARAM(lParam) ;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
PAINTSTRUCT ps;
HDC hdc;
int id = LOWORD(wParam);
switch( message )
{
case WM_PAINT:
hdc = BeginPaint( hWnd, &ps );
EndPaint( hWnd, &ps );
break;
case WM_COMMAND:
if (id == IDC_OPEN_FILE_BUTTON)
{
OpenModelFile();
}
break;
case WM_DESTROY:
PostQuitMessage( 0 );
break;
default:
return DefWindowProc( hWnd, message, wParam, lParam );
}
return 0;
}
在简单的解决方法中解决了问题。双击之后,我将特殊标志设置为1,然后在WM_MouseMove消息末尾将其置于零。在消息循环中,我仅在降低标志时考虑鼠标的移动。
事实证明,在Windows 10中,生成了一系列False WM_MouseMove消息。因此,除了上面提到的旗帜外,它可以防止第一条消息,还必须利用R. Chen的建议从他的书"旧事物"中的建议,并将当前信息的比较与上一封相结合。如果它们匹配,则不会考虑该消息。
冒险继续。双击窗口标题时,会出现相同的虚假消息。当Windows发送wm_nclbuttondblclk。
我也有相同的问题;当用户双击选择(Microsoft Bug(时,clsid_fileopendialog模态对话框将用MK_LBUTTON标志泄漏鼠标移动到下面的任何窗口。在我的情况下,下面的窗口是一个3D视口对这些消息的响应。
我通过WM_LBUTTONDOWN和WM_LBUTTONUP消息,通过将视口轨道左键按钮状态找到一个更好的解决方案。然后,当按钮状态不关闭时,忽略鼠标将用MK_LBUTTON标志移动。这是更干净的(没有全局标志,一个相关的代码全部在一个地方(。