C#中勢將表單拖拽進行到底

來源:互聯網
上載者:User

  問題描述: 

  想在.Net下實現對一些非規則表單,沒有Caption,FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;表單的拖拽,最小化,最大化,特殊操作的實現(如圖1所示)。在黃色的地區即地區1裡實現對表單的拖拽操作,在橙色地區即地區2裡實現對表單的最小化操作,在藍色地區即地區3裡實現對表單的關閉操作,在綠色地區即地區4裡實現對表單的特殊操作(如雙倍表單)。
  

(圖1) 

  問題實現:

  第一種方法:添加Label為Label添加Click事件。(如圖2所示) 如果要用這種方法實現,就要為每一個顏色地區進行切圖,並要保證有正確的切圖長和寬,然後設定Label的背景為這個圖片。

                    (圖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;
   }
  
   }



相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.