В один момент возникла задача сделать TabControl по отрисованному дизайну, с вкладками с левой стороны. Сложность была в том, что проект был уже написан с использованием winform, и переделывать его целиком не хотелось. Попытался реализовать эту задачу средствами класического TabControl, но встретился со множеством проблем, связанных с этим.
Первой проблемой стало то, что если спозиционировать вкладки с левой стороны, то мы получаем следующую картину:
Но мне нужно было, чтобы надписи шли гаризонтально. Изучив чуть глубже данный контрол, решил воспользоваться параметром DrawMode=OwnerDrawFixed. Все надписи стерлись, и на кнопке стало возможным писать и рисовать. Но остался фон самой кнопки, который полностью закрасить не удалось.
Следующим шагом поменял Appearance c Normal на Buttons, был еще вариант FlatButtons, но через конструктор его поставить не удалось, а выставление в коде ни на что не повлияло.
В режиме Buttons вылезла такая ерунда:
На картинке видно, что между кнопками и набором TabPages появилось расстояние. Отуда оно взялось и каким параметром регулируется, мне выяснить так и не удалось.
Еще некоторое время я изучал существующие платные и бесплатные библиотеки контролов на наличие возможности изменения под себя вкладок TabControl, но они либо предлагали использовать заранее созданные стили, либо позволяли максимум поменять цвет.
В итоге намучившись с ним, я решил написать свой контрол, взяв за основу стандартный. Целью стало скрыть стандартные вкладки и на смену им поставить свои, завязав их на контрол.
Постараюсь подробно описать все, что для этого пришлось сделать.
Шаг 1
Для начала в проекте нужно создать новый котрол. Для этого в панели Solution Explorer кликаем правой кнопкой по проекту, далее Add->Component, в открывшейся панели вводим имя нового контрола (у меня это NewTabControl)
Шаг 2
После создания открываем код созданного контрола. В коде делаем следующие правки:
дописываем
using System.Windows.Forms;
using System.Drawing;
Создаем три класса, наследуя их от классов стандартных контролов.
Класс нового TabControl
public partial class NewTabControl: System.Windows.Forms.TabControl
Класс нового контрола
public class NewTabPanel: System.Windows.Forms.Panel
Класс одной вкладки
public class PanelTP: System.Windows.Forms.Panel
Теперь нам нужно перезагрузить следующий метод в классе NewTabControl:
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x1328 && !DesignMode) m.Result = (IntPtr)1;
else base.WndProc(ref m);
}
Данное действие позволит нам скрыть стандартные вкладки.
Теперь нам нужно связать все классы между собой. Не буду описывать весь код, его я приложу к данной статье. Опишу только самые интересные моменты.
Шаг 3
Компонуем все элементы в классе NewTabPanel:
private void InitializeComponent()
{
this.panel2 = new System.Windows.Forms.Panel(); //Панель с вкладками
this.tabControl = new NewTabControl();
this.Controls.Add(this.tabControl);
this.Controls.Add(this.panel2);
this.Size = new System.Drawing.Size(311, 361);
this.panel2.Dock = System.Windows.Forms.DockStyle.Left;
this.tabControl.Dock = System.Windows.Forms.DockStyle.Fill;
tabControl.ControlAdded += new ControlEventHandler(tc_ControlAdded); //Событие на создание новой вкладки
tabControl.ControlRemoved += new ControlEventHandler(tc_ControlRemoved); //Событие удаления вкладки
tabControl.Selected += new TabControlEventHandler(tc_Selected); //Событие выделения вкладки
}
Шаг 4
Теперь можно задать формат, как будет выглядеть сама вкладка.
На данном этапе вы можете сами расположить текст, картинку или любой другой элемент на будущей вкладке. А также задать размер и фон самой вкладки.
У себя я вывожу иконку и название вкладки.
В классе PanelTP создаем метод:
private void InitializeComponent()
{
this.Height = 27;
this.Width = 128;
this.BackgroundImage = Tabpanel.Properties.Resources.tab_c_74;
this.Click += new EventHandler(Select_Item);
PictureBox Icon;
Icon = new PictureBox();
Icon.Width = 25;
Icon.Height = 26;
Icon.Left = 3;
Icon.Top = 5;
Icon.Image = Tabpanel.Properties.Resources.green_dialbut_611;
this.Controls.Add(Icon);
Label lname;
lname = new Label();
lname.Width = 95;
lname.Height = 25;
lname.Left = 28;
lname.Top = 5;
lname.Font = new System.Drawing.Font("Times New Roman", 8f, FontStyle.Regular);
lname.Text = this.name;
lname.Click += new EventHandler(Select_Item);
this.Controls.Add(lname);
}
Шаг 5
Не буду описывать методы, обрабатывающие события, они подробно описаны в приложенном проекте. Перейду к применению.
После того как мы все сохранили, на панели Toolbox появятся новые компоненты
Теперь мы можем его разместить в нашей форме как захотим.
Чтобы добавить вкладку используем:
newTabPanel1.TabPages.Add("TabName");
Чтобы удалить:
newTabPanel1.TabPages.Remove(newTabPanel1.TabPages[id])
Где id — это номер вкадки
При такой реализации TabControl вы всегда сможете настроить сортировку между вкладками или скрыть выбранную вкладку, сделать вкладку любого размера и оформления, сделать панель с вкладками соврачиваемой и разворачиваемой.
По такому же принципу вы можете создать любой свой контрол скомпоновав и запрограммировав его из имеющихся.
Возможно, для кого-то я описал очевидные вещи, но надеюсь, найдутся и те, кому данная статья будет полезна.
Исходники проекта можно скачать тут.
Бинарник тут.
Возможно вам также будет интересна моя статья Как подключить сторонний браузер в приложении на C#