An Introduction to Controls

A control is a child window which is treated as a component of its parent window. A control is "defined" by its window class. Control (window) classes expect their windows to have parents. Win95 predefines a number of window classes that create controls.

Because they're windows, controls are potentially manipulated and queried with messages.

WM_COMMAND

Most controls have the capability of sending a specific set of notifications to their parent windows in the form of WM_COMMAND messages. A control will send WM_COMMAND with its window handle, a control ID, and a notification code.
    An exception is the scroll bar control (class SCROLLBAR) which sends a WM_VSCROLL or WM_HSCROLL message.

A simple scratchpad editor--WINDOW05.ASM

The following code implements a text editor with no file processing.  All we do is add an EDIT control, and resize it when the main window changes size.  Everything else, including the scrolling and the right-click menu, is done by the EDIT control.

If you aren't using the supplied WINMAIN module, you'll need to add a call to TranslateMessage in the message loop.  The window class EDIT requires WM_CHAR messages to work, and TranslateMessage provides it.

        extrn   GetMessage:near,TranslateMessage:near,DispatchMessage:near

        .data
msgbuf MSG      <>

        .code
msg_loop:
        push    large 0         ; uMsgFilterMax
        push    large 0         ; uMsgFilterMin
        push    large 0         ; hWnd (filter), 0 = all windows
        push    offset msgbuf   ; lpMsg
        call    GetMessage      ; returns FALSE if WM_QUIT
        or      eax,eax
        jz      end_loop

        push    offset msgbuf
        call    TranslateMessage

        push    offset msgbuf
        call    DispatchMessage

        jmp     msg_loop

end_loop:
We use the WS_OVERLAPPEDWINDOW style (notice the extra word WINDOW) which is the shorthand for the standard main window style.  This style gives us all the title bar options, and allows resizing by pulling on the main window edges and corners.
    We also set up the CreateWindowEx arguments for the EDIT window.  EDIT is already registered when the program starts.
    .data
wc WNDCLASSEX <size WNDCLASSEX,CS_HREDRAW+CS_VREDRAW,WndProc,0,0, 0, \
                  0,0,COLOR_WINDOW+1, 0,wndclsname,0>
wndmain CREATEARGS <0,wndclsname,caption,WS_OVERLAPPEDWINDOW+WS_VISIBLE,\
                  100,100,200,200, 0,0,0,0>
wndedit CREATEARGS <0,editclsname,0,WS_CHILD+WS_HSCROLL+WS_VSCROLL+\
                  WS_VISIBLE+ES_AUTOHSCROLL+ES_AUTOVSCROLL+ES_MULTILINE,\
                  0,0,0,0, 0,0,0,0>
wndclsname  db 'ScratchPad',0
editclsname db 'edit',0
caption db 'Scratch Pad Editor',0

hEdit dd 0
We process three messages in the main window.  The new message WM_SIZE is sent when the main window is resized.
        extrn   DefWindowProc:near

        .code
WndProc:
        mov     eax,[esp+4+4]           ; message ID
        cmp     eax,WM_CREATE           ; window created
        je      finish_create
        cmp     eax,WM_SIZE             ; about to draw resized window
        je      resizing_window
        cmp     eax,WM_DESTROY          ; about to start window destruction
        je      start_destroy
        jmp     DefWindowProc           ; delegate other message processing
When the main window is created, we create an edit window and make it a child of the main window.  We save the handle of the edit window because we will need it to resize it.
        extrn   CreateWindowEx:near

finish_create:
        mov     eax,[esp+4+0]  ; grab hwnd before ESP changes

        push    esi
        push    edi

        mov     esi,offset wndedit
        mov     [esi].cwargParent,eax    ; make "wndmain" a parent of "edit"
        mov     eax,[wc].wcxInstance
        mov     [esi].cwargInstance,eax  ; set edit instance
        sub     esp,48    ; allocate args
        mov     edi,esp
        mov     ecx,12
        rep movsd
        call    CreateWindowEx
        mov     [hEdit],eax             ; save edit window handle

        pop     edi
        pop     esi

        xor     eax,eax    ; signal a successful CREATE
        ret     16
We didn't add a border to the edit window, so you can't see if the following code resizes the edit window properly.  Add WS_BORDER to the edit window arguments to see the resizing effects.
    We use the client area size supplied by lParam.  This only provides us with 16-bit values, which is adequate for Win95, but not necessarily for NT.  To get the 32-bit values, use GetClientRect.
        extrn   MoveWindow:near

        .code
resizing_window:
        ; grab arguments before ESP changes
        xor     eax,eax
        xor     ecx,ecx
        mov     ax,[esp+4+12+2] ; y, height
        mov     cx,[esp+4+12+0] ; x, width
        push    large 1 ; repaint
        push    eax             ; height
        push    ecx             ; width
        push    large 0 ; y = 0, top left corner of client area
        push    large 0 ; x = 0
        push    [hEdit] ; resize edit window
        call    MoveWindow

        xor     eax,eax
        ret     16