• 采用ATL实现无模板对话框的显示


    在采用ATL、WTL的开发对话框程序的标准方法是从CDialogImpl上继承,然后在类中定义一个IDD,把这个窗口与资源关联起来。如果不定这个IDD是编译不通过的,代码如下:

    class CAboutDlg : public CDialogImpl<CAboutDlg>
    {
    public:
    enum { IDD = IDD_ABOUTBOX };

    BEGIN_MSG_MAP(CAboutDlg)
    MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
    COMMAND_ID_HANDLER(IDOK, OnCloseCmd)
    COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd)
    END_MSG_MAP()

    // Handler prototypes (uncomment arguments if needed):
    // LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
    // LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
    // LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)

    LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
    LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
    };

    在有些情况下,我们并不会采用窗口模板来创建窗口,而是对话框及所有的控件都采用自定义的方式来实现,比我们通过根据配置文件来生成控件列表。为了实现这个需求我开发一个无模板对话框类,代码如下:

    typedef CWinTraits<WS_POPUP|WS_BORDER|WS_SYSMENU|DS_MODALFRAME|WS_CAPTION,
    WS_EX_DLGMODALFRAME | WS_EX_CONTROLPARENT> CDialogWinTraits;


    template <class T, class TWinTraits = CDialogWinTraits, class TBase = CWindow>
    class ATL_NO_VTABLE CNTDialogImpl : public CDialogImplBaseT< TBase >
    {
    public:
    #ifdef _DEBUG
    bool m_bModal;
    CNTDialogImpl() : m_bModal(false) { }
    #endif //_DEBUG
    // modal dialogs
    virtual INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow(), _U_RECT rect = NULL,
    LPCTSTR szWindowName = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0)
    {
    // 创建模板
    LPDLGTEMPLATE pTemplate = CreateDlgTemplate (dwStyle, dwExStyle, szWindowName);
    if (pTemplate == NULL) return -1;

    // 更新位置
    if (rect.m_lpRect)
    {
    pTemplate->x = (short)rect.m_lpRect->left;
    pTemplate->y = (short)rect.m_lpRect->right;
    pTemplate->cx = (short)(rect.m_lpRect->right - rect.m_lpRect->left);
    pTemplate->cy = (short)(rect.m_lpRect->bottom - rect.m_lpRect->top);
    }

    // 开始显示窗口
    ATLASSUME(m_hWnd == NULL);
    if (m_thunk.Init(NULL,NULL) == FALSE)
    {
    SetLastError(ERROR_OUTOFMEMORY);
    return -1;
    }

    _AtlWinModule.AddCreateWndData(&m_thunk.cd, this);
    #ifdef _DEBUG
    m_bModal = true;
    #endif //_DEBUG

    LRESULT ret = DialogBoxIndirect(_AtlBaseModule.GetResourceInstance(),
    pTemplate, hWndParent, T::StartDialogProc);

    GlobalFree(pTemplate);
    return ret;
    }
    BOOL EndDialog(int nRetCode)
    {
    ATLASSERT(::IsWindow(m_hWnd));
    #ifdef _DEBUG
    ATLASSUME(m_bModal); // must be a modal dialog
    #endif //_DEBUG
    return ::EndDialog(m_hWnd, nRetCode);
    }

    protected:
    LPWORD lpwAlign ( LPWORD lpIn)
    {
    ULONG ul = (ULONG) lpIn;
    ul +=3; ul >>= 2; ul <<= 2;
    return (LPWORD) ul;
    }

    // 创建对话框模板
    LPDLGTEMPLATE CreateDlgTemplate (DWORD dwStyle, DWORD dwExStyle, LPCTSTR szWindowName)
    {
    HGLOBAL hgbl = NULL;
    LPDLGTEMPLATE lpdt = NULL;
    LPWORD lpw = NULL;
    LPWSTR lpwsz = NULL;

    hgbl = GlobalAlloc(GMEM_ZEROINIT, 1024);
    if (!hgbl) return NULL;

    lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);

    // 定义窗口样式
    lpdt->style = TWinTraits::GetWndStyle (dwStyle);
    lpdt->dwExtendedStyle = TWinTraits::GetWndExStyle (dwExStyle);
    lpdt->cdit = 0; // 窗口中的控件数量
    lpdt->x = 0;
    lpdt->y = 0;
    lpdt->cx = 100; // 默认宽度
    lpdt->cy = 50; // 默认高度

    lpw = (LPWORD) (lpdt + 1);
    *lpw++ = 0x0000; // 没有菜单
    *lpw++ = 0x0000; // 采用默认类

    lpwsz = (LPWSTR) lpw;
    int nchar = 0;
    if (szWindowName)
    {
    int slen = _tcslen(szWindowName) + 1;
    _tcsncpy_s (lpwsz, slen, szWindowName, slen);
    nchar = slen;
    }
    lpw += nchar;

    GlobalUnlock(hgbl);
    return (LPDLGTEMPLATE) hgbl;
    }
    };

    使用方法为把从CDialogImpl上继承改为从CNTDialogImpl中继承就可以,而且不用再定义IDD:

    class CAboutDlg : public CNTDialogImpl<CAboutDlg>
    {
    public:
    BEGIN_MSG_MAP(CAboutDlg)
    MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
    COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd)
    END_MSG_MAP()

    LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
    LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);

    };

    在OnInitDialog中你可以创建你想到的控件,同时最好加上窗口居中的代码,否则窗口会显示在主窗口的左则,不太好看。代码如下:

    LRESULT CAboutDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
    {
    CenterWindow(GetParent()); // 窗口居中
    ResizeClient (300, 200); // 调整窗口大小
    //在以下窗口控件
    //.......

    return TRUE;
    }

  • 相关阅读:

    (luogu)[模板]最长公共子序列
    表达式的值
    邮票面值设计
    尼克的任务
    HISTOGRA
    消防局的设立
    青蛙的约会
    产生数
    奇怪的电梯
  • 原文地址:https://www.cnblogs.com/ihaoqi/p/3250368.html
Copyright © 2020-2023  润新知