|
I forgot to remove the following function before posting the VB version.
Protected Overrides Function IsInputKey(ByVal keyData As System.Windows.Forms.Keys) As Boolean
If keyData = (Keys.Tab Or Keys.Shift) Then
Return True
ElseIf keyData = Keys.Tab Then
Return True
Else
Return MyBase.IsInputKey(keyData)
End If
End Function
This was added because I needed special Tab key handling. You should remove this function if you want the default Tab key behaviour.
Malcolm Powell
|
|
|
|
|
Good work. That's exactly what I needed. Of course my thanks go also to Fadrian!
|
|
|
|
|
This is a work in progress, but can be used as it stands right now. This is an ExtendedDateTimePicker class which inherits from Windows.Systems.Forms.DateTimePicker and so can be used as a direct replacement.
**This control does not behave correctly as far as drawing in design mode, so if you can assist in that area it would be greatly appreciated....
#region ExtendedDateTimePicker<br />
public class ExtendedDateTimePicker : System.Windows.Forms.DateTimePicker<br />
{<br />
#region Enums<br />
public enum FLATSTYLE_STYLES<br />
{<br />
None = 0,<br />
Popup = 1,<br />
Standard = 2,<br />
System = 3<br />
}<br />
#endregion<br />
<br />
#region Property Variables<br />
public FLATSTYLE_STYLES _flatStyle = FLATSTYLE_STYLES.Standard;<br />
#endregion<br />
<br />
#region Properties<br />
[Browsable(true)]<br />
[EditorBrowsable(EditorBrowsableState.Always)]<br />
[Category("Appearance")]<br />
[Description("Determines the display of the control.")]<br />
public FLATSTYLE_STYLES FlatStyle<br />
{<br />
get { return _flatStyle; }<br />
set <br />
{ <br />
_flatStyle = value;<br />
if (_flatStyle == FLATSTYLE_STYLES.Popup)<br />
{<br />
_dropButton = new DropDownButton(this);<br />
_dropButton.Width = _buttonWidth + 2;<br />
_dropButton.Height = this.Height - 2;<br />
_dropButton.Top = 0;<br />
this.Controls.Add(_dropButton);<br />
if (this.RightToLeft == RightToLeft.No || !this.RightToLeftLayout)<br />
_dropButton.Left = this.Width - (_buttonWidth + 2);<br />
}<br />
else<br />
{<br />
_dropButton = null;<br />
}<br />
this.Invalidate(); }<br />
}<br />
#endregion<br />
<br />
private System.ComponentModel.Container components = null;<br />
<br />
#region Member variables<br />
protected int _buttonWidth = 17;<br />
protected DropDownButton _dropButton = null;<br />
protected bool _dropped = false;<br />
#endregion<br />
<br />
#region Contructors<br />
public ExtendedDateTimePicker()<br />
{<br />
InitializeComponent();<br />
<br />
_buttonWidth = GetComboDropDownWidth();<br />
}<br />
<br />
protected override void Dispose(bool disposing)<br />
{<br />
if (disposing)<br />
{<br />
if (components != null)<br />
components.Dispose();<br />
}<br />
base.Dispose(disposing);<br />
}<br />
#endregion<br />
<br />
#region Designer Generated code<br />
private void InitializeComponent()<br />
{<br />
components = new System.ComponentModel.Container();<br />
}<br />
#endregion<br />
<br />
#region Overridden Control Functions<br />
protected override void OnMouseEnter(EventArgs e)<br />
{<br />
base.OnMouseEnter(e);<br />
<br />
if (_flatStyle == FLATSTYLE_STYLES.Popup)<br />
{<br />
Win32.SendMessage(this.Handle, Win32.WM_NCPAINT, (IntPtr)1, 0);<br />
_dropButton.Invalidate();<br />
}<br />
}<br />
<br />
protected override void OnMouseLeave(EventArgs e)<br />
{<br />
base.OnMouseLeave(e);<br />
<br />
if (_flatStyle == FLATSTYLE_STYLES.Popup)<br />
{<br />
Win32.SendMessage(this.Handle, Win32.WM_NCPAINT, (IntPtr)1, 0);<br />
_dropButton.Invalidate();<br />
}<br />
}<br />
<br />
protected override void OnGotFocus(EventArgs e)<br />
{<br />
base.OnGotFocus(e);<br />
<br />
if (_flatStyle == FLATSTYLE_STYLES.Popup)<br />
{<br />
Win32.SendMessage(this.Handle, Win32.WM_NCPAINT, (IntPtr)1, 0);<br />
_dropButton.Invalidate();<br />
}<br />
}<br />
<br />
protected override void OnLostFocus(EventArgs e)<br />
{<br />
base.OnLostFocus(e);<br />
<br />
if (_flatStyle == FLATSTYLE_STYLES.Popup)<br />
{<br />
Win32.SendMessage(this.Handle, Win32.WM_NCPAINT, (IntPtr)1, 0);<br />
_dropButton.Invalidate();<br />
}<br />
}<br />
<br />
protected override void OnResize(EventArgs e)<br />
{<br />
base.OnResize(e);<br />
<br />
if (_flatStyle == FLATSTYLE_STYLES.Popup)<br />
{<br />
if (this.RightToLeft == RightToLeft.No || !this.RightToLeftLayout)<br />
_dropButton.Left = this.Width - (_buttonWidth + 2);<br />
<br />
Win32.SendMessage(this.Handle, Win32.WM_NCPAINT, (IntPtr)1, 0);<br />
}<br />
}<br />
<br />
protected override void WndProc(ref Message m)<br />
{<br />
IntPtr hDC = IntPtr.Zero;<br />
Graphics gDC = null;<br />
<br />
<br />
if (_flatStyle == FLATSTYLE_STYLES.Popup)<br />
{<br />
switch (m.Msg)<br />
{<br />
case Win32.WM_NCCALCSIZE:<br />
if (m.WParam == IntPtr.Zero)<br />
{<br />
Win32.NCCALCSIZE_PARAMS csp;<br />
<br />
csp = (Win32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam,<br />
typeof(Win32.NCCALCSIZE_PARAMS));<br />
<br />
csp.rgrc0.Top += 1;<br />
csp.rgrc0.Bottom -= 1;<br />
csp.rgrc0.Left += 1;<br />
csp.rgrc0.Right -= 1;<br />
<br />
Marshal.StructureToPtr(csp, m.LParam, false);<br />
}<br />
else if (m.WParam == new IntPtr(1))<br />
{<br />
Win32.NCCALCSIZE_PARAMS csp;<br />
<br />
csp = (Win32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam,<br />
typeof(Win32.NCCALCSIZE_PARAMS));<br />
<br />
csp.rgrc0.Top += 1;<br />
csp.rgrc0.Bottom -= 1;<br />
csp.rgrc0.Left += 1;<br />
csp.rgrc0.Right -= 1;<br />
Marshal.StructureToPtr(csp, m.LParam, false);<br />
}<br />
break;<br />
case Win32.WM_NCPAINT:<br />
hDC = Win32.GetWindowDC(m.HWnd);<br />
gDC = Graphics.FromHdc(hDC);<br />
Win32.SendMessage(m.HWnd, Win32.WM_ERASEBKGND, hDC, 0);<br />
OverrideControlBorder(gDC);<br />
m.Result = (IntPtr)0;
Win32.ReleaseDC(m.HWnd, hDC);<br />
gDC.Dispose();<br />
break;<br />
default:<br />
base.WndProc(ref m);<br />
break;<br />
}<br />
}<br />
else<br />
{<br />
base.WndProc(ref m);<br />
}<br />
}<br />
#endregion<br />
<br />
#region Utility Functions<br />
[Browsable(false)]<br />
private bool IsMouseInControl<br />
{<br />
get<br />
{<br />
if (this.DesignMode)<br />
{<br />
return false;<br />
}<br />
<br />
Point mPos = Control.MousePosition;<br />
bool retVal = this.ClientRectangle.Contains(this.PointToClient(mPos));<br />
return retVal;<br />
}<br />
}<br />
<br />
private void OverrideControlBorder(Graphics g)<br />
{<br />
bool allowHot = (this.Enabled && !this.DesignMode) && !(this.IsMouseInControl && Control.MouseButtons == MouseButtons.Left && !this.ContainsFocus);<br />
bool hot = (this.ContainsFocus || this.IsMouseInControl) && allowHot;<br />
Pen border = null;<br />
<br />
Rectangle rect = new Rectangle(0, 0,<br />
this.ClientRectangle.Width + 1, this.ClientRectangle.Height + 1);<br />
<br />
if (allowHot && hot)<br />
{<br />
border = new Pen(SystemColors.GrayText, 1);<br />
}<br />
else<br />
{<br />
border = new Pen(Color.White, 1);<br />
}<br />
<br />
g.DrawRectangle(border, rect);<br />
border.Dispose();<br />
}<br />
<br />
private void OverrideDropDown(Graphics g)<br />
{<br />
bool allowHot = (this.Enabled && !this.DesignMode) && !(this.IsMouseInControl && Control.MouseButtons == MouseButtons.Left && !this.ContainsFocus);<br />
bool hot = (this.ContainsFocus || this.IsMouseInControl) && allowHot;<br />
Pen border = null;<br />
Brush button = new SolidBrush(SystemColors.Control);<br />
<br />
border = (allowHot && hot) ? new Pen(SystemColors.GrayText, 1) : new Pen(Color.White, 1);<br />
<br />
if (!this.ShowUpDown)<br />
{<br />
Rectangle rect = new Rectangle(this.Width - _buttonWidth + 1, 0, _buttonWidth - 1, this.Height - 1);<br />
g.DrawRectangle(border, rect);<br />
rect.Inflate(-1, -1);<br />
rect.Height += 1;<br />
g.FillRectangle(button, rect);<br />
}<br />
else<br />
{<br />
Rectangle rect = new Rectangle(this.Width - _buttonWidth + 1, 0, _buttonWidth - 1, this.Height - 1);<br />
g.DrawRectangle(border, rect);<br />
rect.Inflate(-1, -1);<br />
rect.Height += 1;<br />
g.FillRectangle(button, rect); <br />
}<br />
border.Dispose();<br />
button.Dispose();<br />
}<br />
<br />
protected int GetComboDropDownWidth()<br />
{<br />
ComboBox cbo = new ComboBox();<br />
Win32.COMBOBOXINFO cbi = new Win32.COMBOBOXINFO();<br />
cbi.cbSize = Marshal.SizeOf(cbi);<br />
Win32.GetComboBoxInfo(cbo.Handle, ref cbi);<br />
cbo.Dispose();<br />
return cbi.rcButton.Right - cbi.rcButton.Left;<br />
}<br />
#endregion<br />
<br />
#region DropDownButton Private Class<br />
protected class DropDownButton : System.Windows.Forms.Button<br />
{<br />
#region Windows API<br />
[DllImport("user32")]<br />
protected static extern IntPtr GetWindowDC(IntPtr hWnd);<br />
<br />
[DllImport("user32")]<br />
protected static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);<br />
#endregion<br />
<br />
private System.ComponentModel.Container components = null;<br />
<br />
#region Member Variables<br />
private ExtendedDateTimePicker _owner = null;<br />
#endregion<br />
<br />
#region Constructor<br />
public DropDownButton(<br />
ExtendedDateTimePicker owner)<br />
{<br />
InitializeComponent();<br />
<br />
this._owner = owner;<br />
this.SetStyle(ControlStyles.UserPaint, true);<br />
this.SetStyle(ControlStyles.Selectable, false);<br />
this.FlatStyle = FlatStyle.Popup;<br />
}<br />
<br />
protected override void Dispose(bool disposing)<br />
{<br />
if (disposing)<br />
{<br />
if (components != null)<br />
components.Dispose();<br />
}<br />
base.Dispose(disposing);<br />
}<br />
#endregion<br />
<br />
#region Designer Generated code<br />
private void InitializeComponent()<br />
{<br />
components = new System.ComponentModel.Container();<br />
}<br />
#endregion<br />
<br />
#region Overrides<br />
protected override void OnPaint(PaintEventArgs e)<br />
{<br />
DrawControlBorder(e.Graphics);<br />
DrawButton(e.Graphics);<br />
DrawGlyph(e.Graphics);<br />
}<br />
<br />
protected override void OnMouseEnter(EventArgs e)<br />
{<br />
base.OnMouseEnter(e);<br />
<br />
Win32.SendMessage(_owner.Handle, Win32.WM_NCPAINT, (IntPtr)1, 0);<br />
}<br />
<br />
protected override void OnMouseLeave(EventArgs e)<br />
{<br />
base.OnMouseLeave(e);<br />
<br />
Win32.SendMessage(_owner.Handle, Win32.WM_MOUSELEAVE, IntPtr.Zero, 0);<br />
}<br />
<br />
protected override void OnMouseDown(MouseEventArgs mevent)<br />
{<br />
base.OnMouseDown(mevent);<br />
<br />
if (mevent.Button == MouseButtons.Left)<br />
{<br />
int x = _owner.Width - 10;<br />
int y = _owner.Height / 2;<br />
int lParam = x + y * 0x00010000;<br />
Win32.SendMessage(_owner.Handle, Win32.WM_LBUTTONDOWN, (IntPtr)1, lParam);<br />
}<br />
}<br />
#endregion<br />
<br />
#region Drawing Functions<br />
protected virtual void DrawControlBorder(Graphics g)<br />
{<br />
<br />
bool allowHot = (this.Enabled && !this.DesignMode) &&<br />
!(this.IsMouseInControl && this.ContainsFocus && _owner.ContainsFocus);<br />
bool hot = (this.ContainsFocus || this.IsMouseInControl || _owner.ContainsFocus) && allowHot;<br />
<br />
Rectangle rect = new Rectangle(0, 0,<br />
this.ClientRectangle.Width - 1, this.ClientRectangle.Height - 1);<br />
<br />
Pen border = (hot) ? new Pen(SystemColors.GrayText, 1) : new Pen(Color.White, 1);<br />
<br />
RightToLeft rtl = _owner.RightToLeft;<br />
bool rtll = _owner.RightToLeftLayout;<br />
<br />
Point leftTop = new Point(rect.Left, rect.Top);<br />
Point leftBottom = new Point(rect.Left, rect.Bottom);<br />
Point topLeft = new Point(rect.Left + 1, rect.Top);<br />
Point topRight = new Point(rect.Right - 1, rect.Top);<br />
Point rightTop = new Point(rect.Right, rect.Top);<br />
Point rightBottom = new Point(rect.Right, rect.Bottom);<br />
Point bottomLeft = new Point(rect.Left + 1, rect.Bottom);<br />
Point bottomRight = new Point(rect.Right - 1, rect.Bottom);<br />
<br />
Pen sides = new Pen(SystemColors.Control, 1);<br />
<br />
g.DrawLine((rtl == RightToLeft.Yes || rtll) ? sides : border, leftTop, leftBottom);<br />
g.DrawLine(sides, topLeft, topRight);<br />
g.DrawLine((rtl == RightToLeft.Yes || rtll) ? border : sides, rightTop, rightBottom);<br />
g.DrawLine(sides, bottomRight, bottomLeft);<br />
<br />
border.Dispose();<br />
sides.Dispose();<br />
}<br />
<br />
protected virtual void DrawButton(Graphics g)<br />
{<br />
bool allowHot = (this.Enabled && !this.DesignMode) &&<br />
!(this.IsMouseInControl && Control.MouseButtons == MouseButtons.Left<br />
&& !this.ContainsFocus);<br />
bool hot = (this.ContainsFocus || this.IsMouseInControl) && allowHot;<br />
<br />
Rectangle rect = new Rectangle(1, 1,<br />
this.ClientRectangle.Width - 2, this.ClientRectangle.Height - 2);<br />
<br />
Brush filler = (hot) ? new SolidBrush(SystemColors.Control) : <br />
new SolidBrush(SystemColors.Control);<br />
<br />
g.FillRectangle(filler, rect);<br />
filler.Dispose();<br />
}<br />
<br />
protected virtual void DrawGlyph(Graphics g)<br />
{<br />
RightToLeft rtl = _owner.RightToLeft;<br />
bool rtll = _owner.RightToLeftLayout;<br />
<br />
int xC = this.ClientRectangle.Left + ((this.ClientRectangle.Width / 2) - 1);<br />
int yC = this.ClientRectangle.Top + ((this.ClientRectangle.Height / 2) - 1);<br />
<br />
Pen pen = new Pen(SystemColors.ControlText, 1);<br />
<br />
g.DrawLine(pen, xC - 2, yC - 1, xC + 2, yC - 1);<br />
g.DrawLine(pen, xC - 1, yC, xC + 1, yC);<br />
g.DrawLine(pen, xC, yC - 1, xC, yC + 1);<br />
<br />
pen.Dispose();<br />
}<br />
#endregion<br />
<br />
#region Utilities<br />
[Browsable(false)]<br />
private bool IsMouseInControl<br />
{<br />
get<br />
{<br />
if (this.DesignMode)<br />
{<br />
return false;<br />
}<br />
<br />
Point mPos = Control.MousePosition;<br />
bool retVal = this.ClientRectangle.Contains(this.PointToClient(mPos)) ||<br />
_owner.ClientRectangle.Contains(_owner.PointToClient(mPos));<br />
return retVal;<br />
}<br />
}<br />
#endregion<br />
}<br />
#endregion<br />
}<br />
#endregion
ToDo:
1. Make it draw properly in designer
2. Support the blue highlighting with the blue button when mousing over like VS2005 comboboxes
3. Figure out the difference between System and Standard drawing styles in other controls to implement here
4. Implement None flatstyle
5. Make RightToLeft adjustments work correctly (something is screwy there with the button as it doesn't draw as expected);
How it works:
Since pre-Windows Vista, there was no way to retrieve the internal structure of the datetimepicker control, I simply created an internal class to create and draw a button as a child of the date time picker, and simple moved my button over the datetimepicker's button. The button is only created when the control's flatstyle is set to Popup at this time. All other styles simple are the default datetimepicker.
|
|
|
|
|
Hi,
Not sure if I can help, but if you send the complete source code to me, I will give it a try. At the moment it is missing the Win32 class for the above code to compile
Fadrian
|
|
|
|
|
Here is the Win32.cs file contents. It only consists of API information:
using System;<br />
using System.Collections.Generic;<br />
using System.Text;<br />
using System.Runtime.InteropServices;<br />
<br />
namespace ExtendedControls<br />
{<br />
internal class Win32<br />
{<br />
#region Windows Constants<br />
public const int WM_NCCALCSIZE = 131;<br />
public const int WM_NCHITTEST = 132;<br />
public const int WM_NCPAINT = 133;<br />
public const int WM_NCMOUSEMOVE = 160;<br />
<br />
public const int WM_SETFOCUS = 7;<br />
public const int WM_KILLFOCUS = 8;<br />
public const int WM_PAINT = 15;<br />
public const int WM_ERASEBKGND = 14;<br />
public const int WM_SETCURSOR = 32;<br />
public const int WM_MOUSEMOVE = 512;<br />
public const int WM_LBUTTONDOWN = 513;<br />
public const int WM_LBUTTONUP = 514;<br />
public const int WM_MOUSELEAVE = 675;<br />
public const int WM_PRINTCLIENT = 792;<br />
public const int CB_GETCOMBOBOXINFO = 356;<br />
<br />
public const int GWL_STYLE = -16;<br />
public const int GWL_EXSTYLE = -20;<br />
public const int ECM_FIRST = 0x1500;<br />
public const int EM_SETCUEBANNER = (ECM_FIRST + 1);<br />
#endregion<br />
<br />
#region Windows Structures<br />
#region RECT Structure<br />
[StructLayout(LayoutKind.Sequential)]<br />
public struct RECT<br />
{<br />
public int Left;<br />
public int Top;<br />
public int Right;<br />
public int Bottom;<br />
}<br />
#endregion<br />
<br />
#region NCCALCSIZE_PARAMS Structure<br />
[StructLayout(LayoutKind.Sequential)]<br />
public struct NCCALCSIZE_PARAMS<br />
{<br />
public RECT rgrc0, rgrc1, rgrc2;<br />
public IntPtr lppos;<br />
}<br />
#endregion<br />
<br />
#region COMBOBOXINFO Structure<br />
[StructLayout(LayoutKind.Sequential)]<br />
public struct COMBOBOXINFO<br />
{<br />
public int cbSize;<br />
public RECT rcItem;<br />
public RECT rcButton;<br />
public IntPtr stateButton;<br />
public IntPtr hwndCombo;<br />
public IntPtr hwndEdit;<br />
public IntPtr hwndList;<br />
}<br />
#endregion<br />
<br />
#region DATETIMEPICKERINFO Structure<br />
[StructLayout(LayoutKind.Sequential)]<br />
public struct DATETIMEPICKERINFO<br />
{<br />
public int cbSize;
public RECT rcCheck;
public int stateCheck;
public RECT rcButton;
public int stateButton;
public IntPtr hwndEdit;
public IntPtr hwndUD;
public IntPtr hwndDropDown;
}<br />
#endregion<br />
<br />
#endregion<br />
<br />
#region Constructor<br />
public Win32()<br />
{<br />
}<br />
#endregion<br />
<br />
#region Windows API<br />
[DllImport("user32", CharSet = CharSet.Auto)]<br />
public static extern int GetWindowLong(IntPtr hWnd, int index);<br />
<br />
[DllImport("user32", CharSet = CharSet.Auto)]<br />
public static extern int SetWindowLong(IntPtr hWnd, int index, int value);<br />
<br />
[DllImport("user32", CharSet = CharSet.Unicode)]<br />
public static extern bool SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, string lParam);<br />
<br />
[DllImport("user32", CharSet = CharSet.Auto)]<br />
public static extern bool SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, ref COMBOBOXINFO lParam);<br />
<br />
[DllImport("user32")]<br />
public static extern IntPtr GetWindowDC(IntPtr hWnd);<br />
<br />
[DllImport("user32")]<br />
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);<br />
<br />
[DllImport("user32", CharSet = CharSet.Auto)]<br />
public static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, int lParam);<br />
<br />
[DllImport("user32")]<br />
public static extern bool GetComboBoxInfo(IntPtr hwndCombo, ref COMBOBOXINFO info);<br />
#endregion<br />
<br />
#region Utility Functions<br />
public static int HiWord(int param)<br />
{<br />
if ((param & 0x80000000) == 0x80000000)<br />
return (param >> 16);<br />
else<br />
return (param >> 16) & 0xffff;<br />
}<br />
<br />
public static int LoWord(int param)<br />
{<br />
return param & 0xffff;<br />
}<br />
#endregion<br />
}<br />
}<br />
-- modified at 11:35 Monday 7th May, 2007
There is also a strange bug that I cannot seem to pinpoint. In Popup style, when you mouse out of the right hand side of the control slowly, the border on the button does not redraw. Or, if it does redraw, the code is coming up with a result that the mouse is still in the control. If you drag out at a normal or fast speed, then the button border draws correctly. It's only one the right hand side though.
|
|
|
|
|
Ok, to fix the popup in design mode issue, you just have to remove the drop down control in the else block of the FlatStyle property.
else
{
if (this.Controls.Contains(_dropButton))
this.Controls.Remove(_dropButton);
_dropButton = null;
}
To fix the mouse move issue, modify the DropDownButton class:
Add field: bool mouseEnter
Set the value to true in the MouseEnter event and false in the MouseLeave event.
Then, modify the statement in IsMouseInControl property to use that value
bool retVal = (mouseEnter && this.ClientRectangle.Contains(this.PointToClient(mPos))) ||
_owner.ClientRectangle.Contains(_owner.PointToClient(mPos));
Other comments:
- Instead of creating new Pen object everywhere and dispose it, try using the predefined pen
Pen border = (hot) ? SystemPens.HotTrack : Pens.White;
- You can use ControlPaint to draw the
ControlPaint.DrawComboButton(g, this.ClientRectangle, ButtonState.Flat);
- Instead of comparing your LParam or WParam with new IntPtr(value), you can cast it
if ((int) m.WParam == 1)
Hope the above comments help
Fadrian
|
|
|
|
|
Update on the flat DateTimePicker:
First off, thanks Fadrian for suggesting not creating my own pens. That's just me being stupid, so definitely cudos on that one.
Ok, the drawing in design mode is nearly working, just the button draws the border when you click on the control. Not sure why, but !this.designmode isn't making the bool statement false, and it should.
As far as the mouseleave issue, that was also my fault. I did have a function that checks if the mouse is in the control based on the pointtoclient, but my button was a few pixels too wide, and so even when the mouse was out of the control, it was technically still over the button. Fixed that problem by making the button the correct size. Not even sure why I was enlarging the button by 2 pixels...anyway
I tried using the ControlPaint.DrawComboButton function. Great little built in function, but does not work correctly in this situation. The function draws the flat button with the dark gray borders all the time (in this case, not desireable). Also, the glyph on the button does not match the combobox glyph when in Popup style. So I'm going to keep my drawing functions in there.
Also, at this time, I've added the 'None' style flat style. So basically, at this point, all the styles work the same as the combobox as I can't see a difference between Standard and System when it comes to these controls in particular.
If anyone is interested in the code and the dll file at this point, let me know and I'll put it up on my ftp server. Included in the source code is a textbox control with flatstyle and cuebanner support, and also combobox with cuebanner support.
|
|
|
|
|
Great to hear that it is almost working now.
It will be great if you can send me a copy of the complete source for future reference. Only if you don't mind I'm thinking that if there is further post on this, with the source code in hand I maybe be able to help answering.
My email fsudaman@gmail.com
Thanks,
FS
|
|
|
|
|
|
Is there a VB version?
Thanks
|
|
|
|
|
Sorry for the late response. I missed this post completely.
I dont have a VB.NET version but you can just take the code and compile it as a library and include that to your project. Check this post for more info.
http://www.codeproject.com/cs/combobox/ComboBox_appears_flat.asp?df=100&forumid=43335&fr=26&select=994303#xx994303xx
|
|
|
|
|
I just posted a VB version but made it a new thread with the same title by mistake. This message is just to trigger automatic email for this thread.
Malcolm Powell
|
|
|
|
|
Hello,
When I'm using FlatDateTimePicker class.
The problem is, that when a control containing it is going to be displayed, an PInvokeStackInbalanceException is raised
The debugger points to the line containing:
SendMessage(this.Handle, WM_ERASEBKGND, hDC, 0);
I don't know how to fix it or where to search for the source of the error...
Jacek Osiecki
Poland
|
|
|
|
|
Hi,
I think I know the problem you are having.
Similar issue was raised for my combobox control a while ago and it has been fixed.
Check out this article, and look at the "Support for .net 2005" message posting.
http://www.codeproject.com/cs/combobox/ComboBox_appears_flat.asp
The problem is caused by pinvoke signature.
Fadrian
|
|
|
|
|
Thanks, that's exactly what I was looking for!
I owe you one
Jacek
Poland
|
|
|
|
|
The flat DateTimePicker doesn't work properly with TransparencyKey set on a Form-owner of the control. 3-D background is showing on bottom and right edges. Do you have any idea how to fix that?
Alex
|
|
|
|
|
Hi Alex,
Been a while since I last work on this. I tried a few things before discovering the fix by trapping a calcsize message and handle it.
Declare
---------
const int WM_NCCALCSIZE = 0x83;
Add to the WndProc:
-------------------
case WM_NCCALCSIZE:
m.Result = (IntPtr) 1; // indicate msg has been processed
break;
I did some testing and seems to work well. I am not sure if there is any other implications, but maybe you can tell me. I'm no expert on this and ain't sure as in why this fixed the problem either. If anyone reading this knows the answer, please comments on this.
Fadrian
|
|
|
|
|
I tried, and find the control still does not have support for the time element
what's wrong?
|
|
|
|
|
This control support the time element just like the normal .NET DateTimePicker does.
If you want to display time, you will change the Format to Time. Or optionally change the format to CustomFormat and and set the CustomFormat string in the property box to display the time element as well.
|
|
|
|
|
I like flat things, so I like this too.
My problem is that the buttons on the popup aren't flat. I figure that to repaint part of the popup, you have to repaint everything, right?
May as well make a new control from scratch...
|
|
|
|
|
Hi,
You are right there, but I didn't intend to make the popup flat. I haven't tried, but I assume to make the calendar popup flat will require some efforts.
Rewriting the control may require a lot of effort as well, plus to support all the interface and designer features of DateTimePicker that is currently provided by the framework will take sometimes. There are several libraries out that provides custom DateTimePicker, but is not interface/function equivalent with the standard DateTimePicker. This contorl is meant to provide a simple migration path and keeping the option open to leverage future upgrade possibly in the .NET framework.
Fadrian
|
|
|
|
|
Very nice control, very simple, yet functional. I do have two questions though.
1. One is that I also implemented mouseenter/mouseleave event and I also get the same flickering issues as described in another thread in your combobox control.
2. Two is that I tried changing the backcolor property of the control (control itself, not the dropdown area of the calendar) and for some reason when I call base class I cannot see it. Documentation says it's possible to change the backcolor but yet I cannot. Any ideas why is that?
Thanks.
|
|
|
|
|
Refer to my answer for ComboBox for question 1.
As for the background, DateTimePicker doesn't seem to allow you to specify the background color of the actual contorl itself. You can test that quickly by dropping a .NET DateTimePicker control to your form. Since my control pretty much inherit everything else from the .NET control, the same limitations apply.
I tried some hacks and able to set the background in a very elegance way, however, changing the color affect the entire application. DateTimePicker control use Global Application Setting style, which I believe changing the color of one control will cause it to apply to all. Anyway, this is the code if you are interested.
[DllImport("user32.dll", EntryPoint="SetClassLongA")]
private static extern int SetClassLong(IntPtr hwnd, int nIndex, int dwNewLong);
[DllImport("gdi32.dll")]
private static extern int CreateSolidBrush (int crColor);
[DllImport("gdi32.dll")]
private static extern int DeleteObject (int hObject);
private int hBackgroundBrush = 0;
private const int GCL_HBRBACKGROUND = -10;
public override Color BackColor
{
get
{
return base.BackColor;
}
set
{
base.BackColor = value;
if (hBackgroundBrush != 0)
DeleteObject(hBackgroundBrush);
hBackgroundBrush = CreateSolidBrush(ColorTranslator.ToWin32(value));
SetClassLong(this.Handle, GCL_HBRBACKGROUND, hBackgroundBrush);
}
}
Oh also, you will need to clean up the memory object as well for the brush:
protected override void Dispose(bool disposing)
{
if (disposing)
DeleteObject(hBackgroundBrush);
base.Dispose (disposing);
}
|
|
|
|
|
Hi Fadrian
Hmm, I read about avoiding flickering, but when I tried to use your control, I experienced, that the combobutton is still flickering when the mouse is over, say when using the WM_NC_HITTEST event.
Is this normal (if so, how can we get rid of it??) or just an individual, personal problem?
Thnx, Duc
|
|
|
|
|
me again...
Would it not be more appropriate to just paint the combobutton ONCE when wm_nc_hittest gets in, instead of invalidating the whole control (which in fact is a never ending story, as long as the mouse cursor is left over the dropdown button)?
My suggestion:
Case WM_NC_HITTEST
MyBase.WndProc(m)
If DroppedDown Then
new:
OverrideDropDown(gdc)
instead of:
Me.Invalidate(Me.ClientRectangle, False)
End If
Could u comment on this?
Thnx, Duc
|
|
|
|
|