Bookmark: HemiDemi MyShare Baidu Google Bookmarks Yahoo! My Web Del.icio.us Digg technorati furl Bookmark to:YouPush Bookmark to:你推我報

随笔开始之前,要感谢斯克迪亚(http://www.cnblogs.com/SkyD/)他本人热心的帮助,他的文章对我有一定启发性。同时推荐大家去看看CodeProject上的http://www.codeproject.com/KB/WPF/WPFDiagramDesigner_Part1.aspx文章,拖放办法是从那里的copy过来的,WPFDiagramDesigner系列对很多初学者应该是个很好的代码教材,感谢其作者。

 

I. 简单的开始

刚开始学习WPF几天,发现实现不规则窗体的拖放非常简单。网上普遍的办法就是

不规则窗体的显示办法:

AllowsTransparency="True"
WindowStyle="None"
Background="Transparent"

再给window里添加MouserLeftButtonDown事件处理函数,函数里就加一个DragMove函数就完成了。

 

II. 妄想

由于平常为了节省系统资源,总是禁用“拖拉时显示窗口内容”这系统选项。使得拖动窗体时出现一个原窗体大小的矩形虚框。某次拖放Yahoo的日历Widget却发现没有这虚框出现,不受禁用“拖拉时显示窗口内容”的限制。

拖放时出现虚框

Widget不会出现这种情况

在winform中实现这个并不是很难,既然现在学习WPF,就在WPF上实现吧。

Window1.xaml内容

<Window x:Class="Todo.Window1"
    xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
    Title
="Window1" Height="300" Width="300"
    AllowsTransparency
="True"
    WindowStyle
="None"
    Background
="Transparent"
    Loaded
="Window_Loaded">
    
<Window.Resources>
        
<ControlTemplate x:Key="ThumbTemplate" TargetType="Thumb">
            
<Rectangle Fill="Transparent"/>
        
</ControlTemplate>
        
<ControlTemplate x:Key="DragWindowTemplate" TargetType="ContentControl">
            
<Grid>
                
<Thumb Template="{StaticResource ThumbTemplate}" DragDelta="Thumb_DragDelta"/>
                
<ContentPresenter Content="{TemplateBinding ContentControl.Content}"/>
            
</Grid>
        
</ControlTemplate>
    
</Window.Resources>
    
    
<Canvas>
        
<ContentControl Height="300" Width="300" Template="{StaticResource DragWindowTemplate}">
             
<Rectangle Fill="Black" Height="300" Width="300"  RadiusX="20" RadiusY="20" Opacity="0.55" IsHitTestVisible="False" />
        
</ContentControl>
        
<Label Foreground="White" Name="position"  BorderThickness="0" HorizontalContentAlignment="Center">不受禁用“拖拉时显示窗口内容”限制</Label>
    
</Canvas>
</Window>

 

Window1.xaml.cs内容

public partial class Window1 : Window
{
    [DllImport(
"User32.dll", SetLastError = true)]
    
internal static extern int SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int Flags);

    
/// <summary>
    
/// 移动窗体的API
    
/// </summary>
    
/// <param name="hWnd">窗体句柄</param>
    
/// <param name="X">X坐标</param>
    
/// <param name="Y">Y坐标</param>
    
/// <param name="nWidth">窗体宽</param>
    
/// <param name="nHeight">窗体高</param>
    
/// <param name="bRepaint">是否重绘</param>
    
/// <returns></returns>
    [DllImport("User32.dll", SetLastError = true)]
    
internal static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);

    
private int originalTop;    // 记录窗体原来的位置
    private int originalLeft;   // 记录窗体原来的位置
    private WindowInteropHelper wIH;    // WPF与Win32代码间互操作的类,这里用来获取窗体句柄

    
public Window1()
    {
        InitializeComponent();
    }

    
private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        originalTop 
= (int)this.Top;
        originalLeft 
= (int)this.Left;
        wIH 
= new WindowInteropHelper(this);    //初始化wIH
        MoveWindow(wIH.Handle, originalTop, originalLeft, (int)this.Width, (int)this.Height, false);
    }

    
private void Thumb_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
    {
        originalTop 
+= (int)e.HorizontalChange;
        originalLeft 
+= (int)e.VerticalChange;
        MoveWindow(wIH.Handle, originalTop, originalLeft, (
int)this.Width, (int)this.Height, false);
    }
}

 

III. 总结:还是不够好!

效果是实现了,但还是不完美,还存在几个问题:

1. 首先是在Thumb_DragDelta事件函数里直接使用窗体this.Top += e.HorizontalChange这种方式来控制窗体在屏幕的位置,会出大问题!因为只要这样做,e.HorizontalChange就会立即根据新的Top进行改变,进而使得Top的值以难以想象的加速度提升(this.Left也是如此),因为这里采用了的Win32 API来进行窗体移动(感觉有点不WPF了-_-b)。

2. 就是用了API之后,第一次点击窗体时会出现一次闪动,之后就不会再出现。虽然不知道是什么原因(希望高手能告诉我),但经过实践证明,在loaded事件实现一次API,就会消除这种情况。

3. <Rectangle>等与<Image>拖放时绘制速度貌似有差异,希望是错觉,总体拖放感觉还是没有widget的平滑。希望日后能改进。

 

引用來源:http://www.cnblogs.com/jinkeungsiu/archive/2008/11/04/1326585.html


Posted by romeogi1023 at 痞客邦 PIXNET Comments(0) Trackback(0) Hits(13)