zhangyang 6 лет назад
Родитель
Сommit
ea762ce1aa

+ 450 - 0
lewaimai_dispatch/CGameFrameWnd.h

@@ -0,0 +1,450 @@
+#pragma once
+
+#include "pch/pch.h"
+
+class CGameFrameWnd : public CWindowWnd, public INotifyUI, public IListCallbackUI
+{
+public:
+	CGameFrameWnd() { };
+	LPCTSTR GetWindowClassName() const { return _T("UIMainFrame"); };
+	UINT GetClassStyle() const { return CS_DBLCLKS; };
+	void OnFinalMessage(HWND /*hWnd*/) { delete this; };
+
+	void Init() {
+		m_pCloseBtn = static_cast<CButtonUI*>(m_pm.FindControl(_T("closebtn")));
+		m_pMaxBtn = static_cast<CButtonUI*>(m_pm.FindControl(_T("maxbtn")));
+		m_pRestoreBtn = static_cast<CButtonUI*>(m_pm.FindControl(_T("restorebtn")));
+		m_pMinBtn = static_cast<CButtonUI*>(m_pm.FindControl(_T("minbtn")));
+
+		CActiveXUI* pActiveXUI = static_cast<CActiveXUI*>(m_pm.FindControl(_T("ie")));
+		if (pActiveXUI) {
+			IWebBrowser2* pWebBrowser = NULL;
+			pActiveXUI->GetControl(IID_IWebBrowser2, (void**)&pWebBrowser);
+			if (pWebBrowser != NULL) {
+				pWebBrowser->Navigate(::SysAllocString(L"https://github.com/duilib/duilib"), NULL, NULL, NULL, NULL);
+				//pWebBrowser->Navigate(L"about:blank",NULL,NULL,NULL,NULL); 
+				pWebBrowser->Release();
+			}
+		}
+	}
+
+	void OnPrepare() {
+		GameListUI* pGameList = static_cast<GameListUI*>(m_pm.FindControl(_T("gamelist")));
+		GameListUI::Node* pCategoryNode = NULL;
+		GameListUI::Node* pGameNode = NULL;
+		GameListUI::Node* pServerNode = NULL;
+		GameListUI::Node* pRoomNode = NULL;
+		pCategoryNode = pGameList->AddNode(_T("{x 4}{i gameicons.png 18 3}{x 4}推荐游戏"));
+		for (int i = 0; i < 4; ++i)
+		{
+			pGameNode = pGameList->AddNode(_T("{x 4}{i gameicons.png 18 10}{x 4}四人斗地主"), pCategoryNode);
+			for (int i = 0; i < 3; ++i)
+			{
+				pServerNode = pGameList->AddNode(_T("{x 4}{i gameicons.png 18 10}{x 4}测试服务器"), pGameNode);
+				for (int i = 0; i < 3; ++i)
+				{
+					pRoomNode = pGameList->AddNode(_T("{x 4}{i gameicons.png 18 10}{x 4}测试房间"), pServerNode);
+				}
+			}
+		}
+		pCategoryNode = pGameList->AddNode(_T("{x 4}{i gameicons.png 18 3}{x 4}最近玩过的游戏"));
+		for (int i = 0; i < 2; ++i)
+		{
+			pGameList->AddNode(_T("三缺一"), pCategoryNode);
+		}
+		pCategoryNode = pGameList->AddNode(_T("{x 4}{i gameicons.png 18 3}{x 4}棋牌游戏"));
+		for (int i = 0; i < 8; ++i)
+		{
+			pGameList->AddNode(_T("双扣"), pCategoryNode);
+		}
+		pCategoryNode = pGameList->AddNode(_T("{x 4}{i gameicons.png 18 3}{x 4}休闲游戏"));
+		for (int i = 0; i < 8; ++i)
+		{
+			pGameList->AddNode(_T("飞行棋"), pCategoryNode);
+		}
+
+		CListUI* pUserList = static_cast<CListUI*>(m_pm.FindControl(_T("userlist")));
+		pUserList->SetTextCallback(this);
+		for (int i = 0; i < 400; i++) {
+			CListTextElementUI* pListElement = new CListTextElementUI;
+			pUserList->Add(pListElement);
+		}
+	}
+
+	void SendChatMessage() {
+		CEditUI* pChatEdit = static_cast<CEditUI*>(m_pm.FindControl(_T("chatEdit")));
+		if (pChatEdit == NULL) return;
+		pChatEdit->SetFocus();
+		if (pChatEdit->GetText().IsEmpty()) return;
+
+		CRichEditUI* pRichEdit = static_cast<CRichEditUI*>(m_pm.FindControl(_T("chatmsglist")));
+		if (pRichEdit == NULL) return;
+		long lSelBegin = 0, lSelEnd = 0;
+		CHARFORMAT2 cf;
+		ZeroMemory(&cf, sizeof(CHARFORMAT2));
+		cf.cbSize = sizeof(cf);
+		cf.dwReserved = 0;
+		cf.dwMask = CFM_COLOR;
+		cf.crTextColor = RGB(220, 0, 0);
+
+		lSelEnd = lSelBegin = pRichEdit->GetTextLength();
+		pRichEdit->SetSel(lSelEnd, lSelEnd);
+		pRichEdit->ReplaceSel(_T("某人"), false);
+		lSelEnd = pRichEdit->GetTextLength();
+		pRichEdit->SetSel(lSelBegin, lSelEnd);
+		pRichEdit->SetSelectionCharFormat(cf);
+
+		lSelBegin = lSelEnd;
+		pRichEdit->SetSel(-1, -1);
+		pRichEdit->ReplaceSel(_T("说:"), false);
+
+		pRichEdit->SetSel(-1, -1);
+		pRichEdit->ReplaceSel(pChatEdit->GetText(), false);
+		pChatEdit->SetText(_T(""));
+
+		pRichEdit->SetSel(-1, -1);
+		pRichEdit->ReplaceSel(_T("\n"), false);
+
+		cf.crTextColor = RGB(0, 0, 0);
+		lSelEnd = pRichEdit->GetTextLength();
+		pRichEdit->SetSel(lSelBegin, lSelEnd);
+		pRichEdit->SetSelectionCharFormat(cf);
+
+		pRichEdit->EndDown();
+	}
+
+	void Notify(TNotifyUI& msg)
+	{
+		if (msg.sType == _T("windowinit")) OnPrepare();
+		else if (msg.sType == _T("click")) {
+			if (msg.pSender == m_pCloseBtn) {
+				COptionUI* pControl = static_cast<COptionUI*>(m_pm.FindControl(_T("hallswitch")));
+				if (pControl && pControl->IsSelected() == false) {
+					CControlUI* pFadeControl = m_pm.FindControl(_T("fadeEffect"));
+					if (pFadeControl) pFadeControl->SetVisible(true);
+				}
+				else {
+					/*Close()*/PostQuitMessage(0); // 因为activex的原因,使用close可能会出现错误
+				}
+				return;
+			}
+			else if (msg.pSender == m_pMinBtn) { SendMessage(WM_SYSCOMMAND, SC_MINIMIZE, 0); return; }
+			else if (msg.pSender == m_pMaxBtn) { SendMessage(WM_SYSCOMMAND, SC_MAXIMIZE, 0); return; }
+			else if (msg.pSender == m_pRestoreBtn) { SendMessage(WM_SYSCOMMAND, SC_RESTORE, 0); return; }
+			CDuiString name = msg.pSender->GetName();
+			if (name == _T("quitbtn")) {
+				/*Close()*/PostQuitMessage(0); // 因为activex的原因,使用close可能会出现错误
+			}
+			else if (name == _T("returnhallbtn")) {
+				CControlUI* pFadeControl = m_pm.FindControl(_T("fadeEffect"));
+				if (pFadeControl) pFadeControl->SetVisible(false);
+
+				COptionUI* pControl = static_cast<COptionUI*>(m_pm.FindControl(_T("hallswitch")));
+				pControl->Activate();
+				pControl = static_cast<COptionUI*>(m_pm.FindControl(_T("roomswitch")));
+				if (pControl) pControl->SetVisible(false);
+			}
+			else if (name == _T("fontswitch")) {
+				TFontInfo* pFontInfo = m_pm.GetDefaultFontInfo();
+				if (pFontInfo->iSize < 18) {
+					TFontInfo* pFontInfo = m_pm.GetFontInfo(0);
+					if (pFontInfo)m_pm.SetDefaultFont(pFontInfo->sFontName, pFontInfo->iSize, pFontInfo->bBold,
+						pFontInfo->bUnderline, pFontInfo->bItalic);
+				}
+				else {
+					TFontInfo* pFontInfo = m_pm.GetFontInfo(1);
+					if (pFontInfo)m_pm.SetDefaultFont(pFontInfo->sFontName, pFontInfo->iSize, pFontInfo->bBold,
+						pFontInfo->bUnderline, pFontInfo->bItalic);
+				}
+				m_pm.GetRoot()->NeedUpdate();
+			}
+			else if (name == _T("leaveBtn") || name == _T("roomclosebtn")) {
+				COptionUI* pControl = static_cast<COptionUI*>(m_pm.FindControl(_T("hallswitch")));
+				if (pControl) {
+					pControl->Activate();
+					pControl = static_cast<COptionUI*>(m_pm.FindControl(_T("roomswitch")));
+					if (pControl) pControl->SetVisible(false);
+				}
+			}
+			else if (name == _T("sendbtn")) {
+				SendChatMessage();
+			}
+		}
+		else if (msg.sType == _T("selectchanged")) {
+			CDuiString name = msg.pSender->GetName();
+			if (name == _T("hallswitch")) {
+				CTabLayoutUI* pControl = static_cast<CTabLayoutUI*>(m_pm.FindControl(_T("switch")));
+				if (pControl && pControl->GetCurSel() != 0) pControl->SelectItem(0);
+			}
+			else if (name == _T("roomswitch")) {
+				CTabLayoutUI* pControl = static_cast<CTabLayoutUI*>(m_pm.FindControl(_T("switch")));
+				if (pControl && pControl->GetCurSel() != 1) {
+					pControl->SelectItem(1);
+					DeskListUI* pDeskList = static_cast<DeskListUI*>(m_pm.FindControl(_T("destlist")));
+					pDeskList->SetFocus();
+					CRichEditUI* pRichEdit = static_cast<CRichEditUI*>(m_pm.FindControl(_T("chatmsglist")));
+					if (pRichEdit) {
+						pRichEdit->SetText(_T("欢迎进入XXX游戏,祝游戏愉快!\n\n"));
+						long lSelBegin = 0, lSelEnd = 0;
+						CHARFORMAT2 cf;
+						ZeroMemory(&cf, sizeof(CHARFORMAT2));
+						cf.cbSize = sizeof(cf);
+						cf.dwReserved = 0;
+						cf.dwMask = CFM_COLOR;
+						cf.crTextColor = RGB(255, 0, 0);
+						lSelEnd = pRichEdit->GetTextLength();
+						pRichEdit->SetSel(lSelBegin, lSelEnd);
+						pRichEdit->SetSelectionCharFormat(cf);
+					}
+				}
+			}
+		}
+		else if (msg.sType == _T("itemclick")) {
+			GameListUI* pGameList = static_cast<GameListUI*>(m_pm.FindControl(_T("gamelist")));
+			if (pGameList->GetItemIndex(msg.pSender) != -1)
+			{
+				if (_tcscmp(msg.pSender->GetClass(), DUI_CTR_LISTLABELELEMENT) == 0) {
+					GameListUI::Node* node = (GameListUI::Node*)msg.pSender->GetTag();
+
+					POINT pt = { 0 };
+					::GetCursorPos(&pt);
+					::ScreenToClient(m_pm.GetPaintWindow(), &pt);
+					pt.x -= msg.pSender->GetX();
+					SIZE sz = pGameList->GetExpanderSizeX(node);
+					if (pt.x >= sz.cx && pt.x < sz.cy)
+						pGameList->ExpandNode(node, !node->data()._expand);
+				}
+			}
+		}
+		else if (msg.sType == _T("itemactivate")) {
+			GameListUI* pGameList = static_cast<GameListUI*>(m_pm.FindControl(_T("gamelist")));
+			if (pGameList->GetItemIndex(msg.pSender) != -1)
+			{
+				if (_tcscmp(msg.pSender->GetClass(), DUI_CTR_LISTLABELELEMENT) == 0) {
+					GameListUI::Node* node = (GameListUI::Node*)msg.pSender->GetTag();
+					pGameList->ExpandNode(node, !node->data()._expand);
+					if (node->data()._level == 3) {
+						COptionUI* pControl = static_cast<COptionUI*>(m_pm.FindControl(_T("roomswitch")));
+						if (pControl) {
+							pControl->SetVisible(true);
+							pControl->SetText(node->parent()->parent()->data()._text);
+							pControl->Activate();
+
+						}
+					}
+				}
+			}
+		}
+		else if (msg.sType == _T("itemselect")) {
+			if (msg.pSender->GetName() == _T("chatCombo")) {
+				CEditUI* pChatEdit = static_cast<CEditUI*>(m_pm.FindControl(_T("chatEdit")));
+				if (pChatEdit) pChatEdit->SetText(msg.pSender->GetText());
+				static_cast<CComboUI*>(msg.pSender)->SelectItem(-1);
+			}
+		}
+		else if (msg.sType == _T("return")) {
+			if (msg.pSender->GetName() == _T("chatEdit")) {
+				SendChatMessage();
+			}
+		}
+	}
+
+	LPCTSTR GetItemText(CControlUI* pControl, int iIndex, int iSubItem)
+	{
+		if (pControl->GetParent()->GetParent()->GetName() == _T("userlist")) {
+			if (iSubItem == 0) return _T("<i vip.png>");
+			if (iSubItem == 1) return _T("<i vip.png>");
+			if (iSubItem == 2) return _T("此人昵称");
+			if (iSubItem == 3) return _T("5");
+			if (iSubItem == 4) return _T("50%");
+			if (iSubItem == 5) return _T("0%");
+			if (iSubItem == 6) return _T("100");
+		}
+
+		return _T("");
+	}
+
+	LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+	{
+		LONG styleValue = ::GetWindowLong(*this, GWL_STYLE);
+		styleValue &= ~WS_CAPTION;
+		::SetWindowLong(*this, GWL_STYLE, styleValue | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
+
+		m_pm.Init(m_hWnd);
+		CDialogBuilder builder;
+		CDialogBuilderCallbackEx cb;
+
+		CControlUI* pRoot = builder.Create(_T("hall.xml"), (UINT)0, &cb, &m_pm);
+		ASSERT(pRoot && "Failed to parse XML");
+
+		m_pm.AttachDialog(pRoot);
+		m_pm.AddNotifier(this);
+
+		Init();
+		return 0;
+	}
+
+	LRESULT OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+	{
+		bHandled = FALSE;
+		return 0;
+	}
+
+	LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+	{
+		::PostQuitMessage(0L);
+
+		bHandled = FALSE;
+		return 0;
+	}
+
+	LRESULT OnNcActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+	{
+		if (::IsIconic(*this)) bHandled = FALSE;
+		return (wParam == 0) ? TRUE : FALSE;
+	}
+
+	LRESULT OnNcCalcSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+	{
+		return 0;
+	}
+
+	LRESULT OnNcPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+	{
+		return 0;
+	}
+
+	LRESULT OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+	{
+		POINT pt; pt.x = GET_X_LPARAM(lParam); pt.y = GET_Y_LPARAM(lParam);
+		::ScreenToClient(*this, &pt);
+
+		RECT rcClient;
+		::GetClientRect(*this, &rcClient);
+
+		if (!::IsZoomed(*this)) {
+			RECT rcSizeBox = m_pm.GetSizeBox();
+			if (pt.y < rcClient.top + rcSizeBox.top) {
+				if (pt.x < rcClient.left + rcSizeBox.left) return HTTOPLEFT;
+				if (pt.x > rcClient.right - rcSizeBox.right) return HTTOPRIGHT;
+				return HTTOP;
+			}
+			else if (pt.y > rcClient.bottom - rcSizeBox.bottom) {
+				if (pt.x < rcClient.left + rcSizeBox.left) return HTBOTTOMLEFT;
+				if (pt.x > rcClient.right - rcSizeBox.right) return HTBOTTOMRIGHT;
+				return HTBOTTOM;
+			}
+			if (pt.x < rcClient.left + rcSizeBox.left) return HTLEFT;
+			if (pt.x > rcClient.right - rcSizeBox.right) return HTRIGHT;
+		}
+
+		RECT rcCaption = m_pm.GetCaptionRect();
+		if (pt.x >= rcClient.left + rcCaption.left && pt.x < rcClient.right - rcCaption.right \
+			&& pt.y >= rcCaption.top && pt.y < rcCaption.bottom) {
+			CControlUI* pControl = static_cast<CControlUI*>(m_pm.FindControl(pt));
+			if (pControl && _tcscmp(pControl->GetClass(), DUI_CTR_BUTTON) != 0 &&
+				_tcscmp(pControl->GetClass(), DUI_CTR_OPTION) != 0 &&
+				_tcscmp(pControl->GetClass(), DUI_CTR_TEXT) != 0)
+				return HTCAPTION;
+		}
+
+		return HTCLIENT;
+	}
+
+	LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+	{
+		SIZE szRoundCorner = m_pm.GetRoundCorner();
+		if (!::IsIconic(*this) && (szRoundCorner.cx != 0 || szRoundCorner.cy != 0)) {
+			CDuiRect rcWnd;
+			::GetWindowRect(*this, &rcWnd);
+			rcWnd.Offset(-rcWnd.left, -rcWnd.top);
+			rcWnd.right++; rcWnd.bottom++;
+			HRGN hRgn = ::CreateRoundRectRgn(rcWnd.left, rcWnd.top, rcWnd.right, rcWnd.bottom, szRoundCorner.cx, szRoundCorner.cy);
+			::SetWindowRgn(*this, hRgn, TRUE);
+			::DeleteObject(hRgn);
+		}
+
+		bHandled = FALSE;
+		return 0;
+	}
+
+	LRESULT OnGetMinMaxInfo(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+	{
+		int primaryMonitorWidth = ::GetSystemMetrics(SM_CXSCREEN);
+		int primaryMonitorHeight = ::GetSystemMetrics(SM_CYSCREEN);
+		MONITORINFO oMonitor = {};
+		oMonitor.cbSize = sizeof(oMonitor);
+		::GetMonitorInfo(::MonitorFromWindow(*this, MONITOR_DEFAULTTOPRIMARY), &oMonitor);
+		CDuiRect rcWork = oMonitor.rcWork;
+		rcWork.Offset(-oMonitor.rcMonitor.left, -oMonitor.rcMonitor.top);
+		if (rcWork.right > primaryMonitorWidth) rcWork.right = primaryMonitorWidth;
+		if (rcWork.bottom > primaryMonitorHeight) rcWork.right = primaryMonitorHeight;
+		LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam;
+		lpMMI->ptMaxPosition.x = rcWork.left;
+		lpMMI->ptMaxPosition.y = rcWork.top;
+		lpMMI->ptMaxSize.x = rcWork.right;
+		lpMMI->ptMaxSize.y = rcWork.bottom;
+		bHandled = FALSE;
+		return 0;
+	}
+
+	LRESULT OnSysCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+	{
+		// 有时会在收到WM_NCDESTROY后收到wParam为SC_CLOSE的WM_SYSCOMMAND
+		if (wParam == SC_CLOSE) {
+			::PostQuitMessage(0L);
+			bHandled = TRUE;
+			return 0;
+		}
+		BOOL bZoomed = ::IsZoomed(*this);
+		LRESULT lRes = CWindowWnd::HandleMessage(uMsg, wParam, lParam);
+		if (::IsZoomed(*this) != bZoomed) {
+			if (!bZoomed) {
+				CControlUI* pControl = static_cast<CControlUI*>(m_pm.FindControl(_T("maxbtn")));
+				if (pControl) pControl->SetVisible(false);
+				pControl = static_cast<CControlUI*>(m_pm.FindControl(_T("restorebtn")));
+				if (pControl) pControl->SetVisible(true);
+			}
+			else {
+				CControlUI* pControl = static_cast<CControlUI*>(m_pm.FindControl(_T("maxbtn")));
+				if (pControl) pControl->SetVisible(true);
+				pControl = static_cast<CControlUI*>(m_pm.FindControl(_T("restorebtn")));
+				if (pControl) pControl->SetVisible(false);
+			}
+		}
+		return lRes;
+	}
+
+	LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
+	{
+		LRESULT lRes = 0;
+		BOOL bHandled = TRUE;
+		switch (uMsg) {
+		case WM_CREATE:        lRes = OnCreate(uMsg, wParam, lParam, bHandled); break;
+		case WM_CLOSE:         lRes = OnClose(uMsg, wParam, lParam, bHandled); break;
+		case WM_DESTROY:       lRes = OnDestroy(uMsg, wParam, lParam, bHandled); break;
+		case WM_NCACTIVATE:    lRes = OnNcActivate(uMsg, wParam, lParam, bHandled); break;
+		case WM_NCCALCSIZE:    lRes = OnNcCalcSize(uMsg, wParam, lParam, bHandled); break;
+		case WM_NCPAINT:       lRes = OnNcPaint(uMsg, wParam, lParam, bHandled); break;
+		case WM_NCHITTEST:     lRes = OnNcHitTest(uMsg, wParam, lParam, bHandled); break;
+		case WM_SIZE:          lRes = OnSize(uMsg, wParam, lParam, bHandled); break;
+		case WM_GETMINMAXINFO: lRes = OnGetMinMaxInfo(uMsg, wParam, lParam, bHandled); break;
+		case WM_SYSCOMMAND:    lRes = OnSysCommand(uMsg, wParam, lParam, bHandled); break;
+		default:
+			bHandled = FALSE;
+		}
+		if (bHandled) return lRes;
+		if (m_pm.MessageHandler(uMsg, wParam, lParam, lRes)) return lRes;
+		return CWindowWnd::HandleMessage(uMsg, wParam, lParam);
+	}
+
+public:
+	CPaintManagerUI m_pm;
+
+private:
+	CButtonUI* m_pCloseBtn;
+	CButtonUI* m_pMaxBtn;
+	CButtonUI* m_pRestoreBtn;
+	CButtonUI* m_pMinBtn;
+	//...
+};

+ 6 - 0
lewaimai_dispatch/CLoginWnd.cpp

@@ -0,0 +1,6 @@
+#include "pch/pch.h"
+
+
+
+
+

+ 196 - 0
lewaimai_dispatch/CLoginWnd.h

@@ -0,0 +1,196 @@
+#pragma once
+
+#include "pch/pch.h"
+#include "CGameFrameWnd.h"
+
+class CLoginFrameWnd : public CWindowWnd, public INotifyUI, public IMessageFilterUI
+{
+public:
+	CLoginFrameWnd()
+	{
+
+	}
+
+	LPCTSTR GetWindowClassName() const { return _T("UILoginFrame"); };
+
+	UINT GetClassStyle() const { return UI_CLASSSTYLE_DIALOG; };
+
+	void OnFinalMessage(HWND /*hWnd*/)
+	{
+		m_pm.RemovePreMessageFilter(this);
+		delete this;
+	};
+
+	void Init() {
+		CEditUI* pAccountEdit = static_cast<CEditUI*>(m_pm.FindControl(_T("accountedit")));
+		if (pAccountEdit) pAccountEdit->SetText(_T("请输入智铺子员工账号"));
+		pAccountEdit->SetFocus();
+	}
+
+	void Notify(TNotifyUI& msg)
+	{
+		if (msg.sType == _T("click"))
+		{
+			if (msg.pSender->GetName() == _T("closebtn"))
+			{ 
+				PostQuitMessage(0); 
+				return; 
+			}
+			else if (msg.pSender->GetName() == _T("loginBtn")) 
+			{
+				HandleLogin();
+				return;
+			}
+		}
+	}
+
+	LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+	{
+		LONG styleValue = ::GetWindowLong(*this, GWL_STYLE);
+		styleValue &= ~WS_CAPTION;
+		::SetWindowLong(*this, GWL_STYLE, styleValue | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
+
+		m_pm.Init(m_hWnd);
+		m_pm.AddPreMessageFilter(this);
+
+		CDialogBuilder builder;
+		CDialogBuilderCallbackEx cb;
+
+		CControlUI* pRoot = builder.Create(_T("login.xml"), (UINT)0, &cb, &m_pm);
+		ASSERT(pRoot && "Failed to parse XML");
+
+		m_pm.AttachDialog(pRoot);
+		m_pm.AddNotifier(this);
+
+		Init();
+
+		return 0;
+	}
+
+	LRESULT OnNcActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+	{
+		if (::IsIconic(*this)) bHandled = FALSE;
+		return (wParam == 0) ? TRUE : FALSE;
+	}
+
+	LRESULT OnNcCalcSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+	{
+		return 0;
+	}
+
+	LRESULT OnNcPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+	{
+		return 0;
+	}
+
+	LRESULT OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+	{
+		POINT pt; pt.x = GET_X_LPARAM(lParam); pt.y = GET_Y_LPARAM(lParam);
+		::ScreenToClient(*this, &pt);
+
+		RECT rcClient;
+		::GetClientRect(*this, &rcClient);
+
+		RECT rcCaption = m_pm.GetCaptionRect();
+		if (pt.x >= rcClient.left + rcCaption.left && pt.x < rcClient.right - rcCaption.right \
+			&& pt.y >= rcCaption.top && pt.y < rcCaption.bottom) {
+			CControlUI* pControl = static_cast<CControlUI*>(m_pm.FindControl(pt));
+			if (pControl && _tcscmp(pControl->GetClass(), DUI_CTR_BUTTON) != 0)
+				return HTCAPTION;
+		}
+
+		return HTCLIENT;
+	}
+
+	LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+	{
+		SIZE szRoundCorner = m_pm.GetRoundCorner();
+		if (!::IsIconic(*this) && (szRoundCorner.cx != 0 || szRoundCorner.cy != 0)) {
+			CDuiRect rcWnd;
+			::GetWindowRect(*this, &rcWnd);
+			rcWnd.Offset(-rcWnd.left, -rcWnd.top);
+			rcWnd.right++; rcWnd.bottom++;
+			HRGN hRgn = ::CreateRoundRectRgn(rcWnd.left, rcWnd.top, rcWnd.right, rcWnd.bottom, szRoundCorner.cx, szRoundCorner.cy);
+			::SetWindowRgn(*this, hRgn, TRUE);
+			::DeleteObject(hRgn);
+		}
+
+		bHandled = FALSE;
+		return 0;
+	}
+
+	LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
+	{
+		LRESULT lRes = 0;
+		BOOL bHandled = TRUE;
+		switch (uMsg) {
+		case WM_CREATE:        lRes = OnCreate(uMsg, wParam, lParam, bHandled); break;
+		case WM_NCACTIVATE:    lRes = OnNcActivate(uMsg, wParam, lParam, bHandled); break;
+		case WM_NCCALCSIZE:    lRes = OnNcCalcSize(uMsg, wParam, lParam, bHandled); break;
+		case WM_NCPAINT:       lRes = OnNcPaint(uMsg, wParam, lParam, bHandled); break;
+		case WM_NCHITTEST:     lRes = OnNcHitTest(uMsg, wParam, lParam, bHandled); break;
+		case WM_SIZE:          lRes = OnSize(uMsg, wParam, lParam, bHandled); break;
+		default:
+			bHandled = FALSE;
+		}
+		if (bHandled) return lRes;
+		if (m_pm.MessageHandler(uMsg, wParam, lParam, lRes)) return lRes;
+		return CWindowWnd::HandleMessage(uMsg, wParam, lParam);
+	}
+
+	LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled)
+	{
+		if (uMsg == WM_KEYDOWN)
+		{
+			if (wParam == VK_RETURN)
+			{
+				CEditUI* pEdit = static_cast<CEditUI*>(m_pm.FindControl(_T("accountedit")));
+				if (pEdit->GetText().IsEmpty())
+				{
+					pEdit->SetFocus();
+				}
+				else
+				{
+					pEdit = static_cast<CEditUI*>(m_pm.FindControl(_T("pwdedit")));
+					if (pEdit->GetText().IsEmpty())
+					{
+						pEdit->SetFocus();
+					}
+					else
+					{
+						this->HandleLogin();
+					}
+				}
+				return true;
+			}
+			else if (wParam == VK_ESCAPE)
+			{
+				PostQuitMessage(0);
+				return true;
+			}
+
+		}
+		return false;
+	}
+
+	void HandleLogin()
+	{
+		CGameFrameWnd* pFrame = new CGameFrameWnd();
+		if (pFrame == NULL)
+		{
+			return;
+		}
+
+		pFrame->SetIcon(IDI_ICON_DUILIB);
+		pFrame->Create(NULL, _T("游戏中心"), UI_WNDSTYLE_FRAME, 0L, 0, 0, 1024, 738);
+		pFrame->CenterWindow();
+
+		::ShowWindow(*pFrame, SW_SHOWMAXIMIZED);
+
+		Close();
+	}
+
+public:
+	CPaintManagerUI m_pm;
+};
+

+ 442 - 11
lewaimai_dispatch/ControlEx.h

@@ -1,28 +1,459 @@
-#pragma once
+#ifndef __CONTROLEX_H__
+#define __CONTROLEX_H__
 
-class ComputerExamineUI : public CContainerUI
+#include <vector>
+#include <math.h>
+
+inline double CalculateDelay(double state) {
+	return pow(state, 2);
+}
+
+// category(0)->game(1)->server(2)->room(3)
+class GameListUI : public CListUI
 {
 public:
-	ComputerExamineUI()
+	enum { SCROLL_TIMERID = 10 };
+
+	struct NodeData
 	{
-		CDialogBuilder builder;
-		CContainerUI* pComputerExamine = static_cast<CContainerUI*>(builder.Create(_T("ComputerExamine.xml"), (UINT)0));
-		if( pComputerExamine ) {
-			this->Add(pComputerExamine);
+		int _level;
+		bool _expand;
+		CDuiString _text;
+		CListLabelElementUI* _pListElement;
+	};
+
+	class Node
+	{
+		typedef std::vector <Node*>	Children;
+		Children	_children;
+		Node*		_parent;
+		NodeData    _data;
+
+	private:
+		void set_parent(Node* parent) { _parent = parent; }
+
+	public:
+		Node() : _parent(NULL) {}
+		explicit Node(NodeData t) : _data(t), _parent(NULL) {}
+		Node(NodeData t, Node* parent) : _data(t), _parent(parent) {}
+		~Node()
+		{
+			for (int i = 0; i < num_children(); i++)
+				delete _children[i];
+		}
+		NodeData& data() { return _data; }
+		int num_children() const { return _children.size(); }
+		Node* child(int i) { return _children[i]; }
+		Node* parent() { return (_parent); }
+		bool has_children() const { return num_children() > 0; }
+		void add_child(Node* child)
+		{
+			child->set_parent(this);
+			_children.push_back(child);
+		}
+		void remove_child(Node* child)
+		{
+			Children::iterator iter = _children.begin();
+			for (; iter < _children.end(); ++iter)
+			{
+				if (*iter == child)
+				{
+					_children.erase(iter);
+					return;
+				}
+			}
+		}
+		Node* get_last_child()
+		{
+			if (has_children())
+			{
+				return child(num_children() - 1)->get_last_child();
+			}
+			else return this;
+		}
+	};
+
+	GameListUI() : _root(NULL), m_dwDelayDeltaY(0), m_dwDelayNum(0), m_dwDelayLeft(0)
+	{
+		SetItemShowHtml(true);
+
+		_root = new Node;
+		_root->data()._level = -1;
+		_root->data()._expand = true;
+		_root->data()._pListElement = NULL;
+	}
+
+	~GameListUI() { if (_root) delete _root; }
+
+	bool Add(CControlUI* pControl)
+	{
+		if (!pControl) return false;
+		if (_tcscmp(pControl->GetClass(), DUI_CTR_LISTLABELELEMENT) != 0) return false;
+		return CListUI::Add(pControl);
+	}
+
+	bool AddAt(CControlUI* pControl, int iIndex)
+	{
+		if (!pControl) return false;
+		if (_tcscmp(pControl->GetClass(), DUI_CTR_LISTLABELELEMENT) != 0) return false;
+		return CListUI::AddAt(pControl, iIndex);
+	}
+
+	bool Remove(CControlUI* pControl, bool bDoNotDestroy = false)
+	{
+		if (!pControl) return false;
+		if (_tcscmp(pControl->GetClass(), DUI_CTR_LISTLABELELEMENT) != 0) return false;
+
+		if (reinterpret_cast<Node*>(static_cast<CListLabelElementUI*>(pControl->GetInterface(DUI_CTR_LISTLABELELEMENT))->GetTag()) == NULL)
+			return CListUI::Remove(pControl, bDoNotDestroy);
+		else
+			return RemoveNode(reinterpret_cast<Node*>(static_cast<CListLabelElementUI*>(pControl->GetInterface(DUI_CTR_LISTLABELELEMENT))->GetTag()));
+	}
+
+	bool RemoveAt(int iIndex, bool bDoNotDestroy = false)
+	{
+		CControlUI* pControl = GetItemAt(iIndex);
+		if (!pControl) return false;
+		if (_tcscmp(pControl->GetClass(), DUI_CTR_LISTLABELELEMENT) != 0) return false;
+
+		if (reinterpret_cast<Node*>(static_cast<CListLabelElementUI*>(pControl->GetInterface(DUI_CTR_LISTLABELELEMENT))->GetTag()) == NULL)
+			return CListUI::RemoveAt(iIndex, bDoNotDestroy);
+		else
+			return RemoveNode(reinterpret_cast<Node*>(static_cast<CListLabelElementUI*>(pControl->GetInterface(DUI_CTR_LISTLABELELEMENT))->GetTag()));
+	}
+
+	void RemoveAll()
+	{
+		CListUI::RemoveAll();
+		for (int i = 0; i < _root->num_children(); ++i)
+		{
+			Node* child = _root->child(i);
+			RemoveNode(child);
+		}
+		delete _root;
+		_root = new Node;
+		_root->data()._level = -1;
+		_root->data()._expand = true;
+		_root->data()._pListElement = NULL;
+	}
+	void SetVisible(bool bVisible = true)
+	{
+		if (m_bVisible == bVisible) return;
+		CControlUI::SetVisible(bVisible);
+	}
+
+	void SetInternVisible(bool bVisible = true)
+	{
+		CControlUI::SetInternVisible(bVisible);
+	}
+
+	void DoEvent(TEventUI& event)
+	{
+		if (!IsMouseEnabled() && event.Type > UIEVENT__MOUSEBEGIN && event.Type < UIEVENT__MOUSEEND) {
+			if (m_pParent != NULL) m_pParent->DoEvent(event);
+			else CVerticalLayoutUI::DoEvent(event);
+			return;
+		}
+
+		if (event.Type == UIEVENT_TIMER && event.wParam == SCROLL_TIMERID) {
+			if (m_dwDelayLeft > 0) {
+				--m_dwDelayLeft;
+				SIZE sz = GetScrollPos();
+				LONG lDeltaY = (LONG)(CalculateDelay((double)m_dwDelayLeft / m_dwDelayNum) * m_dwDelayDeltaY);
+				if ((lDeltaY > 0 && sz.cy != 0) || (lDeltaY < 0 && sz.cy != GetScrollRange().cy)) {
+					sz.cy -= lDeltaY;
+					SetScrollPos(sz);
+					return;
+				}
+			}
+			m_dwDelayDeltaY = 0;
+			m_dwDelayNum = 0;
+			m_dwDelayLeft = 0;
+			m_pManager->KillTimer(this, SCROLL_TIMERID);
+			return;
+		}
+		if (event.Type == UIEVENT_SCROLLWHEEL) {
+			LONG lDeltaY = 0;
+			if (m_dwDelayNum > 0) lDeltaY = (LONG)(CalculateDelay((double)m_dwDelayLeft / m_dwDelayNum) * m_dwDelayDeltaY);
+			switch (LOWORD(event.wParam)) {
+			case SB_LINEUP:
+				if (m_dwDelayDeltaY >= 0) m_dwDelayDeltaY = lDeltaY + 8;
+				else m_dwDelayDeltaY = lDeltaY + 12;
+				break;
+			case SB_LINEDOWN:
+				if (m_dwDelayDeltaY <= 0) m_dwDelayDeltaY = lDeltaY - 8;
+				else m_dwDelayDeltaY = lDeltaY - 12;
+				break;
+			}
+			if (m_dwDelayDeltaY > 100) m_dwDelayDeltaY = 100;
+			else if (m_dwDelayDeltaY < -100) m_dwDelayDeltaY = -100;
+			m_dwDelayNum = (DWORD)sqrt((double)abs(m_dwDelayDeltaY)) * 5;
+			m_dwDelayLeft = m_dwDelayNum;
+			m_pManager->SetTimer(this, SCROLL_TIMERID, 50U);
+			return;
+		}
+
+		CListUI::DoEvent(event);
+	}
+
+	Node* GetRoot() { return _root; }
+
+	Node* AddNode(LPCTSTR text, Node* parent = NULL)
+	{
+		if (!parent) parent = _root;
+
+		CListLabelElementUI* pListElement = new CListLabelElementUI;
+		Node* node = new Node;
+		node->data()._level = parent->data()._level + 1;
+		if (node->data()._level == 0) node->data()._expand = true;
+		else node->data()._expand = false;
+		node->data()._text = text;
+		node->data()._pListElement = pListElement;
+
+		if (parent != _root) {
+			if (!(parent->data()._expand && parent->data()._pListElement->IsVisible()))
+				pListElement->SetInternVisible(false);
+		}
+
+		CDuiString html_text;
+		html_text += _T("<x 6>");
+		for (int i = 0; i < node->data()._level; ++i) {
+			html_text += _T("<x 24>");
+		}
+		if (node->data()._level < 3) {
+			if (node->data()._expand) html_text += _T("<v center><a><i tree_expand.png 2 1></a></v>");
+			else html_text += _T("<v center><a><i tree_expand.png 2 0></a></v>");
+		}
+		html_text += node->data()._text;
+		pListElement->SetText(html_text);
+		//if( node->data()._level == 0 ) pListElement->SetFixedHeight(28);
+		//else pListElement->SetFixedHeight(24);
+		pListElement->SetTag((UINT_PTR)node);
+		if (node->data()._level == 0) {
+			pListElement->SetBkImage(_T("file='tree_top.png' corner='2,1,2,1' fade='100'"));
+		}
+
+		int index = 0;
+		if (parent->has_children()) {
+			Node* prev = parent->get_last_child();
+			index = prev->data()._pListElement->GetIndex() + 1;
 		}
 		else {
-			this->RemoveAll();
+			if (parent == _root) index = 0;
+			else index = parent->data()._pListElement->GetIndex() + 1;
+		}
+		if (!CListUI::AddAt(pListElement, index)) {
+			delete pListElement;
+			delete node;
+			node = NULL;
+		}
+		parent->add_child(node);
+		return node;
+	}
+
+	bool RemoveNode(Node* node)
+	{
+		if (!node || node == _root) return false;
+		for (int i = 0; i < node->num_children(); ++i) {
+			Node* child = node->child(i);
+			RemoveNode(child);
+		}
+		CListUI::Remove(node->data()._pListElement);
+		node->parent()->remove_child(node);
+		delete node;
+		return true;
+	}
+
+	void ExpandNode(Node* node, bool expand)
+	{
+		if (!node || node == _root) return;
+
+		if (node->data()._expand == expand) return;
+		node->data()._expand = expand;
+
+		CDuiString html_text;
+		html_text += _T("<x 6>");
+		for (int i = 0; i < node->data()._level; ++i) {
+			html_text += _T("<x 24>");
+		}
+		if (node->data()._level < 3) {
+			if (node->data()._expand) html_text += _T("<v center><a><i tree_expand.png 2 1></a></v>");
+			else html_text += _T("<v center><a><i tree_expand.png 2 0></a></v>");
+		}
+		html_text += node->data()._text;
+		node->data()._pListElement->SetText(html_text);
+
+		if (!node->data()._pListElement->IsVisible()) return;
+		if (!node->has_children()) return;
+
+		Node* begin = node->child(0);
+		Node* end = node->get_last_child();
+		for (int i = begin->data()._pListElement->GetIndex(); i <= end->data()._pListElement->GetIndex(); ++i) {
+			CControlUI* control = GetItemAt(i);
+			if (_tcscmp(control->GetClass(), DUI_CTR_LISTLABELELEMENT) == 0) {
+				Node* local_parent = ((GameListUI::Node*)control->GetTag())->parent();
+				control->SetInternVisible(local_parent->data()._expand && local_parent->data()._pListElement->IsVisible());
+			}
+		}
+		NeedUpdate();
+	}
+
+	SIZE GetExpanderSizeX(Node* node) const
+	{
+		if (!node || node == _root) return CDuiSize();
+		if (node->data()._level >= 3) return CDuiSize();
+
+		SIZE szExpander = { 0 };
+		szExpander.cx = 6 + 24 * node->data()._level - 4/*适当放大一点*/;
+		szExpander.cy = szExpander.cx + 16 + 8/*适当放大一点*/;
+		return szExpander;
+	}
+
+private:
+	Node* _root;
+
+	LONG m_dwDelayDeltaY;
+	DWORD m_dwDelayNum;
+	DWORD m_dwDelayLeft;
+};
+
+class DeskListUI : public CTileLayoutUI
+{
+public:
+	enum { SCROLL_TIMERID = 10 };
+
+	DeskListUI() : m_uButtonState(0), m_dwDelayDeltaY(0), m_dwDelayNum(0), m_dwDelayLeft(0)
+	{
+		SetItemSize(CDuiSize(182, 152));
+		CDialogBuilder builder;
+		CContainerUI* pDesk = static_cast<CContainerUI*>(builder.Create(_T("desk.xml"), (UINT)0));
+		if (pDesk != NULL) {
+			for (int i = 0; i < 500; ++i)
+			{
+				if (pDesk == NULL) pDesk = static_cast<CContainerUI*>(builder.Create());
+				if (pDesk != NULL) {
+					this->Add(pDesk);
+					TCHAR indexBuffer[16];
+					CDuiString strIndexString = _T("- ");
+					strIndexString += _itot(i + 1, indexBuffer, 10);
+					strIndexString += _T(" -");
+					pDesk->GetItemAt(3)->SetText(strIndexString);
+					pDesk = NULL;
+				}
+				else {
+					this->RemoveAll();
+					return;
+				}
+			}
+		}
+	}
+
+	void DoEvent(TEventUI& event)
+	{
+		if (!IsMouseEnabled() && event.Type > UIEVENT__MOUSEBEGIN && event.Type < UIEVENT__MOUSEEND) {
+			if (m_pParent != NULL) m_pParent->DoEvent(event);
+			else CTileLayoutUI::DoEvent(event);
 			return;
 		}
+
+		if (event.Type == UIEVENT_TIMER && event.wParam == SCROLL_TIMERID)
+		{
+			if ((m_uButtonState & UISTATE_CAPTURED) != 0) {
+				POINT pt = m_pManager->GetMousePos();
+				LONG cy = (pt.y - m_ptLastMouse.y);
+				m_ptLastMouse = pt;
+				SIZE sz = GetScrollPos();
+				sz.cy -= cy;
+				SetScrollPos(sz);
+				return;
+			}
+			else if (m_dwDelayLeft > 0) {
+				--m_dwDelayLeft;
+				SIZE sz = GetScrollPos();
+				LONG lDeltaY = (LONG)(CalculateDelay((double)m_dwDelayLeft / m_dwDelayNum) * m_dwDelayDeltaY);
+				if ((lDeltaY > 0 && sz.cy != 0) || (lDeltaY < 0 && sz.cy != GetScrollRange().cy)) {
+					sz.cy -= lDeltaY;
+					SetScrollPos(sz);
+					return;
+				}
+			}
+			m_dwDelayDeltaY = 0;
+			m_dwDelayNum = 0;
+			m_dwDelayLeft = 0;
+			m_pManager->KillTimer(this, SCROLL_TIMERID);
+			return;
+		}
+		if (event.Type == UIEVENT_BUTTONDOWN && IsEnabled())
+		{
+			m_uButtonState |= UISTATE_CAPTURED;
+			m_ptLastMouse = event.ptMouse;
+			m_dwDelayDeltaY = 0;
+			m_dwDelayNum = 0;
+			m_dwDelayLeft = 0;
+			::SetCursor(::LoadCursor(NULL, MAKEINTRESOURCE(IDC_HAND)));
+			m_pManager->SetTimer(this, SCROLL_TIMERID, 50U);
+			return;
+		}
+		if (event.Type == UIEVENT_BUTTONUP)
+		{
+			if ((m_uButtonState & UISTATE_CAPTURED) != 0) {
+				m_uButtonState &= ~UISTATE_CAPTURED;
+				::SetCursor(::LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW)));
+				if (m_ptLastMouse.y != event.ptMouse.y) {
+					m_dwDelayDeltaY = (event.ptMouse.y - m_ptLastMouse.y);
+					if (m_dwDelayDeltaY > 120) m_dwDelayDeltaY = 120;
+					else if (m_dwDelayDeltaY < -120) m_dwDelayDeltaY = -120;
+					m_dwDelayNum = (DWORD)sqrt((double)abs(m_dwDelayDeltaY)) * 5;
+					m_dwDelayLeft = m_dwDelayNum;
+				}
+				else
+					m_pManager->KillTimer(this, SCROLL_TIMERID);
+			}
+			return;
+		}
+		if (event.Type == UIEVENT_SCROLLWHEEL)
+		{
+			LONG lDeltaY = 0;
+			if (m_dwDelayNum > 0) lDeltaY = (LONG)(CalculateDelay((double)m_dwDelayLeft / m_dwDelayNum) * m_dwDelayDeltaY);
+			switch (LOWORD(event.wParam)) {
+			case SB_LINEUP:
+				if (m_dwDelayDeltaY >= 0) m_dwDelayDeltaY = lDeltaY + 8;
+				else m_dwDelayDeltaY = lDeltaY + 12;
+				break;
+			case SB_LINEDOWN:
+				if (m_dwDelayDeltaY <= 0) m_dwDelayDeltaY = lDeltaY - 8;
+				else m_dwDelayDeltaY = lDeltaY - 12;
+				break;
+			}
+			if (m_dwDelayDeltaY > 100) m_dwDelayDeltaY = 100;
+			else if (m_dwDelayDeltaY < -100) m_dwDelayDeltaY = -100;
+			m_dwDelayNum = (DWORD)sqrt((double)abs(m_dwDelayDeltaY)) * 5;
+			m_dwDelayLeft = m_dwDelayNum;
+			m_pManager->SetTimer(this, SCROLL_TIMERID, 50U);
+			return;
+		}
+		CTileLayoutUI::DoEvent(event);
 	}
+
+private:
+	UINT m_uButtonState;
+	POINT m_ptLastMouse;
+	LONG m_dwDelayDeltaY;
+	DWORD m_dwDelayNum;
+	DWORD m_dwDelayLeft;
 };
 
+
 class CDialogBuilderCallbackEx : public IDialogBuilderCallback
 {
 public:
-	CControlUI* CreateControl(LPCTSTR pstrClass) 
+	CControlUI* CreateControl(LPCTSTR pstrClass)
 	{
-		if( _tcscmp(pstrClass, _T("ComputerExamine")) == 0 ) return new ComputerExamineUI;
+		if (_tcscmp(pstrClass, _T("GameList")) == 0) return new GameListUI;
+		else if (_tcscmp(pstrClass, _T("DeskList")) == 0) return new DeskListUI;
 		return NULL;
 	}
-};
+};
+
+
+#endif __CONTROLEX_H__

+ 319 - 0
lewaimai_dispatch/MiniDumper.cpp

@@ -0,0 +1,319 @@
+#include <windows.h>
+#include <stdio.h>
+#include <assert.h>
+#include <time.h>
+#include <tchar.h>
+#include <dbghelp.h>
+#include "miniDumper.h"
+
+#ifdef UNICODE
+    #define _tcssprintf wsprintf
+    #define tcsplitpath _wsplitpath
+#else
+    #define _tcssprintf sprintf
+    #define tcsplitpath _splitpath
+#endif
+
+const int USER_DATA_BUFFER_SIZE = 4096;
+
+//-----------------------------------------------------------------------------
+// GLOBALS
+//-----------------------------------------------------------------------------
+CMiniDumper* CMiniDumper::s_pMiniDumper = NULL;
+LPCRITICAL_SECTION CMiniDumper::s_pCriticalSection = NULL;
+
+// Based on dbghelp.h
+typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess,
+                                         DWORD dwPid,
+                                         HANDLE hFile,
+                                         MINIDUMP_TYPE DumpType,
+                                         CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
+                                         CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
+                                         CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
+
+//-----------------------------------------------------------------------------
+// Name: CMiniDumper()
+// Desc: Constructor
+//-----------------------------------------------------------------------------
+CMiniDumper::CMiniDumper( bool bPromptUserForMiniDump )
+{
+	// Our CMiniDumper should act alone as a singleton.
+	assert( !s_pMiniDumper );
+
+    s_pMiniDumper = this;
+    m_bPromptUserForMiniDump = bPromptUserForMiniDump;
+
+    // The SetUnhandledExceptionFilter function enables an application to 
+    // supersede the top-level exception handler of each thread and process.
+    // After calling this function, if an exception occurs in a process 
+    // that is not being debugged, and the exception makes it to the 
+    // unhandled exception filter, that filter will call the exception 
+    // filter function specified by the lpTopLevelExceptionFilter parameter.
+	::SetUnhandledExceptionFilter( unhandledExceptionHandler );
+
+    // Since DBGHELP.dll is not inherently thread-safe, making calls into it 
+    // from more than one thread simultaneously may yield undefined behavior. 
+    // This means that if your application has multiple threads, or is 
+    // called by multiple threads in a non-synchronized manner, you need to  
+    // make sure that all calls into DBGHELP.dll are isolated via a global
+    // critical section.
+    s_pCriticalSection = new CRITICAL_SECTION;
+
+    if( s_pCriticalSection )
+        InitializeCriticalSection( s_pCriticalSection );
+}
+
+//-----------------------------------------------------------------------------
+// Name: ~CMiniDumper()
+// Desc: Destructor
+//-----------------------------------------------------------------------------
+CMiniDumper::~CMiniDumper( void )
+{
+    if( s_pCriticalSection )
+    {
+        DeleteCriticalSection( s_pCriticalSection );
+        delete s_pCriticalSection;
+    }
+}
+
+//-----------------------------------------------------------------------------
+// Name: unhandledExceptionHandler()
+// Desc: Call-back filter function for unhandled exceptions
+//-----------------------------------------------------------------------------
+LONG CMiniDumper::unhandledExceptionHandler( _EXCEPTION_POINTERS *pExceptionInfo )
+{
+	if( !s_pMiniDumper )
+		return EXCEPTION_CONTINUE_SEARCH;
+
+	return s_pMiniDumper->writeMiniDump( pExceptionInfo );
+}
+
+//-----------------------------------------------------------------------------
+// Name: setMiniDumpFileName()
+// Desc: 
+//-----------------------------------------------------------------------------
+void CMiniDumper::setMiniDumpFileName( void )
+{
+    time_t currentTime;
+    time( &currentTime );
+
+    _tcssprintf( m_szMiniDumpPath,
+                 _T( "%s%s.%ld.dmp" ),
+                 m_szAppPath,
+                 m_szAppBaseName,
+                 currentTime );
+}
+
+//-----------------------------------------------------------------------------
+// Name: getImpersonationToken()
+// Desc: The method acts as a potential workaround for the fact that the 
+//       current thread may not have a token assigned to it, and if not, the 
+//       process token is received.
+//-----------------------------------------------------------------------------
+bool CMiniDumper::getImpersonationToken( HANDLE* phToken )
+{
+    *phToken = NULL;
+
+    if( !OpenThreadToken( GetCurrentThread(),
+                          TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
+                          TRUE,
+                          phToken) )
+    {
+        if( GetLastError() == ERROR_NO_TOKEN )
+        {
+            // No impersonation token for the current thread is available. 
+            // Let's go for the process token instead.
+            if( !OpenProcessToken( GetCurrentProcess(),
+                                   TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
+                                   phToken) )
+                return false;
+        }
+        else
+            return false;
+    }
+
+    return true;
+}
+
+//-----------------------------------------------------------------------------
+// Name: enablePrivilege()
+// Desc: Since a MiniDump contains a lot of meta-data about the OS and 
+//       application state at the time of the dump, it is a rather privileged 
+//       operation. This means we need to set the SeDebugPrivilege to be able 
+//       to call MiniDumpWriteDump.
+//-----------------------------------------------------------------------------
+BOOL CMiniDumper::enablePrivilege( LPCTSTR pszPriv, HANDLE hToken, TOKEN_PRIVILEGES* ptpOld )
+{
+    BOOL bOk = FALSE;
+
+    TOKEN_PRIVILEGES tp;
+    tp.PrivilegeCount = 1;
+    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+    bOk = LookupPrivilegeValue( 0, pszPriv, &tp.Privileges[0].Luid );
+
+    if( bOk )
+    {
+        DWORD cbOld = sizeof(*ptpOld);
+        bOk = AdjustTokenPrivileges( hToken, FALSE, &tp, cbOld, ptpOld, &cbOld );
+    }
+
+    return (bOk && (ERROR_NOT_ALL_ASSIGNED != GetLastError()));
+}
+
+//-----------------------------------------------------------------------------
+// Name: restorePrivilege()
+// Desc: 
+//-----------------------------------------------------------------------------
+BOOL CMiniDumper::restorePrivilege( HANDLE hToken, TOKEN_PRIVILEGES* ptpOld )
+{
+    BOOL bOk = AdjustTokenPrivileges(hToken, FALSE, ptpOld, 0, NULL, NULL);
+    return ( bOk && (ERROR_NOT_ALL_ASSIGNED != GetLastError()) );
+}
+
+//-----------------------------------------------------------------------------
+// Name: writeMiniDump()
+// Desc: 
+//-----------------------------------------------------------------------------
+LONG CMiniDumper::writeMiniDump( _EXCEPTION_POINTERS *pExceptionInfo )
+{
+	LONG retval = EXCEPTION_CONTINUE_SEARCH;
+	m_pExceptionInfo = pExceptionInfo;
+
+    HANDLE hImpersonationToken = NULL;
+    if( !getImpersonationToken( &hImpersonationToken ) )
+        return FALSE;
+
+	// You have to find the right dbghelp.dll. 
+	// Look next to the EXE first since the one in System32 might be old (Win2k)
+	
+	HMODULE hDll = NULL;
+	TCHAR szDbgHelpPath[MAX_PATH];
+
+	if( GetModuleFileName( NULL, m_szAppPath, _MAX_PATH ) )
+	{
+		TCHAR *pSlash = _tcsrchr( m_szAppPath, '\\' );
+
+		if( pSlash )
+		{
+			_tcscpy_s( m_szAppBaseName, pSlash + 1);
+			*(pSlash+1) = 0;
+		}
+
+		_tcscpy_s( szDbgHelpPath, m_szAppPath );
+        _tcscat_s( szDbgHelpPath, _T("DBGHELP.DLL") );
+		hDll = ::LoadLibrary( szDbgHelpPath );
+	}
+
+	if( hDll == NULL )
+	{
+		// If we haven't found it yet - try one more time.
+		hDll = ::LoadLibrary( _T("DBGHELP.DLL") );
+	}
+
+	LPCTSTR szResult = NULL;
+
+	if( hDll )
+	{
+        // Get the address of the MiniDumpWriteDump function, which writes 
+        // user-mode mini-dump information to a specified file.
+		MINIDUMPWRITEDUMP MiniDumpWriteDump = 
+            (MINIDUMPWRITEDUMP)::GetProcAddress( hDll, "MiniDumpWriteDump" );
+
+		if( MiniDumpWriteDump != NULL )
+        {
+			TCHAR szScratch[USER_DATA_BUFFER_SIZE];
+
+			setMiniDumpFileName();
+
+			// Ask the user if he or she wants to save a mini-dump file...
+			_tcssprintf( szScratch,
+                         _T("There was an unexpected error:\n\nWould you ")
+                         _T("like to create a mini-dump file?\n\n%s " ),
+                         m_szMiniDumpPath);
+
+			// Create the mini-dump file...
+			HANDLE hFile = ::CreateFile( m_szMiniDumpPath, 
+                                            GENERIC_WRITE, 
+                                            FILE_SHARE_WRITE, 
+                                            NULL, 
+                                            CREATE_ALWAYS, 
+                                            FILE_ATTRIBUTE_NORMAL, 
+                                            NULL );
+
+			if( hFile != INVALID_HANDLE_VALUE )
+			{
+				_MINIDUMP_EXCEPTION_INFORMATION ExInfo;
+				ExInfo.ThreadId          = ::GetCurrentThreadId();
+				ExInfo.ExceptionPointers = pExceptionInfo;
+				ExInfo.ClientPointers    = NULL;
+
+                // We need the SeDebugPrivilege to be able to run MiniDumpWriteDump
+                TOKEN_PRIVILEGES tp;
+                BOOL bPrivilegeEnabled = enablePrivilege( SE_DEBUG_NAME, hImpersonationToken, &tp );
+
+                BOOL bOk;
+
+                // DBGHELP.dll is not thread-safe, so we need to restrict access...
+                EnterCriticalSection( s_pCriticalSection );
+                {
+					// Write out the mini-dump data to the file...
+                    bOk = MiniDumpWriteDump( GetCurrentProcess(),
+                                                GetCurrentProcessId(),
+                                                hFile,
+                                                MiniDumpNormal,
+                                                &ExInfo,
+                                                NULL,
+                                                NULL );
+                }
+                LeaveCriticalSection( s_pCriticalSection );
+
+                // Restore the privileges when done
+                if( bPrivilegeEnabled )
+	                restorePrivilege( hImpersonationToken, &tp );
+
+                if( bOk )
+				{
+					szResult = NULL;
+					retval = EXCEPTION_EXECUTE_HANDLER;
+				}
+				else
+				{
+					_tcssprintf( szScratch,
+                                    _T("Failed to save the mini-dump file to '%s' (error %d)"),
+                                    m_szMiniDumpPath,
+                                    GetLastError() );
+
+					szResult = szScratch;
+				}
+
+				::CloseHandle( hFile );
+			}
+			else
+			{
+				_tcssprintf( szScratch,
+                                _T("Failed to create the mini-dump file '%s' (error %d)"),
+                                m_szMiniDumpPath,
+                                GetLastError() );
+
+				szResult = szScratch;
+			}
+		}
+		else
+		{
+			szResult = _T( "Call to GetProcAddress failed to find MiniDumpWriteDump. ")
+                       _T("The DBGHELP.DLL is possibly outdated." );
+		}
+	}
+	else
+	{
+		szResult = _T( "Call to LoadLibrary failed to find DBGHELP.DLL." );
+	}
+
+	if( szResult && m_bPromptUserForMiniDump )
+		::MessageBox( NULL, szResult, NULL, MB_OK );
+
+	TerminateProcess( GetCurrentProcess(), 0 );
+
+	return retval;
+}
+

+ 32 - 0
lewaimai_dispatch/MiniDumper.h

@@ -0,0 +1,32 @@
+#ifndef MINIDUMPER_H
+#define MINIDUMPER_H
+
+#include <windows.h>
+
+class CMiniDumper
+{
+public:
+
+    CMiniDumper(bool bPromptUserForMiniDump);
+    ~CMiniDumper(void);
+
+private:
+
+    static LONG WINAPI unhandledExceptionHandler(struct _EXCEPTION_POINTERS *pExceptionInfo);
+    void setMiniDumpFileName(void);
+    bool getImpersonationToken(HANDLE* phToken);
+    BOOL enablePrivilege(LPCTSTR pszPriv, HANDLE hToken, TOKEN_PRIVILEGES* ptpOld);
+    BOOL restorePrivilege(HANDLE hToken, TOKEN_PRIVILEGES* ptpOld);
+    LONG writeMiniDump(_EXCEPTION_POINTERS *pExceptionInfo );
+
+    _EXCEPTION_POINTERS *m_pExceptionInfo;
+    TCHAR m_szMiniDumpPath[MAX_PATH];
+    TCHAR m_szAppPath[MAX_PATH];
+    TCHAR m_szAppBaseName[MAX_PATH];
+    bool m_bPromptUserForMiniDump;
+
+    static CMiniDumper* s_pMiniDumper;
+    static LPCRITICAL_SECTION s_pCriticalSection;
+};
+
+#endif // MINIDUMPER_H

BIN
lewaimai_dispatch/duilib.ico


+ 21 - 258
lewaimai_dispatch/lewaimai_dispatch_windows.cpp

@@ -1,270 +1,33 @@
 #include "pch/pch.h"
 
-#include <exdisp.h>
-#include <comdef.h>
-#include "ControlEx.h"
+#include "CLoginWnd.h"
+#include "CGameFrameWnd.h"
 
-class C360SafeFrameWnd : public CWindowWnd, public INotifyUI
-{
-public:
-	C360SafeFrameWnd() { };
-	LPCTSTR GetWindowClassName() const { return _T("UIMainFrame"); };
-	UINT GetClassStyle() const { return CS_DBLCLKS; };
-	void OnFinalMessage(HWND /*hWnd*/) { delete this; };
-
-	void Init() {
-		m_pCloseBtn = static_cast<CButtonUI*>(m_pm.FindControl(_T("closebtn")));
-		m_pMaxBtn = static_cast<CButtonUI*>(m_pm.FindControl(_T("maxbtn")));
-		m_pRestoreBtn = static_cast<CButtonUI*>(m_pm.FindControl(_T("restorebtn")));
-		m_pMinBtn = static_cast<CButtonUI*>(m_pm.FindControl(_T("minbtn")));
-	}
-
-	void OnPrepare() {
-	}
-
-	void Notify(TNotifyUI& msg)
-	{
-		if (msg.sType == _T("windowinit")) OnPrepare();
-		else if (msg.sType == _T("click")) {
-			if (msg.pSender == m_pCloseBtn) {
-				PostQuitMessage(0);
-				return;
-			}
-			else if (msg.pSender == m_pMinBtn) {
-				SendMessage(WM_SYSCOMMAND, SC_MINIMIZE, 0); return;
-			}
-			else if (msg.pSender == m_pMaxBtn) {
-				SendMessage(WM_SYSCOMMAND, SC_MAXIMIZE, 0); return;
-			}
-			else if (msg.pSender == m_pRestoreBtn) {
-				SendMessage(WM_SYSCOMMAND, SC_RESTORE, 0); return;
-			}
-		}
-		else if (msg.sType == _T("selectchanged"))
-		{
-			CDuiString name = msg.pSender->GetName();
-			CTabLayoutUI* pControl = static_cast<CTabLayoutUI*>(m_pm.FindControl(_T("switch")));
-			if (name == _T("examine"))
-				pControl->SelectItem(0);
-			else if (name == _T("trojan"))
-				pControl->SelectItem(1);
-			else if (name == _T("plugins"))
-				pControl->SelectItem(2);
-			else if (name == _T("vulnerability"))
-				pControl->SelectItem(3);
-			else if (name == _T("rubbish"))
-				pControl->SelectItem(4);
-			else if (name == _T("cleanup"))
-				pControl->SelectItem(5);
-			else if (name == _T("fix"))
-				pControl->SelectItem(6);
-			else if (name == _T("tool"))
-				pControl->SelectItem(7);
-		}
-	}
-
-	LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-	{
-		LONG styleValue = ::GetWindowLong(*this, GWL_STYLE);
-		styleValue &= ~WS_CAPTION;
-		::SetWindowLong(*this, GWL_STYLE, styleValue | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
-
-		m_pm.Init(m_hWnd);
-		CDialogBuilder builder;
-		CDialogBuilderCallbackEx cb;
-		CControlUI* pRoot = builder.Create(_T("skin.xml"), (UINT)0, &cb, &m_pm);
-		ASSERT(pRoot && "Failed to parse XML");
-		m_pm.AttachDialog(pRoot);
-		m_pm.AddNotifier(this);
-
-		Init();
-		return 0;
-	}
-
-	LRESULT OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-	{
-		bHandled = FALSE;
-		return 0;
-	}
-
-	LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-	{
-		::PostQuitMessage(0L);
-
-		bHandled = FALSE;
-		return 0;
-	}
-
-	LRESULT OnNcActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-	{
-		if (::IsIconic(*this)) bHandled = FALSE;
-		return (wParam == 0) ? TRUE : FALSE;
-	}
-
-	LRESULT OnNcCalcSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-	{
-		return 0;
-	}
-
-	LRESULT OnNcPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-	{
-		return 0;
-	}
-
-	LRESULT OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-	{
-		POINT pt; pt.x = GET_X_LPARAM(lParam); pt.y = GET_Y_LPARAM(lParam);
-		::ScreenToClient(*this, &pt);
-
-		RECT rcClient;
-		::GetClientRect(*this, &rcClient);
+#include "MiniDumper.h"
+CMiniDumper g_miniDumper(true);
 
-		// 		if( !::IsZoomed(*this) ) {
-		// 			RECT rcSizeBox = m_pm.GetSizeBox();
-		// 			if( pt.y < rcClient.top + rcSizeBox.top ) {
-		// 				if( pt.x < rcClient.left + rcSizeBox.left ) return HTTOPLEFT;
-		// 				if( pt.x > rcClient.right - rcSizeBox.right ) return HTTOPRIGHT;
-		// 				return HTTOP;
-		// 			}
-		// 			else if( pt.y > rcClient.bottom - rcSizeBox.bottom ) {
-		// 				if( pt.x < rcClient.left + rcSizeBox.left ) return HTBOTTOMLEFT;
-		// 				if( pt.x > rcClient.right - rcSizeBox.right ) return HTBOTTOMRIGHT;
-		// 				return HTBOTTOM;
-		// 			}
-		// 			if( pt.x < rcClient.left + rcSizeBox.left ) return HTLEFT;
-		// 			if( pt.x > rcClient.right - rcSizeBox.right ) return HTRIGHT;
-		// 		}
-
-		RECT rcCaption = m_pm.GetCaptionRect();
-		if (pt.x >= rcClient.left + rcCaption.left && pt.x < rcClient.right - rcCaption.right \
-			&& pt.y >= rcCaption.top && pt.y < rcCaption.bottom) {
-			CControlUI* pControl = static_cast<CControlUI*>(m_pm.FindControl(pt));
-			if (pControl && _tcscmp(pControl->GetClass(), DUI_CTR_BUTTON) != 0 &&
-				_tcscmp(pControl->GetClass(), DUI_CTR_OPTION) != 0 &&
-				_tcscmp(pControl->GetClass(), DUI_CTR_TEXT) != 0)
-				return HTCAPTION;
-		}
-
-		return HTCLIENT;
-	}
-
-	LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-	{
-		SIZE szRoundCorner = m_pm.GetRoundCorner();
-		if (!::IsIconic(*this) && (szRoundCorner.cx != 0 || szRoundCorner.cy != 0)) {
-			CDuiRect rcWnd;
-			::GetWindowRect(*this, &rcWnd);
-			rcWnd.Offset(-rcWnd.left, -rcWnd.top);
-			rcWnd.right++; rcWnd.bottom++;
-			HRGN hRgn = ::CreateRoundRectRgn(rcWnd.left, rcWnd.top, rcWnd.right, rcWnd.bottom, szRoundCorner.cx, szRoundCorner.cy);
-			::SetWindowRgn(*this, hRgn, TRUE);
-			::DeleteObject(hRgn);
-		}
-
-		bHandled = FALSE;
-		return 0;
-	}
-
-	LRESULT OnGetMinMaxInfo(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-	{
-		MONITORINFO oMonitor = {};
-		oMonitor.cbSize = sizeof(oMonitor);
-		::GetMonitorInfo(::MonitorFromWindow(*this, MONITOR_DEFAULTTOPRIMARY), &oMonitor);
-		CDuiRect rcWork = oMonitor.rcWork;
-		rcWork.Offset(-oMonitor.rcMonitor.left, -oMonitor.rcMonitor.top);
-
-		LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam;
-		lpMMI->ptMaxPosition.x = rcWork.left;
-		lpMMI->ptMaxPosition.y = rcWork.top;
-		lpMMI->ptMaxSize.x = rcWork.right;
-		lpMMI->ptMaxSize.y = rcWork.bottom;
-
-		bHandled = FALSE;
-		return 0;
-	}
-
-	LRESULT OnSysCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-	{
-		// 有时会在收到WM_NCDESTROY后收到wParam为SC_CLOSE的WM_SYSCOMMAND
-		if (wParam == SC_CLOSE) {
-			::PostQuitMessage(0L);
-			bHandled = TRUE;
-			return 0;
-		}
-		BOOL bZoomed = ::IsZoomed(*this);
-		LRESULT lRes = CWindowWnd::HandleMessage(uMsg, wParam, lParam);
-		if (::IsZoomed(*this) != bZoomed) {
-			if (!bZoomed) {
-				CControlUI* pControl = static_cast<CControlUI*>(m_pm.FindControl(_T("maxbtn")));
-				if (pControl) pControl->SetVisible(false);
-				pControl = static_cast<CControlUI*>(m_pm.FindControl(_T("restorebtn")));
-				if (pControl) pControl->SetVisible(true);
-			}
-			else {
-				CControlUI* pControl = static_cast<CControlUI*>(m_pm.FindControl(_T("maxbtn")));
-				if (pControl) pControl->SetVisible(true);
-				pControl = static_cast<CControlUI*>(m_pm.FindControl(_T("restorebtn")));
-				if (pControl) pControl->SetVisible(false);
-			}
-		}
-		return lRes;
-	}
-
-	LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
-	{
-		LRESULT lRes = 0;
-		BOOL bHandled = TRUE;
-		switch (uMsg) {
-		case WM_CREATE:        lRes = OnCreate(uMsg, wParam, lParam, bHandled); break;
-		case WM_CLOSE:         lRes = OnClose(uMsg, wParam, lParam, bHandled); break;
-		case WM_DESTROY:       lRes = OnDestroy(uMsg, wParam, lParam, bHandled); break;
-		case WM_NCACTIVATE:    lRes = OnNcActivate(uMsg, wParam, lParam, bHandled); break;
-		case WM_NCCALCSIZE:    lRes = OnNcCalcSize(uMsg, wParam, lParam, bHandled); break;
-		case WM_NCPAINT:       lRes = OnNcPaint(uMsg, wParam, lParam, bHandled); break;
-		case WM_NCHITTEST:     lRes = OnNcHitTest(uMsg, wParam, lParam, bHandled); break;
-		case WM_SIZE:          lRes = OnSize(uMsg, wParam, lParam, bHandled); break;
-		case WM_GETMINMAXINFO: lRes = OnGetMinMaxInfo(uMsg, wParam, lParam, bHandled); break;
-		case WM_SYSCOMMAND:    lRes = OnSysCommand(uMsg, wParam, lParam, bHandled); break;
-		default:
-			bHandled = FALSE;
-		}
-		if (bHandled) return lRes;
-		if (m_pm.MessageHandler(uMsg, wParam, lParam, lRes)) return lRes;
-		return CWindowWnd::HandleMessage(uMsg, wParam, lParam);
-	}
-
-public:
-	CPaintManagerUI m_pm;
-
-private:
-	CButtonUI* m_pCloseBtn;
-	CButtonUI* m_pMaxBtn;
-	CButtonUI* m_pRestoreBtn;
-	CButtonUI* m_pMinBtn;
-	//...
-};
-
-int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int nCmdShow)
+int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
+	_In_opt_ HINSTANCE hPrevInstance,
+	_In_ LPWSTR    lpCmdLine,
+	_In_ int       nCmdShow)
 {
-	//初始化日志
-	//CLewaimaiLog log;
-	//log.Init();
-
-	//读取配置文件
-	//CConfigReader::ReadConfigFile();
-
 	CPaintManagerUI::SetInstance(hInstance);
+#if 0
 	CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath() + _T("skin"));
-	CPaintManagerUI::SetResourceZip(_T("360SafeRes.zip"));
+	CPaintManagerUI::SetResourceZip(_T("GameRes.zip"));
+#else
+	CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath() + _T("skin/GameRes"));
+#endif
 
 	HRESULT Hr = ::CoInitialize(NULL);
-	if (FAILED(Hr)) return 0;
-
-	C360SafeFrameWnd* pFrame = new C360SafeFrameWnd();
-	if (pFrame == NULL) return 0;
-	pFrame->Create(NULL, _T("360安全卫士"), UI_WNDSTYLE_FRAME, 0L, 0, 0, 800, 572);
-	pFrame->CenterWindow();
-	::ShowWindow(*pFrame, SW_SHOW);
+	if (FAILED(Hr)) return 0;	
+
+	CLoginFrameWnd* pLoginFrame = new CLoginFrameWnd();
+	if (pLoginFrame == NULL) { return 0; }
+	pLoginFrame->Create(NULL, _T("请登录"), UI_WNDSTYLE_DIALOG, 0, 0, 0, 0, 0, NULL);
+	pLoginFrame->SetIcon(IDI_ICON_DUILIB);
+	pLoginFrame->CenterWindow();
+	pLoginFrame->ShowModal();
 
 	CPaintManagerUI::MessageLoop();
 

+ 13 - 0
lewaimai_dispatch/lewaimai_dispatch_windows.vcxproj

@@ -32,6 +32,7 @@
     <UseDebugLibraries>true</UseDebugLibraries>
     <PlatformToolset>v141</PlatformToolset>
     <CharacterSet>Unicode</CharacterSet>
+    <UseOfMfc>false</UseOfMfc>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
@@ -192,12 +193,16 @@ copy $(ProjectDir)conf\ $(SolutionDir)bin\$(Platform)\$(Configuration)\conf\</Co
     </PostBuildEvent>
   </ItemDefinitionGroup>
   <ItemGroup>
+    <ClInclude Include="CGameFrameWnd.h" />
+    <ClInclude Include="CLoginWnd.h" />
     <ClInclude Include="ControlEx.h" />
     <ClInclude Include="helper\CConfigReader.h" />
     <ClInclude Include="helper\CAliyunMNS.h" />
     <ClInclude Include="helper\CLewaimaiString.h" />
     <ClInclude Include="helper\CRandomHelper.h" />
     <ClInclude Include="helper\define.h" />
+    <ClInclude Include="MiniDumper.h" />
+    <ClInclude Include="resource.h" />
     <ClInclude Include="tool\CLewaimaiLog.h" />
     <ClInclude Include="pch\pch.h" />
     <ClInclude Include="tool\CLewaimaiDistance.h" />
@@ -206,11 +211,13 @@ copy $(ProjectDir)conf\ $(SolutionDir)bin\$(Platform)\$(Configuration)\conf\</Co
     <ClInclude Include="helper\CSystem.h" />
   </ItemGroup>
   <ItemGroup>
+    <ClCompile Include="CLoginWnd.cpp" />
     <ClCompile Include="helper\CConfigReader.cpp" />
     <ClCompile Include="helper\CAliyunMNS.cpp" />
     <ClCompile Include="helper\CLewaimaiString.cpp" />
     <ClCompile Include="helper\CRandomHelper.cpp" />
     <ClCompile Include="helper\CSystem.cpp" />
+    <ClCompile Include="MiniDumper.cpp" />
     <ClCompile Include="tool\CLewaimaiLog.cpp" />
     <ClCompile Include="lewaimai_dispatch_windows.cpp" />
     <ClCompile Include="pch\pch.cpp" />
@@ -221,6 +228,12 @@ copy $(ProjectDir)conf\ $(SolutionDir)bin\$(Platform)\$(Configuration)\conf\</Co
   <ItemGroup>
     <None Include="conf\dispatch.conf" />
   </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="zhipuzi_pos_windows.rc" />
+  </ItemGroup>
+  <ItemGroup>
+    <Image Include="duilib.ico" />
+  </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>

+ 28 - 0
lewaimai_dispatch/lewaimai_dispatch_windows.vcxproj.filters

@@ -48,9 +48,21 @@
     <ClInclude Include="helper\define.h">
       <Filter>头文件</Filter>
     </ClInclude>
+    <ClInclude Include="CLoginWnd.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
     <ClInclude Include="ControlEx.h">
       <Filter>头文件</Filter>
     </ClInclude>
+    <ClInclude Include="MiniDumper.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="resource.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="CGameFrameWnd.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="lewaimai_dispatch_windows.cpp">
@@ -86,8 +98,24 @@
     <ClCompile Include="helper\CSystem.cpp">
       <Filter>源文件</Filter>
     </ClCompile>
+    <ClCompile Include="CLoginWnd.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
+    <ClCompile Include="MiniDumper.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <None Include="conf\dispatch.conf" />
   </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="zhipuzi_pos_windows.rc">
+      <Filter>资源文件</Filter>
+    </ResourceCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <Image Include="duilib.ico">
+      <Filter>资源文件</Filter>
+    </Image>
+  </ItemGroup>
 </Project>

+ 1 - 0
lewaimai_dispatch/lewaimai_dispatch_windows.vcxproj.user

@@ -18,5 +18,6 @@
     <LocalDebuggerCommand>$(SolutionDir)bin\$(Platform)\$(Configuration)\$(ProjectName)\$(TargetFileName)</LocalDebuggerCommand>
     <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
     <LocalDebuggerWorkingDirectory>$(SolutionDir)bin\$(Platform)\$(Configuration)\$(ProjectName)\</LocalDebuggerWorkingDirectory>
+    <LocalDebuggerAttach>false</LocalDebuggerAttach>
   </PropertyGroup>
 </Project>

+ 13 - 8
lewaimai_dispatch/pch/pch.h

@@ -9,14 +9,6 @@
 #ifndef PCH_H
 #define PCH_H
 
-#include <windows.h>
-#include <objbase.h>
-#include <zmouse.h>
-
-#include <DuiLib/UIlib.h>
-
-using namespace DuiLib;
-
 /*
  *操作系统相关的头文件
  **/
@@ -68,5 +60,18 @@ using namespace std;
 #include "../tool/CLewaimaiPos.h"
 #include "../tool/CLewaimaiDistance.h"
 
+#include <objbase.h>
+#include <zmouse.h>
+
+#include <DuiLib/UIlib.h>
+using namespace DuiLib;
+
+#include <exdisp.h>
+#include <comdef.h>
+
+#include "../ControlEx.h"
+
+#include "../resource.h"
+
 #endif //PCH_H
 

+ 17 - 0
lewaimai_dispatch/resource.h

@@ -0,0 +1,17 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ 生成的包含文件。
+// 供 zhipuzi_pos_windows.rc 使用
+//
+#define IDI_ICON1                       101
+#define IDI_ICON_DUILIB                 101
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        102
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1001
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif

BIN
lewaimai_dispatch/zhipuzi_pos_windows.aps


BIN
lewaimai_dispatch/zhipuzi_pos_windows.rc