# wpfMainWindow
**Repository Path**: zxjlxc/wpf-main-window
## Basic Information
- **Project Name**: wpfMainWindow
- **Description**: 设置主窗体的几种方法
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2023-11-08
- **Last Updated**: 2023-12-04
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 一、概述
怎样处理主界面的样式
# 二、解决方案
## 1.直接去掉窗口的边框和标题栏
1、先写一个border置顶

效果

2、去掉标题栏
```C#
WindowStyle="None"
```
效果

3、去掉四周的拖拽
```C#
AllowsTransparency="True"
```
效果

4、给窗体添加可以调整大小属性
```c#
ResizeMode="CanResizeWithGrip"
```
效果

5、给红色的border添加鼠标拖拽事件
```c#
MouseMove="Border_MouseMove"
```
```c#
private void Border_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
DragMove();
}
}
```
6、最小化、最大化、关闭


```C#
private void MinTextBlock_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
this.WindowState = WindowState.Minimized;
}
private void MaxTextBlock_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (this.WindowState == WindowState.Maximized)
{
this.WindowState = WindowState.Normal;
}
else
this.WindowState = WindowState.Maximized;
}
private void CloseTextBlock_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
this.Close();
}
```
改进使用矢量图
```C#
```
效果

7、重写右下角的拖拽图标
如果感觉右下角的图标比较丑

Thumb 类,表示可由用户拖动的控件。
首先删除窗口的属性,去掉这一句
```C#
ResizeMode="CanResizeWithGrip"
```
然后
```C#
```
```C#
private void Thumb_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
Width += e.HorizontalChange;
Height += e.VerticalChange;
}
```
效果,背景色设置为透明了,所以看不到

## 2、使用WindowChrome
### ①基本内容
一个标准的Window的基本构成,主要由非工作区(non-client area)和工作区(client area)组成。
标准window中除client之外的部分称为non-client area,通常称之为chrome,它提供了标准的窗口功能和行为,具体包含以下部分:边框、阴影、标题栏、Icon、标题、SystemMenu、最小化、最大化、还原、关闭、大小调整手柄。
当Window处于最大化状态时标题栏比较矮。在100% DPI时标题栏的高度为30像素,最大化时变为22像素,这时候右上角的几个按钮缩小了,其它元素的Margin也减少了一些。
### ②Window的大小
最后要说的是Window的大小。Window的实际大小并不是表面上看到的大小。
如下Window定义的大小为450,800,实时可视化树显示网格abc的大小是785.6,412.8。高度可能是因为标题栏,但宽度可以肯定是变小了。

如果将Window设置为启动位置在左上角
```C#
WindowStartupLocation="Manual" Top="0" Left="0"
```
效果(可以看到左边有间隔,上边没有)

通过[Inspect](https://docs.microsoft.com/zh-cn/windows/desktop/WinAuto/inspect-objects)看到的Window如下,黄色边框为它的实际范围:

可以看到系统理解的Window范围和我们看到的不同,这是Window设计的问题,有几个值用于计算chrome的尺寸:

在有标题的标准Window,chrome的顶部尺寸为SM_CYFRAME + SM_CXPADDEDBORDER + SM_CYCAPTION = 31,左右两边尺寸为SM_CXFRAME + SM_CXPADDEDBORDER = 8,底部尺寸为SM_CYFRAME + SM_CXPADDEDBORDER = 8。
最大化情况下Border和ResizeBorder都超出屏幕范围而且被隐藏了,所以Window的尺寸会超过显示器工作区的尺寸,这时候标题栏也会相应地变矮。在Windows 10,系统认为Window有4像素的ResizeBorder,但因为Windows 10是窄边框设计,而且在普通状态下和最大化状态下的标题栏高度还不一样,导致用UISpy观察Window和我们看到的Window不一致,也常常导致位置计算上的问题。
注意,上面的尺寸计算都是基于100 % DPI,在不同DPI的情况下还需要将DPI的值纳入计算。
### ③案例
目的:尽量保存原窗口属性,又可以使工作区(client)覆盖非工作区(non-client、chrome)。
1.我认为是把WindowChrome写出来,并且为空,所以之前的一些设置没有了,这样就使得工作区覆盖到了非工作区。同时移动、最小化、最大化、关闭功能都还在,只是看不到。
```C#
```
效果

2.我认为是重新写真实的工作区,使他为空,这样我们可以观察一切。
```C#
```
效果(此时我们可以清楚的看到布局)

3.关闭按钮没有贴近右边,我们把左右下设置为非工作区的边界
```c#
NonClientFrameEdges="Left,Bottom,Right"
```
效果

4.但是现在窗口最大化时标题栏和里面的按钮就被压缩变短了,如下图

可以把上边的厚度改大一些,不让原始的工作区挤压到标题栏
```c#
GlassFrameThickness="0,64,0,0"
```
效果

最大化时(可以看到也没有被挤压)

到这里,就实现了工作区可以覆盖非工作区,也保留了基本属性。
## 3、简单方便的方法
前面两种方案各有优缺。第一种比较灵活,但是没有了基本属性。第二种保留了很多基本属性,但是不够灵活,比如想要实现标题栏按钮的一些效果比较麻烦。
看到有人说两种结合比较简单方便。
1.使用
```c#
WindowStyle="None"
```
去掉样式(没有了按钮,但是周边还可以拖拽),再使用
```c#
```
此时的效果是有基本属性(周边可以拖拽、窗体可以移动),工作区也覆盖了非工作区,也没有标题栏按钮,可以灵活的自定义各种效果。
注意:给在WindowChrome区域的元素添加WindowChrome.IsHitTestVisibleInChrome="True"附加属性。这样WindowChrome区域的元素就可以交互了。
效果

## 4、效果最好的应该是2
可以参考项目WpfAppTest
建议使用这样的
```
```