Seth D. Fulmer
Seth D. Fulmer

Reputation: 569

In WIndows API, under what "event" do I put child control creation or why aren't my controls appearing?

It's been years since I last worked with Windows API and I'm trying my hand at it again. I have a simple Window (with title "Test"). I put in the Window message handler under WM_CREATE, 2 CreateWindow calls to create a static and an edit control. I'm pretty sure the coordinates are decent (not overlapping or off the window rectangle). Am I putting the calls under the wrong event? It's just a simple window - not MDI or SDI or anything like that. Here is my code for the entire program. I hope it's sufficient to figure out what I'm doing wrong. I'm using Eclipse CDT with Cygwin's G++ compiler to build it....:

#include <windows.h>

BOOL InitApplication(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE hinstance, int nCmdShow);
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

BOOL InitApplication(HINSTANCE hInstance)
{
    WNDCLASS wc;

    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = MainWndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = GetStockObject(WHITE_BRUSH);
    wc.lpszMenuName = "";
    wc.lpszClassName = "MainWindow";

    return(RegisterClass(&wc));
}

BOOL InitInstance(HINSTANCE hinstance, int nCmdShow)
{
    HINSTANCE hCurInstance = hinstance;
    HWND hWnd = CreateWindow("MainWindow", "Test", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, (HWND)(NULL), (HMENU)(NULL), hCurInstance, (LPVOID)(NULL));

    if(!hWnd)
        return(FALSE);

    // Show the window and send a WM_PAINT message to the window
        // procedure.

        ShowWindow(hWnd, nCmdShow);
        UpdateWindow(hWnd);

        return(TRUE);
}

LRESULT CALLBACK MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)
        {
        case WM_CREATE:
            CreateWindow("WC_STATIC", "&Test: ", SS_LEFT | WS_VISIBLE | WS_CHILD, 10, 10, 50, 20, hWnd, NULL, (HINSTANCE)(GetWindowLongPtr(hWnd, GWLP_HINSTANCE)), (LPVOID)(NULL));
            CreateWindow("WC_EDIT", "", WS_BORDER | WS_TABSTOP | WS_VISIBLE | WS_CHILD | ES_LEFT, 60, 10, 50, 20, hWnd, NULL, (HINSTANCE)(GetWindowLongPtr(hWnd, GWLP_HINSTANCE)), (LPVOID)(NULL));
            return(0);
        default:
            return(DefWindowProcA(hWnd, uMsg, wParam, lParam));
        }
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmd, int nCmdShow)
{
    BOOL fGotMessage;
    MSG msg;

    if(!InitApplication(hInstance))
            return(FALSE);

    if(!InitInstance(hInstance, nCmdShow))
            return(FALSE);

    while(((fGotMessage = GetMessage(&msg, (HWND) NULL, 0, 0)) != 0) && (fGotMessage != -1))
        {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
        }

    return(msg.wParam);
}

Upvotes: 0

Views: 146

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 595392

WM_CREATE is the correct "event" message to create the child controls in.

You are simply using the wrong class names for the child controls. That is why you are not seeing them. Had you checked the result of those CreateWindow() calls for failures, you would have noticed that CreateWindow() was returning NULL, and GetLastError() was reporting ERROR_CANNOT_FIND_WND_CLASS (1407).

You need to replace "WC_STATIC" with "Static", and replace "WC_EDIT" with "Edit". Or, you can use the pre-defined WC_STATIC and WC_EDIT constants that are defined in <commctrl.h>.

You can also replace GetWindowLongPtr(hWnd, GWLP_HINSTANCE) with NULL when creating system-defined classes, as they are registered globally, not per-module. The HINSTANCE parameter of CreateWindow/Ex() is ignored for them.


On a side note: your GetMessage() loop can be simplified to just:

while (GetMessage(&msg, (HWND) NULL, 0, 0))

See: When will GetMessage return -1?

Upvotes: 3

Related Questions