zyzx的小窝

C/C++,GUI,个人移动存储,zyzx_lsl@163.com

 

N(1)Tools方法:用户工具条功能实现

tag:C++、接口编程、设计方法 、工具条

/* Create by  zyzx
* Created 2008-05-18
* Modified 2008-05-25
*/
       
         呵呵,原本想取题为Tools模式的,但想想只是一个惯用法还谈不上一种设计模式。。
         好了,言归正传,做用户界面的时候通常会碰到这个问题:比如,我们为界面做了一系列的工具栏按钮,当用户点选按钮后会设置程序进入某个状态,在这种状态下,软件做出相应反馈。 如果只做一个或几个工具,按过程式的方法,还勉强可以接受,但不利于扩展。如果做成软件,一般可不只几个工具供用户选择了哦。。。
         Tools模式,有前人发表过的思想,但偶楞是没找着,还是楞楞看开源代码才明白啥回事的。。。

         举个简单的例子:就拿我们常用的Windows自带的画图工具来说,选中左边的工具栏框选项,在绘图区域按下左键拖动鼠标,是在屏幕上绘制虚线框,执行选框操作;选中直线,在绘图区域按下左键拖动鼠标,是绘制直线,执行绘直线操作;选中橡皮,在绘图区域按下左键拖动鼠标,执行擦除操作………

        这里由于跟窗口(GDI对象)有关,从简来说:无非是左键按下啊,拖动啊,再到释放左键执行操作,或是右键的啥啊啥的。。他们的共通之处:(由于与DC相关,参数可酌情考虑)
       Class CUIToolsBase : public XXX(?)
       {
       public:
              virtual void OnMouseDown( UINT nFlags, CPoint point ) = 0;       //鼠标点下,参数按MFC格式
              virtual void OnMouseUp( UINT nFlags, CPoint point ) = 0;            //鼠标弹起
              virtual void OnMouseMove( UINT nFlags, CPoint point ) = 0;       //鼠标移动
              virtual void OnMouseDraging( UINT nFlags, CPoint point ) = 0;       //鼠标拖动
            …………
        public:
              CUIToolsBase ();
              virtual ~CUIToolsBase();
       protected:
              virtual void Execute() = 0;                                                            //执行本Tool的操作
       };
而其他的Tool都从本类继承而来。
   
比如选择框的Tool
     CUIToolsSelect : public CUIToolsBase
     {
     public:
          virtual void OnMouseDown( UINT nFlags, CPoint point )                      //实现代码最好写在cpp文件中,懒下
          {
                 if( 左键 == nFlags /*&& 要判断键盘(Ctrl,Shift,Alt )状态吗 */){
                        m_StartPt = point ;
                        m_EndPt = point;
                 }
          }     
          virtual void OnMouseDraging( UINT nFlags, CPoint point )
          {
                if( 左键 == nFlags /*&& 要判断键盘(Ctrl,Shift,Alt )状态吗 */){
                        if( !m_DrawRect ){
                              XXX( m_StartPt, point );                 //异或方式在CDC上绘制矩形框,第一次绘制
                        }else{
                              XXX( m_StartPt, m_EndPt );          //异或方式在CDC上清除上一次绘制的矩形框
                              XXX( m_StartPt, point );                //异或方式在CDC上绘制当前矩形框
                        }
                        m_EndPt = point;
                 }
            }
           virtual void OnMouseUp( UINT nFlags, CPoint point )
           {
                if( 左键 == nFlags /*&& 要判断键盘(Ctrl,Shift,Alt )状态吗 */){
                        if ( m_DrawRect ){
                                 XXX( m_StartPt, m_EndPt );      //异或方式在CDC上清除上一次绘制的矩形框
                                 m_EndPt = point
                                 m_DrawRect = false;
                                 Execute();
                         }
                  }
            }
              
      public:
            CUIToolsSelect () { Init(); }
            virtual ~CUIToolsSelect (){ }

      protected:
            void Init() { m_StarPt = ??; m_EndPt = ??; m_DrawRect = false; }
            virtual void Execute()
            {
                   XXXX( m_StartPt, m_EndPt );             //执行选择操作
                   //这里也可以按Command模式只发出命令
            }
     
      private:
                CPoint m_StartPt;            //启始点
                CPoint m_EndPt;             //结束点
            bool     m_DrawRect;       //是否已经绘制矩形框标志,初始化为false!
      };
     
如下图:
Tools方法08-05-23.png

在要设置Tools的窗口内作如下处理:
        CWorkWnd : public XXXX
        {
        public:
              构造,析构......
              enum{
                   UITOOLS_UNKNOW = 0,
                   UITOOLS_SELECT,
                   UITOOLS_ERASE,
                   UITOOLS_LINE,
                   ......
                   UITOOLS_COUNT = ?
              }
        public:
              void SetCurrentTool( int tool ){                                          // 外部调用此方法设置Tool
                     XXXXX                                                                         // 相关前处理
                     switch( tool ) {
                     case UITOOLS_SELECT:
                           DoSetCurrentTool( new CUIToolsSelect() );
                           break;
                     case UITOOLS_ERASE:
                           DoSetCurrentTool( new CUIToolsErase() );
                           break;
                     case UITOOLS_LINE:
                           DoSetCurrentTool( new CUIToolsLine() );
                           break;
                     default:
                           break;
                     }
            }
       protected:
              void OnMouseDown( UINT nFlags, CPoint point ){
                     if ( m_CurrentTool ) {
                             m_CurrentTool->OnMouseDown( nFlags, point );
                     }
              }
              void OnMouseUp( UINT nFlags, CPoint point ) {
                     if ( m_CurrentTool ) {
                              m_CurrentTool->OnMouseUp( nFlags, point );
                     }
              }
              void OnMouseMove( UINT nFlags, CPoint point ) {
                      if ( m_CurrentTool ) {
                              m_CurrentTool->OnMouseMove( nFlags, point );
                      }
              }
              void OnMouseDraging( UINT nFlags, CPoint point ){
                      if( m_CurrentTool ) {
                              m_CurrentTool->OnMouseDraging( nFlags, point );
                      }
              }
       protected:
              void DoSetCurrentTool( CUIToolsBase* tool ){
                      if ( m_CurrentTool ) delete m_CurrentTool;
                      m_CurrentTool = tool;
               }
       ......
       private:
               CUIToolsBase*               m_CurrentTool;                      // 只关联到接口,运行时指定对象
       }

总结:
        此方法思路比较简单:无非是先定义一系列接口,在某个模块( 小到类,函数)中使用接口,执行动作由运行时的实际对象决定。关于这种方式在实际中会碰到很多类似的问题。

扩展:
        为软件建立统一的Tools管理类,支持多个工具条。。。

posted on 2009-04-27 17:00 zyzx 阅读(567) 评论(0)  编辑 收藏 引用 所属分类: C/C++体会


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理


导航

统计

常用链接

留言簿(1)

随笔分类

随笔档案

常用链接

搜索

最新评论

阅读排行榜

评论排行榜