Most of what I have found just has people using a similar block of code as what I have done below (which I use to custom draw my border with a specific color on a user control):
// PInvoke declaration
[DllImport("User32.dll", EntryPoint = "GetDCEx")]
internal static extern IntPtr GetDCEx(IntPtr hWnd, IntPtr hRgn, int flags);
// Event Override
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
IntPtr hWnd = this.Handle;
IntPtr hRgn = IntPtr.Zero;
IntPtr hdc = GetDCEx(hWnd, hRgn, 1027);
using (Graphics grfx = Graphics.FromHdc(hdc))
{
Rectangle rect = new Rectangle(0, 0, this.Width - 1, this.Height -
1);
Pen pen = new Pen(Color.FromArgb(192, 192, 192), 1);
grfx.DrawRectangle(pen, rect);
}
}
But I don't actually know why I'm passing 1027 into the flags param. Looking at Microsoft's documentation for this method, I see that there is a list of DeviceContext values (copied below). So what does 1027 actually mean in this context?
/// <summary>Values to pass to the GetDCEx method.</summary>
[Flags()]
private enum DeviceContextValues : uint
{
/// <summary>DCX_WINDOW: Returns a DC that corresponds to the window rectangle rather
/// than the client rectangle.</summary>
Window = 0x00000001,
/// <summary>DCX_CACHE: Returns a DC from the cache, rather than the OWNDC or CLASSDC
/// window. Essentially overrides CS_OWNDC and CS_CLASSDC.</summary>
Cache = 0x00000002,
/// <summary>DCX_NORESETATTRS: Does not reset the attributes of this DC to the
/// default attributes when this DC is released.</summary>
NoResetAttrs = 0x00000004,
/// <summary>DCX_CLIPCHILDREN: Excludes the visible regions of all child windows
/// below the window identified by hWnd.</summary>
ClipChildren = 0x00000008,
/// <summary>DCX_CLIPSIBLINGS: Excludes the visible regions of all sibling windows
/// above the window identified by hWnd.</summary>
ClipSiblings = 0x00000010,
/// <summary>DCX_PARENTCLIP: Uses the visible region of the parent window. The
/// parent's WS_CLIPCHILDREN and CS_PARENTDC style bits are ignored. The origin is
/// set to the upper-left corner of the window identified by hWnd.</summary>
ParentClip = 0x00000020,
/// <summary>DCX_EXCLUDERGN: The clipping region identified by hrgnClip is excluded
/// from the visible region of the returned DC.</summary>
ExcludeRgn = 0x00000040,
/// <summary>DCX_INTERSECTRGN: The clipping region identified by hrgnClip is
/// intersected with the visible region of the returned DC.</summary>
IntersectRgn = 0x00000080,
/// <summary>DCX_EXCLUDEUPDATE: Unknown...Undocumented</summary>
ExcludeUpdate = 0x00000100,
/// <summary>DCX_INTERSECTUPDATE: Unknown...Undocumented</summary>
IntersectUpdate = 0x00000200,
/// <summary>DCX_LOCKWINDOWUPDATE: Allows drawing even if there is a LockWindowUpdate
/// call in effect that would otherwise exclude this window. Used for drawing during
/// tracking.</summary>
LockWindowUpdate = 0x00000400,
/// <summary>DCX_USESTYLE: Undocumented, something related to WM_NCPAINT message.</summary>
UseStyle = 0x00010000,
/// <summary>DCX_VALIDATE When specified with DCX_INTERSECTUPDATE, causes the DC to
/// be completely validated. Using this function with both DCX_INTERSECTUPDATE and
/// DCX_VALIDATE is identical to using the BeginPaint function.</summary>
Validate = 0x00200000,
}
1027
is 0100 0000 0011
in binary, so it’s a combination of the following flags:
The value comes from using a binary OR on the flags:
Window | Cache | LockWindowUpdate
= 0x1 | 0x2 | 0x400
= 0x403
= 1027
For clarity, you should specify the flags in code that way instead of just using a magic number:
DeviceContextValues.Window | DeviceContextValues.Cache | DeviceContextValues.LockWindowUpdate
User contributions licensed under CC BY-SA 3.0