zoukankan      html  css  js  c++  java
  • 一种用户小体验 从那里来就回到那里去

     各位都用过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

  • 相关阅读:
    单例模式
    Curator Zookeeper分布式锁
    LruCache算法原理及实现
    lombok 简化java代码注解
    Oracle客户端工具出现“Cannot access NLS data files or invalid environment specified”错误的解决办法
    解决mysql Table ‘xxx’ is marked as crashed and should be repaired的问题。
    Redis 3.0 Cluster集群配置
    分布式锁的三种实现方式
    maven发布项目到私服-snapshot快照库和release发布库的区别和作用及maven常用命令
    How to Use Convolutional Neural Networks for Time Series Classification
  • 原文地址:https://www.cnblogs.com/xdesigner/p/589969.html
Copyright © 2011-2022 走看看