65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.41/5 (26投票s)

2005年9月29日

2分钟阅读

viewsIcon

122135

downloadIcon

2741

如何为自定义控件添加简单的缩放功能。

引言

最初,我写了一篇小文章来描述为自定义控件添加缩放功能所需的步骤(请参阅下方的详细信息)。 许多用户在使用描述的例程时遇到了问题。 这就是我决定编写一个自定义控件库(UniversalControl.dll)并提供一个演示项目的原因。 我还向控件添加了垂直和水平滚动条,因为这似乎是一项必不可少的功能。

用法(请参阅演示项目)

  1. UniversalControl.dll库添加到您的工具箱。
  2. CUniversalControl项目拖放到您的应用程序中。
  3. 配置您的CUniversalControl(设置颜色,启用/禁用滚动条,...)。
  4. 编写您自己的绘制例程(DrawContents(Graphics grc))。
  5. 将其添加到控件的绘制事件中。
cUniversalControl1.EDraw += new DDrawContents(DrawContents);

详细说明

用户使用鼠标左键选择缩放区域,请参阅下面的屏幕截图

Sample Image

Sample Image

代码

已向控件添加了三个例程来处理鼠标事件。 当按下鼠标按钮时,将调用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);
  }
}
© . All rights reserved.