为啥 SetWindowPos 不改变 ComboBoxEx 下拉高度?

Posted

技术标签:

【中文标题】为啥 SetWindowPos 不改变 ComboBoxEx 下拉高度?【英文标题】:Why SetWindowPos does not change ComboBoxEx dropdown height?为什么 SetWindowPos 不改变 ComboBoxEx 下拉高度? 【发布时间】:2015-09-07 21:19:20 【问题描述】:

我正在使用图像测试 ComboBoxEx 控件。我使用了 microsoft example 没有任何大的变化。它有效,但 comboboxex 下拉列表不显示列表!事实上,SetWindowPos 函数并不会改变 ComboBoxEx 下拉菜单的高度! 我在window7sp1x64 中使用VS2010sp1、release、win32 和Common Control 6.0 pragma。完全显示下拉列表的唯一方法是将 CreateWindowEx 中的 ComboboxEx 高度更改为一个大值! 如何以编程方式更改 ComboBoxEx 下拉列表?

我想创建一个组合框,同时显示文本和图像。我完全使用了以下代码:

HWND *CreateComboBoxEX(HWND hwndParent)

    HWND hwnd;
    INITCOMMONCONTROLSEX icex;

    icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
    icex.dwICC = ICC_USEREX_CLASSES;

    InitCommonControlsEx(&icex);

    hwnd = CreateWindowEx(0, WC_COMBOBOXEX, L"", 
    WS_BORDER | WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST, 0, 0, 200, 40,
    hwndParent, (HMENU)NULL, GetModuleHandle(0), NULL);
    if (hwnd == NULL)
        return(NULL);
    return(hwnd);


BOOL WINAPI AddItems(HWND hwndCB)


//  Declare and init locals.
COMBOBOXEXITEM cbei;
int iCnt;


typedef struct 
    int iImage;
    int iSelectedImage;
    int iIndent;
    LPTSTR pszText;
 ITEMINFO, *PITEMINFO;

ITEMINFO IInf[ ] = 
     0, 3,  0, L"first", 
     1, 4,  1, L"second",
     2, 5,  2, L"third",
     0, 3,  0, L"fourth",
     1, 4,  1, L"fifth",
     2, 5,  2, L"sixth",
     0, 3,  0, L"seventh",
     1, 4,  1, L"eighth",
     2, 5,  2, L"ninth",
     0, 3,  0, L"tenth",
     1, 4,  1, L"eleventh",
     2, 5,  2, L"twelfth",
     0, 3,  0, L"thirteenth",
     1, 4,  1, L"fourteenth",
     2, 5,  2, L"fifteenth"
;

// Set the mask common to all items.
cbei.mask = CBEIF_TEXT | CBEIF_INDENT |
            CBEIF_IMAGE| CBEIF_SELECTEDIMAGE;

for(iCnt=0;iCnt<MAX_ITEMS;iCnt++)
    // Initialize the COMBOBOXEXITEM struct.
    cbei.iItem          = iCnt;
    cbei.pszText        = IInf[iCnt].pszText;
    cbei.cchTextMax     = sizeof(IInf[iCnt].pszText);
    cbei.iImage         = IInf[iCnt].iImage;
    cbei.iSelectedImage = IInf[iCnt].iSelectedImage;
    cbei.iIndent        = IInf[iCnt].iIndent;


    // Tell the ComboBoxEx to add the item. Return FALSE if 
    // this fails.
    if(SendMessage(hwndCB,CBEM_INSERTITEM,0,(LPARAM)&cbei) == -1)
        return FALSE;

// Assign the existing image list to the ComboBoxEx control 
// and return TRUE. 
// g_himl is the handle to the existing image list
SendMessage(hwndCB,CBEM_SETIMAGELIST,0,(LPARAM)g_himl);

// Set size of control to make sure it's displayed correctly now
// that the image list is set.
SetWindowPos(hwndCB,NULL,20,20,250,120,SWP_NOACTIVATE);

return TRUE; 

在 WindowProc 的 WM_CREATE 部分:

himglist = ImageList_Create(24, 24, ILC_COLOR32 | ILC_MASK, 0, 0);
hBitmap = LoadBitmap(GetModuleHandle(0), MAKEINTRESOURCE(IDB_IMGLIST));
ImageList_Add(himglist, hBitmap, 0);
DeleteObject(hBitmap);
hwndComboBoxEx = CreateComboBox(hWnd);
AddItems(hwndComboBoxEx);

程序显示带有文本和图像的组合框,当我点击它时,机器人不显示下拉列表。我想完整地查看下拉列表。 我检查了 SetWindowPos。它会改变 ComboBoxEx 的宽度,但不会改变高度! 我很困惑!它有什么问题?

【问题讨论】:

不完全理解这个问题。 请发布一些代码来说明您正在尝试做什么以及什么不适合您。 How to Create a Simple Combo Box 包含示例代码。如果没有看到你的代码,就不可能猜到你哪里出错了。请提供MCVE。 您是否为未明确处理的窗口消息调用DefWindowProc?您是否吞下了应该打开下拉列表的消息? 'mcve' 的'c' 部分表示可以按原样运行的东西,可以证明问题。另外:CreateComboBoxEX 没有返回HWND,而是返回*HWND。在这种情况下,可能无关紧要,但您应该注意类型。 【参考方案1】:

ComboBoxEx 有一个常规 ComboBox 的子窗口,有些消息无法正确传递。我认为这也取决于 Window 版本。

您应该在创建控件时设置高度。同时删除指针。

HWND CreateComboBoxEX(HWND hwndParent)

    INITCOMMONCONTROLSEX icex;
    icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
    icex.dwICC = ICC_USEREX_CLASSES;
    InitCommonControlsEx(&icex);

    //*** put the correct height in here: *** 
    HWND hwnd = CreateWindowEx(0, WC_COMBOBOXEX, L"", 
            WS_BORDER | WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST, 0, 0, 200, 120, 
            hwndParent, (HMENU)NULL, GetModuleHandle(0), NULL);

    return(hwnd);

您可以稍后使用SetWindowPos 更改 X/Y 位置和宽度。

另一种方法:

使用SetWindowPos 更改 ComboBoxEx 的 X/Y 位置和宽度。然后调整 ComboBoxEx 的子级大小以设置正确的高度。

//height will have no effect here
SetWindowPos(hwndCB, NULL, 20, 20, 250, 120, SWP_NOACTIVATE);

HWND child = (HWND)SendMessage(hwndCB, CBEM_GETCOMBOCONTROL, 0, 0);
if (child)

    //Resize using the same width, but different height. And don't move. 
    SetWindowPos(child, NULL, 0, 0, 250, 120, SWP_NOMOVE);

【讨论】:

以上是关于为啥 SetWindowPos 不改变 ComboBoxEx 下拉高度?的主要内容,如果未能解决你的问题,请参考以下文章

MoveWindow和SetWindowPos

API函数,setwindowpos及其它函数用法

Windows API一日一练 38 SetWindowPos函数

Extjs Combo - 为啥在我没有创建表单时加载组合包含组合

mfc SetWindowPos

mfc 对话框 改变大小