windows程序设计——子视窗控制项

来源:互联网 发布:c语言格式控制符 编辑:程序博客网 时间:2024/06/07 09:44

我们以一个窗口作为消息处理的主体,除了鼠标、键盘、定时器外,窗口中的子窗口发送的消息也可作为一种输入。当子窗口的自身处理消息,在必要时给父窗口发送消息,相当于父窗口的的高阶输入设备,这个称为"子视窗控制项"。常见的有:按钮、核取方块、编辑方块、清单方块、下拉式清单方块、字串标签和卷动列等,windows为这些基本项目都编写了默认的处理代码,我们只需要在主窗口中获取并处理(WM_COMMAND)消息就好了。

按钮是一类子视窗,使用方法如下:

/*----------------------------------------   BTNLOOK.C -- Button Look Program                (c) Charles Petzold, 1998  ----------------------------------------*/#include <windows.h>//定义按钮的风格和文本信息结构,并初始化struct{     int     iStyle ;     TCHAR * szText ;}button[] ={     BS_PUSHBUTTON,      TEXT ("PUSHBUTTON"),      //下压式按钮,也即普通按钮     BS_DEFPUSHBUTTON,   TEXT ("DEFPUSHBUTTON"),   //含自动选中状态的单选按钮,一个对话框中只能指定一个默认按钮     BS_CHECKBOX,        TEXT ("CHECKBOX"),        //复选按钮,不常用     BS_AUTOCHECKBOX,    TEXT ("AUTOCHECKBOX"),    //含自动选中状态的复选按钮     BS_RADIOBUTTON,     TEXT ("RADIOBUTTON"),     //单选按钮,不常用     BS_3STATE,          TEXT ("3STATE"),          //含自动选中状态的三态复选按钮     BS_AUTO3STATE,      TEXT ("AUTO3STATE"),      //三态复选按钮,不常用     BS_GROUPBOX,        TEXT ("GROUPBOX"),        //组框     BS_AUTORADIOBUTTON, TEXT ("AUTORADIO"),       //含自动选中状态的单选按钮     BS_OWNERDRAW,       TEXT ("OWNERDRAW")        //自绘式按钮} ;#define NUM (sizeof button / sizeof button[0])LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;//建立窗口框架int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,                    PSTR szCmdLine, int iCmdShow){     static TCHAR szAppName[] = TEXT ("BtnLook") ;     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) GetStockObject (WHITE_BRUSH) ;     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 ("Button Look"),                          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 ;}//窗口消息处理LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){     static HWND  hwndButton[NUM] ; //子窗口句柄     static RECT  rect ;     static TCHAR szTop[]    = TEXT ("message            wParam       lParam"),                  szUnd[]    = TEXT ("_______            ______       ______"),                  szFormat[] = TEXT ("%-16s%04X-%04X    %04X-%04X"),                  szBuffer[50] ;     static int   cxChar, cyChar ;     HDC          hdc ;     PAINTSTRUCT  ps ;     int          i ;          switch (message)     {     case WM_CREATE : //创建窗口的时候建立子窗体(各种风格的按钮)          // 获取字体大小,函数GetDialogBaseUnits只在对话框中起作用正常窗体还用的GetTextMetrics          cxChar = LOWORD (GetDialogBaseUnits ()) ;          cyChar = HIWORD (GetDialogBaseUnits ()) ;            //创建按钮          for (i = 0 ; i < NUM ; i++)               hwndButton[i] = CreateWindow ( TEXT("button"),  //类别名称                                   button[i].szText, //文字                                   WS_CHILD | WS_VISIBLE | button[i].iStyle, //视窗样式                                   cxChar, cyChar * (1 + 2 * i), //位置                                   20 * cxChar, 7 * cyChar / 4, //宽高                                   hwnd, //父视窗句柄                                   (HMENU) i, //子视窗ID                                   ((LPCREATESTRUCT) lParam)->hInstance, //程序句柄                                   NULL) ;          return 0 ;     case WM_SIZE : //窗口大小改变          //设置文字输出区域          rect.left   = 24 * cxChar ;          rect.top    =  2 * cyChar ;          rect.right  = LOWORD (lParam) ;          rect.bottom = HIWORD (lParam) ;          return 0 ;               case WM_PAINT : //绘图输出消息列表的表头          InvalidateRect (hwnd, &rect, TRUE) ;                    hdc = BeginPaint (hwnd, &ps) ;          SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;          SetBkMode (hdc, TRANSPARENT) ;                    TextOut (hdc, 24 * cxChar, cyChar, szTop, lstrlen (szTop)) ;          TextOut (hdc, 24 * cxChar, cyChar, szUnd, lstrlen (szUnd)) ;                    EndPaint (hwnd, &ps) ;          return 0 ;               case WM_DRAWITEM : //子窗口自绘消息     case WM_COMMAND : //响应子视窗消息          //令窗口在rect中向上滚动cyChar          ScrollWindow (hwnd, 0, -cyChar, &rect, &rect) ;          //获取dc,并选入SYSTEM_FIXED_FONT字体          hdc = GetDC (hwnd) ;          SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;          //在最后一行输出消息类型和参数          TextOut (hdc, 24 * cxChar, cyChar * (rect.bottom / cyChar - 1),                   szBuffer,                   wsprintf (szBuffer, szFormat,                         message == WM_DRAWITEM ? TEXT ("WM_DRAWITEM") : TEXT ("WM_COMMAND"),                         HIWORD (wParam), LOWORD (wParam),                         HIWORD (lParam), LOWORD (lParam))) ;          //释放DC,并刷新界面          ReleaseDC (hwnd, hdc) ;          ValidateRect (hwnd, &rect) ;          break ;               case WM_DESTROY : //销毁窗口          PostQuitMessage (0) ;          return 0 ;     }     return DefWindowProc (hwnd, message, wParam, lParam) ;}
子视窗想父窗口发送WM_COMMAND消息,结果如下:

通知码说明如下:



而父窗口也可以向子窗口发送信息,来控制或获得子窗口,消息如下:


父窗口中通常使用下列方法来控制子窗口:

//通过句柄获取idid = GetWindowLong (hwndChild, GWL_ID) ;id = GetDlgCtrlID (hwndChild) ;//通过id获取句柄hwndChild = GetDlgItem (hwndParent, id) ;//模拟按下按钮和不再按下SendMessage (hwndButton, BM_SETSTATE, 1, 0) ;SendMessage (hwndButton, BM_SETSTATE, 0, 0) ;//发送选中和不再选中信息(单选,复选)SendMessage (hwndButton, BM_SETCHECK, 1, 0) ;SendMessage (hwndButton, BM_SETCHECK, 0, 0) ;//获取是否选中iCheck = (int) SendMessage (hwndButton, BM_GETCHECK, 0, 0) ;//获得和设置子窗口的文本信息SetWindowText (hwnd, pszString) ;iLength = GetWindowText (hwnd, pszBuffer, iMaxLength) ;iLength = GetWindowTextLength (hwnd) ;//设置和获得是否可见ShowWindow (hwndChild, SW_SHOWNORMAL) ;ShowWindow (hwndChild, SW_HIDE) ;IsWindowVisible (hwndChild) ;//设置和获得是否可用EnableWindow (hwndChild, FALSE) ;EnableWindow (hwndChild, TRUE) ;IsWindowEnabled (hwndChild) ;//设置焦点SetFocus (hwnd) ;//设置背景和文字颜色SetBkColor (hdc, GetSysColor (COLOR_BTNFACE)) ;SetTextColor (hdc, GetSysColor (COLOR_WINDOWTEXT)) ;
虽然没什么用处但是可以通过响应WM_CTLCOLORBTN消息来改变背景和文字的颜色,更通常的做法是使用BS_OWNERDRAW风格的按钮在drawitem中自己绘制:

/*---------------------------------------------   OWNDRAW.C -- Owner-Draw Button Demo Program                (c) Charles Petzold, 1998  ---------------------------------------------*/#include <windows.h>//定义两个窗口ID#define ID_SMALLER      1#define ID_LARGER       2//按钮宽高为字体的宽高8倍和4倍#define BTN_WIDTH        (8 * cxChar)#define BTN_HEIGHT       (4 * cyChar)LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;HINSTANCE hInst ;//建立框架int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,                    PSTR szCmdLine, int iCmdShow){     static TCHAR szAppName[] = TEXT ("OwnDraw") ;     MSG          msg ;     HWND         hwnd ;     WNDCLASS     wndclass ;          hInst = hInstance ;          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) GetStockObject (WHITE_BRUSH) ;     wndclass.lpszMenuName  = szAppName ;     wndclass.lpszClassName = szAppName ;          if (!RegisterClass (&wndclass))     {          MessageBox (NULL, TEXT ("This program requires Windows NT!"),                      szAppName, MB_ICONERROR) ;          return 0 ;     }          hwnd = CreateWindow (szAppName, TEXT ("Owner-Draw Button Demo"),                          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 Triangle (HDC hdc, POINT pt[]){     SelectObject (hdc, GetStockObject (BLACK_BRUSH)) ;     Polygon (hdc, pt, 3) ;     SelectObject (hdc, GetStockObject (WHITE_BRUSH)) ;}LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){     static HWND      hwndSmaller, hwndLarger ;     static int       cxClient, cyClient, cxChar, cyChar ;     int              cx, cy ;     LPDRAWITEMSTRUCT pdis ;     POINT            pt[3] ;     RECT             rc ;          switch (message)     {     case WM_CREATE :          //字体宽高          cxChar = LOWORD (GetDialogBaseUnits ()) ;          cyChar = HIWORD (GetDialogBaseUnits ()) ;                    // 创建两个BS_OWNERDRAW风格的按钮          hwndSmaller = CreateWindow (TEXT ("button"), TEXT (""),                                      WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,                                      0, 0, BTN_WIDTH, BTN_HEIGHT,                                      hwnd, (HMENU) ID_SMALLER, hInst, NULL) ;                    hwndLarger  = CreateWindow (TEXT ("button"), TEXT (""),                                      WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,                                      0, 0, BTN_WIDTH, BTN_HEIGHT,                                      hwnd, (HMENU) ID_LARGER, hInst, NULL) ;          return 0 ;               case WM_SIZE :          //获取窗体大小          cxClient = LOWORD (lParam) ;          cyClient = HIWORD (lParam) ;                    // 把按钮设置到最中心          MoveWindow (hwndSmaller, cxClient / 2 - 3 * BTN_WIDTH  / 2,                                   cyClient / 2 -     BTN_HEIGHT / 2,                      BTN_WIDTH, BTN_HEIGHT, TRUE) ;                    MoveWindow (hwndLarger,  cxClient / 2 +     BTN_WIDTH  / 2,                                   cyClient / 2 -     BTN_HEIGHT / 2,                      BTN_WIDTH, BTN_HEIGHT, TRUE) ;          return 0 ;               case WM_COMMAND :          GetWindowRect (hwnd, &rc) ;                    // 判断点击的是那个窗口来决定放大还是缩小          switch (wParam)          {          case ID_SMALLER :               rc.left   += cxClient / 20 ;               rc.right  -= cxClient / 20 ;               rc.top    += cyClient / 20 ;               rc.bottom -= cyClient / 20 ;               break ;                         case ID_LARGER :               rc.left   -= cxClient / 20 ;               rc.right  += cxClient / 20 ;               rc.top    -= cyClient / 20 ;               rc.bottom += cyClient / 20 ;               break ;          }          //改变窗口大小          MoveWindow (hwnd, rc.left, rc.top, rc.right  - rc.left,                            rc.bottom - rc.top, TRUE) ;          return 0 ;               case WM_DRAWITEM : //BS_OWNERDRAW风格的自绘消息          pdis = (LPDRAWITEMSTRUCT) lParam ;                    //填充背景和画边框          FillRect (pdis->hDC, &pdis->rcItem,                    (HBRUSH) GetStockObject (WHITE_BRUSH)) ;                    FrameRect (pdis->hDC, &pdis->rcItem,                     (HBRUSH) GetStockObject (BLACK_BRUSH)) ;                    //获取子窗口的宽度          cx = pdis->rcItem.right  - pdis->rcItem.left ;          cy = pdis->rcItem.bottom - pdis->rcItem.top  ;                    switch (pdis->CtlID)          {          case ID_SMALLER : //若是缩小按钮               pt[0].x = 3 * cx / 8 ;  pt[0].y = 1 * cy / 8 ;               pt[1].x = 5 * cx / 8 ;  pt[1].y = 1 * cy / 8 ;               pt[2].x = 4 * cx / 8 ;  pt[2].y = 3 * cy / 8 ;                              Triangle (pdis->hDC, pt) ;                              pt[0].x = 7 * cx / 8 ;  pt[0].y = 3 * cy / 8 ;               pt[1].x = 7 * cx / 8 ;  pt[1].y = 5 * cy / 8 ;               pt[2].x = 5 * cx / 8 ;  pt[2].y = 4 * cy / 8 ;                              Triangle (pdis->hDC, pt) ;                              pt[0].x = 5 * cx / 8 ;  pt[0].y = 7 * cy / 8 ;               pt[1].x = 3 * cx / 8 ;  pt[1].y = 7 * cy / 8 ;               pt[2].x = 4 * cx / 8 ;  pt[2].y = 5 * cy / 8 ;                              Triangle (pdis->hDC, pt) ;                              pt[0].x = 1 * cx / 8 ;  pt[0].y = 5 * cy / 8 ;               pt[1].x = 1 * cx / 8 ;  pt[1].y = 3 * cy / 8 ;               pt[2].x = 3 * cx / 8 ;  pt[2].y = 4 * cy / 8 ;                              Triangle (pdis->hDC, pt) ;               break ;                         case ID_LARGER : //若是放大按钮               pt[0].x = 5 * cx / 8 ;  pt[0].y = 3 * cy / 8 ;               pt[1].x = 3 * cx / 8 ;  pt[1].y = 3 * cy / 8 ;               pt[2].x = 4 * cx / 8 ;  pt[2].y = 1 * cy / 8 ;                              Triangle (pdis->hDC, pt) ;                              pt[0].x = 5 * cx / 8 ;  pt[0].y = 5 * cy / 8 ;               pt[1].x = 5 * cx / 8 ;  pt[1].y = 3 * cy / 8 ;               pt[2].x = 7 * cx / 8 ;  pt[2].y = 4 * cy / 8 ;                              Triangle (pdis->hDC, pt) ;                              pt[0].x = 3 * cx / 8 ;  pt[0].y = 5 * cy / 8 ;               pt[1].x = 5 * cx / 8 ;  pt[1].y = 5 * cy / 8 ;               pt[2].x = 4 * cx / 8 ;  pt[2].y = 7 * cy / 8 ;                              Triangle (pdis->hDC, pt) ;                              pt[0].x = 3 * cx / 8 ;  pt[0].y = 3 * cy / 8 ;               pt[1].x = 3 * cx / 8 ;  pt[1].y = 5 * cy / 8 ;               pt[2].x = 1 * cx / 8 ;  pt[2].y = 4 * cy / 8 ;                              Triangle (pdis->hDC, pt) ;               break ;          }                    // Invert the rectangle if the button is selected          //判断是否按下,若按下则整个按钮设为反色          if (pdis->itemState & ODS_SELECTED)               InvertRect (pdis->hDC, &pdis->rcItem) ;                    // Draw a focus rectangle if the button has the focus          // 判断是否有焦点,若有焦点则画焦点矩形          if (pdis->itemState & ODS_FOCUS)          {               pdis->rcItem.left   += cx / 16 ;               pdis->rcItem.top    += cy / 16 ;               pdis->rcItem.right  -= cx / 16 ;               pdis->rcItem.bottom -= cy / 16 ;                              DrawFocusRect (pdis->hDC, &pdis->rcItem) ;          }          return 0 ;               case WM_DESTROY :          PostQuitMessage (0) ;          return 0 ;     }     return DefWindowProc (hwnd, message, wParam, lParam) ;}
除了自绘还可以通过SetWindowLong函数来子类化对象:

/*----------------------------------------   COLORS1.C -- Colors Using Scroll Bars                (c) Charles Petzold, 1998  ----------------------------------------*/#include <windows.h>//声明窗口处理函数和滚动条消息的处理函数LRESULT CALLBACK WndProc    (HWND, UINT, WPARAM, LPARAM) ;LRESULT CALLBACK ScrollProc (HWND, UINT, WPARAM, LPARAM) ;//被设为焦点的子窗id,和原先的滚动条回调函数int     idFocus ;WNDPROC OldScroll[3] ;//建立框架int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,                    PSTR szCmdLine, int iCmdShow){     static TCHAR szAppName[] = TEXT ("Colors1") ;     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 = CreateSolidBrush (0) ; //背景为白色     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 ("Color Scroll"),                          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 ;}LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){     static COLORREF crPrim[3] = { RGB (255, 0, 0), RGB (0, 255, 0),                                   RGB (0, 0, 255) } ; //三原色     static HBRUSH  hBrush[3], hBrushStatic ; //三个画刷     static HWND    hwndScroll[3], hwndLabel[3], hwndValue[3], hwndRect ; //滚动条,title,值,方块的子窗口句柄     static int     color[3], cyChar ;     static RECT    rcColor ;     static TCHAR * szColorLabel[] = { TEXT ("Red"), TEXT ("Green"),                                        TEXT ("Blue") } ;     HINSTANCE      hInstance ;     int            i, cxClient, cyClient ;     TCHAR          szBuffer[10] ;          switch (message)     {     case WM_CREATE : //创建窗口          hInstance = (HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE) ;                    // Create the white-rectangle window against which the           // scroll bars will be positioned. The child window ID is 9.  //创建一个SS_WHITERECT空白的static子窗口          hwndRect = CreateWindow (TEXT ("static"), NULL,                                   WS_CHILD | WS_VISIBLE | SS_WHITERECT,                                   0, 0, 0, 0,                                   hwnd, (HMENU) 9, hInstance, NULL) ;                    for (i = 0 ; i < 3 ; i++)          {               // The three scroll bars have IDs 0, 1, and 2, with               // scroll bar ranges from 0 through 255.               //创建三个SBS_VERT竖立的滚动条               hwndScroll[i] = CreateWindow (TEXT ("scrollbar"), NULL,                                             WS_CHILD | WS_VISIBLE |                                              WS_TABSTOP | SBS_VERT,                                             0, 0, 0, 0,                                              hwnd, (HMENU) i, hInstance, NULL) ;               //设置范围和初始值               SetScrollRange (hwndScroll[i], SB_CTL, 0, 255, FALSE) ;               SetScrollPos   (hwndScroll[i], SB_CTL, 0, FALSE) ;                              // The three color-name labels have IDs 3, 4, and 5,                // and text strings "Red", "Green", and "Blue".               //创建三个static子控件作为说明               hwndLabel [i] = CreateWindow (TEXT ("static"), szColorLabel[i],                                             WS_CHILD | WS_VISIBLE | SS_CENTER,                                             0, 0, 0, 0,                                              hwnd, (HMENU) (i + 3),                                              hInstance, NULL) ;                              // The three color-value text fields have IDs 6, 7,                // and 8, and initial text strings of "0".               //创建三个static显示各自滚动条所表示的RGB值               hwndValue [i] = CreateWindow (TEXT ("static"), TEXT ("0"),                                             WS_CHILD | WS_VISIBLE | SS_CENTER,                                             0, 0, 0, 0,                                             hwnd, (HMENU) (i + 6),                                              hInstance, NULL) ;               //将滚动条的处理函数设置为ScrollProc,并将原先的处理函数保存到OldScroll中               OldScroll[i] = (WNDPROC) SetWindowLong (hwndScroll[i],                                              GWL_WNDPROC, (LONG) ScrollProc) ;               //创建三个原色的画刷               hBrush[i] = CreateSolidBrush (crPrim[i]) ;          }          //创建画刷          hBrushStatic = CreateSolidBrush (                              GetSysColor (COLOR_BTNHIGHLIGHT)) ;          //字体高度          cyChar = HIWORD (GetDialogBaseUnits ()) ;          return 0 ;               case WM_SIZE : //窗口大小改变时重设子控件位置          cxClient = LOWORD (lParam) ;          cyClient = HIWORD (lParam) ;                    SetRect (&rcColor, cxClient / 2, 0, cxClient, cyClient) ;                    MoveWindow (hwndRect, 0, 0, cxClient / 2, cyClient, TRUE) ;                    for (i = 0 ; i < 3 ; i++)          {               MoveWindow (hwndScroll[i],                           (2 * i + 1) * cxClient / 14, 2 * cyChar,                           cxClient / 14, cyClient - 4 * cyChar, TRUE) ;                              MoveWindow (hwndLabel[i],                           (4 * i + 1) * cxClient / 28, cyChar / 2,                           cxClient / 7, cyChar, TRUE) ;                              MoveWindow (hwndValue[i],                           (4 * i + 1) * cxClient / 28,                            cyClient - 3 * cyChar / 2,                           cxClient / 7, cyChar, TRUE) ;          }          SetFocus (hwnd) ;          return 0 ;               case WM_SETFOCUS ://将焦点设置为某个滚动条          SetFocus (hwndScroll[idFocus]) ;          return 0 ;               case WM_VSCROLL : //当滚动条滚动时          //获取子控件id          i = GetWindowLong ((HWND) lParam, GWL_ID) ;          //计算滚动条的值          switch (LOWORD (wParam))          {          case SB_PAGEDOWN :               color[i] += 15 ;                                             // fall through          case SB_LINEDOWN :               color[i] = min (255, color[i] + 1) ;               break ;                         case SB_PAGEUP :               color[i] -= 15 ;                                             // fall through          case SB_LINEUP :               color[i] = max (0, color[i] - 1) ;               break ;                         case SB_TOP :               color[i] = 0 ;               break ;                         case SB_BOTTOM :               color[i] = 255 ;               break ;                         case SB_THUMBPOSITION :          case SB_THUMBTRACK :               color[i] = HIWORD (wParam) ;               break ;                         default :               break ;          }          //设置滚动条位置,并设置static的文本信息          SetScrollPos  (hwndScroll[i], SB_CTL, color[i], TRUE) ;          wsprintf (szBuffer, TEXT ("%i"), color[i]) ;          SetWindowText (hwndValue[i], szBuffer) ;          //重设方块的背景画刷          DeleteObject ((HBRUSH)                SetClassLong (hwnd, GCL_HBRBACKGROUND, (LONG)                     CreateSolidBrush (RGB (color[0], color[1], color[2])))) ;                    InvalidateRect (hwnd, &rcColor, TRUE) ;          return 0 ;               case WM_CTLCOLORSCROLLBAR : //画滚动条时返回滚动条的背景画刷          i = GetWindowLong ((HWND) lParam, GWL_ID) ;          return (LRESULT) hBrush[i] ;                    case WM_CTLCOLORSTATIC : //标题和值static控件的文本和背景颜色          i = GetWindowLong ((HWND) lParam, GWL_ID) ;                         if (i >= 3 && i <= 8)    // static text controls          {               SetTextColor ((HDC) wParam, crPrim[i % 3]) ;               SetBkColor ((HDC) wParam, GetSysColor (COLOR_BTNHIGHLIGHT));               return (LRESULT) hBrushStatic ;          }          break ;                    case WM_SYSCOLORCHANGE : //系统颜色更改时          DeleteObject (hBrushStatic) ;          hBrushStatic = CreateSolidBrush (GetSysColor (COLOR_BTNHIGHLIGHT)) ;          return 0 ;                    case WM_DESTROY : //窗口销毁时清理创建的object          DeleteObject ((HBRUSH)               SetClassLong (hwnd, GCL_HBRBACKGROUND, (LONG)                     GetStockObject (WHITE_BRUSH))) ;                         for (i = 0 ; i < 3 ; i++)               DeleteObject (hBrush[i]) ;                         DeleteObject (hBrushStatic) ;          PostQuitMessage (0) ;          return 0 ;     }     return DefWindowProc (hwnd, message, wParam, lParam) ;}     LRESULT CALLBACK ScrollProc (HWND hwnd, UINT message,                              WPARAM wParam, LPARAM lParam){     int id = GetWindowLong (hwnd, GWL_ID) ;     //通过键盘来改变焦点     switch (message)     {     case WM_KEYDOWN :          if (wParam == VK_TAB)               SetFocus (GetDlgItem (GetParent (hwnd),                     (id + (GetKeyState (VK_SHIFT) < 0 ? 2 : 1)) % 3)) ;          break ;                    case WM_SETFOCUS :          idFocus = id ;          break ;     }     return CallWindowProc (OldScroll[id], hwnd, message, wParam, lParam) ;}
与static子窗口不同,edit是可以让用户编辑文本信息的控件。edit给父窗口的控件发送的消息说明如下:

而父窗口通过如下接口控制edit:

//剪切,复制,删除,黏贴SendMessage (hwndEdit, WM_CUT, 0, 0) ;SendMessage (hwndEdit, WM_COPY, 0, 0) ;SendMessage (hwndEdit, WM_CLEAR, 0, 0) ;SendMessage (hwndEdit, WM_PASTE, 0, 0) ;//获取和设置选择区域SendMessage (hwndEdit, EM_GETSEL, (WPARAM) &iStart, (LPARAM) &iEnd) ;SendMessage (hwndEdit, EM_SETSEL, iStart, iEnd) ;//替换文字SendMessage (hwndEdit, EM_REPLACESEL, 0, (LPARAM) szString) ;//取得行数iCount = SendMessage (hwndEdit, EM_GETLINECOUNT, 0, 0) ;//取得光标对于行头的编译量iOffset = SendMessage (hwndEdit, EM_LINEINDEX, iLine, 0) ;//取得当前行的长度iLength = SendMessage (hwndEdit, EM_LINELENGTH, iLine, 0) ;//取得获取当前行到缓冲区iLength = SendMessage (hwndEdit, EM_GETLINE, iLine, (LPARAM) szBuffer) ;
listbox也是一个常用的控件:

/*----------------------------------------   ENVIRON.C -- Environment List Box                (c) Charles Petzold, 1998  ----------------------------------------*/#include <windows.h>#define ID_LIST     1#define ID_TEXT     2LRESULT 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 ;}//填充listboxvoid 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.               // 添加到listbox中               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) ;          //填充listbox          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) ;}

原创粉丝点击