Создание собственного контрола на основе TabControl в C#

В один момент возникла задача сделать TabControl по отрисованному дизайну, с вкладками с левой стороны. Попытался реализовать эту задачу средствами класического 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 вы всегда сможете настроить сортировку между вкладками или скрыть выбранную вкладку, сделать вкладку любого размера и оформления, сделать панель с вкладками соврачиваемой и разворачиваемой.
По такому же принципу вы можете создать любой свой контрол скомпоновав и запрограммировав его из имеющихся.

Возможно, для кого-то я описал очевидные вещи, но надеюсь, найдутся и те, кому данная статья будет полезна.

Исходники проекта можно скачать тут.
Бинарник тут.

ссылка на оригинал статьи http://habrahabr.ru/post/170375/

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *