C-选择文件时的Windows消息循环中的多余(错误)消息



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标志移动。这是更干净的(没有全局标志,一个相关的代码全部在一个地方(。

最新更新