/* 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 { // 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 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; } }