最近看了一下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 else110 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 else126 {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.Maximized142 ? WindowState.Normal143 : WindowState.Maximized;144 }145 }
功能主要cs代码
原标题:实现的WPF外边框窗体
关键词:wpf