GDI Refresh Problem

F

Franco Gustavo

Hi,

How can I execute 2 GDI steps without update the screen and update them
togheter?.

Basically I have a form and I want to change the Form Region and change the
Form Location, later show the changes on the screen.

On the Following code you can see that the code is executed but where the
window was there is the rest of the window that wasn't cleaned, if you move
a window over it it disapears.

I want to avoid see every change I do on the screen because I'm running many
changes a seconds (Animation)

I tried many ways but still I can get a way to work.

Here is the small code. (Uncomment try1 or try2)
Thanks,

namespace PrototipesAndTesting
{
public class AnimateNoFlick : System.Windows.Forms.Form
{
#region enums
public enum SetWindowPosFlags
{
SWP_NOSIZE = 0x0001,
SWP_NOMOVE = 0x0002,
SWP_NOZORDER = 0x0004,
SWP_NOREDRAW = 0x0008,
SWP_NOACTIVATE = 0x0010
}
#endregion

#region WINAPIs
[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr
hWndInsertAfter, int x, int y, int Width, int Height, SetWindowPosFlags
flags);
[DllImport("User32.dll", CharSet=CharSet.Auto)]
private static extern int SetWindowRgn(IntPtr hWnd, IntPtr hRgn, bool
redraw);
[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern int InvalidateRect(IntPtr hWnd, IntPtr rc, int
bErase);
[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern bool UpdateWindow(IntPtr hWnd);
#endregion

#region Variables Declaration
private System.Windows.Forms.Button button1;
private System.ComponentModel.Container components = null;
#endregion

#region Constructors
public AnimateNoFlick()
{
InitializeComponent();
}
#endregion

#region Initialization And Disposing
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.button1 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(96, 64);
this.button1.Name = "button1";
this.button1.TabIndex = 2;
this.button1.Text = "button1";
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// AnimateNoFlick
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(280, 262);
this.Controls.Add(this.button1);
this.Location = new System.Drawing.Point(300, 100);
this.Name = "AnimateNoFlick";
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
this.Text = "AnimateNoFlick";
this.ResumeLayout(false);

}
#endregion

private void button1_Click(object sender, System.EventArgs e)
{
bool bResult;
int iResult;

Rectangle stepRec = new Rectangle(300, 500, this.Width,
this.Height);
Region region = new Region(new Rectangle(30,30, 200, 200));

Graphics graphics = this.CreateGraphics();
IntPtr ptr = region.GetHrgn(graphics);
graphics.Dispose();

//Try 1
//bResult = SetWindowPos(this.Handle, IntPtr.Zero, stepRec.X,
stepRec.Y, stepRec.Width, stepRec.Height, SetWindowPosFlags.SWP_NOZORDER |
SetWindowPosFlags.SWP_NOACTIVATE | SetWindowPosFlags.SWP_NOREDRAW);
//iResult = SetWindowRgn(this.Handle, ptr, true);

//Try 2
iResult = SetWindowRgn(this.Handle, ptr, false);
bResult = SetWindowPos(this.Handle, IntPtr.Zero, stepRec.X,
stepRec.Y, stepRec.Width, stepRec.Height, SetWindowPosFlags.SWP_NOZORDER |
SetWindowPosFlags.SWP_NOACTIVATE);


InvalidateRect(this.Handle, IntPtr.Zero, 1);
UpdateWindow(this.Handle);
Application.DoEvents();
}
#endregion
}
}
 
M

Mick Doherty

Why are you using Interop?

private void button1_Click(object sender, System.EventArgs e)
{

Rectangle stepRec = new Rectangle(300, 500, this.Width,
this.Height);
Region region = new Region(new Rectangle(30,30, 200, 200));
this.Region = region;
this.Location = new Point(stepRec.X,stepRec.Y);

}

--
Mick Doherty
http://dotnetrix.co.uk/nothing.html


Franco Gustavo said:
Hi,

How can I execute 2 GDI steps without update the screen and update them
togheter?.

Basically I have a form and I want to change the Form Region and change
the Form Location, later show the changes on the screen.

On the Following code you can see that the code is executed but where the
window was there is the rest of the window that wasn't cleaned, if you
move a window over it it disapears.

I want to avoid see every change I do on the screen because I'm running
many changes a seconds (Animation)

I tried many ways but still I can get a way to work.

Here is the small code. (Uncomment try1 or try2)
Thanks,

namespace PrototipesAndTesting
{
public class AnimateNoFlick : System.Windows.Forms.Form
{
#region enums
public enum SetWindowPosFlags
{
SWP_NOSIZE = 0x0001,
SWP_NOMOVE = 0x0002,
SWP_NOZORDER = 0x0004,
SWP_NOREDRAW = 0x0008,
SWP_NOACTIVATE = 0x0010
}
#endregion

#region WINAPIs
[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr
hWndInsertAfter, int x, int y, int Width, int Height, SetWindowPosFlags
flags);
[DllImport("User32.dll", CharSet=CharSet.Auto)]
private static extern int SetWindowRgn(IntPtr hWnd, IntPtr hRgn, bool
redraw);
[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern int InvalidateRect(IntPtr hWnd, IntPtr rc, int
bErase);
[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern bool UpdateWindow(IntPtr hWnd);
#endregion

#region Variables Declaration
private System.Windows.Forms.Button button1;
private System.ComponentModel.Container components = null;
#endregion

#region Constructors
public AnimateNoFlick()
{
InitializeComponent();
}
#endregion

#region Initialization And Disposing
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.button1 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(96, 64);
this.button1.Name = "button1";
this.button1.TabIndex = 2;
this.button1.Text = "button1";
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// AnimateNoFlick
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(280, 262);
this.Controls.Add(this.button1);
this.Location = new System.Drawing.Point(300, 100);
this.Name = "AnimateNoFlick";
this.StartPosition =
System.Windows.Forms.FormStartPosition.Manual;
this.Text = "AnimateNoFlick";
this.ResumeLayout(false);

}
#endregion

private void button1_Click(object sender, System.EventArgs e)
{
bool bResult;
int iResult;

Rectangle stepRec = new Rectangle(300, 500, this.Width,
this.Height);
Region region = new Region(new Rectangle(30,30, 200, 200));

Graphics graphics = this.CreateGraphics();
IntPtr ptr = region.GetHrgn(graphics);
graphics.Dispose();

//Try 1
//bResult = SetWindowPos(this.Handle, IntPtr.Zero, stepRec.X,
stepRec.Y, stepRec.Width, stepRec.Height, SetWindowPosFlags.SWP_NOZORDER |
SetWindowPosFlags.SWP_NOACTIVATE | SetWindowPosFlags.SWP_NOREDRAW);
//iResult = SetWindowRgn(this.Handle, ptr, true);

//Try 2
iResult = SetWindowRgn(this.Handle, ptr, false);
bResult = SetWindowPos(this.Handle, IntPtr.Zero, stepRec.X,
stepRec.Y, stepRec.Width, stepRec.Height, SetWindowPosFlags.SWP_NOZORDER |
SetWindowPosFlags.SWP_NOACTIVATE);


InvalidateRect(this.Handle, IntPtr.Zero, 1);
UpdateWindow(this.Handle);
Application.DoEvents();
}
#endregion
}
}
 
F

Franco Gustavo

Because using .NET framework the changes are applied inmediatly and you get
flickering. if it is done many 50 times a seconds.

The last parameter in calling SetWindowRgn is the changes should be draw or
not.
The Same case with SetWindowPos and the flag SetWindowPosFlags.SWP_NOREDRAW.

Basicallty, Between two frames I want to clean just the portion where the
new frame won't be.

Yesterday I found a solution but it is kind of slow if there are many
windows behing the animation window.

The solution I found was:

1) CreateRegion
2) Translate region where the final destination will be
3) Apply Region to the Form and DRAW the changes (Last paramer true).
--- So Far only the difference between the old region and the new region
will be cleared from the screen
4) CreateRegion same as 1)
5) Apply Region to the Form and DO NOT apply the chages (Last paramer false)
6) Call SetWindowPos to position the window in the final place.
7) Invalidate
8) Call DoEvents

This work fine.

But if the application is running on the Desktop it run smoth and fast, but
if there is more windows behing it, it come slow in step 3) to sending the
message to every window behing it to redraw the new portion of the screen..

Basically I want to create a AnimateWindow API but I don't want to hide it
complety, WIN32 API allow to show or hide, but not to animate just one
portion of it.

Gustavo

"Mick Doherty"
Why are you using Interop?

private void button1_Click(object sender, System.EventArgs e)
{

Rectangle stepRec = new Rectangle(300, 500, this.Width,
this.Height);
Region region = new Region(new Rectangle(30,30, 200, 200));
this.Region = region;
this.Location = new Point(stepRec.X,stepRec.Y);

}

--
Mick Doherty
http://dotnetrix.co.uk/nothing.html


Franco Gustavo said:
Hi,

How can I execute 2 GDI steps without update the screen and update them
togheter?.

Basically I have a form and I want to change the Form Region and change
the Form Location, later show the changes on the screen.

On the Following code you can see that the code is executed but where the
window was there is the rest of the window that wasn't cleaned, if you
move a window over it it disapears.

I want to avoid see every change I do on the screen because I'm running
many changes a seconds (Animation)

I tried many ways but still I can get a way to work.

Here is the small code. (Uncomment try1 or try2)
Thanks,

namespace PrototipesAndTesting
{
public class AnimateNoFlick : System.Windows.Forms.Form
{
#region enums
public enum SetWindowPosFlags
{
SWP_NOSIZE = 0x0001,
SWP_NOMOVE = 0x0002,
SWP_NOZORDER = 0x0004,
SWP_NOREDRAW = 0x0008,
SWP_NOACTIVATE = 0x0010
}
#endregion

#region WINAPIs
[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr
hWndInsertAfter, int x, int y, int Width, int Height, SetWindowPosFlags
flags);
[DllImport("User32.dll", CharSet=CharSet.Auto)]
private static extern int SetWindowRgn(IntPtr hWnd, IntPtr hRgn,
bool redraw);
[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern int InvalidateRect(IntPtr hWnd, IntPtr rc, int
bErase);
[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern bool UpdateWindow(IntPtr hWnd);
#endregion

#region Variables Declaration
private System.Windows.Forms.Button button1;
private System.ComponentModel.Container components = null;
#endregion

#region Constructors
public AnimateNoFlick()
{
InitializeComponent();
}
#endregion

#region Initialization And Disposing
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.button1 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(96, 64);
this.button1.Name = "button1";
this.button1.TabIndex = 2;
this.button1.Text = "button1";
this.button1.Click += new
System.EventHandler(this.button1_Click);
//
// AnimateNoFlick
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(280, 262);
this.Controls.Add(this.button1);
this.Location = new System.Drawing.Point(300, 100);
this.Name = "AnimateNoFlick";
this.StartPosition =
System.Windows.Forms.FormStartPosition.Manual;
this.Text = "AnimateNoFlick";
this.ResumeLayout(false);

}
#endregion

private void button1_Click(object sender, System.EventArgs e)
{
bool bResult;
int iResult;

Rectangle stepRec = new Rectangle(300, 500, this.Width,
this.Height);
Region region = new Region(new Rectangle(30,30, 200, 200));

Graphics graphics = this.CreateGraphics();
IntPtr ptr = region.GetHrgn(graphics);
graphics.Dispose();

//Try 1
//bResult = SetWindowPos(this.Handle, IntPtr.Zero, stepRec.X,
stepRec.Y, stepRec.Width, stepRec.Height, SetWindowPosFlags.SWP_NOZORDER
| SetWindowPosFlags.SWP_NOACTIVATE | SetWindowPosFlags.SWP_NOREDRAW);
//iResult = SetWindowRgn(this.Handle, ptr, true);

//Try 2
iResult = SetWindowRgn(this.Handle, ptr, false);
bResult = SetWindowPos(this.Handle, IntPtr.Zero, stepRec.X,
stepRec.Y, stepRec.Width, stepRec.Height, SetWindowPosFlags.SWP_NOZORDER
| SetWindowPosFlags.SWP_NOACTIVATE);


InvalidateRect(this.Handle, IntPtr.Zero, 1);
UpdateWindow(this.Handle);
Application.DoEvents();
}
#endregion
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top