C# Source Code: Source code for an Outlook bar control
[
Home
|
Contents
|
Search
|
Reply
| Previous | Next ]
C# Source Code
Source code for an Outlook bar control
By:
Andrew Baker
Email (spam proof):
Email the originator of this post
Date:
Wednesday, May 04, 2005
Hits:
1951
Category:
Windows Forms/GUI/Controls
Article:
Below is the source code for an Outlook bar control. If you enhance this code then please post your changes back to this group, so I can incorperate them back into the original. The control doesn't currently have a design time interface (would be good if someone could complete this) and as such has to be setup programatically, eg: OutlookGroupPanel panelApp = outlookBar.AddGroup("Application"); OutlookGroupPanel panelShortCuts = outlookBar.AddGroup("My Shortcuts"); OutlookGroupPanel panelOtherShortCuts = outlookBar.AddGroup("Other Shortcuts"); // Add four buttons to the "Application Panel" (hooking up the event handlers // for the buttons) panelApp.AddButton("Today", imgToday, null, new EventHandler(_OnPanelButtonClicked)); panelApp.AddButton("Calendar", imgCalendar, null, new EventHandler(_OnPanelButtonClicked)); panelApp.AddButton("Contacts", imgContacts, null, new EventHandler(_OnPanelButtonClicked)); panelApp.AddButton("Tasks", imgTasks, null, new EventHandler(_OnPanelButtonClicked)); ///
/// Click handler for Outlook Bar Panel. ///
///
///
private void _OnPanelButtonClicked(object sender, EventArgs e) { OutlookPanelButton panelButton = sender as OutlookPanelButton; MessageBox.Show("#"+ panelButton.Text, "Panel Event"); } Outlook bar source code: using System; using System.Drawing; using System.Diagnostics; using System.Collections; using System.Windows.Forms; using System.ComponentModel; #region OutlookBar ///
/// Provides a dockable outlook style panel. ///
[ToolboxBitmap(typeof(Panel)] public class OutlookBar : Panel { #region Events ///
/// Raised when the selected group changes. ///
[Description("Raised when the selected group changes.")] [Category("Behavior")] public event System.EventHandler SelectedGroupChanged; #endregion Events #region Private Variables private int _panelButtonHeight = 25; private int _selectedGroup = 0; private int _activePanelHeight = 0; private ArrayList _outlookGroups = new ArrayList(); private Splitter _splitterBar = new Splitter(); private int _minWidth = 100; private int _maxWidth = 200; #endregion Private Variables #region Constructors ///
/// Default contructor. ///
public OutlookBar() { _selectedGroup = 0; _activePanelHeight = 0; this.Dock = DockStyle.Left; this.Controls.Add(_splitterBar); _splitterBar.BringToFront(); _splitterBar.Dock = DockStyle.Right; _splitterBar.BorderStyle = BorderStyle.None; _splitterBar.MouseMove +=new MouseEventHandler(_OnSplitterMouseMove); _splitterBar.Width = 4; // Set the width to the default width this.Width = _minWidth; } #endregion Constructors #region Properties ///
/// Gets or sets the minimum width that the user can resize the outlook bar to. ///
[Description("Gets or sets the minimum width that the user can resize the outlook bar to.")] [Category("Behavior")] [DefaultValue(100)] public int MinWidth { get { return _minWidth; } set { _minWidth = value; _CheckWidth( this.Width ); } } ///
/// Gets or sets the maximum width that the user can resize the outlook bar to. ///
[Description("Gets or sets the maximum width that the user can resize the outlook bar to.")] [Category("Behavior")] [DefaultValue(200)] public int MaxWidth { get { return _maxWidth; } set { _maxWidth = value; _CheckWidth( this.Width ); } } ///
/// Returns the selected group panel. ///
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public OutlookGroupPanel this[int index] { get { return _outlookGroups[index] as OutlookGroupPanel; } } ///
/// Returns the count of the groups. ///
public int Count { get{ return _outlookGroups.Count; } } ///
/// Gets or sets the docking state of the outlook bar. ///
[Description("Gets or sets the docking state of the outlook bar."), Category("Appearance"), DefaultValue(DockStyle.Left)] public override DockStyle Dock { get { return base.Dock; } set { if( base.Dock != value) { base.Dock = value; _RepositionAllGroups(); } } } ///
/// Gets or sets the button heights for the panel buttons. ///
[Description("Gets or sets the button heights for the panel buttons."), Category("Appearance"), DefaultValue(25)] public int ButtonHeight { get { return _panelButtonHeight; } set { _panelButtonHeight = value; // do recalc layout for entire bar _CalculateActiveGroupHeight(); _RepositionAllGroups(); } } ///
/// Gets or sets the selected group. ///
[Description("Gets or sets the selected group."), Category("Appearance"), DefaultValue(0)] public int SelectedGroup { get { return _selectedGroup; } set { if ( value < 0 || value >= _outlookGroups.Count ) { throw new ArgumentOutOfRangeException("SelectedGroup", value, "The OutlookBar only contains " + _outlookGroups.Count + " panels!"); } _selectedGroup = value; _RepositionAllGroups(); if ( this.SelectedGroupChanged != null ) { // Raise the selected group changed event this.SelectedGroupChanged(this, System.EventArgs.Empty); } } } #endregion Properties #region Public Methods ///
/// Removes a panel from the outlook bar. ///
///
The panel group to remove. public void RemoveGroup(OutlookGroupPanel groupPanel) { this.Controls.Remove(groupPanel); } ///
/// Removes a panel from the outlook bar. ///
///
The text of the group button text. public void RemoveGroup(string groupButtonText) { OutlookGroupPanel removeGroup = null; foreach ( OutlookGroupPanel groupPanel in _outlookGroups ) { if ( groupPanel.GroupButton.Text == groupButtonText ) { // Found the panel removeGroup = groupPanel; break; } } if ( removeGroup != null ) { this.Controls.Remove(removeGroup); _RepositionAllGroups(); } } ///
/// Adds a group to the outlook bar. ///
///
The group button text of the group. ///
Returns the new outlook panel.
public OutlookGroupPanel AddGroup(string groupButtonText) { // Get the next index int index = _outlookGroups.Count; // Create the group panel OutlookGroupPanel groupPanel = new OutlookGroupPanel(groupButtonText, index); // Add the group panel this.Controls.Add(groupPanel); if ( _outlookGroups.Count == 1 ) { // Select the first group added this.SelectedGroup = 0; } _CalculateActiveGroupHeight(); _RepositionAllGroups(); return groupPanel; } #endregion Public Methods #region Protected Methods ///
/// Override to handle disposing of resources. ///
///
protected override void Dispose(bool disposing) { if ( disposing ) { _outlookGroups = null; } base.Dispose (disposing); } ///
/// Raises the ControlAdded event. ///
///
protected override void OnControlAdded(ControlEventArgs e) { base.OnControlAdded (e); // Keep a collection of the panels if ( e.Control is OutlookGroupPanel ) { _outlookGroups.Add(e.Control); } _splitterBar.BringToFront(); } ///
/// Raises the ControlRemoved event. ///
///
protected override void OnControlRemoved(ControlEventArgs e) { base.OnControlRemoved (e); if ( e.Control is OutlookGroupPanel ) { this.Controls.Remove(e.Control); } } ///
/// Raises the Resize event. ///
///
protected override void OnResize(EventArgs e) { base.OnResize (e); _CheckWidth( this.Width ); this.BringToFront(); _CalculateActiveGroupHeight(); _RepositionAllGroups(); } ///
/// Handles resizing the outlook bar. ///
///
protected virtual void OnSplitterMouseMove(MouseEventArgs e) { if ( e.Button == MouseButtons.Left ) { _CheckWidth( this.PointToClient( Control.MousePosition ).X ); } } #endregion Protected Methods #region Private Methods ///
/// Handles resizing the outlook bar. ///
///
///
private void _OnSplitterMouseMove(object sender, MouseEventArgs e) { this.OnSplitterMouseMove(e); } ///
/// Checks the width is within the min and max allowable values. ///
///
The new width to set the control to. private void _CheckWidth( int newWidth ) { int width = Math.Max( newWidth, _minWidth ); if ( _maxWidth != 0 ) { width = Math.Min( _maxWidth, width ); } if ( width != this.Width) { this.Width = width; } } ///
/// Repositions the outlook bar bands. ///
private void _RepositionAllGroups() { for (int i = 0; i < _outlookGroups.Count; i++) { OutlookGroupPanel groupPanel = _outlookGroups[i] as OutlookGroupPanel; _RepositionPanel(groupPanel, i); } } ///
/// Calculates the height of the selected group area (the area containing the icons) ///
private void _CalculateActiveGroupHeight() { _activePanelHeight = (this.ClientRectangle.Height) - (_outlookGroups.Count * _panelButtonHeight); } ///
/// Recalculates the outlook bar layout. ///
///
///
private void _RepositionPanel(OutlookGroupPanel groupPanel, int index) { int calcTop, calcHeight, calcWidth; if ( index <= _selectedGroup ) { // Below the selected group calcTop = _panelButtonHeight * index; } else { // Above or equal to the selected group calcTop = _panelButtonHeight * index + _activePanelHeight; } if ( _selectedGroup == index ) { // Positioning the selected group calcHeight = _activePanelHeight + _panelButtonHeight; } else { // Positioning an inactive group calcHeight = _panelButtonHeight; } calcWidth = this.ClientRectangle.Width - _splitterBar.Width; // the group dimensions groupPanel.Location = new Point( 0, calcTop ); groupPanel.Size = new Size( calcWidth , calcHeight ); // the contained button dimensions groupPanel.GroupButton.Location = new Point( 0, 0 ); groupPanel.GroupButton.Size = new Size( calcWidth, _panelButtonHeight ); // the contained panel dimensions groupPanel.GroupPanel.Location = new Point( 0, _panelButtonHeight ); groupPanel.GroupPanel.Size = new Size( calcWidth - 2, calcHeight - 6 ); } #endregion Private Methods } #endregion OutlookBar #region OutlookGroupPanel ///
/// This container control represents a grouping to be added to the OutlookBar control. This container panel /// is designed to contain any number of OutlookPanelButton controls. ///
[DefaultEvent("Click")] [ToolboxItem(false)] public class OutlookGroupPanel : Panel { #region Events ///
/// Click event. ///
[Description("Click event")] public new event System.EventHandler Click; #endregion Events #region Private Variables private int _groupIndex = -1; // Resources private ArrayList _panelButtons = new ArrayList(); private Button _groupButton = null; private Panel _groupPanel = null; #endregion Private Variables #region Constructors ///
/// Default constructor for a group panel. ///
///
The panel text. ///
The panel index. public OutlookGroupPanel(string text, int panelIndex) { // Store the properties _groupIndex = panelIndex; _groupPanel = new Panel(); // Create the button _groupButton = new Button(); _groupButton.Text = text; _groupButton.FlatStyle = FlatStyle.Popup; _groupButton.TabStop = false; _groupButton.Click += new EventHandler(_OnButtonClick); // Add the controls this.Controls.Add(_groupButton); this.Controls.Add(_groupPanel); _groupPanel.ControlAdded += new ControlEventHandler(_OnGroupPanelControlAdded); _groupPanel.ControlRemoved += new ControlEventHandler(_OnGroupPanelControlRemoved); } #endregion Constructors #region Public Properties ///
/// Get the specified panel button. ///
public OutlookPanelButton this[int index] { get { return _panelButtons[index] as OutlookPanelButton; } } ///
/// Get the specified panel button. ///
public OutlookPanelButton this[string text] { get { for( int i = 0; i < _panelButtons.Count; i++) { OutlookPanelButton button = _panelButtons[i] as OutlookPanelButton; if ( string.Compare( button.Text, text, true ) == 0 ) { // Found button return button; } } return null; } } ///
/// Returns the count of the panel buttons in this group. ///
public int Count { get { return _panelButtons.Count; } } ///
/// Returns the index for this for this group. ///
public int GroupIndex { get{ return _groupIndex;} } ///
/// Returns the panel for this group. ///
public Panel GroupPanel { get{ return _groupPanel; } } ///
/// Returns the button for this group. ///
public Button GroupButton { get{ return _groupButton; } } ///
/// Gets the parent for this panel group. ///
public new OutlookBar Parent { get { return base.Parent as OutlookBar; } } #endregion Public Properties #region Public Methods ///
/// Adds an entry into the icon panel. ///
///
The button text. ///
The large button icon (can be null). ///
The small button icon (can be null). ///
The click event handler. ///
Returns the panel button.
public OutlookPanelButton AddButton(string buttonText, Image largeIcon, Image smallIcon, EventHandler onClickEvent) { // Create the new button OutlookPanelButton panelButton = new OutlookPanelButton(buttonText, largeIcon, smallIcon, onClickEvent); // Add the control _groupPanel.Controls.Add( panelButton ); return panelButton; } ///
/// Removes the specified button from the group. ///
///
The icon text of the button to remove. public void RemoveButton(string buttonText) { OutlookPanelButton removeButton = null; foreach ( OutlookPanelButton panelButton in _panelButtons ) { if ( string.Compare( panelButton.Text , buttonText, true ) == 0 ) { // Found the control removeButton = panelButton; break; } } if ( removeButton != null ) { // Remove the button _groupPanel.Controls.Remove( removeButton ); } } ///
/// Removes the specified button from the group. ///
///
The button to remove. public void RemoveButton(OutlookPanelButton button) { if ( button != null ) { // Remove the button _groupPanel.Controls.Remove( button ); } } #endregion Public Methods #region Protected Methods ///
/// Override to handle disposing of resources. ///
///
protected override void Dispose(bool disposing) { if ( disposing ) { _panelButtons = null; if ( _groupButton != null ) { _groupButton.Dispose(); _groupButton = null; } if ( _groupPanel != null ) { _groupPanel.Dispose(); _groupPanel = null; } } base.Dispose (disposing); } ///
/// Handles the button click which activates this panel. ///
///
protected virtual void OnButtonClick(EventArgs e) { // Set the selected group to this group this.Parent.SelectedGroup = _groupIndex; if ( Click != null ) { // Raise click event Click(this, EventArgs.Empty); } } ///
/// Called when a new control is added to the group panel. ///
///
protected virtual void OnGroupPanelControlAdded(ControlEventArgs e) { if ( e.Control is OutlookPanelButton ) { // Keep a list of the buttons in this group e.Control.BringToFront(); _panelButtons.Add( e.Control ); } } ///
/// Called when a control is removed from the the group panel. ///
///
protected virtual void OnGroupPanelControlRemoved(ControlEventArgs e) { if ( e.Control is OutlookPanelButton ) { // Keep a list of the buttons in this group _panelButtons.Remove( e.Control ); } } #endregion Protected Methods #region Private Methods ///
/// Handles the button click which activates this panel. ///
///
///
private void _OnButtonClick(object sender, EventArgs e) { this.OnButtonClick(e); } ///
/// Called when a new control is added to the group panel. ///
///
///
private void _OnGroupPanelControlAdded(object sender, ControlEventArgs e) { this.OnGroupPanelControlAdded(e); } ///
/// Called when a control is removed from the the group panel. ///
///
///
private void _OnGroupPanelControlRemoved(object sender, ControlEventArgs e) { this.OnGroupPanelControlRemoved(e); } #endregion Private Methods } #endregion OutlookGroupPanel #region OutlookPanelButton ///
/// A panel button which belongs to a panel group in the outlook bar control. ///
[DefaultEvent("Click")] [ToolboxItem(false)] public class OutlookPanelButton : Control { #region Private Variables private int _margin = 3; private Color _backColor = Color.Empty; private Color _mouseOverColor = Color.FromArgb(182,189,210); private EventHandler _click = null; private bool _isMouseOver = false; private bool _useLargeIcons = true; // Resources to dispose of private OutlookGroupPanel _parentGroup = null; private PictureBox _pictureBox = null; private Label _lblIcon = null; private System.Windows.Forms.Timer _tmrCheckMouseOver; private Image _smallIcon = null; private Image _largeIcon = null; #endregion Private Variables #region Private Constants const int TOP_BORDER = 3; #endregion Private Constants #region Constructors ///
/// Parameterised constructor for this panel. ///
///
The large icon for this button (can be null). ///
The small icon for this button (can be null). ///
The text to display for this button. ///
The click event handler for this button. public OutlookPanelButton(string buttonText, Image largeIcon, Image smallIcon, EventHandler onClickEvent) { // Store the index _click = onClickEvent; _largeIcon = largeIcon; _smallIcon = smallIcon; // Create icon _pictureBox = new PictureBox(); _pictureBox.SizeMode = PictureBoxSizeMode.AutoSize; _pictureBox.Top = TOP_BORDER; if ( smallIcon == null ) { _useLargeIcons = true; _pictureBox.Image = largeIcon; } else { _useLargeIcons = false; _pictureBox.Image = smallIcon; } _pictureBox.MouseDown += new MouseEventHandler(_OnPictureMouseDown); _pictureBox.Paint +=new PaintEventHandler(_OnPicturePaint); _pictureBox.MouseLeave += new EventHandler(_OnIconMouseLeave); _pictureBox.MouseMove += new MouseEventHandler(_OnIconMouseMove); _pictureBox.Visible = true; // Create label _lblIcon = new Label(); _lblIcon.Text = buttonText; _lblIcon.Visible = true; _lblIcon.TextAlign = ContentAlignment.MiddleCenter; _lblIcon.Height = _TextSize(_lblIcon).Height; _lblIcon.Left = 1; _lblIcon.TextChanged +=new EventHandler(_OnIconLabelTextChanged); // Add the controls this.Controls.Add(_lblIcon); this.Controls.Add(_pictureBox); // Store the backcolor _backColor = this.BackColor; // Calculate the height required (width is set by docking) this.Height = _pictureBox.Top + _pictureBox.Height + _lblIcon.Height + _margin; this.Dock = DockStyle.Top; this.Visible = true; _tmrCheckMouseOver = new Timer(); _tmrCheckMouseOver.Enabled = false; _tmrCheckMouseOver.Tick +=new EventHandler(_OnTimerCheckMouseOver); } #endregion Constructors #region Public Properties ///
/// Gets or sets the click event handler. ///
public new EventHandler Click { get { return _click; } set { _click = value; } } ///
/// Gets the parent group for this button. ///
public new OutlookGroupPanel Parent { get{ return _parentGroup; } } ///
/// Gets or sets the margin around this panel button. ///
public int Margin { get { return _margin; } set { _margin = value; this.Height = _pictureBox.Height + _lblIcon.Height + _margin; } } ///
/// Gets or sets the outlook panel button text. ///
public override string Text { get { return _lblIcon.Text; } set { _lblIcon.Text = value; } } ///
/// Gets or sets the large icon used for this button. ///
public Image LargeIcon { get { return _largeIcon; } set { _largeIcon = value; _SetButtonImage(); } } ///
/// Gets or sets if the icon displayed is the small or large icon. ///
public bool UseLargeIcons { get{ return _useLargeIcons; } set { _useLargeIcons = value; _SetButtonImage(); } } ///
/// Gets or sets the icon backcolor when the mouse hovers over the control. ///
public bool IsMouseOver { get { return _isMouseOver; } set { if ( value != _isMouseOver) { // Value has changed _isMouseOver = value; if ( value ) { // Mouse over icon _pictureBox.BackColor = _mouseOverColor; _pictureBox.BorderStyle = BorderStyle.FixedSingle; // HACK: the MouseLeave event doesn't always fire, this timer // checks the mouse is still over the icon. _tmrCheckMouseOver.Enabled = true; } else { // Mouse not over icon _tmrCheckMouseOver.Enabled = false; _pictureBox.BackColor = _backColor; _pictureBox.BorderStyle = BorderStyle.None; } } } } ///
/// Gets or sets the small icon used for this button. ///
public Image SmallIcon { get { return _smallIcon; } set { _smallIcon = value; _SetButtonImage(); } } ///
/// Gets or sets the mouse over color for this buttons image. ///
public Color MouseOverColor { get { return _mouseOverColor; } set { _mouseOverColor = value; } } #endregion Public Properties #region Protected Methods ///
/// Override to handle disposing of resources. ///
///
protected override void Dispose(bool disposing) { if ( disposing ) { _parentGroup = null; if ( _lblIcon != null ) { _lblIcon.Dispose(); _lblIcon = null; } if ( _pictureBox != null ) { _pictureBox.Dispose(); _pictureBox = null; } if ( _lblIcon != null ) { _lblIcon.Dispose(); _lblIcon = null; } if ( _tmrCheckMouseOver != null ) { _tmrCheckMouseOver.Dispose(); _tmrCheckMouseOver = null; } if ( _smallIcon != null ) { _smallIcon.Dispose(); _smallIcon = null; } if ( _largeIcon != null ) { _largeIcon.Dispose(); _largeIcon = null; } } base.Dispose (disposing); } ///
/// Event handler for enabled state changing - update control appearance. ///
///
protected override void OnEnabledChanged(EventArgs e) { base.OnEnabledChanged (e); _SetButtonImage(); } ///
/// Retrieves the parent for this panel button. ///
///
protected override void OnParentChanged(EventArgs e) { base.OnParentChanged (e); // The buttons are added to a panel control on the OutlookGroupPanel. // Hence must use .Parent.Parent. _parentGroup = base.Parent.Parent as OutlookGroupPanel; } ///
/// Overrides to synchronise the fonts. ///
///
protected override void OnFontChanged(EventArgs e) { base.OnFontChanged (e); _lblIcon.Font = this.Font; _lblIcon.Height = _TextSize(_lblIcon).Height; OnResize( EventArgs.Empty ); } ///
/// Sychronises the controls component back colors. ///
///
protected override void OnBackColorChanged(EventArgs e) { base.OnBackColorChanged (e); _pictureBox.BackColor = this.BackColor; _backColor = this.BackColor; } ///
/// Raises the resize event. ///
///
protected override void OnResize(EventArgs e) { base.OnResize (e); // Center icon _pictureBox.Left = ((this.ClientSize.Width - _pictureBox.Width) / 2); // Spread label across control _lblIcon.Width = this.ClientSize.Width - (_lblIcon.Left * 2); _lblIcon.Top = _pictureBox.Top + 1 + _pictureBox.Height; // Set the control height this.Height = _pictureBox.Top + _pictureBox.Height + _lblIcon.Height + _margin; } #endregion Protected Methods #region Private Methods ///
/// Sets the relevant image icon for the button. ///
private void _SetButtonImage() { if ( _useLargeIcons ) { // Using large icons _pictureBox.Image = _largeIcon; } else { // Using small icons _pictureBox.Image = _smallIcon; } // Resize the image OnResize(EventArgs.Empty); } ///
/// Handles the mouse leave (restoring the icon backcolor). ///
///
///
private void _OnIconMouseLeave(object sender, EventArgs e) { this.IsMouseOver = false; } ///
/// Handles the mouse enter (changing the icon backcolor). ///
///
///
private void _OnIconMouseMove(object sender, MouseEventArgs e) { this.IsMouseOver = true; } ///
/// Raised when the icon is clicked. ///
///
///
private void _OnPictureMouseDown(object sender, MouseEventArgs e) { if ( e.Button == MouseButtons.Left && _click != null ) { _click(this, e); } } ///
/// Handles drawing the picture box when it's disabled. ///
///
///
private void _OnPicturePaint(object sender, PaintEventArgs e) { if ( !this.Enabled && _pictureBox.Image != null ) { ControlPaint.DrawImageDisabled( e.Graphics, _pictureBox.Image, _pictureBox.ClientRectangle.X, _pictureBox.ClientRectangle.Y, this.BackColor); } } ///
/// HACK: The mouse leave event doesn't always fire, so this check the mouse /// is still over the icon. ///
///
///
private void _OnTimerCheckMouseOver(object sender, EventArgs e) { if ( !_IsMouseOver( _pictureBox.ClientRectangle ) ) { // Mouse is no longer over icon _tmrCheckMouseOver.Enabled = false; this.IsMouseOver = false; } } ///
/// Resizes the label when it's text changes. ///
///
///
private void _OnIconLabelTextChanged(object sender, EventArgs e) { _lblIcon.Height = _TextSize(_lblIcon).Height; OnResize( EventArgs.Empty ); } ///
/// Determines if the mouse is over the specified rectangle. ///
///
The screen rectangle of the area to check if the mouse is over. ///
Returns true if the mouse is over the specified rectangle, else returns false.
private bool _IsMouseOver( Rectangle rectangle ) { return rectangle.IntersectsWith ( new Rectangle( Control.MousePosition, new Size(1, 1) ) ) ; } ///
/// Returns the text height and width of the "Text" contained in the specified control. ///
///
The control containing the text to be measured. ///
Returns the size of the text area.
///
Calculates the text size using the font of the control. /// This routine is equivalent to TextHeight and TextWidth functions in VB. ///
private Size _TextSize(Control owner) { using(Graphics g = owner.CreateGraphics()) { return Size.Ceiling( g.MeasureString(owner.Text, owner.Font) ); } } #endregion Private Methods } #endregion OutlookPanelButton
Terms and Conditions
Support this site
Download a trial version of the best FTP application on the internet