蛙蛙推荐:winform入门

蛙蛙推荐:winform入门
摘要:现在web应用的发展大大快于桌面应用,但桌面应用在某些场合确实也有很大的有事,其实.net 2.0在windows form方面做了不少的改进,大家也许也零零散散的知道一些,本文来综合这些技术点来做一个模仿outlook2003的桌面应用程序框架。

outlook的界面早已深入人心(当然有些人打死也不用outlook),其实outlook在UI和用户体验多方面的好多考虑是有理论根据的,比如手风琴式的按钮条会让用打户使用起来很方便,三栏式的布局让人的视觉不用左右来回移动,全键盘操作等等方面,也许大家天天用没在意这些,可当初的设计者一定在用户体验上做了好多考虑和取舍的,所以我们这些开发者一般要做的就是模仿。限于篇幅,本文只讲到一些基础的东西,算是一个入门,最终我们会模仿一个outlook界面的大概样子,如果更深入学习outlook的界面,请参考以下链接
Outlook 2003 Look and Feel

http://windowsclient.net/downloads/folders/applications/entry1338.aspx

 

【窗体设计】
首先窗体的高宽比例要考虑的,不是没有讲究的,这里用932和561,要整体看起来美观,其实这个更具体应用有关的,不能一概而论。再次就是窗体的Icon要做一个能体现你的应用的,一般为了灵活可以在窗体加载事件里从资源文件里读取图标,如下:
 Icon = Icon.FromHandle(Resources.Outlook.GetHicon());
然后就是标题要修改一下,就是Text属性。还有就是有时候界面太大或者太小的时候影响窗体内的显示元素,这时候可以用MaximumSize和MinimumSize来设置窗体的最大大小和最小大小。还有的时候我们希望窗体没有最大化和最小化的按钮,分别应该设置MinimizeBox和maximizeBox属性,甚至有时候我们不想让用户能调整窗体的大小,我们可以把FormBorderStyle设置为FixedDialog。如果要想让应用程序一打开就全屏,应该设置WindowState属性为Maximized。
好多应用程序关闭后能记住上次用户拖动设置的窗体大小,下次打开的时候还是上次的窗口大小,这些就需要编程来实现了,后面会介绍到,关于整个窗体设计就说这么多,别的属性大家慢慢看MSDN。
【总体布局】
顶部是菜单栏,接着是工具按钮条,再下面是主工作区,最下面是状态栏,其中工作区又分为左右两部分。以此往界面上拖动MenuStrip,ToolStrip,StatusStrip和一个SplitContainer,然后适当调整SplitContainer左右面板的大小就可以了,然后把FixPanel设置为左边的面板,这样窗体大小改动后左边的面板不会改变。默认SplitContainer放上去,运行的时候拖动手柄会显示一条虚线,我觉得这是一个bug,自动获取焦点了,要把TabStop属性设置为false就可以了,但是你拖动手柄调整大小后,虚线不会自动去掉,所以我就在它的鼠标释放的时候把焦点转给了菜单,就没虚线了,这是我的解决方案,大家有别的方案可以告诉我。我的如下
private void splitContainer1_MouseUp(object sender, MouseEventArgs e)
{
    menuStrip1.Focus();
}
SplitContainer会自动填充剩余的空间,并且没有任何边框。但是不要紧,.net 2.0的所有windows控件新增了magrin和padding属性,用来设置外空白和内填充,和CSS差不多,我们可以把左右两个面板设置背景色,然后padding设置为1,最后在左右两个面板里再分别拖进去两个面板,Dock设置为fill,背景色设置为Control,这样就会显示1像素的边框了,这种技巧在网页设计里很常见,这里也适用。
【菜单】
菜单排放的顺序依次是 文件,编辑,视图,转到,工具,操作和帮助,这些排列虽然没有硬性规定,却是约定俗成的,你随便排列会给用户带来不便,包括子菜单的排列等。然后菜单项的文本里可以设置alt键的热键,比如文件的文本可以设置成“文件(&F)”这样用户按住alt键盘和f键就会激活文件菜单。然后菜单的左边可以设置一个表达菜单项意义的图片,还可以设置一个全局快捷键,比如新建联系人用ctrl+shift+C来设置shortcutkeys属性。要想让菜单项的左边显示一个对勾的话需要设置CheckState属性。还有就是如果点击菜单项会弹出对话框的话,菜单项的文本后面要加一个省略号,如果菜单有子菜单项的话右边显示一个小三角,后者是自动的。菜单一般要能用纯键盘操作,关于键的设计,参考如下链接,虽然文章比较早,但仍有意义。
键盘用户界面设计指南

http://wz.cnblogs.com/detail/1873/

关于菜单的基础就是这些。
【工具条】
ToolStrip是个功能很强大的控件,可以在上面添加按钮,下拉按钮,分隔按钮,标签,文本框,组合文本框,甚至进度条等。工具条里演示了这个强大的控件,不过这里只是单纯的用任务提示栏添加各种子控件就可以了,有些应用有多个工具栏,比如标准工具栏,插入工具栏等等,而且还能拖动和隐藏。那是吧ToolStrip放到了ToolStripContainer里了,本文暂不演示,只是提一下,本文只演示最基本的布局和用户体验考虑。ToolStrip的表现力非常强,可以参考如下链接管中窥豹一番:
使用 Windows Forms 2.0 创建智能应用程序布局

http://msdn.microsoft.com/zh-cn/library/aa730847(VS.80).aspx


【状态栏】
状态栏向用户反馈信息的一个重要的工具,很少有程序没有状态栏的。winform 2.0的状态栏比以前版本也强大很多,但缺少了分隔栏,不过没关系,我们在上面添加了label后把右边框显示出来就显示出风格条了,这应该设置BorderSides属性。然后我们有时候想让状态栏上有三个元素,两边的靠在两边,中间的自动填充满,这时候要把中间的label的Spring属性设置为True。再有就是我们有时候想把ToolStripDrowdownButton右下角的小三角去掉,这通常是为了美观,可以把ShowDropDownArrow设置为False。当然这些都是很细小的设置,但是如果你不知道的话,会郁闷半天的。
【手风琴式的功能按钮条】
这个称呼不是我起的,好多人都这么叫,这个是本文的重点,outlook的功能条看起来很炫,其实用ToolStrip控件加上一些自绘就可以模仿出来。
首先在主分割面板的左面板里再放置一个SplitContainer,把Horizontal设置为Horizontal,这样两个面板就成为上下布局了,然后把下面的面板设置为FixPanel,这是因为我们这里要放按钮条,按钮条的高度我们不希望随着窗口的大小而变动。先在这个面板里放一个ToolStrip,为了让按钮从上到下一次排列,我们把LayoutStyle 的值改为 VerticalStackWithOverflow,为了不显示按钮条的是拖动手柄,我们把GripStyle 设置为Hidden,为了显示office式的漂亮效果,我们把RenderMode设置为Professional,还有就是我们把字体设置为宋体,加粗和8号,关于字体的设置可以讨论的有很多,不同情况用不同的字体,这里暂不讨论。为了让按钮条不至于太窄,我们把ImageScalingSize设置为24×24,默认是16*16的有些小,然后把TabStop设置为false,margin和padding都设置为0。
接下来就可以往ToolStrip上添加按钮了,首先把magrin设置为0,padding设置为2,这样按钮上的文字不会挨到按钮的边儿了,这样好看一些然后设置图像,默认设置的透明图像可能会有白变,但把ImageTransparentColor设置为238,238,238就没那个白边了,其中的道理我也不明白,反正直接设置成Transparent白边去不了。然后把DispayStyle设置为ImageAndText,ImageAlign设置为MidleLelt,TextAlign设置为MiddleRight,TextImageRelation设置为Overlay(这部可做可不做),,如果字体已经是粗体就不用单独设置了,否则在按钮上单独设置字体加粗,整体效果就出来了。
然后默认的ToolStrip的背景和边框不是很好看,outlook的按钮条有渐变色,这些就需要用到重绘了,大致原理是创建一个自定义的控件,继承自ToolStrip,然后在OnRendererChanged和构造函数里挂接ToolStrip的背景颜色绘制事件和按钮的背景颜色绘制事件,然后在事件处理函数里重新绘制它们的边框和背景填充色,这里要用到gdi来做2D的渲染,不是本文讲的范围,大家可以搜索下相关资料。另外可以参考以下链接来了解如何写出专业化的ToolStrip,可以根据用户的操作系统样式来改变菜单条的样式。
演练:创建具有专业样式的 ToolStrip 控件
http://msdn.microsoft.com/zh-cn/library/ms233664(VS.80).aspx

 

 

public   partial   class  WawaToolStrip : ToolStrip
{
    
protected  ToolStripProfessionalRenderer _pr;

    
public  WawaToolStrip()
    {
        
//  Check Dock
        Dock  =  DockStyle.Fill;
        GripStyle 
=  ToolStripGripStyle.Hidden;
        Margin 
=   new  Padding( 0 );
        CanOverflow 
=   false ;
        AutoSize 
=   false ;
        LayoutStyle 
=  ToolStripLayoutStyle.VerticalStackWithOverflow;  // 垂直排列按钮

        SetRenderer();
    }

    
private   void  SetRenderer()
    {
        
if  ((Renderer  is  ToolStripProfessionalRenderer)  &&  (Renderer  !=  _pr))
        {
            
if  (_pr  ==   null )
            {
                _pr 
=   new  ToolStripProfessionalRenderer();
                _pr.RoundedEdges 
=   false ;
                
// 重绘ToolStrip的背景颜色
                _pr.RenderToolStripBackground  +=  StackStrip_RenderToolStripBackground;
                OnSetRenderer(_pr);
            }
            Renderer 
=  _pr;
        }
    }

    
private   void  StackStrip_RenderToolStripBackground( object  sender, ToolStripRenderEventArgs e)
    {
        
        
if  (_pr  !=   null )
        {
            
//  Setup colors from the provided renderer
            Color start  =  _pr.ColorTable.ToolStripGradientMiddle;
            Color end 
=  _pr.ColorTable.ToolStripGradientEnd;

            
//  Size to paint
            Rectangle bounds  =   new  Rectangle(Point.Empty, e.ToolStrip.Size);

            
//  Make sure we need to do work
             if  ((bounds.Width  >   0 &&  (bounds.Height  >   0 ))
            {
                
using  (Brush b  =   new  LinearGradientBrush(bounds, start, end, LinearGradientMode.Vertical))
                {
                    e.Graphics.FillRectangle(b, bounds);
                }
            }

            
//  Draw border
            
// e.Graphics.DrawRectangle(SystemPens.ControlDarkDark, bounds);
            e.Graphics.DrawLine(SystemPens.ControlDarkDark, bounds.X, bounds.Y, bounds.Width  -   1 , bounds.Y);
            e.Graphics.DrawLine(SystemPens.ControlDarkDark, bounds.X, bounds.Y, bounds.X, bounds.Height 
-   1 );
            e.Graphics.DrawLine(SystemPens.ControlDarkDark, bounds.X 
+  bounds.Width  -   1 , bounds.Y,
                                bounds.X 
+  bounds.Width  -   1 , bounds.Height  -   1 );
        }
    }
    
protected   virtual   void  OnSetRenderer(ToolStripProfessionalRenderer pr)
    {
        pr.RenderButtonBackground 
+=  _pr_RenderItemBackground;
    }

    
private   void  _pr_RenderItemBackground( object  sender, ToolStripItemRenderEventArgs e)
    {
        Graphics g 
=  e.Graphics;
        Rectangle bounds 
=   new  Rectangle(Point.Empty, e.Item.Size);

        Color gradientBegin 
=  Color.White;
        Color gradientEnd 
=  Color.FromArgb( 198 194 188 );

        ToolStripButton button 
=  e.Item  as  ToolStripButton;
        
if  (button.Pressed  ||  button.Checked)
        {
            gradientBegin 
=  _pr.ColorTable.ButtonPressedGradientBegin;
            gradientEnd 
=  _pr.ColorTable.ButtonPressedGradientEnd;
        }
        
else   if  (button.Selected)
        {
            gradientBegin 
=  _pr.ColorTable.ButtonSelectedGradientBegin;
            gradientEnd 
=  _pr.ColorTable.ButtonSelectedGradientEnd;
        }

        
//  Draw Button Background
         using  (Brush b  =   new  LinearGradientBrush(bounds, gradientBegin, gradientEnd, LinearGradientMode.Vertical))
        {
            g.FillRectangle(b, bounds);
        }

        
//  Draw Outilne
        e.Graphics.DrawRectangle(SystemPens.ControlDarkDark, bounds);
    }


    
protected   override   void  OnRendererChanged(EventArgs e)
    {
        
base .OnRendererChanged(e);

        
//  Work around bug with setting renderer in the constructor
        SetRenderer();
    }
}

【关于用户设置的保存】
前面提到有些应用会记住自己上次关闭时的窗口大小,其实在winform2.0里做到这个很简单,winform2.0里有一个Settings.settings的文件,它用来添加一些用户的设置,和app.config不同的是,他可以应用于用户范围或者整个应用范围,而且还可以跟随windows漫游文件来走,只要你登录在域里,无论使用哪台机器,你的个性化配置都会跟着你走。在Setting里加入main_form_width和main_form_height两个int型的配置,范围选择user。我们在窗口关闭的时候保存用户配置,打开的时候应用配置,就可以做到窗口大小自动记忆了,代码如下。


 

 

private   void  Form1_Load( object  sender, EventArgs e)
{
    
if (Settings.Default.main_form_height != 0 && Settings.Default.main_form_width != 0)
    
{
        Width 
= Settings.Default.main_form_width;
        Height 
= Settings.Default.main_form_height;
    }

}


private   void  MainForm_FormClosing( object  sender, FormClosingEventArgs e)
{
    Settings.Default.main_form_height 
= Height;
    Settings.Default.main_form_width 
= Width;
    Settings.Default.Save();
}


【小节】
本文只是抛砖引玉,希望大家能做出更专业,用户体验更好的桌面应用来。有了这个入门,大家有时间也可以根据自己的需求系统的学习下windows forms编程,光做web应用有时候思路就受局限了,windows上桌面应用才是王道,只要解决了部署的问题,web程序相对windows程序也没什么优势了,可喜的是.net1.0就支持自动部署了,后来又支持click one,部署和更新真的不是问题,而且界面体验比web强的多,还有本地存储等优势,能写出很强大很丰富的界面来,现在web应用,你要用离线存储得安装ms sync framework,google gears等,要想用丰富的界面得用exts,yui等,要想访问网络得自己解析rest服务返回的数据,还得考虑浏览器兼容性等,而winform这些东西都是天生具备的,大家都围着浏览器,flash,severlight的时候,其实可以写一个插件式的应用程序浏览器,发布的时候只是一个空架子,相当于浏览器,广大开发者可以根据SDK开发各种应用,相当于用HTML写网页,然后用应用程序浏览器去浏览各种应用,相当于浏览器去浏览网页,这得咱们自己去做,自己干等着完全支持html5的浏览器发布,不知道等到哪辈子了,到那时候浏览器能直接画矢量图,使用嵌入式Sql,有脱机缓存方面的API,内置多媒体播放器及富文本编辑器而且有好多开放的接口,那时候和winform也差不多了,本文也就没用了,大家也该忘了winform了。关于HTML5的新特性,参考如下链接
揭开HTML 5工作草稿的神秘面纱
http://www.infoq.com/cn/news/2008/02/html5draft

忘了放代码了,下载路径如下

http://files.cnblogs.com/onlytiancai/WindowsApplication1.7z

补充:

关于winform 2.0的新的功能改进可以参考一下两个链接

构造用户界面

http://msdn.microsoft.com/zh-cn/library/aa730862(VS.80).aspx

Ground Rules for Building Enhanced Windows Forms Support into Your .NET App
http://msdn.microsoft.com/en-us/magazine/cc163793.aspx

http://www.cnblogs.com/onlytiancai/archive/2008/09/14/begin_winform.html

代码我也简单贴一下吧,均出自OLAF,我做了一些精简,很容易理解,GDI的一些API如果不理解可以根据其名字来猜测一些含义,不影响对本文的理解。

 
 

转载于:https://www.cnblogs.com/zhdonghu/archive/2010/12/29/1920855.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值