A Simple List Box Application

Now that you know how to create a list box, fill it with text items, receive messages from the list box, and extract strings, it's time to program an application. The ENVIRON program, shown in Figure 6-6, uses a list box in its client area to display the name of your current MS-DOS environment variables (such as PATH, COMSPEC, and PROMPT). As you select a variable, the name and the environment string are displayed across the top of the client area.

ENVIRON.MAK

#-----------------------

# ENVIRON.MAK make file

#-----------------------

environ.exe : environ.obj environ.def

link environ, /align:16, NUL, /nod slibcew libw, environ

rc environ.exe

environ.obj : environ.c

cl -c -Gsw -Ow -W2 -Zp environ.c

ENVIRON.C

/*----------------------------------------

ENVIRON.C -- Environment List Box

(c) Charles Petzold, 1990

----------------------------------------*/

#include <windows.h>

#include <stdlib.h>

#include <string.h>

#define MAXENV 4096

long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;

int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,

LPSTR lpszCmdLine, int nCmdShow)

{

static char szAppName[] = "Environ" ;

HWND hwnd ;

MSG msg ;

WNDCLASS wndclass ;

if (!hPrevInstance)

{

wndclass.style = CS_HREDRAW | CS_VREDRAW ;

wndclass.lpfnWndProc = WndProc ;

wndclass.cbClsExtra = 0 ;

wndclass.cbWndExtra = 0 ;

wndclass.hInstance = hInstance ;

wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;

wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;

wndclass.hbrBackground = COLOR_WINDOW + 1 ;

wndclass.lpszMenuName = NULL ;

wndclass.lpszClassName = szAppName ;

RegisterClass (&wndclass) ;

}

hwnd = CreateWindow (szAppName, "Environment List Box",

WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT, CW_USEDEFAULT,

CW_USEDEFAULT, CW_USEDEFAULT,

NULL, NULL, hInstance, NULL) ;

ShowWindow (hwnd, nCmdShow) ;

UpdateWindow (hwnd) ;

while (GetMessage (&msg, NULL, 0, 0))

{

TranslateMessage (&msg) ;

DispatchMessage (&msg) ;

}

return msg.wParam ;

}

long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)

{

static char szBuffer [MAXENV + 1] ;

static HWND hwndList, hwndText ;

HDC hdc ;

TEXTMETRIC tm ;

WORD n ;

switch (message)

{

case WM_CREATE :

hdc = GetDC (hwnd) ;

GetTextMetrics (hdc, &tm) ;

ReleaseDC (hwnd, hdc) ;

hwndList = CreateWindow ("listbox", NULL,

WS_CHILD | WS_VISIBLE | LBS_STANDARD,

tm.tmAveCharWidth, tm.tmHeight * 3,

tm.tmAveCharWidth * 16 +

GetSystemMetrics (SM_CXVSCROLL),

tm.tmHeight * 5,

hwnd, 1,

GetWindowWord (hwnd, GWW_HINSTANCE), NULL) ;

hwndText = CreateWindow ("static", NULL,

WS_CHILD | WS_VISIBLE | SS_LEFT,

tm.tmAveCharWidth, tm.tmHeight,

tm.tmAveCharWidth * MAXENV, tm.tmHeight,

hwnd, 2,

GetWindowWord (hwnd, GWW_HINSTANCE), NULL) ;

for (n = 0 ; environ[n] ; n++)

{

if (strlen (environ [n]) > MAXENV)

continue ;

*strchr (strcpy (szBuffer, environ [n]), '=') = '\0' ;

SendMessage (hwndList, LB_ADDSTRING, 0,

(LONG) (LPSTR) szBuffer) ;

}

return 0 ;

case WM_SETFOCUS :

SetFocus (hwndList) ;

return 0 ;

case WM_COMMAND :

if (wParam == 1 && HIWORD (lParam) == LBN_SELCHANGE)

{

n = (WORD) SendMessage (hwndList, LB_GETCURSEL, 0, 0L) ;

n = (WORD) SendMessage (hwndList, LB_GETTEXT, n,

(LONG) (LPSTR) szBuffer) ;

strcpy (szBuffer + n + 1, getenv (szBuffer)) ;

*(szBuffer + n) = '=' ;

SetWindowText (hwndText, szBuffer) ;

}

return 0 ;

case WM_DESTROY :

PostQuitMessage (0) ;

return 0 ;

}

return DefWindowProc (hwnd, message, wParam, lParam) ;

}

ENVIRON.DEF

;------------------------------------

; ENVIRON.DEF module definition file

;------------------------------------

NAME ENVIRON

DESCRIPTION 'Environment List Box Program (c) Charles Petzold, 1990'

EXETYPE WINDOWS

STUB 'WINSTUB.EXE'

CODE PRELOAD MOVEABLE DISCARDABLE

DATA PRELOAD MOVEABLE MULTIPLE

HEAPSIZE 1024

STACKSIZE 8192

EXPORTS WndProc

ENVIRON creates two child windows: a list box with the style LBS_STANDARD and a static window with the style SS_LEFT (left-justified text). ENVIRON uses the environ variable (declared external in STDLIB.H) to obtain the list of environment strings, and it uses the message LB_ADDSTRING to direct the list box window procedure to place each string in the list box.

When you run ENVIRON, you can select an environment variable using the mouse or the keyboard. Each time you change the selection, the list box sends a WM_COMMAND message to the parent window, which is WndProc. When WndProc receives a WM_COMMAND message, it checks to see if wParam is 1 (the child ID of the list box) and if the high word of lParam (the notification code) is equal to LBN_SELCHANGE. If so, it obtains the index of the selection using the LB_GETCURSEL message and the text itself—the environment variable name—using LB_GETTEXT. ENVIRON uses the C function getenv to obtain the environment string corresponding to that variable and SetWindowText to pass this string to the static child window control, which displays the text.

Note that ENVIRON cannot use the index returned from LB_GETCURSEL to index the environ variable and obtain the environment string. Because the list box has an LBS_SORT style (included in LBS_STANDARD), the indices no longer match.