Windows GUI Programming: Subwindows
CS 321 Lecture,
Dr. Lawlor, 2006/04/24
Check out the Forger's Windows
Tutorial. Also see my example code (Directory,
Zip, Tar-gzip).
Try changing the "window class" in your call to
CreateWindow to "EDIT". The "EDIT" window class is prebuilt by Microsoft.
Microsoft calls these pre-registered window classes "controls", and
ships them in the DLL "comctl32.dll". Microsoft gives a short list of common "controls" in CreateWindow, or separately a big list of all the builtin "controls".
Unfortunately, documentation on exactly what controls exist, how to
create them, and what messages they accept seems to be scattered
through the Windows docs.
Window Styles
Several of the builtin controls take parameters at creation time.
These control things like whether the control includes scrollbars,
icons, etc.
The EDIT control supports a bunch of window styles. So we can create a scrolling multi-line edit child window with:
hEdit1 = CreateWindow("EDIT",
"Starter Text\nWith Newlines...",
WS_CHILD | WS_BORDER | WS_HSCROLL| WS_VSCROLL |
ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE ,
...);
Controlling Controls
After creating a window (such as a control), you can make it do stuff
by sending messages directly to its wndProc. For example, you can
select a range of text by passing the EM_SETSEL message:
// This selects characters 10 through 15.
SendMessage(hEdit1, EM_SETSEL, (WPARAM)10, (LPARAM)15);
There are lots of possible messages you might send to a window. See the control docs for details.
Control Size
In Windows, you specify the coordinates of any new window's top-left
corner (x,y), and the size of the new window (w,h). For a new
control, these coordinates are measured in the containing window.
One of the trickiest parts of GUI programming is keeping the various
components of a window in the right locations as the containing window
changes size and location. For example, moving a window causes
Windows to pass your wndProc the WM_WINDOWPOSCHANGING, WM_WINDOWPOSCHANGED, WM_MOVE, WM_SIZE, and WM_NCCALCSIZE
messages. You can hook into any of these messages in your
wndProc, and respond by shuffling your controls around to match the new
window size.
A typical call to move the "hEdit1" window to the bottom half of the enclosing window might look like this:
int x=0, y=200; // Start of edit window (top left corner)
RECT rc; GetClientRect(hWnd, &rc); // Outside window size
MoveWindow(hEdit1,x,y,rc.right-x,rc.bottom-y,true);
The coordinate calculations for complicated windows can get quite
ugly. This is where a more complicated toolkit (MFC, Qt, Windows
Forms, Cocoa, etc.) really shines.
Other Fun Examples
You should definitely try using a BUTTON control. It's really
simple. When clicked, it delivers a WM_COMMAND to the enclosing
window, with wParam equal to the HMENU used when creating the button.
A STATIC control is just some text. It's really simple.
Possibly the easiest way to make a bunch of child windows is to store
them in a DIALOG resource. You can then display the dialog and process
events for it with the "DialogBox" routine. See MYDIALOG_ABOUT in the example.
You can even embed Internet Explorer inside a window, although it's tough to do without ATL.
ATL is the "Advanced Template Library", another Microsoft C++
library. It's similar to, and competes with, their MFC or
"Microsoft Foundation Classes".