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);
}
Related
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.
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
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
}
}
I saw the code posted on this forum for moving the WinForm without borders but my dialog (C#) has a panel covering the whole area. I know I have to use WndProc to do this. I don't know what to do at this point. My window doesn't move unless I expose some of it by shrinking the size of the panel. Thank you.
The code I have:
protected override void WndPro(ref Message m)
{
switch(m.Msg)
{
case 0x84:m.Result = new intPtr(0x2);
return
}
base.wndProc(ref m);
}
You'll need to give the panel the same kind of treatment, except that you return HTTRANSPARENT. That makes it transparent to hit tests and the form will get the message. Now it works. Add a class to your project and paste the code shown below. Compile. Replace your existing panel with this one.
using System;
using System.Windows.Forms;
class BackPanel : Panel {
protected override void WndProc(ref Message m) {
if (m.Msg == 0x84) m.Result = (IntPtr)(-1);
else base.WndProc(ref m);
}
}