如何在运行时更改组合框下拉样式?

How doI change combobox's drop down style at runtime?

如何在运行时更改组合框的样式下拉样式?我试过使用 SetWindowLongPtr() 但它既没有改变样式也没有 return 任何错误。我正在尝试从单击按钮开始进行如下更改。缺少什么:

这是处理它的一段代码:

assert(SetWindowLongPtr(hwndCombo, GWL_STYLE, WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST));
                 assert(SetWindowPos(hwndCombo,
                    0, 0, 0, 0, 0,
                    SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW));

完整代码如下:

#pragma comment(lib, "user32.lib")
#pragma comment(lib, "Comctl32.lib")
#pragma comment(lib, "Gdi32.lib")
    
#define WIN32_LEAN_AND_MEAN
#define UNICODE
#define _UNICODE

#include <windows.h>
#include <assert.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

HINSTANCE g_hinst;
int comboStyle = CBS_SIMPLE;
int createButton = 1;

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PWSTR lpCmdLine, int nCmdShow) {

    HWND hwnd;
    MSG  msg ;    
    WNDCLASSW wc = {0};
    wc.lpszClassName = L"Application";
    wc.hInstance     = hInstance ;
    wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
    wc.lpfnWndProc   = WndProc ;
    wc.hCursor       = LoadCursor(0,IDC_ARROW);

    g_hinst = hInstance;
  
    RegisterClassW(&wc);
    hwnd = CreateWindowW(wc.lpszClassName, L"Combo box",
                  WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                  100, 100, 270, 170, 0, 0, hInstance, 0);  


    while (GetMessage(&msg, NULL, 0, 0)) {
        DispatchMessage(&msg);
    }

    return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, 
        WPARAM wParam, LPARAM lParam) {

    static HWND hwndCombo;
    const wchar_t *items[] = { L"foo", L"baa", L"lol" };
    
    switch(msg)
    {
        case WM_CREATE:
        {
            hwndCombo = CreateWindow(L"Combobox", NULL, 
                WS_CHILD | WS_VISIBLE | comboStyle,
                10, 10, 120, 110, hwnd, NULL, g_hinst, NULL);   

            if(createButton)
            {
                CreateWindow(L"Button", L"Change Style", 
                        WS_CHILD | WS_VISIBLE,
                        150, 10, 90, 25, hwnd, (HMENU) 1, g_hinst, NULL);
            }

            for (int i = 0; i < sizeof(items)/sizeof(items[0]); ++i)
            {
                SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) items[i]);
            }
        }
        break;

        case WM_COMMAND:
             if (HIWORD(wParam) == BN_CLICKED)
             {            
                 //MessageBox(NULL, L"!", NULL, MB_OK);
                 comboStyle = CBS_DROPDOWNLIST;
                 createButton = 0;
                 //InvalidateRect(hwndCombo, NULL, TRUE);
                 //SendMessage(hwnd, WM_CREATE, 0, lParam);
                 assert(SetWindowLongPtr(hwndCombo, GWL_STYLE, WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST));
                 assert(SetWindowPos(hwndCombo,
                    0, 0, 0, 0, 0,
                    SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW));
             }
             break;

        case WM_DESTROY:
            PostQuitMessage(0);
            break; 
    }
  
    return DefWindowProc(hwnd, msg, wParam, lParam);
}

尽管 document 说:

If you have changed certain window data using SetWindowLong, you must call SetWindowPos for the changes to take effect. Use the following combination for uFlags: SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED.

但有些样式仅在window创建时生效,因此无法通过此调用设置。

如果您想在运行时修改静态控件的样式,最好的选择是简单地销毁并重新创建具有新样式的控件:

case WM_COMMAND:
    if (HIWORD(wParam) == BN_CLICKED)
    {
        comboStyle = CBS_DROPDOWNLIST;
        createButton = 0;
        DestroyWindow(hwndCombo);
        hwndCombo = CreateWindow(L"Combobox", NULL,
            WS_CHILD | WS_VISIBLE | comboStyle,
            10, 10, 120, 110, hwnd, NULL, g_hinst, NULL);
        for (int i = 0; i < sizeof(items) / sizeof(items[0]); ++i)
        {
            SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM)items[i]);
        }
    }
    break;

更多参考资料:Change Win32 Window Style, SetWindowLong() function doesn't change window style even after calling SetWindowPos()