2010-05-10 8 views
2

테두리 스타일 NONE 및 WM_NCHITTEST의 사용자 지정 처리를 지정하여 사용자 지정 그리기 창을 만듭니다. 일부 영역을 '내 창 캡션'으로 정의하고이 영역에서 WM_NCHITTEST에 대한 HTCAPTION 결과를 반환했습니다. 창문이 정상 상태에있을 때 그 행동은 저에게 기대됩니다. 창은 '내 창 캡션'을 드래그하여 이동할 수 있으며 두 번 클릭하여 최대화 할 수 있습니다.WM_NCHITTEST, HTCAPTION 및 최대화 된 창

문제는 최대화 된 상태에서 내 창의 동작입니다. 나는 여전히 '내 창 캡션'영역에서 WM_NCHITTEST에 대한 HTCAPTION 결과를 반환하고 창을 다시 두 번 클릭하여 원래 크기로 복원 할 수 있지만 여전히 이동할 수 있으며 원하는 것은 아닙니다. 그러한 행동을 수정하기 위해 무엇을해야합니까?


수정 :

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 방법은 내 사용자 지정 그려 양식의 적중 테스트 결과의 평가에 대한 책임이 있습니다. 구현이보기 흉하게 보일 수도 있지만 매우 간단합니다.

답변

2

당신이 묘사 한 것은 약간 이상합니다. 최대화 된 창은 일반적으로 이동할 수 없습니다. 특히 그것은 전체 데스크탑 영역을 차지하고 AFAIK 시스템은 캡션 (즉, 히트 테스트가 HT_CAPTION 인 영역)이 드래그 될 때 시스템을 드래그하지 않습니다.

당신은 더 많은 정보를 지정하십시오 수 :

  1. 은 (는 다중 모니터 시스템)가 어떻게 많은 데스크탑?
  2. 창문이 전체 바탕 화면 영역을 차지하지 않도록 WM_GETMINMAXINFO에 응답합니까?

생각 나는 창을 최대화했을 때 해결 방법을 상상할 수 있습니다. 히트 테스트시 HT_CAPTION을 반환하지 마십시오. 대신 HT_CLIENT을 반환 할 수 있습니다. 이렇게하면 창을 끌 수 없습니다.

하지만 두 번 클릭하면 수동으로 "복원"을 구현해야합니다. 그런 다음 WM_LBUTTONDBLCLK에 응답하고 수동으로 위치를 복원해야합니다.

+1

고정 코드로 내 질문을 업데이트했습니다. – okutane

3

이것은 최대화되었을 때 창을 드래그 할 수 없게하는 코드입니다.

// 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

Windows 7에서 예상되는 올바른 동작은 으로 드래그 된 최대화 된 윈도우로,은 드래그 가능해야합니다. 메모장이나 다른 Windows 응용 프로그램으로 시도해보십시오. - 도킹되거나 최대화 된 Windows는 자동으로 "복원"크기로 되돌아 가서 드래그 할 수 있습니다.