Странное поведение захвата мыши
От: Melamed Россия  
Дата: 28.08.18 08:31
Оценка:
Пытаюсь написать собственное Popup окно.
По-идее, окно должно пропадать с экрана при нажатии левой кнопки мыши, когда курсор находится вне области этого окна. Для этого я использую захват мыши.
Но он ведет себя странно: Если не было нажатия мыши, когда курсор мыши находится в области окна, захватившего мышь, то все работает нормально. В противном случае захват перестает работать.
Код появления выпадающего окна
BOOL CALLBACK ColorPropertiesProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    static HWND hWndPopup = NULL; 
    switch(uMsg)
    {
    case WM_INITDIALOG:
        {
            hWndPopup = CreateDialogParam(
                (HINSTANCE)GetWindowLong(hWnd,GWL_HINSTANCE),
                MAKEINTRESOURCE(IDD_COLORPANEL),hWnd,
                ColorPanelProc,0);
            break;
        }
    case WM_COMMAND:
        {
            int nID = LOWORD(wParam);
            switch(nID)
            {
            case IDC_BTMCOLOR:
                {
                    RECT rc, rcBtn;
                    rc.left = 0;
                    rc.top = 0;
                    rc.right = 96;
                    rc.bottom = 72;
                    AdjustWindowRect(&rc, GetWindowLong(hWndPopup,GWL_STYLE), FALSE);
                    MapDialogRect(hWndPopup,&rc);
                    
                    GetWindowRect(GetDlgItem(hWnd,IDC_BTMCOLOR),&rcBtn);
                    rc.left = rcBtn.left-(rc.right-rcBtn.right+rcBtn.left)/2;
                    SetWindowPos(hWndPopup, NULL, 
                        rc.left, rcBtn.bottom, rc.right, rc.bottom, 
                        SWP_SHOWWINDOW | SWP_DRAWFRAME |
                        SWP_NOOWNERZORDER | SWP_NOZORDER);
                    SetCapture(GetDlgItem(hWndPopup,IDC_COLORGRID));
                    MSG msg;
                    while (IsWindowVisible(hWndPopup) && 
                        GetMessage(&msg, NULL, 0, 0)) 
                    {
                        if (!IsDialogMessage(hWndPopup, &msg))
                        {
                            if((msg.hwnd == hWndPopup) || 
                                (msg.hwnd == GetDlgItem(hWndPopup,IDC_COLORGRID)))
                            {
                                TranslateMessage(&msg);
                                DispatchMessage(&msg);
                            }
                        }
                    }
                    InvalidateRect(hWnd,NULL,TRUE);
                    break;
                }
            }
            break;
        }
    case WM_DESTROY:
        {
            DestroyWindow(hWndPopup);
            break;
        }
    default:
        {
            return FALSE;
        }
    }
    return TRUE;
}

BOOL CALLBACK ColorPanelProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    return FALSE;
}


Код события WM_LBUTTONDOWN моего собственного контролера. Больше нигде не использую функцию ReleaseCapture

void ColorPanel::OnLButtonDown(HWND hWnd, int X, int Y)
{
    if(GetWindowLong(hWnd,GWL_STYLE) & CPS_POPUP)
    {
        RECT rc;
        GetWindowRect(hWnd,&rc);
        POINT pt;
        pt.x = X;
        pt.y = Y;
        ClientToScreen(hWnd,&pt);
        if(!PtInRect(&rc,pt))
        {
            ShowWindow(GetParent(hWnd),SW_HIDE);    
            ReleaseCapture();        
            return;
        }
    }
    InvalidateRect(hWnd,NULL,FALSE);
    
}


Операционная система MS Windows 10
Re: Странное поведение захвата мыши
От: Maniacal Россия  
Дата: 28.08.18 10:59
Оценка:
Здравствуйте, Melamed, Вы писали:

M>Пытаюсь написать собственное Popup окно.

M>По-идее, окно должно пропадать с экрана при нажатии левой кнопки мыши, когда курсор находится вне области этого окна. Для этого я использую захват мыши.
M>Но он ведет себя странно: Если не было нажатия мыши, когда курсор мыши находится в области окна, захватившего мышь, то все работает нормально. В противном случае захват перестает работать.

Единственное, что могу сказать, что SetCapture никак не помогает отлавливать события мыши за пределами окна за исключением случая, если на мыши удерживается кнопка, которая была нажата в момент пока курсор был ещё в пределах окна. Я бы лучше событие потери фокуса окна отлавливал для того, чтобы его скрыть.
Re: Странное поведение захвата мыши
От: c-smile Канада http://terrainformatica.com
Дата: 29.08.18 22:12
Оценка:
Здравствуйте, Melamed, Вы писали:

M>Пытаюсь написать собственное Popup окно.

M>По-идее, окно должно пропадать с экрана при нажатии левой кнопки мыши, когда курсор находится вне области этого окна. Для этого я использую захват мыши.

300 лет назад Raymond Chen был написал этот вот пример:

https://github.com/pauldotknopf/WindowsSDK7-Samples/tree/master/winui/shell/legacysamples/fakemenu


Базовая идея — просто SetCapture не хватает. Нужно еще

a) это окно показывать как ShowWindow(hwndPopup, SW_SHOWNOACTIVATE); и
b) mouse modal loop крутить : https://github.com/pauldotknopf/WindowsSDK7-Samples/blob/master/winui/shell/legacysamples/fakemenu/fakemenu.cpp#L442
Re: Странное поведение захвата мыши
От: CEMb  
Дата: 31.08.18 02:36
Оценка:
Здравствуйте, Melamed, Вы писали:

M>Пытаюсь написать собственное Popup окно.

M>По-идее, окно должно пропадать с экрана при нажатии левой кнопки мыши, когда курсор находится вне области этого окна. Для этого я использую захват мыши.

Если захват мыши не принципиален, можно попробовать WM_ACTIVATE
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.