EDIT: So, I realized what caused my initial problems. After a very long time fiddling, experimenting and studying the source code of the .Net framework, here you can make the final method (given that you have a control that inherits the control you want to draw a custom frame on):
[DllImport("user32.dll")] public static extern bool RedrawWindow(IntPtr hWnd, IntPtr lprcUpdate, IntPtr hrgnUpdate, RedrawWindowFlags flags); [Flags()] public enum RedrawWindowFlags : uint { Invalidate = 0X1, InternalPaint = 0X2, Erase = 0X4, Validate = 0X8, NoInternalPaint = 0X10, NoErase = 0X20, NoChildren = 0X40, AllChildren = 0X80, UpdateNow = 0X100, EraseNow = 0X200, Frame = 0X400, NoFrame = 0X800 }
So, leave OnPaint as it is, make sure WS_BORDER set, then catch WM_NCPAINT and draw a border through hDC and make sure RedrawWindow is called in OnResize .
Perhaps it can even be extended to draw a custom scrollbar, because this is the part of the window frame that you can use during WM_NCPAINT .
I removed my old answer from this.
EDIT 2: For ComboBox you need to catch WM_PAINT in WndProc() , because for some reason .Net source for drawing ComboBox does not use OnPaint() , but WM_PAINT . So something like this:
protected override void WndProc(ref Message m) { base.WndProc(ref m); if (m.Msg == NativeMethods.WM_PAINT) { OnWmPaint(); } } private void OnWmPaint() { using (Graphics g = CreateGraphics()) { if (!_HasBorders) { g.DrawRectangle(new Pen(BackColor), new Rectangle(0, 0, this.Width - 1, this.Height - 1)); return; } if (!Enabled) { g.DrawRectangle(new Pen(_BorderColorDisabled), new Rectangle(0, 0, this.Width - 1, this.Height - 1)); return; } if (ContainsFocus) { g.DrawRectangle(new Pen(_BorderColorActive), new Rectangle(0, 0, this.Width - 1, this.Height - 1)); return; } g.DrawRectangle(new Pen(_BorderColor), new Rectangle(0, 0, this.Width - 1, this.Height - 1)); } }