win32子窗口和控件

WINDOWS 提供了几个预定义的窗口类以方便我们的使用。大多数时间内,我们把它们用在对话框中,所以我们一般就它们叫做子窗口控件。子窗口控件会自己处理消息,并在自己状态发生改变时通知父窗口。这样就大大地减轻了我们的编程工作,所以我们应尽可能地利用它们。本课中我们把这些控件放在窗口中以简化程序,但是大多数时间内子窗口控件都是放在对话框中的。我们示例中演示的子窗口控件包括:按钮、下拉菜单、检查框、单选按钮、编辑框等。使用子窗口控件时,先调用 CreateWindow 或 CreateWindowEx。在这里由于WINDOWS 已经注册了这些子控件,所以无须我们再注册。当然我们不能改变它们的类名称。譬如:如果您想产生一个按钮,在调用上述两个函数时就必须指定类名为"button"。其他必须指定的参数还有父窗口的句柄和将要产生的子控件的ID号。子控件的ID号是用来标识子控件的,故也必须是唯一 的。子控件产生后,当其状态改变时将会向父窗口发送消息。一般我们应在父窗口的WM_CREATE消息中产生字控件。子控件向父窗口发送的消息是 WM_COMMAND,并在传递的参数wPara的底位中包括控件的ID号,消息号在wParam的高位,lParam中则包括了子控件的窗口的句柄。各类控件有不同的消息代码集,详情请参见WIN32 API参考手册。父窗口也可以通过调用函数SendMessage向子控件发送消息,其中第一个参数是子控件的窗口句柄,第二个参数是要发送的消息号,附加的参数可以在wParam和lParam中传递,其实只要知道了某个窗口的句柄就可以用该函数向其发送相关消息。所以产生了子窗口后必须处理 WM_COMMAND消息以便可以接收到子控件的消息。
取父窗口的窗口句柄:
hwndParent = GetParent (hwnd) ;
发送消息:
SendMessage (hwndParent, message, wParam, lParam) ;
预定义的控件有:
按钮、复选框、编辑方块、清单方块、下拉式清单方块、静态字符串标签和滚动条。
当使用预定义的控件时,不必为其注册窗口类,窗口类已经存在于Windows中,并有一个预先定义的名字。
您只需在CreateWindow()的参数中指出窗口类名字。CreateWindow()的窗口样式参数准确地定义了子窗口
控件的外形和功能。Windows内建了这些控件的窗口消息处理程序。
========================================


按钮控件 


创建子窗口时指定窗口类为"button".
显示窗口的CreateWindow参数如下:
Class name(类别名称)  TEXT ("button")
Window text(窗口文字)  一个c字符串szText
Window style(窗口样式)  WS_CHILD | WS_VISIBLE | 按钮样式(下边有说明)
x position(x位置)
y position(y位置)
Width(宽度)
Height(高度)
Parent window(父窗口)
Child window ID(子窗口ID) 要转换为HMENU类型.如(HMENU) i  
Instance handle(执行实体句柄) 执行实例句柄
Extra parameters(附加参数)   NULL
其中的按钮样式为:
BS_PUSHBUTTON
BS_DEFPUSHBUTTON
BS_CHECKBOX   (带有复选框.复选框的状态要手动发送BM_SETCHECK消息设置)
BS_AUTOCHECKBOX  (带有复选框.复选框的状态自动设置)
BS_RADIOBUTTON  (带单选按钮.其状态要手动发送BM_SETCHECK消息设置)
BS_3STATE
BS_AUTO3STATE
BS_GROUPBOX  (分组方块. 它只是一个标题框. 不处理输入.)
BS_AUTORADIOBUTTON
BS_OWNERDRAW
按钮会向父窗口发送WM_COMMAND消息.参数:
LOWORD(wParam)  为子窗口ID.
HIWORD(wParam)   为通知码.
lParam   为子窗口句柄.
通知码HIWORD(wParam)有:
BN_CLICKED
BN_PAINT
BN_HILITE or BN_PUSHED
BN_UNHILITE or BN_UNPUSHED
BN_DISABLE
BN_DOUBLECLICKED or BN_DBLCLK
BN_SETFOCUS
BN_KILLFOCUS
父窗口也可以向按钮发送消息.
BM_GETCHECK (复选框的选定标记)
BM_SETCHECK
BM_GETSTATE ("正常状态" 还是"按下状态" )
BM_SETSTATE
BM_SETSTYLE (改变按钮样式)
BM_CLICK
BM_GETIMAGE
BM_SETIMAGE
要得到控件ID用
GetDlgCtrlId(hwndChild);
要得到控件的子窗口句柄用
GetDlgItem(hwndParent, id);
 
改变按钮的文字用
SetWindowText (hwnd, pszString) ;
取按钮的当前文字用
iLength = GetWindowText (hwnd, pszBuffer, iMaxLength) ;
======================================
显示/隐藏子窗口
如果子窗口的窗口类的样式中没有WS_VISIBLE. 则在没有呼叫ShowWindow之前不会显示窗口.
显示子窗口用:
ShowWindow (hwndChild, SW_SHOWNORMAL) ;
隐藏子窗口用:
ShowWindow (hwndChild, SW_HIDE) ;
查看子窗口是否可见用:
IsWindowVisible (hwndChild) ;
不可用/启用 子窗口
要使按钮不可用(文字变为灰色).用:
EnableWindow (hwndChild, FALSE) ;
恢复为可用:
EnableWindow (hwndChild, TRUE) ;
判断是否被启用:
IsWindowEnabled (hwndChild) ;
输入焦点
用户使用按钮时.按钮获得输入焦点而其父窗口失去输入焦点.这时父窗口先收到WM_KILLFOCUS消
息(wParam参数为获得输入焦点的窗口的句柄).然后获得输入焦点的窗口(按钮子窗口)收到一个WM
_SETFOCUS消息(wParam参数为失去输入焦点的窗口的句柄).
控件与颜色
系统颜色
Windows保留了29种系统颜色以供各种显示使用(例如:菜单颜色.菜单文字颜色.窗口颜色等等)。您可
以使用GetSysColor和SetSysColors来获得和设定这些颜色。设定的系统颜色只在目前Windows对
话过程中有效。
要在按钮中显示图标或位图,您可以用BS_ICON或BS_BITMAP样式,并用BM_SETIMAGE消息设定位图。
对于BS_OWNERDRAW样式的按钮,它允许完全自由地绘制按钮。
====================================

 

静态控件

 
创建子窗口时指定窗口类为"static".它既不接收鼠标或键盘输入,也不向父窗口发送WM_COMMAND消息。
设置静态控件的文字用SetWindowText.
================================


滚动条控件 
创建子窗口时指定窗口类为"scrollbar".
它不向父窗口发送WM_COMMAND消息,而是像窗口滚动条那样发送WM_VSCROLL和WM_HSCROLL消息。
可以通过lParam参数来区分窗口滚动条与滚动条控件。对子窗口滚动条其值为0,对于滚动条控件其值为滚动
条子窗口的句柄。wParam对窗口滚动条和滚动条控件来说含义相同。
设置滚动条控件用的函数和设置窗口滚动条一样:
SetScrollRange (hwndScroll, SB_CTL, iMin, iMax, bRedraw) ;
SetScrollPos (hwndScroll, SB_CTL, iPos, bRedraw) ;
SetScrollInfo (hwndScroll, SB_CTL, &si, bRedraw) ;
区别是设置滚动条控件时.第一个参数是控件子窗口句柄而不是父窗口句柄.第二个参数是SB_CTL而不是
SB_VERT或SB_HORZ.
===========================
为控件指定窗口函数
控件的窗口函数是windows内部的. 但可以用GWL_WNDPROC做参数通过GetWindowLong函数得到它
的函数地址. 而且可以用SetWindowLong给它重新指定一个新的窗口函数(新的函数也要是callback函数).如:
OldScroll = (WNDPROC) SetWindowLong (hwndScroll, GWL_WNDPROC,
         (LONG) ScrollProc)) ; //返回值是原来的窗口函数的地址.
在需要用Tab键在控件之间切换输入焦点时. 由于控件获得输入焦点后所有的键盘消息都发送给控件的窗口
函数了.而控件原来的窗口函数并不处理Tab键按下的消息.这时就可以用上边的方法给控件重新设定一个窗
口消息处理函数并在其中处理Tab键.最后再在新的窗口函数中呼叫原来的窗口函数处理其它消息:
return CallWindowProc (OldScroll, hwnd, message, wParam,lParam) ;
这样就可以处理Tab键了.
就像可以通过SetWindowLong给窗口重新设置窗口函数一样.可以用SetClassLong来设置某个窗口的窗
口类的一些东西.例如下边重新设置窗口类的画刷:
 SetClassLong (hwnd, GCL_HBRBACKGROUND,
      (LONG)CreateSolidBrush (RGB (color[0], color[1], color[2])));
===============================


编辑控件 
创建子窗口时用"edit".如:
hwndEdit = CreateWindow (TEXT ("edit"), NULL,       
               WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL |       
               WS_BORDER | ES_LEFT | ES_MULTILINE |       
               ES_AUTOHSCROLL | ES_AUTOVSCROLL,       
               0, 0, 0, 0, hwnd, (HMENU) ID_EDIT,       
              ((LPCREATESTRUCT) lParam) -> hInstance, NULL) ;
编辑控件的样式:
文字对齐: ES_LEFT、ES_RIGHT和ES_CENTER
多行: ES_MULTILINE (缺省为单行)
在单行样式中.要文字水平卷动: ES_AUTOHSCROLL
在多行样式中.要文字水平卷动(不是出现滚动条)(这阻止了自动换行): ES_AUTOHSCROLL
在多行样式中.要文字垂直卷动(不是出现滚动条): ES_AUTOVSCROLL
在多行样式中.要显示滚动条用WS_HSCROLL和WS_VSCROLL
编辑控件缺省时没有边框.要显示边框用 WS_BORDER
选择编辑控件的文字时.文字反白显示.但编辑控件失去焦点后文字将不再加亮显示.要使失去焦点后
选择的文字仍然加亮显示用: ES_NOHIDESEL
编辑控件给父窗口消息处理程序发送WM_COMMAND消息.消息参数为
LOWORD (wParam)     子窗口ID
HIWORD (wParam)      通知码
lParam              子窗口句柄
其中通知码为:
EN_SETFOCUS        编辑控件已经获得输入焦点
EN_KILLFOCUS       编辑控件已经失去输入焦点
EN_CHANGE          编辑控件的内容将改变
EN_UPDATE          编辑控件的内容已经改变
EN_ERRSPACE        编辑控件执行已经超出中间
EN_MAXTEXT         编辑控件在插入时执行超出空间
EN_HSCROLL         编辑控件的水平滚动条已经被按下
EN_VSCROLL         编辑控件的垂直滚动条已经被按下
要处理tab键切换输入焦点或处理Enter键. 可以给它重新指定一个窗口函数并在其中拦截.
要在编辑区插入文字用:
GetWindowTextLength
GetWindowText
SetWindowText
给编辑控件发送消息:
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) ;
//取得目前选择的起始位置和末尾位置.(末尾位置是选择的最后一个文字的位置加1)
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) ;
//对任何特定的行(从0行开始),您可以取得距离编辑缓冲区文字开头的偏移量.
//iLine为-1时返回光标所在行的偏移量.
iLength = SendMessage (hwndEdit, EM_LINELENGTH, iLine, 0) ;
//取得第iLine行的长度
iLength = SendMessage (hwndEdit, EM_GETLINE, iLine, (LPARAM) szBuffer) ;
//将第iLine行复制到缓冲区szBuffer中
==========================


列表控件 
创建列表子窗口时,用"listbox"作为窗口类.
列表样式:
LBS_NOTIFY   允许父窗口接收列表的WM_COMMAND消息(缺省时不向父窗口发送WM_COMMAND消息)
LBS_SORT    对列表中的项目排序
LBS_MULTIPLESEL   列表是多选的(缺省时为单选)
LBS_NOREDRAW    防止在向列表增加项目时自动重画列表
样式LBS_STANDARD包含了最常用的样式:(LBS_NOTIFY | LBS_SORT | WS_VSCROLL | WS_BORDER)
将字符串放入列表:
SendMessage (hwndList, LB_INSERTSTRING, i, (LPARAM) szString) ;
第一个参数是列表控件的窗口句柄.
第二个参数LB_INSERTSTRING表示要插入一个项目.
第三个参数表示要插入的位置.(位置值从0开始.0表示最上边第一个位置.-1表示插入最后)
第四个参数是要插入的字符串(字符串以0结尾).
函数返回0表示正常完成.
如果列表控件包含LBS_SORT样式.则插入一个字符串时可以将第2个参数设置为LB_ADDSTRING.这样
字符串就会被自动插入到一个位置.如:
SendMessage (hwndList, LB_ADDSTRING, 0, (LPARAM) szString) ;
要在列表控件中删除一个字符串.只要指定第2个参数为LB_DELETESTRING. 例如:
SendMessage (hwndList, LB_DELETESTRING, iIndex, 0) ;
要删除所有列表中的内容.则指定第2个参数为LB_RESETCONTENT. 如:
SendMessage (hwndList, LB_RESETCONTENT, 0, 0) ;
在向列表增加或删除字符串时.列表控件会自动被它的窗口函数重画.如果你有许多字符串需要增加.
你可能希望在所有字符串增加完成前暂时阻止列表的自动重画.这要:
SendMessage (hwndList, WM_SETREDRAW, FALSE, 0) ;
在增加完成后再恢复列表控件的自动重画就可以了:
SendMessage (hwndList, WM_SETREDRAW, TRUE, 0) ;
要取得现在列表控件中的项目数用:
iCount = SendMessage (hwndList, LB_GETCOUNT, 0, 0) ;
在单选列表控件中.要选择一个项目(它会被加亮显示)用:
SendMessage (hwndList, LB_SETCURSEL, iIndex, 0) ;
//iIndex参数为要选择第几个项目.指定为-1表示取消所有选择.
在单选列表控件中.也可以根据一个字符串的第一个字母来选择一个项目.如:
iIndex = SendMessage (hwndList, LB_SELECTSTRING, iIndex,
                     (LPARAM) szSearchString) ;
表示从第iIndex位置开始搜索.如果哪个项目的开始字母与 szSearchString相同.则选择该项目.并
返回该项目的位置. 没有匹配的项目时返回-1.
在单选列表控件中.要取得当前选择项目的索引.用:
iIndex = SendMessage (hwndList, LB_GETCURSEL, 0, 0) ;
如果没有被选项目.函数返回LB_ERR(值为-1).
在单选列表控件中.将某个项目复制到一个字符缓冲区.用:
iLength = SendMessage (hwndList, LB_GETTEXT, iIndex, (LPARAM) szBuffer) ;
则将列表控件中索引为iIndex的项目复制到szBuffer. 并返回字符串的长度iLength.
(为了使szBuffer缓冲区足够大.你可以用LB_GETTEXTLEN做参数先取得该项目的字符串长度.)
对于多选列表控件:
可以使用LB_SETSEL来设定某特定项目的选择状态(不会影响其他项目的选择状态):
SendMessage (hwndList, LB_SETSEL, wParam, iIndex) ;
参数wParam为0时.取消选择. 为-1时.选择/取消所有项目. 为其它值时. 选择第iIndex个项目.
查看某项目的选择状态:
iSelect = SendMessage (hwndList, LB_GETSEL, iIndex, 0) ;
//项目被选择时返回非0. 否则返回0.
要使清单控件获得输入焦点用:
SetFocus (hwndList) ;
清单控件发送给父窗口的消息是WM_COMMAND. 参数如下:
LOWORD (wParam) 子窗口ID
HIWORD (wParam) 通知码
lParam 子窗口句柄
 
其中通知码的值如下:
LBN_ERRSPACE -2  表示已经超出执行空间
LBN_SELCHANGE 1  表示目前选择已经被改变
LBN_DBLCLK 2     说明某项目已经被鼠标双击
LBN_SELCANCEL 3
LBN_SETFOCUS 4
LBN_KILLFOCUS 5
 
只有清单窗口样式包括LBS_NOTIFY时,清单控件才会向父窗口发送LBN_SELCHANGE和LBN_DBLCLK。
文件列表
要将文件目录列表填入清单列表.用:
SendMessage (hwndList, LB_DIR, iAttr, (LPARAM) szFileSpec) ;
//iAttr参数是文件属性代码,其低字节是文件属性代码:
iAttr    值 属性
DDL_READWRITE  0x0000  普通文件
DDL_READONLY  0x0001 只读文件 
DDL_HIDDEN  0x0002 隐藏文件 
DDL_SYSTEM  0x0004 系统文件 
DDL_DIRECTORY  0x0010 子目录 
DDL_ARCHIVE  0x0020 归档位设立的档案
//高字节提供了一些对所要求项目的附加控制:
iAttr  值 属性 
DDL_DRIVES 0x4000 包括磁盘驱动器句柄 
DDL_EXCLUSIVE 0x8000 互斥搜索

 

ComboBox

如下图所示,显示了三种不同风格的Combo Box样式。当然,现在这样看不出第一种与第三种之间的区别,但是第二种与其他两种的区别是明显的,第二种的列表框始终是出于现实状态的。

Combo Box: 
一个下拉组合框控件拥有文本框及列表框的功能。
它允许用户通过输入文本到下拉组合框中或者从
下拉列表中选择相应的条目。
Combo Box拥有三种风格
Drop-down combo box   可输入文本或在下拉列表中选择,当鼠标点击右方的下拉箭头时显示下拉列表框  (CBS_DROPDOWN)
Simple combo box      可输入文本或在列表中选择,列表框一直显示  (CBS_SIMPLE)
Drop-down list box      只能在下拉列表中选择,当鼠标点击右方的下拉箭头时显示下拉列表框  (CBS_DROPDOWNLIST)

 

        有了直观的感受,现在来就来看如何实现它。其实它的实现并不是很困难,通过一个CreateWindow函数即可实现,如果需要对它的功能进行添加或者是美化外观之类的,可能就需要对它的窗口过程进行重写了(只是推测,并未实现,有兴趣的话可以动手试一试),在CreateWindow之后调用SetWindowLong设置其窗口过程处理函数。说了这么多,先来看看代码吧!

 

  1. #include <WINDOWS.H>  
  2. #include <COMMCTRL.H>  
  3. #pragma comment(lib, "comctl32.lib")  
  4. #define DROP_DOWN_COMBO     1  
  5. #define SIMPLE_COMBO        2  
  6. #define DROP_DOWN_LIST      3  
  7. LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);  
  8. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)  
  9. {  
  10.     WNDCLASS wc;  
  11.     HWND hwnd;  
  12.     HWND drop_down_hwnd, simple_combo, drop_down_list;  
  13.     MSG msg;  
  14.     int i;  
  15.       
  16.     wc.cbClsExtra = 0;  
  17.     wc.cbWndExtra = 0;  
  18.     wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);  
  19.     wc.hCursor = LoadCursor(hInstance, IDC_ARROW);  
  20.     wc.hIcon = LoadIcon(hInstance, IDI_APPLICATION);  
  21.     wc.hInstance = hInstance;  
  22.     wc.lpfnWndProc = WndProc;  
  23.     wc.lpszClassName = TEXT("TEST");  
  24.     wc.lpszMenuName = NULL;  
  25.     wc.style = CS_HREDRAW | CS_VREDRAW;  
  26.       
  27.     if (!RegisterClass(&wc))  
  28.     {  
  29.         MessageBox(NULL, TEXT("Register class error!"), TEXT("ERROR"), MB_ICONERROR | MB_OK);  
  30.         return 0;  
  31.     }  
  32.     hwnd = CreateWindow(TEXT("TEST"), TEXT("TEST"), WS_OVERLAPPEDWINDOW, 10, 10, 300, 400, NULL,  
  33.         NULL, hInstance, NULL);  
  34.     if (hwnd == NULL)  
  35.     {  
  36.         MessageBox(NULL, TEXT("Create window error!"), TEXT("ERROR"), MB_ICONERROR | MB_OK);  
  37.         return 0;  
  38.     }  
  39.     /* Create drop-down combo box */  
  40.     drop_down_hwnd = CreateWindow("combobox", NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | CBS_DROPDOWN | CBS_HASSTRINGS,  
  41.         10, 20, 80, 100, hwnd, (HMENU)DROP_DOWN_COMBO, hInstance, NULL);  
  42.     /* Add some text into the drop-down combo box */  
  43.     for (i=0;i<=20;i++)  
  44.     {  
  45.         char temp[10];  
  46.         SendMessage(drop_down_hwnd,CB_ADDSTRING,0,(LPARAM)itoa(i,temp,10));  
  47.     }  
  48.     /* Create simple combo box */  
  49.     simple_combo = CreateWindow("combobox", NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | CBS_SIMPLE | CBS_HASSTRINGS,  
  50.         100, 20, 80, 100, hwnd, (HMENU)SIMPLE_COMBO, hInstance, NULL);  
  51.     /* Add some text into the simple combo box */  
  52.     for (i=0;i<=20;i++)  
  53.     {  
  54.         char temp[10];  
  55.         SendMessage(simple_combo,CB_ADDSTRING,0,(LPARAM)itoa(i,temp,10));  
  56.     }  
  57.     /* Create drop-down list combo box */  
  58.     drop_down_list = CreateWindow("combobox", NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | CBS_DROPDOWNLIST | CBS_HASSTRINGS,  
  59.         190, 20, 80, 100, hwnd, (HMENU)DROP_DOWN_LIST, hInstance, NULL);  
  60.     /* Add some text into the drop-down list combo box */  
  61.     for (i=0;i<=20;i++)  
  62.     {  
  63.         char temp[10];  
  64.         SendMessage(drop_down_list,CB_ADDSTRING,0,(LPARAM)itoa(i,temp,10));  
  65.     }  
  66.     ShowWindow(hwnd, nShowCmd);  
  67.     UpdateWindow(hwnd);  
  68.     while (GetMessage(&msg, NULL, 0, 0))  
  69.     {  
  70.         TranslateMessage(&msg);  
  71.         DispatchMessage(&msg);  
  72.     }  
  73.     return 0;  
  74. }  
  75.   
  76. LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)  
  77. {  
  78.     switch (msg)  
  79.     {  
  80.     case WM_CREATE:  
  81.           
  82.         return 0;  
  83.     case WM_DESTROY:  
  84.         PostQuitMessage(0);  
  85.         return 0;  
  86.     }  
  87.     return DefWindowProc(hwnd, msg, wParam, lParam);  
  88. }  

 

        可以看到在程序的一开始我引入了COMMCTRL.H这个头文件,需要说明一下,在这个头文件中包含了windows的一些通用控件,比如说上面创建的combo box就是其中之一。在创建combo box窗口时,分别用到了CBS_DROPDOWN、CBS_SIMPLE和CBS_DROPDOWNLIST三种风格,接下来就是给控件发送CB_ADDSTRING消息添加条目,对于更多的消息可以在MSDN上面去查看。此外,还有一个当时没注意的问题,把我给困扰了很久,那就是窗口的高度,之前写程序的时候,没有注意这个问题,写出来的控件下拉框始终弹不出来,有种说法是要重写窗口处理函数,在其中处理WM_LBUTTONDOWN消息,并发送CB_SHOWDROPDOWN消息来显示,还需处理CBN_SELCHANGE消息,其实并没有必要。默认的就可以到达那样的效果,如果是下拉列表未弹出来,检查你的窗口高度是否合理。当然,在combo box插入的条目可能会很多,固定的窗口高度并不可行,因为这时只能通过键盘的上下箭头来移动选取,使用起来不是很方便。这时就需要加入垂直滚动条了,在创建时加入WS_VSCROLL即可,这下使用起来就方便多了。

posted @ 2015-12-11 18:58  左昱_leftshine  阅读(1833)  评论(0编辑  收藏  举报