**
原理:
**
以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;elsecanvas.Visibility = Visibility.Visible;}private void Window_SizeChanged(object sender, SizeChangedEventArgs e){InitWatermark();}}
}