WPF实用指南一:在WPF窗体的边框中添加搜索框和按钮

来源:互联网 发布:网络黑彩平台 编辑:程序博客网 时间:2024/05/17 04:21

在边框中加入一些元素,在应用程序的界面设计中,已经开始流行起来。特别是在浏览器(Crome,IE,Firefox,Opera)中都有应用。

在WPF中,如何实现这种效果呢?这正是我们今天需要探讨的问题。先看看实现效果

图一:实现之前的效果                                                                                                                                        

图二:实现之后的效果


这样的效果依赖于操作系统Aero风格的支持,也就是说在Windows Vista,Windows 7 或者更高版本中可以获得此中效果。如果要在Windows XP中实现,那么您就需要另外想办法了。


好了。我们来看看是怎么实现的吧。

首先:在MainWindow窗体的xaml代码中加入以下代码,这一步没有什么特别的,和平常做的一样。

<Grid.RowDefinitions>            <RowDefinition Height="30" />            <RowDefinition Height="*" />        </Grid.RowDefinitions>        <StackPanel Orientation="Horizontal"  HorizontalAlignment="Right" VerticalAlignment="Center">             <TextBox Width="150"  VerticalAlignment="Center" Text="输入关键词" />             <Button Content="查找" VerticalAlignment="Center" Margin="5,0,5,0" />        </StackPanel>         <Grid Background="White" Grid.Row="1">            <Label Content="Hello World"></Label>        </Grid>

然后:为窗体设定背景。这一步比较重要,要实现上面图片的效果,需要将其设定为Transparent

Background="Transparent"
好了,到此xaml的编辑已经结束了,接下来看看后台代码是如何实现的。

如果你创建的是WPF的应用程序,只需要添加System.Drawing引用即可。

using System;using System.Windows;using System.Windows.Media;using System.Windows.Interop;using System.Runtime.InteropServices;
要实现上述效果,需要使用一个Win32函数DwmExtendFrameIntoClientArea这个函数需要个MARGINS的结构体。代码定义如下
[StructLayout(LayoutKind.Sequential)]public struct MARGINS{  public int cxLeftWidth;  public int cxRightWidth;  public int cxTopHeight;  public int cxBottomHeight;}[DllImport("dwmapi.dll")]public static extern int DwmExtendFrameIntoClientArea(  IntPtr hWnd, ref MARGINS pMarInset);
Windows API使用句柄控制着窗体,所以在窗体的Load事件中,第一步我们需要获取窗体的句柄,使用.NET类库提供的WindowInteropHelper类来获取。
然后从句柄中获得HwndSource,它用来宿主WPF的内容。接下来创建MARGINS结构体实例用来存储相关设置。最后调用API。看看代码实现:
       void OnLoaded(object sender, RoutedEventArgs e)        {            IntPtr windowHandle = new WindowInteropHelper(this).Handle;             HwndSource window = HwndSource.FromHwnd(windowHandle);             window.CompositionTarget.BackgroundColor = Colors.Transparent;             MARGINS margins = new MARGINS();            margins.cxTopHeight = 30;             margins = AdjustForDPISettings(margins, windowHandle);             int result = DwmExtendFrameIntoClientArea(windowHandle, ref margins);        }
private MARGINS AdjustForDPISettings(MARGINS input, IntPtr hWnd)        {            MARGINS adjusted = new MARGINS();                          var graphics = System.Drawing.Graphics.FromHwnd(hWnd);            float dpiRatioX = graphics.DpiX / 96;            float dpiRatioY = graphics.DpiY / 96;            adjusted.cxLeftWidth = (int)(input.cxLeftWidth * dpiRatioX);            adjusted.cxRightWidth = (int)(input.cxRightWidth * dpiRatioX);            adjusted.cxTopHeight = (int)(input.cxTopHeight * dpiRatioY);            adjusted.cxBottomHeight = (int)(input.cxBottomHeight * dpiRatioY);            return adjusted;        }
到此,整个效果就都实现了。完整代码如下:

using System;using System.Windows;using System.Windows.Media;using System.Windows.Interop;using System.Runtime.InteropServices;namespace WpfTutorial{    /// <summary>    /// MainWindow.xaml 的交互逻辑    /// </summary>    public partial class MainWindow : Window    {        public MainWindow()        {            InitializeComponent();            this.Loaded += OnLoaded;        }        void OnLoaded(object sender, RoutedEventArgs e)        {            IntPtr windowHandle = new WindowInteropHelper(this).Handle;             HwndSource window = HwndSource.FromHwnd(windowHandle);             window.CompositionTarget.BackgroundColor = Colors.Transparent;             MARGINS margins = new MARGINS();            margins.cxTopHeight = 30;             margins = AdjustForDPISettings(margins, windowHandle);             int result = DwmExtendFrameIntoClientArea(windowHandle, ref margins);        }        private MARGINS AdjustForDPISettings(MARGINS input, IntPtr hWnd)        {            MARGINS adjusted = new MARGINS();                          var graphics = System.Drawing.Graphics.FromHwnd(hWnd);            float dpiRatioX = graphics.DpiX / 96;            float dpiRatioY = graphics.DpiY / 96;            adjusted.cxLeftWidth = (int)(input.cxLeftWidth * dpiRatioX);            adjusted.cxRightWidth = (int)(input.cxRightWidth * dpiRatioX);            adjusted.cxTopHeight = (int)(input.cxTopHeight * dpiRatioY);            adjusted.cxBottomHeight = (int)(input.cxBottomHeight * dpiRatioY);            return adjusted;        }        [StructLayout(LayoutKind.Sequential)]        public struct MARGINS        {            public int cxLeftWidth;            public int cxRightWidth;            public int cxTopHeight;            public int cxBottomHeight;        }        [DllImport("dwmapi.dll")]        public static extern int DwmExtendFrameIntoClientArea(          IntPtr hWnd, ref MARGINS pMarInset);    }}