Geometry In DialogBox

Skip to first unread message

Bruce M Carroll

Nov 18, 1993, 3:37:17 AM11/18/93
I am trying to generate a template background for a DialogBox.
The problem is that this template requires that I draw geometric
objects in the DialogBox window.

When is the proper time to draw this stuff?

I have tried placing some sample code in response to the WM_INITDIALOG,
WM_ACTIVATE, WM_SHOWWINDOW and WM_CTLCOLOR messages. I can't get any of them
to work correctly. However, it seems that if I place some sample code before
the switch(mMsg), then it does print the stuff. I suppose because every
message sent to the DLGPROC sees the code, some message must arrive after the
window has been shown that allows it to plot. This doesn't seem like good
style to me, however I can't find any alternatives.

Is there some message that is sent after the window is shown that I could
key on? I thought at one time that I could draw to a hidden window (then
I could use the WM_SHOWWINDOW), but I have tried and have had no success.

Could I define my own message somehow to accomplish this?

John Grant

Nov 18, 1993, 4:33:06 PM11/18/93

Before I begin, let me say that this a FAQ, but that nobody
has really explained it very well. Most people seem to
forget the basics of Windows message sequences and the
nature and importance of WM_PAINT, that is (hopefully)
learned in Chapter 1 of a book like 'Petzold'. It would
be a good idea to review the use of WM_PAINT which is so
fundamental to Windows. If you don't understand it then you
will be just guessing at messages to process.

How the Dialog Box is Painted
First you must understand how Windows and the dialog manager
work. The following test will help you to visualize it. In
your DlgProc(), put the following:
case WM_PAINT: Sleep(2000);

You will see that the dialog box is drawn (frame and surface)
and then WM_PAINT is sent to your DlgProc(). There is a 2 s
delay and when you return, all of the buttons are drawn on the
surface of the dialog box. (the Sleep() function is my own,
implemented using a GetTickCount() loop).

So now you know the painting order:
1. the dialog manager draws the dialog surface
2. the dialog manager sends you a WM_PAINT message
3. the dialog manager draws the buttons on the dialog box

So if you want to draw on the dialog box, you do it as usual
at the WM_PAINT message.


You Must tell the Dialog Manager What you have Done!
When you return from WM_PAINT, your picture will just be painted
over by the dialog manager when it draws the buttons and other
controls, because it does not know that you have drawn anything.
So you must tell it that you have drawn something on the surface
of the dialog box. There are 2 ways to do this:

(a) force Windows to draw the controls *FIRST* before you draw
your picture on top of the control:
case WM_PAINT: hwnd=GetDlgItem(hdlg,ID_MYPICTURE);
UpdateWindow(hwnd); //do it NOW
...draw your picture on ID_MYPICTURE...
When you return, the dialog manager doesn't bother drawing
the ID_MYPICTURE control because it did it already, i.e.
the region has been 'validated' by the WM_PAINT message
you sent it with UpdateWindow().

(b) draw your picture and *PREVENT* Windows from drawing
any controls on top of it when you return:
case WM_PAINT: hwnd=GetDlgItem(hdlg,ID_MYPICTURE);
...draw your picture on ID_MYPICTURE...
As above, the dialog manager doesn't bother drawing the
ID_MYPICTURE control because it has been removed from the
'invalid' region that still requires painting by the
ValidateRect() function.

Method (a) is the preferred method for most situations. I have
included method (b) for comparison and completeness.

Which Method to Use?
Your choice may depend on the nature of the static control in
which you are drawing and/or whether you are using CTL3D.DLL.
If you are completely obliterating the static control by drawing
on top of the entire control, then either method (a) or (b) is
fine. However, if you are using the control as a frame and you
draw your picture slightly smaller inside the control, then you
should use method (a) so that it draws the control first and then
you put the picture inside. If you use method (b), the control
will never be drawn at all.

If you use CTL3D.DLL, you can get some very nice effects by
using combinations of SS_WHITEFRAME, SS_BLACKFRAME etc to
draw a 3d frame around your picture. For this you should use
method (a) and force the controls to be drawn. Then you
draw your picture inside the frame.

You draw your picture on the static control by using GetDC()
to get an HDC and then using the usual GDI functions, including

Now you know.
John A. Grant
Airborne Geophysics
Geological Survey of Canada, Ottawa

David Brabant

Nov 19, 1993, 2:05:49 AM11/19/93

Just use WM_PAINT.


| David Brabant, | E-MAIL : |
| Siemens Nixdorf, | Phone : +32 41 201 609 |
| Centre Software de Liege, | FAX : +32 41 201 642 |
| 2, rue des Fories, +----------------------------------+
| 4020 Liege, Belgium. | #include "disclaim.hpp" |

Reply all
Reply to author
0 new messages