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

    添加时间:2013-8-12 点击量:

    在采取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++ = 0 x0000; // 没有菜单
    lpw++ = 0 x0000; // 采取默认类

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



    分享到: