快速登录界面关于如何登录以及多账号列表解析以及config配置文件是如何读取
1、快速登录界面关于如何登录以及快速登录界面账号如何显示
如图所示:根据按下按钮一键登录中途会发生什么。
-
关于一键登录按钮皮肤skin的设置:
<Button name="QuickLoginOkBtn" text="{f 2}一键登录{/f}" float="true" pos="105,186,0,0" width="205" height="33" textcolor="#ff38220c" disabledtextcolor="#FFA7A6AA" showhtml="true" align="center" normalimage="common/login_n.png" hotimage="common/login_o.png" pushedimage="common/login_c.png" />
-
根据Button中的name名字来找相关Button实现逻辑:
- 根据m_pBtnLogin就可以找实现逻辑:
void CSecureUnisignonDlg::Notify(TNotifyUI& msg)
{
if(msg.sType == _T("click"))
{
if(m_pBtnCancel == msg.pSender)
{
this->OnClickBtnCancel();
}
else if(m_pBtnLogin == msg.pSender)
{
this->OnClickBtnLogin();
}
}
else if(msg.sType == _T("itemactivate"))
{
CLoginedAccountListContainerElementUI* pElem = dynamic_cast<CLoginedAccountListContainerElementUI*>(msg.pSender);
this->OnClickBtnLogin();
}
else if (_tcsicmp(msg.sType, _T("link")) == 0)
{
}
}
-
这段代码是一个 DuiLib(DirectUI Library)窗口类
CSecureUnisignonDlg
中的Notify
函数。该函数用于处理窗口中的通知消息,根据不同的消息类型执行相应的操作。下面是对这段代码的解释:-
这段代码是一个 DuiLib(DirectUI Library)窗口类
CSecureUnisignonDlg
中的Notify
函数。该函数用于处理窗口中的通知消息,根据不同的消息类型执行相应的操作。下面是对这段代码的解释:void CSecureUnisignonDlg::Notify(TNotifyUI& msg) { // 判断消息类型 if(msg.sType == _T("click")) { // 处理按钮点击事件 if(m_pBtnCancel == msg.pSender) { this->OnClickBtnCancel(); } else if(m_pBtnLogin == msg.pSender) { this->OnClickBtnLogin(); } } else if(msg.sType == _T("itemactivate")) { // 处理列表项激活事件 CLoginedAccountListContainerElementUI* pElem = dynamic_cast<CLoginedAccountListContainerElementUI*>(msg.pSender); this->OnClickBtnLogin(); } else if (_tcsicmp(msg.sType, _T("link")) == 0) { // 处理链接点击事件 // 暂时没有具体的处理代码 } }
解释:
Notify
函数是 DuiLib 中的消息通知函数,用于处理窗口中各种控件的事件。- 通过检查
msg.sType
的值,可以确定收到的是哪种类型的消息。 - 如果消息类型是 “click”,则表示按钮被点击。根据发送者的身份(
msg.pSender
),分别调用OnClickBtnCancel
或OnClickBtnLogin
函数,以执行相应的操作。 - 如果消息类型是 “itemactivate”,则表示列表项被激活。通过
dynamic_cast
将msg.pSender
转换为列表项类型,然后调用OnClickBtnLogin
函数,执行相应的操作。 - 如果消息类型是 “link”,则表示链接被点击。目前该部分代码中没有具体的处理逻辑,您可以根据需要添加相应的处理代码。
-
这段代码主要用于处理窗口中按钮点击、列表项激活和链接点击等事件。根据实际需求,您可以在对应的事件处理函数中添加具体的业务逻辑。
-
-
然后按钮点击事件的话找到相应后续逻辑:
BOOL CSecureUnisignonDlg::OnClickBtnLogin()
{
// 打印跟踪信息
TRACET();
// 检查是否已选择协议
if (!((ContainerDlg*)m_pParentWindow)->GetProtocolSelected())
{
// 如果未选择协议,显示用户提示
this->ShowUserPrompt(-1, _T("请您详细阅读协议,并勾选同意!"));
return FALSE;
}
// 检查账号列表是否为空
if (NULL == m_pAccountListUI)
return TRUE;
// 如果账号列表为空,返回
if (0 == m_pAccountListUI->GetCount())
return TRUE;
// 设置登录按钮为焦点,并禁用
if (NULL != m_pBtnLogin)
{
m_pBtnLogin->SetFocus();
m_pBtnLogin->SetEnabled(false);
}
// 更新应用程序信息
CSDOLApp::GetInstance()->UpdateAppInfo();
// 打印日志,输出账号列表项的数量
TRACEI("[!SL-SUD-OCBL!] Count = %u\n", m_pAccountListUI->GetCount());
// 检查区域选择
if (this->CheckAreaSelected() == false)
{
return FALSE;
}
// 异步获取动态密钥
CAuthenManager::GetInstance()->AsyncGetDynamicKey(this);
return TRUE;
}
-
这是一个在
CSecureUnisignonDlg
类中定义的OnClickBtnLogin
函数。以下是对该函数的主要步骤的解释:- 函数首先打印跟踪信息,这有助于调试和追踪程序执行流程。
- 检查是否已选择协议,如果没有选择,则显示用户提示信息,并返回
FALSE
。 - 检查账号列表是否为空,如果为空,则返回
TRUE
。 - 设置登录按钮为焦点,并禁用按钮,防止重复点击。
- 更新应用程序信息,可能是某些全局数据的初始化。
- 打印日志,输出账号列表项的数量。
- 检查区域选择,如果检查失败,则返回
FALSE
。 - 最后,通过
CAuthenManager
异步获取动态密钥,该过程可能包含网络请求等异步操作。
-
总体而言,该函数执行了一系列的前提条件检查,更新了一些状态,禁用了按钮,然后触发了异步操作。具体操作会根据函数中调用的其他方法和类的实现而有所不同。
-
根据**CAuthenManager::GetInstance()->AsyncGetDynamicKey(this);**触发异步操作获取动态密钥后续实现逻辑:
BOOL CAuthenManager::AsyncGetDynamicKey(void *pUserData) { // 打印跟踪信息 TRACET(); // 检查 SdoBase 句柄是否为空 if (m_pSdoBaseHandle == NULL) { TRACEE("AM - ag.dk - sbh is NULL!"); return FALSE; } // 记录开始时间 CTimeRecorder::GetInstance()->RecordStartTime(CallInterface_GetDynamicKey, ::GetTickCount()); m_nLastActionId = CallInterface_GetDynamicKey; int nError = 0; int nRetryTimes = 3; // 循环重试获取动态密钥 while (nRetryTimes-- != 0) { TRACED("%d", nRetryTimes); // 设置用户数据 SdoBase_SetUserData(m_pSdoBaseHandle, pUserData); // 调用 SdoBase_GetDynamicKey 获取动态密钥 nError = SdoBase_GetDynamicKey(m_pSdoBaseHandle); // 如果返回错误为 ERROR_PROCESSING,则取消请求并等待一段时间后重试 if (nError == ERROR_PROCESSING) { AsyncCancelRequests(pUserData); Sleep(300); continue; } // 如果没有错误,跳出循环 break; } // 返回操作是否成功 return (nError == 0); }
-
解释:
- 函数首先打印跟踪信息,这有助于调试和追踪程序执行流程。
- 检查
SdoBase
句柄是否为空,如果为空,则返回FALSE
。 - 记录开始时间,这可能用于计算异步操作的执行时间。
- 初始化错误码和重试次数。
- 进行重试循环,最多重试 3 次。
- 在每次循环中,设置用户数据,并调用
SdoBase_GetDynamicKey
获取动态密钥。 - 如果返回错误为
ERROR_PROCESSING
,则取消异步请求并等待 300 毫秒后继续下一次循环。 - 如果没有错误,跳出循环。
- 最后,返回操作是否成功,即检查最终的错误码是否为 0。
-
该函数的主要目的是通过
SdoBase_GetDynamicKey
异步获取动态密钥,具体的异步操作可能涉及到网络请求等。循环重试部分是为了处理可能的错误情况。 -
然后如果
SdoBase_GetDynamicKey
调用成功的话就会执行相应回调函数:-
-
void SDOAPI CAuthenManager::onGetDynamicKeyCallback(int nResultCode, const char* szFailReason, const char* szDynamicKey, const char* guid, SdoBaseHandle* handle) { // 打印跟踪信息 TRACET(); // 如果结果码不为 0,表示获取动态密钥失败 if (nResultCode != 0) { // 对特定范围的错误码进行映射 if (nResultCode >= -10130200 && nResultCode <= -10130100) { // 将认证组件中的错误码 [-10130200, -10130100] 映射到区间 [-10524200, -10524100] nResultCode = nResultCode - 394000; } // 如果失败原因不为空,打印警告信息 if (szFailReason != NULL) { TRACEW("AM -- o.g.dkcb --- %d --- %s", nResultCode, szFailReason); } } else { // 获取动态密钥成功,缓存动态密钥 if (szDynamicKey != NULL) { sm_pAuthenManager->m_strDynamicKey = StringHelper::ANSIToUnicode(szDynamicKey); } } // 记录最后一次时间差并上报 sm_pAuthenManager->RecordLastTimeSpanAndReport(nResultCode); // 构造获取动态密钥结果对象 SGetDynamicKeyResult result; result.m_nResult = nResultCode; result.m_strFailReason = StringHelper::ANSIToUnicode(szFailReason); result.m_strDynamicKey = (szDynamicKey != NULL) ? StringHelper::ANSIToUnicode(szDynamicKey) : _T(""); result.m_pUserData = SdoBase_GetUserData(sm_pAuthenManager->m_pSdoBaseHandle); result.m_strguid = StringHelper::ANSIToUnicode(guid); // 通知登录窗口,发送 WM_LOGIN_GET_DYNAMICKEY 消息 sm_pAuthenManager->NotifyLoginWnd(WM_LOGIN_GET_DYNAMICKEY, &result, 0); }
-
解释:
- 函数首先打印跟踪信息,这有助于调试和追踪程序执行流程。
- 如果结果码不为 0,表示获取动态密钥失败,对特定范围的错误码进行映射。
- 如果失败原因不为空,打印警告信息。
- 如果结果码为 0,表示获取动态密钥成功,将动态密钥缓存在
CAuthenManager
类的成员变量中。 - 调用
RecordLastTimeSpanAndReport
函数记录最后一次时间差并上报,可能用于性能统计。 - 构造
SGetDynamicKeyResult
对象,存储获取动态密钥的结果和相关信息。 - 通过
NotifyLoginWnd
函数通知登录窗口,发送WM_LOGIN_GET_DYNAMICKEY
消息,传递获取动态密钥的结果。
-
然后调用**sm_pAuthenManager->NotifyLoginWnd(WM_LOGIN_GET_DYNAMICKEY, &result, 0);**通知相关窗口获取动态密钥成功或者失败:
-
-
void CAuthenManager::NotifyLoginWnd(int nNotifyType, void* result, void* ud) { // 打印跟踪信息 TRACET(); // 全部采用 PostMessage 防止阻塞认证组件中的线程 // 动态分配的内存在相关窗口收到相应消息后再释放 switch (nNotifyType) { // 根据不同的消息类型构造消息并发送 case WM_LOGIN_GET_DYNAMICKEY: { SGetDynamicKeyResult *pResult = new SGetDynamicKeyResult(*(SGetDynamicKeyResult*)result); ::PostMessage(this->m_hWnd, WM_LOGIN_GET_DYNAMICKEY, WPARAM(pResult), 0); } break; case WM_LOGIN_AUTHEN_RESULT: { SAuthenResult *pResult = new SAuthenResult(*(SAuthenResult*)result); ::PostMessage(this->m_hWnd, WM_LOGIN_AUTHEN_RESULT, WPARAM(pResult), 0); } break; // ... 其他消息类型的处理 default: break; } }
-
这是
CAuthenManager
类中的NotifyLoginWnd
函数,该函数用于通过PostMessage
发送消息通知登录窗口(或其他窗口)。该函数根据传入的消息类型(nNotifyType
)构造相应的消息结构体,并将消息通过PostMessage
发送到窗口的消息队列中。以下是对该函数的主要步骤的解释:- 函数首先打印跟踪信息,这有助于调试和追踪程序执行流程。
- 根据传入的消息类型(
nNotifyType
)使用switch
语句进行分支处理,构造不同类型的消息结构体。 - 对于每种消息类型,动态分配一个新的消息结构体对象,并通过
PostMessage
发送消息给窗口。WPARAM
参数用于传递指向消息结构体的指针。 - 在动态分配的内存上述消息结构体被窗口收到相应消息后进行释放,因为它是通过
new
进行的动态分配。
-
这样的设计允许在异步操作完成后以非阻塞的方式向窗口发送消息,实现了消息的异步通知和处理。不同的消息类型对应不同的消息结构体,以便在消息处理时能够根据消息类型获取相应的信息。
-
然后根据对应的窗口收到的WM_LOGIN_GET_DYNAMICKEY消息:
-
-
LRESULT CSecureUnisignonDlg::HandleCustomMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { // 打印跟踪信息 TRACET(); bHandled = FALSE; switch( uMsg ) { // 根据不同的消息类型调用相应的处理函数 case WM_LOGIN_GET_DYNAMICKEY: { // 转换消息参数为相应的结构体类型 SGetDynamicKeyResult *pGetDynamicKeyResult = (SGetDynamicKeyResult*)wParam; // 调用处理函数处理获取动态密钥的结果 this->OnGetDynamicKeyResult(pGetDynamicKeyResult); // 释放动态分配的结构体内存 SAFE_DELETE(pGetDynamicKeyResult); } break; case WM_LOGIN_AUTHEN_RESULT: { SAuthenResult *pSdoMobileAuthenResult = (SAuthenResult*)wParam; this->OnAuthenResult(pSdoMobileAuthenResult); SAFE_DELETE(pSdoMobileAuthenResult); } break; case WM_LOGIN_AUTHEN_CONTINUE: { SAuthenContinue* pSdoaAuthenContinue = (SAuthenContinue*)wParam; this->OnAuthenContinue(pSdoaAuthenContinue); SAFE_DELETE(pSdoaAuthenContinue); } break; case WM_LOGIN_UPDATE_FCM_INFO: { SUpdateFcmInfoResult* pSUpdateFcmInfoResult = (SUpdateFcmInfoResult*)wParam; this->ShowFcmDlg(pSUpdateFcmInfoResult); SAFE_DELETE(pSUpdateFcmInfoResult); } break; default: // 如果是其他消息类型,则标记为未处理 bHandled = FALSE; } return 0; }
-
这是
CSecureUnisignonDlg
类中的HandleCustomMessage
函数,用于处理自定义的窗口消息。根据收到的消息类型(uMsg
),该函数调用相应的处理函数,然后标记消息已经被处理。以下是对该函数的主要步骤的解释:- 函数首先打印跟踪信息,这有助于调试和追踪程序执行流程。
- 使用
switch
语句根据消息类型(uMsg
)进行分支处理。 - 对于每个消息类型,转换消息参数为相应的结构体类型。
- 调用相应的处理函数(例如
OnGetDynamicKeyResult
、OnAuthenResult
等)来处理消息。 - 释放动态分配的结构体内存,以避免内存泄漏。
- 标记消息已经被处理,以防止消息传递到默认的消息处理函数中。
-
这样的设计允许在窗口收到自定义消息时执行特定的操作,根据消息类型调用相应的处理函数,以实现定制的消息处理逻辑。
-
然后调用**this->OnGetDynamicKeyResult(pGetDynamicKeyResult);**把获取动态密钥的结果传入接口:
-
-
void CSecureUnisignonDlg::OnGetDynamicKeyResult(SGetDynamicKeyResult *pGetDynamicKeyResult) { // 检查用户数据,确保与当前窗口关联 if (pGetDynamicKeyResult->m_pUserData != this) { return; } // 如果获取动态密钥失败 if (pGetDynamicKeyResult->m_nResult != 0) { // 打印警告信息 TRACEW("Get dk failed!"); // 启用登录按钮 m_pBtnLogin->SetEnabled(true); // 显示用户提示信息 this->ShowUserPrompt(pGetDynamicKeyResult->m_nResult, pGetDynamicKeyResult->m_strFailReason); return; } // 记录收集登录数据的开始时间 CTimeRecorder::GetInstance()->RecordStartTime(CollectLoginData, ::GetTickCount()); // 调用 OnSSOLogin 函数进行单点登录操作 BOOL bLoginResult = OnSSOLogin(); // 打印日志,输出登录结果 TRACEI("[!SL-SUD-OCBL!] Result = %d\n", bLoginResult); // 如果登录结果为 FALSE,表示是异步操作 if (!bLoginResult) { // 启用登录按钮 m_pBtnLogin->SetEnabled(true); // 发送自定义消息 WM_NOTIFY_SECUREUNISIGNON_RETURN 到父窗口 ::SendMessage(m_pParentWindow->GetHWND(), WM_NOTIFY_SECUREUNISIGNON_RETURN, 0, 0); } }
-
-
-
-
-
-
-
-