15. Windows: The Basics

Page 261
  III. WINDOWS (USER32.DLL PROGRAMMING)  
Page 263
  15. Windows: The Basics  
   
  We begin our study of Windows' windows with the basics, including much of the terminology associated with windows.  
 
  Terminology  
   
  Let us begin with the basic terminology of windows. Note that many of these terms are not used in a precise way and so their meanings may differ depending on the context. However, our definitions will serve as general guidelines.  
   
  When Windows is started, it automatically creates the desktop window, which is a system-defined window that paints the background of the screen and serves as the "base" for all windows displayed by all applications.  
   
  Every graphical-based Windows application (as opposed to console-based application) creates at least one window, called its main window. This window is the main interface between the application and the user.  
   
  Here are the general categories of windows:  
 
  Application window
A window that typically has one or more of the following: a titlebar with an icon and Maximize, Minimize, and Close buttons; a menu bar; and scroll bars. One concept that many users are not familiar with, but which is important for programmers, is that of the client area. This is the area of a window that can receive output, such as text or graphics. Thus, for instance, the client area of a window does not include rulers, menu bars, window borders, or scroll bars. The remainder of a window is referred to as the nonclient area.
 
Page 264
 
  Control
A special-purpose window that is used for single-function (usually) communication with the user. Every control is a child of some other window, called the control's container.
 
 
  Dialog box
A window whose main function is to contain controls, and thus provide multi-function communication with the user.
 
 
  Message box
A window that is used to display a message.
 
   
  Some windows are considered top-level windows. Unfortunately, this term is defined differently in different parts of the MSDN documentation. In one location, it is defined as a window with no parent. (We will discuss parent windows later.) In another location, it is defined as a window either having no parent or whose parent is the desktop window. Also according to the documentation, the EnumChildWindows API function will enumerate all top-level windows (if a certain parameter is set to 0). However, as we will see, the function enumerates some windows that do have parents other than the desktop window. The only reasonable conclusion is that the term top-level window is not used consistently. However, it seems generally to refer to a window that is not a child window.  
   
  As we will see in some detail in Chapter 16, Windows Messages, every window has associated with it:  
 
  A window handle
A 32-bit number that uniquely identifies the window throughout the system.
 
 
  A window class
A distinction used to create the window and gives the window its initial characteristics. We will discuss window classes in Chapter 17, Window Classes and the Window Creation Process.
 
 
  Window styles
We discuss these next.
 
 
  Window Styles  
   
  In addition to a handle and a class, every window has one or more window styles that define the characteristics of the window, such as the presence or absence of borders, titlebars. Maximize buttons, and so on. Window styles are defined by symbolic constants, of which there are roughly 200 in number. Window styles are generally combined (by ORing the constants) to produce the desired effect. For instance, setting the style of a window to:  
 
  WS_MAXIMIZEBOX Or WS_MINIMIZEBOX Or WS_SYSMENU  
Page 265
   
  gives the window Maximize and Minimize buttons as well as a window menu (which used to be called a system menu).  
   
  Note that some styles are defined as combinations of other styles. For instance, the WS_POPUPWINDOW style is defined as:  
 
  WS_POPUPWINDOW = WS_POPUP Or WS_BORDER Or WS_SYSMENU  
   
  This is very helpful, in view of the large number of styles.  
   
  Many window styles fit neatly into categories, which we discuss next.  
   
  Styles That Define General Window Characteristics  
   
  Some styles help define the general characteristics (as opposed to specific characteristics, such as having a Maximize button) of a window.  
   
  Overlapped windows  
   
  An overlapped window is a top-level window with style WS_OVERLAPPED or WS_OVERLAPPEDWINDOW. Those windows with style WS_OVERLAPPED have a titlebar and border and those with style WS_OVERLAPPEDWINDOW have a titlebar, sizing border, window menu, and Minimize and Maximize buttons.  
   
  An application's main window is generally an overlapped window.  
   
  Pop-up windows  
   
  A pop-up window is a window with style WS_POPUP. These are special types of overlapped windows that are used for dialog boxes, message boxes, and other temporary windows that can appear outside of an application's main window. A pop-up window may or may not have a titlebar. Otherwise, pop-up windows are the same as overlapped windows with the WS_OVERLAPPED style.  
   
  Child windows  
   
  A child window is a window that is defined with the WS_CHILD style. This style must be specified when the window is created. As we will see, the CreateWindow and CreateWindowEx functions have a parameter that is used to specify the handle of the parent window of the child.  
   
  A child window is confined to the client area of its parent window. Child windows are typically used to divide the client area of its parent into functional areas. A child window may have a titlebar, a window menu, Minimize and Maximize buttons, a border, and scroll bars, but it cannot have a menu.  
   
  Note that the GetParent function can be used to retrieve a handle to a window's parent. We will use this function in an upcoming example.  
Page 266
   
  Window Border Styles  
   
  Several styles define the border characteristics of a window, as follows:  
 
  WS_BORDER
A window with a thin-line border.
 
 
  WS_DLGFRAME
A window with a double border, typically used with dialog boxes. Such a window cannot have a titlebar.
 
 
  WS_EX_DLGMODALFRAME
A window with a double border, but possibly with a titlebar as well (if the window also has the WS_CAPTION style).
 
 
  WS_EX_STATICEDGE
A window with a three-dimensional border style. This is intended to be used for windows that do not accept user input.
 
 
  WS_THICKFRAME
A window with a sizing border.
 
   
  Styles That Affect the Nonclient Area of a Window  
   
  The nonclient area of a window can include a titlebar, window menu, Minimize and Maximize buttons, sizing border, and horizontal and vertical scrollbars. Here are the relevant styles:  
 
  WS_CAPTION
A window with a titlebar (includes the WS_BORDER style)
 
 
  WS_HSCROLL
A window with a horizontal scrollbar
 
 
  WS_MAXIMIZEBOX
A window with a Maximize button
 
 
  WS_MINIMIZEBOX
A window with a Minimize button
 
 
  WS_SYSMENU
A window with a window menu in the titlebar
 
 
  WS_VSCROLL
A window with a vertical scrollbar
 
   
  Styles that Affect the Initial State of a Window  
   
  The following styles determine the initial state of a window:  
Page 267
 
  WS_DISABLED
A window that is initially disabled
 
 
  WS_MAXIMIZE
A window that is initially maximized
 
 
  WS_MINIMIZE
A window that is initially minimized
 
 
  WS_VISIBLE
A window that is initially visible
 
   
  Parent and Child Styles  
   
  It is possible for one window to be a child of another window. The clipping region of a window is that portion of the window's client area where Windows currently permits drawing. There are two styles that affect clipping regions:  
 
  WS_CLIPCHILDREN
This style clips all child windows from the drawing area of the parent.
 
 
  WS_CLIPSIBLINGS
This style clips a child window relative to its sibling windows. Thus, when one child window needs repainting, only its exposed area will be repainted, which prevents repainting on top of an overlapped sibling window.
 
   
  We will discuss clipping in detail in Chapter 22, Device Contexts I: Overview.  
   
  Extended Styles  
   
  There are a great many extended styles. We mention only two:  
 
  WS_EX_TOPMOST
This style specifies that a window should be placed above all nontopmost windows, even when another application is in the foreground. Of course, one topmost window may cover another topmost window. For instance, some help systems let you specify that a window be topmost.
 
 
  WS_EX_TOOLWINDOW
This style defines a tool window; that is, a window that is intended to be used as a floating toolbar.
 
   
  We will continue our discussion of styles, and how to change them, in Chapter 17.  
 
  Owned Windows  
   
  It is possible for an overlapped or pop-up window to be owned by another overlapped or pop-up window. This is quite different from the parent-child relationship, since in the case of owned windows both windows must be overlapped or  
Page 268
   
  pop-up windows. In particular, a child window can be neither an owner nor an owned window. Dialog boxes and message boxes are owned windows by default, for instance.  
   
  The basic characteristics of an owned window are:  
   
  An owned window always lies on top of its owner in the Z order (described shortly).  
   
  Windows automatically destroys an owned window when its owner is destroyed.  
   
  An owned window is hidden when its owner is minimized.  
   
  The GetWindow function can be used to retrieve a handle to a window's owner.  
 
  Z Order  
   
  The Z order refers to the order of visibility of windows on the screen. More specifically, the Z order indicates the window's relative position with respect to an imaginary z-axis that comes directly out of the monitor at right angles, toward the user, as pictured in Figure 15-1.  
   
  0268-01.gif  
   
  Figure 15-1.
Illustrating Z order
 
   
  Windows keeps the Z orders of all windows in a single list, but it does so in a structured way. In particular, the child windows of a parent window are always grouped with the parent, so when the Z order of the parent window changes, the Z orders of its children follow along. Figure 15-2 illustrates what happens when a top-level window (Window2) moves to the top of the Z order. Quite simply, it brings its children along for the ride.  
Page 269
   
  0269-01.gif  
   
  Figure 15-2.
Moving up in the Z order
 
   
  The topmost windows (style WS_EX_TOPMOST), if any, always appear at the top of the Z order and are thus always visible, unless obscured by another topmost window. There follow the parent-child groupings. When a window is created, it is placed at the top of the Z order for its type. Thus, a new parent window is placed just below the topmost windows, and a new child window is placed just below its parent window and therefore above any other child windows for that parent.  
   
  Note that this scheme gives the child windows of a single parent a relative Z ordering as well.  
   
  There are several API functions that relate to Z order. Here are a few.  
   
  BringWindowToTop  
   
  The BringWindowToTop function:  
 
  BOOL BringWindowToTop(
  HWND hWnd  // handle to window
);
 
   
  brings a window to the top of the Z order for its type. If the window is a top-level window, then it is activated. If the window is a child window, its top-level parent window is activated and thus brought to the top of the Z order for windows of its type.  
   
  Note that this function does not change the type of window; that is, it will not promote a nontopmost window to a topmost window and so it will not place a top-level window over a topmost window (only over other top-level windows).  
   
  SetWindowPos  
   
  The SetWindowPos function can be used to change the size, position, and Z order of a window, as in the following code.  
  BOOL SetWindowPos(       HWND hWnd,               // handle to window       HWND hWndInsertAfter,    // placement-order handle       int X,                   // horizontal position       int Y,                   // vertical position       int cx,                  // width       int cy,                  // height       UNIT uFlags              // window-positioning flags     );   
Page 270
   
  The hWndInsertAfter parameter can assume one of the following values:  
 
  HWND_BOTTOM
Places the window at the bottom of the Z order. If the window was topmost, it loses its topmost status and is placed at the bottom of all other windows.
 
 
  HWND_NOTOPMOST
For a topmost window, places the window above all nontopmost windows and thus directly beneath all topmost windows. This flag has no effect on a nontopmost window.
 
 
  HWND_TOP
Places the window at the top of the Z order for its type. When applied to a child window, moves its top-level parent to the top of the Z order for its type. (Same as BringWindowToTop.)
 
 
  HWND_TOPMOST
Gives a top-level window the topmost attribute and places it at the top of the Z order. We will use this feature in several of our utilities.
 
   
  GetTopWindow  
   
  The GetTopWindow function has syntax:  
 
  HWND GetTopWindow(
  HWND hWnd  // handle to parent window
);
 
   
  This function looks at just the child windows of the specified parent and retrieves a handle to the child window at the top of the Z order among all children of that parent. If hWnd is NULL (0), then the function retrieves a handle to the window at the top of the Z order among all windows.  
   
  In a similar vein, the GetNextWindow function:  
 
  HWND GetNextWindow(
   HWND hWnd, // handle to current window
   UINT wCmd  // direction flag
);
 
   
  retrieves a handle to the window that is next (lower down) or previous  
   
  (higher up) in the Z order of the same type as the window in  
   
  question. Thus, if hWnd refers to a top-level (nontopmost)  
   
  window, the function retrieves a handle to the appropriate  
Page 271
   
  top-level window, and if hWnd refers to a child window, the function returns a child window (for the same parent). If no such window exists, the function returns NULL (0).  
 
  Enumerating Windows  
   
  The Win32 API provides a collection of enumeration functions that can be used to enumerate various objects, including windows. Let us take a look at the notion of an enumeration function, since it will come up several times in the book (and has already come up in the rpiEnumProcs applications).  
   
  Enumeration Functions  
   
  Here are a few examples of enumeration functions:  
 
  EnumProcesses
Enumerates the process identifiers for each process object in the system
 
 
  EnumProcessModules
Enumerates the handles of each module in the specified process
 
 
  EnumWindows
Enumerates top-level windows
 
 
  EnumChildWindows
Enumerates child windows of a window
 
 
  EnumThreadWindows
Enumerates all nonchild windows associated with a thread
 
 
  EnumFonts
Enumerates the fonts available on a specified device
 
 
  EnumFontFamilies
Enumerates the available fonts in a given font family
 
 
  EnumObjects
Enumerates the pens or brushes available for a specified device context
 
 
  EnumDateFormats
Enumerates the long or short date formats that are available for a specified locale
 
 
  EnumDeviceDrivers
Enumerates the load address for each device driver in the system
 
 
  EnumPrinterDrivers
Enumerates all of the printer drivers currently installed
 
 
  EnumPorts
Enumerates the ports that are available for printing
 
Page 272
   
  Generally speaking, the main issue related to enumeration functions is how to return the enumerated data. The problem is that there is no way of knowing ahead of time how much data needs enumerating, so passing a data structure (such as an array) to an enumeration function is not very practical.  
   
  Nevertheless, some enumeration functions make us do just that. As we will see, they make us guess at the size of a buffer for the returned value and then return not only the data but also the number of bytes required to hold the data. If the buffer that we have allocated is not sufficiently large, we must increase the size of that buffer and try again. This is crude but it does work.  
   
  On the other hand, several enumeration functions take a ''cop out" approach by saying, in effect, "I will tell you separately about each item to be enumerated, and you figure out what to do with this information."  
   
  The way that an enumeration function tells the calling program separately about each item to be enumerated is by calling a function that the calling program must supply. This function is descriptively referred to as a callback function.  
   
  The idea is simply that the enumeration function will call a callback function once for each item that it enumerates, passing information (such as the item's handle) in the parameters of the callback function. (In many ways, this is reminiscent of VB events Windows fires an "event" for each object being enumerated.)  
   
  Thus, the signature (parameter types, etc.) of the callback function must be supplied to us in the documentation for the enumeration function, but it is up to us to create this function, pass its address to the enumeration function, and write code for the function to process the information returned in the parameters. Typically, an enumeration function inspects the return value of the callback function to see whether it should continue enumerating or just quit.  
   
  Fortunately, VB can supply the address of a callback function using the AddressOf operator. In fact, this is probably why the AddressOf operator was introduced into Visual Basic!  
   
  To illustrate, the EnumWindows function is declared as:  
 
  BOOL EnumWindows(
   WNDENUMPROC lpEnumFunc,   // pointer to callback function
   LPARAM lParam             // application-defined value
);
 
   
  The lpEnumFunc parameter should be set to the address of the callback function. The lParam parameter can be defined by the caller and is passed to the callback function each time it is called by EnumWindows. One use for this value is as a counter.  
Page 273
   
  The EnumWindows function can be translated into VB as:  
 
  Declare Function EnumWindows Lib "USER32" ( _
   ByVal lpFunct As Long, _
   lParam As Long _
) As Long
 
   
  where lParam is passed by reference. Now, we declare a counter variable:  
 
  Dim c As Long  
   
  outside the callback function (this is key) and pass it by reference to EnumWindows.  
 
  EnumWindows (AddreesOf OurCallBack, c)  
   
  In turn, EnumWindows passes the variable c to our callback function, which will just increment it by 1. Since each time the callback function is called, it increments the external (to the callback function) variable c by 1, the variable c will contain a count of all enumerated windows when the EnumWindows function is done.  
   
  Example: The EnumWins Utility  
   
  The CD that accompanies this book contains the source code for a utility called rpiEnumWins, which enumerates all windows and places information about each in a TreeView control. Figure 15-3 shows the main window.  
   
  It is interesting to see the kinds of windows that Windows creates. One of the most amusing features of this utility is that it will draw a red rectangle on the screen at the current location of a window, whether it is visible or not.  
   
  This utility uses the API EnumChildWindows, which is similar to EnumWindows, but which will enumerate child windows as well as top-level windows. The declaration is:  
  BOOL EnumChildWindows(       HWND hWndParent,         // handle to parent window       WNDENUMPROC lpEnumFunc,  // pointer to callback function       LPARAM lParam            // application-defined value     );   
   
  Here is what the documentation says about the hWndParent parameter:  
  If this parameter is NULL, the parent window is the desktop window, and the function enumerates all top-level windows.  
   
  This is a bit contradictory, since it implies that all top-level windows have the desktop window as parent, which is not the case. In any case, this function seems to enumerate all top-level windows (whatever that really means).  
   
  The main action in the rpiEnumWins utility is in the callback function EnumChildProc. Here we gather the data about each window, such as its handle, caption,  
Page 274
   
  0274-01.gif  
   
  Figure 15-3.
The rpiEnumWins utility
 
   
  class name, window rectangle (coordinates of the window on the screen), and process and thread IDs. A new TreeView node is created for each window. Fortunately, the Tag property of a node can be a variant, and so it can hold an entire array of values. This is where we store all of the window's data.  
 
  Function EnumChildProc(ByVal hwnd As Long, lParam As Long) As Long

' This is called by Windows for each child window
' ByVal is needed in order to use hwnd
' lParam can be called ByVal or ByRef but make sure it matches in Declare _
  statement!

Dim lret As Long
Dim lTitleLen As Long
 
 

Page 275
 
  Dim sWinTitle As String
Dim sWinClass As String
Dim hOwner As Long
Dim s As String
Dim uNode As Node
Dim r As RECT
Dim lThreadID As Long
Dim lProcID As Long

' Gather window data
lTitleLen = GetWindowTextLength(hwnd) + 1
sWinTitle = String $ (lTitleLen, 0)
lret = GetWindowText(hwnd, sWinTitle, lTitleLen)
sWinTitle = Left $ (sWinTitle, lret)
sWinClass = GetClass(hwnd)
hOwner = GetWindow(hwnd, GW_OWNER)
GetWindowRect hwnd, r
lThreadID = GetWindowThreadProcessId(hwnd, lProcID)

' Increment window count
lParam = lParam + 1

s = HexFormat(hwnd) & "  """ & sWinTitle & """  " & sWinClass

' Append owner if nonzero
If hOwner <> 0 Then
   s = s & " [Owner: " & HexFormat(hOwner) & "]"
End If

Set uNode = frmEnumWins.trvWins.Nodes.Add( _
   frmEnumWins.trvWins.Nodes(idxCurrentParent).Key, _
   tvwChild, "Key" & Format $ (lParam), s)

' Tag is an array
uNode.Tag = Array(hwnd, sWinTitle, sWinClass, _
   hOwner, r.Bottom, r.Left, r.Right, r.Top, lProcID, lThreadID)

' To continue
EnumChildProc = True

End Function
 
 
  Size and Position Functions  
   
  The Win32 API has a great many functions that relate to the positioning and sizing of windows on the screen. Frankly, these functions are a bit boring, but we should at least introduce some of them here, so that you can investigate them further when needed.  
Page 276
   
  SetWindowPlacement  
   
  The SetWindowPlacement function sets the show state and the restored, minimized, and maximized positions of the specified window:  
 
  BOOL SetWindowPlacement(
  HWND hWnd,                      // handle to window
  CONST WINDOWPLACEMENT *lpwndpl  // address of structure with position data
);
 
   
  Here lpwndpl is the address of a WINDOWPLACEMENT structure:  
 
  typedef struct _WINDOWPLACEMENT {
   UINT length;            // length of this structure
   UINT flags;
   UINT showCmd;
   POINT ptMinPosition;    // upper-left corner when the window is Minimized
   POINT ptMaxPosition;    // upper-left corner when the window is Maximized
   RECT rcNormalPosition;
} WINDOWPLACEMENT;
 
   
  Note that the length field of this structure must be filled in before calling SetWindowPlacement. We won't discuss all of the possible values for the members of this structure, but just note that among the possible values for showCmd are SW_HIDE, SW_RESTORE, SW_SHOW, SW_SHOWMAXIMIZED, SW_SHOWMINIMIZED, and SW_SHOWNORMAL. These are pretty self-explanatory.  
   
  The Windows API uses POINT and RECT structures quite often. A POINT structure is defined as:  
 
  typedef struct tagPOINT {
    LONG x;
    LONG y;
} POINT;
 
   
  and a RECT structure as:  
 
  typedef struct _RECT {
   LONG left;
   LONG top;
   LONG right;
   LONG bottom;
} RECT;
 
   
  The VB translations are very straightforward, since VC++ UNITs and LONGs become VB longs. The only wrinkle is that the word POINT is a VB keyword, so we should choose another word:  
 
  Type POINTAPI
   x As Long
   yAs Long
End Type

Type RECT
 
 

Page 277
 
     Left As Long
   Top As Long
   Right As Long
   Bottom As Long
End Type

Type WINDOWPLACEMENT
     Length As Long
     flags As Long
     showCmd As Long
     ptMinPosition As POINTAPI
     ptMaxPosition As POINTAPI
     rcNormalPosition As RECT
End Type
 
   
  We can now declare SetWindowPlacement as:  
 
  Declare Function SetWindowPlacement Lib "user32" Alias "SetWindowPlacement" ( _
   ByVal hwnd As Long, _
   lpwndpl As WINDOWPLACEMENT _
) As Long
 
   
  As you may have guessed, there is also a GetWindowPlacement function that retrieves the current window settings in a WINDOWPLACEMENT structure.  
   
  MoveWindow  
   
  The MoveWindow function changes the position and size of a window. It is important to note that, for a top-level window, the position is relative to the upper-left corner of the screen, whereas for a child window, it is relative to the upper-left corner of the parent window's client area.  
   
  The declaration is:  
  BOOL MoveWindow(       HWND hWnd,       // handle to window       int X,           // position to left side of window (in pixels)       int Y,           // position to top of window (in pixels)       int nWidth,      // width (in pixels)       int nHeight,     // height (in pixels)       BOOL bRepaint    // repaint flag     );   
   
  or, in VB:  
 
  Declare Function MoveWindow Lib "user32" Alias "MoveWindow" ( _
   ByVal hwnd As Long, _
   ByVal x As Long, _
   ByVal y As Long, _
   ByVal nWidth As Long, _
   ByVal nHeight As Long, _
   ByVal bRepaint As Long _
) As Long
 
Page 278
   
  The bRepaint flag should be set to True to have Windows repaint the window after it is moved or resized.  
   
  Unfortunately, all of the parameters to this function must be filled in, so even if we want to change only the window's size, we must compute the window's current position to use in the position parameters. This can be done using the GetWindowRect function discussed below.  
   
  SetWindowPos  
   
  We discussed the SetWindowPos function earlier in the chapter. This function can be used to change the size, position, and Z order of a window:  
   BOOL SetWindowPos(        HWND hWnd,              // handle to window        HWND hWndInsertAfter,   // placement-order handle        int X,                  // horizontal position        int Y,                  // vertical position        int cx,                 // width        int cy,                 // height        UINT uFlags             // window-positioning flags      );   
   
  Note that there is no corresponding GetWindowPos.  
   
  GetWindowRect and GetClientRect  
   
  The GetWindowRect function retrieves the window's rectangle (or bounding rectangle), which is a rectangle that would precisely circumscribe the entire window (client and nonclient areas). The dimensions of this rectangle are screen coordinates, that is, coordinates (in pixels) relative to the upper-left corner of the screen. Here is the declaration:  
 
  BOOL GetWindowRect(
  HWND hWnd,     // handle to window
  LPRECT lpRect  // address of RECT structure that will be filled by function
);
 
   
  The GetClientRect function does the same thing for the client area of the window:  
 
  BOOL GetClientRect(
   HWND hWnd,    // handle to window
   LPRECT lpRect // address of structure for client coordinates
);
 
   
  You might expect that the coordinates returned in the RECT structure would be window coordinates, that is, coordinates relative to the upper-left corner of the window, but this is not the case. Indeed, the main purpose of this function is to retrieve the size of the client area, so it simplifies matters for the function to return client coordinates, that is, coordinates that are relative to the client area itself. Hence, the upper-left corner will always be (0,0).  
Page 279
   
  Ignorance reigns supreme  
   
  Consider for a moment the following code:  
 
  SetWindowPos Text1.hwnd, HWND_TOP, 0, 0, 2, 2, SWP_SHOWWINDOW Or SWP_NOMOVE
GetWindowRect Text1.hwnd, r
Debug.Print r.Top, r.Bottom, r.Left, r.Right
 
   
  This simply sets the height and width of a text box to 2 pixels. A sample output is:  
 
  46            48            17            19  
   
  We might have expected the Top and Bottom values to differ by only 1 (see Figure 15-4), since the text box has height 2 pixels. However, the GetWindowRect function returns the coordinates (r.Right, r.Bottom) of the pixel just below and to the right of the window, as shown in Figure 15-4. Hence, this pixel is not actually part of the window!  
   
  0279-01.gif  
   
  Figure 15-4.
Illustrating rectangle dimensions
 
   
  This was done deliberately, so that the following equations would hold:  
 
  r.Height = r.Bottom - r.Top
r.Width = r.Right - r.Left
 
   
  In my opinion, this is a clear example of ignorance reigning supreme to deliberately return misleading values for the Bottom and Right properties just so that programmers would not have to learn the correct formulas:  
 
  r.Height = r.Bottom - r.Top + 1
r.Width = r.Right - r.Left + 1
 
   
  Oh well.  
Page 280
   
  ClientToScreen and ScreenToClient  
   
  The functions ClientToScreen and ScreenToClient can be used to translate between client coordinates and screen coordinates. The functions have the same form. They both take a POINT structure as input and replace the values in this structure with the translated values. Thus, the POINT structure is an IN/OUT parameter. Here are the declarations:  
 
  BOOL ClientToScreen(
   HWND hWnd,      // window handle for source coordinates
   LPPOINT lpPoint // pointer to structure containing screen coordinates
);

BOOL ScreenToClient(
   HWND hWnd,      // window handle for source coordinates
   LPPOINT lpPoint // address of structure containing coordinates
);
 
   
  We will use these functions in several utilities.  


WIN32 API Programming with Visual Basic
Win32 API Programming with Visual Basic
ISBN: 1565926315
EAN: 2147483647
Year: 1999
Pages: 31
Authors: Steven Roman

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net