[Contents] [Prev] [Next]

Step 3: Writing in the window

In Step 3, you'll begin working with the new window that was added to the application in Step 2. Instead of popping up a message box when the mouse buttons are pressed, the event-handling functions will get some real functionality-pressing the left mouse button will cause the coordinates of the point at which the button was clicked to be printed in the window, and pressing the right mouse button will cause the window to be cleared. You can find the source for Step 3 in the file STEP03.CPP in the directory EXAMPLES\OWL\TUTORIAL.

The code for this new functionality is in the EvLButtonDown function. The TPoint parameter that's passed to the EvLButtonDown contains the coordinates at which the mouse button was clicked. You'll need to add a char string to the function to hold the text representation of the point. You can then use the wsprintf function to format the string. Now you have to set up the window to print the string.

Constructing a device context

To perform any sort of graphical operation in Windows, you must have a device context for the window or area you want to work with. The same holds true in ObjectWindows. ObjectWindows provides a number of classes that make it easy to set up, use, and dispose of a device context. Because TDrawWindow works as a client in a frame window, you'll use the TClientDC class. TClientDC is a device context class that provides access to the client area owned by a window. Like all ObjectWindows device context classes, TClientDC is based on the TDC class, and is defined in the owl\dc.h header file.

TClientDC has a single constructor that takes an HWND as its only parameter. Because you want a device context for your TDrawWindow object, you need the handle for that window. As it happens, the TWindow base class provides an HWND conversion operator. This operator is called implicitly whenever you use the window object in places that require an HWND. So the constructor for your TClientDC object looks something like this:

TClientDC  dc(*this);
Notice that the this pointer is dereferenced. The HWND conversion operator doesn't work with pointers to window objects.

Printing in the device context

Once the device context is set up, you have to actually print the string. The TDC class provides several versions of the TextOut function. Just like the MessageBox function in Step 2, the TextOut functions contained in the device context classes looks similar to the Windows API function TextOut. The first version of TextOut looks exactly the same as the Windows API version, except that the first HDC parameter is omitted:

virtual  bool  TextOut(int  x,  int  y,  const  char  far*  str,
          int  count=-1);
The HDC parameter is filled by the TDC object. The second version of TextOut omits the HDC parameter and combines the x- and y-coordinates into a single TPoint structure:

bool  TextOut(const  TPoint&  p,  const  char  far*  str,
          int  count=-1);
Because the coordinates are passed into the EvLButtonDown function in a TPoint object, you can use the second version of TextOut to print the coordinates in the window. Your completed EvLButtonDown function should look something like this:

void  TDrawWindow::EvLButtonDown(uint,  TPoint&  point)
    char  s[16];
    TClientDC  dc(*this);

    wsprintf(s,  "(%d,%d)",  point.x,  point.y);
    dc.TextOut(point,  s,  strlen(s));
You need to include the string.h header file to use the strlen function.

Clearing the window

TDrawWindow's base class, TWindow, provides three different invalidation functions. Two of these, InvalidateRect and InvalidateRgn, look and function much like their Windows API versions, but omitting the HWND parameters. The third function, Invalidate, invalidates the entire client area of the window. Invalidate takes a single parameter, a bool indicating whether the invalid area should be erased when it's updated. By default, this parameter is true.

Therefore, to erase the entire client area of TDrawWindow, you need only call Invalidate, either specifying true or nothing at all for its parameter. To clear the screen when the user presses the right mouse button, you must make this call in the EvRButtonDown function. The function would look something like this:

void  TDrawWindow::EvRButtonDown(uint,  TPoint&)

Where to find more information

Here's a guide to where you can find more information on the topics introduced in this step:

[Contents] [Prev] [Next]