从资源生成的C ++ / Win32对话框不正常

时间:2014-08-23 19:30:42

标签: c++ winapi dialog resources

我为(无模式)对话框编写了一个资源脚本,该对话框应该包含一个编辑控件(用于显示非编辑日志报告):

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
}   

当我使用

通过菜单调出对话框时
hwndLogDlg = CreateDialog(NULL, MAKEINTRESOURCE(IDD_LOG), hwnd, (DLGPROC)LogDlgProc)

以下事情不正确:

  1. 对话框窗口包含一个编辑控件,但是还有另一个编辑控件,其大小与它相同。该编辑控件似乎是一个非子窗口。 此外,当我在编辑控件中设置调用SetDlgItemText(hwndLogDlg, IDDE_LOGTXT, "<Could not load log data>");的文本时,它们都已设置 我怀疑资源编译器将脚本中的编辑控件视为对话框的子项,第二次作为单独的窗口,虽然设置了WS_CHILD。
  2. 创建对话框时会阻止主窗口,但对话框是无模式的。
  3. 单击对话框窗口的关闭按钮不会导致它关闭,即使我在WM_QUIT和WM_DESTROY上调用DestroyWindow(hwndDlg);。连同主窗口被阻挡的问题,我关闭所有内容的唯一方法是从任务栏或任务管理器关闭窗口。
  4. 消息循环:

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

    对话窗口程序:

    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;
    }
    

    所以我最想得到的是一个无模式对话框,其中包含一个(只读)编辑控件(占用对话框窗口的所有客户区)。 这个问题是关于我的资源语法还是我称之为的方式?我甚至可能错过了WM_INITDIALOG的必要步骤吗?

2 个答案:

答案 0 :(得分:2)

通常,从对话框proc返回FALSE以获取默认处理。

然而,某些逻辑上返回值的消息是特殊的。您可以使用SetDlgMsgResult中的<windowsx.h>宏来正确处理这些特殊情况。或者你现在可以忽略它们。

此外,我怀疑你不应该致电DestroyWindow

答案 1 :(得分:2)

一些意见:

a)我猜你在LogDlgProc的电话中实际使用了CreateDialog()?在ShowWindow(hwndDlg, SW_SHOW);之后你还有CreateDialog()吗?

b)您的EDITTEXT控件在资源文件中声明,并且数字为id,您的逻辑使用IDDE_TXT - 将对话框资源更改为EDITTEXT IDDE_TXT...

c)更改代码,将编辑控件设置为SetDlgItemText(hwndDlg, IDDE_TXT, ...);;确保fH.getStr()返回正确的字符串值

d)如有必要,请在阅读之后关闭fH(取决于fileHandler的实施方式)

e)为未处理的消息返回FALSE

f)在您致电WM_DESTROY之前,您不会获得DestroyWindow,我认为处理IDCANCEL应该足够了

您的对话框proc应该看起来像

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;
}