六、Windows子窗口控件的清单方块类别—一个简单的清单方块应用
既然您知道了如何建立清单方块,如何使用文字项目填入清单方块,如何接收来自清单方块的控件以及如何取得字符串,现在是到了写一个应用程序的时候了。如程序9-5中所示,ENVIRON程序在显示区域中使用清单方块来显示目前操作系统环境变量(例如PATH和WINDIR)。当您选择一个环境变量时,其内容将显示在显示区域的顶部。
        
ENVIRON.C
        
/*-------------------------------------------------------------------------
        
  ENVIRON.C -- Environment List Box
        
                                 (c) Charles Petzold, 1998
        
---------------------------------------------------------------------------*/
        
#include <windows.h>
        
#define ID_LIST     1
        
#define ID_TEXT     2
        
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
        
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
        
                                                         PSTR szCmdLine, int iCmdShow)
        
{
        
           static TCHAR szAppName[] = TEXT ("Environ") ;
        
           HWND                                 hwnd ;
        
           MSG                                  msg ;
        
           WNDCLASS                      wndclass ;
        
   
        
           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                       = (HBRUSH) (COLOR_WINDOW + 1) ;
        
           wndclass.lpszMenuName                        = NULL ;
        
           wndclass.lpszClassName                       = szAppName ;
        
   
        
           if (!RegisterClass (&wndclass))
        
           {
        
                  MessageBox (  NULL, TEXT ("This program requires Windows NT!"),
        
                                                                        szAppName, MB_ICONERROR) ;
        
                  return 0 ;
        
           }
        
   
        
           hwnd = CreateWindow (szAppName, TEXT ("Environment List Box"),
        
                      WS_OVERLAPPEDWINDOW,
        
                      CW_USEDEFAULT, CW_USEDEFAULT,
        
                      CW_USEDEFAULT, CW_USEDEFAULT,
        
                      NULL, NULL, hInstance, NULL) ;
        
   
        
           ShowWindow (hwnd, iCmdShow) ;
        
          UpdateWindow (hwnd) ;
        
   
        
           while (GetMessage (&msg, NULL, 0, 0))
        
           {
        
                          TranslateMessage (&msg) ;
        
                          DispatchMessage (&msg) ;
        
           }
        
           return msg.wParam ;
        
}
        
void FillListBox (HWND hwndList)
        
{
        
           int     iLength ;
        
           TCHAR * pVarBlock, * pVarBeg, * pVarEnd, * pVarName ;
        
           pVarBlock = GetEnvironmentStrings () ;       // Get pointer to environment block
        
           while (*pVarBlock)
        
           {
        
           if (*pVarBlock != '=')               // Skip variable names beginning with '='
        
           {
        
              pVarBeg = pVarBlock ;     // Beginning of variable name
        
            while (*pVarBlock++ != '=') ; // Scan until '='
        
            pVarEnd = pVarBlock - 1 ;            // Points to '=' sign
        
            iLength = pVarEnd - pVarBeg ; // Length of variable name
        
            // Allocate memory for the variable name and terminating
        
            // zero. Copy the variable name and append a zero.
        
            pVarName = calloc (iLength + 1, sizeof (TCHAR)) ;
        
            CopyMemory (pVarName, pVarBeg, iLength * sizeof (TCHAR)) ;
        
            pVarName[iLength] = '\0' ;
        
            // Put the variable name in the list box and free memory.
        
            SendMessage (hwndList, LB_ADDSTRING, 0, (LPARAM) pVarName) ;
        
                                   free (pVarName) ;
        
            }
        
            while (*pVarBlock++ != '\0') ;       // Scan until terminating zero
        
           }
        
           FreeEnvironmentStrings (pVarBlock) ;
        
}
        
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam)
        
{
        
           static HWND   hwndList, hwndText ;
        
           int                                  iIndex, iLength, cxChar, cyChar ;
        
           TCHAR                         *      pVarName, * pVarValue ;
        
           switch (message)
        
           {
        
           case   WM_CREATE :
        
                  cxChar = LOWORD (GetDialogBaseUnits ()) ;
        
                  cyChar = HIWORD (GetDialogBaseUnits ()) ;
        
                                         // Create listbox and static text windows.
        
                  hwndList = CreateWindow (TEXT ("listbox"), NULL,
        
                          WS_CHILD | WS_VISIBLE | LBS_STANDARD,
        
                        cxChar, cyChar * 3,
        
                          cxChar * 16 + GetSystemMetrics (SM_CXVSCROLL),
        
                          cyChar * 5,
        
                          hwnd, (HMENU) ID_LIST,
        
                         (HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE),
        
                                                                        NULL) ;
        
        
        
                  hwndText = CreateWindow (TEXT ("static"), NULL,
        
                          WS_CHILD | WS_VISIBLE | SS_LEFT,
        
                         cxChar, cyChar,
        
                          GetSystemMetrics (SM_CXSCREEN), cyChar,
        
                          hwnd, (HMENU) ID_TEXT,
        
                          (HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE),
        
                                                                                NULL) ;
        
                  FillListBox (hwndList) ;
        
                  return 0 ;
        
        
        
  case   WM_SETFOCUS :
        
                  SetFocus (hwndList) ;
        
                  return 0 ;
        
           case   WM_COMMAND :
        
                  if (LOWORD (wParam) == ID_LIST && HIWORD (wParam) == LBN_SELCHANGE)
        
                  {
        
                                                         // Get current selection.
        
             iIndex  = SendMessage (hwndList, LB_GETCURSEL, 0, 0) ;
        
              iLength = SendMessage (hwndList, LB_GETTEXTLEN, iIndex, 0) + 1 ;
        
            pVarName = calloc (iLength, sizeof (TCHAR)) ;
        
             SendMessage (hwndList, LB_GETTEXT, iIndex, (LPARAM) pVarName) ;
        
                                                         // Get environment string.
        
              iLength = GetEnvironmentVariable (pVarName, NULL, 0) ;
        
              pVarValue = calloc (iLength, sizeof (TCHAR)) ;
        
              GetEnvironmentVariable (pVarName, pVarValue, iLength) ;
        
                                                         // Show it in window.
        
             
        
              SetWindowText (hwndText, pVarValue) ;
        
             free (pVarName) ;
        
              free (pVarValue) ;
        
                  }
        
                  return 0 ;
        
           case   WM_DESTROY :
        
                  PostQuitMessage (0) ;
        
                  return 0 ;
        
           }
        
           return DefWindowProc (hwnd, message, wParam, lParam) ;
        
}
        
ENVIRON建立两个子窗口:一个是LBS_STANDARD样式的清单方块,另一个是SS_LEFT样式(置左对齐文字)的静态窗口。ENVIRON使用函数GetEnvironmentStrings来获得一个指标,该指标指向存有全部环境变量名及其值的内存区块。ENVIRON用FillListBox函数来分析此内存区块,并使用LB_ADDSTRING消息来指定清单方块窗口消息处理程序将每个字符串放入清单方块中。
当您执行ENVIRON时,可以使用鼠标或者键盘来选择环境变量。每次您改变选择时,清单方块都会给其父窗口WndProc发送一个WM_COMMAND消息。当WndProc收到WM_COMMAND消息时,它就检查wParam的低字组是否为ID_LIST(清单方块的子窗口ID)和wParam的高字组(通知码)是否等于LBN_SELCHANGE。如果是的,那么它就使用LB_GETCURSEL消息来获得选中项目的索引,并使用LB_GETTEXT来获得外部环境变量名的字符串本身。ENVIRON程序使用C语言函数GetEnvironmentVariable来获得与变量相对应的环境字符串,使用SetWindowText将该字符串传递到静态子窗口控件中,这个静态子窗口控件被用来显示文字。
