(转)sl简单自定义win窗体控件
sl简单自定义win窗体控件








就开始给窗体添加功能。
在这为了简化步骤,就以父容器为Canvas考虑,由于他是绝对布局的所以实现移动较方便,大家如果要是控件的使用范围些 可以去试试用平移变换实现窗体移动。
首先 还是先明确下一些基础点,由于 窗体的外观是在模板里定义的,所以于窗体有关的部件我们不能直接访问,不过访问的方法有好几种,我在这介绍两种。
1.我们可以在那些模板里的部件加上Loaded事件,再在这个事件的处理函数里把,这个部件的引用保存下来。
2.是重写OnApplyTemplate方法在这个方法里调用GetTemplateChild获得部件引用。
我这是利用第二种方法,好现在开始实现功能
- public override void OnApplyTemplate()
- {
- base.OnApplyTemplate();
- TitleC = GetTemplateChild("Win_Title") as TextBlock;//是呈现窗体的TextBlock
- BackImage = GetTemplateChild("BackRect") as Rectangle;//是背景矩形
- TitleC.Text = Title;//Title是窗体标题的依赖属性
- //窗体顶部矩形 用于移动矩形
- (GetTemplateChild("Win_Move") as Rectangle).MouseLeftButtonDown += new MouseButtonEventHandler(WInControl_MouseLeftButtonDown);
- //窗体四边的矩形,还记得吗上篇文章 我给他设置Cursor属性这就是为了实现 鼠标移动到窗体边缘的变化 主要要把那四个矩形的背景不能透明,即使0.05也行 就不能透明
- (GetTemplateChild("Side_Right") as Rectangle).MouseLeftButtonDown+=new MouseButtonEventHandler(WInControl_MouseLeftButtonDown);
- (GetTemplateChild("Side_Left") as Rectangle).MouseLeftButtonDown += new MouseButtonEventHandler(WInControl_MouseLeftButtonDown);
- (GetTemplateChild("Side_Top") as Rectangle).MouseLeftButtonDown += new MouseButtonEventHandler(WInControl_MouseLeftButtonDown);
- (GetTemplateChild("Side_Botton") as Rectangle).MouseLeftButtonDown += new MouseButtonEventHandler(WInControl_MouseLeftButtonDown);
- //就是窗体上的那三个按钮
- (GetTemplateChild("MinB") as Button).Click +=new RoutedEventHandler(WInControl_Click);
- (GetTemplateChild("MaxB") as Button).Click +=new RoutedEventHandler(WInControl_Click);
- (GetTemplateChild("CloseB") as Button).Click += new RoutedEventHandler(WInControl_Click);
- }
这里就是移动窗体和尺寸拉伸的 代码
protected void WInControl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
- {
- Rectangle rect = sender as Rectangle;
- rect.MouseMove += new MouseEventHandler(rect_MouseMove);
- rect.MouseLeftButtonUp += new MouseButtonEventHandler(rect_MouseLeftButtonUp);
- rect.CaptureMouse();
- LastPoint = e.GetPosition(Owner);
- // 这里就注册鼠标移动事件 和 弹起事件
- }
- void rect_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
- {
- Rectangle rect = sender as Rectangle;
- rect.MouseMove -= rect_MouseMove;
- rect.MouseLeftButtonUp -= rect_MouseLeftButtonUp;
- rect.ReleaseMouseCapture();
- //这里也没什么好说
- }
- protected void rect_MouseMove(object sender, MouseEventArgs e)
- {
- Rectangle rect = sender as Rectangle;
- Point p = e.GetPosition(Owner);
- //这里按照Name判断执行什么操作
- switch (rect.Name)
- {
- case "Win_Move": MoveWin(p); break;
- case "Side_Right": ChangeRightWin(p); break;
- case "Side_Left": ChangeLeftWin(p); break;
- case "Side_Top": ChangeTopWin(p); break;
- case "Side_Botton": ChangeBottomWIn(p); break;
- }
- }
- //而这里是移动的主要逻辑 如果大家做过拖曳控件的功能就非常简单
- public void MoveWin(Point e)
- { //LastPoint在鼠标点击事件里赋值 记录了上一个事件里鼠标的位置
- // 而这用这事鼠标的位置减去上一时刻的鼠标位置 然后再移动窗体这个差值
- //这两个判断语句是防止窗体整个移界面
- Point D_point = new Point(e.X - LastPoint.X, e.Y - LastPoint.Y);
- if (!(Canvas.GetTop(this) <= 0 && D_point.Y <= 0))
- {
- if (!(Canvas.GetTop(this) > Owner.ActualHeight && D_point.Y >= 0))
- {
- Canvas.SetLeft(this, Canvas.GetLeft(this) + D_point.X);
- Canvas.SetTop(this, Canvas.GetTop(this) + D_point.Y);
- //再保存位置
- LastPoint = e;
- }
- }
- }
- //下面四个方法是改变窗体大小的
- void ChangeBottomWIn(Point e)
- { //这个是底边拉伸窗体 也很好理解 就是计算出 当鼠标点下 后每次Move的差值 在把这个差值加到窗体高度上
- double M_mun = e.Y - Canvas.GetTop(this) - this.Height;
- if (this.Height >= 100 || M_mun > 0)
- this.Height += M_mun;
- }
- void ChangeTopWin(Point e)
- { //这是顶部拉伸的代码 但这不能简单把移动差值加到 控件高度上
- //这样会造成向上拉伸 向下变长的现象 我们必须先向上移动控件 这个差值再加
- double M_mun = Canvas.GetTop(this) - e.Y;
- if(this.Height >= 100 || M_mun >0)
- this.Height += M_mun;
- LastPoint = e;
- Canvas.SetTop(this, LastPoint.Y);
- }
- //接下来的左边和右边就不讲 原理和上面一样
- void ChangeLeftWin(Point e)
- {
- double M_mun = Canvas.GetLeft(this) - e.X;
- if (this.Width >= 100 || M_mun > 0)
- this.Width += M_mun;
- LastPoint = e;
- Canvas.SetLeft(this, LastPoint.X);
- }
- void ChangeRightWin(Point e)
- {
- double M_mun = e.X - Canvas.GetLeft(this) - this.Width;
- if (this.Width >= 100 || M_mun > 0)
- this.Width += M_mun;
- }
接下来是实现最大化的功能
接着看代码
- public static readonly DependencyProperty IsMaxmunProperty = DependencyProperty.Register("IsMaxmun", typeof(bool), typeof(WInControl), new PropertyMetadata(false, onIsMaxmunChange)); //这是定义的最大化的依赖属性说是最大化 其实是最大化和窗口化
- public bool IsMaxmun//最大化
- {
- get { return (bool)this.GetValue(IsMaxmunProperty); }
- set { this.SetValue(IsMaxmunProperty, value); }
- }
- public static void onIsMaxmunChange(DependencyObject sender, DependencyPropertyChangedEventArgs e)
- {
- WInControl This = sender as WInControl;
- if (This.IsMaxmun == true)
- This.ToMaxmun();
- else
- This.ToMinnormal();
- }
- protected virtual void ToMaxmun()
- { //把窗体高和宽保存起来 再把窗体设置成与父容器 这里有个Owner是用来设置父容器引用
- //大家也可 用Parent属性 他就是在可视树上的父节点
- LastPoint.X = Canvas.GetLeft(this);
- LastPoint.Y = Canvas.GetTop(this);
- LastWinSize.Width = this.Width;
- LastWinSize.Height = this.Height;
- Canvas.SetLeft(this, 0);
- Canvas.SetTop(this, 0);
- this.Height = (Owner).RenderSize.Height;
- this.Width = (Owner).RenderSize.Width;
- }
- protected virtual void ToMinnormal()
- { //这里就是还原窗体
- Canvas.SetLeft(this, LastPoint.X);
- Canvas.SetTop(this, LastPoint.Y);
- this.Height = LastWinSize.Height;
- this.Width = LastWinSize.Width;
- }
这就是最大化和窗口化功能 还有一点在最大化时大家要 移除那几个矩形的鼠标点击事件 再在
窗口化添加这个事件 最小化就留给大家自己考虑。
- public static readonly DependencyProperty TitleProperty = DependencyProperty.Register("Title", typeof(string), typeof(WInControl), new PropertyMetadata(string.Empty, OnTitleChanged));
这个是窗体标题
- public string Title
- {
- get { return (string)GetValue(TitleProperty); }
- set { SetValue(TitleProperty, value); }
- }
- public static void OnTitleChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
- {
- WInControl This = sender as WInControl;
- if (This.TitleC != null)
- This.TitleC.Text = This.Title;
- }
这里有一点要注意 由于这个方法比较早调用 而 TitleC没有设置引用 所以要判断下是否为null
这里一部分基本功能已经完成了
不过有两个重要的功能就是关闭 和打开窗体
这里的repeat和repeat2是防止动画被多次设定
动画已经在资源里
只是没有设定作用对象
- public override void Close()
- {
- Storyboard app = Resources["_disappear"] as Storyboard;
- if (repeat == false)
- {
- foreach (var item in app.Children)
- {
- Storyboard.SetTarget(item, this);
- }
- repeat = true;
- }
- app.Begin();
- }
- public override void Open()
- {
- Storyboard app = Resources["_appear"] as Storyboard;
- this.Visibility = Visibility.Visible;
- if (repeat2 == false)
- {
- foreach (var item in app.Children)
- {
- Storyboard.SetTarget(item, this);
- }
- repeat2 = true;
- }
- app.Begin();
- }
就这样就可以实现关闭和打开的功能
而且动画由你自己设定
这里先讲到这里 可能有很多不足 但免免强强一个自己写的win窗体控件算完成了
对于那些sl老手可能没什么
但我希望对sl初学的朋友有帮助
还请大家多提意见相互学习 Demo我整理下晚点发上来
希望大家这个基础上继续加强!!!!!!!!!!
演示地址http://anye6488-001-site1.site4future.com/anyePath.web/anyePathTestPage1.html
注:本文转自http://dingtao-wgs.blog.163.com/blog/static/502607142010101754018734/,仅供学习之用。
(转)sl简单自定义win窗体控件的更多相关文章
- jquery和css自定义video播放控件
下面介绍一下通过jquery和css自定义video播放控件. Html5 Video是现在html5最流行的功能之一,得到了大多数最新版本的浏览器支持.包括IE9,也是如此.不同的浏览器提供了不同的 ...
- 如何在多线程中调用winform窗体控件
由于 Windows 窗体控件本质上不是线程安全的.因此如果有两个或多个线程适度操作某一控件的状态(set value),则可能会迫使该控件进入一种不一致的状态.还可能出现其他与线程相关的 bug,包 ...
- jQ效果:jQuery和css自定义video播放控件
下面介绍一下通过jquery和css自定义video播放控件. Html5 Video是现在html5最流行的功能之一,得到了大多数最新版本的浏览器支持.包括IE9,也是如此.不同的浏览器提供了不同的 ...
- QT 窗体控件的透明度设置(三种方法)
整个窗体 当设置QT的窗体(QMainWindow, QDialog)时,直接用 targetForm->setWindowOpacity() 函数即可实现,效果为窗体及窗体内所有控件都透明 ...
- C# WinForm自定义通用分页控件
大家好,前几天因工作需要要开发一个基于WinForm的小程序.其中要用到分页,最开始的想法找个第三方的dll用一下,但是后来想了想觉得不如自己写一个玩一下 之前的web开发中有各式各样的列表组件基本都 ...
- WPF教程十一:简单了解并使用控件模板
WPF教程十一:简单了解并使用控件模板 这一章梳理控件模板,每个WPF控件都设计成无外观的,但是行为设计上是不允许改变的,比如使用Button的控件时,按钮提供了能被点击的内容,那么自由的改变控件外观 ...
- kettle系列-[KettleUtil]kettle插件,类似kettle的自定义java类控件
该kettle插件功能类似kettle现有的定义java类插件,自定java类插件主要是支持在kettle中直接编写java代码实现自定特殊功能,而本控件主要是将自定义代码转移到jar包,就是说自定义 ...
- winform窗体控件(全)
回顾跟补充下除了昨天那常用6个其他的winform窗体控件作用 1:Button:按钮 (1)AutoSize:如果是True的情况下,内容将会撑开:False的话会另起一行 (2)Enabled: ...
- WPF自定义控件与样式(8)-ComboBox与自定义多选控件MultComboBox
一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: 下拉选 ...
随机推荐
- 兼容IE浏览器的js浏览器全屏代码
众所周知,IE是个奇葩的浏览器,但是由于用户量很大,开发者还是不得不为IE考虑一下,于是,各种浏览器相关的操作,都要多一个特别的判断——专门针对IE浏览器的判断,这里的全屏也不例外.看代码: func ...
- 【emWin】例程三:显示方向的切换
实验指导书及代码包下载: http://pan.baidu.com/s/1pK9o0xP
- PostGr-SQL 基本概念
http://wenjiesu.iteye.com/blog/801129 [什么是schema?] 究竟什么是schema?这个问题困扰了我很久. 我们只讨论数据库中的schema,而不讨论XML中 ...
- OpenGL中实现双缓冲技术
在OpenGL中实现双缓冲技术的一种简单方法: 1.在调用glutInitDisplayMode函数时, 开启GLUT_DOUBLE,即glutInitDisplayMode(GLUT_RGB | G ...
- Android高级之十二讲之如何降低应用内存消耗
安卓应用的内存往往是有限的,从开始的8M到16M,24M,32M,48M,64M等逐步变大,但内存的变大是由于分辨率的提高导致,并不意味着可以随意声明使用内存,而不及时回收(即使Java有自己的垃圾回 ...
- js 相关知识整理(一)
真正声明变量,是用逗号隔开的 EcM5:严格模式“use strict” java与js 语言的区别: 1.弱类型语言 1.声明变量时不需要提前指定数据类型 2.同一个变量可先后保存不同类型的数据 3 ...
- http 状态码
一些常见的状态码为: 200 - 服务器成功返回网页 404 - 请求的网页不存在 503 - 服务不可用 详细分解: 1xx(临时响应) 表示临时响应并需要请求者继续执行操作的状态代码. 代码 说明 ...
- linux 技巧:使用 screen 管理你的远程会话
你是不是经常需要 SSH 或者 telent 远程登录到 Linux 服务器?你是不是经常为一些长时间运行的任务而头疼,比如系统备份.ftp 传输等等.通常情况下我们都是为每一个这样的任务开一个远程终 ...
- AFNetworking 2.0指北
AFNetworking 2.0 来了 SEP 30TH, 2013 前几天 Mattt 发布了 AFNetworking 2.0,我的一个最大感慨就是,他怎么那么高产? 关于 Mattt Mattt ...
- as3绕过策略文件给视频截图
接上篇 http://www.cnblogs.com/DarkMaster/p/5973593.html 这篇同样是在老外博客上找到的,分享给大家,再次感叹老外牛逼啊. 原文地址:http://gam ...