Steve,
You seem to be missing some fundamental concepts here. I'll try to explain.
The positioning of an object is not automatically managed by scrolling, your
code has to be aware of that and make adjustments accordingly. If you're
drawing things in a scrollable panel the way to go is to set up a transform
for the whole panel and draw your objects according to that transform. This
means that all objects are under control of the scrollbars and don't care if
they are scrolled or not, they just draw themselves...
Saving the Graphics state is something you should do if your objects alter
that state individually, such as if an object supports rotation or scaling.
You don't need to save the state if you never intend to alter the state in
the draw routine and doing so gets you no benefit.
If an object is maintained outside of the scrollable list, maybe as some
sort of floating indicator, then it's probably better to consider it as
something apart from the list of scrollable objects and deal with it on its
own. Objects such as this may also better qualify for being created as
floating windows. This is particularly true for auto scrolled windows
because they set a clipping region that only covers the invalid part of the
window, therefore other objects are often not drawn at-all.
To manage scrolling, AutoScroll can be used to create the transform such
as...
Matrix mx=new Matrix(1,0,0,1,this.AutoScrollPosition.X,
this.AutoScrollPosition.Y);
e.Graphics.Transform=mx;
Now, drawing a rectangle at 10,10,100,75 will draw a rectangle that tracks
the scroll bars and moves with the viewpoint.
If you want an object that doesn't move in relation to the scrollbars you
can set up it's own transform such as...
public void DrawB(Graphics g)
{
GraphicsState state=g.Save();
g.Transform=new Matrix(1,0,0,1,0,0); // an identity matrix will stop it from
scrolling with the window
Rectangle rect = new Rectangle(50,50,20,20);
using (Pen pen = new Pen(Color.Red, 1))
{
g.DrawRectangle(pen, rect);
}
g.Restore(state);
}
However, because the panel only invalidates the bit that's just scrolled
into view, this never gets drawn unless the whole window is refreshed making
it look as though the item isn't drawn at-all. This means that a floating
window or a draw cycle that you manage totally is needed. For the latter you
need to be deriving your own control and not relying on the Panels Paint
event.
After my signature I include the modified version of your old code. Note how
the panel window is smaller. this lets you see that the red square is
actually drawn. It doesen't however fix your problem which, as I say
requires a more complex solution.
--
Bob Powell [MVP]
Visual C#, System.Drawing
Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tipstricks.htm Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/faqmain.htm All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
namespace Scroll2Objects
{
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Panel panel1;
private System.ComponentModel.Container components = null;
ObjectA A;
ObjectB B;
public Form1()
{
InitializeComponent();
A = new ObjectA();
B = new ObjectB();
}
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
private void InitializeComponent()
{
this.panel1 = new System.Windows.Forms.Panel();
this.SuspendLayout();
//
// panel1
//
this.panel1.AutoScroll = true;
this.panel1.AutoScrollMinSize = new System.Drawing.Size(400, 300);
this.panel1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this.panel1.Location = new System.Drawing.Point(208, 120);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(136, 128);
this.panel1.TabIndex = 0;
this.panel1.Paint += new
System.Windows.Forms.PaintEventHandler(this.panel1_Paint);
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(432, 350);
this.Controls.Add(this.panel1);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
}
#endregion
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void panel1_Paint(object sender, System.Windows.Forms.PaintEventArgs
e)
{
Matrix mx=new
Matrix(1,0,0,1,this.panel1.AutoScrollPosition.X,this.panel1.AutoScrollPosition.Y);
e.Graphics.Transform=mx;
A.DrawA(e.Graphics); // A draws according to the current transform so will
track with the scrollbars
B.DrawB(e.Graphics); // B sets up it's own transform and so does not...
}
}
public class ObjectA
{
private Size _size;
public Size size
{
set
{
_size = value;
}
get
{
return _size;
}
}
private Point _location;
public Point location
{
set
{
_location = value;
}
get
{
return _location;
}
}
//GraphicsState oldstate;
public void DrawA(Graphics g)
{
// chopped out by bob oldstate=g.Save();
Rectangle rect = new Rectangle(100 ,100 ,100 ,100);
using (Pen pen = new Pen(Color.Green, 1))
{
g.DrawRectangle(pen, rect);
}
// chopped out by bob g.Restore(oldstate);
}
}
public class ObjectB
{
private Size _size;
public Size size
{
set
{
_size = value;
}
get
{
return _size;
}
}
private Point _location;
public Point location
{
set
{
_location = value;
}
get
{
return _location;
}
}
public void DrawB(Graphics g)
{
GraphicsState state=g.Save();
g.Transform=new Matrix(1,0,0,1,0,0); // an identity matrix will stop it from
scrolling with the window
Rectangle rect = new Rectangle(50,50,20,20);
using (Pen pen = new Pen(Color.Red, 1))
{
g.DrawRectangle(pen, rect);
}
g.Restore(state);
}
}
}
[quoted text, click to view] "Steve Magoon" <owkmann@nojunk.yahoo.com> wrote in message
news:O6g5DRIYFHA.2520@TK2MSFTNGP09.phx.gbl...
>
> "Bob Powell [MVP]" <bob@_spamkiller_bobpowell.net> wrote in message
> news:unOPLKIYFHA.2520@TK2MSFTNGP09.phx.gbl...
>> You're setting the location of the A object to the autoscroll positions
>> which are negative.
>>
>> See my article on understanding auto-scroll in Windows Forms Tips and
>> Tricks.
>
>
> But isn't that correct? In your article on auto-scroll, you recommend