|
|
@@ -5,12 +5,38 @@
|
|
|
#include "CMessageboxWnd.h"
|
|
|
#include "../tool/CFoodHandle.h"
|
|
|
|
|
|
-void CLoginWnd::Init()
|
|
|
+#include <stdarg.h>
|
|
|
+#include <stdio.h>
|
|
|
+#include <stdlib.h> // _countof
|
|
|
+
|
|
|
+// ---------------------------------------------------------------------------
|
|
|
+// 临时调试日志:定位「下拉里点第 2/3 个用户名,账号框仍显示第 1 个」用。
|
|
|
+// 输出到程序当前目录的 login_debug.log,同时 OutputDebugString(可用 DebugView 看)。
|
|
|
+// 第十四轮回退到原生 Combo 触发后,仍在 Init / itemselect 里留作校验;整体验收通过后删掉。
|
|
|
+// ---------------------------------------------------------------------------
|
|
|
+static void LoginLog(const wchar_t* fmt, ...)
|
|
|
{
|
|
|
- //刷新版本号
|
|
|
- CLabelUI* version = static_cast<CLabelUI*>(m_pm.FindControl(_T("login_version")));
|
|
|
- version->SetText((L"智铺子收银系统 " + CLewaimaiString::UTF8ToUnicode(CSystem::GetVersion())).c_str());
|
|
|
+ wchar_t buf[1024];
|
|
|
+
|
|
|
+ va_list ap;
|
|
|
+ va_start(ap, fmt);
|
|
|
+ _vsnwprintf_s(buf, _countof(buf), _TRUNCATE, fmt, ap);
|
|
|
+ va_end(ap);
|
|
|
+
|
|
|
+ FILE* fp = NULL;
|
|
|
+ if (_wfopen_s(&fp, L"login_debug.log", L"a, ccs=UTF-8") == 0 && fp != NULL)
|
|
|
+ {
|
|
|
+ fwprintf_s(fp, L"%s\n", buf);
|
|
|
+ fclose(fp);
|
|
|
+ }
|
|
|
+
|
|
|
+ OutputDebugStringW(buf);
|
|
|
+ OutputDebugStringW(L"\n");
|
|
|
+}
|
|
|
|
|
|
+
|
|
|
+void CLoginWnd::Init()
|
|
|
+{
|
|
|
//初始化下拉框的用户名
|
|
|
CComboUI* pCom = static_cast<CComboUI*>(m_pm.FindControl(_T("accountcombo")));
|
|
|
|
|
|
@@ -18,10 +44,16 @@ void CLoginWnd::Init()
|
|
|
for (std::map<std::string, std::string>::iterator it = users.begin(); it != users.end(); it++)
|
|
|
{
|
|
|
std::string username = it->first;
|
|
|
-
|
|
|
+
|
|
|
CListLabelElementUI* elem = new CListLabelElementUI();
|
|
|
elem->SetText(CLewaimaiString::UTF8ToUnicode(username).c_str());
|
|
|
|
|
|
+ // 行高 34:下拉项是在代码里 new 出来的,不经过 CDialogBuilder,
|
|
|
+ // 拿不到 login.xml 里 <Default name="ListLabelElement" value="height="34"">,
|
|
|
+ // 所以必须在这里显式设。(文字色/热态底色/padding 走 TListInfoUI,由 Combo 的
|
|
|
+ // item* 属性下发,那些不用在代码里管。)
|
|
|
+ elem->SetFixedHeight(34);
|
|
|
+
|
|
|
pCom->Add(elem);
|
|
|
}
|
|
|
|
|
|
@@ -54,29 +86,307 @@ void CLoginWnd::Init()
|
|
|
CEditUI* pAccountEdit = static_cast<CEditUI*>(m_pm.FindControl(_T("accountedit")));
|
|
|
CEditUI* pPasswordEdit = static_cast<CEditUI*>(m_pm.FindControl(_T("pwdedit")));
|
|
|
|
|
|
- pAccountEdit->SetText(CLewaimaiString::UTF8ToUnicode(last_login_username).c_str());
|
|
|
- pPasswordEdit->SetText(CLewaimaiString::UTF8ToUnicode(password).c_str());
|
|
|
+ // 回填上次登录账号。
|
|
|
+ // 显示的活儿现在全归 accountedit(Combo 退成只负责弹下拉、自己不画东西),
|
|
|
+ // 所以账号文字一律写进 Edit —— 历史列表里有没有都要写,
|
|
|
+ // 第一次登录时下拉是空的,也要让输入框里有上一次手动敲过的账号。
|
|
|
+ std::wstring wsLastUser = CLewaimaiString::UTF8ToUnicode(last_login_username);
|
|
|
+
|
|
|
+ if (pAccountEdit)
|
|
|
+ {
|
|
|
+ pAccountEdit->SetText(wsLastUser.c_str());
|
|
|
+ }
|
|
|
+
|
|
|
+ // ⚠️ 历史账号的「回填」统一走上面 accountedit / pwdedit 的直写(行 97、行 120 起):
|
|
|
+ // 账号文字 → accountedit,记住的密码 → pwdedit,二者都已写好,无需再借 SelectItem。
|
|
|
+ // 这里【刻意不调用】 pCom->SelectItem(nIndex):
|
|
|
+ // Init() 在 OnCreate 阶段执行,此时窗口/焦点体系尚未完全就绪;SelectItem 会同步
|
|
|
+ // 派发 itemselect → Notify 里 pAccount->SetFocus()(会创建原生 EDIT 子窗口)+
|
|
|
+ // SetInputError() 等一系列副作用,极易在启动期崩溃(即「系统启动就崩」)。
|
|
|
+ // 下拉项是否预高亮上次账号只是纯视觉细节,启动期没必要为此冒险;
|
|
|
+ // 用户后续手动点开下拉选历史项时,itemselect 仍正常派发、密码照常回填。
|
|
|
+
|
|
|
+ // 再兜底写一次密码,保证「没有历史项」和「历史项里没记住密码」两种情况都对
|
|
|
+ if (pPasswordEdit)
|
|
|
+ {
|
|
|
+ pPasswordEdit->SetText(CLewaimaiString::UTF8ToUnicode(password).c_str());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 恢复到正常态:按钮可点、无转圈、无错误提示、无同步遮罩
|
|
|
+ SetLoginLoading(false);
|
|
|
+ SetInputError(false);
|
|
|
+
|
|
|
+ CContainerUI* pResult = static_cast<CContainerUI*>(m_pm.FindControl(_T("loginresult")));
|
|
|
+
|
|
|
+ if (pResult)
|
|
|
+ {
|
|
|
+ pResult->SetVisible(false);
|
|
|
+ }
|
|
|
+
|
|
|
+ CContainerUI* pMask = static_cast<CContainerUI*>(m_pm.FindControl(_T("login_sync_mask")));
|
|
|
+
|
|
|
+ if (pMask)
|
|
|
+ {
|
|
|
+ pMask->SetVisible(false);
|
|
|
+ }
|
|
|
|
|
|
if (CSetting::GetInstance()->GetParam("setting_is_auto_login") == "1")
|
|
|
{
|
|
|
StartLogin();
|
|
|
}
|
|
|
+
|
|
|
+ if (m_mode == 2)
|
|
|
+ {
|
|
|
+ PostMessage(WM_LOGIN_AGAIN_OUT);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// ---------------------------------------------------------------------------
|
|
|
+// 正常 / 登录中 两态切换
|
|
|
+// 对照设计稿:登录中按钮内换成「16px 转圈 + 9px 间距 + '登录中…'」,
|
|
|
+// 按钮底图不动,所以只需要换文案和两个浮层控件的可见性。
|
|
|
+// ---------------------------------------------------------------------------
|
|
|
+void CLoginWnd::SetLoginLoading(bool bLoading)
|
|
|
+{
|
|
|
+ CButtonUI* pBtn = static_cast<CButtonUI*>(m_pm.FindControl(_T("loginBtn")));
|
|
|
+
|
|
|
+ if (pBtn)
|
|
|
+ {
|
|
|
+ // 转圈期间清掉「登 录」,否则会和浮层上的「登录中…」叠在一起
|
|
|
+ pBtn->SetText(bLoading ? _T("") : _T("登 录"));
|
|
|
+ }
|
|
|
+
|
|
|
+ CGifAnimUI* pSpinner = static_cast<CGifAnimUI*>(m_pm.FindControl(_T("login_spinner")));
|
|
|
+
|
|
|
+ if (pSpinner)
|
|
|
+ {
|
|
|
+ pSpinner->SetVisible(bLoading);
|
|
|
+ }
|
|
|
+
|
|
|
+ CLabelUI* pLoadingText = static_cast<CLabelUI*>(m_pm.FindControl(_T("login_loading_text")));
|
|
|
+
|
|
|
+ if (pLoadingText)
|
|
|
+ {
|
|
|
+ pLoadingText->SetVisible(bLoading);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// ---------------------------------------------------------------------------
|
|
|
+// 输入框错误态:把两个输入框的 normal/hot/focus 三态图整组换成红色版本
|
|
|
+// ---------------------------------------------------------------------------
|
|
|
+void CLoginWnd::SetInputError(bool bError)
|
|
|
+{
|
|
|
+ m_bInputError = bError;
|
|
|
+
|
|
|
+ // 原生编辑窗口的背景是【实体画刷】,跟 DuiLib 画的底图是两层,必须把颜色对上,
|
|
|
+ // 否则聚焦时会在错误态的浅红底(#FFF8F6)上糊一块白的。
|
|
|
+ // 画刷在 CEditWnd 里按实例缓存(WM_CTLCOLOREDIT 中 m_hBkBrush 为空才建),
|
|
|
+ // 而 CEditWnd 每次聚焦都会新建,所以这次改的颜色在【下一次聚焦】生效 ——
|
|
|
+ // 实际调用点(登录失败 / 重新登录)此时输入框都不是焦点,没问题。
|
|
|
+ const DWORD NATIVE_BK_NORMAL = 0xFFFFFFFF; // 三态图填充色 #FFFFFF
|
|
|
+ const DWORD NATIVE_BK_ERROR = 0xFFFFF8F6; // 错误态填充色 #FFF8F6
|
|
|
+
|
|
|
+ CEditUI* pAccount = static_cast<CEditUI*>(m_pm.FindControl(_T("accountedit")));
|
|
|
+ if (pAccount)
|
|
|
+ {
|
|
|
+ // 原生 EDIT 子窗口背景色必须和 DuiLib 底图对齐
|
|
|
+ pAccount->SetNativeEditBkColor(bError ? NATIVE_BK_ERROR : NATIVE_BK_NORMAL);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 账号框(edit + combo 箭头)的视觉统一由 UpdateAccountBoxVisual 处理
|
|
|
+ UpdateAccountBoxVisual();
|
|
|
+
|
|
|
+ CEditUI* pPwd = static_cast<CEditUI*>(m_pm.FindControl(_T("pwdedit")));
|
|
|
+
|
|
|
+ if (pPwd)
|
|
|
+ {
|
|
|
+ LPCTSTR lpNormal = bError ? _T("file='login_input_lock_err.png'") : _T("file='login_input_lock_normal.png'");
|
|
|
+ LPCTSTR lpHot = bError ? _T("file='login_input_lock_err.png'") : _T("file='login_input_lock_hot.png'");
|
|
|
+ LPCTSTR lpFocus = bError ? _T("file='login_input_lock_err.png'") : _T("file='login_input_lock_focus.png'");
|
|
|
+
|
|
|
+ pPwd->SetNormalImage(lpNormal);
|
|
|
+ pPwd->SetHotImage(lpHot);
|
|
|
+ pPwd->SetFocusedImage(lpFocus);
|
|
|
+ pPwd->SetNativeEditBkColor(bError ? NATIVE_BK_ERROR : NATIVE_BK_NORMAL);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// ---------------------------------------------------------------------------
|
|
|
+// 账号框(accountedit + accountcombo)视觉统一:按「错误 > 聚焦 > 悬浮 > 正常」同步四态图。
|
|
|
+// 由于 Combo 与 Edit 是独立控件,不手动同步的话,鼠标悬停箭头时左边仍是 normal、
|
|
|
+// Edit 聚焦时箭头可能还是 hot/normal,导致边框颜色断裂。
|
|
|
+// ---------------------------------------------------------------------------
|
|
|
+void CLoginWnd::UpdateAccountBoxVisual()
|
|
|
+{
|
|
|
+ CEditUI* pAccount = static_cast<CEditUI*>(m_pm.FindControl(_T("accountedit")));
|
|
|
+ CComboUI* pAccountCombo = static_cast<CComboUI*>(m_pm.FindControl(_T("accountcombo")));
|
|
|
+ if (!pAccount || !pAccountCombo)
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const bool bFocused = pAccount->IsFocused() || pAccountCombo->IsFocused();
|
|
|
+
|
|
|
+ // 【必须带 corner='4,4,48,4'】login.xml 里 Combo 四态图就是这么声明的。
|
|
|
+ // CComboUI::PaintStatusImage 走 DrawImage 的九宫格逻辑,corner 决定右 48
|
|
|
+ // 的箭头区不被拉伸、1:1 绘制(login.xml 第 59-60 行注释有说明)。
|
|
|
+ // 之前这里漏写 corner,图会被整体拉伸,箭头尺寸/位置跟 XML 初值不一致。
|
|
|
+ const LPCTSTR kComboErr = _T("file='login_input_user_err.png' corner='4,4,48,4'");
|
|
|
+ const LPCTSTR kComboFocus = _T("file='login_input_user_focus.png' corner='4,4,48,4'");
|
|
|
+ const LPCTSTR kComboHot = _T("file='login_input_user_hot.png' corner='4,4,48,4'");
|
|
|
+ const LPCTSTR kComboNormal= _T("file='login_input_user_normal.png' corner='4,4,48,4'");
|
|
|
+
|
|
|
+ if (m_bInputError)
|
|
|
+ {
|
|
|
+ pAccount->SetNormalImage(_T("file='login_input_user_editbox_err.png'"));
|
|
|
+ pAccount->SetHotImage(_T("file='login_input_user_editbox_err.png'"));
|
|
|
+ pAccount->SetFocusedImage(_T("file='login_input_user_editbox_err.png'"));
|
|
|
+
|
|
|
+ pAccountCombo->SetNormalImage(kComboErr);
|
|
|
+ pAccountCombo->SetHotImage(kComboErr);
|
|
|
+ pAccountCombo->SetPushedImage(kComboErr);
|
|
|
+ pAccountCombo->SetFocusedImage(kComboErr);
|
|
|
+ }
|
|
|
+ else if (bFocused)
|
|
|
+ {
|
|
|
+ pAccount->SetNormalImage(_T("file='login_input_user_editbox_focus.png'"));
|
|
|
+ pAccount->SetHotImage(_T("file='login_input_user_editbox_focus.png'"));
|
|
|
+ pAccount->SetFocusedImage(_T("file='login_input_user_editbox_focus.png'"));
|
|
|
+
|
|
|
+ pAccountCombo->SetNormalImage(kComboFocus);
|
|
|
+ pAccountCombo->SetHotImage(kComboFocus);
|
|
|
+ pAccountCombo->SetPushedImage(kComboFocus);
|
|
|
+ pAccountCombo->SetFocusedImage(kComboFocus);
|
|
|
+ }
|
|
|
+ else if (m_bAccountBoxHovered)
|
|
|
+ {
|
|
|
+ pAccount->SetNormalImage(_T("file='login_input_user_editbox_hot.png'"));
|
|
|
+ pAccount->SetHotImage(_T("file='login_input_user_editbox_hot.png'"));
|
|
|
+ pAccount->SetFocusedImage(_T("file='login_input_user_editbox_hot.png'"));
|
|
|
+
|
|
|
+ pAccountCombo->SetNormalImage(kComboHot);
|
|
|
+ pAccountCombo->SetHotImage(kComboHot);
|
|
|
+ pAccountCombo->SetPushedImage(kComboFocus);
|
|
|
+ pAccountCombo->SetFocusedImage(kComboFocus);
|
|
|
+ }
|
|
|
else
|
|
|
{
|
|
|
- CVerticalLayoutUI* pInput = static_cast<CVerticalLayoutUI*>(m_pm.FindControl(_T("login_input")));
|
|
|
- pInput->SetVisible(true);
|
|
|
+ pAccount->SetNormalImage(_T("file='login_input_user_editbox_normal.png'"));
|
|
|
+ pAccount->SetHotImage(_T("file='login_input_user_editbox_hot.png'"));
|
|
|
+ pAccount->SetFocusedImage(_T("file='login_input_user_editbox_focus.png'"));
|
|
|
+
|
|
|
+ pAccountCombo->SetNormalImage(kComboNormal);
|
|
|
+ pAccountCombo->SetHotImage(kComboHot);
|
|
|
+ pAccountCombo->SetPushedImage(kComboFocus);
|
|
|
+ pAccountCombo->SetFocusedImage(kComboFocus);
|
|
|
+ }
|
|
|
|
|
|
- CVerticalLayoutUI* pLoading = static_cast<CVerticalLayoutUI*>(m_pm.FindControl(_T("login_loading")));
|
|
|
- pLoading->SetVisible(false);
|
|
|
+ LoginLog(L"[BOXVISUAL] err=%d focused=%d(edit=%d combo=%d) hovered=%d",
|
|
|
+ m_bInputError ? 1 : 0, bFocused ? 1 : 0,
|
|
|
+ pAccount->IsFocused() ? 1 : 0, pAccountCombo->IsFocused() ? 1 : 0,
|
|
|
+ m_bAccountBoxHovered ? 1 : 0);
|
|
|
+}
|
|
|
+
|
|
|
+// ---------------------------------------------------------------------------
|
|
|
+// 【账号框悬浮态联动 v5】读取鼠标真实位置,判断是否在 acct_box 整框内,
|
|
|
+// 状态变化时才刷新两边视觉。
|
|
|
+//
|
|
|
+// 为什么必须在 HandleMessage 里、m_pm.MessageHandler() 【之后】调用:
|
|
|
+// ① 之前放在 MessageHandler(PreMessageFilter) 里,它由
|
|
|
+// CPaintManagerUI::TranslateMessage 在 ::DispatchMessage 【之前】触发
|
|
|
+// (UIManager.cpp:4211),DuiLib 自己那套 hover 分发(UIManager.cpp:1629
|
|
|
+// FindControl -> UIEVENT_MOUSEENTER)还没跑,我们算完的状态会被它随后覆盖。
|
|
|
+// ② PreMessageFilter 拿到的 lParam 是【消息目标窗口】的客户区坐标。鼠标停在
|
|
|
+// 原生 EDIT 子窗口(类名 "EditWnd",UIEdit.cpp:294 在 SETFOCUS 时创建)上时,
|
|
|
+// 消息目标是那个子窗口,坐标原点跟主窗口不同,PtInRect(acct_box) 必然算错。
|
|
|
+// ③ 改用 ::GetCursorPos + ::ScreenToClient 取坐标,与消息发给哪个窗口无关,
|
|
|
+// 配合放在 DuiLib 处理之后,时序和坐标都稳。
|
|
|
+// ---------------------------------------------------------------------------
|
|
|
+void CLoginWnd::SyncAccountBoxHover()
|
|
|
+{
|
|
|
+ // 命中区用【accountedit + accountcombo 两个控件自身 rect 的并集】,
|
|
|
+ // 不用 acct_box 的 GetPos():acct_box 带 padding="0,-4,0,16",而 GetPos()
|
|
|
+ // 返回的是外框 m_rcItem;Combo/Edit 是 float 绝对定位,坐标基准是【内容区】,
|
|
|
+ // 实际可见框比 m_rcItem 上移了 4px(top padding = -4)。
|
|
|
+ // 两个子控件的 rect 才是真正画出来的那 328x50 视觉框,用它最准。
|
|
|
+ CControlUI* pEdit = m_pm.FindControl(_T("accountedit"));
|
|
|
+ CControlUI* pCombo = m_pm.FindControl(_T("accountcombo"));
|
|
|
+ if (!pEdit && !pCombo)
|
|
|
+ {
|
|
|
+ // 只报一次,避免刷屏
|
|
|
+ static bool s_bWarned = false;
|
|
|
+ if (!s_bWarned)
|
|
|
+ {
|
|
|
+ s_bWarned = true;
|
|
|
+ LoginLog(L"[HOVER] !! accountedit / accountcombo 都找不到,悬浮联动失效");
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
- CVerticalLayoutUI* pIniting = static_cast<CVerticalLayoutUI*>(m_pm.FindControl(_T("login_init_data_ing")));
|
|
|
- pIniting->SetVisible(false);
|
|
|
+ RECT rcBox = { 0, 0, 0, 0 };
|
|
|
+ if (pCombo)
|
|
|
+ {
|
|
|
+ rcBox = pCombo->GetPos();
|
|
|
+ }
|
|
|
+ if (pEdit)
|
|
|
+ {
|
|
|
+ const RECT rcEdit = pEdit->GetPos();
|
|
|
+ if (rcBox.right == rcBox.left && rcBox.bottom == rcBox.top)
|
|
|
+ {
|
|
|
+ rcBox = rcEdit;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ ::UnionRect(&rcBox, &rcBox, &rcEdit);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- if (m_mode == 2)
|
|
|
+ POINT pt = { 0, 0 };
|
|
|
+ ::GetCursorPos(&pt);
|
|
|
+ ::ScreenToClient(m_pm.GetPaintWindow(), &pt);
|
|
|
+
|
|
|
+ const bool bInside = (::PtInRect(&rcBox, pt) != FALSE);
|
|
|
+
|
|
|
+ if (bInside == m_bAccountBoxHovered)
|
|
|
{
|
|
|
- PostMessage(WM_LOGIN_AGAIN_OUT);
|
|
|
+ return; // 状态没变,不刷
|
|
|
}
|
|
|
+
|
|
|
+ m_bAccountBoxHovered = bInside;
|
|
|
+ LoginLog(L"[HOVER] %s pt=(%d,%d) rcBox=(%d,%d,%d,%d)",
|
|
|
+ bInside ? L"ENTER" : L"LEAVE",
|
|
|
+ pt.x, pt.y, rcBox.left, rcBox.top, rcBox.right, rcBox.bottom);
|
|
|
+ UpdateAccountBoxVisual();
|
|
|
+}
|
|
|
+
|
|
|
+// ---------------------------------------------------------------------------
|
|
|
+// 主线程快照界面输入,供登录子线程使用
|
|
|
+// ---------------------------------------------------------------------------
|
|
|
+void CLoginWnd::FetchLoginInput()
|
|
|
+{
|
|
|
+ m_wsAccount.clear();
|
|
|
+ m_wsPassword.clear();
|
|
|
+
|
|
|
+ // 账号从 accountedit 取:Combo 不显示文字,输入框里的才是用户真正要登录的账号
|
|
|
+ CEditUI* pAccount = static_cast<CEditUI*>(m_pm.FindControl(_T("accountedit")));
|
|
|
+
|
|
|
+ if (pAccount)
|
|
|
+ {
|
|
|
+ m_wsAccount = pAccount->GetText().GetData();
|
|
|
+ }
|
|
|
+
|
|
|
+ CEditUI* pPwd = static_cast<CEditUI*>(m_pm.FindControl(_T("pwdedit")));
|
|
|
+
|
|
|
+ if (pPwd)
|
|
|
+ {
|
|
|
+ m_wsPassword = pPwd->GetText().GetData();
|
|
|
+ }
|
|
|
+
|
|
|
+ CCheckBoxUI* pAuto = static_cast<CCheckBoxUI*>(m_pm.FindControl(_T("login_auto_login")));
|
|
|
+ CCheckBoxUI* pRemember = static_cast<CCheckBoxUI*>(m_pm.FindControl(_T("login_remember_password")));
|
|
|
+
|
|
|
+ m_bAutoLogin = (pAuto != nullptr && pAuto->IsSelected());
|
|
|
+ m_bRememberPwd = (pRemember != nullptr && pRemember->IsSelected());
|
|
|
}
|
|
|
|
|
|
void CLoginWnd::Notify(TNotifyUI& msg)
|
|
|
@@ -128,26 +438,53 @@ void CLoginWnd::Notify(TNotifyUI& msg)
|
|
|
{
|
|
|
CComboUI* pCom = static_cast<CComboUI*>(m_pm.FindControl(_T("accountcombo")));
|
|
|
|
|
|
- std::wstring name = pCom->GetItemAt(pCom->GetCurSel())->GetText();
|
|
|
- std::string password = CSetting::GetInstance()->GetUser(CLewaimaiString::UnicodeToUTF8(name));
|
|
|
- std::wstring wspassword = CLewaimaiString::UTF8ToUnicode(password);
|
|
|
+ if (pCom->GetCurSel() < 0)
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ std::wstring username = pCom->GetItemAt(pCom->GetCurSel())->GetText().GetData();
|
|
|
+
|
|
|
+ // 选中项写回输入框:Combo 自己不显示文字了,显示归 accountedit
|
|
|
+ CEditUI* pAccount = static_cast<CEditUI*>(m_pm.FindControl(_T("accountedit")));
|
|
|
+
|
|
|
+ if (pAccount)
|
|
|
+ {
|
|
|
+ LoginLog(L"[itemselect] 进入: CurSel=%d, 选中项=%s, 写入前edit=%s",
|
|
|
+ pCom->GetCurSel(), username.c_str(), (LPCTSTR)pAccount->GetText());
|
|
|
+
|
|
|
+ pAccount->SetText(username.c_str());
|
|
|
|
|
|
- CEditUI* pEdit = static_cast<CEditUI*>(m_pm.FindControl(_T("accountedit")));
|
|
|
- pEdit->SetText(name.c_str());
|
|
|
+ LoginLog(L"[itemselect] 写入后: edit=%s", (LPCTSTR)pAccount->GetText());
|
|
|
+
|
|
|
+ // 焦点钉回账号框:弹层关闭时 CComboWnd::WM_CLOSE 会执行
|
|
|
+ // m_pOwner->SetFocus()(UICombo.cpp:173),把 DuiLib 的 logical focus
|
|
|
+ // 交给 Combo;Combo 没有原生子窗口,系统焦点就停在主窗口 hwnd 上,
|
|
|
+ // 用户看到「焦点跑到密码框」。这里显式抢回来。
|
|
|
+ // 只用公开接口,不碰 CEditUI 的内部成员(m_pWindow 等)。
|
|
|
+ pAccount->SetFocus();
|
|
|
+ }
|
|
|
+
|
|
|
+ std::string password = CSetting::GetInstance()->GetUser(CLewaimaiString::UnicodeToUTF8(username));
|
|
|
+ std::wstring wspassword = CLewaimaiString::UTF8ToUnicode(password);
|
|
|
|
|
|
CEditUI* pPassword = static_cast<CEditUI*>(m_pm.FindControl(_T("pwdedit")));
|
|
|
- pPassword->SetText(wspassword.c_str());
|
|
|
- }
|
|
|
- }
|
|
|
- else if (msg.sType == L"windowinit")
|
|
|
- {
|
|
|
- //m_pm.SetNextTabControl(false);
|
|
|
|
|
|
- //CEditUI* pAccountEdit = static_cast<CEditUI*>(m_pm.FindControl(_T("accountedit")));
|
|
|
- //if (pAccountEdit)
|
|
|
- //{
|
|
|
- //pAccountEdit->SetFocus();
|
|
|
- //}
|
|
|
+ if (pPassword)
|
|
|
+ {
|
|
|
+ pPassword->SetText(wspassword.c_str());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 换了账号就把上一次的红色错误态收掉
|
|
|
+ SetInputError(false);
|
|
|
+
|
|
|
+ CContainerUI* pResult = static_cast<CContainerUI*>(m_pm.FindControl(_T("loginresult")));
|
|
|
+
|
|
|
+ if (pResult)
|
|
|
+ {
|
|
|
+ pResult->SetVisible(false);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
else if (msg.sType == _T("killfocus"))
|
|
|
{
|
|
|
@@ -155,6 +492,13 @@ void CLoginWnd::Notify(TNotifyUI& msg)
|
|
|
{
|
|
|
CSystem::HideSystemKeyboard();
|
|
|
}
|
|
|
+
|
|
|
+ CDuiString name = msg.pSender->GetName();
|
|
|
+ if (name == _T("accountedit") || name == _T("accountcombo"))
|
|
|
+ {
|
|
|
+ // 账号框任一子控件失焦,按「悬浮 > 正常」刷新整框视觉
|
|
|
+ UpdateAccountBoxVisual();
|
|
|
+ }
|
|
|
}
|
|
|
else if (msg.sType == _T("setfocus"))
|
|
|
{
|
|
|
@@ -165,6 +509,13 @@ void CLoginWnd::Notify(TNotifyUI& msg)
|
|
|
CSystem::ShowSystemKeyboard(m_hWnd);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ CDuiString name = msg.pSender->GetName();
|
|
|
+ if (name == _T("accountedit") || name == _T("accountcombo"))
|
|
|
+ {
|
|
|
+ // 账号框任一子控件聚焦,强制把整框切到 focus 绿图,让边框连成一体
|
|
|
+ UpdateAccountBoxVisual();
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -176,6 +527,19 @@ LRESULT CLoginWnd::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHand
|
|
|
|
|
|
// 把自己的窗口句柄与窗口绘制管理器挂接在一起
|
|
|
m_pm.Init(m_hWnd);
|
|
|
+
|
|
|
+ // ---------------------------------------------------------------------------
|
|
|
+ // 【焦点修复】m_bNoActivate 必须为 false。
|
|
|
+ // DuiLib 的 CPaintManagerUI 原本不初始化该成员(UIManager.cpp 初始化列表缺项),
|
|
|
+ // 而它门控着三处 ::SetFocus(m_hWndPaint)(UIManager.cpp 1738 / 2442 / 2475)。
|
|
|
+ // 一旦读到垃圾值 true,原生 EDIT 子窗(CeditWnd)收不到 WM_KILLFOCUS 就永不销毁
|
|
|
+ // (其唯一销毁途径是 OnKillFocus 里的 PostMessage(WM_CLOSE),UIEdit.cpp:218),
|
|
|
+ // 表现为光标一直闪、点空白不丢焦点。
|
|
|
+ // 库侧已在构造函数初始化列表补 m_bNoActivate(false);这里再显式设一次作双保险,
|
|
|
+ // 幂等无害,确认库工程已重新编译后可删除本行。
|
|
|
+ // ---------------------------------------------------------------------------
|
|
|
+ //m_pm.SetNoActivate(false);
|
|
|
+
|
|
|
m_pm.AddPreMessageFilter(this);
|
|
|
|
|
|
CDialogBuilder builder;
|
|
|
@@ -308,38 +672,50 @@ LRESULT CLoginWnd::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
|
{
|
|
|
return lRes;
|
|
|
}
|
|
|
- if(m_pm.MessageHandler(uMsg, wParam, lParam, lRes))
|
|
|
+ // 先让 DuiLib 处理,拿到它的返回值但先不 return:
|
|
|
+ // 账号框悬浮联动必须等 DuiLib 把 UISTATE_HOT 设好之后再算(顺序关键)。
|
|
|
+ const BOOL bDuiLibHandled = m_pm.MessageHandler(uMsg, wParam, lParam, lRes);
|
|
|
+
|
|
|
+ if (uMsg == WM_MOUSEMOVE || uMsg == WM_MOUSELEAVE ||
|
|
|
+ uMsg == WM_NCMOUSEMOVE || uMsg == WM_NCMOUSELEAVE)
|
|
|
+ {
|
|
|
+ SyncAccountBoxHover();
|
|
|
+ }
|
|
|
+
|
|
|
+ if(bDuiLibHandled)
|
|
|
{
|
|
|
return lRes;
|
|
|
}
|
|
|
return CWindowWnd::HandleMessage(uMsg, wParam, lParam);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
LRESULT CLoginWnd::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())
|
|
|
+ // 回车的行为和原来一致:账号空则聚焦账号,密码空则聚焦密码,都填了才登录
|
|
|
+ CEditUI* pAccount = static_cast<CEditUI*>(m_pm.FindControl(_T("accountedit")));
|
|
|
+ CEditUI* pPwd = static_cast<CEditUI*>(m_pm.FindControl(_T("pwdedit")));
|
|
|
+
|
|
|
+ if(pAccount && pAccount->GetText().IsEmpty())
|
|
|
{
|
|
|
- pEdit->SetFocus();
|
|
|
+ pAccount->SetFocus();
|
|
|
}
|
|
|
+ else if(pPwd && pPwd->GetText().IsEmpty())
|
|
|
+ {
|
|
|
+ pPwd->SetFocus();
|
|
|
+ }
|
|
|
else
|
|
|
{
|
|
|
- pEdit = static_cast<CEditUI*>(m_pm.FindControl(_T("pwdedit")));
|
|
|
- if(pEdit->GetText().IsEmpty())
|
|
|
- {
|
|
|
- pEdit->SetFocus();
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- //这里如果不把焦点设置为窗口,登录的时候会显示输入框(好像是个bug?获得焦点的控件无法隐藏?)
|
|
|
- SetFocus(this->GetHWND());
|
|
|
-
|
|
|
- this->StartLogin();
|
|
|
- }
|
|
|
+ //这里如果不把焦点设置为窗口,登录的时候会显示输入框(好像是个bug?获得焦点的控件无法隐藏?)
|
|
|
+ SetFocus(this->GetHWND());
|
|
|
+
|
|
|
+ this->StartLogin();
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
|
@@ -349,7 +725,12 @@ LRESULT CLoginWnd::MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, bool&
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
+ }
|
|
|
+ // 【注意】账号框悬浮联动不在这里做。
|
|
|
+ // CEditUI / CComboUI 的 DoEvent 处理 UIEVENT_MOUSEENTER 时只设 UISTATE_HOT +
|
|
|
+ // Invalidate,根本不 SendNotify(UIEdit.cpp:346 / UICombo.cpp:565),所以 Notify
|
|
|
+ // 收不到 mouseenter;而 PreMessageFilter 又跑在 DuiLib 处理之前、坐标还是消息
|
|
|
+ // 目标窗口的。正确位置见 HandleMessage 里的 SyncAccountBoxHover()。
|
|
|
else if (uMsg == WM_LOGIN_SUCCESS)
|
|
|
{
|
|
|
ShowLoginSuccess();
|
|
|
@@ -383,18 +764,27 @@ LRESULT CLoginWnd::MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, bool&
|
|
|
|
|
|
void CLoginWnd::StartLogin()
|
|
|
{
|
|
|
- //隐藏密码输入框,显示进度条
|
|
|
- CVerticalLayoutUI* pInput = static_cast<CVerticalLayoutUI*>(m_pm.FindControl(_T("login_input")));
|
|
|
- pInput->SetVisible(false);
|
|
|
+ // 已经在登录中就忽略重复触发(回车连击、自动登录 + 手动点击)
|
|
|
+ if (m_is_login_ing)
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
- CVerticalLayoutUI* pLoading = static_cast<CVerticalLayoutUI*>(m_pm.FindControl(_T("login_loading")));
|
|
|
- pLoading->SetVisible(true);
|
|
|
+ m_is_login_ing = true;
|
|
|
|
|
|
- CVerticalLayoutUI* pIniting = static_cast<CVerticalLayoutUI*>(m_pm.FindControl(_T("login_init_data_ing")));
|
|
|
- pIniting->SetVisible(false);
|
|
|
+ // 先把界面输入快照下来,后面子线程只用这份快照,不再碰控件
|
|
|
+ FetchLoginInput();
|
|
|
|
|
|
- CLabelUI* pLoginResultLabel = static_cast<CLabelUI*>(m_pm.FindControl(_T("loginresult")));
|
|
|
- pLoginResultLabel->SetVisible(false);
|
|
|
+ // 按钮切成「转圈 + 登录中…」,并收掉上一次的错误提示
|
|
|
+ SetLoginLoading(true);
|
|
|
+ SetInputError(false);
|
|
|
+
|
|
|
+ CContainerUI* pResult = static_cast<CContainerUI*>(m_pm.FindControl(_T("loginresult")));
|
|
|
+
|
|
|
+ if (pResult)
|
|
|
+ {
|
|
|
+ pResult->SetVisible(false);
|
|
|
+ }
|
|
|
|
|
|
//开启一个线程,开始处理登录
|
|
|
std::thread(&CLoginWnd::HandleLogin, this).detach();
|
|
|
@@ -402,8 +792,6 @@ void CLoginWnd::StartLogin()
|
|
|
|
|
|
void CLoginWnd::HandleLogin()
|
|
|
{
|
|
|
- CLabelUI* pLoginResultLabel = static_cast<CLabelUI*>(m_pm.FindControl(_T("loginresult")));
|
|
|
-
|
|
|
//真正登录前,先检测是否有需要更新
|
|
|
std::map<std::string, std::string> params;
|
|
|
|
|
|
@@ -431,6 +819,7 @@ void CLoginWnd::HandleLogin()
|
|
|
{
|
|
|
if (!document.HasMember("errcode") || !document.HasMember("errmsg") || !document.HasMember("data"))
|
|
|
{
|
|
|
+ m_bInputError = false;
|
|
|
m_wsLoginErrMsg = _T("服务器返回数据格式错误");
|
|
|
PostMessage(WM_LOGIN_ERROR);
|
|
|
|
|
|
@@ -442,6 +831,7 @@ void CLoginWnd::HandleLogin()
|
|
|
if (errcode != 0)
|
|
|
{
|
|
|
std::string errmsg = "response failed! message:" + std::string(document["errmsg"].GetString());
|
|
|
+ m_bInputError = false;
|
|
|
m_wsLoginErrMsg = CLewaimaiString::UTF8ToUnicode(errmsg);
|
|
|
PostMessage(WM_LOGIN_ERROR);
|
|
|
|
|
|
@@ -462,18 +852,9 @@ void CLoginWnd::HandleLogin()
|
|
|
}
|
|
|
|
|
|
//判断账号密码是否正确
|
|
|
- std::wstring account, password;
|
|
|
- CEditUI* pAccountEdit = static_cast<CEditUI*>(m_pm.FindControl(_T("accountedit")));
|
|
|
- if(pAccountEdit)
|
|
|
- {
|
|
|
- account = pAccountEdit->GetText().GetData();
|
|
|
- }
|
|
|
-
|
|
|
- CEditUI* pPasswordEdit = static_cast<CEditUI*>(m_pm.FindControl(_T("pwdedit")));
|
|
|
- if(pPasswordEdit)
|
|
|
- {
|
|
|
- password = pPasswordEdit->GetText().GetData();
|
|
|
- }
|
|
|
+ //账号密码是 StartLogin 在主线程取好存进成员的,子线程不直接读 UI
|
|
|
+ std::wstring account = m_wsAccount;
|
|
|
+ std::wstring password = m_wsPassword;
|
|
|
|
|
|
//把第1个中文冒号替换成英文冒号
|
|
|
CLewaimaiString::Replace(account, _T(":"), _T(":"), 1);
|
|
|
@@ -488,6 +869,7 @@ void CLoginWnd::HandleLogin()
|
|
|
|
|
|
if (s_account.compare("") == 0)
|
|
|
{
|
|
|
+ m_bInputError = true;
|
|
|
m_wsLoginErrMsg = _T("用户名不能为空");
|
|
|
PostMessage(WM_LOGIN_ERROR);
|
|
|
|
|
|
@@ -496,6 +878,7 @@ void CLoginWnd::HandleLogin()
|
|
|
|
|
|
if (s_password.compare("") == 0)
|
|
|
{
|
|
|
+ m_bInputError = true;
|
|
|
m_wsLoginErrMsg = _T("密码不能为空");
|
|
|
PostMessage(WM_LOGIN_ERROR);
|
|
|
|
|
|
@@ -512,16 +895,18 @@ void CLoginWnd::HandleLogin()
|
|
|
//判断当前shop_id是否为0,如果为0说明是主账号还没有绑定店铺,那么就跳转进行店铺绑定
|
|
|
if (CShopinfo::GetInstance()->m_is_shop == "0")
|
|
|
{
|
|
|
+ m_bInputError = false;
|
|
|
m_wsLoginErrMsg = _T("主账号未绑定店铺");
|
|
|
PostMessage(WM_LOGIN_ERROR);
|
|
|
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- CCheckBoxUI* pAuto = static_cast<CCheckBoxUI*>(m_pm.FindControl(_T("login_auto_login")));
|
|
|
- CCheckBoxUI* pRemember = static_cast<CCheckBoxUI*>(m_pm.FindControl(_T("login_remember_password")));
|
|
|
+ // 两个勾选框的状态在 StartLogin 里已经快照到 m_bAutoLogin / m_bRememberPwd
|
|
|
+ bool bAutoLogin = m_bAutoLogin;
|
|
|
+ bool bRememberPwd = m_bRememberPwd;
|
|
|
|
|
|
- if (pAuto->IsSelected())
|
|
|
+ if (bAutoLogin)
|
|
|
{
|
|
|
CSetting::GetInstance()->SetParam("setting_is_auto_login", "1", false);
|
|
|
CSetting::GetInstance()->SetParam("setting_is_remember_password", "1", false);
|
|
|
@@ -533,25 +918,17 @@ void CLoginWnd::HandleLogin()
|
|
|
{
|
|
|
CSetting::GetInstance()->SetParam("setting_is_auto_login", "0", false);
|
|
|
|
|
|
- if (pRemember->IsSelected())
|
|
|
+ if (bRememberPwd)
|
|
|
{
|
|
|
CSetting::GetInstance()->SetParam("setting_is_remember_password", "1", false);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- CSetting::GetInstance()->SetParam("setting_is_remember_password", "0", false);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- if (pRemember->IsSelected())
|
|
|
- {
|
|
|
CSetting::GetInstance()->SetUser(s_account, s_password, true);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
+ CSetting::GetInstance()->SetParam("setting_is_remember_password", "0", false);
|
|
|
CSetting::GetInstance()->SetUser(s_account, "", true);
|
|
|
}
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
//在这里设置完参数后,统一保存到数据库
|
|
|
CSetting::GetInstance()->SetParam("last_login_username", s_account, true);
|
|
|
@@ -566,6 +943,7 @@ void CLoginWnd::HandleLogin()
|
|
|
bool ret = CFoodHandle::GetInstance()->InitAllFood();
|
|
|
if (!ret)
|
|
|
{
|
|
|
+ m_bInputError = false;
|
|
|
m_wsLoginErrMsg = _T("同步云端商品数据失败!");
|
|
|
PostMessage(WM_LOGIN_ERROR);
|
|
|
return;
|
|
|
@@ -576,6 +954,7 @@ void CLoginWnd::HandleLogin()
|
|
|
ret = CShopinfo::GetInstance()->UpdateOneShopinfo(errmsg);
|
|
|
if (!ret)
|
|
|
{
|
|
|
+ m_bInputError = false;
|
|
|
m_wsLoginErrMsg = errmsg;
|
|
|
PostMessage(WM_LOGIN_ERROR);
|
|
|
return;
|
|
|
@@ -587,6 +966,7 @@ void CLoginWnd::HandleLogin()
|
|
|
ret = CShopinfo::GetInstance()->GetTabletypeInfo();
|
|
|
if (!ret)
|
|
|
{
|
|
|
+ m_bInputError = false;
|
|
|
m_wsLoginErrMsg = L"获取店铺桌子分类失败";
|
|
|
PostMessage(WM_LOGIN_ERROR);
|
|
|
return;
|
|
|
@@ -599,7 +979,8 @@ void CLoginWnd::HandleLogin()
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- //登录失败了
|
|
|
+ //登录失败了:属于账号/密码填错,输入框要标红
|
|
|
+ m_bInputError = true;
|
|
|
m_wsLoginErrMsg = std::wstring(_T("登录失败:") + CLewaimaiString::UTF8ToUnicode(errmsg));
|
|
|
PostMessage(WM_LOGIN_ERROR);
|
|
|
|
|
|
@@ -626,18 +1007,67 @@ void CLoginWnd::ShowLoginSuccess()
|
|
|
|
|
|
void CLoginWnd::ShowLoginError()
|
|
|
{
|
|
|
- CVerticalLayoutUI* pInput = static_cast<CVerticalLayoutUI*>(m_pm.FindControl(_T("login_input")));
|
|
|
- pInput->SetVisible(true);
|
|
|
+ // 结束登录中状态:按钮恢复「登 录」,转圈收起
|
|
|
+ m_is_login_ing = false;
|
|
|
+ SetLoginLoading(false);
|
|
|
|
|
|
- CVerticalLayoutUI* pLoading = static_cast<CVerticalLayoutUI*>(m_pm.FindControl(_T("login_loading")));
|
|
|
- pLoading->SetVisible(false);
|
|
|
+ // 账号/密码类错误才把输入框标红,网络类、同步类错误不标
|
|
|
+ SetInputError(m_bInputError);
|
|
|
|
|
|
- CVerticalLayoutUI* pIniting = static_cast<CVerticalLayoutUI*>(m_pm.FindControl(_T("login_init_data_ing")));
|
|
|
- pIniting->SetVisible(false);
|
|
|
+ // 同步阶段出错时遮罩可能还开着,这里一并收掉,否则挡住错误提示
|
|
|
+ CContainerUI* pMask = static_cast<CContainerUI*>(m_pm.FindControl(_T("login_sync_mask")));
|
|
|
|
|
|
- CLabelUI* pLoginResultLabel = static_cast<CLabelUI*>(m_pm.FindControl(_T("loginresult")));
|
|
|
- pLoginResultLabel->SetText(m_wsLoginErrMsg.c_str());
|
|
|
- pLoginResultLabel->SetVisible(true);
|
|
|
+ if (pMask)
|
|
|
+ {
|
|
|
+ pMask->SetVisible(false);
|
|
|
+ }
|
|
|
+
|
|
|
+ CContainerUI* pResult = static_cast<CContainerUI*>(m_pm.FindControl(_T("loginresult")));
|
|
|
+ CLabelUI* pText = static_cast<CLabelUI*>(m_pm.FindControl(_T("loginresult_text")));
|
|
|
+
|
|
|
+ if (pText)
|
|
|
+ {
|
|
|
+ pText->SetText(m_wsLoginErrMsg.c_str());
|
|
|
+
|
|
|
+ // 提示条是「图标 14 + 间距 6 + 文字」水平居中的(HorizontalLayout childalign=center)。
|
|
|
+ // 文字宽度必须写死才能算出居中偏移,所以这里按实际文案量一次。
|
|
|
+ // 用 CRenderEngine 量真实宽度,比按字数估算稳;量不出来时退回字数估算。
|
|
|
+ int nTextW = 0;
|
|
|
+ HDC hDC = m_pm.GetPaintDC();
|
|
|
+
|
|
|
+ if (hDC != NULL)
|
|
|
+ {
|
|
|
+ SIZE szText = CRenderEngine::GetTextSize(hDC, &m_pm,
|
|
|
+ m_wsLoginErrMsg.c_str(), pText->GetFont(), DT_SINGLELINE);
|
|
|
+
|
|
|
+ if (szText.cx > 0)
|
|
|
+ {
|
|
|
+ nTextW = szText.cx + 2;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (nTextW <= 0)
|
|
|
+ {
|
|
|
+ for (size_t i = 0; i < m_wsLoginErrMsg.size(); i++)
|
|
|
+ {
|
|
|
+ // 中日韩字符按全宽 13px 算,其余按半宽 7px 算
|
|
|
+ nTextW += (m_wsLoginErrMsg[i] > 0x2E80) ? 13 : 7;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 上限取提示条可视宽度 320 减去图标与间距,避免长文案把图标挤出可视区
|
|
|
+ if (nTextW > 300)
|
|
|
+ {
|
|
|
+ nTextW = 300;
|
|
|
+ }
|
|
|
+
|
|
|
+ pText->SetFixedWidth(nTextW);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (pResult)
|
|
|
+ {
|
|
|
+ pResult->SetVisible(true);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
void CLoginWnd::ShowUpdate()
|
|
|
@@ -675,12 +1105,14 @@ void CLoginWnd::ShowLoginAgainOut()
|
|
|
|
|
|
void CLoginWnd::ShowInitData()
|
|
|
{
|
|
|
- CVerticalLayoutUI* pInput = static_cast<CVerticalLayoutUI*>(m_pm.FindControl(_T("login_input")));
|
|
|
- pInput->SetVisible(false);
|
|
|
+ // 登录已经通过,接下来是拉服务器数据。
|
|
|
+ // 按钮恢复常态(反正会被遮罩盖住),然后把右侧表单区整块盖上半透明遮罩。
|
|
|
+ SetLoginLoading(false);
|
|
|
|
|
|
- CVerticalLayoutUI* pLoading = static_cast<CVerticalLayoutUI*>(m_pm.FindControl(_T("login_loading")));
|
|
|
- pLoading->SetVisible(false);
|
|
|
+ CContainerUI* pMask = static_cast<CContainerUI*>(m_pm.FindControl(_T("login_sync_mask")));
|
|
|
|
|
|
- CVerticalLayoutUI* pIniting = static_cast<CVerticalLayoutUI*>(m_pm.FindControl(_T("login_init_data_ing")));
|
|
|
- pIniting->SetVisible(true);
|
|
|
+ if (pMask)
|
|
|
+ {
|
|
|
+ pMask->SetVisible(true);
|
|
|
+ }
|
|
|
}
|