Quote:
Another complication I can foresee is with scrolling. Imagine I have a
100 pages vertically and some othe 10 horizontally. If I place the
pages as picture boxes in a scrollable panel it's easy to scroll and to
dispose them when go out of scope. I am not sure I will be able to
handle this on a bitmap (representing the document). Hmmm, In this case
the bitmap would remain "still" and what change is just the portion of
document which is projected on to it... |
Just add a horizontal and vertical scrollbar to the usercontrol.
Recalculate their positions, sizes, max values, and visibility every
time the control is resized. Use current values as offsets when
processing subsequent mouse events. When calculating
whether or not to show either vertical or horizontal scrollbar,
remember that the appearance of one limits the space available
on the other axis, which suddenly might require that the other
is shown as well

....
An easier solution might be to set the size of your user control
to encompass the pages you need, place that single user control
on a scrollable panel, thereby getting the scrollbars for free.
Only paint on the part of the user control which is visible.
In this case you should do any buffering yourself. Do NOT use
SetStyle(...) to let the system handle the buffering, as it will
create a buffer the size of the control.
Try out the code below. Start a new VB.NET project, add
a new UserControl named "HugeControl" with the code
shown below. Set Form1.AutoScroll = True. Add an instance
of HugeControl to Form1 and set its size to 30.000 x 30.000.
Yes, a 30.000 x 30.000 pixel control with double-buffered
rendering without taking up more memory for the buffer than
the size of the screen (make sure you read the comments).
/Joergen Bech
---snip---
Option Explicit On
Option Strict On
Public Class HugeControl
Private buffer As Bitmap
Public Sub New()
' This call is required by the Windows Form Designer.
InitializeComponent()
' ' Add any initialization after the
InitializeComponent() call.
'NO! Do NOT use the system's double buffering. A buffer
matching the
' full size of the control would be created, even if we are
only
' going to show a small portion of it.
' If you enable this code, memory will disappear and the
app might
' even crash.
' SetStyle(ControlStyles.AllPaintingInWmPaint, True)
' SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
' SetStyle(ControlStyles.ResizeRedraw, True)
' SetStyle(ControlStyles.UserPaint, True)
'We are being lazy here by just once and for all creating a
buffer
'the size of the primary screen. In the case that the primary
screen
'is smaller than a secondary screen and we are displaying the
application
'on the secondary screen, this is a really, really bad idea.
buffer = New Bitmap(Screen.PrimaryScreen.Bounds.Width, _
Screen.PrimaryScreen.Bounds.Height, _
System.Drawing.Imaging.PixelFormat.Format32bppPArg b)
End Sub
Private Sub HugeControl_Paint(ByVal sender As Object, ByVal e As
System.Windows.Forms.PaintEventArgs) Handles Me.Paint
Dim count As Integer = 0
Dim offsetX As Integer = -e.ClipRectangle.X
Dim offsetY As Integer = -e.ClipRectangle.Y
Dim gBuffer As Graphics = Graphics.FromImage(buffer)
gBuffer.FillRectangle(New SolidBrush(Me.BackColor), New
Rectangle(0, 0, e.ClipRectangle.Width, e.ClipRectangle.Height))
For x As Integer = 0 To Me.ClientRectangle.Width Step 64
Dim x255 As Integer = CType((x / Me.ClientRectangle.Width)
* 255, Integer)
For y As Integer = 0 To Me.ClientRectangle.Height Step 64
Dim y255 As Integer = CType((y /
Me.ClientRectangle.Height) * 255, Integer)
Dim clr As Color = Color.FromArgb(x255, x255, y255)
Dim destrect As New Rectangle(x, y, 64, 64)
If e.ClipRectangle.IntersectsWith(destrect) Then
Dim bufferrect As New Rectangle(x + offsetX, y +
offsetY, 64, 64)
gBuffer.FillEllipse(New SolidBrush(clr),
bufferrect)
count = count + 1
End If
Next
Next
e.Graphics.DrawImageUnscaled(buffer, e.ClipRectangle)
gBuffer.Dispose()
Debug.WriteLine("Count: " & count.ToString)
End Sub
Protected Overrides Sub OnPaintBackground(ByVal e As
System.Windows.Forms.PaintEventArgs)
'Do nothing here. Do not call the base event handler.
End Sub
End Class
---snip---