I have a stock winform datetimepicker that looks something like this...
I would like to make it look something like this...
The WinForm TextBox has a borderless option and I manually created a horizontal rule to give the illusion of a seamless underlined TextBox but the DateTimePicker doesn't seem to have a borderless option.
Is there something I can do to either make the DateTimePicker look like the example above or at least remove the borders so I can manually place the underline?
To achieve the custom look for the control, you have to override the WndProc method, which is the method that processes all the window messages for this control.
protected override void WndProc(ref Message m)
{
IntPtr hDC = GetWindowDC(m.HWnd);
Graphics gdc = Graphics.FromHdc(hDC);
switch (m.Msg)
{
case WM_NC_PAINT:
SendMessage(this.Handle, WM_ERASEBKGND, hDC, 0);
SendPrintClientMsg();
SendMessage(this.Handle, WM_PAINT, IntPtr.Zero, 0);
OverrideControlBorder(gdc);
m.Result = (IntPtr)1; // indicate msg has been processed
break;
case WM_PAINT: base.WndProc(ref m);
OverrideControlBorder(gdc);
OverrideDropDown(gdc);
break;
case WM_NC_HITTEST:
base.WndProc(ref m);
if (DroppedDown)
this.Invalidate(this.ClientRectangle, false);
break;
default:
base.WndProc(ref m);
break;
}
ReleaseDC(m.HWnd, hDC);
gdc.Dispose();
}
This is as close as I can get it:
You will have to make an image for the drop down button.
public class SexyDateTimePicker : DateTimePicker
{
public SexyDateTimePicker() : base()
{
this.SetStyle(ControlStyles.UserPaint, true);
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.DrawLine(Pens.Black, 0, this.ClientSize.Height -1, this.ClientSize.Width, this.ClientSize.Height -1);
e.Graphics.DrawString(this.Text, this.Font, new SolidBrush(Color.Black), 0, 0);
e.Graphics.DrawImage(Properties.Resources.DateOrTimePicker_675, new Point(this.ClientRectangle.X + this.ClientRectangle.Width - 16, this.ClientRectangle.Y));
}
}
The answer with the least amount of code would be to place a panel, place the control in the panel and then "clip" the border of the dateTimePicker (DTP) by reducing the size of the panel.
Related
Since a little bit i tried to add a grip to a window to resize it. I follow an example and it works fine for resizing. But my window does paint properly, it seems like it does not clear before redrawing or does not redraw the whole client area.
Here is my code:
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case (int)WinApi.Messages.WM_NCHITTEST:
WinApi.HitTest ht = HitTestNCA(m.HWnd, m.WParam, m.LParam);
if (ht != WinApi.HitTest.HTCLIENT)
{
// ht == HTBOTTOMRIGHT
m.Result = (IntPtr)ht;
return;
}
break;
}
base.WndProc(ref m);
}
the result is here: screenshot
My problem is simple, I can't drag a window/form from picturebox or panel that is similar to custom toolbar/border.
Basicly you can drag only from background of the form, but not from any control.
Hope you understand my problem. If needed I can make video or pictures.
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case 0x84://Can move window if borders are off.
base.WndProc(ref m);
if ((int)m.Result == 0x1)
m.Result = (IntPtr)0x2;
return;
case 0x00A3: m.Result = IntPtr.Zero; return; //Double click won't zoom in.
}
base.WndProc(ref m);
}
I'm trying to draw borders around words and paragraphs in RichTextBox but when I turn on UserPaint it doesn't draw text anymore while my custom painting seems to work. May be I just forgot to turn on something else? Here is what I have
public partial class RichTextBoxEx : RichTextBox
{
public RichTextBoxEx()
{
InitializeComponent();
SetStyle(ControlStyles.UserPaint, true);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
//Do some painting here
}
}
Using info from this question didn't help me
This worked ok for me:
class RichBox : RichTextBox {
private const int WM_PAINT = 15;
protected override void WndProc(ref Message m) {
if (m.Msg == WM_PAINT) {
this.Invalidate();
base.WndProc(ref m);
using (Graphics g = Graphics.FromHwnd(this.Handle)) {
g.DrawLine(Pens.Red, Point.Empty,
new Point(this.ClientSize.Width - 1,
this.ClientSize.Height - 1));
}
} else {
base.WndProc(ref m);
}
}
}
The events in rich textbox are a pain in the back since they don't fire the way you think they should fire. Here's a post where someone posted the minimum required code to have a new control that exposes the proper paint events for you by hosting a rich textbox and intercepting the windows paint requests. It is in VB.Net but should be easy to translate it for your use.
I have a simple windows form with no border and several label controls (nothing that needs to be clicked). I needed to be able to allow the user to move the form by clicking anywhere on it, so I found this question, and used the following code found there.
private const int WM_NCHITTEST = 0x84;
private const int HTCLIENT = 0x1;
private const int HTCAPTION = 0x2;
protected override void WndProc(ref Message m)
{
switch (m.Msg) {
case WM_NCHITTEST:
base.WndProc(ref m);
if ((int)m.Result == HTCLIENT) {
m.Result = (IntPtr)HTCAPTION;
return;
} else {
return;
}
break;
}
base.WndProc(ref m);
}
This works well...to a point. If I click anywhere on the form itself (the background), WM_NCHITTEST is HTCLIENT, so I can move my form as expected. However, if I click on a label control itself, the message is something different, and I can't tell what it is.
I found this article about the various possible values for WM_NCHITTEST but none of them seem to be what I need.
I realize I could disable all my label controls and that would allow me to click "on" them as if it was the form itself, but I'm wondering if there's a better/different way to do this.
Thanks for the help!
You are overriding the WndProc for the form, but when the cursor is over a label the WM_NCHITTEST message is sent to the label.
You could create your own label control derived from Label and override its WndProc. This should always return HTTRANSPARENT in response to WM_NCHITTEST. Something like:
private const int HTTRANSPARENT = -1;
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_NCHITTEST:
m.Result = (IntPtr)HTTRANSPARENT;
return;
}
base.WndProc(ref m);
}
Also note that there's a small bug in your WndProc. If the message is WM_NCHITTEST but the region isn't HTCLIENT then you call the base class twice.
Is it possible to create a MouseEnter-Event also for the border of the window? I mean also for the minimize and maximize-buttons. Because if I set the Event for my Form1, it works only when i'm inside the Form, but not on the border and the Buttons.
You can override WndProc in you form and you can detect mousemove
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
// mouse in window or in Border and max, close & min buttons
if (m.Msg == 0xa0 || m.Msg == 0x200)
{
//Do some thing
}
}