實現的WPF外邊框窗體,實現WPF邊框窗體
最近看了一下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="" FontSize="20" Click="MinClick" />
21 <Button Content="" FontSize="16" Click="MaxClick" />
22 <Button Content="" 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代碼