Click here to Skip to main content
15,894,460 members
Articles / Programming Languages / C#

Adding designable borders to user controls

Rate me:
Please Sign up or sign in to vote.
4.62/5 (22 votes)
8 Dec 20038 min read 145.8K   2K   45  
A tutorial on adding design-time enabled borders to user controls. Covers topics including atributes, interop, and custom overrides
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using System.Runtime.InteropServices;		// Needed for DLLImport

namespace BorderControls
{
	/// <summary>
	/// Summary description for UserControl1.
	/// </summary>
	public class DesignableControl : System.Windows.Forms.UserControl
	{
		// Set the built-in default border style
		private System.Windows.Forms.BorderStyle borderStyle = BorderStyle.Fixed3D;
		private System.Windows.Forms.Label label;

		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;

		public DesignableControl()
		{
			// This call is required by the Windows.Forms Form Designer.
			InitializeComponent();

			// TODO: Add any initialization after the InitComponent call
		}

		/// <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 Component 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.label = new System.Windows.Forms.Label();
			this.SuspendLayout();
			// 
			// label
			// 
			this.label.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
				| System.Windows.Forms.AnchorStyles.Left) 
				| System.Windows.Forms.AnchorStyles.Right)));
			this.label.Location = new System.Drawing.Point(8, 16);
			this.label.Name = "label";
			this.label.Size = new System.Drawing.Size(72, 23);
			this.label.TabIndex = 0;
			this.label.Text = "Designable";
			this.label.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
			// 
			// DesignableControl
			// 
			this.Controls.Add(this.label);
			this.Name = "DesignableControl";
			this.Size = new System.Drawing.Size(88, 56);
			this.ResumeLayout(false);

		}
		#endregion


		// These constants were taken from WinUser.h
		private const int WS_BORDER  = 0x00800000;
		private const int WS_EX_CLIENTEDGE = 0x00000200;

		// Convert from the BorderStyle constant types to Style and ExStyle values suitable for Win32
		private void BorderStyleToWindowStyle(ref int style, ref int exStyle)
		{
			style &= ~WS_BORDER;
			exStyle &= ~WS_EX_CLIENTEDGE;

			switch(borderStyle)
			{
				case BorderStyle.Fixed3D:
					exStyle |= WS_EX_CLIENTEDGE;
					break;

				case BorderStyle.FixedSingle:
					style |= WS_BORDER;
					break;

				case BorderStyle.None:
					// No border style values
					break;
			}
		}


		// Provide window style constants to enable control border
		protected override CreateParams CreateParams
		{
			get
			{
				CreateParams p = base.CreateParams;		// Get the default values from the base class
				int style = p.Style;					// Store the Style and ExStyle values
				int exStyle = p.ExStyle;
				BorderStyleToWindowStyle(ref style, ref exStyle);	// Modify the values to match the desired border style
				p.Style = style;
				p.ExStyle = exStyle;					// Store the results
				return p;
			}
		}


		/// <summary>
		/// Gets or sets the border style of the tree view control.
		/// </summary>
		[Category("Appearance")]
		[Description("Border style of the control")]
		[DefaultValue(typeof(System.Windows.Forms.BorderStyle), "Fixed3D")]
		public BorderStyle BorderStyle
		{
			get {return borderStyle;}
			set
			{
				borderStyle = value;

				// Get Styles using Win32 calls
				int style = GetWindowLong(Handle, GWL_STYLE);
				int exStyle = GetWindowLong(Handle, GWL_EXSTYLE);

				// Modify Styles to match the selected border style
				BorderStyleToWindowStyle(ref style, ref exStyle);

				// Set Styles using Win32 calls
				SetWindowLong(Handle, GWL_STYLE, style);
				SetWindowLong(Handle, GWL_EXSTYLE, exStyle);

				// Update window property cache (Tell Win32 that the frame changed)
				SetWindowPos(Handle, IntPtr.Zero, 0, 0, 0, 0,
					SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
					SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
			}
		}

		// Constants from WinUser.h
		const int GWL_STYLE = -16;
		const int GWL_EXSTYLE = -20;

		[DllImport("User32", CharSet=CharSet.Auto)]
		private static extern int GetWindowLong(IntPtr hWnd, int Index);

		[DllImport("User32", CharSet=CharSet.Auto)]
		private static extern int SetWindowLong(IntPtr hWnd, int Index, int Value);


		// Constants from WinUser.h
		const uint SWP_NOSIZE   = 0x0001;
		const uint SWP_NOMOVE   = 0x0002;
		const uint SWP_NOZORDER   = 0x0004;
		const uint SWP_NOREDRAW   = 0x0008;
		const uint SWP_NOACTIVATE  = 0x0010;
		const uint SWP_FRAMECHANGED  = 0x0020;
		const uint SWP_SHOWWINDOW  = 0x0040;
		const uint SWP_HIDEWINDOW  = 0x0080;
		const uint SWP_NOCOPYBITS  = 0x0100;
		const uint SWP_NOOWNERZORDER = 0x0200;
		const uint SWP_NOSENDCHANGING = 0x0400;

		[DllImport("User32", ExactSpelling=true)]
		private static extern int SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter,
			int x, int y, int cx, int cy, uint uFlags);
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
Jason Dorie is currently employed with Electronic Arts BlackBox in Vancouver, B.C. He does a variety of programming tasks including writing tools for creating games, 3D rendering, data and video compression, and data processing pipelines. He can often be found lurking on XBox live under the pseudonym "djMidnight".

Comments and Discussions