C# Winforms - 如何创建自定义窗口边框和关闭/最小化按钮?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/305937/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Winforms - How do I create a custom windows border and close/minimise buttons?
提问by Brian Lyttle
I would like to be able to create a black custom window (with border and controls) like that shipped as part of expression blend, Twirl, or Adobe Lightroom.
我希望能够创建一个黑色自定义窗口(带有边框和控件),就像作为 expression blend、Twirl 或 Adobe Lightroom 的一部分提供的那样。
How do I create an owner-drawn window?
如何创建所有者绘制的窗口?
回答by MusiGenesis
If the custom-chrome tools don't provide you with the look-and-feel that you want, this kind of thing is easy to do yourself in C#. Basically, you create a borderless form (FormBorderStyle = None) and then create all the controls and borders yourself, by placing controls where you need them (a label for the title bar, command buttons for close and minimize etc.) and/or drawing directly on the form's surface using the Graphics object.
如果自定义镶边工具不能为您提供您想要的外观,这种事情很容易在 C# 中自己完成。基本上,您创建一个无边框表单(FormBorderStyle = None),然后通过将控件放置在您需要的位置(标题栏的标签、关闭和最小化的命令按钮等)和/或绘图,自己创建所有控件和边框使用 Graphics 对象直接在窗体的表面上。
You also have to implement code to allow the form to be dragged around by its "fake" title bar (see this answerfor a sample of how to do this). You may also have to implement your own resizing mechanism (if you need the forms to be resizable).
您还必须实现代码以允许通过其“假”标题栏拖动表单(有关如何执行此操作的示例,请参阅此答案)。您可能还必须实现自己的调整大小机制(如果您需要调整表单的大小)。
Finally, although the custom-form code might be a bit clunky, you can implement it on a single form and then have all the other forms in your application inherit from this form, which makes it a very useful technique for custom-skinning an entire application.
最后,虽然自定义表单代码可能有点笨拙,但您可以在单个表单上实现它,然后让应用程序中的所有其他表单都继承自该表单,这使其成为自定义整个表单的非常有用的技术应用。
回答by Nikita
My task was to make active window more noticeable, bright - than others, inactive windows of the app. App has many opened windows, some modal, some modeless - and the MDI parent one.
我的任务是使活动窗口比其他应用程序的非活动窗口更引人注目、更明亮。应用程序有许多打开的窗口,有些是模态的,有些是非模态的——还有 MDI 父窗口。
You can can use something like not-a-border - a frame inside the client area. Here is the code snippet, a part of a base class (can be used directly in a form):
您可以使用类似 not-a-border 的东西 - 客户区内的框架。下面是代码片段,是基类的一部分(可以直接在表单中使用):
#region Кастомизированное поведение - рамки, активность и т.д.
private bool isCurrentlyActive = false;
private bool childControlsAreHandled = false;
private Pen activeWindowFramePen, inactiveWindowFramePen;
private Point[] framePoints;
private void AddControlPaintHandler(Control ctrl)
{
ctrl.Paint += DrawWindowFrame;
if (ctrl.Controls != null)
{
foreach (Control childControl in ctrl.Controls)
{
AddControlPaintHandler(childControl);
}
}
}
protected override void OnActivated(EventArgs e)
{
base.OnActivated(e);
if ((this.childControlsAreHandled == false)
&& (WindowFrameType != Forms.WindowFrameType.NoFrame)
&& (this.MdiParent == null))
{
RecalculateWindowFramePoints();
AddControlPaintHandler(this);
this.childControlsAreHandled = true;
}
this.isCurrentlyActive = true;
if (InactiveWindowOpacity < 1)
{
base.Opacity = 1;
}
base.Invalidate(true);
}
protected override void OnDeactivate(EventArgs e)
{
base.OnDeactivate(e);
this.isCurrentlyActive = false;
if (InactiveWindowOpacity < 1)
{
base.Opacity = InactiveWindowOpacity;
}
base.Invalidate(true);
}
protected override void OnResizeEnd(EventArgs e)
{
base.OnResizeEnd(e);
this.framePoints = null;
RecalculateWindowFramePoints();
this.Invalidate(true);
}
private Pen ActivePen
{
get
{
if (this.isCurrentlyActive)
{
if (this.activeWindowFramePen == null)
{
this.activeWindowFramePen = new Pen(Color.FromArgb((int)(WindowFrameOpacity*255), WindowFrameActiveColor), WindowFrameSize * 2);
}
return this.activeWindowFramePen;
}
else
{
if (this.inactiveWindowFramePen == null)
{
this.inactiveWindowFramePen = new Pen(Color.FromArgb((int)(WindowFrameOpacity*255), WindowFrameInactiveColor), WindowFrameSize * 2);
}
return this.inactiveWindowFramePen;
}
}
}
private Point[] RecalculateWindowFramePoints()
{
if ((WindowFrameType == Forms.WindowFrameType.AllSides)
&& (this.framePoints != null)
&& (this.framePoints.Length != 5))
{
this.framePoints = null;
}
if ((WindowFrameType == Forms.WindowFrameType.LeftLine)
&& (this.framePoints != null)
&& (this.framePoints.Length != 2))
{
this.framePoints = null;
}
if (this.framePoints == null)
{
switch (WindowFrameType)
{
case Forms.WindowFrameType.AllSides:
this.framePoints = new Point[5]
{
new Point(this.ClientRectangle.X, this.ClientRectangle.Y),
new Point(this.ClientRectangle.X + this.ClientRectangle.Width, this.ClientRectangle.Y),
new Point(this.ClientRectangle.X + this.ClientRectangle.Width, this.ClientRectangle.Y + this.ClientRectangle.Height),
new Point(this.ClientRectangle.X, this.ClientRectangle.Y + this.ClientRectangle.Height),
new Point(this.ClientRectangle.X, this.ClientRectangle.Y)
};
break;
case Forms.WindowFrameType.LeftLine:
this.framePoints = new Point[2]
{
new Point(this.ClientRectangle.X, this.ClientRectangle.Y),
new Point(this.ClientRectangle.X, this.ClientRectangle.Y + this.ClientRectangle.Height)
};
break;
}
}
return this.framePoints;
}
private void DrawWindowFrame(object sender, PaintEventArgs e)
{
if (WindowFrameType == Forms.WindowFrameType.NoFrame)
{
return;
}
if ((this.framePoints == null) || (this.framePoints.Length == 0))
{
return;
}
Control ctrl = (Control)(sender);
// пересчитаем точки в координатах контрола.
List<Point> pts = new List<Point>();
foreach (var p in this.framePoints)
{
pts.Add(ctrl.PointToClient(this.PointToScreen(p)));
}
e.Graphics.DrawLines(ActivePen, pts.ToArray());
}
public static int WindowFrameSize = 2;
public static WindowFrameType WindowFrameType = Forms.WindowFrameType.NoFrame;
public static Color WindowFrameActiveColor = Color.YellowGreen;
public static Color WindowFrameInactiveColor = SystemColors.ControlDark;
public static double InactiveWindowOpacity = 1.0;
public static double WindowFrameOpacity = 0.3;
#endregion
Static fields of the class are initialized from application settings form (class) - so, all the forms in the app has the same behavior.
类的静态字段从应用程序设置表单(类)初始化 - 因此,应用程序中的所有表单都具有相同的行为。
Hope that helps to someone.
希望对某人有所帮助。