WM_NCHITTEST, HTCAPTION и развернутое окно - PullRequest
2 голосов
/ 10 мая 2010

Я создаю собственное нарисованное окно, указав стиль границы NONE и пользовательскую обработку WM_NCHITTEST. Я определил некоторую область как «заголовок моего окна» и возвращаю результат HTCAPTION для WM_NCHITTEST в этой области. Когда окно находится в нормальном состоянии, поведение я ожидаю. Окно можно перемещать, перетаскивая «заголовок моего окна», и его можно развернуть, дважды щелкнув по нему.

Проблема в поведении моего окна в развернутом состоянии. Я все еще возвращаю результат HTCAPTION для WM_NCHITTEST в области «заголовка моего окна», и окно можно восстановить до исходного размера, дважды щелкнув по нему снова, но его также можно переместить, и это не то, что я хочу. Что я должен сделать, чтобы исправить такое поведение?


Fix:

    protected override void WndProc(ref Message m)
    {
        if(m.Msg == WM_NCHITTEST)
        {
            Point pos = new Point(m.LParam.ToInt32() & 0xffff, m.LParam.ToInt32() >> 16);
            pos = this.PointToClient(pos);
            if(HitTestForNC(ref m, pos))
            {
                if(WindowState != FormWindowState.Maximized || m.Result != (IntPtr)HitTestValues.HTCAPTION)
                {
                    return;
                }
            }
        }
        else if(m.Msg == WM_GETMINMAXINFO)
        {
            base.WndProc(ref m);
            MinMaxInfo mmi = (MinMaxInfo)Marshal.PtrToStructure(m.LParam, typeof(MinMaxInfo));
            mmi.ptMaxPosition = Screen.FromControl(this).WorkingArea.Location;
            mmi.ptMaxSize = Screen.FromControl(this).WorkingArea.Size;
            Marshal.StructureToPtr(mmi, m.LParam, false);
            return;
        }
        base.WndProc(ref m);
    }

    protected override void OnMouseDoubleClick(MouseEventArgs e)
    {
        if(e.Button == MouseButtons.Left)
        {
            Message m = new Message();
            if(HitTestForNC(ref m, e.Location))
            {
                if(m.Result == (IntPtr)HitTestValues.HTCAPTION && WindowState == FormWindowState.Maximized)
                {
                    WindowState = FormWindowState.Normal;
                    return;
                }
            }
        }
        base.OnMouseDoubleClick(e);
    }

Метод HitTestForNC отвечает за оценку результата теста на удар в моей пользовательской нарисованной форме. Реализация может выглядеть уродливо, но это довольно просто.

Ответы [ 3 ]

3 голосов
/ 10 мая 2010

Этот код я использую для предотвращения перетаскивания окна при максимизации.

// Indicates the form caption
Const HT_CAPTION As Integer = &H2
// Windows Message Non Client Button Down
Const WM_NCLBUTTONDOWN As Integer = &HA1

//Routine to implement the 'Drag Window' functionality.
Private Sub frm_Drag(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
  Handles Me.MouseDown

  //Do not move the form if it is maximized.
  If Not Me.WindowState = FormWindowState.Maximized Then
     If e.Button = Windows.Forms.MouseButtons.Left Then
        sender.Capture = False
        Me.WndProc(Message.Create(Me.Handle, WM_NCLBUTTONDOWN, _
        CType(HT_CAPTION, IntPtr), IntPtr.Zero))
     End If
  End If
End Sub
2 голосов
/ 10 мая 2010

В Windows 7 ожидаемое и правильное поведение состоит в том, что развернутые максимизированные окна должны быть перетаскиваемыми. Попробуйте это с помощью Блокнота или любого другого приложения Windows: - Windows, которая закреплена или развернута, автоматически вернется к размеру «восстановления» и станет перетаскиваемой.

2 голосов
/ 10 мая 2010

То, что вы описываете, немного странно - развернутое окно обычно не может быть перемещено. В частности, он занимает всю область рабочего стола, и AFAIK система не «перетаскивает» его при перетаскивании заголовка (то есть области, для которой было выполнено испытание на попадание HT_CAPTION).

Можете ли вы указать более подробную информацию:

  1. Сколько у вас рабочих столов (это система с несколькими мониторами)?
  2. Отвечаете ли вы на WM_GETMINMAXINFO, чтобы ваше окно не занимало всю область рабочего стола?

Кстати, я могу представить обходной путь: когда ваше окно развернуто - не возвращайте HT_CAPTION при проверке попадания. Вместо этого вы можете вернуть HT_CLIENT, это предотвратит перетаскивание окна.

Однако вам придется вручную выполнить «восстановление» вашего окна при двойном щелчке. Затем вы должны ответить на WM_LBUTTONDBLCLK и восстановить свою позицию вручную.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...