界面开发(二)

 

2010-04-07 作者:zhjp11 来源:萧萧空间

 

(三)--- 设置窗体的Region

经过上面两篇的界面开发,我们使用Windows的Hook技术,成功的将系统中的窗体的消息截取,并添加了自己的事件处理程序,这篇文章就是通过我们对这些消息的处理的第一步,设置窗体的样式和窗体的Region。

Region对于窗体来说是一个非常重要的概念,他就是Windows分配给窗体显示的区域,所以,我们第一步就是根据我们的需要设计我们的窗体区域。而对于Windows窗体区域的设置,WndProc中的STYLECHANGED,SHOWWINDOW,SIZE,WINDOWPOSCHANGED都有可能用到。这些方法都对窗体的样式或者窗体的大小就行了修改,所以我们也要对这几个消息进行处理。

首先我们创建一个类用来设置窗体的显示,名称为SkinAppearance.cs,在这个文件中我添加了一个方法,叫做SetRegion,并且参数设置成为我们的窗体SkinningForm。SetRegion的代码如下:

/// <summary>
        
/// Set SkinningForm Region 
        
/// </summary>
        
/// <param name="from">form to set region</param>
        public void SetRegion(SkinningForm form)
        {
            
// Check Form
            if (form == null)
            {
                
return;
            }

            
// Get Form Size
            Size size = form.Size;
            
// Set Color Size
            Size cornerSize = new Size(9090);
            
// Create Region Handle
            IntPtr hRegion = NativeMethod.CreateRoundRectRgn(00, size.Width + 1, size.Height + 1, cornerSize.Width, cornerSize.Height);
            Region region = Region.FromHrgn(hRegion);
            
// Set Region
            form.Region = region;
            region.ReleaseHrgn(hRegion);
        }

这样我们就设置了我们的窗体样式,其中cornerSize我设置的比较大,这样显示的效果比较明显。显示的窗体如下:

这样的显示比较难看,这是因为我们还没有对窗体进行其他的绘画。当然我们也可以通过这个方法对窗体的显示进行其他的操作。下一篇将使用GDI+对窗体进行绘画,主要对窗体的边框进行设计。

本篇代码下载:SkinEngines20100322.rar

(四)--- 还窗体的新面貌

前一篇给窗体设置了Region,将窗体的FormBorderStyle设置成了None,然后修改了窗体的显示区域Region。一个本来完好的窗体让我们设置成为了一个空白的没有任何色彩的窗体,这对我们的界面开发好像是背到而行,有点南辕北辙了。其实不然,只有将窗体上的所有原有的信息给去除掉,才能还原窗体的本来面貌,给窗体一个新面貌。

这篇就对窗体的界面开发设计一个新面貌。

我在界面开篇的开篇就已经说过,界面开发其实就是修改窗体的两个区域,Client Area和None Client Area,如下图:

而我们现在已经将窗体修改成了没有任何信息的窗体,如下图:

现在我们要做的,就是在这个什么都没有的图上添加上我们自己的界面,将窗体的Client Area和None Client Area从新绘制让其有新的面貌。而他的绘制确实需要很多的GDI+知识。

Client Area的绘画很简单,主要就是对窗体的背景色进行修改,这个对于C#开发人员就是一句话的事情,设置窗体的背景色就可以了。代码如下:

this._parentForm.BackColor = this._engine.SkinColor.Back;

但是,对于None Client Area的绘画就比较麻烦,他不仅仅画的是颜色,还有窗体的标题栏、最大化、最小化、关闭按钮、窗体图标和窗体的边框,接下来就是一一对窗体的进行绘画。

窗体的标题栏分为两大部分:窗体的图标和窗体的标题,绘画这些的第一步都是对窗体的绘画区域的设置。找到绘画的区域,然后使用GDI+进行绘画,具体的过程就是这样,代码如下:

#region NcPaint
/// <summary>
/// NcPaint
/// </summary>
/// <param name="form"></param>
/// <returns></returns>
private bool NcPaint(SkinningForm form, SkinEngine engine)
{
    // Declared Filed
    bool result = true;
    IntPtr hdc = (IntPtr)0;
    Graphics g = null;
    Region region = null;
    IntPtr hrgn = (IntPtr)0;

    try
    {
        // Get Rect
        RECT rectScreen = new RECT();
        NativeMethod.GetWindowRect(_parentForm.Handle, ref rectScreen);
        Rectangle rectBounds = rectScreen.ToRectangle();
        rectBounds.Offset(-rectBounds.X, -rectBounds.Y);

        // prepare clipping
        Rectangle rectClip = rectBounds;
        region = new Region(rectClip);
        rectClip.Inflate(-engine.SkinAppearance.BorderWidth, -engine.SkinAppearance.BorderWidth);
        rectClip.Y += engine.SkinAppearance.CaptionHeight;
        rectClip.Height -= engine.SkinAppearance.CaptionHeight;

        // create graphics handle
        hdc = NativeMethod.GetDCEx(_parentForm.Handle, (IntPtr)0,
            (DCXFlags.DCX_CACHE | DCXFlags.DCX_CLIPSIBLINGS | DCXFlags.DCX_WINDOW));
        g = Graphics.FromHdc(hdc);

        // Apply clipping
        region.Exclude(rectClip);
        hrgn = region.GetHrgn(g);
        NativeMethod.SelectClipRgn(hdc, hrgn);

        if (_bufferGraphics == null || _currentCacheSize != rectBounds.Size)
        {
            if (_bufferGraphics != null)
                _bufferGraphics.Dispose();

            _bufferGraphics = _bufferContext.Allocate(g, new Rectangle(0, 0,
                        rectBounds.Width, rectBounds.Height));
            _currentCacheSize = rectBounds.Size;
        }

        // Get Caption Bounds
        Rectangle captionBounds = rectBounds;
        captionBounds.Height = this._engine.SkinAppearance.BorderWidth + this._engine.SkinAppearance.CaptionHeight;

        // Draw Caption
        engine.SkinAppearance.DrawCaptionBackground(g, captionBounds, this._formIsActive, this._engine);
        // Draw Caption Icon
        if (this._parentForm.ShowIcon && this._parentForm.Icon != null)
        {
            DrawIcon(g);
        }
        // Draw Caption Text
        DrawCaptionText(g, this._parentForm.Text, this._parentForm.Font);

        // Draw Caption Button
        DrawCaptionControlBox(g);

        // Draw Border
        engine.SkinAppearance.DrawBorder(g, rectBounds, engine);
    }
    catch
    {
        result = false;
    }

    // cleanup data
    if (hdc != (IntPtr)0)
    {
        NativeMethod.SelectClipRgn(hdc, (IntPtr)0);
        NativeMethod.ReleaseDC(_parentForm.Handle, hdc);
    }
    if (region != null && hrgn != (IntPtr)0)
        region.ReleaseHrgn(hrgn);

    if (region != null)
        region.Dispose();

    if (g != null)
        g.Dispose();
    return result;
}
#endregion

这个就完全绘制了窗体的边框。界面效果如下:

代码下载地址:SkinEngines20100324.rar

(五)--- 界面优化

在上一篇界面开发中,我讲解了将系统界面还原,还原窗体的本来面貌。但是有的博友提出窗体闪烁,这确实是个问题,原来自己开发的时候也是出现了这个问题。花了两天的时间,重要修改了个大概,将窗体绘画的次数和窗体的刷新程度进行了修改。首先看看效果:

这是主窗体,在主窗体中不仅修改了窗体的刷新率,而且添加了一个自定义的窗体按钮,使用了很多的颜色来显示,模仿了Foxmail的界面显示,但是对于除了主窗体外的其他窗体,这些是不存在的。如下图显示的子窗体:

实现的原理和原来的一样,只不过在原来绘画的基础上减少了绘画的内容和绘画区域的大小,这样窗体的界面效果就好多了。下一期将使用上面那个彩色的俺就对窗体进行修改变色。

本期代码如下:SkinEngines20100326.rar



从手机登录页面设计想到的
如何把无意识引入交互设计中
交互设计的真相
当视觉设计师遇上产品经理
手机交互设计原则
用户体验之网页板块设计
更多...   


以用户为中心的设计
可用性评估
Desktop及Web-based视觉设计
认知原理与设计应用
手机用户界面设计


北京 以用户为中心的界面设计
北京 用户体验& 界面设计
上海 华为 用户体验& 界面设计
深圳 用户体验& 界面设计
爱立信 以用户为中心的设计
北京 用户体验与界面设计
福州 以用户为中心的界面设计
更多...   
 
 
 
 

组织简介 | 联系我们 |   Copyright 2002 ®  UML软件工程组织 京ICP备10020922号

京公海网安备110108001071号