#region 窗口移动
private bool _isLeftButtonDown = false;

public const int HTCAPTION = 0x0002;

protected override void WndProc(ref System.Windows.Forms.Message m)
{
base.WndProc(ref m);

switch (m.Msg)
{
case WinApi.WM_LBUTTONDOWN:
case WinApi.WM_LBUTTONUP:

int lParam = m.LParam.ToInt32();
int x = lParam & 0xFFFF;
int y = (lParam >> 16);

switch (m.Msg)
{
case WinApi.WM_LBUTTONDOWN:
if (x < Width - 20 || y > 20)
{
this._isLeftButtonDown = true;
WinApi.ReleaseCapture();
WinApi.SendMessage(this.Handle, WinApi.WM_SYSCOMMAND, WinApi.SC_MOVE + HTCAPTION, 0);
}
break;
case WinApi.WM_LBUTTONUP:
if (this._isLeftButtonDown)
{
this._isLeftButtonDown = false;
if (x < Width - 20 || y > 20)
{
WinApi.ReleaseCapture();
SaveLocation();
}
}
break;
}
break;
}
}

/// <summary>
/// 保存窗口位置.
/// </summary>
private void SaveLocation()
{
if (this._isLeftButtonDown)
{
SavedLocation = this.Location;
}
}

/// <summary>
/// 引发 <see cref="E:System.Windows.Forms.Control.LocationChanged"/> 事件。
/// </summary>
/// <param name="e">包含事件数据的 <see cref="T:System.EventArgs"/>。</param>
protected override void OnLocationChanged(EventArgs e)
{
const int DX = 25;
const int DY = 25;

Point location = this.Location;
Rectangle rect = Screen.PrimaryScreen.WorkingArea;
if (location.X + this.Width < DX)
{
location.X = DX - this.Width;
}
else if (location.X + DX > rect.Width)
{
location.X = rect.Width - DX;
}
if (location.Y + this.Height < DY)
{
location.Y = DY - this.Height;
}
else if (location.Y + DY > rect.Height)
{
location.Y = rect.Height - DY;
}

if (location != this.Location)
{
this.Location = location;
}

SaveLocation();
}

private const string SAVED_LOCATION_REGSTER_KEY = @"Software\AlarmClient\SavedLocation";

/// <summary>
/// 保存路径
/// </summary>
private Point SavedLocation
{
get
{
int x, y;
try
{
RegistryKey key = Registry.CurrentUser.OpenSubKey(SAVED_LOCATION_REGSTER_KEY);
if (key != null)
{
x = (int)key.GetValue("X", 0);
y = (int)key.GetValue("Y", 0);

return new Point(x, y);
}
}
catch (Exception ex)
{
TestLog.DoLog(ex);
}

Rectangle rect = Screen.PrimaryScreen.WorkingArea;
x = rect.Width - this.Width;
y = rect.Height - this.Height;
return new Point(x, y);
}
set
{
try
{
RegistryKey key = Registry.CurrentUser.CreateSubKey(SAVED_LOCATION_REGSTER_KEY);
key.SetValue("X", value.X);
key.SetValue("Y", value.Y);
}
catch (Exception ex)
{
TestLog.DoLog(ex);
}
}
}

/// <summary>
/// 引发 <see cref="E:System.Windows.Forms.Form.Load"/> 事件。
/// </summary>
/// <param name="e">包含事件数据的 <see cref="T:System.EventArgs"/>。</param>
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
//if (this._activeWindow != IntPtr.Zero)
//{
// WinApi.SetActiveWindow(this._activeWindow);
//}
//this.Controls.EachChildFirst((Control c) =>
//{
// LabelX label = c as LabelX;
// if (label == null) return false;

// label.MouseDown += new MouseEventHandler(label_MouseDown);
// label.MouseMove += new MouseEventHandler(label_MouseMove);

// return true;
//});

// 让窗口上的每一个 LabelX 都把鼠标按下和移动的消息发送给本窗口
MouseEventHandler down = new MouseEventHandler(label_MouseDown);
MouseEventHandler move = new MouseEventHandler(label_MouseMove);

// 遍历窗口中的 LabelX
this.Controls.EachChildFirst((Control c) =>
{
LabelX label = c as LabelX;
if (label == null) return false;

label.MouseDown += down;
label.MouseMove += move;

return true;
});

// 加载初始位置
this.Location = this.SavedLocation;
// 设置窗口为一个圆角的矩形
//this.Region = CreateRegion();
}

/// <summary>
/// 给窗口添加圆角区域
/// </summary>
/// <returns></returns>
private Region CreateRegion()
{
const int RX = 15;
const int RY = 15;

//Region region = this.Region;
System.Drawing.Drawing2D.GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath();
path.FillMode = System.Drawing.Drawing2D.FillMode.Winding;
path.AddRectangle(new Rectangle(1, RY, this.Width - 2, this.Height - (RY + RY)));
path.AddRectangle(new Rectangle(RX, 1, this.Width - (RX + RX + 2), this.Height - 2));
path.AddEllipse(1, 0, RX + RX, RY + RY);
path.AddEllipse(1, this.Height - (RY + RY + 2), RX + RX, RY + RY);
path.AddEllipse(this.Width - (RX + RX + 2), 0, RX + RX, RY + RY);
path.AddEllipse(this.Width - (RX + RX + 2), this.Height - (RY + RY + 2), RX + RX, RY + RY);

return new Region(path);
}

/// <summary>
/// 鼠标在 LabelX 上移动时,将消息发送给窗口
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void label_MouseMove(object sender, MouseEventArgs e)
{
WinApi.PostMessage(this.Handle, WinApi.WM_MOUSEMOVE, 1, e.X | (e.Y << 16));
}

/// <summary>
/// 鼠标在 LabelX 上按下时,将消息发送给窗口
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void label_MouseDown(object sender, MouseEventArgs e)
{
WinApi.PostMessage(this.Handle, WinApi.WM_LBUTTONDOWN, 1, e.X | (e.Y << 16));
}
#endregion

窗口移动--基类(BaseForm)的更多相关文章

  1. CS中窗体的基类(BaseForm)注意点

    窗体基类最好新建一个窗体(BaseForm) 1.这样能够保证在VS中保证他的派生窗口也能够可视化. 2.如果基类直接是一个cs类文件,对于处理派生窗口就很复杂,比如按钮权限之类的操作; 如果直接继承 ...

  2. QWidget QMainWindow QDialog 三个基类的区别

    Qt类是一个提供所需的像全局变量一样的大量不同的标识符的命名空间.通常情况下,你可以忽略这个类.QObject和一些其它类继承了它,所以在这个Qt命名空间中定义的所有标识符通常情况下都可以无限制的使用 ...

  3. WPF自定义窗口基类

    WPF自定义窗口基类时,窗口基类只定义.cs文件,xaml文件不定义.继承自定义窗口的类xaml文件的根节点就不再是<Window>,而是自定义窗口类名(若自定义窗口与继承者不在同一个命名 ...

  4. WPF自学入门(九)WPF自定义窗口基类

    今天简单记录一个知识点:WPF自定义窗口基类,常用winform的人知道,winform的窗体继承是很好用的,写一个基础窗体,直接在后台代码改写继承窗体名.但如果是WPF要继承窗体,我个人感觉没有理解 ...

  5. WPF 之 创建继承自Window 基类的自定义窗口基类

    开发项目时,按照美工的设计其外边框(包括最大化,最小化,关闭等按钮)自然不同于 Window 自身的,但窗口的外边框及窗口移动.最小化等标题栏操作基本都是一样的.所以通过查看资料,可按如下方法创建继承 ...

  6. wpf之mvvm基类

    当我们用MVVM设计模式的时候要实现INotifyPropertyChanged,每次都要实现这个接口比较麻烦,所以基类的作用就体现出来了.代码如下:   1 2 3 4 5 6 7 8 9 10 1 ...

  7. Thinkphp源码分析系列(七)–控制器基类

    在mvc模式中,c代表的就是控制器,是是应用程序中处理用户交互的部分.通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据.控制器是沟通视图和模型的桥梁,他接受用户请求,并调用模型层去处理用户 ...

  8. WPF开发时光之痕日记本(二)—— MVVM基类

    当我们用MVVM的时候要实现INotifyPropertyChanged,每次都要实现这个接口比较麻烦,所以基类的作用就体现出来了.代码如下: public class ViewModelBase : ...

  9. Duilib学习笔记《06》— 窗体基类WindowImpBase

    在前面的例子中我们发现,窗口都是继承CWindowWnd.INotifyUI,然后重载相关函数去实现.显然,我们发现窗口的创建流程实际上都是差不多的,主要只是在OnCreate加载的配置文件不同等等… ...

随机推荐

  1. struts2拦截器の简单实现(日语系统,请忽略乱码,重在实现)

    1.创建类实现interceptor接口或者继承abstractinter~~~类 package com.mi.intercepter; import java.util.Date; import ...

  2. Power Gating的设计(模块)

    Switching Fabric的设计: 三种架构:P沟道的switch vdd(header switch),N沟道的switch vss(footer switch),两个switch. 但是如果 ...

  3. 文本挖掘之特征选择(python 实现)

    机器学习算法的空间.时间复杂度依赖于输入数据的规模,维度规约(Dimensionality reduction)则是一种被用于降低输入数据维数的方法.维度规约可以分为两类: 特征选择(feature ...

  4. 【py网页】urllib.urlretrieve远程下载

    下面我们再来看看 urllib 模块提供的 urlretrieve() 函数.urlretrieve() 方法直接将远程数据下载到本地. 1 >>> help(urllib.urlr ...

  5. jquery表单重置另一种方法

    页面中按钮为<a>标签时,点击取消按钮,表单内容重置,需要给form表单id="form": <a class="demo_one1" onc ...

  6. 设置Sql Agent运行Job时的执行账户

    相信使用过Sql Server的人都应该知道,使用Sql Agent可以建立一些自动化Job来帮我们周期性地执行一些任务,其中执行SSIS包就是其中一个任务.而在SSIS包中有时候会去做读取文件等一些 ...

  7. Openstack的的nova list命令

    nova list用于在shell交互模式下查看当前用户存在的实例数目,但是这里仍然要注意的地方: 没有参数的nova list [root@node-5 newstest-master]# nova ...

  8. android 学习随笔十九(对话框、样式、主题、国际化 )

    1.对话框 package com.itheima.dialog; import android.os.Bundle; import android.app.Activity; import andr ...

  9. Asp.Net Web Api 2 实现多文件打包并下载文件示例源码_转

    一篇关于Asp.Net Web Api下载文件的文章,之前我也写过类似的文章,请见:<ASP.NET(C#) Web Api通过文件流下载文件到本地实例>本文以这篇文章的基础,提供了Byt ...

  10. JavaEE基础(二十三)/递归

    1.File类递归练习(统计该文件夹大小) 需求:1,从键盘接收一个文件夹路径,统计该文件夹大小 2.File类递归练习(删除该文件夹) 需求:2,从键盘接收一个文件夹路径,删除该文件夹 3.File ...