基于多选的控件跟踪器






4.81/5 (29投票s)
2001年12月20日
2分钟阅读

261329

7216
一个 CRectTracker 派生类,它可以做更多的事情
引言
在开发设计器和CAD相关应用程序时,通常需要移动和调整所选对象的功能。MFC运行时提供了一个类,即 CRectTracker,它可以做类似的事情,但它有几个缺点,最重要的是它没有多对象选择和调整功能。本文介绍了一个类,CControlTracker,它比CRectTracker的功能更强大。

它继承自CRectTracker,并且本质上与CRectTracker具有相同的接口。CControlTracker与另一个类CControlRect紧密合作,后者继承自CRectTracker和CWnd。这意味着你可以使用CControlRect创建任何控件(通过调用CWnd::Create),并将其添加到CControlTracker管理的控件列表中。然后,只需重写OnLButtonDown和OnSetCursor,就可以获得所有高级的移动/调整控件功能。
void CMainFrame::OnLButtonDown(UINT nFlags, CPoint point) 
{	
	m_ControlTracker.Track( point , nFlags , true );
	CFrameWnd::OnLButtonDown(nFlags, point);
}
BOOL CMainFrame::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
{	
	if( m_ControlTracker.SetCursor( nHitTest, message ) )
		return TRUE;	
	return CFrameWnd::OnSetCursor(pWnd, nHitTest, message);
}
类设计
CControlRect继承自CWnd,因此你可以将CControlRect*传递到任何需要CWnd*的地方。它还继承自CRectTracker。这是为了允许每个控件“跟踪”自身。你可以安全地创建所有控件,包括按钮、静态文本框和ListBox控件,甚至ActiveX控件,就像使用CWnd一样。
class CControlRect : public CRectTracker , public CWnd {
public:
// Controls enumerated in WindowType
	enum WindowType
	{
	enmScrollBar, enmStatic, enmButton, 
	enmEdit, enmListBox, enmComboBox
	};
// Can use enumerated type to create control
	BOOL Create( WindowType wndType, ... );
// Can also use class name to create control
	BOOL Create( LPCTSTR lpszClassName, ... );
// Tracks movement rectangle for control
	void Track( CWnd* pWnd, CPoint point, 
			BOOL bAllowInvert = FALSE, 
			CWnd* pWndClipTo = NULL );
// Sets bounding rectangle for control
	void SetRect( int x1, int y1, int x2, int y2 );
	void SetRect( const CRect & rect );
private:
// Tells weather the control is currently selected
	BOOL m_bSelected;
// Returns handle masks
	UINT GetHandleMask() const;
// Sets default attributes for CRectTracker
	void Initialize();
...
};
CControlTracker管理所有CControlRect类的对象。它维护一个通过调用CControlTracker::Add添加的所有控件的数组。它还维护一个当前所选对象的数组。只为选定的对象绘制句柄。
class CControlTracker : public CRectTracker
{
public:
// Creates the Control Tracker Object
	void Create( CWnd* pParentWnd );
// Adds the Control to the Tracker
	void Add( CControlRect* pObject );
// Starts tracking all the controls
	BOOL Track( const CPoint & point, UINT nFlags = 0, 
				BOOL bTrackRubberBand = TRUE );
// Sets the cursor on all the controls
	BOOL SetCursor( UINT nHitTest, UINT message );
// Tells weather the specified control is selected or not
	BOOL IsSelected( CControlRect* pObject ) const;
// Selects the specified control
// Returns TRUE if it was initially unselected else FALSE
	BOOL Select( CControlRect* pObject );
// DeSelects the specified control.
// Returns TRUE if it was initially selected else FALSE
	BOOL DeSelect( CControlRect* pObject );
// Toggles the state of the object 
// Returns TRUE if control was selected, otherwise returns FALSE
	BOOL Toggle( CControlRect* pObject );
// Draws all the controls
	void Draw( CDC* pDC ) const;
// DeSelects all the controls
// Returns the number of controls that were selected
	int DeSelectAll();
...
};
如何使用它
在你的类中创建CControlTracker和CControlRect(控件)的实例。我已经在我的应用程序窗口类中创建了控件。
class CMainFrame : public CFrameWnd
{
	CControlTracker m_ControlTracker;
	CControlRect r1, r2;
	...
};
重写OnLButtonDown、OnSetCursor、OnDraw和OnCreate。在Parent类的OnCreate成员中,添加以下代码
// Create ControlTracker
m_ControlTracker.Create( this );
// Create Controls
r1.Create( CControlRect::enmStatic, "Static Text Control", 
           this , SS_CENTERIMAGE | SS_BITMAP, CRect( 10,10,70,70 ) );
r2.Create( CControlRect::enmEdit, "Button Control",  
           this, WS_DISABLED,  CRect( 160,110,300,250 ) );
// Add controls in the tracking list of ControlTracker
	m_ControlTracker.Add( &r1 );
	m_ControlTracker.Add( &r2 );
未来工作
在不久的将来,我将致力于将LineTracker功能整合到此跟踪器中。使用这个类,你可以轻松地创建一个很酷的UML编辑器。如果你想提出任何关于设计或功能的改进建议,请告诉我。
历史
- 2001年12月20日:初始版本
许可证
本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。
作者可能使用的许可证列表可以在此处找到。
