自定义控件的简单缩放功能






2.41/5 (26投票s)
2005年9月29日
2分钟阅读

122135

2741
如何为自定义控件添加简单的缩放功能。
引言
最初,我写了一篇小文章来描述为自定义控件添加缩放功能所需的步骤(请参阅下方的详细信息)。 许多用户在使用描述的例程时遇到了问题。 这就是我决定编写一个自定义控件库(UniversalControl.dll)并提供一个演示项目的原因。 我还向控件添加了垂直和水平滚动条,因为这似乎是一项必不可少的功能。
用法(请参阅演示项目)
- 将UniversalControl.dll库添加到您的工具箱。
- 将
CUniversalControl
项目拖放到您的应用程序中。 - 配置您的
CUniversalControl
(设置颜色,启用/禁用滚动条,...)。 - 编写您自己的绘制例程(
DrawContents(Graphics grc)
)。 - 将其添加到控件的绘制事件中。
cUniversalControl1.EDraw += new DDrawContents(DrawContents);
详细说明
用户使用鼠标左键选择缩放区域,请参阅下面的屏幕截图
代码
已向控件添加了三个例程来处理鼠标事件。 当按下鼠标按钮时,将调用OnMouseDown
方法。 它设置新缩放区域的起始点,并将大小重置为零。
/// <summary>
/// event handler for mouse button pressed
/// sets zoom area start coordinates
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void OnMouseDown(object sender,
System.Windows.Forms.MouseEventArgs e)
{
// reset zoom state
m_blnZoom = false;
// sets the starting point of the zoomed area
m_ZoomRect = new Rectangle(new Point(e.X, e.Y),
new Size(0, 0));
}
只要按下鼠标左键,OnMouseMove
就会根据当前鼠标位置更新要缩放的区域。 它调用控件的Invalidate
方法以更新所选的缩放矩形(黑色矩形)。 缺点:不带参数调用的Invalidate
会更新整个控件,这可能会在选择要缩放的区域时导致一些闪烁(解决方案:仅使必要的区域失效)。
/// <summary>
/// handles mouse move events
/// updates current zoom area
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void OnMouseMove(object sender,
System.Windows.Forms.MouseEventArgs e)
{
// updates the current zoom area
// during mouse mouvements
// so it can be drawn by the OnPaint method
if (e.Button != MouseButtons.Left) return;
if (m_ZoomRect.X >= e.X)
m_ZoomRect.Width += Math.Abs(e.X - m_ZoomRect.X);
else m_ZoomRect.Width = Math.Abs(e.X - m_ZoomRect.X);
if (m_ZoomRect.Y >= e.Y)
m_ZoomRect.Height += Math.Abs(e.Y - m_ZoomRect.Y);
else m_ZoomRect.Height = Math.Abs(e.Y - m_ZoomRect.Y);
if (m_ZoomRect.X > e.X) m_ZoomRect.X = e.X;
if (m_ZoomRect.Y > e.Y) m_ZoomRect.Y = e.Y;
this.Invalidate();
}
最后,当释放鼠标按钮时,将调用OnMouseUp
方法。 如果释放鼠标左键,则下一次调用OnPaint
方法会将所选区域绘制到整个控件上(缩放)。
/// <summary>
/// event handler for mouse button released
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void OnMouseUp(object sender,
System.Windows.Forms.MouseEventArgs e)
{
// left mouse button released,
// zoom to the chosen area
if (e.Button == MouseButtons.Left)
m_blnZoom = true;
this.Refresh();
}
最后但并非最不重要的一点是,需要添加到OnPaint
方法中的代码。 如果控件处于“缩放模式”,则将在Graphics
上执行必要的缩放和平移。 之后,将完成所有希望为控件绘制的内容(DrawContents()
)。 最后绘制用于缩放区域的矩形(黑色矩形)。 这就是全部。
/// <summary>
/// redraws the control
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void OnPaint(object sender,
System.Windows.Forms.PaintEventArgs e)
{
if (m_blnZoom)
{
// scale and translate the transform
// that the selected area (m_ZoomRect)
// is drawn on the whole control (zoom)
e.Graphics.ScaleTransform((float)this.ClientSize.Width/m_ZoomRect.Width,
(float)this.ClientSize.Height/m_ZoomRect.Height);
e.Graphics.TranslateTransform(-m_ZoomRect.X, -m_ZoomRect.Y);
}
// draw control specific contents (data to be zoomed)
DrawContents(e.Graphics);
if (!m_blnZoom)
{
// draws the selected zoom area during mouse movements
e.Graphics.DrawRectangle(new Pen(new SolidBrush(Color.Black), 2),
m_ZoomRect);
}
}