Mail.ruПочтаМой МирОдноклассникиВКонтактеИгрыЗнакомстваНовостиКалендарьОблакоЗаметкиВсе проекты

Как сделать кастомную рамку окна в приложении Windows Forms C#?

Глеб Швец Ученик (106), закрыт 1 год назад
Причём не нужна не тупа рамка с BorderStyle=None, а чтобы можно было МЕНЯТЬ её размер, то есть растягивать её за края. Как такое сделать?
Лучший ответ
Андрей Журавлев Мастер (2228) 1 год назад
В любом случае сначала нужно отключить дефолтную отрисовку и включить перерисовку формы при изменении размера:
 FormBorderStyle = FormBorderStyle.None; 
SetStyle(ControlStyles.ResizeRedraw, true);
Изменение размера придется реализовывать самостоятельно, но можно воспользоваться возможностями win api и просто переписать WndProc формы:
 private const int HeaderHeight = 32; 
private const int BorderSize = 4;
private const int CornerSize = 8;

protected override void WndProc(ref Message message)
{
if (message.Msg == 0x84)
{
var cPosition = PointToClient(new((int)message.LParam & 0xffff, (int)message.LParam >> 16));

if (cPosition.Y <= BorderSize)
{
if (cPosition.X <= CornerSize)
{
message.Result = 13; // top left
return;
}

if (cPosition.X >= ClientSize.Width - CornerSize)
{
message.Result = 14; // top right
return;
}

message.Result = 12; // top
return;
}

if (cPosition.Y >= ClientSize.Height - BorderSize)
{
if (cPosition.X <= CornerSize)
{
message.Result = 16; // bottom left
return;
}

if (cPosition.X >= ClientSize.Width - CornerSize)
{
message.Result = 17; // bottom right
return;
}

message.Result = 15; //bottom
return;
}

if (cPosition.X <= BorderSize)
{
if (cPosition.Y <= CornerSize)
{
message.Result = 13; // top left
return;
}

if (cPosition.Y >= ClientSize.Height - CornerSize)
{
message.Result = 16; // bottom left
return;
}

message.Result = 10; // left
return;
}

if (cPosition.X >= ClientSize.Width - CornerSize)
{
if (cPosition.Y <= CornerSize)
{
message.Result = 14; // top right
return;
}

if (cPosition.Y >= ClientSize.Height - CornerSize)
{
message.Result = 17; // bottom right
return;
}

message.Result = 11; // right
return;
}

if (cPosition.Y <= HeaderHeight)
{
message.Result = 2; // caption
return;
}

}

base.WndProc(ref message);
}
Отрисовку границ и заголовка (если надо) так же нужно делать самостоятельно в OnPaint или любым другим удобны способом, например:
 protected override void OnPaint(PaintEventArgs e) 
{
ControlPaint.DrawBorder(e.Graphics, ClientRectangle, Color.DarkGoldenrod, ButtonBorderStyle.Solid);
e.Graphics.FillRectangle(new LinearGradientBrush(new(0, 0), new(Width, Width), Color.DarkGoldenrod, Color.Goldenrod), new(0, 0, Width, HeaderHeight));
e.Graphics.DrawString(Text, new Font(Font, FontStyle.Bold), Brushes.LightGoldenrodYellow, 10, 2);
}
Ну и если понадобится функционал кнопок, то придется восстанавливать самому.
Еще нужно учитывать, что если зона границы или заголовка будет перекрыта другим контролом, то ресайз или перетаскивание работать не будет, а значить необходимо оставлять отступы.
Остальные ответы
Александр Просветленный (21533) 1 год назад
На WinForms скорее всего никак, потому что формы унаследованы от стандартного окна Win32Window и переопределить его нет возможности. А вот в WPF такое можно сделать.
Похожие вопросы