Search code examples
c++winapiembedded-resource

SetDlgItemInt doesn't change editbox of embedded resource


I've created in plain win32 c++ an options menu with an edit box using embedded resources. The edit box ID_EDIT_OPTIONS_BOX has a default value of 30. I can change to value in the edit box to eg 10. I've used the OK-button the place the code for reading and writing the editbox. After I click OK, this new value is stored in my variable INT testInt. But when i re-open the options menu, the edit box still reflects the default value as stored in the resource file.

The basic code I use is this:

testInt = GetDlgItemInt(hDlg, ID_EDIT_OPTIONS_BOX, NULL, FALSE);
SetDlgItemInt(hDlg, ID_EDIT_OPTIONS_BOX, testInt, FALSE);

Do I need to refresh the window or am I missing something really trivial? Below I've listed the full program code, resource header and file.

The program code:

#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>
#include "resource.h"

#define WIN32_LEAN_AND_MEAN

// Global variables
static TCHAR szWindowClass[] = _T("DesktopApp");

static TCHAR szTitle[] = _T("Windows Desktop Guided Tour Application");

HINSTANCE hInst;
int testInt;

// Forward declarations of functions included in this code module:
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK CheckOptionsProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);


int CALLBACK WinMain(
    _In_ HINSTANCE hInstance,
    _In_opt_ HINSTANCE hPrevInstance,
    _In_ LPSTR     lpCmdLine,
    _In_ int       nCmdShow
)
{
    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInstance;
    wcex.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wcex.lpszMenuName = MAKEINTRESOURCE(IDR_MENU);
    wcex.lpszClassName = szWindowClass;
    wcex.hIconSm = LoadIcon(wcex.hInstance, IDI_APPLICATION);

    if (!RegisterClassEx(&wcex))
    {
        MessageBox(NULL,
            _T("Call to RegisterClassEx failed!"),
            _T("Windows Desktop Guided Tour"),
            NULL);

        return 1;
    }

    // Store instance handle in our global variable
    hInst = hInstance;

    HWND hWnd = CreateWindow(
        szWindowClass,
        szTitle,
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT,
        500, 100,
        NULL,
        NULL,
        hInstance,
        NULL
    );

    if (!hWnd)
    {
        MessageBox(NULL,
            _T("Call to CreateWindow failed!"),
            _T("Windows Desktop Guided Tour"),
            NULL);

        return 1;
    }

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

    // Main message loop:
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return (int)msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case ID_FILE_EXIT:
            PostMessage(hWnd, WM_CLOSE, 0, 0);
            break;
        case ID_EDIT_OPTIONS:
            DialogBox(hInst, MAKEINTRESOURCE(ID_EDIT_OPTIONS), hWnd, (DLGPROC)CheckOptionsProc);
            break;
        }
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
        break;
    }

    return 0;
}

LRESULT CALLBACK CheckOptionsProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case ID_EDIT_OPTIONS_OK:
            testInt = GetDlgItemInt(hDlg, ID_EDIT_OPTIONS_BOX, NULL, FALSE);
            SetDlgItemInt(hDlg, ID_EDIT_OPTIONS_BOX, testInt, FALSE);
            EndDialog(hDlg, IDOK);
            break;
        }
    }
    return 0;
}

The resource header

#define IDR_MENU                10
#define ID_FILE_EXIT            20
#define ID_EDIT_OPTIONS         30
#define ID_EDIT_OPTIONS_BOX     40
#define ID_EDIT_OPTIONS_OK      50

And resource file

#include "resource.h"
#include <windows.h>

IDR_MENU MENU
BEGIN
    POPUP "&File"
    BEGIN
        MENUITEM "E&xit", ID_FILE_EXIT
    END
    POPUP "&Edit"
    BEGIN
        MENUITEM "&Options...", ID_EDIT_OPTIONS
    END
END

ID_EDIT_OPTIONS DIALOGEX 0, 0, 260, 128
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Options"
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
FONT 9, "SEGOE UI"
BEGIN
    CONTROL "&OK", ID_EDIT_OPTIONS_OK, BUTTON, BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 145, 110, 50, 11
    CONTROL "30", ID_EDIT_OPTIONS_BOX, EDIT, ES_RIGHT | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 200, 13, 18, 10
END

Solution

  • Use SetDlgItemInt when dialog received WM_INITDIALOG message:

    LRESULT CALLBACK CheckOptionsProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        switch (uMsg)
        {
        case WM_INITDIALOG:
            SetDlgItemInt(hDlg, ID_EDIT_OPTIONS_BOX, testInt, FALSE);
            break;
    
        case WM_COMMAND:
            switch (LOWORD(wParam))
            {
            case ID_EDIT_OPTIONS_OK:
                testInt = GetDlgItemInt(hDlg, ID_EDIT_OPTIONS_BOX, NULL, FALSE);
                EndDialog(hDlg, IDOK);
                break;
            }
        }
        return 0;
    }
    
    
    

    and remember to initialize testInt:

    int testInt = 30;