最近看了一下wpf 越發喜歡. 邊看邊學,順便做點東西. WPF 的窗體有點醜.就自己做個窗體,當學習的demo吧 效果圖:實現功能: 最大化;最小化;關閉;按鈕三態; 標題欄拖動;雙擊標題欄最大化或者還原;滑鼠在窗體邊緣拖動可調整窗體大小;1. 右上角三個按鈕採用樣式實現效果 1 樣式2...
最近看了一下wpf 越發喜歡. 邊看邊學,順便做點東西. WPF 的窗體有點醜.就自己做個窗體,當學習的demo吧
效果圖:
實現功能: 最大化;最小化;關閉;按鈕三態; 標題欄拖動;雙擊標題欄最大化或者還原;滑鼠在窗體邊緣拖動可調整窗體大小;
1. 右上角三個按鈕採用樣式實現效果
1 <Style x:Key="ButtonIconStyle" TargetType="Button"> 2 <Setter Property="FontFamily" Value="/WindowResize;component/Resources/#iconfont"></Setter> 3 <Setter Property="Background" Value="Transparent"></Setter> 4 <Setter Property="Foreground" Value="Black"></Setter> 5 <Setter Property="BorderBrush" Value="Transparent"></Setter> 6 <Setter Property="Padding" Value="3,3,3,3" /> 7 <Setter Property="Template" > 8 <Setter.Value> 9 <ControlTemplate TargetType="{x:Type Button}"> 10 <StackPanel Orientation="Horizontal" VerticalAlignment="Center" > 11 <TextBlock Name="Icon" 12 Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path= Content}" 13 FontSize="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path= FontSize}" 14 /> 15 </StackPanel> 16 <ControlTemplate.Triggers> 17 <Trigger Property="IsMouseOver" Value="True" > 18 <Setter Property="Background" Value="Transparent" TargetName="Icon" ></Setter> 19 <Setter Property="Foreground" Value="Gray" TargetName="Icon"></Setter> 20 </Trigger> 21 <Trigger Property="IsPressed" Value="True" > 22 <Setter Property="Background" Value="Transparent" TargetName="Icon" ></Setter> 23 <Setter Property="Foreground" Value="DarkGray" TargetName="Icon" ></Setter> 24 </Trigger> 25 </ControlTemplate.Triggers> 26 </ControlTemplate> 27 </Setter.Value> 28 </Setter> 29 30 </Style>樣式
2. 佈局 這裡有一個像素的boder
1 <Border BorderThickness="1,1,1,1" BorderBrush="Black"> 2 <Grid> 3 <Grid.RowDefinitions> 4 <RowDefinition Height="30"></RowDefinition> 5 <RowDefinition Height="*"></RowDefinition> 6 </Grid.RowDefinitions> 7 <Grid Grid.Row="0" Background="YellowGreen" MouseMove="HeaderMouseMove" MouseDown="HeaderMouseDown"> 8 <Grid Height="{Binding Height, RelativeSource={RelativeSource TemplatedParent}}" 9 Width="{Binding Width, RelativeSource={RelativeSource TemplatedParent}}" Margin="0,0,0,0"> 10 <Grid.ColumnDefinitions> 11 <ColumnDefinition Width="*"/> 12 <ColumnDefinition Width="Auto"/> 13 </Grid.ColumnDefinitions> 14 <StackPanel Orientation="Horizontal" Grid.Column="0" Grid.ColumnSpan="2" > 15 <Image Source="Resources/icon.png" Width="20" Height="20" Margin="4,0,0,0"></Image> 16 <TextBlock x:Name="CustomTitle" Text="標題要長一定要長" FontSize="14" 17 Margin="4,0,0,0" VerticalAlignment="Center" /> 18 </StackPanel> 19 <StackPanel Orientation="Horizontal" Grid.Column="2" Margin="0,4,4,4" > 20 <Button Content="" Style="{StaticResource ButtonIconStyle}" FontSize="20" Click="MinClick" /> 21 <Button Content="" Style="{StaticResource ButtonIconStyle}" FontSize="16" Click="MaxClick" /> 22 <Button Content="" Style="{StaticResource ButtonIconStyle}" FontSize="20" Click="CloseClick" RenderTransformOrigin="0.52,0.273"/> 23 </StackPanel> 24 </Grid> 25 </Grid> 26 <Grid Grid.Row="1"></Grid> 27 </Grid> 28 </Border>佈局
3. C#代碼實現
- 採用win32函數獲取滑鼠位置
-
1 /// <summary> 2 /// 獲取滑鼠的坐標 3 /// </summary> 4 /// <param name="lpPoint">傳址參數,坐標point類型</param> 5 /// <returns>獲取成功返回真</returns> 6 [DllImport("user32.dll", CharSet = CharSet.Auto)] 7 public static extern bool GetCursorPos(out POINT pt); 8 public struct POINT 9 { 10 public int X; 11 public int Y; 12 public POINT(int x, int y) 13 { 14 this.X = x; 15 this.Y = y; 16 } 17 }
獲取滑鼠信息 - 調整位置大小用到的類->網路獲取
1 public enum HitTest : int 2 { 3 HTERROR = -2, 4 HTTRANSPARENT = -1, 5 HTNOWHERE = 0, 6 HTCLIENT = 1, 7 HTCAPTION = 2, 8 HTSYSMENU = 3, 9 HTGROWBOX = 4, 10 HTSIZE = HTGROWBOX, 11 HTMENU = 5, 12 HTHSCROLL = 6, 13 HTVSCROLL = 7, 14 HTMINBUTTON = 8, 15 HTMAXBUTTON = 9, 16 HTLEFT = 10, 17 HTRIGHT = 11, 18 HTTOP = 12, 19 HTTOPLEFT = 13, 20 HTTOPRIGHT = 14, 21 HTBOTTOM = 15, 22 HTBOTTOMLEFT = 16, 23 HTBOTTOMRIGHT = 17, 24 HTBORDER = 18, 25 HTREDUCE = HTMINBUTTON, 26 HTZOOM = HTMAXBUTTON, 27 HTSIZEFIRST = HTLEFT, 28 HTSIZELAST = HTBOTTOMRIGHT, 29 HTOBJECT = 19, 30 HTCLOSE = 20, 31 HTHELP = 21, 32 }
HitTest - 主要C#代碼,很少很簡單
1 private const int WM_NCHITTEST = 0x0084; 2 private readonly int agWidth = 8; //拐角寬度 3 private readonly int bThickness = 2; // 邊框寬度 4 private Point mousePoint = new Point(); //滑鼠坐標 5 6 protected override void OnSourceInitialized(EventArgs e) 7 { 8 base.OnSourceInitialized(e); 9 HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource; 10 if (hwndSource != null) 11 { 12 hwndSource.AddHook(new HwndSourceHook(this.WndProc)); 13 } 14 } 15 16 protected virtual IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) 17 { 18 switch (msg) 19 { 20 case WM_NCHITTEST: 21 #region 測試滑鼠位置 22 if (WindowState == WindowState.Normal) 23 { 24 this.mousePoint.X = (lParam.ToInt32() & 0xFFFF); 25 this.mousePoint.Y = (lParam.ToInt32() >> 16); 26 // 視窗左上角 27 if (this.mousePoint.Y - this.Top <= this.agWidth 28 && this.mousePoint.X - this.Left <= this.agWidth) 29 { 30 handled = true; 31 return new IntPtr((int) HitTest.HTTOPLEFT); 32 33 } 34 // 視窗左下角 35 else if (this.ActualHeight + this.Top - this.mousePoint.Y <= this.agWidth 36 && this.mousePoint.X - this.Left <= this.agWidth) 37 { 38 handled = true; 39 return new IntPtr((int) HitTest.HTBOTTOMLEFT); 40 } 41 // 視窗右上角 42 else if (this.mousePoint.Y - this.Top <= this.agWidth 43 && this.ActualWidth + this.Left - this.mousePoint.X <= this.agWidth) 44 { 45 handled = true; 46 return new IntPtr((int) HitTest.HTTOPRIGHT); 47 } 48 // 視窗右下角 49 else if (this.ActualWidth + this.Left - this.mousePoint.X <= this.agWidth 50 && this.ActualHeight + this.Top - this.mousePoint.Y <= this.agWidth) 51 { 52 handled = true; 53 return new IntPtr((int) HitTest.HTBOTTOMRIGHT); 54 } 55 // 視窗左側 56 else if (this.mousePoint.X - this.Left <= this.bThickness) 57 { 58 handled = true; 59 return new IntPtr((int) HitTest.HTLEFT); 60 } 61 // 視窗右側 62 else if (this.ActualWidth + this.Left - this.mousePoint.X <= this.bThickness) 63 { 64 handled = true; 65 return new IntPtr((int) HitTest.HTRIGHT); 66 } 67 // 視窗上方 68 else if (this.mousePoint.Y - this.Top <= this.bThickness) 69 { 70 handled = true; 71 return new IntPtr((int) HitTest.HTTOP); 72 } 73 // 視窗下方 74 else if (this.ActualHeight + this.Top - this.mousePoint.Y <= this.bThickness) 75 { 76 handled = true; 77 return new IntPtr((int) HitTest.HTBOTTOM); 78 } 79 } 80 //else // 視窗移動 81 //{ 82 // handled = true; 83 // return new IntPtr((int)HitTest.HTCAPTION); 84 //} 85 break; 86 87 #endregion 88 } 89 return IntPtr.Zero; 90 } 91 92 private void HeaderMouseMove(object sender, MouseEventArgs e) 93 { 94 95 if (e.LeftButton == MouseButtonState.Pressed) 96 { 97 98 if (this.WindowState == WindowState.Maximized) 99 { 100 POINT px; 101 GetCursorPos(out px); 102 this.WindowState = WindowState.Normal; 103 Point p = e.GetPosition(sender as IInputElement); 104 double x = SystemParameters.WorkArea.Width;//得到屏幕工作區域寬度 105 this.Left = px.X - (p.X/x)*this.Width; 106 this.Top = px.Y - 5; 107 108 } 109 else 110 this.DragMove(); 111 } 112 } 113 114 private void MinClick(object sender, RoutedEventArgs e) 115 { 116 this.WindowState= WindowState.Minimized; 117 } 118 119 private void MaxClick(object sender, RoutedEventArgs e) 120 { 121 if (this.WindowState == WindowState.Maximized) 122 { 123 this.WindowState = WindowState.Normal; 124 } 125 else 126 { 127 this.WindowState = WindowState.Maximized; 128 129 } 130 } 131 132 private void CloseClick(object sender, RoutedEventArgs e) 133 { 134 this.Close(); 135 } 136 137 private void HeaderMouseDown(object sender, MouseButtonEventArgs e) 138 { 139 if (e.ClickCount == 2) 140 { 141 this.WindowState = this.WindowState == WindowState.Maximized 142 ? WindowState.Normal 143 : WindowState.Maximized; 144 } 145 }
功能主要cs代碼