简单教程:如何创建一个基于金山卫士界面库的工程

来源:互联网 发布:招聘淘宝 编辑:程序博客网 时间:2024/04/29 16:22
上一篇 http://www.2cto.com/kf/201203/125262.html


完整解决方案代码压缩包:test_full.zip http://up.2cto.com/2012/0328/20120328061229666.zip
 (267.59 KB)
 
参考:
 
http://bbs.code.ijinshan.com/thread-1391-1-1.html
 
为了让更多的朋友能够让自己的程序使用上金山卫士的界面库,现将创建界面库的过程用文字说明,希望可以帮助到各位。如果觉得过程麻烦,也可以直接下载创建后的完整代码。
 
 
基本要求:安装WTL,下载地址:http://wtl.sourceforge.net/。下载解压后,到解压目录的AppWiz子目录下运行setup80.js(对应VS2005)即可安装完毕。
 
       这是补充:要告诉VS2005编译器WTL下的头文件的位置。
 
      工具->选项->VC++目录 在包含中加入    D:\WTL80_7161_Final\include
 
第一步、复制卫士界面库必要的文件
 
在VS2005中,单击菜单“文件”->“新建”->“项目”,在新建对话框中选择项目类型为“WTL”,模版只有一个“ATL/WTL Application Wizard”,选中它并在下方的编辑框中输入项目名和项目位置,这里假设创建后的目录为H:\MyProject\test。单击“确定”,在出现的向导中选择“下一步”,选择“Dialog Based”,并单击“Finish”按钮。


图片1.png

在H:\MyProject\test\test下创建publish文件夹,然后到http://code.ijinshan.com下载金山卫士源代码,将其解压到某个目录,打开其子目录pcmanager\src\publish,将其下的bkres、bkwin、tinyxml和wtlhelper复制到H:\MyProject\test\test\publish下。


图片2.png

第二步、添加包含目录

在VS2005的“解决方案资源管理器”中,右键点击test项目(注意是项目而不是解决方案),选择属性。


图片3.png

在出现的“test属性页”对话框中,选择左边的“配置属性”->“C/C++”->“常规”项,在右边的“附加包含目录”中输入publish,点击“确定”保存设置。

 第三步、将Bkres、TinyXML加入项目中

在“解决方案资源管理器”中,右键点击“Resource Files”,选择“添加”->“现有项”,定位到publish\bkres目录下,将bkres.rc添加进项目。


图片5.png


然后再在test项目上点击右键,选择“添加”->“新建筛选器”,创建名为publish的筛选器,再在publish下创建TinyXML筛选器(创建筛选器只是为了分类方便,这一步可以略过,文件添加到任何一个筛选器中)。接下来用和以上相同的添加现有项的方法将publish\tinyxml下的所有文件添加到TinyXML筛选器下。

 


图片6.png

第四步、去除TinyXML预编译头设置

展开publish\TinyXML筛选器,右键点击一个cpp文件,选择属性。


图片7.png

 

点击左边的“配置属性”->“C/C++”->“预编译头”,将右边的“创建/使用预编译头”选项设置为“不使用预编译头”,点击“确定”。

 


 图片8.png

 
 
对TinyXML筛选器下所有cpp文件都执行这一步。
 
 
第五步,添加必要的代码
 
主要是替换默认生成的WTL基本对话框的代码,转而使用调用卫士界面库的代码,并且加入卫士界面库必需的定义XML相关文件和图片资源。此处为了方便起见,将代码打包,各位可以直接从附件中下载,将文件替换掉原先创建项目时自动生成的代码,然后将新增的bkwinres.h以及bkwinres.rc2添加到项目中即可。
 
这里可以看到_tMain函数中的
 
CMainDlg dlgMain; 
 dlgMain.DoModal(); 
 
而构建CMainDlg的方法是:
 
 
class CMainDlg  : public CBkDialogImpl<CMainDlg> 
                , public CWHRoundRectFrameHelper<CMainDlg> 

public: 
    CMainDlg():CBkDialogImpl<CMainDlg>(IDR_BK_MAIN_DIALOG) 
    { 
    } 
 
    BK_NOTIFY_MAP(IDC_RICHVIEW_WIN) 
        BK_NOTIFY_ID_COMMAND(IDC_BTN_CLOSE, OnBtnClose) 
        BK_NOTIFY_ID_COMMAND(IDC_BTN_MIN, OnMinBtnClick) 
    BK_NOTIFY_MAP_END() 
 
    BEGIN_MSG_MAP(CMainDlg) 
        MSG_BK_NOTIFY(IDC_RICHVIEW_WIN) 
        CHAIN_MSG_MAP(CBkDialogImpl<CMainDlg>) 
        CHAIN_MSG_MAP(CWHRoundRectFrameHelper<CMainDlg>) 
        MSG_WM_SYSCOMMAND(OnCommand) 
        MSG_WM_INITDIALOG(OnInitDialog) 
    END_MSG_MAP() 
 
protected: 
    LRESULT OnCommand(UINT wParam, CPoint point); 
    BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam); 
    void OnBtnClose(); 
    void OnMinBtnClick(); 
}; 
 
CBkDialogImpl  CWHRoundRectFrameHelper是金山开源软件中自定义的类,我们在看它们的实现.
 
 
template <class T> 
class CWHRoundRectFrameHelper 

protected: 
 
    SIZE m_sizeWnd; 
 
    void OnSize(UINT nType, CSize size) 
    { 
        T *pT = static_cast<T*>(this); 
 
        if (nType == SIZE_MINIMIZED) 
            return; 
 
        if (size == m_sizeWnd) 
            return; 
 
        CRect rcWindow, rcClient; 
        CRgn rgnWindow, rgnMinus, rgnAdd; 
 
        pT->GetWindowRect(rcWindow); 
        pT->GetClientRect(rcClient); 
        pT->ClientToScreen(rcClient); 
 
        rcClient.OffsetRect(- rcWindow.TopLeft()); 
 
        rgnWindow.CreateRectRgn(rcClient.left, rcClient.top + 2, rcClient.right, rcClient.bottom - 2); 
        rgnAdd.CreateRectRgn(rcClient.left + 2, rcClient.top, rcClient.right - 2, rcClient.top + 1); 
        rgnWindow.CombineRgn(rgnAdd, RGN_OR); 
        rgnAdd.OffsetRgn(0, rcClient.Height() - 1); 
        rgnWindow.CombineRgn(rgnAdd, RGN_OR); 
        rgnAdd.SetRectRgn(rcClient.left + 1, rcClient.top + 1, rcClient.right - 1, rcClient.top + 2); 
        rgnWindow.CombineRgn(rgnAdd, RGN_OR);  
        rgnAdd.OffsetRgn(0, rcClient.Height() - 3); 
        rgnWindow.CombineRgn(rgnAdd, RGN_OR); 
//         rgnAdd.OffsetRgn(0, rcClient.Height()); 
//         rgnWindow.CombineRgn(rgnAdd, RGN_OR); 
 
//         rgnMinus.CreateRectRgn(rcClient.left, rcClient.top, rcClient.left + 2, rcClient.top + 1); 
//         rgnWindow.CombineRgn(rgnMinus, RGN_DIFF); 
//         rgnMinus.OffsetRgn(rcClient.Width() - 2, 0); 
//         rgnWindow.CombineRgn(rgnMinus, RGN_DIFF); 
//         rgnMinus.OffsetRgn(0, rcClient.Height() - 1); 
//         rgnWindow.CombineRgn(rgnMinus, RGN_DIFF); 
//         rgnMinus.OffsetRgn(3 - rcClient.Width(), 0); 
//         rgnWindow.CombineRgn(rgnMinus, RGN_DIFF); 
//  
//         rgnMinus.SetRectRgn(rcClient.left, rcClient.top, rcClient.left + 1, rcClient.top + 2); 
//         rgnWindow.CombineRgn(rgnMinus, RGN_DIFF); 
//         rgnMinus.OffsetRgn(rcClient.Width() - 1, 0); 
//         rgnWindow.CombineRgn(rgnMinus, RGN_DIFF); 
//         rgnMinus.OffsetRgn(0, rcClient.Height() - 2); 
//         rgnWindow.CombineRgn(rgnMinus, RGN_DIFF); 
//         rgnMinus.OffsetRgn(1 - rcClient.Width(), 0); 
//         rgnWindow.CombineRgn(rgnMinus, RGN_DIFF); 
 
        pT->SetWindowRgn(rgnWindow); 
 
        m_sizeWnd = size; 
    } 
 
public: 
 
    BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0) 
    { 
        BOOL bHandled = TRUE; 
 
        switch(dwMsgMapID) 
        { 
        case 0: 
            if (uMsg == WM_SIZE) 
            { 
                OnSize((UINT)wParam, _WTYPES_NS::CSize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); 
                lResult = 0; 
            } 
            break; 
        } 
        return FALSE; 
    } 
}; 
 
 
 
 
////////////////////////////////////////////////////////////////////////// 
// CBkDialogImpl 
 
template <class T, class TBkView = CBkDialogView, class TBase = CWindow, class TWinTraits = CControlWinTraits> 
class ATL_NO_VTABLE CBkDialogImpl : public CWindowImpl<T, TBase, TWinTraits> 

public: 
 
    static BOOL IsWinXPAndLater() 
    { 
        DWORD dwVersion = GetVersion(); 
        DWORD dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); 
        DWORD dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion))); 
 
        if (dwMajorVersion > 5)         // Vista and later 
            return TRUE; 
        else if (dwMajorVersion < 5)    // 98/NT4 and before 
            return FALSE; 
        else if (dwMinorVersion > 0)    // XP and 2003 
            return TRUE; 
        else                            // 2000 
            return FALSE; 
    } 
 
    static ATL::CWndClassInfo& GetWndClassInfo() 
    { 
        static ATL::CWndClassInfo wc = { 
                { sizeof(WNDCLASSEX),  
                CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | (IsWinXPAndLater() ? CS_DROPSHADOW : 0),  
                  StartWindowProc, 0, 0, NULL, NULL, NULL,  
                  (HBRUSH)(COLOR_WINDOW + 1), NULL, NULL, NULL }, 
                NULL, NULL, IDC_ARROW, TRUE, 0, _T("") 
            }; 
        return wc; 
    } 
 
public: 
    CBkDialogImpl(UINT uResID = 0) 
        : m_uResID(uResID) 
        , m_bShowWindow(TRUE) 
        , m_bExitModalLoop(FALSE) 
    { 
    } 
    virtual ~CBkDialogImpl() 
    { 
 
    } 
 
protected: 
    typedef CBkDialogImpl<T, TBkView, TBase, TWinTraits> __thisClass; 
 
    UINT m_uResID; 
    UINT m_uRetCode; 
 
    TBkView m_richView; 
 
    BOOL m_bShowWindow; 
 
    void ResizeClient(SIZE sizeClient, BOOL bRedraw) 
    { 
        ResizeClient(sizeClient.cx, sizeClient.cy, bRedraw); 
    } 
 
    void ResizeClient(int cx, int cy, BOOL bRedraw) 
    { 
        CRect rcWindow, rcClient; 
        CPoint ptWindow; 
 
        GetWindowRect(rcWindow); 
        GetClientRect(rcClient); 
 
        ptWindow = rcWindow.TopLeft(); 
 
        rcWindow.MoveToXY(0, 0); 
 
        rcWindow -= rcClient; 
        rcClient.SetRect(0, 0, cx, cy); 
        rcWindow += rcClient; 
 
        rcWindow.MoveToXY(ptWindow); 
 
        MoveWindow(rcWindow, bRedraw); 
    } 
 
    void OnSize(UINT nType, CSize size) 
    { 
        CRect rcClient; 
 
        GetClientRect(rcClient); 
 
        if (SIZE_MINIMIZED != nType) 
        { 
            if (m_richView.m_hWnd) 
                m_richView.MoveWindow(rcClient); 
 
        } 
 
        SetMsgHandled(FALSE); 
    } 
 
    BOOL OnEraseBkgnd(CDCHandle dc) 
    { 
        return TRUE; 
    } 
 
    LRESULT OnNcCalcSize(BOOL bCalcValidRects, LPARAM lParam) 
    { 
        if (bCalcValidRects) 
        { 
            CRect rcWindow; 
 
            GetWindowRect(rcWindow); 
 
            LPNCCALCSIZE_PARAMS pParam = (LPNCCALCSIZE_PARAMS)lParam; 
 
            if (SWP_NOSIZE == (SWP_NOSIZE & pParam->lppos->flags)) 
                return 0; 
 
            if (0 == (SWP_NOMOVE & pParam->lppos->flags)) 
            { 
                rcWindow.left = pParam->lppos->x; 
                rcWindow.top = pParam->lppos->y; 
            } 
 
            rcWindow.right = rcWindow.left + pParam->lppos->cx; 
            rcWindow.bottom = rcWindow.top + pParam->lppos->cy; 
            pParam->rgrc[0] = rcWindow; 
            pParam->rgrc[1] = pParam->rgrc[0]; 
        } 
 
        return 0; 
    } 
 
    void OnGetMinMaxInfo(LPMINMAXINFO lpMMI) 
    { 
        HMONITOR hMonitor = ::MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONULL); 
 
        if (hMonitor) 
        { 
            MONITORINFO mi = {sizeof(MONITORINFO)}; 
            ::GetMonitorInfo(hMonitor, &mi); 
 
            CRect rcWork = mi.rcWork, rcMonitor = mi.rcMonitor; 
            lpMMI->ptMaxPosition.x = abs(rcWork.left - rcMonitor.left) - 1; 
            lpMMI->ptMaxPosition.y = abs(rcWork.top - rcMonitor.top) - 1; 
            lpMMI->ptMaxSize.x = abs(rcWork.Width()) + 2; 
            lpMMI->ptMaxSize.y = abs(rcWork.Height()) + 2; 
            lpMMI->ptMaxTrackSize.x = abs(rcWork.Width()) + 2; 
            lpMMI->ptMaxTrackSize.y = abs(rcWork.Height()) + 2; 
        } 
    } 
 
    BOOL OnNcActivate(BOOL bActive) 
    { 
        return TRUE; 
    } 
 
public: 
 
    BOOL Load(UINT uResID) 
    { 
        CStringA strXml; 
 
        BOOL bRet = BkResManager::LoadResource(uResID, strXml); 
 
        if (!bRet) 
            return FALSE; 
 
        return SetXml(strXml); 
    } 
 
    BOOL SetXml(LPCSTR lpszXml) 
    { 
        return m_richView.SetXml(lpszXml); 
    } 
 
    HWND GetViewHWND() 
    { 
        return m_richView.m_hWnd; 
    } 
 
    BOOL SetPanelXml(UINT uItemID, UINT uResID) 
    { 
        return m_richView.SetPanelXml(uItemID, uResID); 
    } 
 
    BOOL SetPanelXml(UINT uItemID, LPCSTR lpszXml) 
    { 
        return m_richView.SetPanelXml(uItemID, lpszXml); 
    } 
 
    BOOL SetRichText(UINT uItemID, UINT uResID) 
    { 
        return m_richView.SetRichText(uItemID, uResID); 
    } 
 
    BOOL FormatRichText(UINT uItemID, LPCTSTR lpszFormat, ...) 
    { 
        va_list args; 
        CString strText; 
 
        va_start(args, lpszFormat); 
 
        strText.FormatV(lpszFormat, args); 
 
        return m_richView.SetRichText(uItemID, strText); 
    } 
 
    BOOL SetRichText(UINT uItemID, LPCWSTR lpszXml) 
    { 
        return m_richView.SetRichText(uItemID, lpszXml); 
    } 
 
    BOOL SetRichText(UINT uItemID, LPCSTR lpszXml) 
    { 
        return m_richView.SetRichText(uItemID, lpszXml); 
    } 
 
    BOOL SetItemText(UINT uItemID, LPCTSTR lpszText) 
    { 
        return m_richView.SetItemText(uItemID, lpszText); 
    } 
 
    CString GetItemText(UINT uItemID) 
    { 
        return m_richView.GetItemText(uItemID); 
    } 
 
    BOOL FormatItemText(UINT uItemID, LPCTSTR lpszFormat, ...) 
    { 
        va_list args; 
        CString strText; 
 
        va_start(args, lpszFormat); 
 
        strText.FormatV(lpszFormat, args); 
 
        return m_richView.SetItemText(uItemID, strText); 
    } 
 
    BOOL SetItemAttribute(UINT uItemID, LPCSTR lpszAttrib, LPCSTR lpszValue) 
    { 
        return m_richView.SetItemAttribute(uItemID, lpszAttrib, lpszValue); 
    } 
 
    BOOL GetItemRect(UINT uItemID, RECT &rcItem) 
    { 
        return m_richView.GetItemRect(uItemID, rcItem); 
    } 
 
    BOOL SetItemStringAttribute(UINT uItemID, LPCSTR lpszAttrib, LPCTSTR lpszValue) 
    { 
        return m_richView.SetItemStringAttribute(uItemID, lpszAttrib, lpszValue); 
    } 
 
    BOOL SetItemIntAttribute(UINT uItemID, LPCSTR lpszAttrib, int nValue) 
    { 
        return m_richView.SetItemIntAttribute(uItemID, lpszAttrib, nValue); 
    } 
 
    BOOL SetItemDWordAttribute(UINT uItemID, LPCSTR lpszAttrib, DWORD dwValue) 
    { 
        return m_richView.SetItemDWordAttribute(uItemID, lpszAttrib, dwValue); 
    } 
 
    BOOL SetItemColorAttribute(UINT uItemID, LPCSTR lpszAttrib, COLORREF crValue) 
    { 
        return m_richView.SetItemColorAttribute(uItemID, lpszAttrib, crValue); 
    } 
 
    BOOL GetItemCheck(UINT uItemID) 
    { 
        return m_richView.GetItemCheck(uItemID); 
    } 
 
    BOOL SetItemCheck(UINT uItemID, BOOL bCheck) 
    { 
        return m_richView.SetItemCheck(uItemID, bCheck); 
    } 
 
    BOOL IsItemEnable(UINT uItemID, BOOL bCheckParent = FALSE) 
    { 
        return m_richView.IsItemEnable(uItemID, bCheckParent); 
    } 
 
    BOOL EnableItem(UINT uItemID, BOOL bEnable) 
    { 
        return m_richView.EnableItem(uItemID, bEnable); 
    } 
 
    BOOL IsItemVisible(UINT uItemID, BOOL bCheckParent = FALSE) 
    { 
        return m_richView.IsItemVisible(uItemID, bCheckParent); 
    } 
 
    BOOL SetItemVisible(UINT uItemID, BOOL bVisible) 
    { 
        return m_richView.SetItemVisible(uItemID, bVisible); 
    } 
 
    BOOL SetTabCurSel(UINT uItemID, int nPage) 
    { 
        return m_richView.SetTabCurSel(uItemID, nPage); 
    } 
 
    int GetTabCurSel(UINT uItemID) 
    { 
        return m_richView.GetTabCurSel(uItemID); 
    } 
 
    BOOL SetTabTitle(UINT uItemID, int nPage, LPCTSTR lpszTitle) 
    { 
        return m_richView.SetTabTitle(uItemID, nPage, lpszTitle); 
    } 
 
    BOOL IsTabPageVisible(UINT uItemID, int nPage) 
    { 
        return m_richView.IsTabPageVisible(uItemID, nPage); 
    } 
 
    BOOL SetTabPageVisible(UINT uItemID, int nPage, BOOL bVisible) 
    { 
        return m_richView.SetTabPageVisible(uItemID, nPage, bVisible); 
    } 
 
    BOOL SetItemIconHandle(UINT uItemID, HICON hIcon) 
    { 
        return m_richView.SetItemIconHandle(uItemID, hIcon); 
    } 
 
    BOOL SetItemPaintHook(UINT uItemID, IBkWindowPaintHook* lpPaintHook) 
    { 
        return m_richView.SetItemPaintHook(uItemID, lpPaintHook); 
    } 
 
    void SetWindowCaption(LPCTSTR lpszCaption) 
    { 
        m_richView.SetWindowCaption(lpszCaption); 
    } 
 
    // Call at WM_INITDIALOG 
    void DontShowWindow() 
    { 
        m_bShowWindow = FALSE; 
    } 
 
<span style="color:#cc0000;">    HWND Create(HWND hWndParent = ::GetActiveWindow(), LPRECT rect = NULL) 
    { 
</span>        if (!m_richView.XmlLoaded()) 
        { 
            if (0 == m_uResID || !Load(m_uResID<span style="color:#cc0000;">))// 载入XML文件 
</span>            { 
                return NULL; 
            } 
        } 
 
        CRect rcWnd(0, 0, 0, 0); 
        LPCTSTR lpszCaption = m_richView.GetWindowCaption(); 
 
        if (_T('\0') == lpszCaption[0])   <span style="color:#ff0000;">// 加载标题 
</span>            lpszCaption = NULL; 
 
        if (rect) 
            rcWnd = rect; 
 
        HWND hWnd = __super::Create(hWndParent, rcWnd, lpszCaption, m_richView.GetDlgStyle(), m_richView.GetDlgExStyle()); 
        if (!hWnd) 
            return NULL; 
 
        BkWinThemeFunc::SetWindowTheme(hWnd, L"", L""); 
 
        if (rect) 
        { 
            rcWnd.MoveToXY(0, 0); 
            m_richView.Create(m_hWnd, rcWnd, 0, 0, IDC_RICHVIEW_WIN); 
        } 
        else 
            m_richView.Create(m_hWnd, NULL, 0, 0, IDC_RICHVIEW_WIN); 
 
        m_bShowWindow = TRUE; 
 
        SendMessage(WM_INITDIALOG, (WPARAM)hWnd); 
 
        m_richView.ShowAllRealWindows(TRUE); 
 
        if (m_hWnd == hWnd) 
        { 
            SIZE sizeDefault = m_richView.GetDefaultSize(); 
            if (sizeDefault.cx && sizeDefault.cy) 
            { 
                ResizeClient(sizeDefault, FALSE); 
            } 
        } 
        else 
            hWnd = m_hWnd; 
 
        return hWnd; 
    } 
 
    UINT_PTR DoModal(HWND hWndParent = NULL, LPRECT rect = NULL) 
    { 
        BOOL bEnableParent = FALSE; 
 
        if (NULL == hWndParent) 
        { 
            hWndParent = BkWinManager::GetActive(); 
            if (NULL == hWndParent) 
                hWndParent = ::GetActiveWindow(); 
        } 
 
        if (hWndParent && hWndParent != ::GetDesktopWindow() && ::IsWindowEnabled(hWndParent)) 
        { 
            ::EnableWindow(hWndParent, FALSE); 
            bEnableParent = TRUE; 
        } 
 
        m_bExitModalLoop = FALSE; 
 
        <span style="color:#ff0000;">HWND hWnd = Create(hWndParent, rect); 
</span>        if (!hWnd) 
        { 
            ::EnableWindow(hWndParent, TRUE); 
            return 0; 
        } 
 
        HWND hWndLastActive = BkWinManager::SetActive(hWnd); 
 
        if (!rect) 
            CenterWindow(); 
 
        if (m_bShowWindow) 
        { 
             
            ::SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW); 
        } 
 
        _ModalMessageLoop(); 
 
        m_bExitModalLoop = FALSE; 
 
        // From MFC 
        // hide the window before enabling the parent, etc. 
 
        if ( IsWindow() ) 
        { 
            SetWindowPos( 
            NULL, 0, 0, 0, 0,  
            SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER); 
        } 
 
        if (bEnableParent) 
        { 
            ::EnableWindow(hWndParent, TRUE); 
        } 
 
        if (hWndParent != NULL && ::GetActiveWindow() == m_hWnd) 
            ::SetActiveWindow(hWndParent); 
 
        BkWinManager::SetActive(hWndLastActive); 
 
        if ( IsWindow() ) 
            DestroyWindow(); 
 
        return m_uRetCode; 
    } 
 
    void OnClose() 
    { 
        SendMessage(WM_COMMAND, MAKELONG(IDCANCEL, 0), NULL); 
    } 
 
    void EndDialog(UINT uRetCode) 
    { 
        m_uRetCode = uRetCode; 
 
        m_bExitModalLoop = TRUE; 
 
        // DestroyWindow里面直接Send了WM_DESTROY,所以不会跑到DoModal的消息循环里,所以有了下面那行代码 
        // DestroyWindow(); 
 
        // 这句非常重要,可以让DoModal消息循环再跑一次,防止卡死在GetMessage,泪奔~~~~~~~ 
        ::PostThreadMessage(::GetCurrentThreadId(), WM_NULL, 0, 0); 
    } 
 
    void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
    { 
        if (IsWindowEnabled()) 
        { 
            if (::GetKeyState(VK_CONTROL) >= 0) 
            { 
                if (VK_ESCAPE == nChar) 
                { 
                    SendMessage(WM_COMMAND, MAKELONG(IDCANCEL, 0), NULL); 
                } 
                else if (VK_RETURN == nChar) 
                { 
                    SendMessage(WM_COMMAND, MAKELONG(IDOK, 0), NULL); 
                } 
            } 
 
            SetMsgHandled(FALSE); 
        } 
    } 
 
    void OnOK(UINT /*uNotifyCode*/, int /*nID*/, CWindow /*wndCtl*/) 
    { 
        BKNMCOMMAND nms; 
        nms.hdr.code = BKNM_COMMAND; 
        nms.hdr.hwndFrom = m_hWnd; 
        nms.hdr.idFrom = IDC_RICHVIEW_WIN; 
        nms.uItemID = IDOK; 
        nms.szItemClass = ""; 
 
        LRESULT lRet = ::SendMessage(m_hWnd, WM_NOTIFY, (LPARAM)nms.hdr.idFrom, (WPARAM)&nms); 
    } 
 
    void OnCancel(UINT /*uNotifyCode*/, int /*nID*/, CWindow /*wndCtl*/) 
    { 
        BKNMCOMMAND nms; 
        nms.hdr.code = BKNM_COMMAND; 
        nms.hdr.hwndFrom = m_hWnd; 
        nms.hdr.idFrom = IDC_RICHVIEW_WIN; 
        nms.uItemID = IDCANCEL; 
        nms.szItemClass = ""; 
 
        LRESULT lRet = ::SendMessage(m_hWnd, WM_NOTIFY, (LPARAM)nms.hdr.idFrom, (WPARAM)&nms); 
    } 
 
public: 
    virtual BOOL PreTranslateMessage(MSG* pMsg) 
    { 
        return FALSE; 
    } 
 
protected: 
 
    BOOL m_bExitModalLoop; 
 
    void _ModalMessageLoop() 
    { 
        BOOL bRet; 
        MSG msg; 
 
        for(;;) 
        { 
            if (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) 
            { 
                if (WM_QUIT == msg.message) 
                    break; 
            } 
 
            if (m_bExitModalLoop || NULL == m_hWnd || !::IsWindow(m_hWnd)) 
                break; 
 
            bRet = ::GetMessage(&msg, NULL, 0, 0); 
 
            if (bRet == -1) 
            { 
                continue;   // error, don't process 
            } 
            else if (!bRet) 
            { 
                ATLTRACE(L"Why Receive WM_QUIT here?\r\n"); 
                break;   // WM_QUIT, exit message loop 
            } 
             
            if ( !PreTranslateMessage(&msg) ) 
            { 
                ::TranslateMessage(&msg); 
                ::DispatchMessage(&msg); 
            } 
        } 
    } 
 
    BEGIN_MSG_MAP_EX(CBkDialogImpl) 
        MSG_WM_NCACTIVATE(OnNcActivate) 
        MSG_WM_ERASEBKGND(OnEraseBkgnd) 
        MSG_WM_NCCALCSIZE(OnNcCalcSize) 
        MSG_WM_GETMINMAXINFO(OnGetMinMaxInfo) 
        MSG_WM_SIZE(OnSize) 
        MSG_WM_KEYDOWN(OnKeyDown) 
        MSG_WM_CLOSE(OnClose) 
        COMMAND_ID_HANDLER_EX(IDOK, OnOK) 
        COMMAND_ID_HANDLER_EX(IDCANCEL, OnCancel) 
    END_MSG_MAP() 
}; 
 
0 0