1. 同时加载两个窗体
先添加一个子窗体,然后再app.xaml.cs里重写OnStartup方法
//app.xaml.cs
using System.Configuration;
using System.Data;
using System.Windows;
namespace WpfApp1
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
subWindow sb = new subWindow(); //这是子窗口
sb.Show();
}
}
}
参考链接:WPF一次性开启两个窗口 - 夜落璇玑 - 博客园 (cnblogs.com)
2.实现点击窗口任意位置拖动
1、注册3个事件如下:
// xaml里
<Window PreviewMouseLeftButtonDown="Window_PreviewMouseLeftButtonDown"
PreviewMouseMove="Window_PreviewMouseMove"
PreviewMouseLeftButtonUp="Window_PreviewMouseLeftButtonUp"/>
//cs里
public partial class subWindow : Window
{
//定义2个变量记录信息
Point _pressedPosition;
bool _isDragMoved = false;
public subWindow()
{
InitializeComponent();
}
//记录鼠标按下位置
void Window_PreviewMouseLeftButtonDown(object sender,
System.Windows.Input.MouseButtonEventArgs e)
{
_pressedPosition = e.GetPosition(this);
}
//鼠标移动触发拖动
void Window_PreviewMouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
if (Mouse.LeftButton == MouseButtonState.Pressed && _pressedPosition != e.GetPosition(this))
{
_isDragMoved = true;
DragMove();
}
}
//鼠标弹起屏蔽消息
void Window_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (_isDragMoved)
{
_isDragMoved = false;
e.Handled = true;
}
}
}
参考链接:c# wpf 实现窗口任意区域点击拖动_wpf 拖动窗体-CSDN博客
3.实现一个透明、无边框、鼠标穿透的WPF窗体
参考链接:Simple WPF:实现一个透明、无边框、鼠标穿透的WPF窗体 - 知乎 (zhihu.com)
//设置 AllowsTransparency="True" WindowStyle="None" Background="Transparent"
<Window x:Class="WpfApp1.subWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
PreviewMouseLeftButtonDown="Window_PreviewMouseLeftButtonDown"
PreviewMouseMove="Window_PreviewMouseMove"
PreviewMouseLeftButtonUp="Window_PreviewMouseLeftButtonUp"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="subWindow" Height="500" Width="700" AllowsTransparency="True" WindowStyle="None" Background="Transparent">
4.去除标题栏
//设置 WindowStyle ="None"
<Window x:Class="NonFrameWindow.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:NonFrameWindow"
mc:Ignorable="d"
WindowStyle ="None" ResizeMode="CanMinimize"
Title="MainWindow" Height="450" Width="800">
5.按钮渐变色 鼠标悬停时按钮不变色 控件重叠
<Window.Resources>
//设置grid的背景色
<Style TargetType="Grid" x:Key="ggrid">
<Setter Property="Background" Value="#F5F7F6F6"></Setter>
</Style>
<!--按钮渐变色-->
<LinearGradientBrush x:Key="Brush2" StartPoint="0,0" EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0" Color="#FF03A795" />
<GradientStop Offset="1" Color="#FF03786B" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
<LinearGradientBrush x:Key="Brush3" StartPoint="0,0" EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0" Color="#FF03A795" />
<GradientStop Offset="1" Color="#FF03786B" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
<!--button鼠标悬停时不变色-->
<Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{x:Null}"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
//调用
<Button Width="130" Height="50" Margin="5" Background="Transparent" BorderThickness="0,0,0,0" Style="{DynamicResource ButtonStyle}">
<Canvas>
<Border BorderThickness="2" Canvas.Left="-17" Canvas.Top="-14" Background="{StaticResource Brush3}" CornerRadius="4" Height="35" Width="80">
//border的渐变色
<Border.BorderBrush>
<RadialGradientBrush>
<GradientStop Color="Black"/>
<GradientStop Color="#FFCCCBCC" Offset="1"/>
</RadialGradientBrush>
</Border.BorderBrush>
<Label Content="123" FontSize="14" Margin="11,1,15,0" />
</Border>
<Border BorderThickness="2" Canvas.Left="-50" Canvas.Top="-17" Background="{StaticResource Brush2}" CornerRadius="18" Height="42" MinWidth="25">
<Border.BorderBrush>
<RadialGradientBrush>
<GradientStop Color="Black"/>
<GradientStop Color="#FFCCCBCC" Offset="1"/>
</RadialGradientBrush>
</Border.BorderBrush>
<Label Content="12" FontSize="14" HorizontalContentAlignment="Center" Margin="0,4,0,0" MinWidth="40"></Label>
</Border>
</Canvas>
</Button>
6. grid 分割线(圆角)
//圆角
<Border CornerRadius="15" BorderThickness="2" Margin="2,0,2,0" Background="#F7F7F7">
<Grid>
<Border>
</Border>
</Grid>
</Border>
<Grid.RowDefinitions>
<RowDefinition Height="9*"/>
<RowDefinition Height="9*"/>
<RowDefinition Height="12*"/>
<RowDefinition Height="12*"/>
<RowDefinition Height="24*"/>
<RowDefinition Height="3*"/>
</Grid.RowDefinitions>
<Rectangle Stroke="#FF6F6D6D" Grid.Row="1"/>
<Rectangle Stroke="#FF6F6D6D" Grid.Row="2"/>
<Rectangle Stroke="#FF6F6D6D" Grid.Row="3"/>
<Rectangle Stroke="#FF6F6D6D" Grid.Row="4"/>
<Rectangle Stroke="#FF6F6D6D" Grid.Row="5"/>
7. textblock 样式(渐变色 )
<TextBlock VerticalAlignment="Bottom" HorizontalAlignment="Left" FontSize="25" FontWeight="Black" Cursor="AppStarting" Height="30">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground">
<Setter.Value>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,0.5">
<GradientStop Color="#FF87E1FF" Offset="0.0" />
<GradientStop Color="#FF009FFF" Offset="0.5" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
</TextBlock.Style><Run Text="抢答器专家"/>
</TextBlock>
//设置字体颜色
<TextBlock Foreground="#FF03786B">加分</TextBlock>
8.textbox 样式(圆角)
<TextBox VerticalAlignment="Center" HorizontalAlignment="Center" Height="30" Width="60" >
<TextBox.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="CornerRadius" Value="2"/>
<Setter Property="BorderBrush" Value="#c1d0dc"/>
</Style>
</TextBox.Resources>
</TextBox>
第二种写法:
<Style TargetType="TextBox">
<Style.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="CornerRadius" Value="5"/>
<Setter Property="BorderBrush" Value="#c1d0dc"/>
</Style>
</Style.Resources>
</Style>
9.button
//设置圆角
<Button.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="CornerRadius" Value="3"></Setter>
</Style>
</Button.Resources>
//设置阴影
<Button.Effect>
<DropShadowEffect BlurRadius="20" ShadowDepth="0" Color="#DADADA" Opacity="0.2"/>
</Button.Effect>
<Style TargetType="{x:Type Button}">
<Setter Property="Foreground" Value="#FF333333"></Setter>
<Setter Property="BorderBrush" Value="#33000000"></Setter>
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="1,0" EndPoint="1,1">
<GradientStop Color="#FFFEFEFE" Offset="0.0"/>
<GradientStop Color="#FFF5F5F5" Offset="0.5" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="Black"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{StaticResource background}" BorderThickness="1" BorderBrush="#33000000">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<!--<Setter Property="Background" Value="{StaticResource Brush2}"></Setter>-->
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="Foreground" Value="#0E867F"></Setter>
</Trigger>
</Style.Triggers>
<Style.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="CornerRadius" Value="4"></Setter>
</Style>
</Style.Resources>
</Style>
10.ComboBox(样式)
xaml:
//圆角
<Style TargetType="{x:Type ComboBox}">
<Setter Property="Margin" Value="5"></Setter>
<Setter Property="Width" Value="120"></Setter>
<Setter Property="HorizontalAlignment" Value="Stretch"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBox}">
<Border BorderBrush="Gray" BorderThickness="1" CornerRadius="5" Background="Transparent">
<Grid>
<!--下拉箭头-->
<ToggleButton ClickMode="Press" Focusable="False" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Margin="2" MinWidth="0" MinHeight="0" Width="Auto">
<ToggleButton.Style>
<Style TargetType="{x:Type ToggleButton}">
<Setter Property="MinWidth" Value="0"/>
<Setter Property="MinHeight" Value="0"/>
<Setter Property="Width" Value="Auto"/>
<Setter Property="Height" Value="Auto"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="#00000000"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<DockPanel Background="{TemplateBinding Background}" LastChildFill="False" SnapsToDevicePixels="True">
<Border x:Name="Border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" DockPanel.Dock="Right" >
<Path Data="M0,0L3.5,4 7,0z" Fill="{TemplateBinding Foreground}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</DockPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}"/>
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>
<!--项内容-->
<ContentPresenter IsHitTestVisible="False" Content="{TemplateBinding SelectionBoxItem}" ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" VerticalAlignment="Center" Margin="3" HorizontalAlignment="Stretch" />
<TextBox x:Name="PART_EditableTextBox" HorizontalAlignment="Stretch" Focusable="True" Visibility="Collapsed" IsReadOnly="False"/>
<!--下拉显示面板HorizontalOffset:设置下拉面板的相对位置-->
<Popup HorizontalOffset="-1" Width="{TemplateBinding ActualWidth}"
IsOpen="{TemplateBinding IsDropDownOpen}" Focusable="False" PopupAnimation="Slide">
<Grid SnapsToDevicePixels="True" HorizontalAlignment="Stretch">
<Border BorderThickness="1,1,1,1" BorderBrush="Gray" HorizontalAlignment="Stretch" CornerRadius="5">
<Border.Background>
<SolidColorBrush Color="White" />
</Border.Background>
</Border>
<ScrollViewer SnapsToDevicePixels="True" HorizontalAlignment="Stretch" >
<StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained" HorizontalAlignment="Stretch" />
</ScrollViewer>
</Grid>
</Popup>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ComboBox Width="80" SelectionChanged="ComboBox_SelectionChanged">
<ComboBoxItem IsSelected="True">0</ComboBoxItem>
<ComboBoxItem>5</ComboBoxItem>
<ComboBoxItem>10</ComboBoxItem>
<ComboBoxItem>20</ComboBoxItem>
</ComboBox>
//允许编辑 设置IsEditable="True",即前面变成文本框形式
<ComboBox x:Name="AddScoreCombox" Width="80" IsEditable="True">
<ComboBoxItem>0</ComboBoxItem>
<ComboBoxItem>10</ComboBoxItem>
<ComboBoxItem>11</ComboBoxItem>
<ComboBoxItem IsSelected="True">19</ComboBoxItem>
</ComboBox>
cs:
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
int count = Convert.ToInt32(combobox.SelectedValue.ToString().Replace("System.Windows.Controls.ComboBoxItem: ", ""));
SubWindow subWindow = SubWindow.pwindow;
subWindow.Close();
SubWindow.hcount = count;
SubWindow subWindow2 = new SubWindow();
subWindow2.Show();
}
//动态生成Items
for(int i = 1; i <= SubWindow.count; i++)
{
combobox.Items.Add(i.ToString());
}
11.在子窗口控制主窗口动态生成控件时,会出现两个相同的窗口
解决办法:
在主窗口里
public static SubWindow pwindow = null;
public SubWindow()
{
InitializeComponent();
pwindow = this; //将当前窗口给pwindow,方便在setting里使用
}
在子窗口里,
SubWindow subWindow = SubWindow.pwindow;
subWindow.Close(); //关闭上一个窗口
SubWindow.hcount = count;
SubWindow subWindow2 = new SubWindow();
subWindow2.Show();
12.RadioButton
<RadioButton GroupName="zu" Margin="20,10,0,10" Grid.Row="0" Content="12" Click="RadioButton_Click"> </RadioButton>
<RadioButton IsChecked="True" GroupName="zu" Margin="20,10,0,10" Grid.Row="1" Content="34" Click="RadioButton_Click"></RadioButton>
private void RadioButton_Click(object sender, RoutedEventArgs e)
{
//获取radiobutton的值
RadioButton radioButton = sender as RadioButton;
radiobuttoncContent = radioButton.Content.ToString();
if (radioButton.IsChecked == true)
{
SubWindow subWindow = SubWindow.pwindow;
subWindow.Close();
SubWindow subWindow2 = new SubWindow();
subWindow2.Show();
}
}
13.slider
<WrapPanel Margin="20,70,0,0">
<TextBlock FontSize="14" LineHeight="12" Foreground="#333333">调整</TextBlock>
<Slider x:Name = "slider2" Width="90" Minimum = "0" Maximum = "3" ValueChanged = "slider1_ValueChanged" Margin = "23,0,0,0"></Slider>
<TextBox x:Name="textbox1" Text="{Binding Textbox1}" Width="25" Height="25" Margin="5,-3,0,0" VerticalContentAlignment="Center" HorizontalContentAlignment="Center"></TextBox>
</WrapPanel>
public static int buttonSize = 0;
private void slider1_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
string val = Convert.ToInt32(e.NewValue).ToString();
//string msg = String.Format("Current value: {0}", val);
this.textbox1.Text = val;
buttonSize =Convert.ToInt32(val);
SubWindow subWindow = SubWindow.pwindow;
subWindow.Close();
SubWindow subWindow2 = new SubWindow();
subWindow2.Show();
}
14.动态生成控件
private void CreateCanvas3()
{
LinearGradientBrush brush3 = (LinearGradientBrush)this.FindResource("Brush3");
LinearGradientBrush brush2 = (LinearGradientBrush)this.FindResource("Brush2");
Canvas canvas = new Canvas()
{
Margin = new Thickness(30 + buttonsize * 3 + Llength, 40 + buttonsize * 4 + hlength * 2, 90 + buttonsize * 3 + Llength, 40 + buttonsize * 3 + hlength * 2)
};
//成绩
Border border = new Border()
{
BorderThickness = new Thickness(2),
BorderBrush = System.Windows.Media.Brushes.WhiteSmoke,
Background = brush3,
CornerRadius = new CornerRadius(4),
Margin = new Thickness(30 + buttonsize * 6, 20 + buttonsize * 6, 2 + buttonsize * 6, 0+buttonsize * 6),
Height = 35 + buttonsize * 4,
Width = 80 + buttonsize * 5
};
Label label = new Label()
{
Content = "123",
FontSize = 14 + buttonsize * 2,
Margin = new Thickness(15, 1, 15, 0),
HorizontalContentAlignment = HorizontalAlignment.Center,
VerticalContentAlignment = VerticalAlignment.Center,
};
//名称
Border border2 = new Border()
{
BorderThickness = new Thickness(2,0,2,2),
BorderBrush = System.Windows.Media.Brushes.WhiteSmoke,
Background = brush3,
CornerRadius = new CornerRadius(0,0,4,4),
Margin = new Thickness(30 + buttonsize * 6, 53 + buttonsize * 6, 0 + buttonsize * 6, 0 + buttonsize * 6),
Height = 35 + buttonsize * 4,
Width = 80 + buttonsize * 5
};
Label label2 = new Label()
{
Content = "456",
FontSize = 14 + buttonsize * 2,
Margin = new Thickness(18, 1, 15, 0),
HorizontalContentAlignment = HorizontalAlignment.Center,
VerticalContentAlignment = VerticalAlignment.Center,
};
border.Child = label;
border2.Child = label2;
//组号
Border border1 = new Border()
{
BorderThickness = new Thickness(2),
BorderBrush = System.Windows.Media.Brushes.WhiteSmoke,
Background = brush2,
CornerRadius = new CornerRadius(50),
Margin = new Thickness(15 + buttonsize * 4, 17 + buttonsize * 4, 0, 0),
Height = 42 + buttonsize * 2,
Width = 40 + buttonsize * 2
};
Label label1 = new Label()
{
Content = "1",
FontSize = 14 + buttonsize * 2,
HorizontalContentAlignment = HorizontalAlignment.Center,
VerticalContentAlignment = VerticalAlignment.Center,
Margin = new Thickness(0, 4, 0, 0),
MinWidth = 40
};
border1.Child = label1;
canvas.Children.Add(border);
canvas.Children.Add(border2);
canvas.Children.Add(border1);
canvaswidth = 110;
buttonwrap.Children.Add(canvas);
}
15.控件右击事件
右击事件是MouseRightButtonUp
//windows.resource里定义一个ContextMenu
<ContextMenu x:Key="ContextMenu">
<MenuItem Name="setting" Header="设置" Click="MenuItem_Click">
</MenuItem>
</ContextMenu>
//右击事件是MouseRightButtonUp,右击之后出现ContextMenu里的设置
<Grid MouseRightButtonUp="Mouse_RightButtonUp" Margin="0,10,0,0">
<WrapPanel x:Name="buttonwrap">
</WrapPanel>
</Grid>
private void Mouse_RightButtonUp(object sender, MouseButtonEventArgs e)
{
Grid sp = (Grid)sender;
ContextMenu cm = new ContextMenu();
ContextMenu ct= this.FindResource("ContextMenu") as ContextMenu;
sp.ContextMenu = ct;
}
//打开设置窗口
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
setting st = new setting();
st.ShowDialog();
}
16.窗体靠近屏幕左边隐藏,并生成一个小球
参考:
c# 获取当前活动窗口句柄,获取窗口大小及位置 - jack_Meng - 博客园 (cnblogs.com)
C# 完美实现窗口边缘吸附功能 - 流泪的冰淇淋 - 博客园 (cnblogs.com)
wpf 如何让当前窗口隐藏_wpf 窗口关闭设置看不到-CSDN博客
wpf 类似于360加速球,的拖动和点击功能的实现_-CSDN问答
[小结][N种方法]实现WPF不规则窗体 - DebugLZQ - 博客园 (cnblogs.com)
WPF中控制窗口显示位置的三种方式 - LJD泊水 - 博客园 (cnblogs.com)
WPF中三种方法得到当前屏幕的宽和高_fullprimaryscreenheight-CSDN博客
在要隐藏的页面的xaml里:
<Grid MouseLeftButtonDown="Grid_MouseLeftButtonDown">
<Image Stretch="Fill" Source="/WPFSharpWindow;component/cow.png" />
</Grid>
cs:
//定义2个变量记录信息
Point _pressedPosition;
bool _isDragMoved = false;
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern int ShowWindow(IntPtr hwnd, int nCmdShow);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left; //最左坐标
public int Top; //最上坐标
public int Right; //最右坐标
public int Bottom; //最下坐标
}
public static MainWindow pwindow=null;
public MainWindow()
{
InitializeComponent();
pwindow = this;
}
+ private void Grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
this.DragMove();
//获取当前屏幕的大小
// double screenheight = SystemParameters.PrimaryScreenHeight;
//this.Left = e.GetPosition(this).Y - 50;
_pressedPosition = e.GetPosition(this);
IntPtr myptr = GetForegroundWindow();
IntPtr awin = GetForegroundWindow(); //获取当前窗口句柄
RECT rect = new RECT();
GetWindowRect(awin, ref rect);
double x = rect.Left;
MessageBox.Show(x.ToString());
if (x <= 1)
{
this.ShowInTaskbar = false;
this.Visibility = Visibility.Hidden;
Hide window1 = new Hide();
//自定义控件显示位置
window1.WindowStartupLocation = WindowStartupLocation.Manual;
window1.Left = -50;
window1.Top = 5;
window1.Show();
}
}
//显示小球的界面:
<Window x:Class="Test.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Test"
mc:Ignorable="d"
Title="Window1" Height="85" Width="85" Background="Transparent" AllowsTransparency="True" WindowStyle="None">
<Grid MouseLeftButtonDown="Grid_MouseLeftButtonDown" >
<Border Background="blue" CornerRadius="190">
<Button Click="Button_Click" Background="Transparent" Width="50" Height="46" Margin="18,0,0,0">
<Button.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="CornerRadius" Value="190"></Setter>
<Setter Property="BorderThickness" Value="0"></Setter>
</Style>
</Button.Resources>
<Image Source="/img/展开.png"></Image>
</Button>
</Border>
</Grid>
</Window>
cs里:
private void Grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
this.DragMove();
this.Left = e.GetPosition(this).Y-50;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
MainWindow mainWindow = MainWindow.pwindow;
//mainWindow.Show();
mainWindow.ShowInTaskbar = true;
mainWindow.Visibility = Visibility.Visible;
//this.Visibility = Visibility.Hidden;
this.ShowInTaskbar = false;
this.Visibility=Visibility.Hidden;
}
17.wpf 记忆上次关闭时窗口的位置,并在下次打开时读取位置
参考:
WPF编程,窗口保持上次关闭时的大小与位置。_closing="window_closing-CSDN博客
若是没有settings文件,可以右击项目-添加-配置文件
1.在settings添加变量
2.在窗口关闭事件中保存窗口位置
private void Button_Click(object sender, RoutedEventArgs e)
{
Settings.Default.Left =this.RestoreBounds.Left;
Settings.Default.Top = this.RestoreBounds.Top;
Settings.Default.Save();
this.Close();
}
3.在窗口的构造函数中读取位置
//读取配置文件
try
{
//设置位置、大小
//Rect restoreBounds = Properties.Settings.Default.MainRestoreBounds;
//this.WindowState = WindowState.Normal;
this.Left = Settings.Default.Left;
this.Top = Settings.Default.Top;
}
catch { }
18.鼠标悬停事件
参考:WPF鼠标事件简介_wpf 鼠标悬浮事件-CSDN博客
19.窗口圆角
//在window里写入WindowStyle="None" AllowsTransparency="True" Background="Transparent" OpacityMask="White"
<Window x:Class="Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
PreviewMouseLeftButtonDown="Window_PreviewMouseLeftButtonDown"
PreviewMouseMove="Window_PreviewMouseMove"
PreviewMouseLeftButtonUp="Window_PreviewMouseLeftButtonUp"
xmlns:local="clr-namespace:Test"
ResizeMode = "NoResize"
mc:Ignorable="d"
Title="" Height="720" Width="200" WindowStyle="None" AllowsTransparency="True" Background="Transparent" OpacityMask="White">
<Border Width="200" CornerRadius="15" BorderThickness="2" Margin="2,0,2,0" Background="Firebrick">
<Grid>
<Border CornerRadius="30,30,30,30">
<TextBlock>123</TextBlock>
</Border>
</Grid>
</Border>
</Window>
20.wpf设置gif动图为背景
1.WpfAnimatedGIF
参考:
在WPF显示动态GIF图片 - 雨也绵绵 - 博客园 (cnblogs.com)
1.添加nuget包,安装WpfAnimatedGIF,
2.添加 xmlns:gif="http://wpfanimatedgif.codeplex.com"
3.引用:
<Window x:Class="Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:gif="http://wpfanimatedgif.codeplex.com"
xmlns:local="clr-namespace:Test"
//在设计模式下可以看见效果
gif:ImageBehavior.AnimateInDesignMode="True"
mc:Ignorable="d"
Title="MainWindow" Height="750" Width="1200">
调用:
<Grid.Background>
<VisualBrush>
<VisualBrush.Visual>
<Image gif:ImageBehavior.AnimatedSource="\img\R-C.gif"></Image>
</VisualBrush.Visual>
</VisualBrush>
</Grid.Background>
2. ImageAnimator
参考:
cs:
调用:
imgGifShow.ImageSource = GetGifImage(path);
更换动图或关闭时:要把ImageSource设为空,以防内存泄漏
if (imgPath.EndsWith(".gif"))
{
StopAnimate();
}
imgGifShow.ImageSource = null;
#region 显示动图
public BitmapSource GetGifImage(string path)
{
this.gifBitmap = new Bitmap(path);
imgPath = path;
this.bitmapSource = this.GetBitmapSource();
//this.imgGifShow.ImageSource = this.bitmapSource;
StartAnimate();
return bitmapSource;
}
/// <summary>
/// 从System.Drawing.Bitmap中获得用于显示的那一帧图像的BitmapSource
/// </summary>
/// <returns></returns>
private BitmapSource GetBitmapSource()
{
IntPtr handle = IntPtr.Zero;
try
{
handle = this.gifBitmap.GetHbitmap();
this.bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(handle, IntPtr.Zero, System.Windows.Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
}
finally
{
if (handle != IntPtr.Zero)
{
DeleteObject(handle);
}
}
return this.bitmapSource;
}
/// <summary>
/// Start
/// </summary>
public void StartAnimate()
{
ImageAnimator.Animate(this.gifBitmap, this.OnFrameChanged);
}
/// <summary>
/// Stop
/// </summary>
public void StopAnimate()
{
ImageAnimator.StopAnimate(this.gifBitmap, this.OnFrameChanged);
}
/// <summary>
/// 帧处理
/// </summary>
private void OnFrameChanged(object sender, EventArgs e)
{
Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
{
ImageAnimator.UpdateFrames(); // 更新到下一帧
if (this.bitmapSource != null)
{
this.bitmapSource.Freeze();
}
this.bitmapSource = this.GetBitmapSource();
this.imgGifShow.ImageSource = this.bitmapSource;
this.InvalidateVisual();
}));
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
StopAnimate();
}
/// <summary>
/// 删除本地 bitmap resource
/// </summary>
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool DeleteObject(IntPtr hObject);
#endregion
21.倒计时功能
倒计时有三种写法:
1. DispatcherTimer:
DispatcherTimer是为 WPF 专门设计的,不然的话会提示界面资源被其他线程所拥有而无法更新界面。DispatcherTimer 是在 UI 线程跑的可以直接更新 UI
DispatcherTimer 定时器不是单独开启一个线程来运行定时器方法,而是和主线程是同一个线程,只是通过改变运行优先级来实现定时器,当定时器时间到了,主线程就转去执行定时器方法。因此DispatcherTimer定时器不要用来实现执行时间长的任务,不然会使主线程很卡,导致WPF界面很难看,用户不友好!
xaml:
<Border x:Name="DJSBorder" Width="130" Height="130" HorizontalAlignment="Right" Margin="0,0,100,0" Visibility="Collapsed">
<Border.Background>
<ImageBrush ImageSource="\img\倒计时@2x.png"></ImageBrush>
</Border.Background>
<TextBox x:Name="DaoJiShi" IsEnabled="False" Width="70" Height="70" FontSize="70" Background="Transparent" BorderThickness="0"
VerticalContentAlignment="Center" HorizontalContentAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,20"></TextBox>
</Border>
//签到按钮
<Button x:Name="qiandao" Width="80" Height="40" Style="{StaticResource btn1}" FontSize="18" HorizontalAlignment="Left" VerticalAlignment="Top"
Margin="30" Click="QianDao_Click">签到</Button>
cs:
private int Second = 10;
//倒计时
public void disTimer_Tick(object sender, EventArgs e)
{
Second--;
if (Second <0)
{
MessageBox.Show("倒计时已结束!", "系统提示", MessageBoxButton.OK, MessageBoxImage.Warning);
this.disTimer.Stop();//计时停止
//DJSBorder.Visibility = Visibility.Collapsed;
}
else
{
if (Second <= 3)
{
DaoJiShi.Foreground = System.Windows.Media.Brushes.Red;
}
else
{
DaoJiShi.Foreground = System.Windows.Media.Brushes.Yellow;
}
//判断是否处于UI线程上
//判断是否处于UI线程上
if (DaoJiShi.Dispatcher.CheckAccess())
{
DaoJiShi.Text = Second.ToString();
}
else
{
DaoJiShi.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(() =>
{
DaoJiShi.Text = Second.ToString();
}));
}
}
}
private DispatcherTimer disTimer = new DispatcherTimer();
public void CountDown()
{
disTimer.Tick += new EventHandler(disTimer_Tick);//每一秒执行的方法
disTimer.Interval = new TimeSpan(10000000); //时间间隔为一秒。
//因为设置时间间隔后,计时开始后会先过一秒才开始显示倒数计时的时间,这么算起来相当于是多计时了一秒,
//所以要在计时开始前先设置textbox里的值
//然后在计时开始后就减一操作
DaoJiShi.Text = Second.ToString();
DaoJiShi.Foreground = System.Windows.Media.Brushes.Yellow;
disTimer.Start();//计时开始
}
2.System.Timers.Timer
组件Timer是基于服务器的计时器,在属性中的毫秒Interval数过后,该计时器在应用程序中引发Elapsed事件。 可以将 对象配置为 Timer 仅引发一次事件,也可以使用 属性重复引发事件 AutoReset 。 通常, Timer 对象在类级别声明,以便只要需要,它就保留在范围内。 然后,可以处理其 Elapsed 事件以提供常规处理。 例如,假设关键服务器必须保持每周 7 天、每天 24 小时运行。 可以创建一个Timer服务,该服务使用 对象定期检查服务器并确保系统正常运行。 如果系统未响应,服务可能会尝试重启服务器或通知管理员。
Timer 是在非UI线程跑的,不能直接操作UI控件
System.Timers.Timer如果在 WPF 应用程序中使用 ,请注意,在System.Timers.Timer用户界面 (UI) 线程的线程上运行。 若要访问用户界面 (UI) 线程上的对象,需要使用Dispatcher.Invoke 或 BeginInvoke将操作
发布到用户界面 (UI) 线程
上。
System.Timers.Timer timer = null;
public StartBiaoJue(string value1)
{
InitializeComponent();
timer = new System.Timers.Timer(1000); //计时间隔为1秒
timer.Elapsed += Timer_Elapsed;
timer.AutoReset = true;
timer.Enabled = true; //开启计时
}
private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
Second--;
//创建一个委托,用于封装一个方法,在这里是封装了 控制更新控件 的方法
Dispatcher.Invoke(() =>
{
// 更新UI元素
DaoJiShi.Text = Second.ToString(); //文本框值更改
if (Second <= 3 && Second >0)
{
DaoJiShi.Foreground = System.Windows.Media.Brushes.Red;
}
if (Second == 0)
{
timer.Enabled = false; //关闭计时
DJSBorder.Visibility = Visibility.Collapsed;
}
});
}
private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
Second--;
//创建一个委托,用于封装一个方法,在这里是封装了 控制更新控件 的方法
Dispatcher.BeginInvoke(new Action(() =>
{
// 更新UI元素
DaoJiShi.Text = Second.ToString(); //文本框值更改
if (Second <= 3 && Second >0)
{
DaoJiShi.Foreground = System.Windows.Media.Brushes.Red;
}
if (Second == 0)
{
timer.Enabled = false; //关闭计时
DJSBorder.Visibility = Visibility.Collapsed;
}
});
}
3.System.Threading.Timer
System.Threading.Timer 是由线程池调用的。
所有的Timer对象只使用了一个线程来管理。这个线程知道下一个Timer对象在什么时候到期。下一个Timer对象到期时,线程就会唤醒,在内部调用ThreadPool 的 QueueUserWorkItem,将一个工作项添加到线程池队列中,使你的回调方法得到调用。如果回调方法的执行时间很长,计时器可能(在上个回调还没有完成的时候)再次触发。这可能造成多个线程池线程同时执行你的回调方法。
没实际用,因此没代码
可参考:Timer 类 (System.Threading) | Microsoft Learn
22.两个窗口间传值(委托)
1.主窗口向子窗口传值
1.可以在子窗口里定义一个变量用来接收值
子窗口cs里:
public string test_str { get; set; }
public child_window()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
tb_receive.Text = test_str;
}
主窗口cs里:
private void Button_Click(object sender, RoutedEventArgs e)
{
child_window child_Window = new child_window();
child_Window.test_str = tb_message.Text;
child_Window.Show();
}
2.直接通过构造函数来实现 重载
子窗口构造函数改为:也可以再添加一个构造函数,多个构造函数只要参数不同,就不冲突。
public child_window(string str)
{
InitializeComponent();
tb_receive.Text=str;
}
主窗口里:
private void Button_Click(object sender, RoutedEventArgs e)
{
//把值当参数传到子窗口里
child_window child_Window = new child_window(tb_message.Text);
child_Window.Show();
}
2.子窗口向主窗口传值(利用委托)
子窗口:
public delegate void SendMessage(string value);
public SendMessage sendMessage;
public child_window()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
sendMessage(tb_send.Text);
}
主窗口:
public void Recevie(string value)
{
tb_recevie.Text = value;
}
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
child_window child_Window = new child_window();
child_Window.sendMessage = Recevie;
child_Window.Show();
}