There can be no Triumph without Loss,No Victory without Suffering,No Freedom without Sacrifice.
All you have to decide is what to do with the time that is given to you.
Get busy Living, or Get busy Dying?
  首页 | 留言给我 | 订阅 Rss | CLI | 黄白之恋 Posts:158   Hits: 1326867    Comments: 168    
 日历归档
<<  <  2018 - 11  >  >>
SuMoTuWeThFrSa
    123
45678910
11121314151617
18192021222324
252627282930
 About Me
 Name: ZhangSichu
 Sex: Male
 Age: 32
 Email: ZhangSichu@gmail.com
 MSN: ZhangSichu@hotmail.com
 Home: ZhangSichu.com
 WeiBo: weibo.com/zhangsichu
 个人推荐
 分类归档
  ·C++/C(5)  RSS
  ·软件工程(1)  RSS
  ·杂事/随感(26)  RSS
  ·.Net/Java(30)  RSS
  ·面向对象程序设计(5)  RSS
  ·汇编/破解(0)  RSS
  ·平面设计(3)  RSS
  ·SQL(5)  RSS
  ·COM/COM+(2)  RSS
  ·Web开发(81)  RSS
 My Friends
Back Forward Refresh Home 2018年11月15日 星期四 RSS CLI Mine Sweeper. In Javascript.

  将拖拽进行到底
字体大小 [ ]

问题描述:
  想在.Net下实现对一些非规则窗体,没有Caption,FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;窗体的拖拽,最小化,最大化,特殊操作的实现(如图1所示)。在黄色的区域即区域1里实现对窗体的拖拽操作,在橙色区域即区域2里实现对窗体的最小化操作,在蓝色区域即区域3里实现对窗体的关闭操作,在绿色区域即区域4里实现对窗体的特殊操作(如双倍窗体)。

Click to Open in New Window
   (图1)

问题实现:
  第一种方法 添加Label为Label添加Click事件。(如图2所示)
如果要用这种方法实现,就要为每一个颜色区域进行切图,并要保证有正确的切图长和宽,然后设置Label的背景为这个图片。

Click to Open in New Window
   (图2)
处理他们的Click事件,拖拽处理MouseDown MouseUp事件。
  第二中方法 不添加Label只处理鼠标事件,判断鼠标的位置然后决定执行什么操作,这种方法很耗费资源,每次鼠标点击就要判断,鼠标是否在某个区域然后决定是否要处理。不过这个处理用多态包装了。程序看起来比较整齐。
//定义常量
    private Point point;
    private const int dragMove=172;
    private const int dragMin=72;
    private const int dragClose=72;
    private const int dragDouble=78;
    private const int dragHeight=29;
    private MouseHandleEnum dragEnum;
    
//定义MouseDown事件
private void DragMain_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
    {
      point.X=e.X;
      point.Y=e.Y;
      if(e.Y<dragHeight)
      {
        if(e.X<dragMove)
        {
          dragEnum = MouseHandleEnum.Move;
          return;
        }
        if(e.X<dragMove+dragMin)
        {
          dragEnum = MouseHandleEnum.Min;
          return;
        }
        if(e.X<dragMove+dragMin+dragClose)
        {
          dragEnum = MouseHandleEnum.Close;
          return;
        }
        if(e.X<dragMove+dragMin+dragClose+dragDouble)
        {
          dragEnum = MouseHandleEnum.Double;
          return;
        }  
      }

    }

    
//定义MouseUp事件
private void DragMain_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
    {
      point.X=e.X-point.X;
      point.Y=e.Y-point.Y;
      IDragMouse idragMouse;
      switch(dragEnum)
      {
        case MouseHandleEnum.Move :
          idragMouse = new MouseMove(point,this);
          break;
        case MouseHandleEnum.Min :
          idragMouse = new MouseMin(point,this);
          break;
        case MouseHandleEnum.Close :
          idragMouse = new MouseClose(point,this);
          break;
        case MouseHandleEnum.Double :
          idragMouse = new MouseDouble(point,this);
          break;
        default:
          idragMouse = null;
          break;
      }
      if(idragMouse!=null)
        idragMouse.MouseDo();
    }
  }
//定义基类
namespace DragMouse
{
public enum MouseHandleEnum
{
   None=0,
   Move=1,
   Min=2,
   Close=3,
   Double=4,
}
public class DragMouseBase
  {
    protected Point point;
    public Form form;
    public DragMouseBase(Point point, Form form)
    {
      this.point = point;
      this.form = form;
    }
  }
}
//定义接口
namespace DragMouse
{
  /// <summary>
  ///
  /// </summary>
  public interface IDragMouse
  {
    void MouseDo();
  }
}
//拖拽操作
namespace DragMouse
{
  /// <summary>
  ///
  /// </summary>
  public class MouseClose : DragMouseBase,IDragMouse
  {
    public MouseClose(Point point,Form form):base(point,form)
    {
      //
      // TODO: Add constructor logic here
      //
    }
    #region IDragMouse Members

    public void MouseDo()
    {
      Application.Exit();
      // TODO: Add MouseClose.MouseDo implementation
    }

    #endregion
  }
}
//其他操作类似。
  第三种方法 是用责任链这个设计模式来包装鼠标的点击操作,把操作分配到各个责任链的节点上,是程序更加面向对象,有更好的扩展性。


//两个鼠标事件
private void DragMain_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
    {
      request.GetInformation(e.X,e.Y);

    }


private void DragMain_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
    {
      request.SetScreenPoint(e.X,e.Y);

    }

//封装的请求类
  public class Request
  {
    public int iScreenX;
    public int iScreenY;

    public int eX;
    public int eY;

    public readonly int yHigh;
    public readonly int dragLength;
    public readonly int minLength;
    public readonly int closeLength;
    public readonly int doubleLength;

    private DragHandler dragHandler;
    private MinHandler minHandler;
    private CloseHandler closeHandler;
    private DoubleHandler doubleHandler;

    public Form parentForm;

    public void SetScreenPoint(int iX,int iY)
    {
      iScreenX = iX;
      iScreenY = iY;
      dragHandler.HandleRequest(this);
    }

    public void GetInformation(int ex,int ey)
    {
      eX=ex;
      eY=ey;
    }

    public Request(int yhigh,int draglength,Form form)
    {
      yHigh = yhigh;
      dragLength = draglength;
      parentForm = form;
      dragHandler = new DragHandler();
      minHandler =new MinHandler();
      closeHandler = new CloseHandler();
      doubleHandler = new DoubleHandler();

      dragHandler.SetSuccessor(minHandler);
      minHandler.SetSuccessor(closeHandler);
      closeHandler.SetSuccessor(doubleHandler);
    }

    
public Request(int yhigh,int draglength,int minlength,Form form):this(yhigh,draglength,form)
    {
      minLength = minlength;
    }

    
public Request(int yhigh,int draglength,int minlength,int closelength,Form form):this(yhigh,draglength,minlength,form)
    {
      closeLength = closelength;
    }

    
public Request(int yhigh,int draglength,int minlength,int closelength, int doublelength , Form form):this(yhigh,draglength,minlength,closelength,form)
    {
      doubleLength = doublelength;
    }

  }
//拖拽操作
  public class DragHandler : Handler
  {
    override public void HandleRequest(Request request)
    {
      // determine if we can handle the request
      if ((request.eY<request.yHigh)&&(request.eX<request.dragLength)) // some complex decision making!
      {
        request.parentForm.Left += request.iScreenX-request.eX;
        request.parentForm.Top += request.iScreenY-request.eY;

        // request handling code goes here
      }
      else
      {
        // not handled here - pass on to next in the chain
        if (successorHandler != null)
          successorHandler.HandleRequest(request);
      }
    }
  }
//其他操作类似

  第四种方法 (只是有想法还没有找到成功的实现办法)
  在MFC中可以用PostMessage或者SendMessag发消息,当鼠标单击,但不在窗体的CaptionTitle上时,发一个消息告诉系统鼠标在CaptionTitle(每个窗口自己TitleBar)上,这样窗口的拖拽就可以由系统托管了。现在实现了在窗口中任意位置单击鼠标拖拽窗体。但是没有实现上面要求的那些多样化操作。

  if(point.y<this->m_Height)
  {
//发消息给系统伪装鼠标在Caption Bar 上。
    if(point.x<this->m_Drag)
    {
      PostMessage(WM_NCLBUTTONDOWN,
        HTCAPTION,
        MAKELPARAM(point.x,point.y));
      return;
    }
    if(point.x<this->m_Drag+this->m_Min&&point.x>this->m_Drag)
    {
      PostMessage(WM_NCLBUTTONDOWN,
        HTMINBUTTON,
        MAKELPARAM(point.x,point.y));
      return;
    }
    if(point.x<this->m_Drag+this->m_Min+this->m_Close&&point.x>this->m_Drag+this->m_Min)
    {
      PostMessage(WM_NCLBUTTONDOWN,
        HTCLOSE,
        MAKELPARAM(point.x,point.y));
      return;
    }
    if(point.x<this->m_Drag+this->m_Min+this->m_Close+this->m_Double&&point.x>this->m_Drag+this->m_Min+this->m_Close)
    {
      CRgn *rgn = new CRgn();
      CRect *rect =new CRect();
      this->GetWindowRect(*rect);
      this->SetWindowRgn(*rgn,true);
      return;
    }

  }
  遗憾
第四种方法是效率最高的,但是没有完全搞出来。
本文所有事例程序在中文WindowsXp Sp2 + VC7 下编译通过

File: 本文源程序
  Posted @ 8/21/2005 11:23:11 PM | Hits (57422) | Comments (1

  Comment
 #re:将拖拽进行到底  10/25/2006 12:48:22 AM  Guy...you are real...i like you...write me :) i want to see you...
  Post Comment
标题 *
作者 *
密码 记住我
评论 *
    


Stable in Firefox 1.5 2.0Stable in IE6 IE7Stable in MozillaStable in Netscape
ZhangSichu.com V0.1.7507
Powered By ZhangSichu
Copyright © ZhangSichu
Download ZhangSichu.com source code. Download source code