Lutz Roeder’s .NET Reflector

Bundan 3 yıl kadar once Xenocode’dan Kenji Obata benle irtibata geçip o zamanlar henüz daha Beta aşamasında olan Fox’u satın almak istediğinde çok bocalamıştım. Acaba Fox’u satsam mı? Yoksa open source yapıp kodlarını mı dağıtsam? Yada hiç bir sey yapmayıp aynen devam edip Fox’u tekbaşıma geliştirme devam mı etsem?

O zamanlar Lutz Roederle de bu konuyu konuşmuştuk, o Fox gibi bir decompile aracının Open Source olmasını çok mantıklı bulmuyordu. Hatta bu tarz tool ların mümkünse kodlarının yayılmamasından yanaydı. Her neyse o zamanlar şartlar beni Fox’u Xenocode’a satmaya mecbur bıraktı diyebilirim. Bu satış sonrasında Fox’un iki yeni sürümünü Xenocode için yazdıktan sonra Fox’un geldiği yeri görünce sattığıma pişman bile olmuştum. Hiç beklemediğim kadar gelişmişti Fox ve keşke satmasaydım demiştim.
More...

How to permit multiple selections for Enum properties?

PropertyGrid will use default editor for the properties which’s type is enum. This default editor does not allow multiple selections even the Enum has Flags attribute.
I have been prepared a new Editor for this kind of properties. You can download the source codes from here

Download Source Codes


Our editor’s code is as follows;
internal class FlagsEditor : UITypeEditor
{
       FlagsEditorControl editor = null;

       public FlagsEditor()
       { }

       // our editor is a DropDown editor
       public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
       {
             return UITypeEditorEditStyle.DropDown;
       }

       public override object EditValue(ITypeDescriptorContext context, 
                                        IServiceProvider provider, object value)
       {
             // if value is not an enum than we can not edit it
             if (!(value is Enum))
                    throw new Exception("Value doesn't support");

             // try to figure out that is this a Flags enum or not ?
             Type enumType = value.GetType();
             object[] attributes = enumType.GetCustomAttributes(typeof(FlagsAttribute), true);
             if (attributes.Length == 0)
                    throw new Exception("Editing enum hasn;t got Flags attribute");

             // check the underlying type
             Type type = Enum.GetUnderlyingType(value.GetType());
             if (type != typeof(byte) && type != typeof(sbyte)
                    && type != typeof(short) && type != typeof(ushort)
                    && type != typeof(int)&& type != typeof(uint))
                    return value;

             if (provider != null)
             {
                    // use windows forms editor service to show drop down
                    IWindowsFormsEditorService edSvc = provider.GetService(
                                    typeof(IWindowsFormsEditorService))
                                  as IWindowsFormsEditorService;
                    if (edSvc == null)
                           return value;
                    if (editor == null)
                           editor = new FlagsEditorControl(this);
                    // prepare list
                    editor.Begin(edSvc, value);
                    // show drop down now
                    edSvc.DropDownControl(editor);
                    // now we take the result
                    value = editor.Value;
                    // reset editor
                    editor.End();
             }
             return Convert.ChangeType(value, type);
       }

}


In this code FlagsEditorControl is a UserControl which PropertyGrid hosts it in a drop down during the edit operation.
You can change your design by changing this Control.

To use this editor for a property, we have to write Editor Attribute to that property as the below;
// set editor of this property to our FlagsEditor
[Editor(typeof(FlagsEditor), typeof(UITypeEditor))]
public FileAttributes FlagsAttribute
{
       get { return _FlagsAttribute; }
       set { _FlagsAttribute = value; }
}

What is the problem of .NET with the EnableWindow?

EnableWindow function enables or disables the mouse and keyboard input to the specified control. You can use this function from user32.dll as the follows;

[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern bool EnableWindow(HandleRef hWnd, bool enable);

[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern bool EnableWindow(IntPtr hWnd, bool enable);


But .NET Framework’s Control class, it is the base class to create a custom control in .NET, manages its Enable property a little bit different from the unmanaged Controls and Windows. Normally we can understand a control’s enable status from its Window Styles. If it contains WS_DISABLED flag this means that the given control is disabled otherwise it is enabled. But .NET Framework’s Control class does not use this WS_DISABLED flag. Instead it uses its own mechanism to understand that it is Enabled or not? So when we use EnableWindow function on a .NET Control it just enables the window and set its flags. But .NET still uses its own state flag which we can only change it by using Enabled property of that class. So .NET Framework Control still things that it is not enabled.
Therefore it is painted as disabled and does not accept mouse inputs. Actually default window procedure of this control started to accept mouse messages but again Control class’s own mechanism checks that is this control Enabled property before processing the mouse message.
Although Control which is enabled by EnableWindow function does not accept mouse messages, it begins to accept keyboard messages. Because there is no limitation in .NET Control class for the keyboard messages like mouse messages.

Here is the .NET's codes;
private void WmMouseDown(ref Message m, MouseButtons button, int clicks)
{
       MouseButtons buttons1 = Control.MouseButtons;
       SetState(0x8000000, true);
       if (!GetStyle(ControlStyles.UserMouse))
       {
             DefWndProc(ref m);
       }
       else
       {
             if ((button == MouseButtons.Left) && GetStyle(ControlStyles.Selectable))
             {
                    FocusInternal();
             }
       }
       if (buttons1 == Control.MouseButtons)
       {
             if (!GetState2(0x10))
             {
                    CaptureInternal = true;
             }
             // Here checks Enabled property to process mouse events
             if ((buttons1 == Control.MouseButtons) && Enabled)
             {
                    OnMouseDown(new MouseEventArgs(button, clicks, NativeMethods.Util.SignedLOWORD(m.LParam), NativeMethods.Util.SignedHIWORD(m.LParam), 0));
             }
       }
}

public bool Enabled
{
       get
       {
             // uses 3rd bit of the state flag to indicate the Enabled value
             if (!GetState(4))
             {
                    return false;
             }
             if (ParentInternal == null)
             {
                    return true;
             }
             return ParentInternal.Enabled;
       }
       set
       {
             bool value = Enabled;
             // sets the 3rd bit of the state flag
             SetState(4, value);
             if (value != value)
             {
                    if (!value)
                    {
                           SelectNextIfFocused();
                    }
                    OnEnabledChanged(EventArgs.Empty);
             }
       }
}

internal bool GetState(int flag)
{
       // state is a field
       return (state & flag) != 0;

}

Code extracted by Xenocode Fox .NET Decompiler

Something about CollectionEditor

Today I wrote a simple example which shows how we can use CollectionEditor of the .NET. In addition to this I also made a simple example which shows how to implement custom CollectionEditor which allows us to add more than one item to the collection.

Download Example Sources

Download Example

public class ExampleComponent : Component{
       ArrayListCollection _ArrayListItems = new ArrayListCollection();
       List<Button> _ListItems = new List<Button>();
       List<Control> _MultipleItems = new List<Control>();

 
      public ExampleComponent()
       { }

       [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
       [Description("Contains only Control objects in an ArrayList")]
       [Category("Behaviour")]
       public ArrayListCollection ArrayListItems
       {
             get { return _ArrayListItems; }
       }

       [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
       [Description("Contains only Button objects in a List<Button> collection")]
       [Category("Behaviour")]
       public List<Button> ListItems
       {
             get { return _ListItems; }
       }

       // custom editor attribute
       [Editor(typeof(CustomCollectionEditor), typeof(UITypeEditor))]
       [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
       [Description("Contains ListView, Button and CheckBox items in a List<Control> collection")]
       [Category("Behaviour")]
       public List<Control> MultipleItems
       {
             get { return _MultipleItems; }
       }

       public class ArrayListCollection : ArrayList
       {
             // CollectionEditor searches collection type's Index property and finds its property type.
             // It uses this type to add new items
             public new Control this[int index]
             {
                    get { return base[index] as Control; }
             }
       }

       // Custom collection editor.
       // by using this editor we can add ListView, Button and
       // CheckBoxes to the same collection
       public class CustomCollectionEditor : CollectionEditor
       {
             public CustomCollectionEditor()
                    : base(typeof(List<Control>))
             {}

             // override this method if you have to do custom initializing
             // operations. For example, if you have to use a constructor which
             // takes arguments you can create your own items here ...
             // or may be you have to do some initializing operations ...
             protected override object CreateInstance(Type itemType)
             {
                    if (itemType == typeof(CheckBox))
                    {
                           CheckBox checkbox = new CheckBox();
                           checkbox.Text = "My Text, hede";
                           return checkbox;
                    }
                    Control control = base.CreateInstance(itemType) as Control;
                    control.Text = "Other, hede";
                    return control;
             }

             // if you want to use a custom collection editor form,
             // you have to override this method and return your form here
             protected override CollectionEditor.CollectionForm CreateCollectionForm()
             {
                    return base.CreateCollectionForm();
             }

             // here you can return a text which will be appeared in the list
             // for the given item
             protected override string GetDisplayText(object value)
             {
                    Control control = value as Control;
                    return string.Format("{0} - {1}", control.GetType().Name, control.Text);
             }

             // we allow 3 types can be added to our collection
             protected override Type[] CreateNewItemTypes()
             {
                    return new Type[] { typeof(ListView), typeof(Button), typeof(CheckBox) };
             }
       }

}


Xenocode Postbuild is the powerful, reliable, and easy-to-use code protection and deployment solution for .NET developers.

Search

Calendar

<<  August 2008  >>
MonTueWedThuFriSatSun
28293031123
45678910
11121314151617
18192021222324
25262728293031
1234567
View posts in large calendar

Disclaimer

© 2007 - 2008
Ozcan DEGIRMENCI
All rights reserved. The content can be used elsewhere given that the source is properly acknowledged.