Click here to Skip to main content
Email Password   helpLost your password?

MozBar

Introduction

I started this project when I needed something like the toolbar in FireFox's Options dialog in one of my other projects. This is where the name came from. I looked around but couldn't find any control that had what I needed so I decided to write my own.

Another benefit of writing this control was that it gave me the opportunity to play around with some of the techniques used in control creation, i.e., Designers, TypeConverters and TypeEditors. I will not go into code details (that's what the source code is for) but I will try to mention a little about the techniques used.

I took a lot of hints from Matthew Hall's Themed Taskbar for general design and use of collections, and I also borrowed John O' Byrne's excellent Imagelistpopup control, modified it slightly and used it in my image dropdown editor.

Using the control

Like any other .NET control, for use in the IDE, you should add the MozBar control to a Toolbox panel. This can be accomplished by right-clicking on a Toolbox tab and selecting "Add/Remove items...", browsing to the MozBar assembly, and selecting it. This will add all the MozBar controls to the Toolbox so they can be dragged/dropped to a Windows Form or control.

There are two primary controls in the MozBar assembly:

A MozItem is the control that defines a toolbar item. A MozItem must be contained by a MozPane. A MozPane is a container for a collection of MozItem controls, and provides automatic placement and relocation as they are added or removed.

Once an instance of MozPane or MozItem is added to the form, select it and view its properties.

MozPane

The MozPane acts as a container for all the MozItems that the MozBar will contain.

There are several properties that define the appearance and behavior of the MozBar:

The most useful events are:

All eventArgss include the MozItem responsible for the event. To check which item caused the event, use the Tag property.

private void mozPane1_ItemSelected(object sender, Pabo.MozBar.MozItemEventArgs e)
{
    // Check the tag..

    switch(e.MozItem.Tag)
    {
        case "Save":
        {
            break;
        }
        case "Load":
        {
            break;
        }
    }
}

The ItemClick event uses the ItemClickEventArgs which in addition to the responsible MozItem also includes the Button property which contains the button used.

To select an item, use the methods SelectItem(int index) or SelectItem(string tag), you have the option of using either the index or the tag to identify the item.

MozItem

A MozItem is the actual toolbar item and it can be added to MozPane by simply dragging it onto the MozPane from the toolbox or by using the Controls property in the MozPane control.

A MozItem can have one of three possible states:

Each of the states can have a different image, borderstyle and color for background and border. The images are set through the item's Images property; colors and borderstyles are set with the ItemColors and ItemBorderStyles properties in the MozPane control.

An item can also have different styles, that are set using the ItemStyle property:

When set to Divider, the item will show as a divider (similar to the ones used in menus) either horizontally or vertically depending on the Style of the MozPane. If TextAndPicture is used, the Text can be aligned using the TextAlign property, possible positions are Left, Top, Right or Bottom.

Nested properties

A nice way to organize related properties in a control is to group them together in a nested structure, common examples of this in controls are Size and Font properties. In MozBar, this technique is used with several properties, among them the Padding property in MozPane.

Padding property

To accomplish this, we need to do two things. First, we need a class (PaddingCollection) that contains the properties we want grouped together, and second, we need a TypeConverter (PaddingCollectionTypeConverter) to display the properties properly.

[TypeConverter(typeof(PaddingCollectionTypeConverter))]
public class PaddingCollection
{
    private MozPane m_pane;
    private int m_horizontal;
    private int m_vertical;

    public PaddingCollection(MozPane pane)
    {
        // set the control to which the collection belong

        m_pane = pane;
        // Default values

        m_horizontal = 2;
        m_vertical = 2;
    }

    [RefreshProperties(System.ComponentModel.RefreshProperties.All)]
    [Description("Horizontal padding.")]
    public int Horizontal
    {
        get
        {
            return m_horizontal;
        }
        set
        {
            m_horizontal = value;
            if (m_pane!=null)
            {
                // padding has changed , force DoLayout

                m_pane.DoLayout();
                m_pane.Invalidate();
                if (m_pane.PaddingChanged!=null)
                  m_pane.PaddingChanged(this,new EventArgs());
 
            }
        }
    }

    [RefreshProperties(System.ComponentModel.RefreshProperties.All)]
    [Description("Vertical padding.")]
    public int Vertical
    {
        get
        {
            return m_vertical;
        }
        set
        {
            m_vertical = value;
            if (m_pane!=null)
            {
                m_pane.DoLayout();
                m_pane.Invalidate();
                if (m_pane.PaddingChanged!=null)
                    m_pane.PaddingChanged(this,new EventArgs());
            }
        }
    }

}

The class is pretty straightforward but the important things are the attributes. The TypeConverter attribute is used to assign the type converter to the class.

[TypeConverter(typeof(PaddingCollectionTypeConverter))]
public class PaddingCollection
{
}

The RefreshProperties attribute is used to force a refresh of properties when the property to which the attribute is assigned is changed.

[RefreshProperties(System.ComponentModel.RefreshProperties.All)]
public int Horizontal
{
}

Since this is a nested property, the type converter should inherit from ExpandableObjectConverter and we need to override four methods. In CanConvertTo and CanConvertFrom, we need to make sure we can convert to and from strings. The actual conversion is done in the ConvertTo and ConvertFrom functions.

public class PaddingCollectionTypeConverter : ExpandableObjectConverter
{

    public override bool CanConvertFrom(ITypeDescriptorContext context, 
                                                       Type sourceType)
    {
        if(sourceType == typeof(string))
            return true;
        return base.CanConvertFrom (context, sourceType);
    }

    public override bool CanConvertTo(ITypeDescriptorContext context, 
                                                Type destinationType)
    {
        if(destinationType == typeof(string))
            return true;
        return base.CanConvertTo (context, destinationType);
    }

    public override object ConvertFrom(ITypeDescriptorContext 
       context, System.Globalization.CultureInfo culture, object value)
    {

        if(value.GetType() == typeof(string))
        {
            // Parse property string

            string[] ss = value.ToString().Split(new char[] {';'}, 2);
            if (ss.Length==2)
            {
                // Create new PaddingCollection

                PaddingCollection item = 
                   new PaddingCollection((MozPane)context.Instance); 
                // Set properties

                item.Horizontal = int.Parse(ss[0]);
                item.Vertical = int.Parse(ss[1]); 
                return item;
            }
        }
        return base.ConvertFrom (context, culture, value);
    }

    public override object ConvertTo(ITypeDescriptorContext context, 
                    System.Globalization.CultureInfo culture, 
                    object value, Type destinationType)
    {

        if(destinationType == typeof(string) && 
          (value is MozPane.PaddingCollection) )
        {
            // cast value to paddingCollection

            PaddingCollection dest = (PaddingCollection)value;  
            // create property string

            return dest.Horizontal.ToString()+"; "+dest.Vertical.ToString();
        }
        return base.ConvertTo (context, culture, value, destinationType);
    }

}

All that's left to do is to create a public property in MozPane that handles a value of type PaddingCollection, and we are all set.

true)>
[Category("Appearance")]
[Description("Padding (Horizontal, Vertical)")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public PaddingCollection Padding
{
    get
    {
        return m_padding;
    }
    set
    {
        if (value!=m_padding)
        {
            if (value != null)
                m_padding = value;
            DoLayout();
            Invalidate();
            if (this.PaddingChanged!=null)
              this.PaddingChanged(this,new EventArgs());
        }
    }
}

Custom image selector

Another nice thing to provide with controls is custom type editors. Each of the image states in MozItem uses a custom image selector for selecting images from the ImageList assigned in the MozPane.

Padding property

For this to work, we must create our own type editor (ImageMapEditor) that inherits from System.Drawing.Design.UITypeEditor.

public class ImageMapEditor : System.Drawing.Design.UITypeEditor   
{
}

We must override GetEditStyle and return the style we want to use.

public override System.Drawing.Design.UITypeEditorEditStyle 
         GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
{
    if(context != null && context.Instance != null ) 
    {
        return UITypeEditorEditStyle.DropDown ;
    }
    return base.GetEditStyle (context);
}

We must also override GetPaintValueSupported to be able to paint our own value.

public override bool 
       GetPaintValueSupported(System.ComponentModel.ITypeDescriptorContext context)
{
    return true;
}

To initiate the editing of the property, we override EditValue. If there is an ImageList assigned, we create a new instance of ImageListPanel and then use IWindowsFormsEditorService.DropDownControl to display it in a dropdown. Before displaying the dropdown, we also add an event listener so that we can handle the user input.

public override object 
                EditValue(System.ComponentModel.ITypeDescriptorContext context, 
                IServiceProvider provider, object value)
{
    wfes = (IWindowsFormsEditorService) 
      provider.GetService(typeof(IWindowsFormsEditorService));
    if((wfes == null) || (context == null))
        return null ;

    ImageList imageList = GetImageList(context.Instance) ;
    if ((imageList == null) || (imageList.Images.Count==0))
        return -1 ;

    m_imagePanel = new ImageListPanel(); 

    m_imagePanel.BackgroundColor = Color.FromArgb(241,241,241);
    m_imagePanel.BackgroundOverColor = Color.FromArgb(102,154,204);
    m_imagePanel.HLinesColor = Color.FromArgb(182,189,210);
    m_imagePanel.VLinesColor = Color.FromArgb(182,189,210);
    m_imagePanel.BorderColor = Color.FromArgb(0,0,0);
    m_imagePanel.EnableDragDrop = true;
    m_imagePanel.Init(imageList,12,12,6,(int)value);

    // add listner for event

    m_imagePanel.ItemClick += new ImageListPanelEventHandler(OnItemClicked);

    // set m_selectedIndex to -1 in case

    // the dropdown is closed without selection

    m_selectedIndex = -1;
    // show the popup as a drop-down

    wfes.DropDownControl(m_imagePanel);

    // return the selection (or the original value if none selected)

    return (m_selectedIndex != -1) ? m_selectedIndex : (int) value ;
}

Finally, we need to override PaintValue to paint our own value.

public override void PaintValue(System.Drawing.Design.PaintValueEventArgs pe)
{
    int imageIndex = -1 ;
    // value is the image index

    if(pe.Value != null) 
    {
        try 
        {
            imageIndex = (int)Convert.ToUInt16( pe.Value.ToString() ) ;
        }
        catch
        {
        }
    }
    // no instance, or the instance represents an undefined image

    if((pe.Context.Instance == null) || (imageIndex < 0))
        return ;
    // get the image set

    ImageList imageList = GetImageList(pe.Context.Instance) ;
    // make sure everything is valid

    if((imageList == null) || (imageList.Images.Count == 0) 
              || (imageIndex >= imageList.Images.Count))
        return ;
    // Draw the preview image

    pe.Graphics.DrawImage(imageList.Images[imageIndex],pe.Bounds);
}

When the custom type editor is done, all we need to do is add the Editor attribute to the properties that should use it.

[TypeConverter(typeof(ImageTypeConverter))]
[Editor(typeof(MozBar.ImageMapEditor),typeof(System.Drawing.Design.UITypeEditor))]
[Description("Image for normal state.")]        
public int Normal
{
    get
    {
        return m_imageIndex;
    }
    set
    {
        if (value != m_imageIndex)
        {
            m_imageIndex = value;
            if (m_item.ImageChanged!=null)
              m_item.ImageChanged(this, 
                 new ImageChangedEventArgs(itemState.Normal));
            m_item.Invalidate();
        }
    }
}

Theme support

MozBar implements basic theme support. If Theme is enabled and visual themes are supported by the application, it will use colors from the currently active theme for its select and focus state.

LunaSilverOlive

Implementing theme support basically involves four steps:

To find out if the system supports themes, we need to check which version of ComCtl32.dll is in use. This is done by using its DllGetVersion function. This will return true if visual styles are enabled either by using a manifest or Application.EnableVisualStyles(). It will return false if visual themes have been disabled for the application.

// Setup struct and function call


[StructLayout(LayoutKind.Sequential)]
public struct DLLVERSIONINFO
{
    public int cbSize;
    public int dwMajorVersion;
    public int dwMinorVersion;
    public int dwBuildNumber;
    public int dwPlatformID;
}

[DllImport("Comctl32.dll", EntryPoint="DllGetVersion", ExactSpelling=true,
PreserveSig=false, CharSet=CharSet.Unicode)]
private static extern int DllGetVersion(ref DLLVERSIONINFO s);

public bool _IsAppThemed()
{
    try
    {
        // Check which version of ComCtl32 thats in use..

        DLLVERSIONINFO version = new DLLVERSIONINFO();
        version.cbSize = Marshal.SizeOf(typeof(DLLVERSIONINFO));
        
        int ret = DllGetVersion(ref version);
        // If MajorVersion > 5 themes are allowed.

        if (version.dwMajorVersion >= 6)
            return true;
        else
            return false;
    }
    catch (Exception)
    {
        return false;
    }
}

Almost all theme related functionality is found in the uxTheme.dll. This is an unmanaged DLL and since Microsoft does not supply any managed wrapper, we need to use DllImport to call the functions we are interested in. The uxTheme API and the constants needed to use it are described in the two header files UxTheme.h and TmSchema.h which are available in the Microsoft Platform SDK, or if you have VS2003 or VS2005 they should also be available in the ..\VC\PlatformSDK\Include directory. These are the functions used by MozBar:

[DllImport("uxTheme.dll", EntryPoint="GetThemeColor", ExactSpelling=true,
PreserveSig=false, CharSet=CharSet.Unicode )]
private extern static void GetThemeColor (System.IntPtr hTheme,
    int partID,
    int stateID,
    int propID,
    out int color);

[DllImport( "uxtheme.dll", CharSet=CharSet.Unicode )]
private static extern IntPtr OpenThemeData( IntPtr hwnd, string classes );

[DllImport( "uxtheme.dll", EntryPoint="CloseThemeData", ExactSpelling=true,
 PreserveSig=false, CharSet=CharSet.Unicode) ]
private static extern int CloseThemeData( IntPtr hwnd );

To intercept the WM_THEMECHANGED event, we must override WndProc and check the message.

protected override void WndProc(ref Message m)
{
    base.WndProc (ref m);
    switch (m.Msg)
    {
        case WM_THEMECHANGED:
        {
            // Theme has changed , get new colors if Theme = true

            if (Theme)
                GetThemeColors();
            break;
        }
    }
}

OK, so now we have our functions, we know when the theme has changed and if visual themes are supported. The only thing left to do is to get the theme related info we want and possibly adjust it to fit our needs.

private void GetThemeColors()
{
    int EPB_HEADERBACKGROUND = 1;
    int EPB_NORMALGROUPBACKGROUND = 5;
        
    int TMT_GRADIENTCOLOR1 = 3810;
    int TMT_GRADIENTCOLOR2 = 3811;

    Color selectColor = new Color(); 
    Color focusColor = new Color();
    Color borderColor = new Color();
    bool useSystemColors = false;

    // Check if themes are available

    if (m_themeManager._IsAppThemed())
    {
        if (m_theme!=IntPtr.Zero)
          m_themeManager._CloseThemeData(m_theme); 

        // Open themes for "ExplorerBar"

        m_theme = m_themeManager._OpenThemeData(this.Handle,"EXPLORERBAR");  
        if (m_theme!=IntPtr.Zero)
        {
            // Get Theme colors..

            selectColor = m_themeManager._GetThemeColor(m_theme, 
                          EPB_HEADERBACKGROUND,1,TMT_GRADIENTCOLOR2);
            focusColor = m_themeManager._GetThemeColor(m_theme,
                         EPB_NORMALGROUPBACKGROUND,1,TMT_GRADIENTCOLOR1);
            borderColor = ControlPaint.Light(selectColor);
            selectColor = ControlPaint.LightLight(selectColor);
            focusColor = ControlPaint.LightLight(selectColor);
        }
    }

    // apply colors..

    ItemColors.SelectedBorder = selectColor;
    ItemColors.Divider = borderColor;
    this.BorderColor = borderColor;
     
    ItemColors.SelectedBackground = selectColor;
    ItemColors.FocusBackground = focusColor;
    ItemColors.FocusBorder = selectColor;

    Invalidate();

}

Known problems/issues

History

Conclusion

I hope this control can be of use to you. I'm sure there is plenty of room for improvements and added functionality, so if you have any ideas or suggestions please post a comment.

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
Generalweird bug
cinamon
20:09 25 Dec '07  
Hi the control seems great, but I am experiencing weird bugs, I have a 6 images in an imagelist and they are assigned to the panel at design time, it looks all fine at first, then in the IDE designer, as soon as I double click an MozItem and write some code (VB) in the 'click' handler the IMAGE of this item has changed to another image in the imagelist, clearing the imagelist property of the panel and reattaching it fixes the desginer but the running application pulls wrong images now...something is wrong, will experiment further
anyone able to recreate this problem ?
GeneralRe: weird bug
shawn32
14:00 27 May '08  
I have noticed this as well. Has anyone else noticed this?
GeneralRe: weird bug
shawn32
4:42 28 May '08  
This resolved the issue for me....

Go into the properties for the MozPanel and remove your imagelist form the ImageList property. Then re-add it. This may have been caused by the way I added this control to my project. I simply set a reference and copied the populated control from another project.


-Shawn
GeneralRe: weird bug
MrWolfy
11:04 28 Jun '08  
Hi All!

Yes, by my exprience this bug is caused by setting a MozItem's Image directly, via the properties of the MozItem itself, rather than through the mozPane's Items(Collection) list.
Try to stick to only setting MozItem's Images through their parent panel, rather than through the properties of the actual MozItem and everything should be fine.

Hope this Helps! Wink

MrWolfy
QuestionCompact Framework
vital.cruvinel
5:54 31 Jul '07  
Is there any version in .NET Compact Framework?
GeneralRemoving the border
gimmedacode
14:52 27 Apr '07  
Hi there, great control. I've been working on my own control, and haven't been able to remove the border for the image that's drawn in the PaintValue function. (You have an image in the article where the preview in the grid control (the soccer ball) has a black border around it)

Any ideas on how to remove the border?

Thanks
John
NewsBorder Draw Problem - Solution [modified]
Julian Ott
10:37 14 Oct '06  
Hi, i probably have a solution for your border
draw issue:

i manipulate the createparams, so it has a border.
this border is now black. to override it,
interrupt the NC_PAINT message. Code goes like this:

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace TestCS
{
/// /// Summary description for BorderControl.
/// summary
public class BorderControl:Control
{
public BorderControl()
{
//
// TODO: Add constructor logic here
//
}
protected override CreateParams CreateParams
{
get
{
CreateParams cp=base.CreateParams;
cp.Style|=0x800000;
return cp;
}
}
protected override void WndProc(ref Message m)
{
if (m.Msg==WM_NCPAINT)
{
IntPtr hdc=GetWindowDC(m.HWnd);
if(hdc==IntPtr.Zero) return;
Graphics gr=Graphics.FromHdc(hdc);
gr.DrawRectangle(Pens.Red,0,0,this.Width-1,this.Height-1);
gr.Dispose();
ReleaseDC(m.HWnd,hdc);
m.Result=IntPtr.Zero;
}
else
base.WndProc (ref m);
}

[DllImport("user32.dll")]
public static extern IntPtr GetWindowDC (IntPtr hwnd);
[DllImport("user32.dll")]
public static extern int ReleaseDC (IntPtr hwnd, IntPtr hdc);
public const int WM_NCPAINT = 0x85;
}
}

hope this could help
regards, julian
Generalnice control
picazo
12:19 11 Apr '06  
Any chance you have a c++ version?

-----------------
Genaro
Generalhow to make mozPanel not select any item?
nonotoday
17:12 15 Feb '06  
how to make mozPanel not select any item? or select a specific item?
i want to know how to set it using some codes.
GeneralSome suggestions
deecke
5:25 9 Jan '06  
Good work. Just yesterday I created a (simpler) control like that.
My idea was to create a control with the same functionality, but
the styles should be more flexible.
Some suggestions:

ItemHeight
----------
The height of the items should not depend on the contents.
E.g. I would like to have items without images (ItemStyle=Text) with
an height of 100. It should be possible to set an arbitrary height for
all items, with or without image.

TextAlign
---------
There should be an additional alignment "center". Assume the image
of on item is not set while other items found their images and the TextAlign
is set to Bottom... that looks not very nice. It would be better to align
the text in the center of the item (which has - of course - the same height
like the other ones).

ImageList
---------
Why the dependency on an imagelist? I would like to set the images directly.
Often the use of an imagelist is just overhead.

Ok, enough. If you're interested in, I have some more ideas.

None the less, good control, I stopped to work on mine.
GeneralRe: Some suggestions... Sorry!
deecke
15:09 9 Jan '06  
ImageList...
Sorry, there's no dependency on the ImageList (as I found out).
It's possible to set the images directly.
Next time I should test better before sending suggestions.

GeneralRe: Some suggestions
Patrik Bohman
1:53 17 Jan '06  
Thanks for the suggestions , I'm just about to go over this control again to add vs2005 support so any ideas are welcome.
GeneralRe: Some suggestions
bugmenot123
13:34 7 Feb '06  
As of right now is it possible to use this control with VS2005, or do I need to wait for you to release a VS2005 version?

Thanks,
KC
GeneralRe: Some suggestions
Patrik Bohman
10:03 8 Feb '06  
You will need to recompile for vs2005.A few changes might be necessary but it should work, a vs2005 version should be up shortly though.
GeneralVersion 1.5.1 is up.
Patrik Bohman
10:59 29 Sep '05  
small bug fix , see history for changes.
GeneralVersion 1.5 is up
Patrik Bohman
3:38 19 Aug '05  
Se history for changes.
Generalbig bug
Unruled Boy
17:49 15 Aug '05  
an imagelit, added some 16x16 icons, apply to a mozbar,

then, change imagelist'size from 16x16 to 32x32, and added a 32*32 icon, then change a mozitem's normal image with this newly added 32*32 icon.

no effect!

btw. in design time, it will stretch(enlarge) the 16x16 icons.

Regards,
unruledboy@hotmail.com
GeneralRe: big bug
Patrik Bohman
10:19 16 Aug '05  
Dont know if its big but there seems to be a problem when shifting imagelists,   making the following change to MozPane.Imagelist property
should fix it :

public ImageList ImageList
{
   get
   {
      .
      .
      .
   }
   set
   {
         .
         .
         .
         for (int i=0; i<this.Items.Count; i++)
         {
           // reset all images
           this.Items[i].Images.NormalImage = null;
            this.Items[i].Images.FocusImage = null;
           this.Items[i].Images.SelectedImage = null;
         }
         .
         .
         .
   }
}

You can not have images with different size in an imagelist , so stretching smaller images is normal behavior when increasing the size.
Generalwhere is the sample code?
Unruled Boy
17:02 15 Aug '05  
I did not find the sample codeD'Oh!

Regards,
unruledboy@hotmail.com
GeneralRe: where is the sample code?
Patrik Bohman
10:52 16 Aug '05  
There is not much to it , just the MozBar and a propertygrid.

Generallicense?
Unruled Boy
17:01 15 Aug '05  
I would like to use this code in my shareware, what is the license?


Regards,
unruledboy@hotmail.com
GeneralRe: license?
Patrik Bohman
11:02 16 Aug '05  
As with most of the stuff on CodeProject its free to use , take a look at the top of each source file for details.
GeneralMozItem on Toolbox
yoeru
21:38 13 Jul '05  
Additional edits on MozItem class, line number 57:

[ToolboxBitmap(typeof(MozPane),"Pabo.MozBar.MozPane.bmp")] public class MozItem : System.Windows.Forms.Control

[ToolboxBitmap(typeof(MozItem),"Pabo.MozBar.MozItem.bmp")] public class MozItem : System.Windows.Forms.Control

So far the control is doing great! Thanks.
GeneralImageMapEditor class
yoeru
19:49 13 Jul '05  
A small edit on line 143 of ImageMapEditor class:

public void OnItemClicked(object sender, ImageListPanelEventArgs e) {
m_selectedIndex = ((ImageListPanelEventArgs) e).SelectedItem;

//remove listner
m_imagePanel.ItemClick += new ImageListPanelEventHandler(OnItemClicked);
// close the drop-dwon, we are done
wfes.CloseDropDown() ;

m_imagePanel.Dispose() ;
m_imagePanel = null ;
}

The bold code as the comment says "remove listener" must be changed to "-=" instead.

public void OnItemClicked(object sender, ImageListPanelEventArgs e) {
m_selectedIndex = ((ImageListPanelEventArgs) e).SelectedItem;

//remove listner
m_imagePanel.ItemClick -= new ImageListPanelEventHandler(OnItemClicked);
// close the drop-dwon, we are done
wfes.CloseDropDown() ;

m_imagePanel.Dispose() ;
m_imagePanel = null ;
}

cheers!

GeneralRe: ImageMapEditor class
Patrik Bohman
21:14 13 Jul '05  
correct , a copy and paste error.


Last Updated 29 Sep 2005 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010