Yet Another Windows Library

Yet Another Windows Library (YAWL), is introduced in Chapter 8, in the section of the same name. I wrote YAWL to make my life as a GUI programmer easier, and it's designed just to do the basics. However, it illustrates the main features of class frameworks, and you will find this knowledge useful if you need to use a real application framework.

This tutorial is organized around the main classes of YAWL; all class names begin with T. TWin is the base class for all windows that appear on the screen (although you can make them invisible as well). TEventWindow is derived from TWin and is the base class for all application windows that need to respond to system events like mouse clicks and keystrokes; this is mostly done by overriding TEventWindow's virtual methods. TFrameWindow is derived from TEventWindow and is used as the base class for your main application window.

There is also a TDC, which encapsulates a Windows Device Context. This is used to access the Windows Graphics Device Interface (GDI) calls, for drawing lines and text, and so forth. A higher-level turtle graphics interface class TG can be used with TGFrameWindow.

Manipulating Windows: (TWin)

TWin encapsulates a window; there are auxilliary classes Rect and Point, which are used to specify screen areas and points.

class Rect {
public:
  int left,top,right,bottom;
  Rect() {  }
  Rect(int x0, int y0, int x1, int y1)
   {  left = x0; top = y0; right = x1;  bottom = y1; }
};
class Point {
public:
  int x,y;
  Point() {  }
  Point(int xp, int yp) {  x = xp; y = yp; }
};

class TWin {
. . .
public:
// Getting the size and position of the window
  void  get_rect(Rect &rt);           // gets _window_ rectangle
  void  get_client_rect(Rect &rt);    // gets _client_ rectangle
  int   width();
  int   height();
// Converting coordinates
  void  to_screen(Point& pt);
  void  to_client(Point& pt);
 // Resize and move the window
  void  resize(int x0, int y0, int w, int h);
  void  resize(int w, int h);
  void  move(int x0, int y0);

The window rectangle is the window's position, in screen coordinates. The client rectangle is the part of the window that is available for painting (that is, not including scrollbars, menus, caption bars, and so on). The client rectangle is indicated in client coordinates, which are measured from the top-left corner of the client area. Points can be converted between screen and client coordinates by using to_screen() and to_client(). width() and height() refer to the total size, including any nonclient parts such as scrollbars. If you want to find the width of the client area, you check the Rect value that is returned by get_client_rect(). resize() sets the full window size.

These two methods are used to force a repaint.

// Causing a repaint
  void  update();
  void  invalidate(Rect *lprt=NULL);

Normally, when part of a window is uncovered, that area becomes invalid and causes a paint event to happen, in order to refresh that area of the window (although often people repaint the whole window even if only a small part has changed). invalidate() forces a rectangular area to become invalid and thus ready to be repainted; without the lprt parameter, the whole client area of the window becomes invalid. Just because a window has invalid areas doesn't mean that it is immediately repainted; paint events wait in a queue for more important things (such as user input) to happen. update() is used to force an immediate repaint.

These methods set and get any text associated with the window. The section on user-defined conversions in Chapter 9 gives an example of these methods in use:

// Setting and getting the window text
  void  set_text(pchar str);
  pchar get_text(pchar str=obuff,int sz=BUFSIZE);

For ordinary top-level windows, the window text is the caption that appears in the top caption bar. For controls such as edit boxes, buttons, and labels, the window text is the text displayed in the controls. The get_text() method is used to retrieve the text typed in an edit control by a user.

At any point, there is only one active window that is waiting for user input. These functions allow you to access this window, make another window active, change the appearance of a window (for example, make it maximized or even hidden), and so forth:

static TWin *get_active_window();
int  get_id();
void set_focus();
void  show(int how = SW_SHOW);
bool  is_visible();

If you type TWin::get_active_window()->set_text("hello") at the UCW command prompt, the command modifies the actual UCW command window. Likewise, there can be only one window that has the input focus, waiting for keyboard input; you can set this window by using set_focus(). You can use show() to set the window state; the important states are SW_HIDE, SW_MAXIMIZE, SW_MINIMIZE, SW_RESTORE, and SW_SHOW. SW_RESTORE is used to restore a window to its original state, if it has been minimized, and so forth.

is_visible() becomes false after you use show(SW_HIDE).

Managing Events: TEventWindow

TEventWindow is the base class for any window that tries to intercept Windows events or messages. For the main window you usually use TFrameWindow, which is derived from TEventWindow. You catch events by overriding the following virtual methods:

virtual void size(int cx, int cy);
virtual void on_move();

These methods are called when the window is resized or moved, respectively, by user action or directly by TWin::resize() and TWin::move().

The following is automatically called to repaint the window when it has become invalid:

virtual void paint(TDC& dc);

You should try to keep all graphics calls in this method and use the graphics context provided.

The keydown event fires when the user presses any key, including noncharacter keys such as Alt and Shift. The following is an example:

virtual void keydown(int vkey);
virtual void on_char(int vkey,int repeat);

The result of a keydown() or a keyup() event is an actual character event, which causes on_char() to be called. (Note that repeat is greater than one if a key has been held down long enough.)

The points shown in the following example are in client coordinates:

// mouse messages
 virtual void mouse_down(Point& pt);
 virtual void mouse_move(Point& pt);
 virtual void mouse_up  (Point& pt);
 virtual void right_mouse_down(Point& pt);
 virtual void mouse_double_click(Point& pt);

Because mouse_move() is called continuously, you should try not to do too much work while processing it.

You can override command() if you need to directly process commands (sent from menus, child controls, and so on):

virtual bool command(int id);
virtual bool sys_command(int id);

These functions must return true if you acted on the command, and must return false if you ignored it.

The following is called every m milliseconds, after a call to TEventWindow::create_timer(m).

virtual void timer();

You can stop the timer by using TEventWindow::kill_timer().

The following is called whenever the window gains or loses the input focus:

virtual void focus(bool yes_no);

query_close() is called when the user attempts to close a window:

virtual bool query_close();

This is an opportunity to try to argue with the user and bring up an “are you really sure?” message. If this method returns false, the window is not closed. destroy() causes the window to close; TFrameWindow, for example, redefines destroy(), to close the whole application.

Graphics: (TDC)

All graphics are created via a device context object (in the class TDC), which is passed to the paint method. You can draw any time you like by defining a TClientDC object, which is given an event window pointer.

void move_to(int x, int y);
void line_to(int x, int y);
void rectangle(const Rect& rt);
void ellipse(const Rect& rt);
void draw_text(pchar msg);
void text_out(int x, int y, char *buff, int sz = -1);
void set_text_align(int flags, bool update_cp = false);
void get_text_extent(pchar text, int& w, int& h,
                     TFont *font=NULL);

These correspond to the common graphics device interface (GDI) calls. draw_text() depends on set_text_align(0,true); that is, any move_to() or line_to() operation modifies CP (which stands for “current position”), and the new CP value is used to position text. This is currently the default setting.

Setting Color

You can either specify color by using an RGB triplet, where (1.0,1.0,1.0) is pure white, or with a 24-bit hexadecimal color value, such as 0xFF0000. You use the pen to draw lines and outlines of shapes such as rectangles, ellipses, and polygons. You use the brush to fill in shapes. YAWL ties the text and graphics colors together.

//*** this changes both the _pen_ and the _text_ color
void set_color(float r, float g, float b);
void set_color(long color);
void set_text_color(long color);
*** ditto, does brush and background color
void set_back_color(float r, float g, float b);
void set_back_color(long color);

Setting Text Fonts

You can explicitly construct a TFont object and call TDC::select(), as in the following example:

TFont f1,f2;
f1.create("Arial",24,NORMAL);
f2.create("Courier",12,  BOLD | ITALIC);
...
dc.select(f1);

Using Turtle Graphics

The turtle graphics subsystem is an alternative to the traditional GDI-style graphics. I've used turtle graphics in the section “Drawing Trees with Turtle Graphics” in Chapter 6. It brings two new things to the party. First, you can define a floating-point coordinate system that starts at the bottom-left corner. One advantage of this is that the picture can scale automatically with window size.

Second, as well as the usual plotting commands, turtle graphics provides a set of relative graphics commands, organized around the turtle. This mostly invisible beast can be controlled in two ways: by specifying how much it turns and by specifying how much it moves ahead.

You can use TGFrameWindow, rather than TFrameWindow. The section “Using an Existing Framework” in Chapter 8 has an example of a turtle graphics program that uses TGFrameWindow. To use it, override the following methods; they receive points expressed as a pair of floating-point numbers, and the tg_paint() method receives its device context as a turtle graphics object.

virtual void tg_mouse_down(FPoint& p);
virtual void tg_right_mouse_down(FPoint& p);
virtual void tg_mouse_move(FPoint& p);
virtual void tg_paint(TG& tg);

The following are all turtle graphics methods:

void scale(double x1, double x2, double y1, double y2);
void penup();
void plot(double x, double y);
void rectangle(double x1, double y1, double x2, double y2);
void ellipse(double x1, double y1, double x2, double y2);
int scalex(double x);
int scaley(double y);
double unscalex(int ix);
double unscaley(int iy);
void fcolor(double r, double g, double b);
void bcolor(double r, double g, double b);

You set the domain and range by using scale(); the default is (0,100,0,100). The drawing methods are based on the old Hewlett-Packard pen-based API: plot(x,y) moves the pen to (x,y); if the pen is down, it draws a line. If the pen is not down, it is moved to the point and then put down. You can explicitly raise the pen by using penup(). This example constrasts the two methods of plotting some points. The advantage of using TG over the usual TDC graphics is that the first point is not a special case. The values x[i] and y[i] in the example would also have to be in client coordinates; in TG, a scale can be set:


;> // plotting some points using TDC
;> dc.move_to(x[0],y[0]);
;> for(int i = 1; i < n; i++) dc.draw_to(x[i],y[i]);
;> // plotting some points using TG
;> tg.scale(0,n,0,max);
;> tg.penup();
;> for(int i = 0; i < n; i++) tg.plot(i,values[i]);
						

The scalex() and scaley() routines compute integer client coordinates for the window, and unscalex() and unscaley() work the other way. You set the foreground and background color with fcolor() and bcolor(), and rectangle() and ellipse() work like the TDC methods, except that they use scaled coordinates.

The following methods change the turtle angle (in degrees):

void turn(double angle);
void left();              // same as turn(-90)
void right();             // same as turn(+90)

The following methods move the turtle position, with the pen up and down, respectively:

void draw(double len);
void move(double len);
void go_to(double x, double y);

The following method shows the turtle (which is initially not visible):

void show(bool yes=true);

The following method places text at the turtle position:

void text(char *msg);

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.141.37.10