This is my first post. I always follow CodeProject and now I want to make my first contribution. Sorry for my English, it's not my natal language. In this article I suggest a way to create your own TitleBar without overriding WndProc, and making it as easy as possible. Too many code on the web but nothing like this. We'll achieve a Form without CaptionText but with caption on the button on taskbar, and the possibility to add our own titlebar on the form.
WndProc
CaptionText
We only have to do some steps to achieve it. Tell the form not to show CaptionText is the first of all, second: create our function to control and to change the WindowStates and we add buttons to make WindowState changes functional in UI.
WindowState
The first thing is to create a Windows project and in Form1 set the ControlBox property to false (no control buttons are shown), the next step is to set the property FormBorderStyle to Sizeable. In the Form code override CreateParams to make that our form ignores CaptionText.
Form1
ControlBox
false
FormBorderStyle
Sizeable
CreateParams
protected override CreateParams CreateParams { get { CreateParams cp = base.CreateParams; cp.Style &= ~0xC00000; // Not allow WS_CAPTION return cp; } }
The next thing is to create a function to set the WindowState values.
private FormWindowState m_WindowState = FormWindowState.Normal; private Rectangle m_FormSizeAndLocation = Rectangle.Empty; private void ChangeWindowState(FormWindowState p_NewState) { this.WindowState = FormWindowState.Normal; switch (p_NewState) { case FormWindowState.Maximized: // if in normal mode we remind window size and location if (m_WindowState == FormWindowState.Normal) { m_FormSizeAndLocation.Location = this.Location; m_FormSizeAndLocation.Size = this.Size; } // make our form to be borderless in Maximized mode this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; // calculate the window dimensions manually to prevent overlap the taskbar this.Size = SystemInformation.WorkingArea.Size; this.Location = SystemInformation.WorkingArea.Location; break; case FormWindowState.Minimized: this.WindowState = FormWindowState.Minimized; break; case FormWindowState.Normal: // make our form Sizeable by code this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Sizable; // Return to previous state values for window ocation & size this.Location = m_FormSizeAndLocation.Location; this.Size = m_FormSizeAndLocation.Size; break; } // to remind our last WindowState mode applied m_WindowState = p_NewState; }
The next steps are easy. Add a panel docked on top of the form and also add three buttons into the panel for Minimize, Maximize, and Close actions. Put the following code on ClickEvent for each button.
ClickEvent
private void ButtonMinimize_Click(object sender, EventArgs e) { ChangeWindowState(FormWindowState.Minimized); } private void ButtonMaximize_Click(object sender, EventArgs e) { if (m_WindowState == FormWindowState.Maximized) // If already maximized, turn to normal. { ChangeWindowState(FormWindowState.Normal); ButtonMaximize.Text = "Max"; } else { ChangeWindowState(FormWindowState.Maximized); ButtonMaximize.Text = "Res"; } } private void ButtonClose_Click(object sender, EventArgs e) { Close(); }
To move the form by click and drag we have to add the next code to our form:
public Form1() { InitializeComponent(); // Add listeners to perform the way to move our form on screen panel1.MouseDown += new MouseEventHandler(panel1_MouseDown); panel1.MouseMove += new MouseEventHandler(panel1_MouseMove); panel1.MouseUp += new MouseEventHandler(panel1_MouseUp); panel1.MouseDoubleClick += new MouseEventHandler(panel1_MouseDoubleClick); } #region MOUSE-EVENTS ON PANEL CONTROL // Routines to perform moving form by click & drag on TitleBar private bool m_MousePressed = false; private int m_oldX, m_oldY; void panel1_MouseDown(object sender, MouseEventArgs e) { Point TS = this.PointToScreen(e.Location); m_oldX = TS.X; m_oldY = TS.Y; m_MousePressed = true; } void panel1_MouseUp(object sender, MouseEventArgs e) { m_MousePressed = false; } void panel1_MouseMove(object sender, MouseEventArgs e) { // if not maximized we can move our form if (m_MousePressed == true && m_WindowState != FormWindowState.Maximized) { Point TS = this.PointToScreen(e.Location); this.Location = new Point(this.Location.X + (TS.X - m_oldX), this.Location.Y + (TS.Y - m_oldY)); m_oldX = TS.X; m_oldY = TS.Y; } } void panel1_MouseDoubleClick(object sender, MouseEventArgs e) { // Simplify the action simulating ButtonMaximized click event ButtonMaximize_Click(ButtonMaximize, new EventArgs()); } #endregion
That's all, just simple code and sentences. Try the demo and you'll see it. It could be simple but too much hard work to achieve this: the basis to perform your own title bar.
I hope this code to be useful for someone. Now you can build the titlebar as pretty as you want even like a UserControl instead of a panel. You can add images and menu to your title bar (because the panel control is a container) and make it as pretty as the one on Photoshop CS5 which was my inspiration.