I figuted it out by study on http://www.codeproject.com/KB/GDI-plus/DesktopLyrics.aspx and http://www.vcskicks.com/splash-screen.php
I am trying my best to explain it bellow:
The Key is to use API.UpdateLayeredWindow(). It enable my application to display background images with transperancy.
The other trick is where I draw the text. instead of drawing the text on the Windows Form or Label directly, it needs draw it on a bitmap. The bitmap is not any component from tool box, it's in the memory.(All regular component won't be shown).
As the first article "
To Create A COOL Desktop Lyrics Demo (A Gift To All People On CP)[
^]"said, the steps are:
1. Create a compatible bitmap. 2. Draw the Text with the color and font on the bitmap. 3. Draw bitmap on the device content. 4. Invoke the UpdateLayeredWindows().
All those steps need do when OnPaint Event happen. Bellow is my codes to draw the Text of the Form on the desktop.
#region FORM EVENTS -------------------------------------------------------
private void Form1_Load(object sender, EventArgs e)
{
UpdateFormDisplay(this.BackgroundImage);
}
protected override void OnPaint(PaintEventArgs e)
{
UpdateFormDisplay(this.BackgroundImage);
}
#endregion
public void UpdateFormDisplay(Image backgroundImage)
{
IntPtr screenDc = API.GetDC(IntPtr.Zero);
IntPtr memDc = API.CreateCompatibleDC(screenDc);
IntPtr hBitmap = IntPtr.Zero;
IntPtr oldBitmap = IntPtr.Zero;
Graphics g1 = this.CreateGraphics();
SizeF thissize = g1.MeasureString(Text, this.Font);
Bitmap bmp = new Bitmap( (int) thissize.Width,(int) thissize.Height);
g1 = Graphics.FromImage(bmp);
try
{
g1.SmoothingMode = SmoothingMode.AntiAlias;
g1.InterpolationMode = InterpolationMode.HighQualityBicubic;
LinearGradientBrush myBrush = new LinearGradientBrush(new Rectangle(0, 0, this.Font.Height,this.Font.Height), Color.White, Color.Blue, LinearGradientMode.Vertical);
SolidBrush backBrush = new SolidBrush(Color.FromArgb(100,this.BackColor));
g1.FillRectangle(backBrush,0,0,thissize.Width,thissize.Height);
this.Size = new Size((int) thissize.Width, (int) thissize.Height);
g1.DrawString(Text, this.Font, myBrush, 0, 0);
hBitmap = bmp.GetHbitmap(Color.FromArgb(0));
oldBitmap = API.SelectObject(memDc, hBitmap);
Size size = bmp.Size;
Point pointSource = new Point(0, 0);
Point topPos = new Point(this.Left, this.Top);
API.BLENDFUNCTION blend = new API.BLENDFUNCTION();
blend.BlendOp = API.AC_SRC_OVER;
blend.BlendFlags = 0;
blend.SourceConstantAlpha = 255;
blend.AlphaFormat = API.AC_SRC_ALPHA;
API.UpdateLayeredWindow(this.Handle, screenDc, ref topPos, ref size, memDc, ref pointSource, 0, ref blend, API.ULW_ALPHA);
bmp.Dispose();
API.ReleaseDC(IntPtr.Zero, screenDc);
if (hBitmap != IntPtr.Zero)
{
API.SelectObject(memDc, oldBitmap);
API.DeleteObject(hBitmap);
}
API.DeleteDC(memDc);
}
catch (Exception)
{
}
finally
{
g1.Dispose();
bmp.Dispose();
}
}
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x00080000;
return cp;
}
}
internal class API
{
public const byte AC_SRC_OVER = 0x00;
public const byte AC_SRC_ALPHA = 0x01;
public const Int32 ULW_ALPHA = 0x00000002;
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct BLENDFUNCTION
{
public byte BlendOp;
public byte BlendFlags;
public byte SourceConstantAlpha;
public byte AlphaFormat;
}
[DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
public static extern bool UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst, ref Point pptDst, ref Size psize, IntPtr hdcSrc, ref Point pprSrc, Int32 crKey, ref BLENDFUNCTION pblend, Int32 dwFlags);
[DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
[DllImport("user32.dll", ExactSpelling = true)]
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern bool DeleteDC(IntPtr hdc);
[DllImport("gdi32.dll", ExactSpelling = true)]
public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
public static extern bool DeleteObject(IntPtr hObject);
}
/pre
To make the Text can be moved by mouse, the mousedown event needs to handled.
[DllImportAttribute("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HTCAPTION = 0x2;
[DllImportAttribute("user32.dll")]
public static extern bool ReleaseCapture();
private void frmSplash_MouseDown(object sender, MouseEventArgs e)
{
ReleaseCapture();
SendMessage(Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
}