• 一种用户小体验 从那里来就回到那里去


     各位都用过Word2000吧,它的用户界面中有个小动画,你按下Ctl+F弹出查找对话框时,会从右下角显示一个黑色的方框,然后快速移动和放大,最后才显示出查找对话框,当用户关闭查找对话框时刚才的动画就会倒放。

    这个用户界面的小体验不错,它清晰的表明了若使用鼠标点击操作时点击何处来打开查找对话框,帮助用户记忆操作过程,这个动画本身就是一个操作帮助和提醒。可以称之为从那里来就回到那里去的过程。

    于是我编写了一个 AnimatedRectDrawer 类型来模仿了这种用户体验,这个类型实际上是Win32API函数 DrawAnimatedRects 用C#的一个包装。它可以将子窗体和主窗体上的某个按钮或其他控件绑定,当用户点击按钮时,子窗体将从这个按钮上动态的弹出来,用户关闭子窗体时,子窗体将动态的收缩到按钮中。过程很形象,而且用户比较牢固的记下按钮和子窗体的关系。

    整个代码如下,在Win2000下调试成功。

    //#define DOTNET20

    using System;
    using System.Text;

    namespace XDesignerWindows32
    {
     
        
    //
        
    //      !!!!!!!!! 注意 !!!!!!!!!!!!!!!!
        
    //
        
    //.NET1.1的窗体关闭事件 Form.Closed 在 .NET2.0中是过时的。在.NET2.0环境中
        
    //
        
    // 应当使用 Form.FormClosed 事件,这两个事件名称和使用的委托类型都不一样,为此
        
    //
        
    // 定义一个名为 DOTNET20 的条件编译标志,若编译环境使用.NET1.1则不需要定义这个
        
    //
        
    // 条件编译变量,若编译环境使用 .NET2.0则建议定义这个条件编译标记,即在代码文件
        
    //
        
    // 的第一行添加    #define DOTNET20
        
    //
        
    // 由于.NET2.0保持兼容性还支持Form.Closed事件,因此当不定义这个条件编译标记而
        
    //
        
    // 使用 Form.Closed 事件仍然可以编译通过,但仍建议进行上述的处理。
        
    //
        
    // 袁永福( http://www.xdesigner.cn ) 2006-12-12
        
    //
        
    //
        
    //   !!!!!!!!!!!!!!! Notice !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        
    // 
        
    // Form.Close event used in .NET1.1 is old in .NET2.0 . In .NET2.0 , It is 
        
    //
        
    // replace by Form.FormClosed , The two event 's name and delegate type is 
        
    // 
        
    // different , so there are define a pre-compile flag named DOTNET20 , when 
        
    //
        
    // you compile this code use .NET1.1 , you did not define this pre-compile 
        
    //
        
    // flag , but when you compile use .NET2.0 , I advice you define this pre-compile
        
    //
        
    // flag , just add "#define DOTNET20" at the begin of this code file .
        
    //
        
    // For compatibility , .NET2.0 support Form.Close , so if you did not define this
        
    //
        
    // pre-compile flag and use Form.Close event , you can compile success , but I 
        
    //
        
    // still advice you define the DOTNET20 flag needed .
        
    //
        
    // yfyuan ( http://www.xdesigner.cn/default-eng.htm ) 2006-12-12
        
    //
     
        
    /// <summary>
        
    /// 绘制矩形动画的模块,本模块为Win32API函数 DrawAnimatedRects 的一个包装
        
    /// 
        
    /// Draw animate rectangle , this class is a package of Win32API 
        
    /// 
        
    /// function DrawAnimatedRects
        
    /// 
        
    /// </summary>
        
    /// <remarks>
        
    /// 编写 袁永福( http://www.xdesigner.cn ) 2006-12-12
        
    /// 
        
    /// Author yfyuan ( http://www.xdesigner.cn/default-eng.htm ) 2006-12-12
        
    /// </remarks>
        public class AnimatedRectDrawer
        {
            
    /// <summary>
            
    /// 注册项目类型
            
    /// 
            
    /// Information of regite form
            
    /// </summary>
            public class DrawInfoItem
            {
                
    /// <summary>
                
    /// 原始控件
                
    /// 
                
    /// Source Control
                
    /// </summary>
                public System.Windows.Forms.Control SourceControl = null;
                
    /// <summary>
                
    /// 原始区域
                
    /// 
                
    /// Source Rectangle
                
    /// </summary>
                public System.Drawing.Rectangle SourceRect = System.Drawing.Rectangle.Empty;
                
    /// <summary>
                
    /// 目标窗体
                
    /// 
                
    /// Desc Form object
                
    /// </summary>
                public System.Windows.Forms.Form Form = null;
                
    /// <summary>
                
    /// 对象额外数据
                
    /// 
                
    /// object's extern data
                
    /// </summary>
                public object Tag = null;
            }

            
    /// <summary>
            
    /// 初始化对象
            
    /// 
            
    /// Init object
            
    /// </summary>
            public AnimatedRectDrawer()
            {

    #if DOTNET20
                _FormClosed 
    = new System.Windows.Forms.FormClosedEventHandler(Form_Closed);
    #else
                _FormClosed 
    = new System.EventHandler(Form_Closed);
    #endif
                _FormLoad 
    = new EventHandler(Form_Load);
            }
            
    /// <summary>
            
    /// 添加项目
            
    /// 
            
    /// Add item
            
    /// </summary>
            
    /// <param name="ctl">原始控件 Source control</param>
            
    /// <param name="rect">原始矩形 source rectangle</param>
            
    /// <param name="frm">目标窗体 desc form</param>
            
    /// <returns>新增的项目对象 the item instance added </returns>
            public DrawInfoItem Add(
                System.Windows.Forms.Control ctl,
                System.Drawing.Rectangle rect, 
                System.Windows.Forms.Form frm)
            {
                DrawInfoItem item 
    = GetItem(frm);
                
    if (item == null)
                {
                    item 
    = new DrawInfoItem();
                    myItems.Add(item);
                    frm.Load 
    += _FormLoad;
    #if DOTNET20
                    frm.FormClosed 
    += _FormClosed;
    #else
                    frm.Closed 
    += _FormClosed;
    #endif
                }
                item.SourceControl 
    = ctl;
                item.SourceRect 
    = rect;
                item.Form 
    = frm;
                
    return item;
            }
            
    /// <summary>
            
    /// 添加项目 
            
    /// 
            
    /// Add item
            
    /// </summary>
            
    /// <param name="ctl">原始控件 source control</param>
            
    /// <param name="frm">目标窗体 desc form</param>
            
    /// <returns>新增的项目对象 the item instance added</returns>
            public DrawInfoItem Add(
                System.Windows.Forms.Control ctl,
                System.Windows.Forms.Form frm)
            {
                
    return Add(ctl, System.Drawing.Rectangle.Empty, frm);
            }
            
    /// <summary>
            
    /// 删除所有项目
            
    /// </summary>
            public void Clear()
            {
                myItems.Clear();
            }
            
    /// <summary>
            
    /// 为窗体查找项目对象
            
    /// Search item for specify form instance
            
    /// </summary>
            
    /// <param name="frm">窗体对象 form instance</param>
            
    /// <returns>
            
    /// 找到的项目对象,若未找到则返回空引用
            
    /// item instance finded , if can not find then return null 
            
    /// </returns>
            public DrawInfoItem GetItem(System.Windows.Forms.Form frm)
            {
                
    foreach (DrawInfoItem item in myItems)
                {
                    
    if (item.Form == frm)
                        
    return item;
                }
                
    return null;
            }

            
    #region 内部代码群 Internal code **************************************
            
    /// <summary>
            
    /// 注册项目列表
            
    /// 
            
    /// registe information list
            
    /// </summary>
            private System.Collections.ArrayList myItems = new System.Collections.ArrayList();
            
    /// <summary>
            
    /// 窗体关闭处理程序委托对象
            
    /// 
            
    /// the delegate instance handle form close event 
            
    /// </summary>
    #if DOTNET20
            
    private System.Windows.Forms.FormClosedEventHandler _FormClosed = null;
    #else
            
    private System.EventHandler _FormClosed = null;
    #endif
            
    /// <summary>
            
    /// 窗体打开处理程序委托对象
            
    /// 
            
    /// the delegate instance handle form load event
            
    /// </summary>
            private System.EventHandler _FormLoad = null;
            
    /// <summary>
            
    /// 窗体打开处理过程 the function handle form load event
            
    /// </summary>
            
    /// <param name="sender"></param>
            
    /// <param name="e"></param>
            private void Form_Load(object sender, System.EventArgs e)
            {
                DrawInfoItem item 
    = GetItem((System.Windows.Forms.Form)sender);
                
    if (item != null)
                {
                    InnerDraw(item, 
    true);
                }

            }
            
    /// <summary>
            
    /// 窗体关闭处理过程 the function handle form close event
            
    /// </summary>
            
    /// <param name="sender"></param>
            
    /// <param name="e"></param>
    #if DOTNET20
            
    private void Form_Closed(
                
    object sender, 
                System.Windows.Forms.FormClosedEventArgs e)
    #else
            
    private void Form_Closed( object sender , System.EventArgs e )
    #endif
            {
                DrawInfoItem myItem 
    = GetItem((System.Windows.Forms.Form)sender);
                
    if (myItem != null)
                {
                    myItems.Remove(myItem);
                    InnerDraw(myItem, 
    false);
                }
            }
            
    /// <summary>
            
    /// 内部的绘制动画的过程 interior function to draw animate rectangle
            
    /// </summary>
            
    /// <param name="item">绘制信息对象 registe information</param>
            
    /// <param name="bolOpen">
            
    /// 是否显示为打开过程 
            
    /// draw animate as open form
            
    /// </param>
            private void InnerDraw(DrawInfoItem item, bool bolOpen)
            {
                
    if (item == null)
                    
    return;
                
                
    if (item.SourceControl == null || item.Form == null)
                    
    return;

                System.Drawing.Rectangle srect 
    = this.GetScreenRect(
                    item.SourceRect, 
                    item.SourceControl);

                
    if (srect.IsEmpty)
                    
    return;

                System.Drawing.Rectangle trect 
    = this.GetScreenRect(
                    System.Drawing.Rectangle.Empty,
                    item.Form);

                
    if (trect.IsEmpty)
                    
    return;

                RECT rect1 
    = new RECT();
                rect1.left 
    = srect.Left;
                rect1.top 
    = srect.Top;
                rect1.right 
    = srect.Right;
                rect1.bottom 
    = srect.Bottom;

                RECT rect2 
    = new RECT();
                rect2.left 
    = trect.Left;
                rect2.top 
    = trect.Top;
                rect2.right 
    = trect.Right;
                rect2.bottom 
    = trect.Bottom;

                
    if (bolOpen)
                    DrawAnimatedRects(item.Form.Handle, IDANI_CAPTION, 
    ref rect1, ref rect2);
                
    else
                    DrawAnimatedRects(item.Form.Handle, IDANI_CAPTION, 
    ref rect2, ref rect1);
            }

            
    private System.Drawing.Rectangle GetScreenRect(
                System.Drawing.Rectangle rect, 
                System.Windows.Forms.Control ctl)
            {
                System.Drawing.Rectangle result 
    = System.Drawing.Rectangle.Empty;
                
    if (ctl == null)
                {
                    result 
    = rect;
                }
                
    else
                {
                    result 
    = GetControlBounds(ctl);
                    
    if (rect.IsEmpty)
                        result 
    = GetControlBounds(ctl);
                    
    else
                    {
                        result 
    = rect;
                        result.Location 
    = ctl.PointToScreen(result.Location);
                    }
                }
                
    return result;
            }
            
    /// <summary>
            
    /// 获得控件在屏幕中的矩形区域 get a control's bounds in screeen
            
    /// </summary>
            
    /// <param name="ctl">控件对象 control instance</param>
            
    /// <returns>矩形区域对象 bounds in screen</returns>
            private System.Drawing.Rectangle GetControlBounds(System.Windows.Forms.Control ctl)
            {
                
    if (ctl == null)
                    
    return System.Drawing.Rectangle.Empty;
                
    if (ctl.IsHandleCreated)
                {
                    RECT rect 
    = new RECT();
                    
    if (GetWindowRect(ctl.Handle, ref rect))
                    {
                        
    return new System.Drawing.Rectangle(
                            rect.left, 
                            rect.top, 
                            rect.right 
    - rect.left, 
                            rect.bottom 
    - rect.top);
                    }
                }
                
    return ctl.Bounds;
            }

            
    #endregion

            
    #region 声明Win32API函数以及结构 declare Win32API function and structure

            
    private const int IDANI_CAPTION = 0x3;
            
    private const int IDANI_CLOSE = 0x2;
            
    private const int IDANI_OPEN = 0x1;


            
    private struct RECT
            {
                
    public int left;
                
    public int top;
                
    public int right;
                
    public int bottom;
            }

            [System.Runtime.InteropServices.DllImport(
    "user32.dll")]
            
    private static extern bool DrawAnimatedRects(
                IntPtr hwnd, 
                
    int Ani, 
                
    ref RECT from, 
                
    ref RECT to);
            
            [System.Runtime.InteropServices.DllImport(
    "user32.dll")]
            
    private static extern bool GetWindowRect(IntPtr hwnd, ref RECT rect);

            
    #endregion
        }
    //public class AnimatedRectDrawer


        
    /// <summary>
        
    /// 测试 AnimatedRectDrawer 的功能的一个窗体
        
    /// 
        
    /// A form which test AnimatedRectDrawer's function
        
    /// </summary>
        public class AnimatedRectDrawerTestForm : System.Windows.Forms.Form
        {
            
    public AnimatedRectDrawerTestForm()
            {
                
    this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
                
    this.Text = "从那里来就回到那里去 - Where come from , where come back";
                
                btn 
    = new System.Windows.Forms.Button();
                
    this.Controls.Add(btn);
                btn.Text 
    = "Open";
                btn.Location 
    = new System.Drawing.Point(3030);
                btn.Click 
    += new EventHandler(btn_Click);
            }

            
    private AnimatedRectDrawer drawer = new AnimatedRectDrawer();
            System.Windows.Forms.Button btn 
    = null;

            
    void btn_Click(object sender, EventArgs e)
            {
                System.Windows.Forms.Form frm 
    = new System.Windows.Forms.Form();
                drawer.Add(btn, frm);
                frm.Owner 
    = this;
                frm.Show();
            }

            
    /// <summary>
            
    /// Entrance function
            
    /// </summary>
            [STAThread]
            
    static void Main()
            {
                System.Windows.Forms.Application.Run(
    new AnimatedRectDrawerTestForm());
            }
        }
    //public class AnimatedRectDrawerTestForm : System.Windows.Forms.Form
    }



    袁永福 ( http://www.xdesigner.cn ) 2006-12-12

  • 相关阅读:
    铁老大:不管你信不信,我是信了的NET代码版
    如何去掉字符串中的空格(转)
    DNN 社交挂件模块和DNN天气模块
    top、postop、scrolltop、scrollHeight、offsetHeight详解以及各浏览器显示效果差异
    vs2008视图菜单栏没有工具箱的解决办法
    DNN资源收集
    LINQ如何实现模糊查询
    Linq to excel
    前端各种出色的弹出层
    repo init 中指定manifest和branch的含义
  • 原文地址:https://www.cnblogs.com/xdesigner/p/589969.html
Copyright © 2020-2023  润新知