最近遇到要在一个DuiLib::CListUI中显示动态数据的子任务.
在使用我改版的DuiLib中发现如下问题, 真杯具.
* 如果反复添加删除CListContainerElementUI, 会引起CListUI所在的Dialog退出时挂掉的问题.
e.g. 在CListUI中增加2000条数据, 在CListUI中删掉2000条数据, 如此反复20次. 再退出该CListUI所在的Dialog, UI就挂掉了.
现象是WM_PAINT陷入了一个循环(这个正常), 但是UI显示不出来了.
这个问题我回避了, 搞不定. 采用妥协的方法, 使CListUI只固定一个行数(e.g. 20行), 根据要显示的内容计算List的UI可见部分应该写什么数据.
这样, 只在建立ListUI时, 插入了新的行. 以后都是更新行上的内容. 就不存在退出时UI挂掉的问题.
* 当CListUI一次添加太多数据时(e.g. 一次添加2000行), 当滚动时, List反应特别的迟钝, 有时还会导致UI卡死.
这个问题我同样回避了, 搞不定. 采用妥协的方法, 使CListUI只固定一个行数(e.g. 20行), 根据要显示的内容计算List的UI可见部分应该写什么数据.
这样, 只在建立ListUI时, 插入了新的行. 以后都是更新行上的内容. 就不存在滚动List自带竖向滚动条时, 引起的机率性UI卡死.
运行效果图:
工程下载点 : srcbk_2015_0824_1711_prj_dlg_show_list_ui_use_massive_amounts_of_data.zip
工程预览:
/// @file MainDlg.h
/// @brief 主对话框的定义, 基类为CXmlWnd
#ifndef __MAIN_DLG_H__
#define __MAIN_DLG_H__
#include "stdafx.h"
#include
#include
#include
#include
/// @file MainDlg.cpp
#include "stdafx.h"
#include "resource.h"
#include "resource.h"
#include
#include
#include
#include
#include
#include "MainDlg.h"
/// Hook键盘产生的数据, 动机 : 当焦点在Edit中时, DuiLib不传递 WM_KEYxx + VT_TAB
/// 下全局钩子, 不采用DLL注入方式, 只监控本程序的键盘输入
/// 当有Tab键按下时, PostMessage 到主程序中处理,
/// 当此时, 登录框出现时, 就切换用户名和密码的Edit焦点
TAG_HOOK_DATA g_KbHookData;
TAG_HOOK_DATA g_MouseHookData;
HWND g_hHwndMain = NULL;
LRESULT CALLBACK MouseProc(int nCode,WPARAM wParam,LPARAM lParam)
{
if (nCode==0)
{
MOUSEHOOKSTRUCT* pMouseHook= (MOUSEHOOKSTRUCT*)lParam;
if ( pMouseHook->hwnd == NULL )
{
}
}
return CallNextHookEx(g_MouseHookData.hHook, nCode, wParam, lParam);
}
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
static LONG_PTR lVkCodePrev_Tab = 0;
static LONG_PTR lVkCode_Tab = 0;
static LONG_PTR lVkCode_Enter = 0;
static LONG_PTR lVkCode_Cancel = 0;
LONG_PTR lTemp = 0;
/** when tab key press down and up
KeyboardProc : nCode = 0x0, wParam = 0x9, lParam = 0xF0001
KeyboardProc : nCode = 0x0, wParam = 0x9, lParam = 0xC00F0001
*/
if (0 == nCode)
{
switch (wParam)
{
case VK_TAB:
{
lVkCode_Tab = (LONG_PTR)lParam;
lTemp = lVkCode_Tab & 0xFFF00000;
if (0 == lTemp)
{
// tab key press down
lVkCodePrev_Tab = lVkCode_Tab;
}
else
{
// tab key press up
if (lVkCode_Tab != lVkCodePrev_Tab)
{
lVkCodePrev_Tab = lVkCode_Tab;
if (NULL != g_hHwndMain)
{
::PostMessageW(g_hHwndMain, WM_TAB_KEY_PRESS, 0, 0);
}
}
}
}
break;
case VK_RETURN:
{
lVkCode_Enter = (LONG_PTR)lParam;
lTemp = lVkCode_Enter & 0xFFF00000;
if (lTemp > 0)
{
// key press up
if (NULL != g_hHwndMain)
{
::PostMessageW(g_hHwndMain, WM_ENTER_KEY_PRESS, 0, 0);
}
}
}
break;
case VK_UP:
{
lVkCode_Enter = (LONG_PTR)lParam;
lTemp = lVkCode_Enter & 0xFFF00000;
if (lTemp>0)
{
POINT pt;
GetCursorPos(&pt);
::PostMessageW(g_hHwndMain,WM_UP_KEY_PRESS,pt.x,pt.y);
}
}
break;
case VK_DOWN:
{
lVkCode_Enter = (LONG_PTR)lParam;
lTemp = lVkCode_Enter & 0xFFF00000;
if (lTemp>0)
{
::PostMessageW(g_hHwndMain,WM_DOWN_KEY_PRESS,0,0);
}
}
break;
case VK_ESCAPE:
{
lVkCode_Cancel = (LONG_PTR)lParam;
lTemp = lVkCode_Cancel & 0xFFF00000;
if (0 == lTemp)
{
// key press down
if (NULL != g_hHwndMain)
{
::PostMessageW(g_hHwndMain, WM_CANCEL_KEY_PRESS, 0, 0);
}
}
}
break;
default:
break;
}
}
return CallNextHookEx(g_KbHookData.hHook, nCode, wParam, lParam);
}
CMainDlg::CMainDlg(WCHAR * pcXmlFileName, WCHAR * pcWndClassName)
: CXmlWnd(pcXmlFileName, pcWndClassName),
m_iCntFilesListRowMax(4),
m_iDataSoruceRecordCnt(200000)
{
DataInit();
}
CMainDlg::~CMainDlg(void)
{
DataUnInit();
}
DUI_BEGIN_MESSAGE_MAP(CMainDlg, CXmlWnd)
DUI_ON_MSGTYPE(DUI_MSGTYPE_CLICK, OnClick)
DUI_END_MESSAGE_MAP()
void CMainDlg::UiInit()
{
do
{
m_dwMainTID = ::GetCurrentThreadId();
WriteLogEx(L"m_dwMainTID = 0x%x or %d", m_dwMainTID, m_dwMainTID);
m_pTabView = (DuiLib::CTabLayoutUI*)m_PaintManager.FindControl(L"TabLayout_setup_now");
if (NULL == m_pTabView)
break;
m_pPage_StartProg = (DuiLib::CContainerUI*)m_pTabView->FindSubControl(L"Container_page_install_over");
if (NULL == m_pPage_StartProg)
break;
UiInit_List();
switch_view(e_view_index_start_prog);
/// 将窗体放到桌面右下角
MoveMyWindowToDesktopRightBottom();
ThreadProcStart();
} while (0);
}
void CMainDlg::UiInit_List()
{
int iWidth = 0;
LPCTSTR pcDefaultAttributes = NULL;
do
{
if (NULL == m_pListFiles)
{
m_pStatusMsg = (CLabelUI*)m_PaintManager.FindControl(L"Label_UI_MSG");
_ASSERT(NULL != m_pStatusMsg);
m_pContainerForVScrollBarForFilesList = (CContainerUI*)m_PaintManager.FindControl(L"container_for_v_scrollbar_for_list");
_ASSERT(NULL != m_pContainerForVScrollBarForFilesList);
m_pVScrollBarForFilesList = (CScrollBarUI*)m_PaintManager.FindControl(L"scrollbar_for_files_list");
_ASSERT(NULL != m_pVScrollBarForFilesList);
m_pVScrollBarForFilesList->SetOwner(NULL);
m_pVScrollBarForFilesList->SetManager(&m_PaintManager, NULL, false);
pcDefaultAttributes = m_PaintManager.GetDefaultAttributeList(_T("VScrollBar"));
if (NULL != pcDefaultAttributes)
{
m_pVScrollBarForFilesList->ApplyAttributeList(pcDefaultAttributes);
/// 为了让滚动时,List中的内容可以衔接的观看
m_pVScrollBarForFilesList->SetLineSize((m_iCntFilesListRowMax > 3) ? (m_iCntFilesListRowMax - 1) : 1);
/// 重新安装滚动条配置, 设置合适的滚动条宽度
iWidth = m_pVScrollBarForFilesList->GetFixedWidth();
m_pContainerForVScrollBarForFilesList->SetFixedWidth(iWidth);
}
m_pListFiles = (CListUI*)m_PaintManager.FindControl(L"list_files");
_ASSERT(NULL != m_pListFiles);
m_pListFiles->SetAttribute(L"bkcolor", L"#FFFFFFFF");
m_pListFiles->SetAttribute(_T("itemaltbk"),_T("true"));
m_pListFiles->SetAttribute(_T("itembkcolor"),_T("#fff8f8f8"));
m_pListFiles->SetAttribute(_T("itemhotbkcolor"), _T("#FFE4E4E4"));
m_pListFiles->SetAttribute(_T("itemselectedbkcolor"), _T("#FFD9E1EE"));
m_pListFiles->EnableScrollBar(false, true);
m_pListFiles->GetHeader()->SetMinWidth(100);
}
} while (0);
}
void CMainDlg::clearFindData()
{
int iIndex = 0;
float fProcessPercent = 0;
float fProcessPercentPerv = 0;
DWORD dwTickBegin = 0;
DWORD dwTickEnd = 0;
std::wstring strTmp = L"";
INFO_LIST_ITEM_DATA* pData = NULL;
std::vector::iterator it;
dwTickBegin = GetTickCount();
while (1)
{
Sleep(0);
it = m_deqFindData.begin();
if (it == m_deqFindData.end())
break;
if (NULL != *it)
{
pData = m_deqFindData.front();
if (NULL != pData)
SAFE_DELETE(pData);
m_deqFindData.erase(m_deqFindData.begin());
iIndex++;
}
dwTickEnd = GetTickCount();
if ((dwTickEnd - dwTickBegin) > 500)
{
fProcessPercent = (1.0f * iIndex / m_iDataSoruceRecordCnt) * 100;
if ((fProcessPercentPerv != fProcessPercent)
&& ((fProcessPercent - 0.001f) > fProcessPercentPerv)) {
fProcessPercentPerv = fProcessPercent;
dwTickBegin = GetTickCount();
strTmp = ns_base::StringFormatV(
L"程序正在退出, 资源释放进度%.2f%%, 请稍候...",
fProcessPercent);
ShowMsg(strTmp.c_str());
}
}
}
m_deqFindData.resize(0);
}
void CMainDlg::MoveMyWindowToDesktopRightBottom()
{
ASSERT(::IsWindow(m_hWnd));
ASSERT((GetWindowStyle(m_hWnd)&WS_CHILD)==0);
RECT rcDlg = { 0 };
::GetWindowRect(m_hWnd, &rcDlg);
RECT rcArea = { 0 };
RECT rcCenter = { 0 };
HWND hWnd=*this;
HWND hWndParent = ::GetParent(m_hWnd);
HWND hWndCenter = ::GetWindowOwner(m_hWnd);
if (hWndCenter!=NULL)
hWnd=hWndCenter;
// 处理多显示器模式下屏幕居中
MONITORINFO oMonitor = {};
oMonitor.cbSize = sizeof(oMonitor);
::GetMonitorInfo(::MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST), &oMonitor);
rcArea = oMonitor.rcWork;
if( hWndCenter == NULL )
rcCenter = rcArea;
else
::GetWindowRect(hWndCenter, &rcCenter);
int DlgWidth = rcDlg.right - rcDlg.left;
int DlgHeight = rcDlg.bottom - rcDlg.top;
// Find dialog's upper left based on rcCenter
int xLeft = rcCenter.right - DlgWidth;
int yTop = rcCenter.bottom - DlgHeight;
// The dialog is outside the screen, move it inside
if( xLeft < rcArea.left )
xLeft = rcArea.left;
else if( xLeft + DlgWidth > rcArea.right )
xLeft = rcArea.right - DlgWidth;
if( yTop < rcArea.top )
yTop = rcArea.top;
else if( yTop + DlgHeight > rcArea.bottom )
yTop = rcArea.bottom - DlgHeight;
::SetWindowPos(m_hWnd, NULL, xLeft, yTop, -1, -1, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
}
void CMainDlg::DataInit()
{
m_strTipMsg = L"";
m_strTipMsgPerv = L"";
m_bMsgProcessOver_RefreshFilesInfo_RemoveAll = FALSE;
m_bMsgProcessOver_RefreshFilesInfo = FALSE;
m_pStatusMsg = NULL;
m_pListFiles = NULL;
m_pVScrollBarForFilesList = NULL;
m_pContainerForVScrollBarForFilesList = NULL;
m_bRunObjProgNow = FALSE;
m_dwMainTID = 0;
m_pTabView = NULL;
m_pPage_StartProg = NULL;
}
void CMainDlg::DataUnInit()
{
}
LONG CMainDlg::GetStyle()
{
long dwStyle = __super::GetStyle();
dwStyle &= ~WS_MAXIMIZEBOX;
return dwStyle;
}
/// CMainDlg::GetExStyle 是虚函数, 在WindowImplBase::OnCreate中被调用, 用来设置扩展窗口风格
LONG CMainDlg::GetExStyle()
{
long dwStyle = __super::GetExStyle();
/// 禁止接受文件拖拽
dwStyle &= ~WS_EX_ACCEPTFILES;
/// 禁止产生任务栏图标
dwStyle |= WS_EX_TOOLWINDOW;
dwStyle &= ~(WS_EX_APPWINDOW);
return dwStyle;
}
void CMainDlg::InsertRow2FileList_RemoveAll()
{
int iCnt = 0;
int iIndex = 0;
CControlUI* pCtrl = NULL;
CListContainerElementUI* pListItem = NULL;
do
{
/// 填充之前, 都是重新填充, 将旧的丢掉
/// 反复删除再插入会导致UI挂死, 这里临时做的处理为, 将行内容全部清除和隐藏
iCnt = m_pListFiles->GetCount();
for (iIndex = 0; iIndex < iCnt; iIndex++)
{
pListItem = (CListContainerElementUI*)m_pListFiles->GetItemAt(iIndex);
ClearRow2FileList(pListItem);
}
} while (0);
}
void CMainDlg::ClearRow2FileList(CListContainerElementUI* pListItem)
{
CButtonUI* pCtrlIcon = NULL;
CLabelUI* pCtrlFileName = NULL;
CLabelUI* pCtrlFileSize = NULL;
CLabelUI* pCtrlFileTime = NULL;
CLabelUI* pCtrlFileType = NULL;
do
{
if (NULL == pListItem)
break;
pCtrlIcon = (CButtonUI*)pListItem->FindSubControl(LIST_ROW_ELEMENT_NAME_FILE_ICON);
if (NULL != pCtrlIcon)
pCtrlIcon->SetNormalImage(L"");
pCtrlFileName = (CLabelUI*)pListItem->FindSubControl(LIST_ROW_ELEMENT_NAME_FILE_NAME);
if (NULL != pCtrlFileName)
pCtrlFileName->SetText(L"");
pCtrlFileSize = (CLabelUI*)pListItem->FindSubControl(LIST_ROW_ELEMENT_NAME_SIZE);
if (NULL != pCtrlFileSize)
pCtrlFileSize->SetText(L"");
pCtrlFileTime = (CLabelUI*)pListItem->FindSubControl(LIST_ROW_ELEMENT_NAME_TIME);
if (NULL != pCtrlFileTime)
pCtrlFileTime->SetText(L"");
pCtrlFileType = (CLabelUI*)pListItem->FindSubControl(LIST_ROW_ELEMENT_NAME_TYPE);
if (NULL != pCtrlFileType)
pCtrlFileType->SetText(L"");
} while (0);
}
void CMainDlg::fn_ShowCurTreeNodeFilesInfo()
{
InsertRow2FileList(m_deqFindData);
}
void CMainDlg::InsertRow2FileList(std::vector& deqFindData)
{
std::deque::iterator it;
int iCnt = 0;
int iIndex = 0;
int iScrollPos = 0;
int iLastScrollPos = 0;
int iScrollRange = 0;
int iDataIndex = 0;
int iDataBeginIndex = 0;
int iDataEndIndex = 0;
CListContainerElementUI* pListItem = NULL;
do
{
iCnt = deqFindData.size();
if (iCnt <= m_iCntFilesListRowMax)
{
iDataBeginIndex = 0;
iDataEndIndex = (iCnt > 0) ? (iCnt - 1) : 0;
}
else
{
iScrollPos = m_pVScrollBarForFilesList->GetScrollPos();
iLastScrollPos = m_pVScrollBarForFilesList->GetLastScrollPos();
iScrollRange = m_pVScrollBarForFilesList->GetScrollRange();
iDataBeginIndex = (int)((1.0f * iScrollPos / iScrollRange) * iCnt);
/// @todo 从最下面开始向上移动的一次, 不会显示新的内容
// if (iScrollPos >= iLastScrollPos)
{
if (iLastScrollPos == (iCnt - 1))
{
OutputDebugStringW(L"");
}
/// 向下移动
if ((iDataBeginIndex + m_iCntFilesListRowMax) >= iCnt)
{
iDataEndIndex = iCnt - 1;
iDataBeginIndex = iDataEndIndex - (m_iCntFilesListRowMax - 1);
}
else
{
iDataEndIndex = iDataBeginIndex + (m_iCntFilesListRowMax - 1);
}
}
// else
// {
// /// 向上移动
// if ((iDataBeginIndex + m_iCntFilesListRowMax) >= iCnt)
// {
// iDataEndIndex = iDataBeginIndex;
// iDataBeginIndex = iDataEndIndex - (m_iCntFilesListRowMax - 1);
// }
// else
// {
// iDataBeginIndex = 0;
// iDataEndIndex = m_iCntFilesListRowMax - 1;
// }
// }
}
iCnt = m_pListFiles->GetCount();
for (iDataIndex = iDataBeginIndex, iIndex = 0;
iDataIndex <= iDataEndIndex;
iDataIndex++, iIndex++)
{
if (iIndex < iCnt)
{
pListItem = (CListContainerElementUI*)m_pListFiles->GetItemAt(iIndex);
}
else
{
pListItem = NULL;
}
if (deqFindData.size() > 0)
{
/// 插入或更新行
InsertRow2FileList(deqFindData.at(iDataIndex), pListItem);
}
else
{
/// 清除行
ClearRow2FileList(pListItem);
}
}
m_pListFiles->Invalidate();
} while (0);
}
void CMainDlg::InsertRow2FileList(INFO_LIST_ITEM_DATA*& FindData, CListContainerElementUI*& pListItem)
{
_ASSERT(NULL != FindData);
int iTmp = 0;
LONGLONG llTime = 0;
std::wstring strPicFileType = L"";
std::wstring strFileType = L"";
BOOL bObjIsDir = FALSE;
std::wstring::size_type nPos = std::wstring::npos;
std::wstring strFileName = ns_base::A2Wex(ns_base::UTF8ToMB(FindData->cFilePath).c_str()).c_str();
std::wstring strFileSize = ns_base::Size2SizeString(atol(FindData->cFileSize), FALSE).c_str();
std::wstring strFileTime = L"";
SYSTEMTIME st;
CButtonUI* pCtrlIcon = NULL;
CLabelUI* pCtrlFileName = NULL;
CLabelUI* pCtrlFileSize = NULL;
CLabelUI* pCtrlFileTime = NULL;
CLabelUI* pCtrlFileType = NULL;
do
{
if (NULL == m_pListFiles)
break;
iTmp = m_pListFiles->GetCount();
/// @todo ls 快了8个小时, 要转成本地时间
llTime = ns_base::string2longlong(FindData->cLastWriteTime);
if (ns_base::php_time_2_systemtime((long)llTime, &st))
{
strFileTime = ns_base::StringFormatV(L"%d-%d-%d %d:%d:%d",
st.wYear,
st.wMonth,
st.wDay,
st.wHour,
st.wMinute,
st.wSecond);
}
if (0 == stricmp(FindData->cFileType, "type_dir"))
{
strPicFileType = L"dir.png";
strFileType = L"目录";
bObjIsDir = TRUE;
}
else
{
strPicFileType = L"file.png";
strFileType = L"文件";
bObjIsDir = FALSE;
}
/// 如果(NULL != pListItem), 就是更新了
if (NULL == pListItem)
{
/// 插入一个文件夹或者文件
CreateListContainerElementUI(
&m_PaintManager,
pListItem,
L"ListItem_File.xml",
this);
/// 将目录排前面, 文件放后面
m_pListFiles->AddAt(
pListItem,
0 /*bObjIsDir ? 0 : m_pListFiles->GetCount()*/);
}
pCtrlIcon = (CButtonUI*)pListItem->FindSubControl(LIST_ROW_ELEMENT_NAME_FILE_ICON);
if (NULL != pCtrlIcon)
pCtrlIcon->SetNormalImage(strPicFileType.c_str());
pCtrlFileName = (CLabelUI*)pListItem->FindSubControl(LIST_ROW_ELEMENT_NAME_FILE_NAME);
if (NULL != pCtrlFileName)
{
nPos = strFileName.rfind(L'/');
if (std::wstring::npos != nPos)
{
strFileName = strFileName.substr(nPos + 1, -1);
}
pCtrlFileName->SetText(strFileName.c_str());
}
pCtrlFileSize = (CLabelUI*)pListItem->FindSubControl(LIST_ROW_ELEMENT_NAME_SIZE);
if (NULL != pCtrlFileSize)
pCtrlFileSize->SetText(strFileSize.c_str());
pCtrlFileTime = (CLabelUI*)pListItem->FindSubControl(LIST_ROW_ELEMENT_NAME_TIME);
if (NULL != pCtrlFileTime)
pCtrlFileTime->SetText(strFileTime.c_str());
pCtrlFileType = (CLabelUI*)pListItem->FindSubControl(LIST_ROW_ELEMENT_NAME_TYPE);
if (NULL != pCtrlFileType)
pCtrlFileType->SetText(strFileType.c_str());
} while (0);
}
LRESULT CMainDlg::WndMessageProc_WM_DISP_REFRESH(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (WM_DISP_REFRESH == uMsg)
{
switch (wParam)
{
case DISP_REFRESH_CUR_TREE_NODE_FILES_INFO_REMOVE_ALL:
InsertRow2FileList_RemoveAll();
m_bMsgProcessOver_RefreshFilesInfo_RemoveAll = TRUE;
break;
case DISP_REFRESH_CUR_TREE_NODE_FILES_INFO:
fn_ShowCurTreeNodeFilesInfo();
m_bMsgProcessOver_RefreshFilesInfo = TRUE;
break;
case DISP_MSG:
ShowMsg(m_strTipMsg.c_str());
break;
default:
break;
}
}
return S_OK;
}
void CMainDlg::ShowMsg(const WCHAR* pcMsg)
{
do
{
/// 防止显示重复数据时, 由于要加锁判断, 使显示效率降低
if (0 == m_strTipMsgPerv.compare((NULL != pcMsg) ? pcMsg : L""))
break;
m_Locker_MainUI.enter();
m_strTipMsg = (NULL != pcMsg) ? pcMsg : L"";
m_Locker_MainUI.leave();
if (GetCurrentThreadId() != m_dwMainTID)
{
::PostMessageW(this->GetHWND(), WM_DISP_REFRESH, DISP_MSG, 0);
}
else
{
m_Locker_MainUI.enter();
m_pStatusMsg->SetText(m_strTipMsg.c_str());
m_Locker_MainUI.leave();
}
} while (0);
}
LRESULT CMainDlg::WndMessageProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
BOOL bNeedDefaultProcess = FALSE;
do
{
switch (uMsg)
{
case WM_DISP_REFRESH:
WndMessageProc_WM_DISP_REFRESH(uMsg, wParam, lParam);
break;
/// 如果窗口的扩展风格 WS_EX_ACCEPTFILES 被禁止, 是接受不到 WM_DROPFILES 消息的
/// 同时, 拖动文件到CMainDlg时, 图标是禁止样式的图标
case WM_DROPFILES:
OutputDebugStringW(L"");
break;
case WM_CREATE:
bNeedDefaultProcess = TRUE;
break;
case WM_SWITCH_VIEW:
switch_view((e_view_index)wParam);
break;
case WM_CLOSE:
EntryUiDestory(TRUE);
bNeedDefaultProcess = ThreadProcEnd(FALSE);
break;
default:
bNeedDefaultProcess = TRUE;
break;
}
if (bNeedDefaultProcess)
return __super::WndMessageProc(uMsg, wParam, lParam);
} while (0);
return S_OK;
}
void CMainDlg::InitWindow()
{
BOOL bRc = FALSE;
DWORD dwStyle = 0;
UiInit();
}
CControlUI* CMainDlg::CreateUiControlByMySelf(LPCTSTR pstrClass)
{
if (0 == _tcscmp(pstrClass,_T("ButtonGif")))
return new CButtonGifUI;
return NULL;
}
LRESULT CMainDlg::SysMessageProc(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled)
{
return __super::SysMessageProc(uMsg, wParam, lParam, bHandled);
}
void CMainDlg::OnFinalMessage(HWND hWnd)
{
m_PaintManager.FreeResourceZip(); ///< !
__super::OnFinalMessage(hWnd);
}
void CMainDlg::Notify(TNotifyUI & msg)
{
std::wstring strName = L"";
do
{
if (NULL == msg.pSender)
{
break;
}
strName = msg.pSender->GetName().GetData();
if (msg.sType == DUI_MSGTYPE_SCROLL)
{
if (msg.pSender == m_pVScrollBarForFilesList)
{
::PostMessage(this->GetHWND(), WM_DISP_REFRESH, DISP_REFRESH_CUR_TREE_NODE_FILES_INFO, 0);
}
}
} while (0);
return __super::Notify(msg);
}
void CMainDlg::OnClick(TNotifyUI& msg)
{
BOOL bNeedDefaultProcess = FALSE;
std::wstring strName = L"";
if (NULL != msg.pSender)
{
strName = msg.pSender->GetName().GetData();
}
if (strName == L"btn_close_ui5")
{
::PostMessageW(this->GetHWND(), WM_CLOSE, 0, 0);
}
else if (strName == L"btn_run_now")
{
m_bRunObjProgNow = TRUE;
}
else
{
bNeedDefaultProcess = TRUE;
}
if (bNeedDefaultProcess)
__super::OnClick(msg);
}
LRESULT CMainDlg::OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
return __super::OnNcHitTest(uMsg, wParam, lParam, bHandled);
}
void CMainDlg::switch_view(e_view_index PageIndex)
{
static int iWidth = 0;
static int iHeight = 0;
do
{
if (::GetCurrentThreadId() != m_dwMainTID)
{
::PostMessageW(this->GetHWND(), WM_SWITCH_VIEW, PageIndex, 0);
break;
}
if (NULL == m_pTabView)
break;
iWidth = m_pTabView->GetFixedWidth();
iHeight = m_pTabView->GetFixedHeight();
switch (PageIndex)
{
case e_view_index_start_prog:
{
if (NULL != m_pPage_StartProg)
{
m_pTabView->SelectItem(m_pPage_StartProg);
}
}
break;
default:
break;
}
} while (0);
}
void CMainDlg::ThreadProcStart()
{
if (!m_ThreadManager.IsNeedQuitThread()
&& !m_ThreadManager.IsThreadRunning())
{
m_ThreadManager.SetThreadHandle((HANDLE)_beginthreadex(NULL, 0, &CMainDlg::ThreadProc, (void*)this, 0, NULL));
}
}
BOOL CMainDlg::ThreadProcEnd(BOOL bStopNow)
{
BOOL bThreadWasStop = FALSE;
do {
m_ThreadManager.StopThread(bStopNow, L"m_ThreadManager");
bThreadWasStop = !m_ThreadManager.IsThreadRunning();
} while (0);
return bThreadWasStop;
}
UINT WINAPI CMainDlg::ThreadProc(void* pParam)
{
UINT uRc = S_FALSE;
do
{
if (NULL == pParam)
break;
uRc = ((CMainDlg*)pParam)->ThreadProc();
} while (0);
return uRc;
}
UINT WINAPI CMainDlg::ThreadProc()
{
BOOL bScrollBarEnable = FALSE;
int iCntData = 0;
std::wstring strMsg = L"";
// int iTest = 0;
// int iTestPrev = 0x7fffffff;
//
// // while (++iTest > 0)
// // {
// // iTestPrev = iTest;
// // }
//
// // iTestPrev 2147483647 int
// // iTestPrev 0x7fffffff int
//
// iTestPrev /= 1000000; ///< 百万级
// // iTestPrev = 2147
ShowMsg(L"正在准备数据, 请稍后...");
PrepareData();
/// 现在采用只填充一个7行的List, 具体填充的内容由ScorllBar来决定
iCntData = m_deqFindData.size();
bScrollBarEnable = iCntData > m_iCntFilesListRowMax;
m_pVScrollBarForFilesList->SetVisible(TRUE == bScrollBarEnable);
m_pVScrollBarForFilesList->SetEnabled(TRUE == bScrollBarEnable);
if (bScrollBarEnable)
{
m_pVScrollBarForFilesList->SetScrollPos(0);
m_pVScrollBarForFilesList->SetScrollRange((iCntData > 0) ? iCntData : 1);
}
m_pContainerForVScrollBarForFilesList->SetFixedWidth(bScrollBarEnable ? m_pVScrollBarForFilesList->GetFixedWidth() : 1);
m_pContainerForVScrollBarForFilesList->Invalidate();
ShowMsg(L"数据准备完成");
/// 进行首次UI刷新, 让List显示数据
do
{
/// 移除files
m_bMsgProcessOver_RefreshFilesInfo_RemoveAll = FALSE;
::PostMessage(this->GetHWND(), WM_DISP_REFRESH, DISP_REFRESH_CUR_TREE_NODE_FILES_INFO_REMOVE_ALL, 0);
while (!m_bMsgProcessOver_RefreshFilesInfo_RemoveAll)
{
if (IsEntryUiDestory())
break;
::Sleep(10);
}
if (IsEntryUiDestory())
break;
/// 刷新files
m_bMsgProcessOver_RefreshFilesInfo = FALSE;
::PostMessage(this->GetHWND(), WM_DISP_REFRESH, DISP_REFRESH_CUR_TREE_NODE_FILES_INFO, 0);
while (!m_bMsgProcessOver_RefreshFilesInfo)
{
if (IsEntryUiDestory())
break;
::Sleep(10);
}
} while (0);
do
{
::Sleep(20);
if (IsEntryUiDestory())
break;
if (m_ThreadManager.IsNeedQuitThread())
break;
if (ns_base::IsMutextExist(PE_INSTANCE_NAME_CMD_LET_DLG_NOTIFY_QUIT))
{
::PostMessageW(this->GetHWND(), WM_CLOSE, 0, 0);
break;
}
if (m_bRunObjProgNow)
{
m_bRunObjProgNow = FALSE;
RunObjProg();
::PostMessageW(this->GetHWND(), WM_CLOSE, 0, 0);
break;
}
} while (1);
clearFindData();
::PostMessageW(this->GetHWND(), WM_CLOSE, 0, 0);
return S_OK;
}
void CMainDlg::PrepareData()
{
int iTmp = 0;
DWORD dwTickBegin = 0;
DWORD dwTickEnd = 0;
std::wstring strTmp = L"";
int iIndex = 0;
INFO_LIST_ITEM_DATA* pData = NULL;
UINT uTimeVal = 0;
srand((UINT)time(NULL));
dwTickBegin = GetTickCount();
for (iIndex = 0; iIndex < m_iDataSoruceRecordCnt; iIndex++)
{
dwTickEnd = GetTickCount();
if ((dwTickEnd - dwTickBegin) > 500)
{
dwTickBegin = GetTickCount();
strTmp = ns_base::StringFormatV(L"数据准备进度%.2f%%", (1.0f * iIndex / m_iDataSoruceRecordCnt) * 100);
ShowMsg(strTmp.c_str());
}
pData = new INFO_LIST_ITEM_DATA;
_ASSERT(NULL != pData);
::ZeroMemory(pData, sizeof(INFO_LIST_ITEM_DATA));
uTimeVal = (UINT)time(NULL);
uTimeVal += ns_base::RandRange(-10, 10);
strcpy_s(pData->cCreationTime, ns_base::StringFormatVA("%u", uTimeVal).c_str());
strcpy_s(pData->cFileSize, ns_base::StringFormatVA("%d", ns_base::RandRange(100, 1000)).c_str());
iTmp = ns_base::RandRange(1, 2);
strcpy_s(pData->cFileType,
ns_base::StringFormatVA("type_%s", (1 == iTmp) ? "dir" : "file").c_str());
if (1 == iTmp)
{
strcpy_s(pData->cFilePath, ns_base::StringFormatVA("TestDir_%d", iIndex).c_str());
}
else
{
strcpy_s(pData->cFilePath, ns_base::StringFormatVA("TestFile_%d.txt", iIndex).c_str());
}
strcpy_s(pData->cLastWriteTime, ns_base::StringFormatVA("%u", uTimeVal + ns_base::RandRange(1, 10)).c_str());
m_deqFindData.push_back(pData);
}
}
void CMainDlg::RunObjProg()
{
ns_base::CreateProcessEx(L"C:\\Windows\\System32\\notepad.exe", L"", FALSE, TRUE);
}