Quantcast
Channel: Brutal Developer - Windows Forms
Viewing all articles
Browse latest Browse all 2

Show calendar on click DateTimePicker control

$
0
0

Something that’s common-place on the web is clicking a text box to pop-up a calendar. What if you wanted the calendar to pop-up when simply clicking on any area of a System.Windows.Forms.DateTimePicker control? You would expect the control to have a method to easily do this but when you notice there isn't even a public Click event things start looking bleak...

I found a way to get this to work by sending a "mouse button down/up" message to the control in the area where the regular display button is. By forcing this extra click in the right area it's as if you just clicked the button yourself. So I made an extension method with some parts borrowed which add an additional method on the System.Windows.Forms.DateTimePicker control.

We want to make a click happen here (in the red box):

datetimepicker

So we can use some native calls as well as basic math to find a good position to click it and send the message like so:

using System;using System.Runtime.InteropServices;using System.Windows.Forms;namespace Brutal.Dev.Extenstions
{publicstaticclass DateTimePickerExtensions
  {#if NETCF
    [DllImport("coredll")]#else
    [DllImport("user32")]#endifstaticexternint SendMessage(IntPtr hWnd, uint uMsg,int wParam, int lParam);privateconstint WM_LBUTTONDOWN = 0x0201;privateconstint WM_LBUTTONUP = 0x0202;publicstaticvoid ShowCalendar(this DateTimePicker picker,
                                    MouseEventArgs clickEvent)
    {if (picker != null)
      {// Remove any existing event to prevent an infinite loop.
        var suppressor = new EventSuppressor(picker);
        suppressor.Suppress();// Get the position on the button.int x = picker.Width - 10;int y = picker.Height / 2;int lParam = x + y * 0x00010000;// Ignore if the calendar button was clickedif (clickEvent.X < picker.Width - 35)
        {
          SendMessage(picker.Handle, WM_LBUTTONDOWN, 1, lParam);
          SendMessage(picker.Handle, WM_LBUTTONUP, 1, lParam);
        }

        suppressor.Resume();
      }
    }
  }
}

Explanation

If you are using the .NET Compact Framework you need to import coredll instead for the P/Invoke for SendMessage so the compiler directive is there to support that.

The extra mouse click event info requirement is so that we can detect where the click happened and ignore it if it was actually on the calendar button (because otherwise it clicks again hiding the calendar – DOH!).

The EventSuppressor is something I picked up on this discussion to stop any other events from firing and also prevent infinite loops calling your mouse events over and over (the code for this in included in the sample code).

If you attach to the MouseDown or MouseUp event you can easily add one line to call the extension on you control and just like that, your calendar will pop-up:

using Brutal.Dev.Extenstions;privatevoid dateTimePicker1_MouseDown(object sender, MouseEventArgs e)
{    
  dateTimePicker1.ShowCalendar(e);
}

If you're a VB.NET kind of person, you can easily convert this code into VB.NET using this online tool which I’ve tried and it works pretty well.





Viewing all articles
Browse latest Browse all 2

Latest Images

Trending Articles





Latest Images