This is by no means a complete solution, just an idea for creating custom shaped forms with custom Titlebars.
The form can be dragged by its fake titlebar, and if right clicked the fake Titlebar will popup the WindowMenu.
The CreateParams property has been modified to add a System Menu (with Min,Move and Close items) to a borderless form.
The Titlebar button are not controls, they are simply drawn in the fake title bar and they react to hittesting.
The MainMenu is actually labels that popup Contextmenus.
The form can be resized only by its resizegrip, but you could define regions for each of the sides and corners and allow sizing by dragging the edge. The example requires a little work to be useable, but it should give you an idea of how to achieve this solution.
With a little InterOp you can draw a standard TitleBar onto which you can place custom buttons, and this solution is much simpler than that of OwnerDrawing the NonClient Area to achieve the same effect.
by: Mick Dohertys'
The form can be dragged by its fake titlebar, and if right clicked the fake Titlebar will popup the WindowMenu.
The CreateParams property has been modified to add a System Menu (with Min,Move and Close items) to a borderless form.
The Titlebar button are not controls, they are simply drawn in the fake title bar and they react to hittesting.
The MainMenu is actually labels that popup Contextmenus.
The form can be resized only by its resizegrip, but you could define regions for each of the sides and corners and allow sizing by dragging the edge. The example requires a little work to be useable, but it should give you an idea of how to achieve this solution.
With a little InterOp you can draw a standard TitleBar onto which you can place custom buttons, and this solution is much simpler than that of OwnerDrawing the NonClient Area to achieve the same effect.
VB net Sample:
Imports System.Drawing.Drawing2D Public Class MainForm Inherits System.Windows.Forms.Form #Region " Windows Form Designer generated code " <System.STAThread()> _ Public Shared Sub Main() Application.EnableVisualStyles() Application.DoEvents() Application.Run(New MainForm) End Sub Public Sub New() MyBase.New() 'This call is required by the Windows Form Designer. InitializeComponent() 'Add any initialization after the InitializeComponent() call setstyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.DoubleBuffer Or ControlStyles.ResizeRedraw Or ControlStyles.UserPaint, True) End Sub 'Form overrides dispose to clean up the component list. Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean) If disposing Then If Not (components Is Nothing) Then components.Dispose() End If End If MyBase.Dispose(disposing) End Sub 'Required by the Windows Form Designer Private components As System.ComponentModel.IContainer 'NOTE: The following procedure is required by the Windows Form Designer 'It can be modified using the Windows Form Designer. 'Do not modify it using the code editor. Friend WithEvents ContextMenu1 As System.Windows.Forms.ContextMenu Friend WithEvents MenuItem1 As System.Windows.Forms.MenuItem Friend WithEvents MenuItem2 As System.Windows.Forms.MenuItem Friend WithEvents ContextMenu2 As System.Windows.Forms.ContextMenu Friend WithEvents MenuExit As System.Windows.Forms.MenuItem Friend WithEvents MenuAbout As System.Windows.Forms.MenuItem Friend WithEvents ToolTip1 As System.Windows.Forms.ToolTip Friend WithEvents LabelFile As System.Windows.Forms.Label Friend WithEvents LabelResize As System.Windows.Forms.Label Friend WithEvents LabelHelp As System.Windows.Forms.Label <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent() Me.components = New System.ComponentModel.Container Me.ContextMenu1 = New System.Windows.Forms.ContextMenu Me.MenuItem1 = New System.Windows.Forms.MenuItem Me.MenuItem2 = New System.Windows.Forms.MenuItem Me.MenuExit = New System.Windows.Forms.MenuItem Me.ContextMenu2 = New System.Windows.Forms.ContextMenu Me.MenuAbout = New System.Windows.Forms.MenuItem Me.ToolTip1 = New System.Windows.Forms.ToolTip(Me.components) Me.LabelFile = New System.Windows.Forms.Label Me.LabelHelp = New System.Windows.Forms.Label Me.LabelResize = New System.Windows.Forms.Label Me.SuspendLayout() ' 'ContextMenu1 ' Me.ContextMenu1.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.MenuItem1, Me.MenuItem2, Me.MenuExit}) ' 'MenuItem1 ' Me.MenuItem1.Index = 0 Me.MenuItem1.Text = "MenuItem1" ' 'MenuItem2 ' Me.MenuItem2.Index = 1 Me.MenuItem2.Text = "-" ' 'MenuExit ' Me.MenuExit.Index = 2 Me.MenuExit.Text = "Exit" ' 'ContextMenu2 ' Me.ContextMenu2.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.MenuAbout}) ' 'MenuAbout ' Me.MenuAbout.Index = 0 Me.MenuAbout.Text = "About" ' 'ToolTip1 ' Me.ToolTip1.ShowAlways = True ' 'LabelFile ' Me.LabelFile.BackColor = System.Drawing.Color.Transparent Me.LabelFile.ForeColor = System.Drawing.SystemColors.MenuText Me.LabelFile.Location = New System.Drawing.Point(8, 24) Me.LabelFile.Name = "LabelFile" Me.LabelFile.Size = New System.Drawing.Size(32, 19) Me.LabelFile.TabIndex = 0 Me.LabelFile.Text = "File" Me.LabelFile.TextAlign = System.Drawing.ContentAlignment.MiddleCenter ' 'LabelHelp ' Me.LabelHelp.BackColor = System.Drawing.Color.Transparent Me.LabelHelp.ForeColor = System.Drawing.SystemColors.MenuText Me.LabelHelp.Location = New System.Drawing.Point(64, 24) Me.LabelHelp.Name = "LabelHelp" Me.LabelHelp.Size = New System.Drawing.Size(32, 19) Me.LabelHelp.TabIndex = 1 Me.LabelHelp.Text = "Help" Me.LabelHelp.TextAlign = System.Drawing.ContentAlignment.MiddleCenter ' 'LabelResize ' Me.LabelResize.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles) Me.LabelResize.AutoSize = True Me.LabelResize.BackColor = System.Drawing.Color.Transparent Me.LabelResize.Font = New System.Drawing.Font("Marlett", 8.25!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(2, Byte)) Me.LabelResize.Location = New System.Drawing.Point(272, 138) Me.LabelResize.Name = "LabelResize" Me.LabelResize.Size = New System.Drawing.Size(16, 14) Me.LabelResize.TabIndex = 2 Me.LabelResize.Text = "o" ' 'MainForm ' Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13) Me.ClientSize = New System.Drawing.Size(288, 152) Me.Controls.Add(Me.LabelResize) Me.Controls.Add(Me.LabelHelp) Me.Controls.Add(Me.LabelFile) Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None Me.Name = "MainForm" Me.Text = "Shaped Form Example" Me.ResumeLayout(False) End Sub #End Region Private ReadOnly Property TitleBar() As Region Get Return New Region(New Rectangle(0, 0, Width, 26)) End Get End Property Private ReadOnly Property CloseButton() As GraphicsPath Get Dim gp As New GraphicsPath gp.AddEllipse(New Rectangle(Width - 26, 3, 18, 18)) Return gp End Get End Property Private ReadOnly Property MinButton() As GraphicsPath Get Dim gp As New GraphicsPath gp.AddEllipse(New Rectangle(Width - 49, 3, 18, 18)) Return gp End Get End Property Private ReadOnly Property FormShape() As GraphicsPath Get Dim gp As GraphicsPath = New GraphicsPath Dim r As Rectangle = ClientRectangle Dim radius As Int32 = 12 gp.AddArc(r.Left, r.Top + 24, radius, radius, 180, 90) gp.AddArc(r.Left + 80 - radius, r.Top + 24 - radius, radius, radius, -270, -90) gp.AddArc(r.Left + 80, r.Top, radius, radius, 180, 90) gp.AddArc(r.Right - radius, r.Top, radius, radius, 270, 90) gp.AddArc(r.Right - radius, r.Bottom - radius, radius, radius, 0, 90) gp.AddArc(r.Left, r.Bottom - radius, radius, radius, 90, 90) gp.CloseFigure() Return gp End Get End Property Private ClosePress As Boolean = False Private MinPress As Boolean = False Private FormDrag As Boolean = False Private FileActive As Boolean = False Private HelpActive As Boolean = False Private FileHot As Boolean = False Private HelpHot As Boolean = False Private Const WM_NCLBUTTONDOWN As Integer = &HA1 Private Const HT_CAPTION As Integer = &H2 Protected Overrides ReadOnly Property CreateParams() As System.Windows.Forms.CreateParams Get Dim cp As CreateParams = MyBase.CreateParams Const WS_CLIPCHILDREN As Integer = &H2000000 Const WS_MINIMIZEBOX As Integer = &H20000 'Const WS_MAXIMIZEBOX As Integer = &H10000 Const WS_SYSMENU As Integer = &H80000 Const CS_DBLCLKS As Integer = &H8 Const CS_DROPSHADOW As Integer = &H20000 Dim ClassFlags As Integer = CS_DBLCLKS Dim OSVER As Integer = Environment.OSVersion.Version.Major * 10 OSVER += Environment.OSVersion.Version.Minor If OSVER >= 51 Then ClassFlags = CS_DBLCLKS Or CS_DROPSHADOW cp.Style = WS_CLIPCHILDREN Or WS_MINIMIZEBOX Or WS_SYSMENU 'Or WS_MAXIMIZEBOX cp.ClassStyle = ClassFlags Return cp End Get End Property Private Sub MainForm_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load Me.LabelFile.Location = New Point(2, 26) Me.LabelHelp.Location = New Point(LabelFile.Right, 26) Me.LabelFile.Font = SystemInformation.MenuFont Me.LabelHelp.Font = SystemInformation.MenuFont Me.Region = New Region(FormShape) End Sub Private Sub MainForm_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint e.Graphics.FillRegion(Brushes.Green, TitleBar) e.Graphics.FillRectangle(SystemBrushes.Menu, New Rectangle(0, 26, Width, 19)) If FileHot Then e.Graphics.FillRectangle(SystemBrushes.Highlight, LabelFile.Bounds) If HelpHot Then e.Graphics.FillRectangle(SystemBrushes.Highlight, LabelHelp.Bounds) Dim BorderPen As New Pen(Color.Green, 2) BorderPen.Alignment = PenAlignment.Inset e.Graphics.DrawPath(BorderPen, FormShape) BorderPen.Dispose() e.Graphics.SmoothingMode = SmoothingMode.HighQuality Dim sf As New StringFormat(StringFormatFlags.NoWrap) sf.Trimming = StringTrimming.EllipsisCharacter sf.Alignment = StringAlignment.Center sf.LineAlignment = StringAlignment.Center e.Graphics.DrawString(Me.Text, Control.DefaultFont, Brushes.White, RectangleF.FromLTRB(84, 0, MinButton.GetBounds.X, 24), sf) If ClosePress Then e.Graphics.FillPath(Brushes.Blue, CloseButton) Else e.Graphics.FillPath(Brushes.Red, CloseButton) End If If MinPress Then e.Graphics.FillPath(Brushes.Red, MinButton) Else e.Graphics.FillPath(Brushes.Yellow, MinButton) End If Dim GlyphFont As New Font("marlett", Font.SizeInPoints, FontStyle.Bold, GraphicsUnit.Point) e.Graphics.DrawString("0", GlyphFont, Brushes.Black, MinButton.GetBounds, sf) e.Graphics.DrawString("r", GlyphFont, Brushes.Black, CloseButton.GetBounds, sf) GlyphFont.Dispose() End Sub Private Sub MainForm_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseDown ClosePress = CloseButton.IsVisible(e.X, e.Y) AndAlso e.Button = MouseButtons.Left MinPress = MinButton.IsVisible(e.X, e.Y) AndAlso e.Button = MouseButtons.Left FormDrag = TitleBar.IsVisible(e.X, e.Y) AndAlso _ e.Button = MouseButtons.Left AndAlso _ ClosePress = False AndAlso MinPress = False If FormDrag Then Me.Capture = False WndProc(Message.Create(Handle, WM_NCLBUTTONDOWN, IntPtr.op_Explicit(HT_CAPTION), IntPtr.Zero)) End If Invalidate() End Sub Private Sub MainForm_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseMove Dim OverClose, OverMin As Boolean OverClose = CloseButton.IsVisible(e.X, e.Y) OverMin = MinButton.IsVisible(e.X, e.Y) ClosePress = OverClose AndAlso e.Button = MouseButtons.Left MinPress = OverMin AndAlso e.Button = MouseButtons.Left If OverClose AndAlso ClosePress = False Then ToolTip1.SetToolTip(Me, "Close") ElseIf OverMin AndAlso MinPress = False Then ToolTip1.SetToolTip(Me, "Minimize") Else ToolTip1.SetToolTip(Me, "") End If Invalidate() End Sub Private Sub MainForm_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseUp Dim OverClose, OverMin As Boolean OverClose = CloseButton.IsVisible(e.X, e.Y) OverMin = MinButton.IsVisible(e.X, e.Y) If OverClose AndAlso ClosePress AndAlso e.Button = MouseButtons.Left Then Me.Close() End If If OverMin AndAlso MinPress AndAlso e.Button = MouseButtons.Left Then Me.WindowState = FormWindowState.Minimized End If If e.Button = MouseButtons.Right AndAlso TitleBar.IsVisible(e.X, e.Y) Then If OverClose = False AndAlso OverMin = False Then Const WM_GETSYSMENU As Integer = &H313 If e.Button = MouseButtons.Right Then Dim pos As Point = Me.PointToScreen(New Point(e.X, e.Y)) Dim hPos As IntPtr = IntPtr.op_Explicit(CInt((pos.Y * &H10000) Or (pos.X And &HFFFF&))) WndProc(Message.Create(Handle, WM_GETSYSMENU, IntPtr.Zero, hPos)) End If End If End If ClosePress = False MinPress = False FormDrag = False Invalidate() End Sub Private Sub MenuAbout_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles MenuAbout.Click MessageBox.Show("Shaped Form Example!" & vbCrLf & "By Mick Doherty (http://dotnetrix.co.uk)", "About...", MessageBoxButtons.OK) End Sub Private Sub MenuExit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuExit.Click Application.Exit() End Sub Private Sub LabelHelp_MouseEnter(ByVal sender As Object, ByVal e As System.EventArgs) Handles LabelHelp.MouseEnter HelpHot = True LabelHelp.ForeColor = SystemColors.HighlightText Invalidate() End Sub Private Sub LabelHelp_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles LabelHelp.MouseUp HelpActive = True ContextMenu2.Show(LabelHelp, New Point(0, LabelHelp.Height)) HelpActive = False LabelHelp.ForeColor = SystemColors.MenuText Invalidate() End Sub Private Sub LabelHelp_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs) Handles LabelHelp.MouseLeave If HelpActive = False Then HelpHot = False LabelHelp.ForeColor = SystemColors.MenuText End If Invalidate() End Sub Private Sub LabelFile_MouseEnter(ByVal sender As Object, ByVal e As System.EventArgs) Handles LabelFile.MouseEnter FileHot = True LabelFile.ForeColor = SystemColors.HighlightText Invalidate() End Sub Private Sub LabelFile_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles LabelFile.MouseUp FileActive = True ContextMenu1.Show(LabelFile, New Point(0, LabelFile.Height)) FileActive = False LabelFile.ForeColor = SystemColors.MenuText Invalidate() End Sub Private Sub LabelFile_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs) Handles LabelFile.MouseLeave If FileActive = False Then FileHot = False LabelFile.ForeColor = SystemColors.MenuText End If Invalidate() End Sub Private Sizing As Boolean = False Private SizeOffset As Point = Point.Empty Private Sub LabelResize_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles LabelResize.MouseDown Sizing = True SizeOffset = New Point(Me.Right - Cursor.Position.X, Me.Bottom - Cursor.Position.Y) End Sub Private Sub LabelResize_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles LabelResize.MouseMove If Sizing = True Then 'Clip cursor to dissallow sizing of form below 250x100 Dim ClipRectangle As Rectangle = RectangleToScreen(New Rectangle(250, 100, Width, Height)) ClipRectangle.Offset(SizeOffset) Cursor.Clip = ClipRectangle Me.Size = New Size(Cursor.Position.X + SizeOffset.X - Location.X, Cursor.Position.Y + SizeOffset.Y - Location.Y) End If End Sub Private Sub LabelResize_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles LabelResize.MouseUp Sizing = False Cursor.Clip = Nothing End Sub Private Sub MainForm_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Resize Me.Region = New Region(FormShape) End Sub End Class
CSharp Sample:
using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; using System.Drawing.Drawing2D; namespace ShapedForm { /// <summary> /// Summary description for Form1. /// </summary> public class MainForm : System.Windows.Forms.Form { private System.ComponentModel.IContainer components; public MainForm() { // // Required for Windows Form Designer support // InitializeComponent(); // // TODO: Add any constructor code after InitializeComponent call // this.SetStyle(ControlStyles.AllPaintingInWmPaint| ControlStyles.DoubleBuffer|ControlStyles.UserPaint|ControlStyles.ResizeRedraw,true); } /// <summary> /// Clean up any resources being used. /// </summary> protected override void Dispose( bool disposing ) { if( disposing ) { if (components != null) { components.Dispose(); } } base.Dispose( disposing ); } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.components = new System.ComponentModel.Container(); this.labelFile = new System.Windows.Forms.Label(); this.labelHelp = new System.Windows.Forms.Label(); this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); this.contextMenu1 = new System.Windows.Forms.ContextMenu(); this.menuItem1 = new System.Windows.Forms.MenuItem(); this.menuItem2 = new System.Windows.Forms.MenuItem(); this.menuExit = new System.Windows.Forms.MenuItem(); this.contextMenu2 = new System.Windows.Forms.ContextMenu(); this.menuAbout = new System.Windows.Forms.MenuItem(); this.labelResize = new System.Windows.Forms.Label(); this.SuspendLayout(); // // labelFile // this.labelFile.BackColor = System.Drawing.Color.Transparent; this.labelFile.ForeColor = System.Drawing.SystemColors.MenuText; this.labelFile.Location = new System.Drawing.Point(8, 24); this.labelFile.Name = "labelFile"; this.labelFile.Size = new System.Drawing.Size(32, 19); this.labelFile.TabIndex = 0; this.labelFile.Text = "File"; this.labelFile.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; this.labelFile.MouseEnter += new System.EventHandler(this.labelFile_MouseEnter); this.labelFile.MouseUp += new System.Windows.Forms.MouseEventHandler(this.labelFile_MouseUp); this.labelFile.MouseLeave += new System.EventHandler(this.labelFile_MouseLeave); // // labelHelp // this.labelHelp.BackColor = System.Drawing.Color.Transparent; this.labelHelp.ForeColor = System.Drawing.SystemColors.MenuText; this.labelHelp.Location = new System.Drawing.Point(64, 24); this.labelHelp.Name = "labelHelp"; this.labelHelp.Size = new System.Drawing.Size(32, 19); this.labelHelp.TabIndex = 1; this.labelHelp.Text = "Help"; this.labelHelp.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; this.labelHelp.MouseEnter += new System.EventHandler(this.labelHelp_MouseEnter); this.labelHelp.MouseUp += new System.Windows.Forms.MouseEventHandler(this.labelHelp_MouseUp); this.labelHelp.MouseLeave += new System.EventHandler(this.labelHelp_MouseLeave); // // contextMenu1 // this.contextMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { this.menuItem1, this.menuItem2, this.menuExit}); // // menuItem1 // this.menuItem1.Index = 0; this.menuItem1.Text = "menuItem1"; // // menuItem2 // this.menuItem2.Index = 1; this.menuItem2.Text = "-"; // // menuExit // this.menuExit.Index = 2; this.menuExit.Text = "Exit"; this.menuExit.Click += new System.EventHandler(this.menuExit_Click); // // contextMenu2 // this.contextMenu2.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { this.menuAbout}); // // menuAbout // this.menuAbout.Index = 0; this.menuAbout.Text = "About"; this.menuAbout.Click += new System.EventHandler(this.menuAbout_Click); // // labelResize // this.labelResize.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.labelResize.AutoSize = true; this.labelResize.BackColor = System.Drawing.Color.Transparent; this.labelResize.Font = new System.Drawing.Font("Marlett", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((System.Byte)(2))); this.labelResize.Location = new System.Drawing.Point(272, 138); this.labelResize.Name = "labelResize"; this.labelResize.Size = new System.Drawing.Size(16, 14); this.labelResize.TabIndex = 2; this.labelResize.Text = "o"; this.labelResize.MouseUp += new System.Windows.Forms.MouseEventHandler(this.labelResize_MouseUp); this.labelResize.MouseMove += new System.Windows.Forms.MouseEventHandler(this.labelResize_MouseMove); this.labelResize.MouseDown += new System.Windows.Forms.MouseEventHandler(this.labelResize_MouseDown); // // MainForm // this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(288, 152); this.Controls.Add(this.labelResize); this.Controls.Add(this.labelHelp); this.Controls.Add(this.labelFile); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; this.Name = "Form1"; this.Text = "Shaped Form Example"; this.Resize += new System.EventHandler(this.MainForm_Resize); this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.Form1_MouseDown); this.Load += new System.EventHandler(this.Form1_Load); this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.Form1_MouseUp); this.Paint += new System.Windows.Forms.PaintEventHandler(this.Form1_Paint); this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.Form1_MouseMove); this.ResumeLayout(false); } #endregion /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { Application.Run(new MainForm()); } private Region TitleBar { get{return new Region(new Rectangle(0, 0, Width, 26));} } private GraphicsPath CloseButton { get { GraphicsPath gp = new GraphicsPath(); gp.AddEllipse(new Rectangle(Width - 26, 3, 18, 18)); return gp; } } private GraphicsPath MinButton { get { GraphicsPath gp = new GraphicsPath(); gp.AddEllipse(new Rectangle(Width - 49, 3, 18, 18)); return gp; } } private GraphicsPath FormShape { get { GraphicsPath gp = new GraphicsPath(); Rectangle r = ClientRectangle; int radius = 12; gp.AddArc(r.Left, r.Top + 24, radius, radius, 180, 90); gp.AddArc(r.Left + 80 - radius, r.Top + 24 - radius, radius, radius, -270, -90); gp.AddArc(r.Left + 80, r.Top, radius, radius, 180, 90); gp.AddArc(r.Right - radius, r.Top, radius, radius, 270, 90); gp.AddArc(r.Right - radius, r.Bottom - radius, radius, radius, 0, 90); gp.AddArc(r.Left, r.Bottom - radius, radius, radius, 90, 90); gp.CloseFigure(); return gp; } } private bool ClosePress = false; private bool MinPress = false; private bool FormDrag = false; private bool FileActive = false; private bool HelpActive = false; private bool FileHot = false; private bool HelpHot = false; private const int WM_NCLBUTTONDOWN = 0xA1; private System.Windows.Forms.Label labelFile; private System.Windows.Forms.Label labelHelp; private System.Windows.Forms.ToolTip toolTip1; private System.Windows.Forms.ContextMenu contextMenu1; private System.Windows.Forms.ContextMenu contextMenu2; private System.Windows.Forms.MenuItem menuItem1; private System.Windows.Forms.MenuItem menuItem2; private System.Windows.Forms.MenuItem menuAbout; private System.Windows.Forms.MenuItem menuExit; private System.Windows.Forms.Label labelResize; private const int HT_CAPTION = 0x2; protected override System.Windows.Forms.CreateParams CreateParams { get { CreateParams cp = base.CreateParams; const int WS_CLIPCHILDREN = 0x2000000; const int WS_MINIMIZEBOX = 0x20000; //const int WS_MAXIMIZEBOX = 0x10000; const int WS_SYSMENU = 0x80000; const int CS_DBLCLKS = 0x8; const int CS_DROPSHADOW = 0x20000; int ClassFlags = CS_DBLCLKS; int OSVER = Environment.OSVersion.Version.Major * 10; OSVER += Environment.OSVersion.Version.Minor; if (OSVER >= 51) ClassFlags = CS_DBLCLKS | CS_DROPSHADOW; cp.Style = WS_CLIPCHILDREN | WS_MINIMIZEBOX | WS_SYSMENU; //| WS_MAXIMIZEBOX cp.ClassStyle = ClassFlags; return cp; } } private void Form1_Load(object sender, System.EventArgs e) { this.labelFile.Location = new Point(2, 26); this.labelHelp.Location = new Point(labelFile.Right, 26); this.labelFile.Font = SystemInformation.MenuFont; this.labelHelp.Font = SystemInformation.MenuFont; this.Region = new Region(FormShape); } private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e) { e.Graphics.FillRegion(Brushes.Green, TitleBar); e.Graphics.FillRectangle(SystemBrushes.Menu, new Rectangle(0, 26, Width, 19)); if (FileHot) e.Graphics.FillRectangle(SystemBrushes.Highlight, labelFile.Bounds); if (HelpHot) e.Graphics.FillRectangle(SystemBrushes.Highlight, labelHelp.Bounds); Pen BorderPen = new Pen(Color.Green, 2); BorderPen.Alignment = PenAlignment.Inset; e.Graphics.DrawPath(BorderPen, FormShape); BorderPen.Dispose(); e.Graphics.SmoothingMode = SmoothingMode.HighQuality; StringFormat sf= new StringFormat(StringFormatFlags.NoWrap); sf.Trimming = StringTrimming.EllipsisCharacter; sf.Alignment = StringAlignment.Center; sf.LineAlignment = StringAlignment.Center; e.Graphics.DrawString(this.Text, Control.DefaultFont, Brushes.White, RectangleF.FromLTRB(84, 0, MinButton.GetBounds().X, 24), sf); if (ClosePress) e.Graphics.FillPath(Brushes.Blue, CloseButton); else e.Graphics.FillPath(Brushes.Red, CloseButton); if (MinPress) e.Graphics.FillPath(Brushes.Red, MinButton); else e.Graphics.FillPath(Brushes.Yellow, MinButton); Font GlyphFont = new Font("marlett", Font.SizeInPoints, FontStyle.Bold, GraphicsUnit.Point); e.Graphics.DrawString("0", GlyphFont, Brushes.Black, MinButton.GetBounds(), sf); e.Graphics.DrawString("r", GlyphFont, Brushes.Black, CloseButton.GetBounds(), sf); GlyphFont.Dispose(); } private void Form1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e) { ClosePress = CloseButton.IsVisible(e.X, e.Y) && e.Button == MouseButtons.Left; MinPress = MinButton.IsVisible(e.X, e.Y) && e.Button == MouseButtons.Left; FormDrag = TitleBar.IsVisible(e.X, e.Y) && e.Button == MouseButtons.Left && ClosePress == false && MinPress == false; if (FormDrag) { this.Capture = false; Message msg = Message.Create(Handle, WM_NCLBUTTONDOWN, (IntPtr)HT_CAPTION, IntPtr.Zero); WndProc(ref msg); } Invalidate(); } private void Form1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) { bool OverClose, OverMin; OverClose = CloseButton.IsVisible(e.X, e.Y); OverMin = MinButton.IsVisible(e.X, e.Y); ClosePress = OverClose && e.Button == MouseButtons.Left; MinPress = OverMin && e.Button == MouseButtons.Left; if (OverClose && ClosePress == false) toolTip1.SetToolTip(this, "Close"); else if (OverMin && MinPress == false) toolTip1.SetToolTip(this, "Minimize"); else toolTip1.SetToolTip(this, ""); Invalidate(); } private void Form1_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e) { bool OverClose, OverMin; OverClose = CloseButton.IsVisible(e.X, e.Y); OverMin = MinButton.IsVisible(e.X, e.Y); if (OverClose && ClosePress && e.Button == MouseButtons.Left) this.Close(); if (OverMin && MinPress && e.Button == MouseButtons.Left) this.WindowState = FormWindowState.Minimized; if (e.Button == MouseButtons.Right && TitleBar.IsVisible(e.X, e.Y)) { if (OverClose == false && OverMin == false) { const int WM_GETSYSMENU = 0x313; if (e.Button == MouseButtons.Right) { Point pos = this.PointToScreen(new Point(e.X, e.Y)); IntPtr hPos = (IntPtr)((int)((pos.Y * 0x10000) | (pos.X & 0xFFFF))); Message msg = Message.Create(this.Handle, WM_GETSYSMENU, IntPtr.Zero, hPos); WndProc(ref msg); } } } ClosePress = false; MinPress = false; FormDrag = false; Invalidate(); } private void menuAbout_Click(object sender, System.EventArgs e) { MessageBox.Show("Shaped Form Example!\nBy Mick Doherty (http://dotnetrix.co.uk)", "About...", MessageBoxButtons.OK); } private void menuExit_Click(object sender, System.EventArgs e) { Application.Exit(); } private void labelHelp_MouseEnter(object sender, System.EventArgs e) { HelpHot = true; labelHelp.ForeColor = SystemColors.HighlightText; Invalidate(); } private void labelHelp_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e) { HelpActive = true; contextMenu2.Show(labelHelp, new Point(0, labelHelp.Height)); HelpActive = false; labelHelp.ForeColor = SystemColors.MenuText; Invalidate(); } private void labelHelp_MouseLeave(object sender, System.EventArgs e) { if (HelpActive == false) { HelpHot = false; labelHelp.ForeColor = SystemColors.MenuText; } Invalidate(); } private void labelFile_MouseEnter(object sender, System.EventArgs e) { FileHot = true; labelFile.ForeColor = SystemColors.HighlightText; Invalidate(); } private void labelFile_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e) { FileActive = true; contextMenu1.Show(labelFile, new Point(0, labelFile.Height)); FileActive = false; labelFile.ForeColor = SystemColors.MenuText; Invalidate(); } private void labelFile_MouseLeave(object sender, System.EventArgs e) { if (FileActive == false) { FileHot = false; labelFile.ForeColor = SystemColors.MenuText; } Invalidate(); } private bool Sizing = false; private Point SizeOffset = Point.Empty; private void labelResize_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e) { Sizing = true; SizeOffset = new Point(this.Right - Cursor.Position.X, this.Bottom - Cursor.Position.Y); } private void labelResize_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) { if (Sizing) { //Clip cursor to dissallow sizing of form below 250x100 Rectangle ClipRectangle = RectangleToScreen(new Rectangle(250, 100, Width, Height)); ClipRectangle.Offset(SizeOffset); Cursor.Clip = ClipRectangle; this.Size = new Size(Cursor.Position.X + SizeOffset.X - Location.X, Cursor.Position.Y + SizeOffset.Y - Location.Y); } } private void labelResize_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e) { Sizing = false; Cursor.Clip = Rectangle.Empty; } private void MainForm_Resize(object sender, System.EventArgs e) { this.Region=new Region(FormShape); } } }
by: Mick Dohertys'
1 comments:
Hello
This is a very good solution for shaped form! Much more better than if we use the 'transparency key'. With that the form cannot visible with screenshot tools on XP.
Thank you for the code.
Post a Comment