Tuesday, January 17, 2006

The DateTimePicker control in the .NetCF v2 doesn't implement DropDown and CloseUp events which could be really helpful whe dealing with the picker. It doesn't mean that these events or messages are not available in the native counterpart. Win CE SDK docs show the presence of the DTN_CLOSEUP and DTN_DROPDOWN notification messages. It means that they are sent by the DateTime picker to its parent. So, I pulled the NativeWindow class to whip up the DateTimePickerEntender class that suclasses the form, catches the messages and raises the events to the client:

public class DateTimePickerExtender : NativeWindow

{

        public event System.EventHandler CloseUp;

        public event System.EventHandler DropDown;

 

        private IntPtr handle;

 

        public DateTimePickerExtender(IntPtr handle)

        {

            this.handle = handle;

            // Subclass the window

            this.AssignHandle(handle);

        }

 

        protected override void WndProc(ref Message m)

        {

            // Check for notification messages

            if (m.Msg == WM_NOTIFY)

            {

                NMHDR nmhdr = new NMHDR();

                        Marshal.PtrToStructure(m.LParam, nmhdr);

                switch (nmhdr.code)

                {

                    case DTN_DROPDOWN:       

                        // Raise the event

                        if (DropDown != null)

                            DropDown(this, new EventArgs());

                        break;

                    case DTN_CLOSEUP:

                        // Raise the event

                        if (CloseUp != null)

                            CloseUp(this, new EventArgs());

                        break;

                }

            }

            base.WndProc(ref m);

        }

 

 

        #region P/Invoke declarations

 

        private const int WM_NOTIFY = 0x004E;

 

        private const int DTN_FIRST = -760;

        private const int DTN_DROPDOWN = (DTN_FIRST + 6);

        private const int DTN_CLOSEUP = (DTN_FIRST + 7);

 

        private class NMHDR

        {

            public IntPtr hwndFrom = IntPtr.Zero;

            public uint idFrom = 0;

            public int code = 0; //uint

        }

 

        #endregion

}

Drop the DateTimePicker controls on the form, create and instance of the DateTimePickerExtender and hook up into the events:

DateTimePickerExtender dtEntender;

 

public Form1()

{

     InitializeComponent();

     dtEntender = new DateTimePickerExtender(this.Handle);

     dtEntender.CloseUp += new EventHandler(dtEntender_CloseUp);

     dtEntender.DropDown += new EventHandler(dtEntender_DropDown);

}

 

void dtEntender_DropDown(object sender, EventArgs e)

{

     Console.WriteLine("DropDown event");

}

 

void dtEntender_CloseUp(object sender, EventArgs e)

{

     Console.WriteLine("CloseUp event");

}

 

1/17/2006 7:35:53 PM (GMT Standard Time, UTC+00:00)  #     | 
 Wednesday, June 01, 2005

Managed controls in the Compact Framework don't expose all available functionality of the native controls they wrap. And that is understandable since the CF team wanted to make them fast and small. For example, ComboBox control doesn't implement the DropDown event that could be quite helpfull to store a previouse value because it should fire before the SelectedIndexChanged event. So I've decided to implement this event using the NativeWindow class I blogged about the other day.

The Windows CE SDK documentation states that there's a CBN_DROPDOWN notification message that is send to the parent of the ComboBox when the listbox of a combo box is about to become visible. This message is sent in the form of WM_COMMAND.

A quick trip to the winuser.h file to pull out the values for the CBN_DROPDOWN and WM_COMMAND and here's the ComboSubclass class that catches this message and raises the DropDown event:

public class ComboSubclass : NativeWindow

{

    private const int WM_COMMAND = 0x111;

    private const int CBN_DROPDOWN   =  7;

 

    public event EventHandler DropDown;

 

    private ComboBox comboBox;

 

    public ComboSubclass(ComboBox comboBox, Control parent)

    {

        this.comboBox = comboBox;

        //Subclass parent form

        this.AssignHandle(parent.Handle);

    }

 

    protected override void WndProc(ref Message m)

    {

        if (m.Msg == WM_COMMAND)

        {

            // Make sure that's its our ComboBox

            if (m.LParam == comboBox.Handle)

            {

                if (DropDown != null)

                {

                    // Raise the event

                    DropDown(comboBox, null);

                }

            }

        }

        base.WndProc(ref m);

    }

}

The usage of this class should be pretty straightforward:

   comboSubclass = new ComboSubclass(comboBox1, this);

  comboSubclass.DropDown += new EventHandler(comboSubclass_DropDown);

           

 

  void comboSubclass_DropDown(object sender, EventArgs e)

  {

      prevIndex = ((ComboBox)sender).SelectedIndex;

  }

Update: You can achieve the same goal in the CF v1 by utilizing ApplicationEx class from SDF and WinProcFilter I posted last year.

6/1/2005 2:14:42 PM (GMT Daylight Time, UTC+01:00)  #     | 
 Monday, May 23, 2005

As you probably know, the CF team has added the capability to use managed delegates as a native callbacks in the CF v2. It means that it’s become quite possible to use API’s that require a callback function such as EnumFonts, EnumWindows etc… The same goes true for been able to use SetWindowLong to subclass window procedure. The full .NET Framework includes a very useful NativeWindow class that wraps window subclassing and creating new windows functionality in the very usable and convenient package. A few months ago, I’d created a .NET Compact Framework v2 implementation of the NativeWindow class with exactly the same functionality (AssignHandle, CreateHandle, WndProc etc...

 

So what can you do with this class? Subclass any control and catch the messages that are not exposed as events, create your own versions of the native controls (EDIT, LISTBOX, ListView etc…)

 

You should expect the NativeWindow to become a part of the Smart Device Framework for CF v2.

 

You can download the NativeWindow class and a test project from here:

NativeWindowTest.zip (62.02 KB)
5/23/2005 5:28:13 PM (GMT Daylight Time, UTC+01:00)  #     |