0
votes

I wrote a resource script for a (modeless) dialog that should contain an edit control (used to show a non-edit log report):

IDD_LOG DIALOGEX 10, 10, 300, 200, 0
STYLE WS_VISIBLE | WS_POPUP | WS_CAPTION | WS_BORDER | WS_SYSMENU | DS_CENTER
CAPTION "Last Log Report"
{
    EDITTEXT 301, 0, 0, 250, 180, WS_VISIBLE | WS_CHILD | WS_VSCROLL | ES_MULTILINE | ES_READONLY
}   

When I call up the dialog via the menu using

hwndLogDlg = CreateDialog(NULL, MAKEINTRESOURCE(IDD_LOG), hwnd, (DLGPROC)LogDlgProc)

the following things are not right with it:

  1. The dialog window contains an edit control, but there's another edit control with the same size above it all. That edit control seems to be a non-child window. Also, when I set the text in the edit control calling SetDlgItemText(hwndLogDlg, IDDE_LOGTXT, "<Could not load log data>");, both of them are set.
    I suspect the resource compiler to see the edit control in the script as both a child of the dialog box and a second time as a separate window, although WS_CHILD is set.
  2. The main window is blocked when the dialog is created, although the dialog is modeless.
  3. Clicking the closing button of the dialog window won't cause it to close, even though I call DestroyWindow(hwndDlg); on WM_QUIT and WM_DESTROY. Together with the problem of the main window being blocked, the only ways for me to close everything is to close the window from the taskbar or taskmanager.

Message loop:

while(GetMessage(&Msg, NULL, 0, 0) > 0) {
    if (!IsDialogMessage(hwndDlg, &Msg)){
        TranslateMessage(&Msg); 
        DispatchMessage(&Msg);
    }
}

Dialog window procedure:

INT_PTR CALLBACK LogDlgProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam){
switch (message){
    case WM_INITDIALOG:{
        hwndLogTxt = GetDlgItem(hwndDlg, IDDE_LOGTXT);

        fileHandler fH;
        if (!fH.init("report.log")){
            SetDlgItemText(hwndLogTxt, IDDE_LOGTXT, "<Could not load log data>");
            err(ERR_CUSTOM,"Failed to extract log file!","Extraction Error!");
        }
        else SetDlgItemText(hwndLogTxt, IDDE_LOGTXT, fH.getStr());
        break;
    }
    case WM_DESTROY:{
        DestroyWindow(hwndDlg);
        break;
    }
}
return true;
}

So what I would like to get in the end, is a modeless dialog box containing a (read-only) edit control (that takes up all of the client-area of the dialog window). Is this problem about my resource syntax or about the way I call it? May I even have been missing necessary steps on WM_INITDIALOG?

2
Your code is not behaving correctly. Therefore you have posted the dialog template definition.Cheers and hth. - Alf
Yeah because the dialog template is pretty much all code I have about the dialog. It might be the message loop too, but that should be correct, since I did like in some other example on msdn.microsoft.com/en-us/library/windows/desktop/…. Added it to the question now.Sam
No idea about your phantom edit control (show your code) but your call to SetDlgItemText is wrong - it takes the parent (dialog) handle, not the control handle.Jonathan Potter
I accidentally changed the SetDlgItemText() parameter while in the rush of copying over into this question, thanks for the hint. I added the dialog window procedure now.Sam

2 Answers

3
votes

In general, return FALSE from the dialog proc to get default processing.

Some messages that logically return a value are however special-cased. You can use the SetDlgMsgResult macro from <windowsx.h> to handle those special cases correctly. Or you can just ignore them for now.

Also, I suspect you should not call DestroyWindow.

3
votes

Some comments:

a) I suppose you actually used LogDlgProc in your call to CreateDialog()? do you also have ShowWindow(hwndDlg, SW_SHOW); after CreateDialog()?

b) your EDITTEXT control is declared in the resource file with a number as the id, your logic uses IDDE_TXT -- change your dialog resource to have EDITTEXT IDDE_TXT...

c) change the code to set your edit control to SetDlgItemText(hwndDlg, IDDE_TXT, ...);; make sure that fH.getStr() returns the correct string value

d) close fH after reading from it if necessary (depending on how fileHandler is implemented)

e) return FALSE for unhandled messages

f) you won't get a WM_DESTROY until you call DestroyWindow, I think handling IDCANCEL should be enough

Your dialog proc should look like

INT_PTR CALLBACK LogDlgProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
{   switch (message)
    {   case WM_INITDIALOG:
        {   fileHandler fH;
            if (fH.init("report.log"))
            {   SetDlgItemText(hwndDlg, IDDE_TXT, fH.getStr());
                // close fH
            }
            else
            {   SetDlgItemText(hwndDlg, IDDE_TXT, "<Could not load log data>");
                err(ERR_CUSTOM,"Failed to extract log file!","Extraction Error!");
            }
            return TRUE;
        }

        case WM_COMMAND: 
            if (LOWORD(wParam) == IDCANCEL) 
            {   DestroyWindow(hwndDlg);
                return TRUE;
            }
//EDIT start
            if (HIWORD(wParam) == EN_SETFOCUS && LOWORD(wParam) == IDDE_TXT)
            {   SendDlgItemMessage(hwndDlg, IDDE_TXT, EM_SETSEL, -1, -1);
                return TRUE;
            }
//EDIT end

    }
    return FALSE;
}