**
原理:
**
以Canvas作为水印显示载体,在Canvas中创建若干个TextBlock控件用来显示水印文案,如下图所示
然后以每一个TextBlock的左上角为中心旋转-30°,最终效果会是如图红线所示:
为了达到第一行旋转后刚好与窗口上边沿齐平,需要计算第一行其实位置的Top坐标,由于旋转角度为-30,由正余弦可以得出第一行的高度应该是斜边(文字宽度,即上图中红线的长度)的一半(sin30°)
接下来确定行间距已经行中间距,首先可以确定行间距为150(height),为了达到如下图所示旋转后在同一直线上,见下图
即width = height * sqrt(3),如果计算结果width小于文字宽度加上文字间隔,则以文字宽度加文字间隔重新计算height
之后根据宽高可计算出一共需要多个TextBlock,双循环循环创建即可
为了使水印显示在其他控件上面,需要在xaml中最后位置创建Canvas,且Canvas的IsHitTestVisible必须为false(不响应鼠标事件)、透明度根据需要自行设置(如0.2)
最终显示效果见下图:
具体代码如下:
xaml:
<Window x:Class="WpfApplication1.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:WpfApplication1"
mc:Ignorable="d" FontSize="18"
SizeChanged="Window_SizeChanged"
Title="MainWindow" Height="400" Width="400">
<Grid>
<Button Height="32" Width="100" Content="btn" Click="Button_Click"/>
<!-- 一定要放到最后面,以确保水印覆盖所有其他控件 -->
<Canvas Name="canvas" Opacity="0.2" IsHitTestVisible="False"/>
</Grid>
</Window>
c#:
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
string watermark = "Watermark";
public MainWindow()
{
InitializeComponent();
}
protected override void OnContentRendered(EventArgs e)
{
base.OnContentRendered(e);
InitWatermark();
}
private void InitWatermark()
{
canvas.Children.Clear();
var formattedText = new FormattedText(
watermark,
CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
new Typeface(FontFamily, FontStyle, FontWeight, FontStretch),
FontSize,
Brushes.Black,
new NumberSubstitution(),
TextFormattingMode.Display);
var height = 150.0;
var width = height * Math.Sqrt(3);
if (width < formattedText.Width + 100)
{
width = formattedText.Width + 100;
height = width / Math.Sqrt(3);
}
var firstRowHeight = formattedText.Width / 2;
int colCount = (int)Math.Ceiling(ActualWidth / width);
int rowCount = (int)Math.Ceiling((ActualHeight - firstRowHeight) / height);
for (int i = 0; i < rowCount; ++i)
{
for (int j = 0; j < colCount; ++j)
{
TextBlock block = new TextBlock();
block.Text = watermark;
Canvas.SetTop(block, firstRowHeight + i * height);
Canvas.SetLeft(block, j * width);
RotateTransform transform = new RotateTransform(-30, 0, 0);
block.RenderTransform = transform;
canvas.Children.Add(block);
}
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
if (canvas.IsVisible)
canvas.Visibility = Visibility.Collapsed;
else
canvas.Visibility = Visibility.Visible;
}
private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
{
InitWatermark();
}
}
}