xenadmin/XenAdmin/Controls/BlueBorderPanel.cs
Gabor Apati-Nagy 7c0bc50b4a CA-176169: Changed copyright statements to include the comma in Citrix Systems,
Inc.

Signed-off-by: Gabor Apati-Nagy<gabor.apati-nagy@citrix.com>
2017-01-16 19:59:50 +00:00

213 lines
7.8 KiB
C#

/* Copyright (c) Citrix Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* * Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using XenAdmin.Core;
namespace XenAdmin.Controls
{
/// <summary>
/// Taken from
/// http://209.85.165.104/search?q=cache:hnUUN2Zhi7YJ:www.developersdex.com/vb/message.asp%3Fp%3D2927%26r%3D5855234+NativeMethods.GetDCEx&hl=en&ct=clnk&cd=1&gl=uk&client=firefox-a
/// </summary>
public class BlueBorderPanel : DoubleBufferedPanel
{
private Color borderColor = Drawing.XPBorderColor;
public Color BorderColor
{
get { return borderColor; }
set
{
if (borderColor != value)
{
borderColor = value;
NativeMethods.SendMessage(this.Handle,
NativeMethods.WM_NCPAINT,
(IntPtr)1, IntPtr.Zero);
}
}
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
NativeMethods.SendMessage(this.Handle,
NativeMethods.WM_NCPAINT, (IntPtr)1, IntPtr.Zero);
}
protected override void WndProc(ref Message m)
{
if (m.Msg == NativeMethods.WM_NCPAINT)
{
if (this.Parent != null)
{
NCPaint();
m.WParam = GetHRegion();
base.DefWndProc(ref m);
NativeMethods.DeleteObject(m.WParam);
m.Result = (IntPtr)1;
}
}
base.WndProc(ref m);
}
private void NCPaint()
{
if (this.Parent == null)
return;
if (this.Width <= 0 || this.Height <= 0)
return;
IntPtr windowDC = NativeMethods.GetDCEx(this.Handle,
IntPtr.Zero, NativeMethods.DCX_CACHE |
NativeMethods.DCX_WINDOW |
NativeMethods.DCX_CLIPSIBLINGS |
NativeMethods.DCX_LOCKWINDOWUPDATE);
if (windowDC.Equals(IntPtr.Zero))
return;
using (Bitmap bm = new Bitmap(this.Width, this.Height,
System.Drawing.Imaging.PixelFormat.Format32bppPArgb))
{
using (Graphics g = Graphics.FromImage(bm))
{
Rectangle borderRect = new Rectangle(0, 0,
Width - 1, Height - 1);
using (Pen borderPen = new Pen(this.borderColor, 1))
{
borderPen.Alignment = PenAlignment.Inset;
g.DrawRectangle(borderPen, borderRect);
}
// Create and Apply a Clip Region to the WindowDC
using (Region Rgn = new Region(new
Rectangle(0, 0, Width, Height)))
{
Rgn.Exclude(new Rectangle(1, 1, Width - 2, Height - 2));
IntPtr hRgn = Rgn.GetHrgn(g);
if (!hRgn.Equals(IntPtr.Zero))
NativeMethods.SelectClipRgn(windowDC, hRgn);
IntPtr bmDC = g.GetHdc();
IntPtr hBmp = bm.GetHbitmap();
IntPtr oldDC = NativeMethods.SelectObject(bmDC,
hBmp);
NativeMethods.BitBlt(windowDC, 0, 0, bm.Width,
bm.Height, bmDC, 0, 0, NativeMethods.SRCCOPY);
NativeMethods.SelectClipRgn(windowDC, IntPtr.Zero);
NativeMethods.DeleteObject(hRgn);
g.ReleaseHdc(bmDC);
NativeMethods.SelectObject(oldDC, hBmp);
NativeMethods.DeleteObject(hBmp);
bm.Dispose();
}
}
}
NativeMethods.ReleaseDC(this.Handle, windowDC);
}
private IntPtr GetHRegion()
{
//Define a Clip Region to pass back to WM_NCPAINTs wParam.
//Must be in Screen Coordinates.
IntPtr hRgn;
Rectangle winRect = this.Parent.RectangleToScreen(this.Bounds);
Rectangle clientRect =
this.RectangleToScreen(this.ClientRectangle);
Region updateRegion = new Region(winRect);
updateRegion.Complement(clientRect);
using (Graphics g = this.CreateGraphics())
hRgn = updateRegion.GetHrgn(g);
updateRegion.Dispose();
return hRgn;
}
}
internal class NativeMethods
{
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, int msg,
IntPtr wParam,
IntPtr lParam);
[DllImport("gdi32.dll")]
public static extern int SelectClipRgn(IntPtr hdc, IntPtr hrgn);
[DllImport("gdi32.dll")]
public static extern IntPtr SelectObject(IntPtr hdc,
IntPtr hgdiobj);
[DllImport("gdi32.dll")]
public static extern bool BitBlt(IntPtr hdcDest,
int nXDest, int nYDest,
int nWidth, int nHeight,
IntPtr hdcSrc,
int nXSrc, int nYSrc, int dwRop);
[DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);
[DllImport("user32.dll")]
public static extern IntPtr GetDCEx(IntPtr hWnd, IntPtr hrgnClip,
int flags);
[DllImport("user32.dll")]
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
public const int WM_NCPAINT = 0x85;
public const int DCX_WINDOW = 0x1;
public const int DCX_CACHE = 0x2;
public const int DCX_CLIPCHILDREN = 0x8;
public const int DCX_CLIPSIBLINGS = 0x10;
public const int DCX_LOCKWINDOWUPDATE = 0x400;
public const int SRCCOPY = 0xCC0020;
}
}