窗口移动--基类(BaseForm)
#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)的更多相关文章
- CS中窗体的基类(BaseForm)注意点
窗体基类最好新建一个窗体(BaseForm) 1.这样能够保证在VS中保证他的派生窗口也能够可视化. 2.如果基类直接是一个cs类文件,对于处理派生窗口就很复杂,比如按钮权限之类的操作; 如果直接继承 ...
- QWidget QMainWindow QDialog 三个基类的区别
Qt类是一个提供所需的像全局变量一样的大量不同的标识符的命名空间.通常情况下,你可以忽略这个类.QObject和一些其它类继承了它,所以在这个Qt命名空间中定义的所有标识符通常情况下都可以无限制的使用 ...
- WPF自定义窗口基类
WPF自定义窗口基类时,窗口基类只定义.cs文件,xaml文件不定义.继承自定义窗口的类xaml文件的根节点就不再是<Window>,而是自定义窗口类名(若自定义窗口与继承者不在同一个命名 ...
- WPF自学入门(九)WPF自定义窗口基类
今天简单记录一个知识点:WPF自定义窗口基类,常用winform的人知道,winform的窗体继承是很好用的,写一个基础窗体,直接在后台代码改写继承窗体名.但如果是WPF要继承窗体,我个人感觉没有理解 ...
- WPF 之 创建继承自Window 基类的自定义窗口基类
开发项目时,按照美工的设计其外边框(包括最大化,最小化,关闭等按钮)自然不同于 Window 自身的,但窗口的外边框及窗口移动.最小化等标题栏操作基本都是一样的.所以通过查看资料,可按如下方法创建继承 ...
- wpf之mvvm基类
当我们用MVVM设计模式的时候要实现INotifyPropertyChanged,每次都要实现这个接口比较麻烦,所以基类的作用就体现出来了.代码如下: 1 2 3 4 5 6 7 8 9 10 1 ...
- Thinkphp源码分析系列(七)–控制器基类
在mvc模式中,c代表的就是控制器,是是应用程序中处理用户交互的部分.通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据.控制器是沟通视图和模型的桥梁,他接受用户请求,并调用模型层去处理用户 ...
- WPF开发时光之痕日记本(二)—— MVVM基类
当我们用MVVM的时候要实现INotifyPropertyChanged,每次都要实现这个接口比较麻烦,所以基类的作用就体现出来了.代码如下: public class ViewModelBase : ...
- Duilib学习笔记《06》— 窗体基类WindowImpBase
在前面的例子中我们发现,窗口都是继承CWindowWnd.INotifyUI,然后重载相关函数去实现.显然,我们发现窗口的创建流程实际上都是差不多的,主要只是在OnCreate加载的配置文件不同等等… ...
随机推荐
- Android测试AsyncTask下载图片
package com.example.myact8_async; import org.apache.http.HttpEntity; import org.apache.http.HttpResp ...
- redis连接数问题
redis连接数查看 info client redis连接数满了,不会继续建立连接. 造成redis连接数满了原因有很多. 1.建立新连接不close()的话redis连接不会回归连接池. 显示所有 ...
- PAT乙级 1012. 数字分类 (20)
1012. 数字分类 (20) 时间限制 100 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 给定一系列正整数,请按要求对数字进 ...
- 关于Python中数据对象的可变性
先贴上Python官网中对数据模型描述的几段话.(在python官网的 语言参考>>数据模型 那部分) Every object has an identity, a type and a ...
- Cloudera CDH 、Impala本地通过Parcel安装配置详解
一.Parcel本地源与Package本地源的区别 本地通过Parcel安装过程与本地通过Package安装过程完全一致,不同的是两者的本地源的配置. 区别如下: Package本地源:软件包是.rp ...
- 【ruby】ruby基础知识
Install Ruby(安装) For windows you can download Ruby from http://rubyforge.org/frs/?group_id=167 for L ...
- GitHub Desktop for Win 安装不上
采用了ClickOnce部署方式,网速不给力,安装过程经常断线,要是有离线安装包就好了.
- springmvc简述
Spring Web MVC 是一种基于 Java 的实现了 Web MVC 设计模式的请求驱动类型的轻量级 Web 框架,即使用了 MVC 架构模式的思想,将 web 层进行职责解耦,基于请求驱动指 ...
- JavaScript复习笔记——字符串
String构造器可以使用new调用,也可以不使用,但是,这两种调用的结果也是完全不一样的.用new调用的时候,String作为构造器函数,创建字符串对象.不使用new的时候,String用作一个常规 ...
- UnicodeDecodeError: ‘ascii’ codec can’t decode...: ordinal not in range(128 问题解决
UnicodeDecodeError: ‘ascii’ codec can’t decode byte 0xe5 in position 108: ordinal not in range(128 原 ...