Окна нестандартной формы

Одной из интереснейших особенностей окон в приложениях .NET является то, что программист может задать им нестандартную форму (например как у Windows Media Player). Это позволяет сделать интерфейс программ более привлекательным, что является важным моментом у различного рода мультимедийных приложений. В этой статье я опишу как задать окнам в приложениях на C# нестандартную форму.

Шаг 1. Создаем в своем любимом графическом редакторе картинку, которая будет выступать формой нашего окна. Не нужную область (область которую мы хотим сделать прозрачной (Background)) обязательно закрашиваем в черный цвет. На основании этого цвета и будет производиться «формовка» окна.
Изображение, используемое в качестве формы окна

Шаг 2. Создаем в Microsoft Visual Studio .NET новый проект оконной программы (Windows Application Project).

Шаг 3. В свойствах формы устанавливаем свойство FormBorderStyle (стиль рамки окна) в None. В качестве BackgroundImage указываем изображение, которое создали на шаге 1. В свойстве TransparencyKey указываем черый цвет (тот цвет, которым закрасили не нужную область изображения).

Шаг 4. Установка FormBorderStyle в None приводит к исчезновению строки заголовка окна с кнопками сворачивания/разворачивания и закрытия окна, поэтому нужно создать эти кнопки вручную. Добавляем из тулбокса (ToolBox) две обычные кнопки для закрытия и сворачивания окна. Одной в свойстве Text указываем «X», а другой «_».
Добавляем кнопки закрытия и сворачивания окна на форму
У кнопки «X» в событии OnClick описываем процедуру закрытия окна:
private void button1_Click(object sender, System.EventArgs e)
{
this.Close();
}

А у кнопки с «_» — процедуру сворачивания:
private void button2_Click(object sender, System.EventArgs e)
{
this.WindowState=FormWindowState.Minimized;
}

Шаг 5. Теперь заставим форму перемещаться мышкой. Создаем новую публичную переменную mouse_offset типа Point:
public Point mouse_offset;
Добавляем форме обработчик события MouseDown, и описываем в нем процедуру инициализации переменной mouse_offset:
private void Form1_MouseDown(object sender,
System.Windows.Forms.MouseEventArgs e)
{
mouse_offset = new Point(-e.X, -e.Y);
}

Теперь создаем обработчик события MouseMove нашей формы, в котором и будет производиться определение текущих координат курсора и собственно перемещение формы:
private void Form1_MouseMove(object sender,
System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
Point mousePos = Control.MousePosition;
mousePos.Offset(mouse_offset.X, mouse_offset.Y); // определяем текущие координаты курсора...
Location = mousePos; // ... и перемещаем форму
}
}

Сохраняем приложение и давим F5. Попробуйте перетянуть форму за любой уччасток — она переместится. Кнопка сворачивания свернет форму, а кнопка закрытия — закроет.
Окно нестандартной формы в действии
Все, конечно, хорошо, но чего-то не хватает...
Добавим плавное появление формы (Fade-In).
За прозрачноссть формы отвечает ее свойство Opacity. Значение 0 — полная прозрачность формы, 1 — полная непрозрачность. Устанавливаем у нашей формы это свойство в 0.
Добавляем на форму таймер (Timer) и включаем его (устанавливаем свойство Enabled в true). Свойство Interval устанавливаем равным 20.
Теперь добавляем обработчик «тиканья» таймера (Tick) со следующим кодом:
this.Opacity += 0.05;
if (this.Opacity >= .95)
{
this.Opacity = 1;
timer1.Enabled = false;
}

Здесь мы в цикле постепенно ослабляем прозрачность формы пока она не станет равной единице, после чего отключаем таймер.
Попробуйте запустить программу, и увидите как форма плавно появляется на экране.

Скачать пример



Поблагодарить автора

Comments:

8 Responses to Окна нестандартной формы

  1. Не актуально в силу следующей проблемы:

    при добавлении других контролов на форму, тех же label-ов или картинок — за них тоже нужно двигать форму.

    Ставить каждому новому контролу событие — неверное решение.

    Да и работает оно при таком раскладе не верно.

    Попробуй к себе текст добавь и потягай

  2. Да, есть такое дело, за другие контролы не перетягивается.

    В таком случае можно в событии OnLoad формы пройтись по коллекции контролов и добавить новое событие для MouseMove и MouseDown:

    foreach (Control control in this.Controls)

    {

    control.MouseMove += new MouseEventHandler (Form1_MouseMove);

    control.MouseDown += new MouseEventHandler (Form1_MouseDown);

    }

    Текущие обработчики этих событий это не заменит (будут выполняться оба обработчика).

    А проблему с тем, что функция перемещения «работает не верно» можно исправить немного преобразовав функцию-обработчик события onMouseMove:

    if (sender != this)

    {

    Control control = (Control) sender;

    mouse_offset = new Point (-e.X — control.Location.X, -e.Y — control.Location.Y);

    }

    else

    {

    mouse_offset = new Point (-e.X, -e.Y);

    }

    Вот доработанный пример.

  3. Но плавное появление справедливо олько для Vista или Seven. Или я ощибаюсь?

  4. У меня при появлении сначала отображается весь рисунок вместе с черным.

  5. protected const int WM_NCHITTEST = 0×0084;

    protected const int HTCAPTION = 2;

    protected override void WndProc (ref Message m)

    {

    if (m.Msg == WM_NCHITTEST)

    {

    m.Result = (IntPtr) HTCAPTION;

    return;

    }

    base.WndProc (ref m);

    }

    Это работает очень даже хорошо. Пример был взят из инета.

    Возникает другая проблема: Как теперь свернуть окно по двойному щелчку мыши в произвольном месте формы? Даже если подписаться на событие, оно не будет обрабатываться.

Оставить комментарий

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>