using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace AppliStation.Util
{
public class DisplayDeviceContext : IDeviceContext, IDisposable
{
private HandleRef hWnd;
private IntPtr hDc;
private bool isGottenDc;
///
/// ディスプレイコンテクストの生成
///
/// ウィンドウハンドル
public DisplayDeviceContext(IntPtr hWnd)
: this(new HandleRef(null, hWnd))
{
}
///
/// ディスプレイコンテクストの生成
///
/// ウィンドウハンドル
public DisplayDeviceContext(HandleRef hWnd)
{
this.hWnd = hWnd;
this.hDc = GetDC(hWnd);
this.isGottenDc = true;
}
protected DisplayDeviceContext(IntPtr hDc, bool isGottenDc)
{
this.hDc = hDc;
this.isGottenDc = isGottenDc;
}
public static DisplayDeviceContext FromHdc(IntPtr hDc)
{
return new DisplayDeviceContext(hDc, false);
}
public DisplayDeviceContext CreateCompatibleDisplayDeviceContext()
{
return FromHdc(CreateCompatibleDC(hDc));
}
public IntPtr GetHdc()
{
return hDc;
}
public void ReleaseHdc()
{
if (this.isGottenDc) { // GetDC 関数を使って取得した場合
int result = ReleaseDC(hWnd, hDc);
if (result != 1) {
throw new System.ComponentModel.Win32Exception();
}
} else {
DeleteObject(hDc);
}
}
public void Dispose()
{
ReleaseHdc();
GC.SuppressFinalize(this);
}
///
/// 指定されたデバイスコンテキストのオブジェクトを選択
///
///
/// context.SelectObject(bitmap.GetHbitmap(Color.FromArgb(0)));
///
/// 選択するオブジェクトのハンドル
/// 置き換えが発生する前のオブジェクトのハンドル
public IntPtr SelectObject(IntPtr hGdiObj)
{
return SelectObject(hDc, hGdiObj);
}
#region DllImport
[DllImport("user32.dll")]
private static extern IntPtr GetDC(HandleRef hWnd);
[DllImport("user32.dll")]
private static extern int ReleaseDC(HandleRef hWnd, IntPtr hDC);
[DllImport("gdi32.dll", SetLastError=true)]
private static extern IntPtr CreateCompatibleDC(IntPtr hdc);
[DllImport("gdi32.dll", ExactSpelling=true, PreserveSig=true, SetLastError=true)]
private static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);
[DllImport("gdi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DeleteObject(IntPtr hObject);
#endregion
}
public class SprashScreenLayered : Form
{
public static Form CreateSprashScreenLayered(Image img, Color bgColor)
{
Form form;
SprashScreenLayered ss = null;
if (OSFeature.Feature.IsPresent(OSFeature.LayeredWindows)) {
form = ss = new SprashScreenLayered();
form.BackgroundImage = img;
} else {
form = new Form();
form.BackgroundImage = img;
form.BackColor = bgColor;
}
//form.ShowInTaskbar = false;
form.ControlBox = false;
form.FormBorderStyle = FormBorderStyle.None;
form.StartPosition = FormStartPosition.CenterScreen;
form.Size = img.Size;
if (ss != null) {
ss.CenterToScreen2();
}
return form;
}
public SprashScreenLayered()
{
}
protected internal void CenterToScreen2()
{
base.CenterToScreen();
}
protected override CreateParams CreateParams {
get {
CreateParams param = base.CreateParams;
// param.ExStyle |= WS_EX_LAYERED;
param.ExStyle |= 0x00080000;
return param;
}
}
public override Image BackgroundImage {
set {
base.BackgroundImage = value;
updateLayeredWindow();
}
}
#region UpdateLayeredWindow関連
[DllImport("user32.dll", ExactSpelling=true, SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst,
[In] ref Point pptDst, [In] ref Size psize,
IntPtr hdcSrc, [In] ref Point pptSrc,
uint crKey,
[In] ref BLENDFUNCTION pblend,
uint dwFlags);
private static Bitmap convertBitmap(Image img)
{
Bitmap bitmap;
bitmap = img as Bitmap;
if (bitmap == null) {
bitmap = new Bitmap(img.Width, img.Height, img.PixelFormat);
Graphics.FromImage(bitmap).DrawImage(img, 0, 0);
}
return bitmap;
}
protected void updateLayeredWindow()
{
Point ptDest = this.Location;
Point ptSrc = Point.Empty;
Size size = BackgroundImage.Size;
BLENDFUNCTION blend = new BLENDFUNCTION();
blend.BlendOp = 0; // AC_SRC_OVER
blend.BlendFlags = 0;
blend.SourceConstantAlpha = 255;
blend.AlphaFormat = 1; // AC_SRC_ALPHA
using(DisplayDeviceContext screen = new DisplayDeviceContext(IntPtr.Zero))
using(DisplayDeviceContext mem = screen.CreateCompatibleDisplayDeviceContext())
using(DisplayDeviceContext hBitmap = DisplayDeviceContext.FromHdc(
convertBitmap(BackgroundImage).GetHbitmap(Color.FromArgb(0))
)) {
IntPtr hOldBitmap = IntPtr.Zero;
try {
hOldBitmap = mem.SelectObject(hBitmap.GetHdc());
UpdateLayeredWindow(this.Handle, screen.GetHdc(),
ref ptSrc, ref size,
mem.GetHdc(), ref ptDest,
0,
ref blend,
2 /* ULW_ALPHA */);
} finally {
if (hBitmap.GetHdc() != IntPtr.Zero) {
mem.SelectObject(hOldBitmap);
}
}
}
}
[StructLayout(LayoutKind.Sequential, Pack=1)]
protected internal struct BLENDFUNCTION
{
public byte BlendOp;
public byte BlendFlags;
public byte SourceConstantAlpha;
public byte AlphaFormat;
}
#endregion
}
}