w0lfshad3

EDIT: the panel logic must be before the child controls logic, fixed in the source or download

EDIT2: addedSadon complete method that processes panel1 and its childs)

I just use ControlsBuffer[...Index] instead of panel1.Controls[...Index]

Code Block

Control[] ControlsBuffer = new Control[panel1.Controls.Count];

panel1.Controls.CopyTo(ControlsBuffer, 0);

panel1.Controls.Clear();

at start and

Code Block
panel1.Controls.AddRange(ControlsBuffer);

at end

It eliminates the jitter however the controls lump togheter. It would be nice if anyone could discover why.

END-EDIT2

Again what i want from Window Forms and what i know of Window Forms have grown apart too much Big Smile ... and i run into some trouble. While zooming a group of controls, i cannot shake the jittering. I tried a buffer but achieved some weird effects as controls grouping in clumps around my Parent.

What i'm trying to achieve is a zoom functionality.

Source code: http://files.filefront.com/MyMoO5rar/;8775135;/fileinfo.html

So far known bugs and must implement-s:

- must stabilize the entire process(when fast scrolling up down(zoming in out) the code gets mixed up mouse positions and loses logic) - this one i think i can achieve with a bool before and after zoom logic with wich i can control mouse wheel input to not work until last zoom operation is done; perhaps even storing mouse wheel notches in the meantime.

- must lose jitter(showing up a relative position of th control just before its final position)

- must gain performance

- must fix logic as when zooming on a top area and the rest of the panel leaving mouse pan logic area, it will jump the panel into another position(because of mouse pan logic probably[look for #region mouse pan]) / also must fix as to keep the panel into similar relative mouse pan logic bounds at all times if possible just for the aspect.

*eventually i will implement a zoomFactor variable to control amount of zoom(it needn't zoom out further than the resolution and needn't zoom in further than when the width for instance is equal to the relative distance beween two controls).

Tried this buffer code before and after i work on my controls in a loop:

Before loop:

Code Block

Control[] ControlsBuffer = new Control[panel1.Controls.Count];

panel1.Controls.CopyTo(ControlsBuffer, 0);

After loop:

Code Block

panel1.Controls.Clear();

panel1.Controls.AddRange(ControlsBuffer);

With ControlBuffer(w/o panel logic):

Code Block

for (int i = 0; i < starArray.Length; i++)

{

// relocate star

ControlsBuffer[starIndex].Location = new Point(ControlsBuffer[starIndex].Location.X + (int)Math.Round(ControlsBuffer[starIndex].Location.X * factor, MidpointRounding.AwayFromZero),

ControlsBuffer[starIndex].Location.Y + (int)Math.Round(ControlsBuffer[starIndex].Location.Y * factor, MidpointRounding.AwayFromZero));

// resize star

ControlsBuffer[starIndex].Size = new Size(ControlsBuffer[starIndex].Size.Width + (int)Math.Round(ControlsBuffer[starIndex].Size.Width * factor, MidpointRounding.AwayFromZero),

ControlsBuffer[starIndex].Size.Height + (int)Math.Round(ControlsBuffer[starIndex].Size.Height * factor, MidpointRounding.AwayFromZero));

starNameIndex = starIndex + 1;

// set StarName Location

point.X = ControlsBuffer[starIndex].Location.X + ControlsBuffer[starIndex].Width / 2 - ControlsBuffer[starNameIndex].Width / 2;

point.Y = ControlsBuffer[starIndex].Location.Y + ControlsBuffer[starIndex].Height;

ControlsBuffer[starNameIndex].Location = point;

starProductionIndex = starIndex + 2;

// set StarProduction Location

point.X = ControlsBuffer[starIndex].Location.X + ControlsBuffer[starIndex].Width / 2 - ControlsBuffer[starProductionIndex].Width / 2;

point.Y = ControlsBuffer[starIndex].Location.Y - ControlsBuffer[starProductionIndex].Height;

ControlsBuffer[starProductionIndex].Location = point;

starIndex += 3;

}

Without ControlBuffer(w/ panel logic):

Code Block

for(int i = 0; i < starArray.Length; i++)

{

// center screen to mouse position

Point cursorPosition = this.PointToClient(Cursor.Position);

Point centerPoint = new Point(Width / 2, Size.Height / 2);

Size offset = new Size(centerPoint.X - cursorPosition.X, centerPoint.Y - cursorPosition.Y);

Cursor.Position = this.PointToScreen(centerPoint);

panel1.Location += offset;

// resize panel1

panel1.ClientSize = new Size(panel1.Size.Width + (int)Math.Round(panel1.Size.Width * factor, MidpointRounding.AwayFromZero),

panel1.Size.Height + (int)Math.Round(panel1.Size.Height * factor, MidpointRounding.AwayFromZero));

// resize ClientArea

//this.ClientSize = new Size((int)Math.Round(ClientSize.Width + ClientSize.Width * factor, MidpointRounding.AwayFromZero),

// (int)Math.Round(ClientSize.Height + ClientSize.Height * factor, MidpointRounding.AwayFromZero));

// after zoom relocate panel1 to appear centered like before zoom

// location = v1{center - location} + v1/10

Size prevVector = new Size(centerPoint.X - panel1.Location.X, centerPoint.Y - panel1.Location.Y);

Size vector = new Size(prevVector.Width + prevVector.Width / 10, prevVector.Height + prevVector.Height / 10);

Size vectorOffset = vector - prevVector;

if (factor < 0)

panel1.Location += vectorOffset;

else

panel1.Location -= vectorOffset;

// relocate star

panel1.Controls[starIndex].Location = new Point(panel1.Controls[starIndex].Location.X + (int)Math.Round(panel1.Controls[starIndex].Location.X * factor, MidpointRounding.AwayFromZero),

panel1.Controls[starIndex].Location.Y + (int)Math.Round(panel1.Controls[starIndex].Location.Y * factor, MidpointRounding.AwayFromZero));

// resize star

panel1.Controls[starIndex].Size = new Size(panel1.Controls[starIndex].Size.Width + (int)Math.Round(panel1.Controls[starIndex].Size.Width * factor, MidpointRounding.AwayFromZero),

panel1.Controls[starIndex].Size.Height + (int)Math.Round(panel1.Controls[starIndex].Size.Height * factor, MidpointRounding.AwayFromZero));

starNameIndex = starIndex + 1;

// set StarName Location

point.X = panel1.Controls[starIndex].Location.X + panel1.Controls[starIndex].Width / 2 - panel1.Controls[starNameIndex].Width / 2;

point.Y = panel1.Controls[starIndex].Location.Y + panel1.Controls[starIndex].Height;

panel1.Controls[starNameIndex].Location = point;

starProductionIndex = starIndex + 2;

// set StarProduction Location

point.X = panel1.Controls[starIndex].Location.X + panel1.Controls[starIndex].Width / 2 - panel1.Controls[starProductionIndex].Width / 2;

point.Y = panel1.Controls[starIndex].Location.Y - panel1.Controls[starProductionIndex].Height;

panel1.Controls[starProductionIndex].Location = point;

starIndex += 3;

}



Re: Windows Forms General Zooming a group of controls(EDIT2)

Oleh Svintsitskyy

Hi w0lfhsad3,

Use SuspendLayout() method in conjunction with ResumeLayout() after.No need to remove controls from container's control collection.

Regards,

Oleh.





Re: Windows Forms General Zooming a group of controls(EDIT2)

w0lfshad3

I tried those two around but they seem to Suspend and Resume layout queue as they say, so they store the jitter too to be produced later.




Re: Windows Forms General Zooming a group of controls(EDIT2)

sirjis

You keep referring to a star control. If what you're doing is dealing purely with graphics, I would handle everything in the panel's paint event -- just keep track of the zoom factor and possibly the viewing center. You could use double buffering to reduce flicker. But maybe you're moving text boxes and combo boxes too, so that wouldn't be possible.

I would personally not do any of this incrementally like you're doing it now. Instead, keep a permanent copy of the controls' desired upper-left and lower-right corners at 1x zoom, and every time you change the zoom factor, apply a matrix transformation to those points to get the new bounding recangles for each control. You can use System.Drawing.Drawing2D.Matrix and its TransformPoints method for this. If this sounds hard, don't worry -- the math is mostly hidden inside the Matrix class.

I'm not sure if that answers your question because I didn't read through everything you asked -- this is just my 2 cents after skimming through the code.




Re: Windows Forms General Zooming a group of controls(EDIT2)

w0lfshad3

Altough it looks bad what its doing is very simple, i'm receiving a factor from mouse wheel, and each mosu wheel notch the Zoom function is called with a factor of +0.1f or -0.1f.

What the function really does is resize the panel the controls stay on and relocate the controls(they dont' need scaling themselves - i'm scaling a control myself though with it's size only and factor, no problem).

The real problem that occur are that it's not syncronized at all so jerking it around makes it receive wrong mouse coordinates and it jitters because i first resize the panel thus all controsl jump too then relocate the controls myself.

Even if i fixed tha jitter by moving all the relocating and resizing into a buffer and back into the panle1.Controls the child controls lump in groups by Location and can't find out why. Solving these probelms would suffice for my zoom funcitonality. The chidren are custom controls made up of panels labels pictureBoxes and textboxes nothign complicated.

Can't do anything in Paint other than change the whole approach of this app, making a bitmap out of it all and working w/o controls altogheter and do hit testing afterwards with will be rathe cumbersome thinking that there will be as much as 300 rectangles to hit check against.