Search code examples
c++winapidialogradio-buttoncreatewindow

Dialog window reinitialisation issue


I have the following issue. In my c++ project I wanted to create a dialog window to input settings for the application to be used. The window is created when you click in the menu: application -> robot settings.

I created the window in the following way:

void Robot_Settings::CreateSettingsWindow(HWND hWnd, RECT& windowSize)
{
GetWindowRect(hWnd, &windowSize);

HWND hSDlg = CreateWindowW(
    L"SettingsDialogClass",
    NULL,
    WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU | WS_VISIBLE | WS_CLIPSIBLINGS,
    (windowSize.right - SETTINGS_WINDOW_SIZE) / 2,
    (windowSize.bottom - SETTINGS_WINDOW_SIZE) / 2,
    SETTINGS_WINDOW_SIZE,
    SETTINGS_WINDOW_SIZE,
    hWnd,
    NULL,
    NULL,
    NULL
);
}

then I have the window procedure:

LRESULT CALLBACK Robot_Settings::SettingsDialogProcedure(HWND hSDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_COMMAND:
    switch (wParam)
    {
    case SETTINGS_BUTTON_SAVE:
        collectInputs(hSDlg);
        break;
    case SETTINGS_BUTTON_CANCEL:
        DestroyWindow(hSDlg);
        break;
    }
case WM_CREATE:
    AddControlsToSettingsDialog(hSDlg);
    break;
case WM_DESTROY:
    DestroyWindow(hSDlg);
    break;
default:
    return DefWindowProcW(hSDlg, msg, wParam, lParam);
}
}

And I add the inner controls on WM_CREATE:

void Robot_Settings::AddControlsToSettingsDialog(HWND hSDlg)
{
// Create Text info about amount input
CreateWindowW(
    L"Static",
    L"Input the amount of robots you want to get simulated:",
    WS_VISIBLE | WS_CHILD,
    (int)(SETTINGS_WINDOW_SIZE * 0.15),
    (int)(SETTINGS_WINDOW_SIZE * 0.2),
    (int)(SETTINGS_WINDOW_SIZE / 2),
    (int)(SETTINGS_WINDOW_SIZE / 2),
    hSDlg,
    NULL,
    NULL,
    NULL
);

// Create Text info about formation input
CreateWindowW(
    L"Static",
    L"Input the formation of th robots in this format -> \"x-x-x-x\" where x is the amount of robots you want to have in each row:",
    WS_VISIBLE | WS_CHILD,
    (int)(SETTINGS_WINDOW_SIZE * 0.15),
    (int)(SETTINGS_WINDOW_SIZE * 0.4),
    (int)(SETTINGS_WINDOW_SIZE / 2),
    (int)(SETTINGS_WINDOW_SIZE / 2),
    hSDlg,
    NULL,
    NULL,
    NULL
);

// Create Text info about speed input
CreateWindowW(
    L"Static",
    L"Input the speed calculated in squares per second at which you want the robots to move:",
    WS_VISIBLE | WS_CHILD,
    (int)(SETTINGS_WINDOW_SIZE * 0.15),
    (int)(SETTINGS_WINDOW_SIZE * 0.6),
    (int)(SETTINGS_WINDOW_SIZE / 2),
    (int)(SETTINGS_WINDOW_SIZE / 2),
    hSDlg,
    NULL,
    NULL,
    NULL
);

// Create TextField for amount input
hAmount = CreateWindowW(
    L"Edit",
    L"",
    WS_VISIBLE | WS_CHILD | WS_BORDER | WS_TABSTOP,
    (int)(SETTINGS_WINDOW_SIZE * 0.7),
    (int)(SETTINGS_WINDOW_SIZE * 0.2),
    100,
    20,
    hSDlg,
    NULL,
    NULL,
    NULL
);
//formation radio buttons
CreateWindowW(
    L"BUTTON",
    L"Formation",
    WS_VISIBLE | WS_CHILD | BS_GROUPBOX, 
    (int)(SETTINGS_WINDOW_SIZE * 0.7),
    (int)(SETTINGS_WINDOW_SIZE * 0.35),
    120,
    120,
    hSDlg,
    NULL,
    NULL,
    NULL);

hTriangle = CreateWindowW(
    L"BUTTON",
    L"Triangle",
    WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON | WS_TABSTOP,
    (int)(SETTINGS_WINDOW_SIZE * 0.72),
    (int)(SETTINGS_WINDOW_SIZE * 0.4),
    100,
    20,
    hSDlg,
    (HMENU) ID_RADIO_TRIANGLE,
    NULL,
    NULL);

hRectangle = CreateWindowW(
    L"BUTTON",
    L"Rectangle",
    WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON | WS_TABSTOP,
    (int)(SETTINGS_WINDOW_SIZE * 0.72),
    (int)(SETTINGS_WINDOW_SIZE * 0.45),
    100,
    20,
    hSDlg,
    (HMENU) ID_RADIO_RECTANGLE,
    NULL,
    NULL);

hRhombus = CreateWindowW(
    L"BUTTON",
    L"Rhombus",
    WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON | WS_TABSTOP,
    (int)(SETTINGS_WINDOW_SIZE * 0.72),
    (int)(SETTINGS_WINDOW_SIZE * 0.5),
    100,
    20,
    hSDlg,
    (HMENU) ID_RADIO_RHOMBUS,
    NULL,
    NULL);

// Create TextField for speed input
hSpeed = CreateWindowW(
    L"Edit",
    L"",
    WS_VISIBLE | WS_CHILD | WS_BORDER | WS_TABSTOP,
    (int)(SETTINGS_WINDOW_SIZE * 0.7),
    (int)(SETTINGS_WINDOW_SIZE * 0.6),
    100,
    20,
    hSDlg,
    NULL,
    NULL,
    NULL
);
// Create button Cancel
CreateWindowW(
    L"Button",
    L"Cancel",
    WS_VISIBLE | WS_CHILD | WS_BORDER | WS_TABSTOP,
    (int)(SETTINGS_WINDOW_SIZE * 0.7),
    (int)(SETTINGS_WINDOW_SIZE * 0.8),
    100,
    40,
    hSDlg,
    (HMENU)SETTINGS_BUTTON_CANCEL,
    NULL,
    NULL
);

// Create button Save
CreateWindowW(
    L"Button",
    L"Save",
    WS_VISIBLE | WS_CHILD | WS_BORDER | WS_TABSTOP,
    (int)(SETTINGS_WINDOW_SIZE * 0.7 - 110),
    (int)(SETTINGS_WINDOW_SIZE * 0.8),
    100,
    40,
    hSDlg,
    (HMENU)SETTINGS_BUTTON_SAVE,
    NULL,
    NULL
);
}

So, my issue is, that every time I try to input any text or click on the radio buttons the window seems to be reinitialized or repainted (can't figure out which is happening but it's not a normal behaviour anyway). And if you check the rectangle radiobutton the window closes.

You can find the entire project at: https://github.com/JamesHawkJ/cpp/tree/master/WycieczkaRobotow

Can you please help me solve this problem?


Solution

  • Every time you receive a WM_COMMAND message from any control other than SETTINGS_BUTTON_SAVE or SETTINGS_BUTTON_CANCEL, your window procedure falls through to WM_CREATE case and calls AddControlsToSettingsDialog. You are creating more and more child windows, stacked on top of each other.

    Also, SettingsDialogProcedure is declared to return LRESULT, but it may reach the closing brace without encountering a return statement. This exhibits undefined behavior.