




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)
文檔簡介
在運行時通過鼠標(biāo)拖動移動控件位置(c#)前些日子因為工作需要想了解有關(guān)于在C#下實現(xiàn)運行時鼠標(biāo)移動控件的方法,Google了一下還真找到了一個帖子,粗略看去代碼還真不少,感覺有點復(fù)雜的樣子,因為當(dāng)時手頭上還有點別的事情,沒來得及細(xì)看,就把帖子轉(zhuǎn)到了自己的blog里面收藏。周末晚上沒事,抽時間看了一下程序,發(fā)現(xiàn)只能以Form為容器進行操作(因為使用了Form的一些屬性來確定控件位置),不完全符合自己的需要,而且作者的實現(xiàn)代碼似乎多了一點,就自己琢磨著怎么給精簡一下,后來竟然把幾乎把大部分代碼給刪掉了,實現(xiàn)方式也有不同,也可以在Form之外的其它容器內(nèi)進行組件運行時拖動。為了程序可讀性,暫未把改變控件大小的代碼加進來,但基本原理和移動控件位置也相差不遠(yuǎn),稍晚一點再添加進來。///<summary>
///使窗口的中的指定控件支持運行時移動
///TODO:運行時縮放
///</summary>
publicclassControlMoveResize
{
#region私有成員
boolIsMoving=false;
PointpCtrlLastCoordinate=newPoint(0,0);
PointpCursorOffset=newPoint(0,0);
PointpCursorLastCoordinate=newPoint(0,0);
privateControlctrl=null;
privateScrollableControlContaine=null;
#endregion
#region私有方法
///<summary>
///在鼠標(biāo)左鍵按下的狀態(tài)記錄鼠標(biāo)當(dāng)前的位置,以及被移動組件的當(dāng)前位置
///</summary>
///<paramname="sender"></param>
///<paramname="e"></param>
privatevoidMouseDown(objectsender,MouseEventArgse)
{
if(Containe==null)
{
return;
}
if(e.Button==MouseButtons.Left)
{
IsMoving=true;
pCtrlLastCoordinate.X=ctrl.Left;
pCtrlLastCoordinate.Y=ctrl.Top;
pCursorLastCoordinate.X=Cursor.Position.X;
pCursorLastCoordinate.Y=Cursor.Position.Y;
}
}
privatevoidMouseMove(objectsender,MouseEventArgse)
{
if(Containe==null)
{
return;
}
if(e.Button==MouseButtons.Left)
{
if(this.IsMoving)
{
PointpCursor=newPoint(Cursor.Position.X,Cursor.Position.Y);
pCursorOffset.X=pCursor.X-pCursorLastCoordinate.X;
pCursorOffset.Y=pCursor.Y-pCursorLastCoordinate.Y;
ctrl.Left=pCtrlLastCoordinate.X+pCursorOffset.X;
ctrl.Top=pCtrlLastCoordinate.Y+pCursorOffset.Y;
}
}
}
privatevoidMouseUp(objectsender,MouseEventArgse)
{
if(Containe==null)
{
return;
}
if(this.IsMoving)
{
if(pCursorOffset.X==0&&pCursorOffset.Y==0)
{
return;
}
if((pCtrlLastCoordinate.X+pCursorOffset.X+ctrl.Width)>0)
{
ctrl.Left=pCtrlLastCoordinate.X+pCursorOffset.X;
}
else
{
ctrl.Left=0;
}
if((pCtrlLastCoordinate.Y+pCursorOffset.Y+ctrl.Height)>0)
{
ctrl.Top=pCtrlLastCoordinate.Y+pCursorOffset.Y;
}
else
{
ctrl.Top=0;
}
pCursorOffset.X=0;
pCursorOffset.Y=0;
}
}
#endregion
#region構(gòu)造函數(shù)
///<summary>
///獲取被移動控件對象和容器對象
///</summary>
///<paramname="c">被設(shè)置為可運行時移動的控件</param>
///<paramname="parentContain">可移動控件的容器</param>
publicControlMoveResize(Controlc,ScrollableControlparentContain)
{
ctrl=c;
this.Containe=parentContain;
ctrl.MouseDown+=newMouseEventHandler(MouseDown);
ctrl.MouseMove+=newMouseEventHandler(MouseMove);
ctrl.MouseUp+=newMouseEventHandler(MouseUp);
}
#endregionC#基礎(chǔ)系列:開發(fā)自己的窗體設(shè)計器(總綱)我所處的行業(yè),所使用的業(yè)務(wù)系統(tǒng)都不大,但是個性需求極其多,每個地區(qū),每家公司都可能存在很大的差別。所以我就想能夠弄一個類似于vs2005的WinForm窗體設(shè)計器的開發(fā)平臺,讓用戶拖拖拽拽就可以添加自己需要的控件,或者刪除不需要的控件,從而完成大部分的工作,實現(xiàn)功能的擴展,而我需要做的,只不過是寫寫插件代碼。
這種類型的系統(tǒng)目前已經(jīng)有很多,但是那些都是屬于別人的,即使我能夠免費下載到一個,也不能完全按照我自己的想法去修修改改。所以我就想自己寫一個。目前已經(jīng)實現(xiàn)了很多的東西,但是在整體的架構(gòu)上,我總覺得不行,所以希望以這系列的文章,來和各位進行交流。我本系列的文章中,所涉及的都是實現(xiàn)這么個系統(tǒng)所使用到的關(guān)鍵技術(shù)。并提供可調(diào)試的代碼。希望能夠得到各位的大力拍磚。
可能有哥們會罵,為什么不直接使用vs2005中的System.Component.Design下的東西就可以直接實現(xiàn)控件的拖拽。當(dāng)然了,這是可以的,就連大名鼎鼎的SharpDevelop都是使用這玩意。不過自己設(shè)計這些東西還是很有意思的!
本系列目錄:1、在容器上拖動鼠標(biāo)增加控件;2、實現(xiàn)控件的選擇;3、實現(xiàn)控件的拖動;4、控件的排列算法(左對齊,中間對齊等等);5、PropertyGrid顯示中文屬性名;6、Undo和Redo的實現(xiàn);7、Winform中自定義快捷鍵的實現(xiàn)技巧;8、一種實現(xiàn)多語言的笨方法(適合中國人);9、ToolBox的實現(xiàn);10、工具箱,設(shè)計器,屬性等的交互。經(jīng)常進行圖形界面設(shè)計的編程者肯定知道,控件在設(shè)計的時候才能隨意拖動,運行的時候就不能拖動了.你肯定會問:運行時能隨意拖動控件嗎?答案是肯定的,我們的項目涉及到了這一點,我已經(jīng)實現(xiàn)了,實際上很簡單的喲.我就拿出來給你們show一下,哈哈,各位高手不要笑我喲.
我們先從簡單的入手,一步一步的來吧:
首先,新建一個Form1,拖進去一個label1,text為:鼠標(biāo)拖動控件練習(xí).接下來就是為它注冊事件了,這里我們注冊的是label1_MouseUp,label1_MouseDown兩個事件.在實現(xiàn)注冊事件的代碼前要先定義一個Point對象(全局),
private
Point
mouse_offset;用來記錄鼠標(biāo)位置,以便平移鼠標(biāo)位置.下面是label1_MouseDown的代碼:private
void
label1_MouseDown(objectsender,
MouseEventArgse){mouse_offset
=
new
Point(-e.X,-e.Y);}是不是非常easy喲.下面是label1_MouseUp的代碼:Privatevoidlabel1_MouseUp(objectsender,MouseEventArgse){if(e.Button==MouseButtons.Left){PointmousePos=Control.MousePosition;mousePos.Offset(mouse_offset.X,mouse_offset.Y);((Control)sender).Location=((Control)sender).Parent.PointToClient(mousePos);}}這個比較復(fù)雜,有必要介紹下,PointmousePos=Control.MousePosition;定義一個Point,它包含鼠標(biāo)光標(biāo)相對于屏幕左上角的坐標(biāo)。此時記錄的是當(dāng)前鼠標(biāo)的位置,也就是最后放控件的位置.
mousePos.Offset(mouse_offset.X,mouse_offset.Y);是一個方法,
Point.Offset(Int32,Int32)將此Point平移指定的量。}((Control)sender).Location=((Control)sender).Parent.PointToClient(mousePos);這個里面的sender大家應(yīng)該很清楚吧,就是觸發(fā)事件的label1嘍,((Control)sender).Location
這句話就是指定label1的位置,((Control)sender).Parent當(dāng)然就代表當(dāng)前的Form1了,如果Form1嵌套在另外一個Form1里面,那么后面可以在有一個.Parent,即:((Control)sender).Parent.Parent,.......依次類推嘍.......Control.PointToClient方法,將指定屏幕點的位置計算成工作區(qū)坐標(biāo)。參數(shù)是:要轉(zhuǎn)換的屏幕坐標(biāo)Point。事實工作已經(jīng)完成了,很簡單吧,覺得汗吧......下次介紹運行時怎樣動態(tài)添加控件.下面把代碼附上:form1.desgener////////代碼namespace
窗體拖動1{partialclassForm1{///<summary>///必需的設(shè)計器變量。///</summary>PrivateSystem.ComponentModel.IContainercomponents=null;///<summary>///清理所有正在使用的資源。///</summary>///<paramname="disposing">如果應(yīng)釋放托管資源,為true;否則為false。</param>ProtectedoverridevoidDispose(booldisposing){If(disposing&&(components!=null)){components.Dispose();}base.Dispose(disposing);}#regionWindows
窗體設(shè)計器生成的代碼///<summary>///設(shè)計器支持所需的方法不要///使用代碼編輯器修改此方法的內(nèi)容。///</summary>PrivatevoidInitializeComponent(){this.label1=newSystem.Windows.Forms.Label();this.SuspendLayout();///label1//this.label1.AutoSize=true;this.label1.Location=newSystem.Drawing.Point(92,86);this.label1.Name="label1";this.label1.Size=newSystem.Drawing.Size(101,12);this.label1.TabIndex=0;this.label1.Text="鼠標(biāo)拖動控件練習(xí)";this.label1.MouseDown+=newSystem.Windows.Forms.MouseEventHandler(this.label1_MouseDown);this.label1.MouseUp+=newSystem.Windows.Forms.MouseEventHandler(this.label1_MouseUp);////Form1//this.AutoScaleDimensions=newSystem.Drawing.SizeF(6F,12F);this.AutoScaleMode=System.Windows.Forms.AutoScaleMode.Font;this.ClientSize=newSystem.Drawing.Size(292,266);this.Controls.Add(this.label1);this.Name="Form1";this.Text="Form1";this.ResumeLayout(false);this.PerformLayout();}#endregionPrivateSystem.Windows.Forms.Labellabel1;}}form1.cs//////代碼usingSystem;usingSystem.Collections.Generic;usingSystem.ComponentModel;usingSystem.Data;usingSystem.Drawing;usingSystem.Text;usingSystem.Windows.Forms;namespace
窗體拖動1{PublicpartialclassForm1:Form{PrivatePointmouse_offset;PublicForm1(){InitializeComponent();}Privatevoidlabel1_MouseUp(objectsender,MouseEventArgse){If(e.Button==MouseButtons.Left){PointmousePos=Control.MousePosition;mousePos.Offset(mouse_offset.X,mouse_offset.Y);((Control)sender).Location=((Control)sender).Parent.PointToClient(mousePos);}}Privatevoidlabel1_MouseDown(objectsender,MouseEventArgse){mouse_offset=newPoint(-e.X,-e.Y);}}}利用C#更專業(yè)的實現(xiàn)運行時調(diào)整控件大小和位置一、技術(shù)要點運行時調(diào)整控件大小和位置很簡單,在.Net下只需修改控件的location和size屬性即可,動態(tài)調(diào)整時再捕獲MouseDown、MouseMove及MouseUp事件來實時修改上述兩個屬性就可以實現(xiàn)。但是我們會發(fā)現(xiàn)在VisualStudio.Net的開發(fā)環(huán)境中設(shè)計窗體布局時,選擇了控件后總會有一個可以調(diào)整其大小和位置的邊框出現(xiàn)以方便用戶進行操作。在VC6中MFC曾經(jīng)為我們提供了CRectTracker類來完成這項工作,但是C#里我卻沒有發(fā)現(xiàn)相關(guān)類。運行時可以調(diào)整控件位置和大小在某些情況下非常有用,譬如.Net提供了窗體打印功能,若能夠在運行時調(diào)整控件大小和位置我們將會動態(tài)的生成非常漂亮和規(guī)整的報表來。借鑒CRectTracker類我們發(fā)現(xiàn)它實際上就相當(dāng)于一個父控件,然后傳遞給它不同類的指針進行附著。在C#下我們以另外一種思維來考慮這個問題,當(dāng)在設(shè)計時的窗體上放置一個Panel控件,然后再往該Panel控件上放置一個子控件并填充之,那么在設(shè)計時調(diào)整Panel大小和位置時其子控件都會隨之改變,我們就利用這個原理在運行時捕獲獲得焦點的子控件,然后讓其成為類似于前述Panel父控件的子控件,并且在父控件周圍利用.NetGDI+畫上用于調(diào)整的邊框和錨點,當(dāng)鼠標(biāo)在特定位置按下并拖動時激活MouseMove事件進行響應(yīng)。實現(xiàn)的關(guān)鍵就是針對于類似Panel控件的操作,直接使用Panel控件進行上述操作也未嘗不可,但是我們將會創(chuàng)建一個專門用于運行時動態(tài)調(diào)整控件大小和位置的自定義控件,我們把它命名為:CRectControl。二、程序?qū)崿F(xiàn)啟動VisualStudio.Net2005,首先創(chuàng)建C#類庫。要想創(chuàng)建一個可以包容其它控件的容器控件,那么控件基類必須從System.Windows.Forms.UserControl繼承,代碼如下:public
class
CRectControl
:System.Windows.Forms.UserControl{……}
新建類庫時默認(rèn)引用不包括System.Windows.Forms和System.Drawing,我們必須手動將上述程序集添加到項目引用中。System.Windows.Forms為我們提供了豐富的創(chuàng)建界面的功能和方法,System.Drawing提供了對
GDI+
基本圖形功能的訪問,我們還需要導(dǎo)入System.Drawing.Drawing2D,該命名空間提供高級的二維和矢量圖形功能,代碼如下:
using
System;using
System.Drawing;using
System.Windows.Forms;using
System.Drawing.Drawing2D;CRectControl創(chuàng)建時傳遞需要調(diào)整的控件實例,根據(jù)控件大小及位置手動繪制CRectControl的邊框,包括8個用于調(diào)整大小的錨點都是需要手動繪制的,代碼如下:public
Rectangle
Rect{
get
{
return
baseRect;}
set
{
int
X=Square.Width;
int
Y=Square.Height;
int
Height=
value.Height;
int
Width=
value.Width;
baseRect=
new
Rectangle(X,Y,Width,Height);
SetRectangles();
}}void
SetRectangles(){
//定義8個小正方形的范圍
//左上
SmallRect[0]=
new
Rectangle(new
Point(baseRect.X-Square.Width,baseRect.Y-Square.Height),Square);
//上中間
SmallRect[4]=
new
Rectangle(new
Point(baseRect.X+(baseRect.Width/2)-(Square.Width/2),baseRect.Y-Square.Height),Square);
//右上
SmallRect[1]=
new
Rectangle(new
Point(baseRect.X+baseRect.Width,baseRect.Y-Square.Height),Square);
//左下
SmallRect[2]=
new
Rectangle(new
Point(baseRect.X-Square.Width,baseRect.Y+baseRect.Height),Square);
//下中間
SmallRect[5]=
new
Rectangle(new
Point(baseRect.X+(baseRect.Width/2)-(Square.Width/2),baseRect.Y+baseRect.Height),Square);
//右下
SmallRect[3]=
new
Rectangle(new
Point(baseRect.X+baseRect.Width,baseRect.Y+baseRect.Height),Square);
//左中間
SmallRect[6]=
new
Rectangle(new
Point(baseRect.X-Square.Width,baseRect.Y+(baseRect.Height/2)-(Square.Height/2)),Square);
//右中間
SmallRect[7]=
new
Rectangle(new
Point(baseRect.X+baseRect.Width,baseRect.Y+(baseRect.Height/2)-(Square.Height/2)),Square);
//整個包括周圍邊框的范圍
ControlRect=
new
Rectangle(new
Point(0,0),
this.Bounds.Size);}public
CRectControl(Control
theControl){
InitializeComponent();
currentControl=theControl;
Create();
}private
void
Create(){
//創(chuàng)建邊界
int
X=currentControl.Bounds.X-Square.Width;
int
Y=currentControl.Bounds.Y-Square.Height;
int
Height=currentControl.Bounds.Height+(Square.Height*2);
int
Width=currentControl.Bounds.Width+(Square.Width*2);
this.Bounds=
new
Rectangle(X,Y,Width+1,Height+1);
this.BringToFront();
Rect=currentControl.Bounds;
//設(shè)置可視區(qū)域
this.Region=
new
Region(BuildFrame());
g=
this.CreateGraphics();}private
GraphicsPath
BuildFrame(){
GraphicsPath
path=
new
GraphicsPath();
BoundRect[0]=
new
Rectangle(0,0,currentControl.Width+(Square.Width*2)+1,Square.Height+1);
BoundRect[1]=
new
Rectangle(0,Square.Height+1,Square.Width+1,currentControl.Bounds.Height+Square.Height+1);
BoundRect[2]=
new
Rectangle(Square.Width+1,currentControl.Bounds.Height+Square.Height-1,currentControl.Width+Square.Width+2,Square.Height+2);
BoundRect[3]=
new
Rectangle(currentControl.Width+Square.Width-1,Square.Height+1,Square.Width+2,currentControl.Height-1);
path.AddRectangle(BoundRect[0]);
path.AddRectangle(BoundRect[1]);
path.AddRectangle(BoundRect[2]);
path.AddRectangle(BoundRect[3]);
return
path;}邊框和錨點的大小位置計算完畢后,我們開始實際的繪制操作:public
void
Draw(){
try
{
g.FillRectangles(Brushes.LightGray,BoundRect);
//填充用于調(diào)整的邊框的內(nèi)部
g.FillRectangles(Brushes.White,SmallRect);
//填充8個錨點的內(nèi)部
g.DrawRectangles(Pens.Black,SmallRect);
//繪制8個錨點的黑色邊線
}
catch
(Exception
ex)
{
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 電焊工施工合同協(xié)議書
- 湖北省隨州市部分高中2024-2025學(xué)年高一下學(xué)期2月聯(lián)考地理試卷(含答案)
- 洗衣設(shè)備購銷合同共
- 健身房運營管理作業(yè)指導(dǎo)書
- 會議策劃與活動執(zhí)行服務(wù)協(xié)議
- 健康科技在老年健康管理中的應(yīng)用解決方案
- 水利建設(shè)工程施工合同協(xié)議書
- 大學(xué)生科普小說讀后感
- 觀看紀(jì)錄片長江觀后感
- 車隊土石方運輸合同
- 醫(yī)院培訓(xùn)課件:《多發(fā)性骨髓瘤》
- 2025年烏海職業(yè)技術(shù)學(xué)院單招職業(yè)技能測試題庫及完整答案一套
- 2025年湖南省長沙市單招職業(yè)傾向性測試題庫及參考答案
- 十八項核心制度培訓(xùn)課件
- 2024年遠(yuǎn)程教育行業(yè)市場運營現(xiàn)狀及行業(yè)發(fā)展趨勢報告
- 2025年2月上海市高三聯(lián)考高考調(diào)研英語試題(答案詳解)
- 2024-2025學(xué)年六年級上學(xué)期數(shù)學(xué)第三單元3.1-搭積木比賽(教案)
- DeepSeek從入門到精通
- 植保機械技術(shù)培訓(xùn)課件
- 2024年水利工程建設(shè)行業(yè)市場發(fā)展監(jiān)測及投資潛力預(yù)測報告
- 醫(yī)保電子憑證培訓(xùn)
評論
0/150
提交評論