完整解决方案代码压缩包: 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”按钮。
在H:\MyProject\test\test下创建publish文件夹,然后到http://code.ijinshan.com下载金山卫士源代码,将其解压到某个目录,打开其子目录pcmanager\src\publish,将其下的bkres、bkwin、tinyxml和wtlhelper复制到H:\MyProject\test\test\publish下。
第二步、添加包含目录
在VS2005的“解决方案资源管理器”中,右键点击test项目(注意是项目而不是解决方案),选择属性。
第三步、将Bkres、TinyXML加入项目中
在“解决方案资源管理器”中,右键点击“Resource Files”,选择“添加”->“现有项”,定位到publish\bkres目录下,将bkres.rc添加进项目。
第四步、去除TinyXML预编译头设置
展开publish\TinyXML筛选器,右键点击一个cpp文件,选择属性。
第五步,添加必要的代码
主要是替换默认生成的WTL基本对话框的代码,转而使用调用卫士界面库的代码,并且加入卫士界面库必需的定义XML相关文件和图片资源。此处为了方便起见,将代码打包,各位可以直接从附件中下载,将文件替换掉原先创建项目时自动生成的代码,然后将新增的bkwinres.h以及bkwinres.rc2添加到项目中即可。
这里可以看到_tMain函数中的
CMainDlg dlgMain;
dlgMain.DoModal();
而构建CMainDlg的方法是:
class CMainDlg : public CBkDialogImpl
, public CWHRoundRectFrameHelper
{
public:
CMainDlg():CBkDialogImpl(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)
CHAIN_MSG_MAP(CWHRoundRectFrameHelper)
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 CWHRoundRectFrameHelper
{
protected:
SIZE m_sizeWnd;
void OnSize(UINT nType, CSize size)
{
T *pT = static_cast(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 ATL_NO_VTABLE CBkDialogImpl : public CWindowImpl
{
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 __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
得到下图,希望对大家有帮助: