跟我做WinForm开发
2012-01-07 12:03 by 空逸云, 3710 visits, 收藏 , 编辑
前言
前阵子,学英文的时候听发音,意外之中发现Google的发音相比大部分TTS发音更准确,而且读句子也没有普通TTS那种一听就是机器人的声音,心血来潮,想利用Google发音做一个小软件,所以就有了本文。
这是最后的UI成品图,可以看到,没有了常见的按钮,也没有了常见的Title框,整个布局随心所欲,GDI+?No。下面,就带大家跟我一起来用最简单的方式开发你所期望的UI吧!
自定义窗体WinForm开发中,我们都知道窗体和控件的作用,实际上,以上的UI实现也是通过自定义窗体和用户控件实现,那该如何做,才能让窗体变成我们所想要的样子呢?
首先,新建一个窗体,在这里,我命名为MainForm.cs,打开我们就可以见到以往的样子:
选中窗体,右键=》属性,将FormBorderStyle设置成None, 窗体就变成了右图所示;接着,我再将其拖拉成我需要的长度和宽度,此时若编译运行,会发现实际上什么都东西都看不到,这正是我们所需要的效果,接着,就防止我们想呈现的元素。接着,我将其拉成一个长方形,并在四周放4个PictureBox,正中间放一个Panel。
这里需要注意的就是4个PictureBox的宽度,长度和未知,实际上我也不是拖控件,而是通过修改控件是属性,这里就需要精确到像素,聪明的你应该想到它们就是4条边框线和中间的内容块了,在这里我推荐一个软件,MarkMan,传说中的标注神器,做UI方面,特别是开发人员,很有帮助。
在将所需的图片填充上去就可以了。
private Image GetResourceImg( string name)
{
return Image . FromStream( Assembly . GetExecutingAssembly() . GetManifestResourceStream(name));
}
void InitFormStyle()
{
//边框
var borderImg = GetResourceImg( @"Speaker.Resource.Images.border.jpg" );
Bitmap borderMap = new Bitmap (borderImg);
borderMap . MakeTransparent( Color . FromArgb( 255 , 0 , 255 ));
this . pb_borderLeft . BackgroundImage = borderMap;
this . pb_borderRight . BackgroundImage = borderMap;
this . pb_borderTop . BackgroundImage = borderMap;
this . pb_borderBottom . BackgroundImage = borderMap;
//主面板
var mainImg = GetResourceImg( @"Speaker.Resource.Images.main.jpg" );
this . pl_main . BackgroundImage = new Bitmap (mainImg);
//Logo
var logoImg = GetResourceImg( @"Speaker.Resource.Images.logo.jpg" );
this . btn_setting . NormalImage = new Bitmap (logoImg);
btn_setting . Reset();
//Speak Button
var normalImg = GetResourceImg( @"Speaker.Resource.Images.button.png" );
var moveImg = GetResourceImg( @"Speaker.Resource.Images.buttonMove.png" );
var downImg = GetResourceImg( @"Speaker.Resource.Images.buttonDown.png" );
btn_speak . NormalImage = normalImg;
btn_speak . MoveImage = moveImg;
btn_speak . DownImage = downImg;
btn_speak . Reset();
}
编译通过之后,边框雏形就出现了~:-)
自定义控件窗体我们已经有了,接下来就是里面一些控件的实现,这里,我主要用到了两个控件,ImageButton和LightTextBox,顾名思义,ImageButton就是一个图片按钮,但它还提供鼠标按下,悬移时的图片选择;LightTextBox是一个TextBox,鼠标悬移的时候,边框高亮;
LightTextBox
新建用户控件LightTextBox,选中控件,右键=》属性,将BorderStyle改为None,这样,控件也不可见了!拖出一个TextBox,并标注为MultiLine,至此,UI就这样了,接着是控件的绘制编码;
public LightTextBox()
{
SetStyle( ControlStyles . OptimizedDoubleBuffer | ControlStyles . AllPaintingInWmPaint, true );
InitializeComponent();
BackColor = Color . Transparent;
txt . Location = new Point ( 3 , 6 );
txt . MouseEnter += new EventHandler (txt_MouseEnter);
txt . MouseLeave += new EventHandler (txt_MouseLeave);
}
实现TextBox的鼠标悬移事件就是为了实现边框高亮效果;
#region Events
void txt_MouseLeave( object sender, EventArgs e)
{
_isFouse = false ;
this . Invalidate();
}
void txt_MouseEnter( object sender, EventArgs e)
{
_isFouse = true ;
this . Invalidate();
}
#endregion
方法部分(控件实现的主要方法)
#region Methods
protected override void OnPaint( PaintEventArgs e)
{
Graphics g = e . Graphics;
g . InterpolationMode = InterpolationMode . HighQualityBicubic;
g . SmoothingMode = SmoothingMode . HighQuality;
txt . Width = Width - 6 ;
CalculateSizeAndPosition();
Draw(e . ClipRectangle, e . Graphics);
base . OnPaint(e);
}
private void CalculateSizeAndPosition()
{
if ( ! txt . Multiline)
{
Height = txt . Height + 9 ;
}
else
{
txt . Height = Height - 9 ;
}
}
private void Draw( Rectangle rectangle, Graphics g)
{
#region 画背景
using ( SolidBrush backgroundBrush = new SolidBrush ( Color . White))
{
g . FillRectangle(backgroundBrush, 2 , 2 , this . Width - 4 , this . Height - 4 );
}
#endregion
#region 画阴影(外边框)
Color drawShadowColor = _shadowColor;
if ( ! _isFouse) //判断是否获得焦点
{
drawShadowColor = Color . Transparent;
}
using ( Pen shadowPen = new Pen (drawShadowColor))
{
if (_radius == 0 )
{
g . DrawRectangle(shadowPen, new Rectangle (rectangle . X, rectangle . Y, rectangle . Width - 1 , rectangle . Height - 1 ));
}
else
{
g . DrawPath(shadowPen, DrawHelper . DrawRoundRect(rectangle . X, rectangle . Y, rectangle . Width - 2 , rectangle . Height - 1 , _radius));
}
}
#endregion
#region 画边框
using ( Pen borderPen = new Pen (_borderColor))
{
if (_radius == 0 )
{
g . DrawRectangle(borderPen, new Rectangle (rectangle . X + 1 , rectangle . Y + 1 , rectangle . Width - 3 , rectangle . Height - 3 ));
}
else
{
g . DrawPath(borderPen, DrawHelper . DrawRoundRect(rectangle . X + 1 , rectangle . Y + 1 , rectangle . Width - 3 , rectangle . Height - 2 , _radius));
}
}
#endregion
}
#endregion
由于字段,属性比较多,我就不贴出来了,感兴趣的可以在后续的源码中查看;此时,若将该控件放到窗体中,鼠标移
动上去,则可发现边框有一层光晕;
ImageButton
这里的自定义控件实现方式一致,都先去掉了BorderStyle,再自己控制呈现内容,所以才能达到显示特殊UI的目的;ImageButton的UI设计就不详述了,直接放出后台实现主代码;
public ImageButton()
{
this . SetStyle( ControlStyles . AllPaintingInWmPaint | ControlStyles . OptimizedDoubleBuffer, true );
InitializeComponent();
Reset();
}
#region Methods
public void Reset()
{
if (_normalImage != null )
{
this . BackgroundImage = _normalImage;
this . Size = new Size (_normalImage . Width, _normalImage . Height);
}
}
private void MakeTransparent( Image image)
{
Bitmap bitmap = image as Bitmap ;
bitmap . MakeTransparent( Color . FromArgb( 255 , 0 , 255 ));
}
#endregion
private void ImageButton_MouseEnter( object sender, EventArgs e)
{
if (_moveImage != null )
this . BackgroundImage = _moveImage;
}
private void ImageButton_MouseLeave( object sender, EventArgs e)
{
this . BackgroundImage = _normalImage;
}
private void ImageButton_MouseDown( object sender, MouseEventArgs e)
{
if (_downImage != null )
this . BackgroundImage = _downImage;
}
private void ImageButton_MouseUp( object sender, MouseEventArgs e)
{
if (_moveImage != null )
this . BackgroundImage = _moveImage;
}
MainForm
万事俱备,只欠东风;把控件都放入MainForm中,并初始其状态即可(上面第一部分代码已放出);此时,编译运行;已达到我们预期的UI效果;但是,UI效果是有了,移动效果,缩小(点击任务栏图标)等却都失效了,该怎么办?Win32API千呼万唤使出来~
private void pl_main_MouseDown( object sender, MouseEventArgs e)
{
if (e . Button == MouseButtons . Left)
{
Win32 . ReleaseCapture();
Win32 . SendMessage(Handle, 274 , 61440 + 9 , 0 );
}
}
这里实际上是调用了Win32API,在这里,又有一个好东西分享;平时做这些Win32API交互/C#与C++交互,需
要做类型转换,特别是C++里面一些指针什么的,很是纠结, http://clrinterop.codeplex测试数据 能帮到你;它能根据你输入的C++函数生成C#的代码;不可谓不是一大杀器啊!
移动解决了,那缩小的问题,也必须解决了;
protected override CreateParams CreateParams
{
get
{
const int WS_MINIMIZEBOX = 0x00020000 ; // Winuser.h中定义
CreateParams cp = base . CreateParams;
cp . Style = cp . Style | WS_MINIMIZEBOX; // 允许最小化操作
return cp;
}
}
重写CreateParams属性就可以了;到这里,我们的应用已经能正常显示出我们所想要的UI;但还不够,大部
分辅助类型的软件都有最小化的功能,那,我们也将其加上去吧;
NotifyIcon这个其实很简单,就是拖一个NotifyIcon到窗体中,并绑定一个ContextMenu到这个NotifyIcon中就可以了;然后在触发一些事件;
private void MainForm_Resize( object sender, EventArgs e)
{
if (WindowState == FormWindowState . Minimized)
{
this . Visible = false ;
}
}
后面,我还主要用NotifyIcon来通知用户,做提示,错误提示等;到这里,整个UI方面就已经完成了;只
剩下后面的逻辑处理,就是输入句子能发音,并且支持快捷键屏幕取词等;
随笔分类 -C#
计算一个数字有多少种排列可能 2012-02-03 09:14 by 空逸云, 613 visits, 网摘 , 收藏 , 编辑
5 Comment Categories: C#
跟我做WinForm开发(2)-后台逻辑操作 2012-01-08 12:32 by 空逸云, 2495 visits, 网摘 , 收藏 , 编辑
25 Comment Categories: C#
跟我做WinForm开发(1)-自定义UI 2012-01-07 12:03 by 空逸云, 3711 visits, 网摘 , 收藏 , 编辑
72 Comment Categories: C#
细说文件读写操作(读写锁) 2011-11-15 00:20 by 空逸云, 1580 visits, 网摘 , 收藏 , 编辑
17 Comment Categories: C#
您真的了解类型转换吗?请止步,解惑! 2011-08-29 00:11 by 空逸云, 1888 visits, 网摘 , 收藏 , 编辑
32 Comment Categories: C# , CLR
您真的了解类型转换吗?请止步,求解! 2011-08-24 23:57 by 空逸云, 3744 visits, 网摘 , 收藏 , 编辑
100 Comment Categories: C#
基于AppDomain的"插件式"开发 2011-08-01 09:58 by 空逸云, 1921 visits, 网摘 , 收藏 , 编辑
38 Comment Categories: C#
青梅煮酒论C#:Specification pattern 2011-01-16 13:56 by 空逸云, 1757 visits, 网摘 , 收藏 , 编辑
16 Comment Categories: C#
你正确的使用Out/Ref了吗? 2010-12-03 19:19 by 空逸云, 379 visits, 网摘 , 收藏 , 编辑
6 Comment Categories: C#
【More Effective C#】Partial Class是怎样炼成的? 2010-10-28 08:14 by 空逸云, 1949 visits, 网摘 , 收藏 , 编辑
13 Comment Categories: C#
【More Effective C#】掩藏在Nullable<T>后的秘密 2010-10-27 08:19 by 空逸云, 1780 visits, 网摘 , 收藏 , 编辑
21 Comment Categories: C#
【More Effective C#】IEnumerable和IQueryable的那点事 2010-10-22 08:08 by 空逸云, 2145 visits, 网摘 , 收藏 , 编辑
22 Comment Categories: C# , LINQ
【More Effective C#】区分早期执行和晚期执行 2010-10-20 08:19 by 空逸云, 1739 visits, 网摘 , 收藏 , 编辑
11 Comment Categories: C# , LINQ
【More Effective C#】Lambda表达式优化 2010-10-19 08:09 by 空逸云, 2673 visits, 网摘 , 收藏 , 编辑
38 Comment Categories: C#
【More Effective C#】LINQ表达式与方法调用的映射 2010-10-15 08:05 by 空逸云, 411 visits, 网摘 , 收藏 , 编辑
2 Comment Categories: C#
【More Effective C#】延迟求值 2010-10-14 18:30 by 空逸云, 416 visits, 网摘 , 收藏 , 编辑
5 Comment Categories: C#
【More Effective C#】仅声明非虚的事件 2010-10-13 08:17 by 空逸云, 178 visits, 网摘 , 收藏 , 编辑
0 Comment Categories: C#
【More Effective C#】扩展方法
更多资料跟我学做c#皮肤美化
WinAPI使用大全
跟我做WinForm开发(2)-后台逻辑操作
作者: 空逸云
出处: http://kongyiyun.cnblogs测试数据
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
作者: Leo_wl
出处: http://HdhCmsTestcnblogs测试数据/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息