223 lines
8.3 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|
|
}
|