> I've encountered a strange problem with GDI/GDI+ and windows forms/win32.
> To
[quoted text clipped - 28 lines]
> let someone me know if there is a better solution and if this is a bug in
> win32 GDI. Thanks in advance.
Stoitcho Goutsev,
See below a small sample application which can be used to reproduce the
problem. Compile and show the form and move another form over the sample to
see the painting problem. Switching on the AllPaintingInWmPaint flag will do
the correct painting. Please let me know your results.
Thanks in advance.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace Test
{
public class FormTest : Form
{
private NCControl ncControl;
private CheckBox checkBox1;
public FormTest()
{
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Text = "FormTest";
ncControl = new NCControl();
ncControl.Dock = DockStyle.Fill;
checkBox1 = new CheckBox();
checkBox1.Text = "AllPaintingInWmPaint";
checkBox1.Size = new Size(80, 17);
checkBox1.AutoSize = true;
checkBox1.Location = new Point(10, 10);
checkBox1.Anchor = AnchorStyles.Left | AnchorStyles.Top;
checkBox1.CheckedChanged += new EventHandler(checkBox1_CheckedChanged);
ncControl.Controls.Add(checkBox1);
this.Controls.Add(ncControl);
}
void checkBox1_CheckedChanged(object sender, EventArgs e)
{
this.ncControl.SetStyleAllPaintingInWmPaint(checkBox1.Checked);
}
}
public class NCControl : ContainerControl
{
public NCControl() : base()
{
this.SetStyle(ControlStyles.ResizeRedraw, true);
}
public void SetStyleAllPaintingInWmPaint(bool value)
{
this.SetStyle(ControlStyles.AllPaintingInWmPaint, value);
}
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_NCCALCSIZE:
this.WmNcCalcSize(ref m);
break;
case WM_NCPAINT:
this.WmNcPaint(ref m);
break;
default:
base.WndProc(ref m);
break;
}
}
private void WmNcCalcSize(ref Message m)
{
base.WndProc(ref m);
if (m.WParam == IntPtr.Zero)
{
RECT clientRect = (RECT) Marshal.PtrToStructure(m.LParam, typeof(RECT));
Marshal.StructureToPtr(this.GetClientRectangleAsRECT(clientRect),
m.LParam, false);
}
else
{
NCCALCSIZE_PARAMS p = (NCCALCSIZE_PARAMS)
Marshal.PtrToStructure(m.LParam, typeof(NCCALCSIZE_PARAMS));
p.rgrc0 = this.GetClientRectangleAsRECT(p.rgrc0);
Marshal.StructureToPtr(p, m.LParam, false);
}
m.Result = IntPtr.Zero;
}
private RECT GetClientRectangleAsRECT(RECT clientRect)
{
clientRect.left += Math.Min(10, clientRect.right - clientRect.left);
clientRect.top += Math.Min(10, clientRect.bottom - clientRect.top);
clientRect.bottom -= Math.Min(10, clientRect.bottom - clientRect.top);
clientRect.right -= Math.Min(10, clientRect.right - clientRect.left);
return clientRect;
}
private void WmNcPaint(ref Message m)
{
base.WndProc(ref m);
IntPtr hRgnClip = IntPtr.Zero;
int flags = DCX_WINDOW | DCX_CACHE | DCX_CLIPSIBLINGS |
DCX_LOCKWINDOWUPDATE;
if ((int) m.WParam != 1)
{
hRgnClip = m.WParam;
flags |= DCX_INTERSECTRGN;
}
IntPtr hDC = GetDCEx(this.Handle, hRgnClip, flags);
using (Graphics g = Graphics.FromHdc(hDC))
{
Rectangle frameRectangle = new Rectangle(0,0,this.Width, this.Height);
Rectangle innerRectangle = frameRectangle;
innerRectangle.Inflate(-10, -10);
Region frameRegion = new Region(frameRectangle);
frameRegion.Exclude(innerRectangle);
using (SolidBrush brush = new SolidBrush(Color.Red))
g.FillRegion(brush, frameRegion);
frameRegion.Dispose();
}
ReleaseDC(this.Handle, hDC);
m.Result = IntPtr.Zero;
}
public const int WM_NCCALCSIZE = 0x00000083;
public const int WM_NCPAINT = 0x00000085;
public const int DCX_WINDOW = 0x0000001;
public const int DCX_CACHE = 0x00000002;
public const int DCX_CLIPSIBLINGS = 0x00000010;
public const int DCX_INTERSECTRGN = 0x00000080;
public const int DCX_LOCKWINDOWUPDATE = 0x00000400;
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
[StructLayout(LayoutKind.Sequential)]
public struct NCCALCSIZE_PARAMS
{
public RECT rgrc0;
public RECT rgrc1;
public RECT rgrc2;
public IntPtr lppos;
}
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true,
SetLastError = true)]
public static extern IntPtr GetDCEx(IntPtr hWnd, IntPtr hRgnClip, int
flags);
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true,
SetLastError = true)]
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
}
}
> jh,
>
[quoted text clipped - 36 lines]
> > let someone me know if there is a better solution and if this is a bug in
> > win32 GDI. Thanks in advance.