フォームのBackgroundImageを使ったレイヤードウィンドウの作成 - C#
こちらの記事でレイヤードウィンドウの作成方法を紹介しました。今回は、フォームのBackgroundImageに設定した画像からレイヤードウィンドウを作成するコードを紹介します。
プログラム例
コード
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Drawing.Imaging;
namespace LayeredSplashWindow
{
public partial class Form1 : Form
{
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CreateCompatibleDC(IntPtr hdc);
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int DeleteObject(IntPtr hobject);
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int DeleteDC(IntPtr hdc);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int UpdateLayeredWindow(
IntPtr hwnd,
IntPtr hdcDst,
[System.Runtime.InteropServices.In()]
ref Point pptDst,
[System.Runtime.InteropServices.In()]
ref Size psize,
IntPtr hdcSrc,
[System.Runtime.InteropServices.In()]
ref Point pptSrc,
int crKey,
[System.Runtime.InteropServices.In()]
ref BLENDFUNCTION pblend,
int dwFlags);
public const byte AC_SRC_OVER = 0;
public const byte AC_SRC_ALPHA = 1;
public const int ULW_ALPHA = 2;
public const int WM_DISPLAYCHANGE = 0x007E;
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct BLENDFUNCTION
{
public byte BlendOp;
public byte BlendFlags;
public byte SourceConstantAlpha;
public byte AlphaFormat;
}
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
UpdateFormDisplay(this.BackgroundImage);
}
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle = cp.ExStyle | WindowsConst.WS_EX_LAYERED;
if ((cp.ExStyle & WindowsConst.WS_EX_TRANSPARENT) != 0){
cp.ExStyle = cp.ExStyle & WindowsConst.WS_EX_TRANSPARENT;
}
return cp;
}
}
public void UpdateFormDisplay(Image backgroundImage)
{
IntPtr screenDc = GetDC(IntPtr.Zero);
IntPtr memDc = CreateCompatibleDC(screenDc);
IntPtr hBitmap = IntPtr.Zero;
IntPtr oldBitmap = IntPtr.Zero;
try {
//Display-image
Bitmap bmp = new Bitmap(backgroundImage);
hBitmap = bmp.GetHbitmap(Color.FromArgb(0));
oldBitmap = SelectObject(memDc, hBitmap);
//Display-rectangle
Size size = bmp.Size;
Point pointSource = new Point(0, 0);
Point topPos = new Point(this.Left, this.Top);
//Set up blending options
BLENDFUNCTION blend = new BLENDFUNCTION();
blend.BlendOp = AC_SRC_OVER;
blend.BlendFlags = 0;
blend.SourceConstantAlpha = 255;
blend.AlphaFormat = AC_SRC_ALPHA;
UpdateLayeredWindow(this.Handle, screenDc,
ref topPos, ref size, memDc, ref pointSource, 0, ref blend, ULW_ALPHA);
//Clean-up
bmp.Dispose();
ReleaseDC(IntPtr.Zero, screenDc);
if (hBitmap != IntPtr.Zero) {
SelectObject(memDc, oldBitmap);
DeleteObject(hBitmap);
}
DeleteDC(memDc);
}
catch (Exception) {
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MultiFormApp
{
public static class WindowsConst
{
public const int WM_NCHITTEST = 0x0084;
/*
* Window Styles
*/
public const int WS_OVERLAPPED = 0x00000000;
public const long WS_POPUP = 0x80000000L; //unchecked((int) WS_POPUP)
public const int WS_CHILD = 0x40000000;
public const int WS_MINIMIZE = 0x20000000;
public const int WS_VISIBLE = 0x10000000;
public const int WS_DISABLED = 0x08000000;
public const int WS_CLIPSIBLINGS = 0x04000000;
public const int WS_CLIPCHILDREN = 0x02000000;
public const int WS_MAXIMIZE = 0x01000000;
public const int WS_CAPTION = 0x00C00000;/* WS_BORDER | WS_DLGFRAME */
public const int WS_BORDER = 0x00800000;
public const int WS_DLGFRAME = 0x00400000;
public const int WS_VSCROLL = 0x00200000;
public const int WS_HSCROLL = 0x00100000;
public const int WS_SYSMENU = 0x00080000;
public const int WS_THICKFRAME = 0x00040000;
public const int WS_GROUP = 0x00020000;
public const int WS_TABSTOP = 0x00010000;
public const int WS_MINIMIZEBOX = 0x00020000;
public const int WS_MAXIMIZEBOX = 0x00010000;
public const int WS_TILED = WS_OVERLAPPED;
public const int WS_ICONIC = WS_MINIMIZE;
public const int WS_SIZEBOX = WS_THICKFRAME;
public const int WS_TILEDWINDOW = WS_OVERLAPPEDWINDOW;
/*
* Common Window Styles
*/
public const int WS_OVERLAPPEDWINDOW = (WS_OVERLAPPED |
WS_CAPTION |
WS_SYSMENU |
WS_THICKFRAME |
WS_MINIMIZEBOX |
WS_MAXIMIZEBOX);
public const long WS_POPUPWINDOW = (WS_POPUP |
WS_BORDER |
WS_SYSMENU);
public const int WS_CHILDWINDOW = (WS_CHILD);
/*
* Extended Window Styles
*/
public const int WS_EX_DLGMODALFRAME = 0x00000001;
public const int WS_EX_NOPARENTNOTIFY = 0x00000004;
public const int WS_EX_TOPMOST = 0x00000008;
public const int WS_EX_ACCEPTFILES = 0x00000010;
public const int WS_EX_TRANSPARENT = 0x00000020;
public const int WS_EX_MDICHILD = 0x00000040;
public const int WS_EX_TOOLWINDOW = 0x00000080;
public const int WS_EX_WINDOWEDGE = 0x00000100;
public const int WS_EX_CLIENTEDGE = 0x00000200;
public const int WS_EX_CONTEXTHELP = 0x00000400;
public const int WS_EX_RIGHT = 0x00001000;
public const int WS_EX_LEFT = 0x00000000;
public const int WS_EX_RTLREADING = 0x00002000;
public const int WS_EX_LTRREADING = 0x00000000;
public const int WS_EX_LEFTSCROLLBAR = 0x00004000;
public const int WS_EX_RIGHTSCROLLBAR = 0x00000000;
public const int WS_EX_CONTROLPARENT = 0x00010000;
public const int WS_EX_STATICEDGE = 0x00020000;
public const int WS_EX_APPWINDOW = 0x00040000;
public const int WS_EX_OVERLAPPEDWINDOW = (WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE);
public const int WS_EX_PALETTEWINDOW
= (WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST);
public const int WS_EX_LAYERED = 0x00080000;
public const int WS_EX_NOINHERITLAYOUT = 0x00100000;
// Disable inheritence of mirroring by children
public const int WS_EX_LAYOUTRTL = 0x00400000; // Right to left mirroring
public const int WS_EX_COMPOSITED = 0x02000000;
public const int WS_EX_NOACTIVATE = 0x08000000;
/*
* WM_NCHITTEST and MOUSEHOOKSTRUCT Mouse Position Codes
*/
public const int HTERROR = (-2);
public const int HTTRANSPARENT = (-1);
public const int HTNOWHERE = 0;
public const int HTCLIENT = 1;
public const int HTCAPTION = 2;
public const int HTSYSMENU = 3;
public const int HTGROWBOX = 4;
public const int HTSIZE = HTGROWBOX;
public const int HTMENU = 5;
public const int HTHSCROLL = 6;
public const int HTVSCROLL = 7;
public const int HTMINBUTTON = 8;
public const int HTMAXBUTTON = 9;
public const int HTLEFT = 10;
public const int HTRIGHT = 11;
public const int HTTOP = 12;
public const int HTTOPLEFT = 13;
public const int HTTOPRIGHT = 14;
public const int HTBOTTOM = 15;
public const int HTBOTTOMLEFT = 16;
public const int HTBOTTOMRIGHT = 17;
public const int HTBORDER = 18;
public const int HTREDUCE = HTMINBUTTON;
public const int HTZOOM = HTMAXBUTTON;
public const int HTSIZEFIRST = HTLEFT;
public const int HTSIZELAST = HTBOTTOMRIGHT;
public const int HTOBJECT = 19;
public const int HTCLOSE = 20;
public const int HTHELP = 21;
}
}
画像 (Photoshop編集時)
画像は背景を抜き、透明部分を含む画像を用意します。
デザイン画面
フォームのBackgourndImageに上図の画像を設定します。
実行結果
プロジェクトを実行します。下図のウィンドウが表示されます。
画像をファイルから読み込む場合
レイヤードウィンドウのマスク画像をフォームのBackGroundImageではなくファイルから読み込む場合のコードです。下記のコードでも正しく動作します。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Drawing.Imaging;
namespace LayeredSplashWindow
{
public partial class Form1 : Form
{
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CreateCompatibleDC(IntPtr hdc);
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int DeleteObject(IntPtr hobject);
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int DeleteDC(IntPtr hdc);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int UpdateLayeredWindow(
IntPtr hwnd,
IntPtr hdcDst,
[System.Runtime.InteropServices.In()]
ref Point pptDst,
[System.Runtime.InteropServices.In()]
ref Size psize,
IntPtr hdcSrc,
[System.Runtime.InteropServices.In()]
ref Point pptSrc,
int crKey,
[System.Runtime.InteropServices.In()]
ref BLENDFUNCTION pblend,
int dwFlags);
public const byte AC_SRC_OVER = 0;
public const byte AC_SRC_ALPHA = 1;
public const int ULW_ALPHA = 2;
public const int WM_DISPLAYCHANGE = 0x007E;
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct BLENDFUNCTION
{
public byte BlendOp;
public byte BlendFlags;
public byte SourceConstantAlpha;
public byte AlphaFormat;
}
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
//UpdateFormDisplay(this.BackgroundImage);
Bitmap bmp = new Bitmap("fig.png");
UpdateFormDisplay(bmp);
}
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle = cp.ExStyle | WindowsConst.WS_EX_LAYERED;
if ((cp.ExStyle & WindowsConst.WS_EX_TRANSPARENT) != 0){
cp.ExStyle = cp.ExStyle & WindowsConst.WS_EX_TRANSPARENT;
}
return cp;
}
}
public void UpdateFormDisplay(Image backgroundImage)
{
IntPtr screenDc = GetDC(IntPtr.Zero);
IntPtr memDc = CreateCompatibleDC(screenDc);
IntPtr hBitmap = IntPtr.Zero;
IntPtr oldBitmap = IntPtr.Zero;
try {
//Display-image
Bitmap bmp = new Bitmap(backgroundImage);
hBitmap = bmp.GetHbitmap(Color.FromArgb(0));
oldBitmap = SelectObject(memDc, hBitmap);
//Display-rectangle
Size size = bmp.Size;
Point pointSource = new Point(0, 0);
Point topPos = new Point(this.Left, this.Top);
//Set up blending options
BLENDFUNCTION blend = new BLENDFUNCTION();
blend.BlendOp = AC_SRC_OVER;
blend.BlendFlags = 0;
blend.SourceConstantAlpha = 255;
blend.AlphaFormat = AC_SRC_ALPHA;
UpdateLayeredWindow(this.Handle, screenDc,
ref topPos, ref size, memDc, ref pointSource, 0, ref blend, ULW_ALPHA);
//Clean-up
bmp.Dispose();
ReleaseDC(IntPtr.Zero, screenDc);
if (hBitmap != IntPtr.Zero) {
SelectObject(memDc, oldBitmap);
DeleteObject(hBitmap);
}
DeleteDC(memDc);
}
catch (Exception) {
}
}
}
}
参考記事
http://www.vcskicks.com/splash-screen.php
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用