VC++ Workshop
Session 4
R. Eckert

CHILD WINDOW CONTROLS

Child window controls--windows with the following characteristics:

Apps use them in conjunction with another window: the parent
Normally used for simple I/O tasks
Let user choose commands, view status, view/edit text, etc.
Properties, appearance, behavior determined by predefined class definitions
     But behavior can be customized
Allow an app to easily set up child windows for common objects:
     Buttons, scroll bars, etc.
Allow user to display and select information in standard ways
Windows Environment does most of work in:
     Painting/updating a Control's screen area
     Determining what user is doing
Often used as input devices for parent window
Constitute the "working components" of dialog boxes
Windows environment contains each control's WinProc()
     Messages to child windows are processed in a predefined way
     Programmer doesn't have to worry about it
Main window communicates with controls by sending/receiving messages
Six “standard” control types:
       -Static Text
       -Button
       -Edit Control
       -List Box
       -Combo Box
       -Scroll Bar
All are windows
Windows Environment automatically repaints Control upon exposure
Example: WordPad ("File"|"Open") -- has most “standard” controls
There are 17 other predefined "Common Controls" (See Petzold, Ch. 12)
       Supported by COMCTL32.DLL library 
       Some important ones:
            Toolbars, Tooltips, Status Bar, Tree View, List View, Image List,
            Progress Bar, Rich Edit, Up-Down Spin control

Predefined Control Class names:

STATIC-
     Primarily to display text
     Can also display icon images and rectangles
     Automatically redrawn if exposed
     Often used as labels for other controls

BUTTON-
     “Clicked” by user to indicate desired actions or choices made
      Lots of different styles (e.g., check, radio, group)
      Typically notify parent window when user chooses the button

EDIT-
     To enter/view/edit/delete text
     Single or multiline control 
     Lots of word processing capability

LISTBOX-
     Contains lists of items that can be selected
     Entire list is shown
     User selects items

COMBOBOX-
     Static text box or edit box combined with a list box
     List box can be displayed at all times or pulled down
     If combo box has a static text box, it displays list box selection  
     If it uses an edit box, user can type in desired selection
          List box highlights first item (if any) matching user entry
          User selects highlighted item to complete choice

SCROLLBAR-
     Lets user choose direction/distance to move a “thumb”; Two types:

1.   Control attached to edge of a parent window
       Allows user to "scroll" info in parent window's client area
2.   Stand-alone child window control 
       Allows user to enter/change an integer by moving scroll bar "thumb"


Creating Child Window Controls--

CreateWindow()-For any kind of window, including a control

1st parameter: Predefined control class name-      
     "STATIC", "BUTTON", “EDIT”, ”LISTBOX”, 
     ”COMBOBOX”, ”SCROLLBAR”,
     or common control class names (see online help on CreateWindow)

2nd parameter: Name of the window-
     BUTTON, EDIT, STATIC classes text in center of control       
     COMBOBOX, LISTBOX, SCROLLBARignored (use "")

3rd parameter: Window style-
     WS_, SS_, BS_, ES_, LBS_, CBS_, SBS_ (see CreateWindow help)
     Several styles can be combined with the bitwise OR operator (|)
     All controls should include WS_CHILD style

4th & 5th parameters: X,Y position-
     Relative to upper left corner of parent window client area

6th & 7th parameters: Width & Height

8th parameter: Handle to parent window

9th parameter: Handle to menu (hMenu)-
     User interacts with controlWM_COMMAND message
     Usually used to identify menu items--
          But controls don't have menus
     hMenu holds integer ID value for the control
     Allows program to identify which control was activated

10th parameter: Handle to instance of program creating control
     GetWindowLong() can be used to get this value

11th parameter: Normally NULL

STATIC Example App: displays 3 static controls (text, icon, rectangle)--



Text static control displays "This is static text"
Icon static control displays the program icon (from resources)
Rectangle static control displays a gray rectangle

Menu items: "Change Title", "Send Message", "Quit"

User clicks "Change Title"
      Text static control changes to "New Text via SetWindowText()"

User clicks "Send Message"
     Text static control changes to "New Text via SendMessage()"

Each is a child window control created with CreateWindow()
     Static control styles set in call to CreateWindow()
          (See online help on static control styles: SS_)
     Next-to-last-parameter: instance handle to creating app
     Three ways to get instance handle (each illustrated in STATIC.CPP):

1.  GetWindowLong(hWnd, nOffset)-

2. Use a global variable set to hInstance after creating main window in WinMain()

3. WM_CREATE message
     lParam points to CREATESTRUCT that has an hInstance member
     So cast lParam to a long pointer to that type of structure:
     CreateWindow(..., ((LPCREATESTRUCT)lParam->hInstance,… );

Sending a Message to a Child Window Control--

     SendMessage()--sends message to a window’s WinProc()
          Doesn't return until message has been processed
          Parameters: 
               Handle of destination window
               ID of message to send
               wParam and lParam values containing message data, if any

Example from STATIC App:

     SendMessage (hStaticText, WM_SETTEXT, 0,
                                 (LPARAM)"New Text Via SendMessage().") ;

     Here message is WM_SETTEXT, sent to static control
     When received, static control's WndProc() changes control’s text string
          wParam must be 0
          lParam points to text string to be displayed

Another Way of Sending Text to a Window or Control-

     SetWindowText();

          Invokes SendMessage(), ID=WM_SETTEXT 
          Specified text displayed in specified window or control. 
          For a main window, sets window's title to specified  text 
          For static control, text is changed
          Parameters:
               Handle to window to display text
               Pointer to string to be displayed

STATIC.CPP uses both methods in response to user menu choices

In STATIC example, text sent is a string

Could use wsprintf() to generate a formatted text string for integer & other data:

     wsprintf(cBuf, format string, values);

Then to send the formatted string to a control, call:

 SendMessage(hControl, WM_SETTEXT, 0, (LPARAM)cBuf);

<See STATIC1 Example--outputs a new number each time menu item selected>



A Related message-sending function: PostMessage();-
     Places (posts) a message in window's message queue 
     Returns immediately 
     Could have been used here

Messages can be retrieved with GetMessage() or PeekMessage();

Getting Text Stored in a Static Control--

     SendMessage(hControl, WM_GETTEXT, nCnt, cBuf);

     Or, equivalently

     GetWindowText(hControl, cBuf, nCnt);


BUTTON CONTROLS--

Little windows that can be clicked by user
Indicate actions to be taken or choices made
Lots of different styles:
     Check--box with check, unchecked, grayed
     Radio--round button, on or off, only one on if in group
     Group--a box that groups other buttons
     Pushbutton--has text, usually initiates some action when selected
Typically buttons notify parent window when user chooses them

Button Styles when creating CreateWindow(): Any BS_ values
     (See online help at end of CreateWindow listing)

WM_COMMAND message details for buttons--

User interacts with the button (or other control)
     WM_COMMAND message sent to parent window
          LOWORD(wParam) = buttonID (hMenu value when created)
          lParam = handle to button's window
          HIWORD(wParam) = button notification code (BN_***)
               Indicates what the user interaction was
               (See on-line help on BN_ )
     <Details here have changed from Win16>

Sending Messages to Buttons--

Use SendMessage()

     Parameters:
          Button window handle
          Message ID, e.g.--
               BM_GETCHECK
               BM_SETCHECK
               BM_GETSTATE
               BM_SETSTATE
               BM_SETSTYLE
          lParam: state being set (or 0 for get msgs))
     Returns: button status (for get msgs) 

BUTTON.CPP Example program--



Illustrates many button styles:
     "Radio1" and "Radio2" radio buttons inside a group box:
          Clicking activates button clicked, deactivates other
     "Check Box" button:
          Clicking cycles between activated, deactivated, grayed states
     "Show Status" pushbutton
          Clicking brings up message box showing status of radio/check buttons
     "Done" pushbutton:
          Terminates application

Has menu item "Test Settings"--
     Has same effect of "Show Status" pushbutton

MessageBox() -- Produces a child window with a message and a title
     Parameters:
          Message box’s parent window handle (hWnd)
          Pointer to text to be displayed in message box
          Pointer to text to appear in message box's title
          Message box style--MB_OKcontains an OK push button.
     Message box remains on screen until user presses the OK button
          (It’s really a simple modal dialog box)


LIST BOX--

Created with CreateWindow() using "LISTBOX" window class
Many possible style parameters (see online help on LBS_)
     LBS_NOTIFY or LBS_STANDARDcan send msgs to parent

Program communicates with listbox by sending it messages
Some messages:
     LB_RESETCONTENT
     LB_ADDSTRING
     LB_GETCURSEL
     LB_GETTEXT
     (See online help on LB_)

User interacts with listbox
     WM_COMMAND message
          LOWORD(wParam) = listbox ID
          lParam = listsbox window handle
          HIWORD(wParam) = listbox notification code (what happened)
               See on-line help on LBN_ for listbox notification codes

The LISTBOX.CPP Example Program--



Creates an empty listbox
Selecting "Fill Listbox" menu item fills listbox with some strings
Selecting any string in the listboxa message box to display chosen string


COMBO BOX--

Like a list box, but with an edit header control that shows current selection  
Can be set up to show only the header style=CBS_DROPDOWN
     Takes up less space

Styles--(see on-line help on CBS_)

COMBO.CPP Example Program--



Logic is very similar to LISTBOX.CPP, with:
LB replaced by CB
LISTBOX --> COMBOBOX


SCROLLBAR--

Two types of scroll bars:

  1. A control attached to the edge of a parent window. It allows the user 
  to "scroll" the information in the parent window's client area

  2. A stand-alone child window control that can allow the user to
  enter an integer value by moving the scroll bar "thumb"

User interacts with a scroll bar
     WM_HSCROLL or WM_VSCROLL message sent
     lParam=scroll bar window handle (stand-alone scrollbars)
     lParam=0 (attached scroll bar it is 0)
     LOWORD(wParam)=notification code describing user action taken:
          SB_LINEUP (up/left arrow pressed) 
          SB_PAGEUP (scroll area above/left of “thumb” pressed)
          SB_LINEDOWN (down/left arrow pressed)
          SB_PAGEDOWN (scroll area beneath/right of “thumb pressed)
          SB_THUMBTRACK (scroll “thumb” pressed)
          SB_THUMBPOSITION (scroll “thumb” released)
               For either of these, HIWORD(wParam)=current thumb position 

Lots of Scrollbar styles when creating it-See online help on SBS_

Default alignment for attached scroll bar: right side and bottom of window

Some Useful Scrollbar Functions:

GetScrollPos()--                Retrieve current position of thumb
GetScrollRange()--      Retrieve minimum and maximum value range
SetScollPos()--         Set position of thumb
SetScrollRange()--      Set minimum and maximum value range
ShowScrollBar()--       Display scroll bar

The SCROLL1.CPP Example (a Stand-alone Scrollbar)--



Stand-alone scrollbar allows user to enter an integer value between 0 and 50 
Current value is continually displayed in a static control
Message box shows current value when user chooses menu item "Get Value"


Scroll Bars Attached to a Window (The SCROLL2.CPP Example)--



Creates a window with a vertical scroll bar 
Puts 3 lines of text in client area
User can scroll through client area using scroll bar
User moves scroll bar
     Force a client area repaint and make text appear in correct position
     Gives impression that lines moved down
     Opposite from how scrolling normally works!

To add scroll bars to the edge of a main window-
     WS_HSCROLL or WS_VSCROLL style when creating window:

      hWnd = CreateWindow ("MyClass", "Scroll Control Example 2",
        WS_OVERLAPPEDWINDOW | WS_VSCROLL,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
        CW_USEDEFAULT,
        NULL, NULL, hInstance, NULL) ;


EDIT CONTROLS (for viewing and editing text)--

Current location kept track of with a "carat"--a small vertical line
Backspace, Delete, and arrow keys + highlighting work as expected
Scrolling possible (WS_HSCROLL, WS_VSCROLL styles
NO ability to format text with different fonts, character styles, etc.

Styles of EDIT windows -- See the online help on edit styles

The EDIT1.CPP Example -- 



Displays a multiline edit control box inside client area 
     User can enter/delete text in the edit control & scrolling is built in
User clicks "Get Text" menu itemcontents appear in main window

EDIT class child window is created with CreateWindow() 
     Style:  WS_CHILD | ES_MULTILINE | WS_VISIBLE |   
               ES_AUTOSCROLL | WS_BORDER
     Null ("") title string contains no text initially

Text in an edit control stored as one long character string
     Carriage return <CR> is stored as ASCII code (0x0D,0x0A)
     <CR> inserted automatically if a line doesn’t fit and wraps
     NULL character inserted only at end of last line of text

Program communicates with control by sending/receiving messages

User selects menu item "Get Text" (WM_COMMAND, IDM_GET)
     1. Send edit control EM_GETLINECOUNT msg to get # of lines stored
     2. For each line, send edit control the following messages:
         EM_GETLINE to copy line to buffer
         EM_LINEINDEX to determine character position of start of next line
         EM_LINELENGTH to get length of line
         Use TextOut() to display extracted text at next position on client area

Note result of expose events:
     Text in main window disappears (not handling WM_PAINT)
     Text in Edit control reappears (WM_PAINT handling built in!)