[原创]用C#创建可拖动窗体

原创 2004年09月14日 21:36:00

用C#创建可拖动窗体

原著:lover_P


    所谓“可拖动窗体”就是无需拖动标题栏就可以拖动的窗体,这在一个没有标题栏的窗体上是一种非常有用的技术。关于这一方面的技巧,网上已经有很多介绍,但都不是很详尽,有些实现也不够简洁。最主要的,这些介绍大多是大片大片的源代码,很少讲解;初学者学期来恐怕要费些力气(我在学习这个技巧的时候就很痛苦)。在这里,我对这个技巧进行了一个详细的讲解,相信各位初学者朋友可以学会如何制作可拖动窗体。

    (注:本文期望的读者是那些有一定用C#开发Windows程序基础但暂时还不会制作可拖动窗体的朋友。)

    首先,我们来复习一下一个Windows窗体的组成。请看这张图:


图1  Windows窗体构成

点击查看原图


    这是一个形式化的标准Windows窗体。首先,窗体的顶部是一个标题栏,其余的部分是窗体的主体,包围在窗体主体外围的是一个边框,边框内不就是我们放置控件或绘制图形的用户区。

    图中还标明了各种窗体构造元素的尺寸的获得方法。对于用户区,System.Windows.Forms.Form提供了实例属性ClientSize,相信大家已经很熟悉了。而要想活棋一般性的窗体构造元素(如标题栏、边框等)的尺寸,我们可以使用.NET类库中提供的一个类:System.Windows.Forms.SystemInformation,这个类提供了一些静态属性如表示标题栏高度的CaptionHeight。有关SystemInformation类的信息可以在.NET SDK文档目录“.NET Framework SDK -> 参考 -> 类库 -> System.Windows.Forms -> SystemInformation 类”处找到(注:这里的超链接只在您安装了.NET Framework 1.1简体中文版并且安装了配套文档时才有效)。这是一个很有用的类,希望大家能够记住它(可能您早就知道了,可我是才知道的-_-汗~~)。

    接下来,我们来看看如何在在用户区拖动鼠标时移动窗体。请看下面这张图:


图2  窗体的移动

点击查看原图


    我们来观察鼠标在窗体内的位置和窗体的移动,很容易可以发现:在窗体被拖动的过程中,鼠标在窗体内的相对位置是始终不变的!那么,我们只要检测到鼠标在屏幕中的移动并修改窗体的位置就可以达到拖动窗体的目的!

    我们知道,在鼠标消息/事件处理中,只能得到鼠标相对于窗体的位置。那么,如何知道鼠标在屏幕中的位置呢?这里又要提到一个类:System.Windows.Forms.Control类。也许你会很吃惊:这不是所有控件的基类么?呵呵~是这样di。不过,尽管是这样,Control类却没有像其他广泛使用的基类那样被声明为抽象类,而且它提供了一个静态属性:MousePosition,通过这个属性可以得到鼠标相对于屏幕的位置。有关Control类的信息可以在.NET Framework文档目录“.NET Framework SDK -> 参考 -> 类库 -> System.Windows.Forms -> Control 类”处找到(注:这里的超链接只在您安装了.NET Framework 1.1简体中文版并且安装了配套文档时才有效)。

    知道了如何获取这些信息之后,制作移动窗体实际上就成了一个很简单的问题了。基本过程是这样的:首先,在鼠标(左键或一个你喜欢的键)按下时,记录鼠标位置;由于在移动的过程中,鼠标的屏幕坐标发生变化但窗体相对坐标不变,我们可以推算出窗体位置的变化为(假设mousePosition具有System.Drawing.Point类型,表示鼠标在窗体中的相对坐标):

// 示例代码1
Form.Top = Control.MousePosition.Y - mousePosition.Y;
Form.Left = Control.MousePosition.X - mousePosition.X;

    这样还不行,因为我们的mousePosition表示的是鼠标在窗体用户区内的相对坐标,但在移动窗体的时候还要考虑窗体标题栏和边框的尺寸。在上面的基础上,我们将代码修正为:

// 示例代码2
Form.Top = Control.MousePosition.Y - mousePosition.Y
           - SystemInformation.FrameBorderSize.Height - SystemInformation.CaptionHeight;
Form.Left = Control.MousePosition.Y - mousePosition.Y
            - SystemInformation.FrameBorderSize.Width;

    也就是说,在高度上(纵坐标)要减去标题栏的高度和边框的高度,而在宽度上(横坐标)要减去边框的宽度。然而,当制作一个既没有标题栏也没有边框的可拖动窗体时,使用“示例代码1”所示的代码就可以了。

    上面的代码只是一个示范性代码。具体的操作如下:

    首先,为窗体添加一个私有域:

private System.Drawing.Point mousePoint;

    然后,为窗体添加鼠标按下事件处理方法(我这里是MainForm_MouseDown,别忘了将该方法链接到MainForm.MouseDown事件,这不用多说了吧?):

private void MainForm_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e) {
    if(e.Button == MouseButtons.Left) {
        this.mousePosition.X = e.X;
        this.mousePosition.Y = e.Y;
    }
}

    在这里注意对鼠标按键进行筛选。

    接下来,为窗体添加鼠标移动事件处理方法(我这里是MainForm_MouseMove):

private void MainForm_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) {
    if(e.Button == MouseButtons.Left) {
        Form.Top = Control.MousePosition.Y - mousePosition.Y
                   - SystemInformation.FrameBorderSize.Height - SystemInformation.CaptionHeight;
        Form.Left = Control.MousePosition.Y - mousePosition.Y
                    - SystemInformation.FrameBorderSize.Width;
    }
}

    这里,如果窗体没有标题栏,可以去掉“-SystemInformation.CaptionHeight”;如果窗体没有边框,还可以去掉“-SystemInformation.FrameBorderSize.Height”和“-SystemInformation.FrameBorderSize.Width”。

    现在,您是不是已经很清楚地明白如何用C#制作可拖动窗口了?祝贺您!最后,送您一个小礼物——桌面时钟。很简洁、很有意思哦~~~

    另外赠送小技巧三则:

  • 如何制作不规则窗体

    这个技巧我掌握的还不是很丰富,现在介绍一种最简单的方法——通过设置窗体的Region属性。首先,声明一个System.Drawing.Drawing2D.GraphicsPath变量,在这个变量中添加您期望作为窗体轮廓的形状组合;之后,从这个变量生成一个System.Drawing.Region实例,并赋给窗体的Region属性即可。如:

GraphicsPath gp = new GraphicsPath();
gp.AddEllipse(0, 0, 120, 120);
Region r = new Region(gp);
this.Region = r;

    将上述代码添加到窗体的构造函数中,我们就能够得到一个自定义的窗体了,这个窗体是一个直径为120像素的圆形(也是我的时钟的外观哦)。

  • 如何生成没有边框的窗体

    将窗体的FormBorderStyle设置为None即可。这很简单事么?那么

  • 如何生成有边框但没有标题栏的窗体

    首先将窗体的ControlBox属性设置为false,也就是不要控制按钮(窗体图标、最大最小化按钮和关闭按钮)。按说这时就不应该有标题栏了,但我们还能看到它很烦人地待在那里,因此,我们要把窗体的Text属性设置为空(注意是String.Empty,而不是null)。

C# Winform 让整个窗口都可以拖动

解决方法:[DllImport("user32.dll")]publicstaticexternbool ReleaseCapture();[DllImport("user32.dll")]publi...
  • esunshine1985
  • esunshine1985
  • 2011年05月10日 13:23
  • 1240

C#实现无边框窗体拖动

1 2
  • CLeopard
  • CLeopard
  • 2014年08月28日 17:03
  • 4075

C#点击窗口任意位置可拖拽

直接上代码 private Point offset; private void Form1_MouseDown(object sender, MouseEventArgs e) { ...
  • ErErFei
  • ErErFei
  • 2016年02月03日 13:43
  • 2345

C# winform实现鼠标左键拖动窗体

public partial class Form1 : Form     {         public Form1()         {             InitializeC...
  • haoxiang110
  • haoxiang110
  • 2015年01月26日 17:21
  • 5249

c# 当窗体设置成无边框后,如何实现拖动效果,简洁实用

在做一个类似QQ的消息提醒功能,就是弹出一个消息提示框的那种效果,需要将 将FormBorderStyle设置为none,但是窗体无法进行拖动。 解决的办法是: 1.在窗体的.cs文...
  • zy_dreamer
  • zy_dreamer
  • 2014年03月05日 09:57
  • 1759

用C#创建可拖动窗体

作者:lover_P所谓“可拖动窗体”就是无需拖动标题栏就可以拖动的窗体,这在一个没有标题栏的窗体上是一种非常有用的技术。关于这一方面的技巧,网上已经有很多介绍,但都不是很详尽,有些实现也不够简洁。最...
  • sunwestern
  • sunwestern
  • 2004年11月12日 14:33
  • 1169

用C#创建可拖动窗体

所谓“可拖动窗体”就是无需拖动标题栏就可以拖动的窗体,这在一个没有标题栏的窗体上是一种非常有用的技术。关于这一方面的技巧,网上已经有很多介绍,但都不是很详尽,有些实现也不够简洁。最主要的,这些介绍大多...
  • zx13525079024
  • zx13525079024
  • 2009年05月07日 16:58
  • 626

c# 实现用鼠标拖动没有标题栏的窗口(窗体的任何部分都可实现拖动效果)

上面形式的窗体,实现窗体的任何部分都可
  • soft_123456
  • soft_123456
  • 2014年11月04日 10:05
  • 1539

WinForm 无边框窗体 拖动工作区移动窗体

今天朋友问我这个问题 在网上找了一下, 果然有,但是 好像文章的bolg 关了,在百度快照里找到的 ,记录下, 自己以后可能也会用的到,免得到时候蛋疼方案1 : 通过重载消息处理实现。重写窗口过程...
  • li_1042237864
  • li_1042237864
  • 2010年08月23日 18:10
  • 8293

Winform窗口去边框实现可以移动

Windows自带的边框很影响我们个性化定制窗口UI的美观程序。 首选选择窗口,属性里的FormBorderStyle设置为None。 边框去掉之后 会发现窗口无法最大最小化和移动。 1 在标题...
  • helloKingshan
  • helloKingshan
  • 2017年06月02日 13:23
  • 1235
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:[原创]用C#创建可拖动窗体
举报原因:
原因补充:

(最多只允许输入30个字)