2010-04-06 8 views
2

저는 WindowStyle None 및 AllowsTransparency True를 사용하여 wpf에서 custom chromed window를 만들려고했으나 화면을 최대화 할 때 전체 화면을 덮을 때 (가장자리에 있기 때문에 가장자리를 숨 깁니다. 전체 화면의 게임처럼 내 화면의 하단에있는 Windows 바). 어떻게 정상적인 창문처럼 동작을 만들 수 있습니까?하지만 내 자신의 맞춤형 wpf-chrome으로 만들 수 있습니까?wpf에서 사용자 정의 크롬 Windows

답변

8

해결책을 찾았지만 몇 가지 win32 interop가 필요합니다. 별로 예쁘지 않지만 작동합니다. 실제로 AllowsTransparency 부분을 사용하지 않는 경우

protected override void OnSourceInitialized(EventArgs e) 
    { 
     base.OnSourceInitialized(e); 

     IntPtr handle = (new WinInterop.WindowInteropHelper(this)).Handle; 
     WinInterop.HwndSource.FromHwnd(handle).AddHook(new WinInterop.HwndSourceHook(WindowProc)); 
    } 

    private IntPtr WindowProc(
     IntPtr hwnd, 
     int msg, 
     IntPtr wParam, 
     IntPtr lParam, 
     ref bool handled) 
    { 
     switch (msg) 
     { 
      case 0x0024: 
       WmGetMinMaxInfo(hwnd, lParam); 
       handled = true; 
       break; 
     } 

     return (IntPtr)0; 
    } 

    private static void WmGetMinMaxInfo(IntPtr hwnd, IntPtr lParam) 
    { 
     MINMAXINFO mmi = (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO)); 

     // Adjust the maximized size and position to fit the work area of the correct monitor 
     int MONITOR_DEFAULTTONEAREST = 0x00000002; 
     IntPtr monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); 

     if (monitor != IntPtr.Zero) 
     { 
      MONITORINFO monitorInfo = new MONITORINFO(); 
      GetMonitorInfo(monitor, monitorInfo); 
      RECT rcWorkArea = monitorInfo.rcWork; 
      RECT rcMonitorArea = monitorInfo.rcMonitor; 
      mmi.ptMaxPosition.x = Math.Abs(rcWorkArea.left - rcMonitorArea.left); 
      mmi.ptMaxPosition.y = Math.Abs(rcWorkArea.top - rcMonitorArea.top); 
      mmi.ptMaxSize.x = Math.Abs(rcWorkArea.right - rcWorkArea.left); 
      mmi.ptMaxSize.y = Math.Abs(rcWorkArea.bottom - rcWorkArea.top); 
     } 

     Marshal.StructureToPtr(mmi, lParam, true); 
    } 

    /// <summary> 
    /// POINT aka POINTAPI 
    /// </summary> 
    [StructLayout(LayoutKind.Sequential)] 
    public struct POINT 
    { 
     /// <summary> 
     /// x coordinate of point. 
     /// </summary> 
     public int x; 
     /// <summary> 
     /// y coordinate of point. 
     /// </summary> 
     public int y; 

     /// <summary> 
     /// Construct a point of coordinates (x,y). 
     /// </summary> 
     public POINT(int x, int y) 
     { 
      this.x = x; 
      this.y = y; 
     } 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    public struct MINMAXINFO 
    { 
     public POINT ptReserved; 
     public POINT ptMaxSize; 
     public POINT ptMaxPosition; 
     public POINT ptMinTrackSize; 
     public POINT ptMaxTrackSize; 
    }; 

    /// <summary> 
    /// </summary> 
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 
    public class MONITORINFO 
    { 
     /// <summary> 
     /// </summary>    
     public int cbSize = Marshal.SizeOf(typeof(MONITORINFO)); 

     /// <summary> 
     /// </summary>    
     public RECT rcMonitor = new RECT(); 

     /// <summary> 
     /// </summary>    
     public RECT rcWork = new RECT(); 

     /// <summary> 
     /// </summary>    
     public int dwFlags = 0; 
    } 

    /// <summary> Win32 </summary> 
    [StructLayout(LayoutKind.Sequential, Pack = 0)] 
    public struct RECT 
    { 
     /// <summary> Win32 </summary> 
     public int left; 
     /// <summary> Win32 </summary> 
     public int top; 
     /// <summary> Win32 </summary> 
     public int right; 
     /// <summary> Win32 </summary> 
     public int bottom; 

     /// <summary> Win32 </summary> 
     public static readonly RECT Empty = new RECT(); 

     /// <summary> Win32 </summary> 
     public int Width 
     { 
      get { return Math.Abs(right - left); } // Abs needed for BIDI OS 
     } 
     /// <summary> Win32 </summary> 
     public int Height 
     { 
      get { return bottom - top; } 
     } 

     /// <summary> Win32 </summary> 
     public RECT(int left, int top, int right, int bottom) 
     { 
      this.left = left; 
      this.top = top; 
      this.right = right; 
      this.bottom = bottom; 
     } 


     /// <summary> Win32 </summary> 
     public RECT(RECT rcSrc) 
     { 
      this.left = rcSrc.left; 
      this.top = rcSrc.top; 
      this.right = rcSrc.right; 
      this.bottom = rcSrc.bottom; 
     } 

     /// <summary> Win32 </summary> 
     public bool IsEmpty 
     { 
      get 
      { 
       // BUGBUG : On Bidi OS (hebrew arabic) left > right 
       return left >= right || top >= bottom; 
      } 
     } 
     /// <summary> Return a user friendly representation of this struct </summary> 
     public override string ToString() 
     { 
      if (this == RECT.Empty) { return "RECT {Empty}"; } 
      return "RECT { left : " + left + "/top : " + top + "/right : " + right + "/bottom : " + bottom + " }"; 
     } 

     /// <summary> Determine if 2 RECT are equal (deep compare) </summary> 
     public override bool Equals(object obj) 
     { 
      if (!(obj is Rect)) { return false; } 
      return (this == (RECT)obj); 
     } 

     /// <summary>Return the HashCode for this struct (not garanteed to be unique)</summary> 
     public override int GetHashCode() 
     { 
      return left.GetHashCode() + top.GetHashCode() + right.GetHashCode() + bottom.GetHashCode(); 
     } 


     /// <summary> Determine if 2 RECT are equal (deep compare)</summary> 
     public static bool operator ==(RECT rect1, RECT rect2) 
     { 
      return (rect1.left == rect2.left && rect1.top == rect2.top && rect1.right == rect2.right && rect1.bottom == rect2.bottom); 
     } 

     /// <summary> Determine if 2 RECT are different(deep compare)</summary> 
     public static bool operator !=(RECT rect1, RECT rect2) 
     { 
      return !(rect1 == rect2); 
     } 

    } 

    [DllImport("user32")] 
    internal static extern bool GetMonitorInfo(IntPtr hMonitor, MONITORINFO lpmi); 

    /// <summary> 
    /// 
    /// </summary> 
    [DllImport("User32")] 
    internal static extern IntPtr MonitorFromWindow(IntPtr handle, int flags); 
+0

이 샘플은 원래 Lester가 게시했습니다. http://blogs.msdn.com/b/llobo/archive/2006/08/01/maximizing-window-_2800_with-windowstyle_3d00_none_2900_-considering-taskbar.aspx – TheZenker

+0

이 솔루션은 응용 프로그램을 최대화 상태로 시작하려고 시도하는 경우. 왜냐하면 WmGetMinMaxInfo는 창을 처음 보았을 때가 아니라 창을 표시 한 후에 창 상태를 변경할 때만 호출되기 때문입니다. –

+0

흠, 그 문제에 대한 해결책이 있습니까? – Alxandr

1

창이 기본 속성인데, 최대화하면 하단의 창 막대를 포함하여 모든 화면 영역을 포함합니다. 이것은 WindoStyle을 None으로 설정 한 경우에만 발생합니다 (그렇지 않으면 전체 영역을 차지하지 않습니다). pls가 실제 작업 영역을 얻을 수 있도록 evnt를 최대화 할 때 이와 같은 것을 사용하지 않도록하십시오.

대신 windowState = WindowStat.Maximized를 설정하여 창 높이와 너비를 변경하고 최대화 복원 및 그 반대의 이미지를 변경하십시오.

window.Left=0; 
window.Top=0; 
window.Height=SystemParameters.WorkArea.Height; 
window.Width=SystemParameters.WorkArea.Width; 

희망 사항이 도움이됩니다.

+0

유일한 방법입니까? WindowState = WindowState.Maximized를 정상적으로 작동하는 것처럼 작동시키지 못합니까? – Alxandr

+0

이것은 내가하고있는 일입니다. Pls 더 나은 soulution을 얻을 경우 업데이 트하십시오. 더 나은 해결책을 찾으면 알려 드리겠습니다. –

+0

이 접근법의 문제점은 윈도우가 실제로 최대화되지 않아서 윈도우를 계속 드래그 할 수 있어야한다는 것입니다. 또한 왼쪽에 작업 표시 줄이있을 수 있으므로 WorkArea.Left 및 .Top은 0,0이 아닐 수도 있습니다. 이 페이지의 interop 솔루션은 작동합니다. –

1

의 WPF 쉘 통합 도서관은 당신을 위해 작동 할 수 있습니다 http://code.msdn.com/WPFShell. WPF SDK 블로그 게시물에 대한 해당 페이지의 링크는 해당 작업이 수행중인 작업을 설명합니다.

관련 문제