2015-11-08 33 views
0

我創建了一個displaystyle = none的WPF窗口,併成功顯示底部的任務欄。我實際上使用了從堆棧溢出的其中一個線程中取得的以下代碼。一切都很好,但我面臨一個小問題,那就是代碼非常笨重,每次創建新窗口時都會顯示在每個窗口上。使顯示樣式最大化窗口無WPF

所以我只需要創建另一個類,並試圖繼承它的窗口類,就像下面:

public partial class CustomWindow1 : Window, clsMaxi 

但unfortulately它不承認clsMaxi類。我必須創建許多窗口,並且在每個窗口上我不想要這麼多的代碼,所以這就是爲什麼我需要創建一些單獨的類,然後嘗試插入。

以下是完整的代碼。所以,任何人都可以幫助我組織這些代碼,這樣我就不會在每次創建新窗口時都打電話給每個窗口。

using System.Runtime.InteropServices; 
using System.Windows.Interop; 

private bool mRestoreIfMove = false; 


public MainWindow() 
{ 
    InitializeComponent(); 
} 


void Window_SourceInitialized(object sender, EventArgs e) 
{ 
    IntPtr mWindowHandle = (new WindowInteropHelper(this)).Handle; 
    HwndSource.FromHwnd(mWindowHandle).AddHook(new HwndSourceHook(WindowProc)); 
} 


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

     return IntPtr.Zero; 
} 


private static void WmGetMinMaxInfo(System.IntPtr hwnd, System.IntPtr lParam) 
{ 
    POINT lMousePosition; 
    GetCursorPos(out lMousePosition); 

    IntPtr lPrimaryScreen = MonitorFromPoint(new POINT(0, 0), MonitorOptions.MONITOR_DEFAULTTOPRIMARY); 
    MONITORINFO lPrimaryScreenInfo = new MONITORINFO(); 
    if (GetMonitorInfo(lPrimaryScreen, lPrimaryScreenInfo) == false) 
    { 
     return; 
    } 

    IntPtr lCurrentScreen = MonitorFromPoint(lMousePosition, MonitorOptions.MONITOR_DEFAULTTONEAREST); 

    MINMAXINFO lMmi = (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO)); 

    if (lPrimaryScreen.Equals(lCurrentScreen) == true) 
    { 
      lMmi.ptMaxPosition.X = lPrimaryScreenInfo.rcWork.Left; 
      lMmi.ptMaxPosition.Y = lPrimaryScreenInfo.rcWork.Top; 
      lMmi.ptMaxSize.X = lPrimaryScreenInfo.rcWork.Right - lPrimaryScreenInfo.rcWork.Left; 
      lMmi.ptMaxSize.Y = lPrimaryScreenInfo.rcWork.Bottom - lPrimaryScreenInfo.rcWork.Top; 
    } 
    else 
    { 
      lMmi.ptMaxPosition.X = lPrimaryScreenInfo.rcMonitor.Left; 
      lMmi.ptMaxPosition.Y = lPrimaryScreenInfo.rcMonitor.Top; 
      lMmi.ptMaxSize.X = lPrimaryScreenInfo.rcMonitor.Right - lPrimaryScreenInfo.rcMonitor.Left; 
      lMmi.ptMaxSize.Y = lPrimaryScreenInfo.rcMonitor.Bottom - lPrimaryScreenInfo.rcMonitor.Top; 
    } 

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


private void SwitchWindowState() 
{ 
    switch (WindowState) 
    { 
     case WindowState.Normal: 
      { 
       WindowState = WindowState.Maximized; 
       break; 
      } 
     case WindowState.Maximized: 
      { 
       WindowState = WindowState.Normal; 
       break; 
      } 
    } 
} 


private void rctHeader_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
{ 
    if (e.ClickCount == 2) 
    { 
     if ((ResizeMode == ResizeMode.CanResize) || (ResizeMode == ResizeMode.CanResizeWithGrip)) 
     { 
      SwitchWindowState(); 
     } 

     return; 
    } 

    else if (WindowState == WindowState.Maximized) 
    { 
     mRestoreIfMove = true; 
     return; 
    } 

    DragMove(); 
} 


private void rctHeader_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e) 
{ 
    mRestoreIfMove = false; 
} 


private void rctHeader_PreviewMouseMove(object sender, MouseEventArgs e) 
{ 
    if (mRestoreIfMove) 
    { 
      mRestoreIfMove = false; 

      double percentHorizontal = e.GetPosition(this).X/ActualWidth; 
      double targetHorizontal = RestoreBounds.Width * percentHorizontal; 

      double percentVertical = e.GetPosition(this).Y/ActualHeight; 
      double targetVertical = RestoreBounds.Height * percentVertical; 

      WindowState = WindowState.Normal; 

      POINT lMousePosition; 
      GetCursorPos(out lMousePosition); 

      Left = lMousePosition.X - targetHorizontal; 
      Top = lMousePosition.Y - targetVertical; 

      DragMove(); 
    } 
} 

[DllImport("user32.dll")] 
[return: MarshalAs(UnmanagedType.Bool)] 
static extern bool GetCursorPos(out POINT lpPoint); 


[DllImport("user32.dll", SetLastError = true)] 
static extern IntPtr MonitorFromPoint(POINT pt, MonitorOptions dwFlags); 

enum MonitorOptions : uint 
{ 
     MONITOR_DEFAULTTONULL = 0x00000000, 
     MONITOR_DEFAULTTOPRIMARY = 0x00000001, 
     MONITOR_DEFAULTTONEAREST = 0x00000002 
} 


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


[StructLayout(LayoutKind.Sequential)] 
public struct POINT 
{ 
     public int X; 
     public int Y; 

     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; 
}; 


[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 
public class MONITORINFO 
{ 
     public int cbSize = Marshal.SizeOf(typeof(MONITORINFO)); 
     public RECT rcMonitor = new RECT(); 
     public RECT rcWork = new RECT(); 
     public int dwFlags = 0; 
} 


[StructLayout(LayoutKind.Sequential)] 
public struct RECT 
{ 
     public int Left, Top, Right, Bottom; 

     public RECT(int left, int top, int right, int bottom) 
     { 
      this.Left = left; 
      this.Top = top; 
      this.Right = right; 
      this.Bottom = bottom; 
     } 
} 

編輯: 請下載在我奮力實現期望的行爲一個簡單的兩頁示例項目。

Sample Project

回答

1

所以,你需要創建你的基類:

public class Maxi : Window 
{ 
    private bool mRestoreIfMove = false; 

    private void Window_SourceInitialized(object sender, EventArgs e) 
    { 
     IntPtr mWindowHandle = (new WindowInteropHelper(this)).Handle; 
     HwndSource.FromHwnd(mWindowHandle).AddHook(new HwndSourceHook(WindowProc)); 
    } 

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

     return IntPtr.Zero; 
    } 

    private static void WmGetMinMaxInfo(System.IntPtr hwnd, System.IntPtr lParam) 
    { 
     POINT lMousePosition; 
     GetCursorPos(out lMousePosition); 

     IntPtr lPrimaryScreen = MonitorFromPoint(new POINT(0, 0), MonitorOptions.MONITOR_DEFAULTTOPRIMARY); 
     MONITORINFO lPrimaryScreenInfo = new MONITORINFO(); 
     if (GetMonitorInfo(lPrimaryScreen, lPrimaryScreenInfo) == false) 
     { 
      return; 
     } 

     IntPtr lCurrentScreen = MonitorFromPoint(lMousePosition, MonitorOptions.MONITOR_DEFAULTTONEAREST); 

     MINMAXINFO lMmi = (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO)); 

     if (lPrimaryScreen.Equals(lCurrentScreen) == true) 
     { 
      lMmi.ptMaxPosition.X = lPrimaryScreenInfo.rcWork.Left; 
      lMmi.ptMaxPosition.Y = lPrimaryScreenInfo.rcWork.Top; 
      lMmi.ptMaxSize.X = lPrimaryScreenInfo.rcWork.Right - lPrimaryScreenInfo.rcWork.Left; 
      lMmi.ptMaxSize.Y = lPrimaryScreenInfo.rcWork.Bottom - lPrimaryScreenInfo.rcWork.Top; 
     } 
     else 
     { 
      lMmi.ptMaxPosition.X = lPrimaryScreenInfo.rcMonitor.Left; 
      lMmi.ptMaxPosition.Y = lPrimaryScreenInfo.rcMonitor.Top; 
      lMmi.ptMaxSize.X = lPrimaryScreenInfo.rcMonitor.Right - lPrimaryScreenInfo.rcMonitor.Left; 
      lMmi.ptMaxSize.Y = lPrimaryScreenInfo.rcMonitor.Bottom - lPrimaryScreenInfo.rcMonitor.Top; 
     } 

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

    private void SwitchWindowState() 
    { 
     switch (WindowState) 
     { 
      case WindowState.Normal: 
       { 
        WindowState = WindowState.Maximized; 
        break; 
       } 
      case WindowState.Maximized: 
       { 
        WindowState = WindowState.Normal; 
        break; 
       } 
     } 
    } 

    internal void rctHeader_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
    { 
     if (e.ClickCount == 2) 
     { 
      if ((ResizeMode == ResizeMode.CanResize) || (ResizeMode == ResizeMode.CanResizeWithGrip)) 
      { 
       SwitchWindowState(); 
      } 

      return; 
     } 

     else if (WindowState == WindowState.Maximized) 
     { 
      mRestoreIfMove = true; 
      return; 
     } 

     DragMove(); 
    } 


    internal void rctHeader_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e) 
    { 
     mRestoreIfMove = false; 
    } 

    internal void rctHeader_PreviewMouseMove(object sender, MouseEventArgs e) 
    { 
     if (mRestoreIfMove) 
     { 
      mRestoreIfMove = false; 

      double percentHorizontal = e.GetPosition(this).X/ActualWidth; 
      double targetHorizontal = RestoreBounds.Width * percentHorizontal; 

      double percentVertical = e.GetPosition(this).Y/ActualHeight; 
      double targetVertical = RestoreBounds.Height * percentVertical; 

      WindowState = WindowState.Normal; 

      POINT lMousePosition; 
      GetCursorPos(out lMousePosition); 

      Left = lMousePosition.X - targetHorizontal; 
      Top = lMousePosition.Y - targetVertical; 

      DragMove(); 
     } 
    } 

    [DllImport("user32.dll")] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    static extern bool GetCursorPos(out POINT lpPoint); 


    [DllImport("user32.dll", SetLastError = true)] 
    static extern IntPtr MonitorFromPoint(POINT pt, MonitorOptions dwFlags); 

    enum MonitorOptions : uint 
    { 
     MONITOR_DEFAULTTONULL = 0x00000000, 
     MONITOR_DEFAULTTOPRIMARY = 0x00000001, 
     MONITOR_DEFAULTTONEAREST = 0x00000002 
    } 


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


    [StructLayout(LayoutKind.Sequential)] 
    public struct POINT 
    { 
     public int X; 
     public int Y; 

     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; 
    }; 


    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 
    public class MONITORINFO 
    { 
     public int cbSize = Marshal.SizeOf(typeof(MONITORINFO)); 
     public RECT rcMonitor = new RECT(); 
     public RECT rcWork = new RECT(); 
     public int dwFlags = 0; 
    } 


    [StructLayout(LayoutKind.Sequential)] 
    public struct RECT 
    { 
     public int Left, Top, Right, Bottom; 

     public RECT(int left, int top, int right, int bottom) 
     { 
      this.Left = left; 
      this.Top = top; 
      this.Right = right; 
      this.Bottom = bottom; 
     } 
    } 
} 

你的主窗口中不包含任何代碼,但只是繼承:

public partial class MainWindow : Maxi 
{ 
    public MainWindow() { InitializeComponent(); } 
} 

然後,它僅僅讓的情況下,你XAML的權利 - 這意味着使用正確的命名空間創建類型基類的對象(在這種情況下,Maxi而不是窗口) - 但指定您的窗口,即在XAML本地:Maxi聲明的x:Class指令中繼承「Maxi」的類。

<local:Maxi 
    x:Class="WpfApplication3.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:WpfApplication3" 
    Title="MainWindow" Background="AliceBlue" WindowStyle="None" Height="350" Width="525" SourceInitialized="Window_SourceInitialized"> 
    <Grid> 
     <Rectangle Name="rctHeader" Height="40" VerticalAlignment="Top" Fill="CadetBlue" 
        PreviewMouseLeftButtonDown="rctHeader_PreviewMouseLeftButtonDown" 
        PreviewMouseLeftButtonUp="rctHeader_PreviewMouseLeftButtonUp" 
        PreviewMouseMove="rctHeader_PreviewMouseMove"/> 
    </Grid> 
</local:Maxi> 
+0

三江源的答覆,我實現了你的代碼,但我面臨以下錯誤:Wpf_Parent_Stype.CustomWindow1「不能指定不同的基類。請幫助... –

+0

我給你的示例代碼對於Windows和基類有不同的名稱。你需要得到正確的命名。如果你顯示你的代碼,我可以提供幫助,但目前你沒有全部顯示。你甚至沒有發佈XAML! –

+0

感謝您的回覆,我編輯了我的原始問題並上傳了一個示例項目(Visual Studio 2012)。請幫助... –