I have a derived textbox which draws an XP border around the control by
catching the WM_NCPAINT message. The control works fine until the
Opacity of the form is set to something other than 0. Setting the
opacity to anything other than 1 causes all sorts of problems. For
example, the DC returned by GetWindowDC is not aligned with the actual
location of the window so the window is drawn in an incorrect location
(it's offest by the width and height of the NC border), the drawing
area in the DC is the wrong size so I cannot paint the entire NC area,
the client area is not correctly positioned and the mouse hit testing
is incorrect. In general things are a mess when opacity is set to
anything other than 1.

Any thoughts or comments?

andrew


using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;

using Barcap.GSL.Windows.Forms.Utils;

namespace XpWindows.Forms.Controls
{
/// <summary>
/// Represents a Windows XP style capable TextBox control. Displays in
XP style if the
/// AppController.Current.FormProperties.XPThemeStyle is set to other
than "None".
/// </summary>
[ToolboxBitmap(typeof(XPTextBox),"Resources.XPTextBox.bmp")]
public class XPTextBox : System.Windows.Forms.TextBox
{
#region Private Variables

private bool _enableXPStyles =
(AppController.Current.FormProperties.XPThemeStyle !=
XPThemeStyle.None);

#endregion Private Variables

#region Constructor

/// <summary>
/// Initializes a new instance of the XPTextBox class.
/// </summary>
public XPTextBox() : base()
{
}

#endregion Constructor

#region Protected Methods

/// <summary>
/// Expose whether XP styles should be used for rendering this
control (derived from the app controller).
/// </summary>
protected bool EnableXPStyles
{
get { return _enableXPStyles; }
}

/// <summary>
/// Override the paint message if XP styles are enabled.
/// </summary>
/// <param name="m">Windows message</param>
protected override void WndProc(ref Message m)
{
const int WM_NCPAINT = 0x0085;

// Base class implementation has to be called no matter what
// because the scroll bars of multiline textboxes are drawn
// in WM_NCPAINT
base.WndProc(ref m);

if ( _enableXPStyles )
{
if (m.Msg == WM_NCPAINT)
{
using(Graphics gr =
Graphics.FromHdc(Win32UI.GetWindowDC(this.Handle)))
{
// Draws a blue border around the textbox
_DrawBorder(gr, 0, 0, this.Width - 1, this.Height - 1);
// Draws over the textbox border using the textbox backcolor
_DrawInnerBorder(gr);
}
}
}
}


#endregion Protected Methods

#region Private Methods

/// <summary>
/// Draw a rectangle border.
/// </summary>
/// <param name="g">The System.Drawing.Graphics object to be used to
draw the rectangle.</param>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="width"></param>
/// <param name="height"></param>
private void _DrawBorder(Graphics g, int x, int y, int width, int
height)
{
g.DrawRectangle(new Pen(XpBorderColor, 0), x, y, width, height);
}

/// <summary>
/// Draws the inner border of the textbox control if XP style is
enabled.
/// </summary>
/// <param name="g">The System.Drawing.Graphics object to be used to
paint the inner border of the control.</param>
private void _DrawInnerBorder(Graphics g)
{
using (Pen pen = new Pen(this.BackColor, 0))
{
g.DrawRectangle(pen, 1, 1, this.Width - 3, this.Height - 3);
}
}

#endregion Private Methods
}

}