采取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;
}
  
                     
                  
     
  
 
    
    
在采取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;
}




