Win32: How to create a ListBox control using the CreateWindowExW() function?
Asked Answered
G

2

6

I've been through multiple sites, documents and tutorials and they all say the same, that is, any control is nothing more than a window in Win32's API, hence one is able to use the CreateWindowExW() function to create a ListBox control/window over the main application window.

Though I get the concepts of all controls being windows with different dwStyle, I have a hard time finding out how to instantiate, to say so, the ListBox control.

I encountered a tutorial where a dialog is written to have a LISTBOX specified in its declaration as follows:

// resource.h
#define IDD_MAIN                        101
#define IDC_TEXT                        1000
#define IDC_NUMBER                      1001
#define IDC_LIST                        1002
#define IDC_ADD                         1003
#define IDC_CLEAR                       1004
#define IDC_REMOVE                      1005
#define IDC_SHOWCOUNT                   1006

// .rc resource file
IDD_MAIN DIALOG DISCARDABLE  0, 0, 207, 156
    STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
    CAPTION "Controls One"
    FONT 8, "MS Sans Serif"
BEGIN
    LTEXT           "Add",IDC_STATIC,7,10,14,8
    EDITTEXT        IDC_TEXT,25,7,120,14,ES_AUTOHSCROLL
    EDITTEXT        IDC_NUMBER,150,7,21,14,ES_NUMBER
    LTEXT           "times.",IDC_STATIC,177,10,23,8
    LISTBOX         IDC_LIST,7,25,138,106,LBS_NOINTEGRALHEIGHT | 
                    LBS_EXTENDEDSEL | WS_VSCROLL | WS_TABSTOP
    PUSHBUTTON      "&Add",IDC_ADD,150,30,50,14
    PUSHBUTTON      "&Remove",IDC_REMOVE,150,47,50,14
    PUSHBUTTON      "&Clear",IDC_CLEAR,150,63,50,14
    LTEXT           "This item was added",IDC_STATIC,7,141,66,8
    CTEXT           "-",IDC_SHOWCOUNT,77,141,32,8
    LTEXT           "times",IDC_STATIC,114,141,17,8
END

And using it in his C program like so:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    return DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, DlgProc);
}

Now, this I am able to do and fully understand the concepts. Aside, I would like to be able to create and design my main application window to add a ListBox control to. This tutorial example doesn't use the CreateWindowExW() function to create the control, instead, it creates a dialog that will actually be the main application window.

1 - Any clue on how to add a ListBox control to the main window in code?

I thought about creating it while handling the WM_CREATE message.

2 - Is this a good idea?

3 - What is the best practice/approach in this scenario?

Gehrke answered 17/12, 2010 at 18:0 Comment(2)
Writing this kind of code is never a good idea, there are plenty of excellent class libraries available that take the tedium and the bugs out of this. It's okay if you want to learn the assembly language of Win32. Not a very compelling SO question though.Metalline
I do not plan to write a full enterprise system using Win32's. I love C, and always wanted to know more about the Win32's. Back in the beginning of my programming studies, Win32's were too complex for me to learn. Today, I completely udnerstand the concepts behind so it is easier for me to learn. Since the .NET Framework is based on the Win32's, I wish to learn more about it.Gehrke
G
11

In order to dynamically create a control in Win32's you need the following code:

HWND hBtn, hLabel, hListbox, hTextBox;

void InitializeComponent(HWND hWnd) {
    HINSTANCE hInstance = GetModuleHandle(NULL);

    // Adding a Button.
    hBtn = CreateWindowExW(WS_EX_APPWINDOW,
        L"BUTTON", NULL,
        WS_CHILD | WS_VISIBLE,
        327, 7, 70, 21,
        hWnd, NULL, hInstance, NULL);        

    SetWindowTextW(hBtn, L"&Button");

    // Adding a Label.
    hLabel = CreateWindowExW(WS_EX_CLIENTEDGE,
        L"STATIC", NULL,
        WS_CHILD | WS_VISIBLE,
        7, 7, 50, 21,
        hWnd, NULL, hInstance, NULL);

    SetWindowTextW(hLabel, L"Label:");

    // Adding a ListBox.
    hListBox = CreateWindowExW(WS_EX_CLIENTEDGE,
        L"LISTBOX", NULL,
        WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_AUTOVSCROLL,
        7, 35, 300, 200,
        hWnd, NULL, hInstance, NULL);

    // Adding a TextBox.
    hTextBox = CreateWindowExW(WS_EX_CLIENTEDGE,
        L"EDIT", NULL,
        WS_CHILD | WS_VISIBLE | ES_AUTOVSCROLL,
        62, 7, 245, 21,
        hWnd, NULL, hInstance, NULL);

    SetWindowTextW(hTextBox, L"Input text here...");
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
    switch (Msg) {
        case WM_CREATE:
            InitializeComponent(hWnd);
            break;            
        default:
            return DefWindowProcW(hWnd, Msg, wParam, lParam);
    }
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
    // Declaring, defining, registering and creating window here...
    // Note that each Window/Control has to have its own Message handling function.
}
Gehrke answered 17/12, 2010 at 20:52 Comment(6)
You should really correct this, otherwise this Q&A causes more damage than it helps. I assume you posted this without looking at the code again until June 25 2013, asking for help again over at cplusplus. I'd like to see the real solution too :)Shophar
I'm sorry, I might be mistaking you for someone else here. However, this code definitely contains errors, like using edit control styles in a list box control and confusing string types.Shophar
I wonder how you may confuse me with someone else. This code isn't C++, but Win32.Gehrke
Phrased correctly, this is in fact C++ (or C?) and it's using the Win32 API. I was just searching for an answer to this question myself and found this bit of code here and on cplusplus.com/forum/general/105127, where it was commented to have several errors in it.Shophar
I see. Thanks for informing me. Besides, the intention of this question was actually only to know how to draw a ListBox control on the form, which this code allows. As for the dynamic of using the ListBox control in production code, I agree this might not work properly. As my intention was to actually familiarize myself with Win32, this code did it, and as so, I accepted my own answer. Perhaps shall you consider to post your answer so that it may get noticed. =)Gehrke
Unfortunately, I have not been able to dynamically create a list box, dispite the fact that it's basically just using CreateWindowEx() (as instructed by msdn.microsoft.com/en-us/library/windows/desktop/…).Shophar
S
2
HWND hListBox; // Handle for list box control

hListBox = CreateWindowEx(
  WS_EX_CLIENTEDGE, // extended window styles
  "LISTBOX", // list box window class name
  NULL,
  WS_CHILD | WS_VISIBLE, // window styles
  7,   // horizontal position
  35,  // vertical position
  300, // width
  200, // height
  hWnd,
  NULL,
  hInstance,
  NULL
);

if (!hListBox){
  // failed to create list box window - take actions ...
}
Shophar answered 25/8, 2014 at 19:42 Comment(3)
In what is this different from the code I already provided in my answer, tell me?Gehrke
Everything not important to creating a list box control is removed. CreateWindowEx() is used instead of CreateWindowExW() and the L"LISTBOX" cast, which adds simplicity. The edit control styles ES_VSCROLL and ES_AUTOVSCROLL are left out, as they are not usable for list box controls (as far as I know yet). Added error check, which is very important for an interface not tolerating any missing control.Shophar
@Sam: What cast? And yours won't work in projects with UNICODE defined. The function that accepts a plain non-Unicode string is named CreateWindowExA.Pendulum

© 2022 - 2024 — McMap. All rights reserved.