金山卫士开源软件之旅(二) 简单教程:如何创建一个基于金山卫士界面库的工程

2023-10-31

完整解决方案代码压缩包: test_full.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

下载 (98.64 KB)
2011-9-30 17:27


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

图片2.png

下载 (111.41 KB)
2011-9-30 17:29


第二步、添加包含目录

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

图片3.png

下载 (25.54 KB)
2011-9-30 17:31


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

图片4.png

下载 (109.83 KB)
2011-9-30 17:38


第三步、将BkresTinyXML加入项目中

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

图片5.png

下载 (19.21 KB)
2011-9-30 17:39


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

图片6.png

下载 (27.18 KB)
2011-9-30 17:39


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

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

图片7.png

下载 (21.34 KB)
2011-9-30 17:40


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

图片8.png

下载 (75.72 KB)
2011-9-30 17:40


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

    HWND Create(HWND hWndParent = ::GetActiveWindow(), LPRECT rect = NULL)
    {
        if (!m_richView.XmlLoaded())
        {
            if (0 == m_uResID || !Load(m_uResID))// 载入XML文件
            {
                return NULL;
            }
        }

        CRect rcWnd(0, 0, 0, 0);
        LPCTSTR lpszCaption = m_richView.GetWindowCaption();

        if (_T('\0') == lpszCaption[0])   // 加载标题
            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;

        HWND hWnd = Create(hWndParent, rect);
        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()
};


  在参考了文章《初步分析整理了xml文件与类之间的关联。分享给大家。》后

http://bbs.code.ijinshan.com/thread-1584-1-1.html

得到下图,希望对大家有帮助:


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

金山卫士开源软件之旅(二) 简单教程:如何创建一个基于金山卫士界面库的工程 的相关文章

  • 什么时候使用Q_NULLPTR?

    I see Q NULLPTR在 Qt 源代码和示例中被广泛使用 但我没有找到关于它到底是什么以及何时应该使用的文档 例如在这个官方示范 http doc snapshots qt io qt5 5 6 qtserialbus can ma
  • 如何将可以为 null 的值或数组隐式包装到 Scala 选项中

    我在 Jar 文件中包含这个 Java 类 作为 Scala 程序的依赖项 如 Axis jar class MyClass private String someStrings public String getSomeStrings r
  • 在远程机器上执行多个命令

    在下面的命令中 我尝试 ssh 命令并执行多个命令 如果任何命令失败 即如果 command1 退出 那么如果 command1 和 commnd 2 退出 否则在远程计算机上执行命令 3 我如何退出 我怎样才能做到这一点 ssh logi
  • 如何检查 GAS 中是否存在文件(通过 id)

    我知道有关如何检查文件是否存在的问答by name using hasnext 不过我需要检查一下按文件 ID 最好没有高级 Drive API 披露 我写了一个基于错误处理的解决方案 function ifFileExists id tr
  • Objective-C 有没有办法捕获发送到 nil 的消息?

    我刚刚被一种烦人的东西咬了bug https stackoverflow com questions 913627 uiviewcontroller viewdidload not being calledObjective C 中的 向
  • MVC 模型在 OnExecuted 操作过滤器中为 null ...或者设置模型的更优雅的方式?

    我有一个 ActionFilter 它覆盖了 OnActionExecuted 方法 在 POST 操作中 filterContext Controller ViewData Model 始终为 null 我确实发现下面的文章似乎在说它不应
  • 确定非空列表条目是否“连续”的 Pythonic 方法

    我正在寻找一种方法来轻松确定列表中所有非 None 项目是否出现在单个连续切片中 我将使用整数作为非 None 项目的示例 例如 列表 None None 1 2 3 None None 满足我对连续整数条目的要求 相比之下 1 2 Non
  • 当Where子句中的术语不在数据库中时,如何从MySQL数据库返回0?

    如果 WHERE 子句中的邻域不存在 如何让 mysql 数据库返回 0 因此 在下面的示例中 旧城区不在数据库中 我希望数据库返回 0 个事件而不是空结果 SELECT incidents neighborhoods FROM myTab
  • 如何在无 null 设计中实现 List、Set 和 Map?

    当您在大多数情况下可以返回 null 空对象以避免 null 时 这很好 但是像 Collection 这样的对象呢 在爪哇 Map回报null if key in get key 地图上没有找到 我能想到的最好的避免方法null在这种情况
  • 从java程序调用SVN命令

    我想从 java 程序调用 SVN 命令 update commit 有什么帮助吗 SVN 乌龟SVN 环境 java程序将在jBoss服务器内运行 从应用程序服务器内使用 GUI SVN 客户端是一个非常非常糟糕的主意 而Tortoise
  • 检查多个变量java中的替换空值

    我试图找到一种简单的方法来在 Java 中的多个变量中执行多个 null 检查 替换 我有一个包含大约 20 个字符串变量的对象 在构造函数中 我想检查是否有任何变量值为空 如果它们为空 我想用空字符串替换它们 我可以执行一系列 if 语句
  • execlp 多个“程序”

    我想运行类似的东西 cat file tar base64 myprogram c base64 d tar zvt I use execlp运行该进程 当我尝试运行类似的东西时cat它有效 但如果我尝试运行base64 d tar zvt
  • Unix 命令列出包含字符串但*不*包含另一个字符串的文件

    如何递归查看包含一个字符串且不包含另一个字符串的文件列表 另外 我的意思是评估文件的文本 而不是文件名 结论 根据评论 我最终使用了 find name html exec grep lR base maps xargs grep L ba
  • 无法在 JavaScript for 循环中读取 null 的属性“长度”

    我正在尝试制作一个像 Stack Overflow 那样的 Markdown 编辑器 如果我实际上没有在文本区域中键入星号和包含短语的 http 我会收到标题中列出的此错误 如果我只输入包含星号的短语 则错误指的是这一行 if linkif
  • Android Root 执行 su 带参数

    我在使用参数执行 su 时遇到问题 包含空格 我的 Command java 看起来像这样 public class Command Process process public String executeCommand String c
  • Microsoft SQL:CASE WHEN 与 ISNULL/NULLIF

    除了可读性之外 在防止 SQL 中的除以 0 错误时 使用 CASE WHEN 语句与 ISNULL NULLIF 相比还有什么显着的好处吗 CASE WHEN BeginningQuantity BAdjustedQuantity 0 T
  • C++ new * char 不为空

    我有一个问题 我在 ASIO 中开发服务器 数据包采用尖头字符 当我创建新字符时 例如char buffer new char 128 我必须手动将其清理为空 By for int i 0 i lt 128 i buffer i 0x00
  • C# 和 SQL Server:如果字符串值为空,如何在命令参数中插入 DBNull.Value?

    我已经搜索了几个小时 但找不到解决方案 我正在将一些字符串插入 SQL 但是有时 我用来执行此操作的方法可能包含空字符串 即 因此我想在 SQL Server 中插入一个空值 首先我测试我的方法以确保我能够插入DBNull Value通过使
  • 将 null 转换为对象?

    我今天遇到了这段代码 AsyncInvoke OnTimeMessageTimer object null ElapsedEventArgs null 有没有什么问题 有时 当方法重载时 您需要这样做 以告诉编译器您正在调用哪一个 null
  • 面向对象编程语言中的引用默认情况下是否应该不可为空? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi

随机推荐

  • 思维导图怎么变成ppt?4个思维导图一键生成ppt的方法

    做好的思维导图如何变成一份ppt 本文罗列了4个可行方法 一起来看看吧 一 直接复制粘贴 这是最简单的方法 虽然这样可能会花费一些时间 但可以确保内容排版和布局与你想要的一致 当然 我们大可使用更高效的方法 二 导出为图片格式 大多数思维导
  • 矩阵相关定义性质全总结

    矩阵相关定义性质全总结 0 前言 矩阵是线性代数中的核心内容 所以我写这篇文章对矩阵 研究生以下阶段 进行一个完整的叙述 虽然是主要说矩阵 但是我也会将行列式 向量 线性方程组三个方面也包含在内 不过是概述的形式 具体的叙述会另外展开写 能
  • C++沉思录读书笔记1.如何定义一个完整的类

    C 沉思录 Ruminations On C 读书笔记1 如何定义一个完整的类 作者 2006 4 27 12 19 C 哲学 只为用到的东西付出代价 定义一个类时必须搞清楚的几个问题 需要构造函数吗 如果答案为 no 那么很可能你需要定义
  • 关于转义字符&

    1 情况是这样的 就是前段传的xml参数里存在 这种特殊字符 所以前端需要转义后再传给后端 也就是 转义为 后传给后端 但是后端接收但这个参数时 会拼接url 就像下面这样的 http www xx com path api gender
  • 【Colab】基本操作【LeNet】【MNIST】训练测试

    文章目录 1 介绍 2 查看基本配置 2 1查看pytorch版本 2 2查看是否可以使用cuda 2 3查看显卡配置 3 挂载 31 挂载谷歌云盘 3 2更改运行目录 4 训练 5 Reference Colab 官网初始界面 1 介绍
  • python函数用法之numpy.mgrid

    参考链接 python笔记 numpy中mgrid的用法 布衣小张 CSDN博客 mgrid numpy中的mgrid函数 KangLongWang的博客 CSDN博客 mgrid函数 mgrid函数返回多维结构 np mgrid 第1维
  • ISP图像处理流程

    文章目录 前言 ISP图像处理流程 总结 参考 前言 因工作需要 今天看了ISP图像处理的基本流程 为了检验自己的理解情况 这里根据自己的理解写下这篇文章 如有错误 敬请原谅 ISP图像处理流程 ISP Image Sensor Proce
  • 后台管理系统项目

    1 项目名称 后台管理 2 技术栈 vue全家桶 element ui axios less eachers 3 项目亮点 性能优化 百万级项目 新旧系统更迭 权限把控 项目开发流程 1 安装vue脚手架 2 vue create 项目名称
  • MySQL-索引

    一 介绍 索引是数据库对象之一 用于提高字段检索效率 使用者只需要对哪个表中哪些字段建立索引即可 其余什么都不做 数据库会自行处理 索引提供指向存储在表的指定列中的数据值的指针 如同图书的目录 能够加快表的查询速度 但同时也增加了插入 更新
  • SpringBoot 二维码生成

    来源 https www cnblogs com songweipeng p 16623793 html 一 基于Google开发工具包ZXing生成二维码
  • 算法与数据结构之带头结点的单链表

    单链表优缺点 链表是非随机存取的存储结构 和顺序表相比 链表存储结构在实现插入 删除的操作时 不需要移动大量数据元素 但不容易实现随机存取线性表的第 i 个数据元素的操作 所以 链表适用于经常需要进行插入和删除操作的线性表 如飞机航班的乘客
  • 【机器学习 - 5】:多元线性回归

    文章目录 多元线性回归 多元线性回归公式推导 举例 波士顿房价 取特征值RM为例 取所有特证为例 多元线性回归 多元线性回归方程 特征值为两个或两个以上 以下是多元线性回归的模型 我们需要求出theta 使得真实值和预测值的差值最小 多元线
  • 前端系列19集-vue3引入高德地图,响应式,自适应

    npm i amap amap jsapi loader save import AMapLoader from amap amap jsapi loader 使用加载器加载JSAPI 可以避免异步加载 重复加载等常见错误加载错误 为地图注
  • 四种推荐系统原理介绍(基于内容过滤/协同过滤/关联规则/序列模式)

    在推荐系统中常用的技术可大致分为四类 基于内容的过滤 协同过滤 基于规则的方法和混合方法 一 基于内容过滤 基于内容过滤推荐系统思路如下 1 通过在抓取每个商品的一系列特征来构建商品档案 2 通过用户购买的商品特征来构建基于内容的用户档案
  • Jmeter怎么添加token?

    不需要token的场景 随便进入一个购物app 都是可以看里面的商品的 这时不需要token 但是当你要买它的时候就需要你登录自己的账号 登录状态需要token 什么时候需要用到token 比如 京东商城里面 我需要查看我的消息列表 这时候
  • Jenkins自动化构建网站与流水线构建Maven项目实战

    1 gitlab Jenkins自动化构建网站实战 基本架构 通过gitlab jenkins构建一个常规网站的原理图 Jenkins插件和环境配置 配置全局变量 要配置的全局变量有Git JDK和Maven 指定JDK的路径 设置Git可
  • vue2.0 vue3.0 input组件封装

    vue2
  • tar -xf node-v12.16.1-linux-armv7l.tar.xz 错误

    1 tar解压tar xz能会出错 因为你的系统里没有对应的解压工具 你安装上xz和tar对应工具包就行 apt get install xz utils 2 chmod无法访问 没有那个文件或目录 方案之一 修改 etc selinux
  • UEFI模式安装下Ubuntu 18.04 系统分区参考(win10+Ubuntu双系统)

    由于这几天给自己的电脑成功装了双系统 所以在此记录下当时在装Ubuntu系统中最难懂的部分 系统分区 以供大家以及自己今后参考 具体安装步骤我就不一一细说了 可以参考其他博主的文章 小米笔记本安装Win10 Ubuntu16 04 LTS
  • 金山卫士开源软件之旅(二) 简单教程:如何创建一个基于金山卫士界面库的工程

    完整解决方案代码压缩包 test full zip 267 59 KB 参考 http bbs code ijinshan com thread 1391 1 1 html 为了让更多的朋友能够让自己的程序使用上金山卫士的界面库 现将创建界