Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / VB

Border Container

4.88/5 (23 votes)
10 Feb 2010CPOL12 min read 1   3.2K  
A collapsable container control with complete header, border, and color customization. Also has the ability to utilize an 'Activation' button (like the 'Active Files' button you'll find at the top of every form in the Visual Studio IDE).

Border Container - A Panel on Steroids

With the changes to the BorderControl I wrote two years ago, the once slim and trim replacement for the WinForms.Panel control has grown large, fat, and heavy! It was a small price to pay to improve the UI for the applications I've been working on, and while the control has grown in size and complexity, the machines using my controls have also grown in power and ability... so it was a wash as far as I was concerned.

That having been said, you could easily take this new control and remove from it everything you didn't require and wind up with a fairly small DLL.

While you can dynamically adjust the height of the Header within the BorderContainer (BC), the three buttons: Close, Collapse, and Activation, are all fixed in height and width, so if you planned on a Header with a height of 12 pixels and you wanted to use one or more of the management buttons, you'll definitely want to change the images within the ImageList as well as the CONSTs that are used for ButtonHeight and ButtonWidth as well.

Image 1

BorderContainer

Along with the BorderContainer (a replacement for the Panel control), you also get in the DLL, a BorderForm which is a replacement for Windows.Forms.Form. It has all of the same properties as BorderContainer minus the Collapse capabilities. There is also a property that sets the opacity of the form while being dragged.

The image on the left shows a sample BorderForm.

The image on the right shows that same BorderForm being dragged with a DragOpacity of 0.5.

BorderContainer

BorderForm - Being dragged
 

Image 4

Author's note: The Color Selector control used as a replacement for .NET's color property editor is included in BorderContainer.dll. It's a dialog box, but as you can see from the demo BorderContainer shown here, you can also use the individual parts: ColorBox and VerticalColorSlider.

What's New?

A graphical 'collapse' button has replaced the old-style push-pins. The image for this button changes based on where the BorderContainer is docked. There is an ImageList that holds normal, mouse-over, and mouse-down images for Top, Left, Right, and Bottom collapsing as well as the Activation and Close buttons. They are 17x19 32 bit PNGs, but changing them would be as easy as replacing the corresponding images within that ImageList, making sure you change the sizes appropriately - then changing the two constants: BUTTON_HEIGHT and BUTTON_WIDTH to match your new image size.

  • ButtonOffset - This is a property that allows you to adjust how close to the right-edge of the BC you want your buttons to line up with.
  • ButtonGap - a property that allows you to adjust the number of pixels in between each button.

A 3-color gradient header is now available along with the ability to adjust where the center color fades in:

  • BackgroundColorBegin - The starting color of your gradient.
  • BackgroundColorCenter - The middle color of the gradient.
  • BackgroundColorEnd - The final color of the gradient. This is also the solid color used to fill-in the Header if you select no gradient, as well as the color used to fill-in the side panels if you enter an InnerBorderWidth > 0.

Here are some of the properties that have been added:

  • AutoCollapse: If True, the BorderContainer (BC) will automatically collapse when the user double-clicks the header.
  • AutoRefresh: If True, the BC will refresh itself automatically whenever UI properties are changed. You can turn this to False if you're going to set a large number of properties at run-time, then refresh the entire control when your property changes have been completed.
  • AllowResize: If True, the user can resize the control at run-time without having to place a Splitter control next to the BC.
  • InnerBorderWidth: A property that will display a border along the inside of the BC - the ClientRectangle is automatically adjusted to prevent controls added to the BC from drawing over the top of this inner border.
  • RoundedCorners: When set to True will draw the header with rounded edges, the size of which is adjusted by setting the RoundSize property.

Using the Code

Drop the DLL into your Libraries folder (or wherever you put your own custom-controls), then add it to the VS IDE toolbar. Once added to the Toolbar, you can use the BC just like a Panel.

Property Details

BorderContainer has the following properties:

BorderDetailsThis is an expandable property that contains the bulk of the UI settings.
BorderColorThe color of your border
BorderLines Expandable property holding all of the border settings
  
InnerBorder If True, will draw a single-pixel border around the inside of the client area
InnerPanelShowAll If True, will set all InnerPanel properties to True
InnerPanelShowBottom Displays the Bottom Inner Panel
InnerPanelShowLeft Displays the Left Inner Panel
InnerPanelShowRight Displays the Right Inner Panel
InnerPanelShowTop Displays the Top Inner Panel but only if DisplayHeader has been set to False.
ShowAllOutLines If True, will set all OutLine properties to True
ShowBottomOutLine Shows the Bottom Outline
ShowLeftOutLine Shows the Left Outline
ShowRightOutLine Shows the Right Outline
ShowTopOutLine Shows the Top Outline
   
DisplayHeaderIf True, a header will be displayed at the top of the BorderContainer
HeaderDetailsExpandable property - all of the details are listed below in this document
InnerBorderWidth Establishes the width in pixels of the Inner Border panels; valid settings range from 0 (no border) to 10 (very wide)
   
AllowResize If True, this will allow the user to resize the non-docked edge(s) of the BC; if the BC is docked, only the movable size of the BC can be dragged for resizing
   
AutoCollapse If True, the BC will collapse when the user double-clicks the Header
   
AutoRefresh If True, the BC will repaint whenever any UI properties are adjusted during run time; if you have a large number of UI properties to change, you might want to set this to False - make your changes, then reset this value to True so the painting only occurs once
   
CollapsePanel This is a built-in Panel control that appears if ShowCollapsePanel = True and the BC has been collapsed; you can set all standard panel properties at design-time, but you'll have to add any additional controls to this panel at run-time
   
CurrentStateThis identifies how the Container will be displayed when the form is opened; 'open' is the default, but you can have the control collapsed at start-up
  
HeaderImageAn icon you can place inside the Header
HeaderImageAlignmentHorizontal placement of the icon

BorderDetails.HeaderDetails is an expandable property that handles all Header-specific UI elements, and has the following sub-properties:

ActivationMenuThis built-in ContextMenuStrip can be edited from within the BorderContainer properties window or at run-time. To add menu items to the strip, expand the ActivationMenu property, scroll down to 'Items', and click on the collection editor. All ToolStripItem types are supported and are added as controls to your form, just as if you had created them by adding your own MenuStrip... so, if you want to trap the SelectedIndexChanged event of a MenuStripComboItem - just look for the control in the 'Class Name' drop down in the VS IDE.
AntiAliasTextIf True, the text displayed in the Header will be anti-aliased.
BackgroundColorBeginThe starting color for the gradient used to fill the Header.
BackgroundColorCenter The middle color for the gradient.
BackgroundColorEnd Has several purposes: first, its the final color in the gradient. It is also the color used to fill the inner panels if InnerPanelWidth > 0, and it is the solid color used to fill the entire Header if no gradient is selected.
ButtonGapThe gap (in pixels) between each of the buttons drawn in the Header.
ButtonOffset The gap (in pixels) between the right-edge of the last button drawn and the right-edge of the BC.
ForegroundColor The foreground color of the BC. Use this to adjust your HeaderText foreground color.
GradientMode Valid settings are: None, Horizontal, Vertical, ForwardDiagonal, and BackwardDiagonal.
GradientPercentage There is a smooth transition from Begin to Center to End colors in the gradient. This is the percentage at which the middle color will be at 100%. Example: GradientMode=Horizontal and your BC is 100 pixels wide. Setting this to 0.20 will mean that at 20% of the width of the BC, the color will be BackgroundColorCenter... So, the closer to 0 you set this, the faster the change from Begin to Center will occur, and the closer to 1 you set it, the further that transition will take.
HeightThe height (in pixels) of the header. All graphics displayed in the header will resize, but keep in mind that if you make the height too small, your users will not see the images properly.
RoundedCornersIf True, the BC will display rounded corners in the header.
RoundSize The radius (in pixels) of the 'round' corners.
ShowActivationMenuIf True, the Activation button will be displayed.
ShowCloseIf True, the Close button will be displayed.
ShowCollapse If 'True, the Collapse button will be displayed.
ShowCollapsePanel If True, the Collapse Panel will be displayed whenever the BC is collapsed.
TextThis is the text-string that is displayed in the Header. If the text is truncated, ellipses (...) will be drawn at the truncation point.
TextAlignmentLeft is default. Middle and Right are the other available options.

Control Events

The following table shows all events that could be raised at run-time.

ResizedFires when your Container is collapsed or expanded
HeaderDoubleClickFires when the user double-clicks the Header
HeaderClickFires when the user clicks the Header
ActivationClickFires whenever the Activation button has been clicked; this will fire regardless of whether or not you are using the built-in ContextMenuStrip
ActivationMenuOpenedFires whenever the Activation menu is opened
ActivationMenuClosedFires whenever the Activation menu is closed
CloseClicked Fires whenever the Close button has been clicked
DragResizeComplete Fires when the User has completed drag-resizing
DragResizing Fires while the BC is being drag-resized
DragResizeBegin Fires when the user begins to drag-resize

Custom Property Editor - Color Picker

There is a custom property editor included with this project called, 'ColorEditor.' This required several additional steps to implement, all of the details of which can be found in this wonderful article written by Saeed Serpooshan. I made several modifications for my own personal use, but there is simply no way I would have been able to complete this portion of my control without help from that article...so, Thanks Saeed!

Color_Picker.gif

Custom Property Display Values

One of the modifications I made was to force the property window to display the value *I* wanted displayed, rather than the default data it wanted to display.

I had problems getting the Custom Property Editor to work on Color type, and I think that's because Color already uses a custom editor ... I had to learn how to override that internal custom editor before mine will work... Anyway, to get around it, I store all of my control colors as strings in the format, "###, ###, ###", which are nothing more than simple RGB values. But I did not want the string to be displayed: I wanted the color in the color-box, followed by editable text.

To pull that off, you have to first tell the editor that you are going to override the painted value, and then (of course) you have to provide the new paint method yourself:

VB
Public Overrides Function GetPaintValueSupported(_
    ByVal context As System.ComponentModel.ITypeDescriptorContext) As Boolean
    Return True
End Function

and here is the overridden Paint:

VB
Public Overrides Sub PaintValue(ByVal e As System.Drawing.Design.PaintValueEventArgs)
    ' Go fill the area first...
    Dim width As Integer = e.Bounds.Width - 1
    Dim height As Integer = e.Bounds.Height - 1
    Dim brush_HeaderBG As New SolidBrush(_myColor)
    e.Graphics.FillRectangle(brush_HeaderBG, 1, 1, width, height)
End Sub

Anti Aliased Text

Anyone out there think this is horrific and complex, and so much work that it's not worth your time and effort? Think again! Normally, if you want to manually paint text, you would do something like this:

VB
' establish our drawing area (_width/_height
' are defined above but not seen in this
' code snippet)
Dim text_Rectangle As New RectangleF
text_Rectangle.X = 1                ' Upper Left Corner...Left
text_Rectangle.Y = 1                ' Upper Left Corner...Top
text_Rectangle.Width = _width - 1   ' Lower Right Corner..Left
text_Rectangle.Height = _height - 1 ' Lower Right Corner..Right

' establish our formatting
Dim text_Format As New StringFormat
text_Format.Trimming = StringTrimming.EllipsisCharacter  ' draws ellipses (...) at the
                                                         ' truncation point
text_Format.Alignment = StringAlignment.Center           ' Vertical positioning
text_Format.LineAlignment = StringAlignment.Center       ' Horizontal positioning
text_Format.FormatFlags = StringFormatFlags.NoWrap       ' Dont wrap the text...let
                                                         ' the Ellipses do their work

' establish our brush
' (SomeColor is a Color Type defined above but not seen in this code snippet)
Dim text_Brush As New SolidBrush(SomeColor)

' Paint the text
e.Graphics.DrawString("Your Text Goes Here", Me.Font, _
                      text_Brush, text_Rectangle, text_Format)

But, let's say you want that happy little string to be anti-aliased. GDI gives us everything we need...this is a very complex set of code and not commented very well, so please read carefully!

VB
.
.
.
' Anti Alias the text
e.Graphics.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAlias

' Paint the text
e.Graphics.DrawString("Your Text Goes Here", Me.Font, _
                      text_Brush, text_Rectangle, text_Format)
.
.
.

A similar technique can be used for all Drawing methods like the border used to surround the rounded corners:

VB
.
.
.
' Anti Alias the drawing
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias
e.Graphics.DrawArc(BorderPen, _PLeft, _PTop, ArcSize, ArcSize, 180, 90)
e.Graphics.DrawArc(BorderPen, _PWidth - ArcSize, _
                   _PTop, ArcSize, ArcSize, -90, 90)
.
.
.

Trimming the Fat

This last section would be to describe the various areas of the control that can be removed if you're looking for just the basics:

  • Activation Menu: Cutting the Activation button and Context Menu would go hand-in-hand with removing the images for that button as well as the code to activate and raise the events. This would be an easy way to trim.
  • Collapse Panel: This was added for one specific project I was working on, and I've never used it again - there's not a ton of overhead in including the collapse panel, but this would be another, very easy target for removal.
  • Gradient brushes: Unless you're going to require gradient headers, all gradient painting and properties could be removed with very little effort.
  • Resizability: The code that allows this is relatively small - you could remove this quite easily, but you would not be saving very much, and most good UIs have the display elements contained within sizable panels.
  • BorderForm: This is an entire namespace that you could remove with a single-click, and compile, reducing the size of the DLL significantly.
  • Color Picker: Removing this will take a bit more work. It is not as simple as changing the property from the custom editor. Since the parent property is expecting a 'String' type for this property, you'll have to remove the custom color editor and change the color properties back to type 'Color'.

Installation

  1. Unzip the source files and open the BorderContainer project.
  2. Compile the project.
  3. Open the Form Toolbox in Visual Studio.
  4. Right-click on the tab in which you would like to place the control.
  5. Click 'Choose Items...'.
  6. From the 'Choose Toolbox Items' dialog box, click 'Browse'.
  7. Navigate to the Bin folder under BorderContainer (and deeper into either Debug or Release, depending on your settings).
  8. Click on BorderContainer.dll and click 'Open'.

That's it! The BorderContainer is now part of your Toolbox and available for use in any of your VB.NET projects.

History

  • 07/29/2008: Control first introduced to CodeProject.com.
  • 02/10/2010: Bug fixes.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)