問題描述:
想在.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;
}
}
新聞熱點
疑難解答