Hi olkasu,
This problem is in your code, not in C1Gauge. When you get the image with c1Gauge1.GetImage() it
contains semi-transparent pixels at the border of the gauge. After changing value the OnPaint method draws the image once again but it doesn’t clear the previous image because of “SetStyle(ControlStyles.Opaque, true);”
When you paint semi-transparent pixels over and over they eventually become “black”.
If you remove “SetStyle(ControlStyles.Opaque, true);” the gauge starts to flicker each time when the value is changed because the UserControl fills its background with Form’s background color to simulate transparency.
To get rid of flickering you can add:
[csharp]SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
[/csharp]to the constructor of UserControl2 and remove “g.Dispose();” from the OnPaint method because that’s a bug.
As the result of all those manipulations the first and second gauges will be drawn similarly, i.e. the button is still covered with either UserControl or C1Gauge.
If you need real transparency use the layered popup window that is drawn with UpdateLayeredWindow API:
[csharp][DllImport(“user32.dll”, ExactSpelling = true)]
internal static extern bool UpdateLayeredWindow(
IntPtr hwnd,
IntPtr hdcDst,
ref Win32.POINT pptDst,
ref Win32.SIZE psize,
IntPtr hdcSrc,
ref Win32.POINT pptSrc,
int crKey,
ref Win32.BLENDFUNCTION pBlend,
int dwFlags);
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct BLENDFUNCTION
{
public byte BlendOp;
public byte BlendFlags;
public byte SourceConstantAlpha;
public byte AlphaFormat;
}
[StructLayout(LayoutKind.Sequential)]
internal struct POINT
{
public int x;
public int y;
public POINT(int x, int y)
{
this.x = x;
this.y = y;
}
}
[StructLayout(LayoutKind.Sequential)]
internal struct SIZE
{
public int cx;
public int cy;
public SIZE(int width, int height)
{
cx = width;
cy = height;
}
}
protected override CreateParams CreateParams
{
[SecurityPermission(SecurityAction.LinkDemand)]
get
{
CreateParams cp = base.CreateParams;
cp.Style = Win32.WS_POPUP;
cp.ExStyle = Win32.WS_EX_LAYERED | Win32.WS_EX_NOACTIVATE;
cp.ClassStyle = 0;
return cp;
}
}
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
UpdateLayeredGaugeWindow();
}
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == Win32.WM_MOUSEACTIVATE)
{
m.Result = new IntPtr(Win32.MA_NOACTIVATE);
}
}
internal void ShowNoActivate()
{
NativeMethods.ShowWindow(Handle, Win32.SW_SHOWNOACTIVATE);
}
internal void BringGaugeToFront(bool topMost)
{
NativeMethods.SetWindowPos(Handle, topMost ? new IntPtr(Win32.HWND_TOPMOST) : IntPtr.Zero, Left, Top, Width, Height,
Win32.SWP_NOACTIVATE | Win32.SWP_NOOWNERZORDER | Win32.SWP_NOSIZE | Win32.SWP_NOMOVE);
}
internal void UpdateLayeredGaugeWindow()
{
Bitmap bitmap = PrepareBitmapWithC1Gauge();
IntPtr screenDc = NativeMethods.GetDC(IntPtr.Zero);
IntPtr memDc = NativeMethods.CreateCompatibleDC(screenDc);
IntPtr hBitmap = IntPtr.Zero;
IntPtr oldBitmap = IntPtr.Zero;
try
{
hBitmap = bitmap.GetHbitmap(Color.FromArgb(0));
oldBitmap = NativeMethods.SelectObject(memDc, hBitmap);
Win32.SIZE size = new Win32.SIZE(_bmpWidth, _bmpHeight);
Win32.POINT ptSrc = new Win32.POINT(0, 0);
Win32.POINT ptDst = new Win32.POINT(_x, _y);
Win32.BLENDFUNCTION blend = new Win32.BLENDFUNCTION();
blend.BlendOp = Win32.AC_SRC_OVER;
blend.BlendFlags = 0;
blend.SourceConstantAlpha = 255;
blend.AlphaFormat = Win32.AC_SRC_ALPHA;
NativeMethods.UpdateLayeredWindow(Handle, screenDc, ref ptDst, ref size, memDc, ref ptSrc, 0, ref blend, Win32.ULW_ALPHA);
}
finally
{
NativeMethods.ReleaseDC(IntPtr.Zero, screenDc);
if (hBitmap != IntPtr.Zero)
{
NativeMethods.SelectObject(memDc, oldBitmap);
NativeMethods.DeleteObject(hBitmap);
}
NativeMethods.DeleteDC(memDc);
}
}
[/csharp]
Something like that. Hope that helps.
Regards,
-Andrey