随笔-14  评论-8  文章-0  trackbacks-1

WPF不受禁用“拖拉时显示窗口内容”限制,拖动不规则窗体时显示内容

随笔开始之前,要感谢斯克迪亚(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的平滑。希望日后能改进。

本人水平十分有限,欢迎大家指导!~

0
0
(请您对文章做出评价)
« 上一篇:Winform中DataGridView单元格内容字体突出显示
» 下一篇:关于位图的结构,与Stride的含义
posted on 2008-11-04 18:53 萧延强 阅读(735) 评论(4)  编辑 收藏 网摘 所属分类: .NET

评论:
#1楼 2008-11-04 23:26 | 上不了岸的鱼{ttzhang}      
读过,留个脚印!
  回复  引用  查看    
#2楼 2008-11-11 23:56 | 兰博基尼[未注册用户]
你直接在Window的MouseLeftButtonDown事件里写this.DragMove()就好了嘛,整这么烦干什么!!
  回复  引用    
#3楼[楼主] 2008-11-12 20:56 | 萧延强      
@兰博基尼
呵呵,是啊,这只是突发奇想,我承认这种实现方法并不实际。

  回复  引用  查看    
#4楼 2009-01-06 15:13 | Jim Zhou[未注册用户]
Hi,

Every body, i am a WPF learner and developer in shanghai, i want to make some friends who are in charge of the field of WPF, every one who wantS to communicate with me on this fantastic technology please add me as your MSN contact.

thanks a lot in advance.

MSN:zhoujiguo1985@live.cn

Jim Zhou

  回复  引用