虛控件在GUI編程中的應(yīng)用
在圖形化用戶界面編程中,用戶控件是一個很重要的概念。本質(zhì)上我們的圖形化用戶界面是由各種控件構(gòu)成,這些控件有些是IDE開發(fā)商提供的,有些是第三方提供的,若這些控件都不能完成功能則需要自己編寫控件了。在C#中編寫一個控件很簡單,以下代碼就能實現(xiàn)一個用戶控件。
public class UserControl1: System.Windows.Forms.UserControl { protected override void OnMouseMove(MouseEventArgs e) { // 處理鼠標(biāo)移動代碼 } protected override void OnPaint(PaintEventArgs e) { // 繪制用戶界面的代碼 } // 用戶控件的其他代碼 }
在此小弟提出“虛控件”的概念,所謂虛控件就是在控件和操作控件的代碼之間放置一個代理層,所有的代碼通過這個代理來操作控件,而控件的事件也通過這個代理層來調(diào)用相關(guān)的控制代碼,控件和代碼不直接發(fā)生關(guān)系。以下代碼實現(xiàn)了一個簡單的“虛控件”中的代理層
public class VirtualControlBase
{
protected System.Windows.Forms.Control myControl = null;
public System.Windows.Forms.PaintEventHandler _Paint = null;
public System.Windows.Forms.MouseEventHandler _MouseMove = null;
public VirtualControlBase()
{
_Paint = new System.Windows.Forms.PaintEventHandler(myControl_Paint);
_MouseMove = new System.Windows.Forms.MouseEventHandler(myControl_MouseMove);
}
// 綁定的控件
public System.Windows.Forms.Control BindControl
{
get
{
return myControl;
}
set
{
if (value != myControl)
{
if (myControl != null)
{
myControl.Paint -= _Paint;
myControl.MouseMove -= _MouseMove;
}
myControl = value;
if (myControl != null)
{
myControl.Paint += _Paint;
myControl.MouseMove += _MouseMove;
}
}
}
} //public System.Windows.Forms.Control BindControl
private void myControl_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
HandlePaint(e.Graphics, e.ClipRectangle);
}
private void myControl_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
HandleMouseMove(e.X, e.Y, e.Button);
}
protected virtual void HandlePaint(System.Drawing.Graphics Graphics, System.Drawing.Rectangle ClipRectangle){}
protected virtual void HandleMouseMove(int x, int y, System.Windows.Forms.MouseButtons Button){}
public System.Drawing.Size ClientSize
{
get
{
return System.Drawing.Size.Empty;
}
}
public System.Drawing.Rectangle Bounds
{
get
{
return myControl.Bounds;
}
}
public System.Drawing.Graphics CreateGraphics()
{
return myControl.CreateGraphics();
}
public System.Windows.Forms.Cursor Cursor
{
get
{
return myControl.Cursor;
}
set
{
myControl.Cursor = value;
}
}
public System.Drawing.Font Font
{
get
{
return myControl.Font;
}
set
{
myControl.Font = value;
}
}
public void Refresh()
{
myControl.Refresh();
}
public void Invalidate(System.Drawing.Rectangle Rect)
{
myControl.Invalidate(Rect, true);
}
public void Update()
{
myControl.Update();
}
} //public class VirtualControlBase
public class UserControl2: VirtualControlBase
{
protected override void HandleMouseMove(int x, int y, MouseButtons Button)
{
// 處理鼠標(biāo)移動的代碼
}
protected override void HandlePaint(Graphics Graphics, Rectangle ClipRectangle)
{
// 繪制用戶界面的代碼
}
// 用戶控件的其他代碼
}
這種模式我稱為“虛控件”模式,而傳統(tǒng)的控件稱為“實控件”模式。
設(shè)計良好的虛控件的代理層能使得代碼的編寫和實控件的代碼的編寫沒有多大的區(qū)別。
虛控件是不能直接使用的,它得依附在其他控件使用,首先在窗體中放置一個標(biāo)準(zhǔn)控件,比如Panel等等。然后實例化一個虛控件,調(diào)用VirtualControlBase.BindControl 屬性來進(jìn)行控件綁定,如此才可使用。
為何開發(fā)一個用戶控件需要如此多此一舉。其實這樣做有不少好處,可列舉的有
- 有利于代碼的分離和模塊化
- 實控件只能使用于圖形化用戶界面程序,而虛控件除了應(yīng)用于圖形化用戶界面程序外還可使用于其他任何類型的程序,包括命令行程序,ASP.NET,WebService,Windows服務(wù)。這個特性可以適用于某些程序的移植。例如將GUI程序移植到ASP.NET中,GUI程序中編制了虛控件繪制的復(fù)雜圖形,而后在ASP.NET程序中,它創(chuàng)建一個BMP圖片,然后使用庫函數(shù)System.Drawing.Graphics.FromImage創(chuàng)建一個Graphics對象,然后調(diào)用虛控件的HandlePaint來繪制這個復(fù)雜圖形,然后就可以發(fā)布出去了。這樣虛控件既可用于GUI程序又可用于ASP.NET程序,實現(xiàn)了代碼的重用。利用這個特性還能比較好的修改舊的GUI代碼,保持原有功能并向ASP.NET等非GUI程序提供圖形支持。
- 虛控件可以減少控件的個數(shù),在某些GUI應(yīng)用中,窗體中可能堆積很多一樣的控件,例如窗體有一個TabControl,有很多頁,每頁中放一個相同類型的用戶控件,用戶需要在這些控件來回切換。大家知道.NET的控件是基于Win32的窗體的,創(chuàng)建一個控件比較費(fèi)力,消耗資源。而虛控件本質(zhì)上只是一個類,在.NET中創(chuàng)建一個類是很簡單的。這樣在窗體中只要放置一個控件,然后生成很多虛控件,在各個控件來回切換就轉(zhuǎn)換為各個虛控件綁定和取消綁定實控件的操作。而且在窗體中放置大量的控件不利于窗體設(shè)計器的工作。若某個控件在設(shè)計狀態(tài)下發(fā)生錯誤則會影響窗體設(shè)計器的正常工作。(在VB中若用戶控件加載錯誤會自動轉(zhuǎn)換為一個PictureBox控件,所有的設(shè)計屬性都會丟失)
- 使用某個控件前需要在VS.NET的工具箱中加入這個控件的圖標(biāo),這個操作比較麻煩,而且打開其他不需要該控件的工程中,工具箱還會顯示該控件的圖標(biāo)。而使用虛控件則不會出現(xiàn)這種情況
其實虛控件的概念還能用VB來實現(xiàn),以下代碼就是一個簡單的例子
' 類 myControl.cls 的內(nèi)容
Private WithEvents myControl As VB.PictureBox
Public Sub SetBindControl(ByVal p As VB.PictureBox)
Set myControl = p
End Sub
Private Sub myControl_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
' 處理鼠標(biāo)移動事件
End Sub
Private Sub myControl_Paint()
' 繪圖圖形的操作
End Sub
以下是C#編寫的一個虛控件代理層的完整代碼。
/// <summary>
/// 綁定控件的模塊
/// </summary>
public class VirtualControlBase
{
/// <summary>
/// 對象綁定的控件
/// </summary>
protected System.Windows.Forms.Control myControl = null;
/// <summary>
/// 處理控件重繪事件的委托對象
/// </summary>
public System.Windows.Forms.PaintEventHandler _Paint = null;
/// <summary>
/// 處理鼠標(biāo)按鍵按下事件的委托對象
/// </summary>
public System.Windows.Forms.MouseEventHandler _MouseDown = null;
/// <summary>
/// 處理鼠標(biāo)移動事件的委托對象
/// </summary>
public System.Windows.Forms.MouseEventHandler _MouseMove = null;
/// <summary>
/// 處理鼠標(biāo)按鍵松開事件的委托對象
/// </summary>
public System.Windows.Forms.MouseEventHandler _MouseUp = null;
/// <summary>
/// 處理鼠標(biāo)光標(biāo)進(jìn)入控件事件的委托對象
/// </summary>
public System.EventHandler _MouseEnter = null;
/// <summary>
/// 處理鼠標(biāo)光標(biāo)離開控件事件的委托對象
/// </summary>
public System.EventHandler _MouseLeave = null;
/// <summary>
/// 處理鼠標(biāo)滾輪事件的委托對象
/// </summary>
public System.Windows.Forms.MouseEventHandler _MouseWheel = null;
/// <summary>
/// 處理鍵盤按鍵按下事件的委托對象
/// </summary>
public System.Windows.Forms.KeyEventHandler _KeyDown = null;
/// <summary>
/// 處理鍵盤輸入字符事件的委托對象
/// </summary>
public System.Windows.Forms.KeyPressEventHandler _KeyPress = null;
/// <summary>
/// 處理鍵盤按鍵松開事件的委托對象
/// </summary>
public System.Windows.Forms.KeyEventHandler _KeyUp = null;
/// <summary>
/// 處理控件獲得焦點事件的委托對象
/// </summary>
public System.EventHandler _GotFocus = null;
/// <summary>
/// 處理控件失去焦點事件的委托對象
/// </summary>
public System.EventHandler _LostFocus = null;
/// <summary>
/// 處理鼠標(biāo)單擊事件的委托對象
/// </summary>
public System.EventHandler _Click = null;
/// <summary>
/// 處理鼠標(biāo)雙擊事件的委托對象
/// </summary>
public System.EventHandler _DoubleClick = null;
/// <summary>
/// 處理控件大小改變事件的委托對象
/// </summary>
public System.EventHandler _Resize = null;
/// <summary>
/// 初始化對象
/// </summary>
public VirtualControlBase()
{
_Paint = new System.Windows.Forms.PaintEventHandler(myControl_Paint);
_MouseDown = new System.Windows.Forms.MouseEventHandler(myControl_MouseDown);
_MouseMove = new System.Windows.Forms.MouseEventHandler(myControl_MouseMove);
_MouseUp = new System.Windows.Forms.MouseEventHandler(myControl_MouseUp);
_MouseEnter = new System.EventHandler(myControl_MouseEnter);
_MouseLeave = new System.EventHandler(myControl_MouseLeave);
_MouseWheel = new System.Windows.Forms.MouseEventHandler(myControl_MouseWheel);
_KeyDown = new System.Windows.Forms.KeyEventHandler(myControl_KeyDown);
_KeyPress = new System.Windows.Forms.KeyPressEventHandler(myControl_KeyPress);
_KeyUp = new System.Windows.Forms.KeyEventHandler(myControl_KeyUp);
_GotFocus = new System.EventHandler(myControl_GotFocus);
_LostFocus = new System.EventHandler(myControl_LostFocus);
_Click = new System.EventHandler(myControl_Click);
_DoubleClick = new System.EventHandler(myControl_DoubleClick);
_Resize = new System.EventHandler(myControl_Resize);
}
/// <summary>
/// 重新綁定控件
/// </summary>
public virtual void ReBind()
{
this.BindControl = this.myControl;
}
/// <summary>
/// 綁定的控件
/// </summary>
public virtual System.Windows.Forms.Control BindControl
{
get
{
return myControl;
}
set
{
if (myControl != null)
{
myControl.Paint -= _Paint;
myControl.MouseDown -= _MouseDown;
myControl.MouseMove -= _MouseMove;
myControl.MouseUp -= _MouseUp;
myControl.MouseEnter -= _MouseEnter;
myControl.MouseLeave -= _MouseLeave;
myControl.MouseWheel -= _MouseWheel;
myControl.KeyDown -= _KeyDown;
myControl.KeyPress -= _KeyPress;
myControl.KeyUp -= _KeyUp;
myControl.GotFocus -= _GotFocus;
myControl.LostFocus -= _LostFocus;
myControl.Click -= _Click;
myControl.DoubleClick -= _DoubleClick;
myControl.Resize -= _Resize;
}
myControl = value;
if (myControl != null)
{
myControl.Paint += _Paint;
myControl.MouseDown += _MouseDown;
myControl.MouseMove += _MouseMove;
myControl.MouseUp += _MouseUp;
myControl.MouseEnter += _MouseEnter;
myControl.MouseLeave += _MouseLeave;
myControl.MouseWheel += _MouseWheel;
myControl.KeyDown += _KeyDown;
myControl.KeyPress += _KeyPress;
myControl.KeyUp += _KeyUp;
myControl.GotFocus += _GotFocus;
myControl.LostFocus += _LostFocus;
myControl.Click += _Click;
myControl.DoubleClick += _DoubleClick;
myControl.Resize += _Resize;
}
OnAfterBindControl();
}
} //public System.Windows.Forms.Control BindControl
/// <summary>
/// 綁定控件后的處理
/// </summary>
protected virtual void OnAfterBindControl(){}
private void myControl_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
HandleKeyDown(e.KeyCode, e.Alt, e.Shift, e.Control);
}
private void myControl_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
HandleKeyPress(e.KeyChar);
}
private void myControl_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e)
{
HandleKeyUp(e.KeyCode, e.Alt, e.Shift, e.Control);
}
private void myControl_MouseLeave(object sender, System.EventArgs e)
{
HandleMouseLeave();
}
private void myControl_MouseWheel(object sender, System.Windows.Forms.MouseEventArgs e)
{
HandleMouseWheel(e.X, e.Y, e.Button, e.Delta);
}
private void myControl_GotFocus(object sender, System.EventArgs e)
{
HandleGotFocus();
}
private void myControl_LostFocus(object sender, System.EventArgs e)
{
HandleLostFocus();
}
private void myControl_MouseEnter(object sender, System.EventArgs e)
{
HandleMouseEnter();
}
private void myControl_Click(object sender, System.EventArgs e)
{
System.Drawing.Point p = System.Windows.Forms.Control.MousePosition;
p = myControl.PointToClient(p);
HandleClick(p.X, p.Y, System.Windows.Forms.Control.MouseButtons);
}
private void myControl_DoubleClick(object sender, System.EventArgs e)
{
System.Drawing.Point p = System.Windows.Forms.Control.MousePosition;
p = myControl.PointToClient(p);
HandleDoubleClick(p.X, p.Y, System.Windows.Forms.Control.MouseButtons);
}
private void myControl_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
HandlePaint(e.Graphics, e.ClipRectangle);
}
private void myControl_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
HandleMouseDown(e.X, e.Y, e.Button);
}
private void myControl_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
HandleMouseMove(e.X, e.Y, e.Button);
}
private void myControl_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
HandleMouseUp(e.X, e.Y, e.Button);
}
private void myControl_Resize(object sender, System.EventArgs e)
{
HandleResize();
}
#region 控件事件處理過程群
/// <summary>
/// 處理鍵盤按鍵按下事件
/// </summary>
/// <param name="KeyCode">按鍵編碼</param>
/// <param name="Alt">Alt鍵是否按下</param>
/// <param name="Shift">Shift鍵是否按下</param>
/// <param name="Control">Control鍵是否按下</param>
protected virtual void HandleKeyDown(System.Windows.Forms.Keys KeyCode, bool Alt, bool Shift, bool Control){}
/// <summary>
/// 處理鍵盤字符事件
/// </summary>
/// <param name="KeyChar">字符數(shù)據(jù)</param>
protected virtual void HandleKeyPress(char KeyChar){}
/// <summary>
/// 處理鍵盤按鍵松開事件
/// </summary>
/// <param name="KeyCode">按鍵編碼</param>
/// <param name="Alt">Alt鍵是否按下</param>
/// <param name="Shift">Shift鍵是否按下</param>
/// <param name="Control">Control鍵是否按下</param>
protected virtual void HandleKeyUp(System.Windows.Forms.Keys KeyCode, bool Alt, bool Shift, bool Control){}
/// <summary>
/// 處理鼠標(biāo)光標(biāo)離開控件工作區(qū)事件
/// </summary>
protected virtual void HandleMouseLeave(){}
/// <summary>
/// 處理鼠標(biāo)滾輪事件
/// </summary>
/// <param name="x">鼠標(biāo)光標(biāo)X坐標(biāo)</param>
/// <param name="y">鼠標(biāo)光標(biāo)Y坐標(biāo)</param>
/// <param name="Button">鼠標(biāo)按鍵值</param>
/// <param name="Delta">滾輪值</param>
protected virtual void HandleMouseWheel(int x, int y, System.Windows.Forms.MouseButtons Button, int Delta){}
/// <summary>
/// 處理控件獲得焦點事件
/// </summary>
protected virtual void HandleGotFocus(){}
/// <summary>
/// 處理控件失去焦點事件
/// </summary>
protected virtual void HandleLostFocus(){}
/// <summary>
/// 處理鼠標(biāo)光標(biāo)進(jìn)入控件工作區(qū)事件
/// </summary>
protected virtual void HandleMouseEnter(){}
/// <summary>
/// 處理鼠標(biāo)單擊事件
/// </summary>
/// <param name="x">鼠標(biāo)光標(biāo)X坐標(biāo)</param>
/// <param name="y">鼠標(biāo)光標(biāo)Y坐標(biāo)</param>
/// <param name="Button">鼠標(biāo)按鍵值</param>
protected virtual void HandleClick(int x, int y, System.Windows.Forms.MouseButtons Button){}
/// <summary>
/// 處理鼠標(biāo)雙擊事件
/// </summary>
/// <param name="x">鼠標(biāo)光標(biāo)X坐標(biāo)</param>
/// <param name="y">鼠標(biāo)光標(biāo)Y坐標(biāo)</param>
/// <param name="Button">鼠標(biāo)按鍵值</param>
protected virtual void HandleDoubleClick(int x, int y, System.Windows.Forms.MouseButtons Button){}
/// <summary>
/// 處理鼠標(biāo)按鍵按下事件
/// </summary>
/// <param name="x">鼠標(biāo)光標(biāo)X坐標(biāo)</param>
/// <param name="y">鼠標(biāo)光標(biāo)Y坐標(biāo)</param>
/// <param name="Button">鼠標(biāo)按鍵值</param>
protected virtual void HandleMouseDown(int x, int y, System.Windows.Forms.MouseButtons Button){}
/// <summary>
/// 處理鼠標(biāo)移動事件
/// </summary>
/// <param name="x">鼠標(biāo)光標(biāo)X坐標(biāo)</param>
/// <param name="y">鼠標(biāo)光標(biāo)Y坐標(biāo)</param>
/// <param name="Button">鼠標(biāo)按鍵值</param>
protected virtual void HandleMouseMove(int x, int y, System.Windows.Forms.MouseButtons Button){}
/// <summary>
/// 處理鼠標(biāo)按鍵松開事件
/// </summary>
/// <param name="x">鼠標(biāo)光標(biāo)X坐標(biāo)</param>
/// <param name="y">鼠標(biāo)光標(biāo)Y坐標(biāo)</param>
/// <param name="Button">鼠標(biāo)按鍵值</param>
protected virtual void HandleMouseUp(int x, int y, System.Windows.Forms.MouseButtons Button){}
/// <summary>
/// 處理重繪用戶界面事件
/// </summary>
/// <param name="Graphics">圖形繪制對象</param>
/// <param name="ClipRectangle">剪切矩形區(qū)域</param>
protected virtual void HandlePaint(System.Drawing.Graphics Graphics, System.Drawing.Rectangle ClipRectangle){}
/// <summary>
/// 處理控件改變大小事件
/// </summary>
protected virtual void HandleResize(){}
#endregion
/// <summary>
/// 創(chuàng)建顯示內(nèi)容的位圖對象
/// </summary>
/// <param name="bounds">要顯示的區(qū)域</param>
/// <returns>創(chuàng)建的BMP位圖對象</returns>
public System.Drawing.Bitmap CreateBitmap(System.Drawing.Rectangle bounds)
{
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(bounds.Width, bounds.Height);
using(System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bmp))
{
g.TranslateTransform(bounds.Left, bounds.Top);
this.HandlePaint(g, bounds);
}
return bmp;
}
/// <summary>
/// 對象是否綁定了一個控件
/// </summary>
public bool HasBindControl
{
get
{
return myControl != null;
}
}
/// <summary>
/// 創(chuàng)建繪圖對象
/// </summary>
/// <returns></returns>
public System.Drawing.Graphics CreateGraphics()
{
if (myControl == null)
return null;
else
return myControl.CreateGraphics();
}
/// <summary>
/// 設(shè)置輸入焦點
/// </summary>
public void Focus()
{
if (myControl != null)
myControl.Focus();
}
/// <summary>
/// 鼠標(biāo)光標(biāo)
/// </summary>
public System.Windows.Forms.Cursor Cursor
{
get
{
if (myControl == null)
return System.Windows.Forms.Cursors.Default;
else
return myControl.Cursor;
}
set
{
if (myControl != null)
myControl.Cursor = value;
}
}
/// <summary>
/// 獲取一個值,該值指示控件是否有輸入焦點。
/// </summary>
public bool Focused
{
get
{
return myControl == null ? false : myControl.Focused;
}
}
/// <summary>
/// 強(qiáng)制控件使其工作區(qū)無效并立即重繪自己和任何子控件。
/// </summary>
public virtual void Refresh()
{
if (myControl != null)
myControl.Refresh();
}
/// <summary>
/// 獲取包含在控件內(nèi)的控件集合
/// </summary>
public System.Windows.Forms.Control.ControlCollection Controls
{
get
{
return myControl == null ? null : myControl.Controls;
}
}
/// <summary>
/// 使控件內(nèi)指定區(qū)域無效,并向控件發(fā)送繪制消息
/// </summary>
/// <param name="Rect"></param>
public virtual void Invalidate(System.Drawing.Rectangle Rect)
{
if (myControl != null)
myControl.Invalidate(Rect, true);
}
/// <summary>
/// 判斷控件是否已捕獲鼠標(biāo)
/// </summary>
public bool Capture
{
get
{
return myControl == null ? false : myControl.Capture;
}
}
/// <summary>
/// 使控件重繪工作區(qū)內(nèi)無效區(qū)域
/// </summary>
public void Update()
{
if (myControl != null)
myControl.Update();
}
} //public class VirtualControlBase
posted on 2006-04-19 14:07 袁永福 電子病歷,醫(yī)療信息化 閱讀(2378) 評論(3) 收藏 舉報
浙公網(wǎng)安備 33010602011771號