Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories

Welcome to the new platform of Programmer's Heaven! We apologize for the inconvenience caused, if you visited us from a broken link of the previous version. The main reason to move to a new platform is to provide more effective and collaborative experience to you all. Please feel free to experience the new platform and use its exciting features. Contact us for any issue that you need to get clarified. We are more than happy to help you.

Creating Controls (buttons, listboxes, etc.) in Main Window (Win32)?

Ed HallEd Hall Posts: 395Member
I must be missing something. I've been through Forger's Tutorial several times and looked at MSDN and other sources, but I just don't get how to place controls on the primary window. What am I missing? I can create popup windows of all sorts with buttons, etc. But, I want to place a listbox, some editboxes and several buttons on the Main window. Can someone point me to the (probably simple) piece of info I need to make this work? Thanks!

Take Care,
Ed

«13

Comments

  • stoberstober Posts: 9,765Member ✭✭✭
    : I must be missing something. I've been through Forger's Tutorial several times and looked at MSDN and other sources, but I just don't get how to place controls on the primary window. What am I missing? I can create popup windows of all sorts with buttons, etc. But, I want to place a listbox, some editboxes and several buttons on the Main window. Can someone point me to the (probably simple) piece of info I need to make this work? Thanks!
    :
    : Take Care,
    : Ed
    :
    :


    That's one why I'm an MFC fan -- it makes that sort of stuff pretty simple. And I don't know how to do it either. Myself, I wouldn't even think of writing a program of any significant size using pure win32 api functions -- makes my head hurt too much.
  • Ed HallEd Hall Posts: 395Member
    : That's one why I'm an MFC fan -- it makes that sort of stuff pretty simple. And I don't know how to do it either. Myself, I wouldn't even think of writing a program of any significant size using pure win32 api functions -- makes my head hurt too much.
    :
    [blue]Thanks Stober,

    I've no familiarity with MFC at all yet. I do have a hole card to play still - my Borland package includes something called Object Windows Library (OWL) that I can use to do lots of stuff including the current things I'm trying to accomplish. Unfortunately, it comes with a price - OWL remaps a lot of APIs and ties up things that I haven't been able to untie. For example, I haven't been able to size the window to what I want - it's determined by something within the OWL libraries and attrib.x and attrib.y have no effect. For that reason I've been trying to get back to a more pure win32, if there is such an animal...

    Take Care,
    Ed[/blue]

  • tsagldtsagld Posts: 621Member
    : : That's one why I'm an MFC fan -- it makes that sort of stuff pretty simple. And I don't know how to do it either. Myself, I wouldn't even think of writing a program of any significant size using pure win32 api functions -- makes my head hurt too much.
    : :
    : [blue]Thanks Stober,
    :
    : I've no familiarity with MFC at all yet. I do have a hole card to play still - my Borland package includes something called Object Windows Library (OWL) that I can use to do lots of stuff including the current things I'm trying to accomplish. Unfortunately, it comes with a price - OWL remaps a lot of APIs and ties up things that I haven't been able to untie. For example, I haven't been able to size the window to what I want - it's determined by something within the OWL libraries and attrib.x and attrib.y have no effect. For that reason I've been trying to get back to a more pure win32, if there is such an animal...
    :
    : Take Care,
    : Ed[/blue]
    :
    :

    Placing controls on a window requires the CreateWindow or CreateWindowEx api.
    MSDN explaines it well, imo. Shouldn't be any problem.


    Greets,
    Eric Goldstein
    www.gvh-maatwerk.nl


  • AsmGuru62AsmGuru62 Posts: 6,519Member
    [b][red]This message was edited by AsmGuru62 at 2006-4-11 4:20:55[/red][/b][hr]
    : Placing controls on a window requires the CreateWindow or CreateWindowEx api.
    : MSDN explaines it well, imo. Shouldn't be any problem.
    :
    :
    : Greets,
    : Eric Goldstein
    : www.gvh-maatwerk.nl
    :
    :
    :
    [blue]That is correct.

    Just want to add where it should be done. Your main window procedure should have WM_CREATE case. In there you need to add a call to CreateWindow() passing HWND from main procedure as parent window for your child window. Use the correct class names for your controls: "edit" for simple edit box, "listbox", "combobox", etc. Also, styles must include WS_CHILD + WS_VISIBLE. The rest of styles should be according to control - MSDN specifies all styles for all controls:

    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/wincontrols.asp

    In case, you make your main window resizeable - respond to WM_SIZE by resizing (call MoveWindow() on each control) controls according to your design.[/blue]


  • Ed HallEd Hall Posts: 395Member
    : [b][red]This message was edited by AsmGuru62 at 2006-4-11 4:20:55[/red][/b][hr]
    : : Placing controls on a window requires the CreateWindow or CreateWindowEx api.
    : : MSDN explaines it well, imo. Shouldn't be any problem.
    : :
    : :
    : : Greets,
    : : Eric Goldstein
    : : www.gvh-maatwerk.nl
    : :
    : :
    : :
    : [blue]That is correct.
    :
    : Just want to add where it should be done. Your main window procedure should have WM_CREATE case. In there you need to add a call to CreateWindow() passing HWND from main procedure as parent window for your child window. Use the correct class names for your controls: "edit" for simple edit box, "listbox", "combobox", etc. Also, styles must include WS_CHILD + WS_VISIBLE. The rest of styles should be according to control - MSDN specifies all styles for all controls:
    :
    : http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/wincontrols.asp
    :
    : In case, you make your main window resizeable - respond to WM_SIZE by resizing (call MoveWindow() on each control) controls according to your design.[/blue]
    :
    Thanks guys,

    I think the "where it should be done" part was what was missing. I can't work on it right now, but I hope I can do some more with it a little later today (might not be until tomorrow). I'll let you know if I get ahold of the concept. My Borland help files (and MSDN) do explain a lot, but the one thing that's missing is a good set of examples. With your help, I think there is a light trying to shine through. Thanks again.

    Take Care,
    Ed

  • Ed HallEd Hall Posts: 395Member
    I'm closer, but not quite there yet. Thanks for the push in the right direction. I do now have four buttons on my main window and can read BN_CLICKED, but I haven't been able to differentiate yet. I've tried adding ID_... for the HMENU hMenu element (with ID_... added to my .h file equal to 9004), but it won't compile. I've also tried simply coding it with an integer (9004). I tried this approach because the hMenu documentation says:

    "For a child window, hMenu specifies the child-window identifier, an integer value used by a dialog box control to notify its parent about events."

    But it won't let me use anything other than NULL.

    From the button description for returned values I read:

    "...the low-order word of the wParam parameter contains the control identifier, the high-order word of wParam contains the notification code, and the lParam parameter contains the control window handle."

    If I try comparing the lParam to my button handle

    [code]
    if (lParam == hwndButton)
    [/code]

    I receive a type mismatch error.

    Anyway I definitely appreciate the help. I won't have any time today to study this further, but maybe tomorrow. Thanks again.

    Take Care,
    Ed




  • AsmGuru62AsmGuru62 Posts: 6,519Member
    [blue]If you post the code inside your WM_CREATE case - we may be able to help you better. Something is missing there...[/blue]
  • Ed HallEd Hall Posts: 395Member
    : [blue]If you post the code inside your WM_CREATE case - we may be able to help you better. Something is missing there...[/blue]
    :
    Thanks,

    I've trimmed the code down quite a bit, but here's (I hope) enough to get a good look at this portion. Currently, I can pick up the fact that a button was clicked, but as it now stands any button gives a response. My BECommnd.h file includes a listing for ID_EXIT and ID_CANCEL with 9004 and 9005, but I haven't found a way to get them linked with the buttons.

    As you can see I have remarked out a couple tests.

    [code]
    #include
    #include "BECommnd.h"

    const char g_szClassName[] = "myWindowClass";
    HWND hwndCancel, hwndExit;

    ...

    LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    switch(msg)
    {
    case WM_CREATE:
    hwndCancel = CreateWindow(
    "BUTTON", // predefined class
    "Cancel", // button text
    WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, // styles

    // Size and position values are given explicitly, because
    // the CW_USEDEFAULT constant gives zero values for buttons.
    220, // starting x position
    20, // starting y position
    60, // button width
    30, // button height
    hwnd, // parent window
    NULL, // No menu
    (HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE),
    NULL); // pointer not needed

    hwndExit = CreateWindow(
    "BUTTON", // predefined class
    "Exit", // button text
    WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, // styles

    // Size and position values are given explicitly, because
    // the CW_USEDEFAULT constant gives zero values for buttons.
    320, // starting x position
    20, // starting y position
    60, // button width
    30, // button height
    hwnd, // parent window
    NULL, // No menu [red]I tried ID_EXIT here[/red]
    (HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE),
    NULL); // pointer not needed

    break;

    case WM_COMMAND:
    switch(LOWORD(wParam))
    {
    case BN_CLICKED:
    // switch(lParam)
    // case ID_EXIT:
    // case hwndExit:
    // if (lParam == hwndExit)
    PostMessage(hwnd, WM_CLOSE, 0, 0);
    // break;
    break;

    case ID_FILE_EXIT:
    PostMessage(hwnd, WM_CLOSE, 0, 0);
    break;

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

    [/code]

    Thanks for any thougts that can get me pointed in the right direction. This project is a rework of a huge program from a couple years ago that used the Borland OWL format. I'm trying to use it to learn how to work more directly with the win32 APIs which should free me from some of the OWL constraints. I'm hoping that figuring out the buttons will help me when I move to the listbox and editboxes I'm also going to need. Fortunately, I'm not in any real hurry to get through this, but I sometimes get rather frustrated.

    Thanks again,
    Ed

  • AsmGuru62AsmGuru62 Posts: 6,519Member
    : [code]
    : #include
    : #include "BECommnd.h"
    :
    : const char g_szClassName[] = "myWindowClass";
    : HWND hwndCancel, hwndExit;
    :
    : ...
    :
    : LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    : {
    : switch(msg)
    : {
    : case WM_CREATE:
    : hwndCancel = CreateWindow(
    : "BUTTON", // predefined class
    : "Cancel", // button text
    : WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, // styles
    :
    : // Size and position values are given explicitly, because
    : // the CW_USEDEFAULT constant gives zero values for buttons.
    : 220, // starting x position
    : 20, // starting y position
    : 60, // button width
    : 30, // button height
    : hwnd, // parent window
    : NULL, // No menu
    [b][red]
    The child window cannot have a zero ID - that is a problem.
    Instead of a menu handle here you need to use an ID for that button -
    the one you will be reacting on in WM_COMMAND case. Cast it to
    HMENU, like this: [blue](HMENU) ID_FILE_EXIT[/blue]
    [/red][/b]
    : (HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE),
    : NULL); // pointer not needed
    :
    : hwndExit = CreateWindow(
    : "BUTTON", // predefined class
    : "Exit", // button text
    : WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, // styles
    :
    : // Size and position values are given explicitly, because
    : // the CW_USEDEFAULT constant gives zero values for buttons.
    : 320, // starting x position
    : 20, // starting y position
    : 60, // button width
    : 30, // button height
    : hwnd, // parent window
    : NULL, // No menu [red]I tried ID_EXIT here[/red]
    : (HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE),
    : NULL); // pointer not needed
    :
    : break;
    :
    : case WM_COMMAND:
    [b][red]
    The case below needs some adjusting. Control notifications (from
    buttons, list boxes, combo boxes) are coming here in HIWORD (wParam).
    The ID of the control comes in LOWORD (wParam), watch out for that
    (I see you comparing LOWORD to BN_CLICKED, and it is not there).
    Since BN_CLICKED is zero, you can use a simple switch on button ID:

    switch (wParam) {
    case ID_FILE_EXIT:
    // your action here...
    break;
    }
    [/red][/b]
    : switch(LOWORD(wParam))
    : {
    : case BN_CLICKED:
    : // switch(lParam)
    : // case ID_EXIT:
    : // case hwndExit:
    : // if (lParam == hwndExit)
    : PostMessage(hwnd, WM_CLOSE, 0, 0);
    : // break;
    : break;
    :
    : case ID_FILE_EXIT:
    : PostMessage(hwnd, WM_CLOSE, 0, 0);
    : break;
    :
    : case WM_CLOSE:
    : DestroyWindow(hwnd);
    : break;
    : case WM_DESTROY:
    : PostQuitMessage(0);
    : break;
    : default:
    : return DefWindowProc(hwnd, msg, wParam, lParam);
    : }
    : return 0;
    : }
    :
    : [/code]

  • Ed HallEd Hall Posts: 395Member
    : [b][red]
    : The child window cannot have a zero ID - that is a problem.
    : Instead of a menu handle here you need to use an ID for that button -
    : the one you will be reacting on in WM_COMMAND case. Cast it to
    : HMENU, like this: [blue](HMENU) ID_FILE_EXIT[/blue]
    : [/red][/b]
    : [b][red]
    : The case below needs some adjusting. Control notifications (from
    : buttons, list boxes, combo boxes) are coming here in HIWORD (wParam).
    : The ID of the control comes in LOWORD (wParam), watch out for that
    : (I see you comparing LOWORD to BN_CLICKED, and it is not there).
    : Since BN_CLICKED is zero, you can use a simple switch on button ID:
    :
    : switch (wParam) {
    : case ID_FILE_EXIT:
    : // your action here...
    : break;
    : }
    : [/red][/b]
    [blue]
    Thanks much. I found the above yesterday and got all the buttons working just as you described above. The casting to HMENU was the real elusive point. I definitely appreciate your help (and verification). Sorry I couldn't get on the board yesterday to let you know I'd found it. I was able to also build in keystroke recognition for the buttons.

    As a point of learning, why was I not able to compare the button handle (hwndExit) to lParam when I received a BN_CLICKED message? My docs say, "...and the lParam parameter contains the control window handle."

    Do they need to be comaped using some other method than == as with strings where you must use [italic]strcmp[/italic] or such?

    Thanks again for helping me get this right.

    Take Care,
    Ed

«13
Sign In or Register to comment.