How do I zoom to a target point and update the scrollbars in C#?

Please support our C# advertiser: Intel Parallel Studio Home
Reply

Join Date: Feb 2009
Posts: 2
Reputation: accessviolation is an unknown quantity at this point 
Solved Threads: 0
accessviolation accessviolation is offline Offline
Newbie Poster

How do I zoom to a target point and update the scrollbars in C#?

 
0
  #1
Feb 6th, 2009
Hello,

I am attempting to develop a custom control that allows the user to
zoom to a specific point on an image, typically a map. The problem
that I am having is when I attempt to adjust the scrollbar position,
the update of the image is very jerky. For example, in the code below,
when the user selects a point on the image, the image is zoomed in on
the point and the scroll bar position is updated to the new origin of
the viewport. When the image is updated, it appears to be drawn at its
original position and scale, then the control's OnPaint method is
called and the image is drawn correctly. This gives the appearance of
the image moving left and up before snapping to the zoomed point. The
problem seems to be exacerbated when double buffering is enabled. Has
anyone else experienced this?

Here's the example code:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Windows.Forms;
  5. using System.Drawing.Imaging;
  6. using System.Drawing.Drawing2D;
  7. using System.Drawing;
  8.  
  9. namespace Zoom
  10. {
  11. public class ZoomPoint : ScrollableControl
  12. {
  13. enum ZoomDirection
  14. {
  15. In,
  16. Out
  17. }
  18. #region Private Data
  19. private float _zoom = 1.0f;
  20. private PointF _origin = new PointF(0, 0);
  21. private Image _image = null;
  22. #endregion
  23.  
  24. public ZoomPoint() {
  25. SetStyle(ControlStyles.UserPaint, true);
  26. SetStyle(ControlStyles.AllPaintingInWmPaint, true);
  27. SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
  28. SetStyle(ControlStyles.ResizeRedraw, true);
  29. this.AutoScroll = true;
  30. UpdateScroll();
  31. }
  32.  
  33. public Image Image {
  34. get {
  35. return _image;
  36. }
  37. set {
  38. _image = value;
  39. _origin = PointF.Empty;
  40. _zoom = 1.0F;
  41. UpdateScroll();
  42. Invalidate();
  43. }
  44. }
  45.  
  46. protected override void OnPaintBackground(PaintEventArgs e) {
  47. // don't allow the background to be painted
  48. }
  49.  
  50. protected override void OnPaint(PaintEventArgs e) {
  51.  
  52. Graphics g = e.Graphics;
  53.  
  54. ClearBackground(g);
  55.  
  56. float dx = -_origin.X;
  57. float dy = -_origin.Y;
  58.  
  59. g.Transform = new Matrix(_zoom, 0, 0, _zoom, dx, dy);
  60. g.FillRectangle(Brushes.Blue, 100, 100, 5, 5);
  61. DrawImage(g);
  62. }
  63.  
  64. private void ClearBackground(Graphics g) {
  65. g.Clear(SystemColors.Window);
  66. }
  67.  
  68. protected override void OnScroll(ScrollEventArgs se) {
  69. base.OnScroll(se);
  70.  
  71. if (se.ScrollOrientation ==
  72. ScrollOrientation.HorizontalScroll) {
  73. _origin.X += se.NewValue - se.OldValue;
  74. }
  75. else {
  76. _origin.Y += se.NewValue - se.OldValue;
  77. }
  78. Invalidate();
  79. }
  80.  
  81. protected override void OnMouseWheel(MouseEventArgs e) {
  82. if (e.Delta > 0) {
  83. ZoomToPoint(e.Location, ZoomDirection.In);
  84. }
  85. else {
  86. ZoomToPoint(e.Location, ZoomDirection.Out);
  87. }
  88. Invalidate();
  89. }
  90.  
  91. protected override void OnMouseClick(MouseEventArgs e) {
  92. ZoomToPoint(e.Location, ZoomDirection.In);
  93. Invalidate();
  94. }
  95.  
  96. private void UpdateScroll() {
  97.  
  98. if (_image != null) {
  99.  
  100. Size scrollSize = new Size(
  101. (int)Math.Round(_image.Width * _zoom),
  102. (int)Math.Round(_image.Height * _zoom));
  103.  
  104. Point position = new Point(
  105. (int)Math.Round(_origin.X),
  106. (int)Math.Round(_origin.Y));
  107.  
  108. this.AutoScrollMinSize = scrollSize;
  109. this.AutoScrollPosition = position;
  110. }
  111. else {
  112. this.AutoScrollMargin = this.Size;
  113. }
  114.  
  115. }
  116.  
  117. private void ZoomToPoint(Point viewPoint, ZoomDirection
  118. direction) {
  119. // get the model point
  120. PointF modelPoint = ToModelPoint(viewPoint);
  121.  
  122. if (direction == ZoomDirection.In) {
  123. // Increase the zoom
  124. _zoom *= 1.25F;
  125. }
  126. else {
  127. // decrease the zoom
  128. _zoom *= .75F;
  129. }
  130.  
  131. // calculate the new origin
  132. _origin.X = (modelPoint.X * _zoom) - viewPoint.X;
  133. _origin.Y = (modelPoint.Y * _zoom) - viewPoint.Y;
  134.  
  135. UpdateScroll();
  136. }
  137.  
  138. private PointF ToModelPoint(Point viewPoint) {
  139. PointF modelPoint = new PointF();
  140.  
  141. modelPoint.X = (_origin.X + viewPoint.X) / _zoom;
  142. modelPoint.Y = (_origin.Y + viewPoint.Y) / _zoom;
  143.  
  144. return modelPoint;
  145. }
  146.  
  147. private void DrawImage(Graphics g) {
  148. if (null != _image) {
  149. // set the transparency color for the image
  150. ImageAttributes attr = new ImageAttributes();
  151. attr.SetColorKey(Color.White, Color.White);
  152.  
  153. Rectangle destRect = new Rectangle(0, 0, _image.Width,
  154. _image.Height);
  155. g.DrawImage(_image, destRect, 0, 0, _image.Width,
  156. _image.Height, GraphicsUnit.Pixel, attr);
  157. }
  158. }
  159.  
  160. protected override void Dispose(bool disposing) {
  161. if (disposing) {
  162. if (null != _image) {
  163. _image.Dispose();
  164. _image = null;
  165. }
  166. }
  167. base.Dispose(disposing);
  168. }
  169. }
Reply With Quote Quick reply to this message  
Join Date: Aug 2008
Posts: 1,735
Reputation: LizR has a spectacular aura about LizR has a spectacular aura about 
Solved Threads: 186
LizR LizR is offline Offline
Posting Virtuoso

Re: How do I zoom to a target point and update the scrollbars in C#?

 
0
  #2
Feb 6th, 2009
Well
Rather than the code, you need to take the zoom and work out the new size of the scrollbar.. as what is now subject to the scrollbar is no longer the same size.
Did I just hear "You gotta help us, Doc. We've tried nothin' and we're all out of ideas" ? Is this you? Dont let this be you! I will put in as much effort as you seem to.
Reply With Quote Quick reply to this message  
Join Date: Feb 2009
Posts: 2
Reputation: accessviolation is an unknown quantity at this point 
Solved Threads: 0
accessviolation accessviolation is offline Offline
Newbie Poster

Re: How do I zoom to a target point and update the scrollbars in C#?

 
0
  #3
Feb 6th, 2009
I don't think I see what you mean. The size of the srollbar, or the AutoScrollMinSize, is calculated as the zoomed image size. That part seems to work fine. The scroll position is then set to the origin of the viewport, which seems to be exactly where I want it. But when I do set the position, there seems to be a major flicker.

After some experiments, I found that If I perform the following steps, I don't get the same flicker.

1. Call ZoomToPoint
2. Set the AutoScrollMinSize property based on the scaled image size
3. Call Invalidate
4. Set the AutoScrollPosition property to the origin.
Reply With Quote Quick reply to this message  
Reply

This thread is more than three months old.
Perhaps start a new thread instead?
Message:



Similar Threads
Other Threads in the C# Forum
Thread Tools Search this Thread



About Us | Contact Us | Advertise | DaniWeb | Acceptable Use Policy | RSS Feed

©2003 - 2009 DaniWeb® LLC