Custom title bar drawing

V

valerie.tching

Hello,

I'm trying to make a skinned application, so i'm overriding the paint
methods of the controls.
Concerning the painting of the form itself, it seems that there are 2
options:
- Making the form borderless (FormBorderStyle to None), and building
our own custom window title bar, but just think that this needs some
useless work as we have to rewrite some window functions (move, resize,
....). Moreover, when maximizing the window, it makes it fullscreen.
- This lead me to the second option which was to use the non client
area painting by catching the WM_NCPAINT message in the WndProc method.
With the help of some Win32 functions, i paint on the form
(FormBorderStyle to Sizable) but something weird happens, the system
buttons on the title bar redraw themselves, for example, when i move
the mouse over the window. So they appear on the custom painting...

Does someone have an idea of what happens with the
maximize/minimize/close buttons and/or have a workaround for the second
option ? Cannot find which message makes the buttons to be repainted.
Or is the first option the best solution to make a skinned application
?

Thanks for your help!

Valerie
 
M

Mick Doherty

The approach you take all depends upon exactly how custom you want to go.

If you want a standard layout, with a custom appearance then I would suggest
that you go for the WM_NCPAINT method. The article at the following link is
as good as any I've seen, although from what I remember there were a few
minor problems that need sorting, but then they may have been sorted since I
last looked.
http://www.geekswithblogs.net/kobush/articles/CustomBorderForms.aspx

I believe that the WM_NCHITTEST messages may be the ones you're missing
which cause the Caption buttons to repaint.



If however, you would like a completely custom appearance, with Caption
buttons and Menu's in non standard layout, then IMO you should go with the
borderless form option.

I experimenting with this myself at the moment, and have a few different
approaches which I am trying. Once I have decided upon the best approach I
will be putting an example on my site to either replace or complement the
current 'Moveable/Resizable shaped form' example so that you can resize a
form by dragging the edges, aswell as have a Fake MenuBar which acts just
like the real thing.

I currently have a couple of unfinished and untidied examples (VB.net only
at the moment) which I could send you if you'd like to take a look before I
upload the winner.
 
F

Frank Hileman

Hi Valerie,

The first option has always been the best one for us. It does require some
more work; we added an enum property called WindowOperation in our visual
Element class for this purpose, that specifies the window operation
performed when mouse events occur on an object.

Regards,
Frank Hileman

check out VG.net: http://www.vgdotnet.com
Animated vector graphics system
Integrated Visual Studio graphics editor
 
S

Stoitcho Goutsev \(100\)

Valerie,

Moving anf resizing of borldless form shouldn't be a big problem. All you
need to do is to handle WM_NCHITTEST message and return correct value based
on the cursor position. Windows will take care of the rest. With the full
screen window you can solve this by restricting the size of the maximized
window hadling the WM_GETMINAMAXINFO.

There are two recuirements for a window to go full screen:
1. To be maximized
2. The client rectangle to be big enough to cover the entire screen. Pay
attention on the requirement that the CLIENT RECT has to be that big.
That means the caption and the WindowsForm's menu and status bar have to be
off the screen. However, if you use third party menu and status bar controls
they are usually implemented as normal controls hosted in the form's client
area and they can be visible.

Here is the code that takes care of this problem :

struct MINMAXINFO
{
public Point ptReserved;
public Size ptMaxSize;
public Point ptMaxPosition;
public Size ptMinTrackSize;
public Size ptMaxTrackSize;
}

const int WM_GETMINMAXINFO = 0x0024;

protected override void WndProc(ref Message m)
{
if (m.Msg == WM_GETMINMAXINFO)
{
MINMAXINFO mmi = (MINMAXINFO)Marshal.PtrToStructure(m.LParam,
typeof(MINMAXINFO));
mmi.ptMaxSize = Screen.GetWorkingArea(this).Size;

Marshal.StructureToPtr(mmi, m.LParam, false);
m.Result = IntPtr.Zero;
return;
}


base.WndProc(ref m);
}
 
V

valerie.tching

Mick said:
The approach you take all depends upon exactly how custom you want to go.

If you want a standard layout, with a custom appearance then I would suggest
that you go for the WM_NCPAINT method. The article at the following link is
as good as any I've seen, although from what I remember there were a few
minor problems that need sorting, but then they may have been sorted since I
last looked.
http://www.geekswithblogs.net/kobush/articles/CustomBorderForms.aspx

I believe that the WM_NCHITTEST messages may be the ones you're missing
which cause the Caption buttons to repaint.



If however, you would like a completely custom appearance, with Caption
buttons and Menu's in non standard layout, then IMO you should go with the
borderless form option.

I experimenting with this myself at the moment, and have a few different
approaches which I am trying. Once I have decided upon the best approach I
will be putting an example on my site to either replace or complement the
current 'Moveable/Resizable shaped form' example so that you can resize a
form by dragging the edges, aswell as have a Fake MenuBar which acts just
like the real thing.

I currently have a couple of unfinished and untidied examples (VB.net only
at the moment) which I could send you if you'd like to take a look before I
upload the winner.

Thanks for the help!

I decided to adopt the borderless option as it give more options for
the skinning.
Thanks also for your article, i found it when i was looking for a
solution to get back the system menu when right-clicking in the
taskbar, and moreover, i didn't know how to make custom shaped windows,
so very useful article :)

Concerning the problem of the title bar system buttons, catching the
WM_NCHITTEST did indeed remove the problem.
Thanks also for the Custom Border Forms link!
 
V

valerie.tching

Thanks for the code, it worked as a charm!
Valerie,

Moving anf resizing of borldless form shouldn't be a big problem. All you
need to do is to handle WM_NCHITTEST message and return correct value based
on the cursor position. Windows will take care of the rest. With the full
screen window you can solve this by restricting the size of the maximized
window hadling the WM_GETMINAMAXINFO.

There are two recuirements for a window to go full screen:
1. To be maximized
2. The client rectangle to be big enough to cover the entire screen. Pay
attention on the requirement that the CLIENT RECT has to be that big.
That means the caption and the WindowsForm's menu and status bar have to be
off the screen. However, if you use third party menu and status bar controls
they are usually implemented as normal controls hosted in the form's client
area and they can be visible.

Here is the code that takes care of this problem :

struct MINMAXINFO
{
public Point ptReserved;
public Size ptMaxSize;
public Point ptMaxPosition;
public Size ptMinTrackSize;
public Size ptMaxTrackSize;
}

const int WM_GETMINMAXINFO = 0x0024;

protected override void WndProc(ref Message m)
{
if (m.Msg == WM_GETMINMAXINFO)
{
MINMAXINFO mmi = (MINMAXINFO)Marshal.PtrToStructure(m.LParam,
typeof(MINMAXINFO));
mmi.ptMaxSize = Screen.GetWorkingArea(this).Size;

Marshal.StructureToPtr(mmi, m.LParam, false);
m.Result = IntPtr.Zero;
return;
}


base.WndProc(ref m);
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top