223 lines
8.3 KiB
C#

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
namespace DevComponents.DotNetBar
{
/// <summary>
/// Summary description for PopupShadow.
/// </summary>
internal class PopupShadow : System.Windows.Forms.Control
{
private bool m_AlphaShadow=true;
public PopupShadow(bool bAlphaShadow)
{
m_AlphaShadow=bAlphaShadow;
this.Visible=false;
this.SuspendLayout();
if(!m_AlphaShadow)
this.BackColor=SystemColors.ControlDark;
//this.ControlBox = false;
//this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
//this.MaximizeBox = false;
//this.MinimizeBox = false;
//this.Opacity = 0.4;
//this.ShowInTaskbar = false;
//this.AutoScale=false;
this.Size=new Size(12,12);
//this.StartPosition=FormStartPosition.Manual;
//this.MinimumSize=new Size(4,4); // This was the key to fix the black box that was showing up for smaller windows
this.SetStyle(ControlStyles.ContainerControl,false);
//this.TopLevel=false;
this.SetStyle(ControlStyles.Selectable,false);
if(m_AlphaShadow)
{
this.SetStyle(ControlStyles.AllPaintingInWmPaint,true);
this.SetStyle(DisplayHelp.DoubleBufferFlag,false);
}
this.ResumeLayout();
}
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
//NativeFunctions.SetLayeredWindowAttributes(this.Handle,Color.Black.ToArgb(),102,NativeFunctions.LWA_ALPHA);
// We want to make the entire bitmap opaque
}
private void PaintShadow()
{
if(this.Width <= 0 || this.Height <= 0) return;
// Create bitmap for drawing onto
using (Bitmap memoryBitmap = new Bitmap(this.Width, this.Height, PixelFormat.Format32bppArgb))
{
using (Graphics g = Graphics.FromImage(memoryBitmap))
{
Rectangle area = new Rectangle(0, 0, this.Width, this.Height);
System.Drawing.Region reg = new System.Drawing.Region();
System.Drawing.Drawing2D.GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath();
Rectangle r = this.ClientRectangle;
const int TRIANGLESIZE = 5;
path.StartFigure();
path.AddLine(r.Right - TRIANGLESIZE, r.Top, r.Right, r.Top);
path.AddLine(r.Right, r.Top, r.Right, r.Top + TRIANGLESIZE);
path.AddLine(r.Right, r.Top + TRIANGLESIZE, r.Right - TRIANGLESIZE, r.Top);
path.CloseFigure();
path.StartFigure();
path.AddLine(r.Left, r.Bottom - TRIANGLESIZE - 1, r.Left, r.Bottom);
path.AddLine(r.Left, r.Bottom, r.Left + TRIANGLESIZE, r.Bottom);
path.AddLine(r.Left + TRIANGLESIZE, r.Bottom, r.Left, r.Bottom - TRIANGLESIZE);
path.CloseFigure();
path.StartFigure();
path.AddRectangle(new Rectangle(0, 0, r.Width - TRIANGLESIZE, r.Height - TRIANGLESIZE));
path.CloseFigure();
reg.Xor(path);
g.SetClip(reg, System.Drawing.Drawing2D.CombineMode.Replace);
path.Dispose();
path = null;
reg.Dispose();
reg = null;
// Draw the background area
g.Clear(Color.Transparent);
g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
// Draw Actual Shadow
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
g.Clear(Color.Black);
const int EDGE = 4;
r.Width--;
r.Height--;
Color[] clr = new Color[]{
Color.FromArgb(14,Color.Black),
Color.FromArgb(43,Color.Black),
Color.FromArgb(84,Color.Black),
Color.FromArgb(113,Color.Black),
Color.FromArgb(128,Color.Black)};
for (int i = 0; i < EDGE; i++)
{
using (Pen pen = new Pen(clr[i], 1))
{
using (GraphicsPath tempPath = GetPath(r, EDGE - i))
g.DrawPath(pen, tempPath);
r.Inflate(-1, -1);
}
}
// Get hold of the screen DC
IntPtr hDC = NativeFunctions.GetDC(IntPtr.Zero);
// Create a memory based DC compatible with the screen DC
IntPtr memoryDC = WinApi.CreateCompatibleDC(hDC);
// Get access to the bitmap handle contained in the Bitmap object
IntPtr hBitmap = memoryBitmap.GetHbitmap(Color.FromArgb(0));
// Select this bitmap for updating the window presentation
IntPtr oldBitmap = WinApi.SelectObject(memoryDC, hBitmap);
// New window size
NativeFunctions.SIZE ulwsize;
ulwsize.cx = this.Width;
ulwsize.cy = this.Height;
// New window position
NativeFunctions.POINT topPos;
topPos.x = this.Left;
topPos.y = this.Top;
// Offset into memory bitmap is always zero
NativeFunctions.POINT pointSource;
pointSource.x = 0;
pointSource.y = 0;
// We want to make the entire bitmap opaque
NativeFunctions.BLENDFUNCTION blend = new NativeFunctions.BLENDFUNCTION();
blend.BlendOp = (byte)NativeFunctions.Win23AlphaFlags.AC_SRC_OVER;
blend.BlendFlags = 0;
blend.SourceConstantAlpha = 255;
blend.AlphaFormat = (byte)NativeFunctions.Win23AlphaFlags.AC_SRC_ALPHA;
// Tell operating system to use our bitmap for painting
NativeFunctions.UpdateLayeredWindow(Handle, hDC, ref topPos, ref ulwsize,
memoryDC, ref pointSource, 0, ref blend,
(int)NativeFunctions.Win32UpdateLayeredWindowsFlags.ULW_ALPHA);
// Put back the old bitmap handle
WinApi.SelectObject(memoryDC, oldBitmap);
// Cleanup resources
WinApi.ReleaseDC(IntPtr.Zero, hDC);
WinApi.DeleteObject(hBitmap);
WinApi.DeleteDC(memoryDC);
}
}
}
public void UpdateShadow()
{
if(!m_AlphaShadow)
return;
PaintShadow();
}
private System.Drawing.Drawing2D.GraphicsPath GetPath(Rectangle r, int pathSize)
{
System.Drawing.Drawing2D.GraphicsPath path=new System.Drawing.Drawing2D.GraphicsPath();
path.AddArc(r.Right-pathSize,r.Y,pathSize,pathSize,270,90);
path.AddLine(r.Right,r.Y+pathSize,r.Right,r.Bottom-pathSize);
path.AddArc(r.Right-pathSize,r.Bottom-pathSize,pathSize,pathSize,0,90);
path.AddLine(r.Right-pathSize,r.Bottom,r.X,r.Bottom);
path.AddLine(r.X,r.Bottom,r.X,r.Top);
return path;
}
protected override void OnPaint(PaintEventArgs e)
{
if(!m_AlphaShadow)
{
e.Graphics.Clear(this.BackColor);
return;
}
}
protected override void WndProc(ref Message m)
{
const int WM_MOUSEACTIVATE = 0x21;
const int MA_NOACTIVATE = 3;
//const int MA_NOACTIVATEANDEAT = 4;
if(m.Msg==WM_MOUSEACTIVATE)
{
m.Result=new System.IntPtr(MA_NOACTIVATE);
return;
}
base.WndProc(ref m);
}
protected override CreateParams CreateParams
{
get
{
const uint WS_POPUP=0x80000000;
const uint WS_CLIPSIBLINGS=0x04000000;
const uint WS_CLIPCHILDREN=0x02000000;
const int WS_EX_TOPMOST=0x00000008;
const int WS_EX_LAYERED=0x00080000;
const int WS_EX_TOOLWINDOW=0x00000080;
CreateParams p=base.CreateParams;
p.ExStyle=(p.ExStyle | WS_EX_TOPMOST | (m_AlphaShadow?WS_EX_LAYERED:0) | WS_EX_TOOLWINDOW);
p.Style=unchecked((int)(WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN));
p.Caption=""; // Setting caption would show window under tasks in Windows Task Manager
return p;
}
}
}
}