Skip to content

Instantly share code, notes, and snippets.

@hmetgundogdu
Last active May 14, 2025 07:09
Show Gist options
  • Select an option

  • Save hmetgundogdu/ca51c8bcf337cdf14a4eac9b3b3b1e87 to your computer and use it in GitHub Desktop.

Select an option

Save hmetgundogdu/ca51c8bcf337cdf14a4eac9b3b3b1e87 to your computer and use it in GitHub Desktop.
Custom TabControl for Windows Forms with no borders by overriding TCM_ADJUSTRECT. Includes a helper to replace existing tab controls.
public partial class NoBorderTabControl : TabControl
{
/// <summary>
/// Fine-tune adjustments to hide the border more precisely.
/// </summary>
public Padding BorderAdjustments { get; set; } = new()
{
Left = 6,
Right = 6,
Top = 2,
Bottom = 6,
};
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
private const string TAB_CONTROL_NAME = "TabControlAsNoBorder";
private const int TCM_FIRST = 0x1300;
private const int TCM_ADJUSTRECT = TCM_FIRST + 40;
protected override void WndProc(ref Message m)
{
if (m.Msg == TCM_ADJUSTRECT)
{
RECT rc = Marshal.PtrToStructure<RECT>(m.LParam);
// Adjust these values depending on your needs
rc.Left -= BorderAdjustments.Left;
rc.Right += BorderAdjustments.Right;
rc.Top -= BorderAdjustments.Top;
rc.Bottom += BorderAdjustments.Bottom;
Marshal.StructureToPtr(rc, m.LParam, true);
}
base.WndProc(ref m);
}
public static TabControl ReplaceTabControl(Control originalParent, TabControl originalTabControl)
{
if (!originalParent.Controls.ContainsKey(TAB_CONTROL_NAME))
{
var newTabControl = new CustomTabControl
{
Name = TAB_CONTROL_NAME,
Size = originalTabControl.Size,
Width = originalTabControl.Width,
Location = originalTabControl.Location,
Dock = originalTabControl.Dock
};
foreach (TabPage tabpage in originalTabControl.TabPages)
{
newTabControl.TabPages.Add(tabpage);
}
originalTabControl.Hide();
if (originalParent is TableLayoutPanel parentPanel)
{
int row = parentPanel.GetRow(originalTabControl);
int column = parentPanel.GetColumn(originalTabControl);
parentPanel.SetColumnSpan(newTabControl, parentPanel.GetColumnSpan(originalTabControl));
parentPanel.Controls.Add(newTabControl, column, row);
}
else
{
if (originalTabControl.Parent is null)
{
throw new InvalidOperationException("There is no parent of tab control here");
}
originalTabControl.Parent.Controls.Add(newTabControl);
}
return newTabControl;
}
else
{
var controlNoBorder = originalParent.Controls[TAB_CONTROL_NAME];
if (controlNoBorder is TabControl)
{
return (TabControl)controlNoBorder;
}
else
{
throw new InvalidOperationException("There is no tab control in side of tab control parent children");
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment