Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
For one of my apps that I created and I will be posting that soon, I wanted to have a splash screen just like the common desktop apps have. So that began my quest for a non-rectangular window. Fortunately WPF does have the capability, but my first attempt was using a Win32 Form and it came out pretty well. It takes a 32 bit bitmap and displays it within a form. So depending on the shape of the image you have a window. So lets look at the code.
class Splash : Form{public Splash(Bitmap bitmap){ // Window settings this.TopMost = true; this.ShowInTaskbar = false; this.Size = bitmap.Size; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Show(); // Must be called before setting bitmap this.SelectBitmap(bitmap); this.BackColor = Color.Red; this.Click += new EventHandler(Splash_Click); this.MouseClick += new MouseEventHandler(Splash_MouseClick);}void Splash_MouseClick(object sender, MouseEventArgs e){ this.Close();}void Splash_Click(object sender, EventArgs e){}// Sets the current bitmappublic void SelectBitmap(Bitmap bitmap) { // Does this bitmap contain an alpha channel? if (bitmap.PixelFormat != PixelFormat.Format32bppArgb) { throw new ApplicationException("The bitmap must be 32bpp with alpha-channel."); } // Get device contexts IntPtr screenDc = APIHelp.GetDC(IntPtr.Zero); IntPtr memDc = APIHelp.CreateCompatibleDC(screenDc); IntPtr hBitmap = IntPtr.Zero; IntPtr hOldBitmap = IntPtr.Zero; try { // Get handle to the new bitmap and select it into the current device context hBitmap = bitmap.GetHbitmap(Color.FromArgb(0)); hOldBitmap = APIHelp.SelectObject(memDc, hBitmap); // Set parameters for layered window update APIHelp.Size newSize = new APIHelp.Size(bitmap.Width, bitmap.Height); // Size window to match bitmap APIHelp.Point sourceLocation = new APIHelp.Point(0, 0); APIHelp.Point newLocation = new APIHelp.Point(this.Left, this.Top); // Same as this window APIHelp.BLENDFUNCTION blend = new APIHelp.BLENDFUNCTION(); blend.BlendOp = APIHelp.AC_SRC_OVER; // Only works with a 32bpp bitmap blend.BlendFlags = 0; // Always 0 blend.SourceConstantAlpha = 255; // Set to 255 for per-pixel alpha values blend.AlphaFormat = APIHelp.AC_SRC_ALPHA; // Only works when the bitmap contains an alpha channel // Update the window APIHelp.UpdateLayeredWindow(Handle, screenDc, ref newLocation, ref newSize, memDc, ref sourceLocation, 0, ref blend, APIHelp.ULW_ALPHA); } finally { // Release device context APIHelp.ReleaseDC(IntPtr.Zero, screenDc); if (hBitmap != IntPtr.Zero) { APIHelp.SelectObject(memDc, hOldBitmap); APIHelp.DeleteObject(hBitmap); // Remove bitmap resources } APIHelp.DeleteDC(memDc); }}protected override CreateParams CreateParams { get { // Add the layered extended style (WS_EX_LAYERED) to this window CreateParams createParams = base.CreateParams; createParams.ExStyle |= APIHelp.WS_EX_LAYERED; return createParams; }}// Let Windows drag this window for us (thinks its hitting the title bar of the window)protected override void WndProc(ref Message message) { if (message.Msg == APIHelp.WM_NCHITTEST) { // Tell Windows that the user is on the title bar (caption) message.Result= (IntPtr)APIHelp.HTCAPTION; } else { base.WndProc(ref message); }}} // Class to assist with Win32 API callsclass APIHelp {// Required constantspublic const Int32 WS_EX_LAYERED = 0x80000;public const Int32 HTCAPTION = 0x02;public const Int32 WM_NCHITTEST = 0x84;public const Int32 ULW_ALPHA = 0x02;public const byte AC_SRC_OVER = 0x00;public const byte AC_SRC_ALPHA = 0x01; public enum Bool { False = 0, True = 1} [StructLayout(LayoutKind.Sequential)]public struct Point { public Int32 x; public Int32 y; public Point(Int32 x, Int32 y) { this.x = x; this.y = y; }} [StructLayout(LayoutKind.Sequential)]public struct Size { public Int32 cx; public Int32 cy; public Size(Int32 cx, Int32 cy) { this.cx = cx; this.cy = cy; }} [StructLayout(LayoutKind.Sequential, Pack = 1)]struct ARGB { public byte Blue; public byte Green; public byte Red; public byte Alpha;} [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("gdi32.dll", ExactSpelling = true, SetLastError = true)]public static extern IntPtr CreateCompatibleDC(IntPtr hDC);[DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]public static extern IntPtr GetDC(IntPtr hWnd);[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);}
The code has comments which are self explanatory. Its much simpler in Avalon but before delving into it, I wanted to show how it can be possibly done using alpha channels.
PS:the above code is taken from one of the bloggers. Cant seem to remember the person.. Blame my memory .. ;)