Как разрешить перетаскивание окна за любую точку?

Тема в разделе "MS Visual C++", создана пользователем Guest, 8 авг 2003.

Статус темы:
Закрыта.
  1. Guest

    Guest Гость

    Как разрешить перетаскивание окна за любую точку?
     
  2. Guest

    Guest Гость

    Демонстрационное приложение DragWin

    Пример - приложение DragWin (диалоговое окошко, MFC) иллюстрирует
    два способа осуществить перемещение окна с захватом его не только
    за заголовок, но и за любую точку на клиентской области. Идея
    первого способа проста - при получении сообщения о перемещении
    мыши передвигаем наше окно в соответствии с новыми координатами.
    Второй способ поизящнее, и заключается в некотором "обмане"
    Windows, после которого она считает, что мышь находится над
    заголовоком окна, даже если реально это уже клиентсткая часть.

    Способ 1

    Реализован для главного окна приложения. Заключается в написании
    собственных обработчиков нажатия (WM_LBUTTONDOWN), перемещения
    (WM_MOUSEMOVE) и отпускания (WM_LBUTTONUP) левой кнопки мыши.
    Обработчики на данные события устанавливаются стандартным образом
    - через MFC ClassWizard.
    Код (Text):
    void CDragWinDlg::OnLButtonDown(UINT nFlags, CPoint point)
    {
     // выставим флажок - пошло перетаскивание
     m_bMoveWindow = TRUE;
     // все сообщения от мыши - к нашему окну, независимо от координат
     // чтобы мышь не улетала с окна при быстром движении
     SetCapture();
     // сохраняем координаты окна
     GetWindowRect(m_RectDlg);
     // сохраняем положение мышки внутри окна программы
     ClientToScreen(&point);
     m_MouseInDlg = point - m_RectDlg.TopLeft();
     // меняем курсор, чтоб веселее было тащить
     m_hCursor = m_hCursorDown;
     ::SetCursor(m_hCursor);

     // вызываем обработчик по умолчанию
     CDialog::OnLButtonDown(nFlags, point);
    }

    void CDragWinDlg::OnMouseMove(UINT nFlags, CPoint point)
    {
     if (m_bMoveWindow) // надо тащить
     {
       // преобразуем координаты мыши в экранные
       // именно они нужны будут для SetWindowPos()
       ClientToScreen(&point);
       // двигаем окно в соответствии с новыми координатами мыши
       SetWindowPos(&wndTop,
         point.x - m_MouseInDlg.x, point.y - m_MouseInDlg.y,
         m_RectDlg.right - m_RectDlg.left,
         m_RectDlg.bottom - m_RectDlg.top,
         SWP_SHOWWINDOW);
       // поскольку обработчик по умолчанию все равно будет использовать
       // первоначальные параметры сообщения
       // обратное преобразование ScreenToClient(&point);
       // можно не вызывать
     }

     // вызываем обработчик по умолчанию
     CDialog::OnMouseMove(nFlags, point);
    }

    void CDragWinDlg::OnLButtonUp(UINT nFlags, CPoint point)
    {
     // перетаскивание закончилось
     m_bMoveWindow = FALSE;

     // "отпускаем" мышку
     ReleaseCapture();

     // меняем курсор на исходный
     m_hCursor = m_hCursorUp;

     // вызываем обработчик по умолчанию
     CDialog::OnLButtonUp(nFlags, point);
    }

    BOOL CDragWinDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
    {
     // заменяем курсор на свой
     ::SetCursor(m_hCursor);

     return TRUE;
     // !!! было return CDialog::OnSetCursor(pWnd, nHitTest, message);
    }
    Замена курсора естесственно не является критичной для собственно
    перетаскивания, а добавлена исключительно для визуализации
    процесса захвата окошка.

    Способ 2

    Реализован для окна About этого же приложения. Заключается в
    замене обработчика события WM_NCHITTEST, которое информирует об
    области, над которой в данный момент находится мышка. Обработчик
    этого сообщения также можно добавить через MFC ClassWizard.
    Предварительно на закладке ClassInfo для класса CAboutDlg нужно
    установить для Message Filter значение Window.

    Переписываем функцию - обработчик следующим образом:

    Код (Text):
    UINT CAboutDlg::OnNcHitTest(CPoint point)
    {
     UINT ret = CDialog::OnNcHitTest(point);

     // если обработчик по умолчанию говорит нам что мышка
     // над клиентской областью окна, заменяем возвращаемое
     // значение на HTCAPTION - мышка над заголовком окна,
     // а за заголовок перемещать окно можно!
     if (ret == HTCLIENT)
       return HTCAPTION;

     return ret;
    }
    Второй способ проще, первый потенциально гибче, используйте тот,
    что лучше подходит к вашему конкретному случаю.
     
Загрузка...
Статус темы:
Закрыта.

Поделиться этой страницей