您的位置:首页 > 产品设计 > UI/UE

DuiLib : 使用CListUI显示海量数据

2015-08-24 16:47 411 查看
最近遇到要在一个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卡死.

这个问题让我做了5天实验, 才想到折中的解决方法.
我采用的方法是:
* 隐藏CListUI实例自带的竖向滚动条控件, 每次只显示一页的数据
* 在CListUI实例右边的Container中自己摆一个 CScrollBarUI, 用户点击滚动条时, 记录点击的位置, 发送自定义消息, 去刷新CListUI中的显示.

实验过了, 准备20W条数据, 在CListUI中显示, 也是蛮快的, 和数据多少无关, 花费的操作和显示时间都是常量.
这个折中的方法, 让我感到很欣慰.

备注:
数据的容器使用std::vector, 而不能是std::deque, 防止数据释放时, 时间太长. 20W条数据时, std::deque释放的不是一般的慢, 和构造数据的速度比较, 慢了100倍.
使用std::vector时, 构造数据和释放数据的时间是基本相同的. 在20W条数据的条件下做过实验了.

运行效果图:



工程下载点 : 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<sstream>
#include <iomanip>
#include <iostream>
#include <map>
#include <deque>

#include "XmlWnd.h"

/// 扩展DuiLib控件
#include "controls_ex.h"

extern HWND     g_hHwndMain;
extern TAG_HOOK_DATA g_KbHookData;
extern TAG_HOOK_DATA g_MouseHookData;

LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK MouseProc(
    int nCode,      // hook code
    WPARAM wParam,  // message identifier
    LPARAM lParam   // mouse coordinates
    );

enum e_view_index
{
    e_view_index_unknown = 0,
    e_view_index_start_prog,
};

typedef struct _INFO_LIST_ITEM_DATA
{
    _INFO_LIST_ITEM_DATA()
    {
        ::ZeroMemory(cFileType, sizeof(cFileType));
        ::ZeroMemory(cCreationTime, sizeof(cCreationTime));
        ::ZeroMemory(cLastWriteTime, sizeof(cLastWriteTime));
        ::ZeroMemory(cFilePath, sizeof(cFilePath));
        ::ZeroMemory(cFileSize, sizeof(cFileSize));
    }

    char cFileType[MAX_PATH]; ///< type_dir 目录, 其它 文件
    char cCreationTime[MAX_PATH];
    char cLastWriteTime[MAX_PATH];
    char cFilePath[MAX_PATH + 1];
    char cFileSize[MAX_PATH];
}INFO_LIST_ITEM_DATA, *PINFO_LIST_ITEM_DATA;

typedef enum _eDispWParam {
    DISP_REFRESH_CUR_TREE_NODE_FILES_INFO_REMOVE_ALL, ///< 移除List的当前页面内容
    DISP_REFRESH_CUR_TREE_NODE_FILES_INFO, ///< 刷新当前用户选择节点的文件信息
    DISP_MSG, ///< 显示消息
}eDispWParam;

class CMainDlg : 
    public CXmlWnd
{
public:
    CMainDlg(WCHAR * pcXmlFileName, WCHAR * pcWndClassName);
    virtual ~CMainDlg(void);

    /// 安装相关
    DWORD m_dwMainTID;

public:
    void ThreadProcStart();
    BOOL ThreadProcEnd(BOOL bStopNow);
    static UINT WINAPI ThreadProc(void* pParam);
    UINT WINAPI ThreadProc();

    DUI_DECLARE_MESSAGE_MAP()

public:
    virtual void InitWindow();
    virtual LONG GetStyle();
    virtual LONG GetExStyle();
    virtual CControlUI* CreateUiControlByMySelf(LPCTSTR pstrClass);
    virtual LRESULT     WndMessageProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
    LRESULT WndMessageProc_WM_DISP_REFRESH(UINT uMsg, WPARAM wParam, LPARAM lParam);
    
    virtual LRESULT     SysMessageProc(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled);
    virtual void        OnFinalMessage(HWND hWnd);
    virtual void        Notify(TNotifyUI & msg);
    virtual void        OnClick(TNotifyUI& msg);
    virtual LRESULT     OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);

private:
    void UiInit();
    void UiInit_List();
    void clearFindData();
    void PrepareData();
    void ShowMsg(const WCHAR* pcMsg);

    void InsertRow2FileList_RemoveAll();
    void ClearRow2FileList(CListContainerElementUI* pListItem);

    void fn_ShowCurTreeNodeFilesInfo();
    void InsertRow2FileList(std::vector<INFO_LIST_ITEM_DATA*>& deqFindData);
    void InsertRow2FileList(INFO_LIST_ITEM_DATA*& FindData, CListContainerElementUI*& pListItem);

    void MoveMyWindowToDesktopRightBottom();
    void DataInit();
    void DataUnInit();
    void RunObjProg();

    void switch_view(e_view_index PageIndex);

private:
    DuiLib::CTabLayoutUI*   m_pTabView;
    DuiLib::CContainerUI*   m_pPage_StartProg;

    CListUI* m_pListFiles; ///< 显示文件信息集合的List
    CScrollBarUI* m_pVScrollBarForFilesList; ///< List右边的竖向滚动条
    CContainerUI* m_pContainerForVScrollBarForFilesList; ///< List右边竖向滚动条的容器
    DuiLib::CLabelUI* m_pStatusMsg; 

    std::wstring m_strTipMsg; ///< 提示消息
    std::wstring m_strTipMsgPerv; ///< 提示消息(最后一次), 为了提高效率
    ns_shaoyuan::CCriticalSection m_Locker_MainUI;

    int m_iCntFilesListRowMax; ///< List一页最多显示几行
    int m_iDataSoruceRecordCnt; ///< 要操作的数据集合总条目数量, 暂定为20W条数据
    std::vector<INFO_LIST_ITEM_DATA*> m_deqFindData; ///< 要显示的数据, 假设有6W条数据
    ns_shaoyuan::CCriticalSection m_Locker_DispInfo;

    ns_base::CThreadManager     m_ThreadManager;
    BOOL m_bRunObjProgNow;

    BOOL m_bMsgProcessOver_RefreshFilesInfo_RemoveAll;
    BOOL m_bMsgProcessOver_RefreshFilesInfo;
};

#endif // #ifndef __MAIN_DLG_H__


/// @file	MainDlg.cpp

#include "stdafx.h"
#include "resource.h"
#include "resource.h"
#include <comutil.h>
#include <commdlg.h>
#include <mshtml.h>
#include <wininet.h>
#include <sys/stat.h>

#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<INFO_LIST_ITEM_DATA*>::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<INFO_LIST_ITEM_DATA*>& deqFindData)
{
    std::deque<INFO_LIST_ITEM_DATA*>::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);
}


xml文件:

<!-- dlgNotify_MainDlg.xml -->
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<Window size="595,412">
    <Font name="微软雅黑" size="11" bold="false" italic="false" />
    <Font name="微软雅黑" size="12" bold="false" italic="false" />
    <Font name="微软雅黑" size="13" bold="false" italic="false" />
    <Font name="微软雅黑" size="14" bold="false" italic="false" />
    <Font name="微软雅黑" size="15" bold="false" italic="false" />
    <Font name="微软雅黑" size="16" bold="false" italic="false" />
    <Font name="微软雅黑" size="14" bold="true" italic="false" />
    <Default name="VScrollBar" value="button1normalimage="file='scrollbar.bmp' source='0,90,16,106' mask='#FFFF00FF'" button1hotimage="file='scrollbar.bmp' source='18,90,34,106' mask='#FFFF00FF'" button1pushedimage="file='scrollbar.bmp' source='36,90,52,106' mask='#FFFF00FF'" button1disabledimage="file='scrollbar.bmp' source='54,90,70,106' mask='#FFFF00FF'" button2normalimage="file='scrollbar.bmp' source='0,108,16,124' mask='#FFFF00FF'" button2hotimage="file='scrollbar.bmp' source='18,108,34,124' mask='#FFFF00FF'" button2pushedimage="file='scrollbar.bmp' source='36,108,52,124' mask='#FFFF00FF'" button2disabledimage="file='scrollbar.bmp' source='54,108,70,124' mask='#FFFF00FF'" thumbnormalimage="file='scrollbar.bmp' source='0,126,16,142' corner='2,2,2,2' mask='#FFFF00FF'" thumbhotimage="file='scrollbar.bmp' source='18,126,34,142' corner='2,2,2,2' mask='#FFFF00FF'" thumbpushedimage="file='scrollbar.bmp' source='36,126,52,142' corner='2,2,2,2' mask='#FFFF00FF'" thumbdisabledimage="file='scrollbar.bmp' source='54,126,70,142' corner='2,2,2,2' mask='#FFFF00FF'" railnormalimage="file='scrollbar.bmp' source='0,144,16,160' corner='2,2,2,2' mask='#FFFF00FF'" railhotimage="file='scrollbar.bmp' source='18,144,34,160' corner='2,2,2,2' mask='#FFFF00FF'" railpushedimage="file='scrollbar.bmp' source='36,144,52,160' corner='2,2,2,2' mask='#FFFF00FF'" raildisabledimage="file='scrollbar.bmp' source='54,144,70,160' corner='2,2,2,2' mask='#FFFF00FF'" bknormalimage="file='scrollbar.bmp' source='0,162,16,178' corner='2,2,2,2' mask='#FFFF00FF'" bkhotimage="file='scrollbar.bmp' source='18,162,34,178' corner='2,2,2,2' mask='#FFFF00FF'" bkpushedimage="file='scrollbar.bmp' source='36,162,52,178' corner='2,2,2,2' mask='#FFFF00FF'" bkdisabledimage="file='scrollbar.bmp' source='54,162,70,178' corner='2,2,2,2' mask='#FFFF00FF'" " />
    <Default name="HScrollBar" value="button1normalimage="file='scrollbar.bmp' source='0,0,16,16' mask='#FFFF00FF'" button1hotimage="file='scrollbar.bmp' source='18,0,34,16' mask='#FFFF00FF'" button1pushedimage="file='scrollbar.bmp' source='36,0,52,16' mask='#FFFF00FF'" button1disabledimage="file='scrollbar.bmp' source='54,0,70,16' mask='#FFFF00FF'" button2normalimage="file='scrollbar.bmp' source='0,18,16,34' mask='#FFFF00FF'" button2hotimage="file='scrollbar.bmp' source='18,18,34,34' mask='#FFFF00FF'" button2pushedimage="file='scrollbar.bmp' source='36,18,52,34' mask='#FFFF00FF'" button2disabledimage="file='scrollbar.bmp' source='54,18,70,34' mask='#FFFF00FF'" thumbnormalimage="file='scrollbar.bmp' source='0,36,16,52' corner='2,2,2,2' mask='#FFFF00FF'" thumbhotimage="file='scrollbar.bmp' source='18,36,34,52' corner='2,2,2,2' mask='#FFFF00FF'" thumbpushedimage="file='scrollbar.bmp' source='36,36,52,52' corner='2,2,2,2' mask='#FFFF00FF'" thumbdisabledimage="file='scrollbar.bmp' source='54,36,70,52' corner='2,2,2,2' mask='#FFFF00FF'" railnormalimage="file='scrollbar.bmp' source='0,54,16,70' corner='2,2,2,2' mask='#FFFF00FF'" railhotimage="file='scrollbar.bmp' source='18,54,34,70' corner='2,2,2,2' mask='#FFFF00FF'" railpushedimage="file='scrollbar.bmp' source='36,54,52,70' corner='2,2,2,2' mask='#FFFF00FF'" raildisabledimage="file='scrollbar.bmp' source='54,54,70,70' corner='2,2,2,2' mask='#FFFF00FF'" bknormalimage="file='scrollbar.bmp' source='0,72,16,88' corner='2,2,2,2' mask='#FFFF00FF'" bkhotimage="file='scrollbar.bmp' source='18,72,34,88' corner='2,2,2,2' mask='#FFFF00FF'" bkpushedimage="file='scrollbar.bmp' source='36,72,52,88' corner='2,2,2,2' mask='#FFFF00FF'" bkdisabledimage="file='scrollbar.bmp' source='54,72,70,88' corner='2,2,2,2' mask='#FFFF00FF'" " />
    <Container float="true" pos="0,0,0,0" width="595" height="412">
        <TabLayout name="TabLayout_setup_now" width="581" height="380">
            <Container name="Container_page_install_over" bkimage="bg_setup_now.png">
                <VerticalLayout>
                    <Container width="595" height="40">
                        <Button name="btn_close_ui5" float="true" pos="554,0,0,0" width="40" height="39" textcolor="#FF000000" disabledtextcolor="#FFA7A6AA" align="center" normalimage="btn_close_n.png" hotimage="btn_close_h.png" pushedimage="btn_close_d.png" />
                    </Container>
                    <Container>
                        <HorizontalLayout>
                            <Container width="10" />
                            <Container>
                                <HorizontalLayout>
                                    <Container name="Container_UI_for_tree_view" >
					                            <List name="list_files" width="660" height="527" bordersize="1" bkcolor="#FFC0C0C0" itemtextcolor="#FF000000" itemselectedtextcolor="#FF000000" itemselectedbkcolor="#FFC1E3FF" itemhottextcolor="#FF000000" itemhotbkcolor="#FFE9F5FF" itemdisabledtextcolor="#FFCCCCCC" itemdisabledbkcolor="#FFFFFFFF" vscrollbar="true" hscrollbar="true">
													            		<ListHeader>
													                    <ListHeaderItem name="HeadItem_file_name" text="名称" width="258" height="31" textcolor="#FF6c6c6c" disabledtextcolor="#FFA7A6AA" align="center" font="1" normalimage="headerctrl_normal.png" hotimage="headerctrl_hot.png" pushedimage="headerctrl_down.png" sepimage="header_Item_boundary.png" sepwidth="1" >
													                    	    <Container>
																								        <HorizontalLayout sepwidth="1" >
																								            <Container />
																								            <Container width="1" bkimage="header_Item_boundary.png" />
																								        </HorizontalLayout>
																									  </Container>
													                    </ListHeaderItem>
													
													                    <ListHeaderItem name="HeadItem_file_size" text="大小" width="73" height="31" textcolor="#FF6c6c6c" disabledtextcolor="#FFA7A6AA" align="center" font="1" normalimage="headerctrl_normal.png" hotimage="headerctrl_hot.png" pushedimage="headerctrl_down.png" sepimage="header_Item_boundary.png" sepwidth="1" >
													                    	    <Container>
																								        <HorizontalLayout sepwidth="1" >
																								            <Container />
																								            <Container width="1" bkimage="header_Item_boundary.png" />
																								        </HorizontalLayout>
																									  </Container>
													                    </ListHeaderItem>
													
													                    <ListHeaderItem name="HeadItem_file_type" text="类型" width="73" height="31" textcolor="#FF6c6c6c" disabledtextcolor="#FFA7A6AA" align="center" font="1" normalimage="headerctrl_normal.png" hotimage="headerctrl_hot.png" pushedimage="headerctrl_down.png" sepimage="header_Item_boundary.png" sepwidth="1" >
													                    	    <Container>
																								        <HorizontalLayout sepwidth="1" >
																								            <Container />
																								            <Container width="1" bkimage="header_Item_boundary.png" />
																								        </HorizontalLayout>
																									  </Container>
													                    </ListHeaderItem>
													
													                    <ListHeaderItem name="HeadItem_file_time" text="时间" width="170" height="31" textcolor="#FF6c6c6c" disabledtextcolor="#FFA7A6AA" align="center" font="1" normalimage="headerctrl_normal.png" hotimage="headerctrl_hot.png" pushedimage="headerctrl_down.png" sepimage="header_Item_boundary.png" sepwidth="1" >
													                    	    <Container>
																								        <HorizontalLayout sepwidth="1" >
																								            <Container />
																								            <Container width="1" bkimage="header_Item_boundary.png" />
																								        </HorizontalLayout>
																									  </Container>
													                    </ListHeaderItem>
													
													                    <ListHeaderItem name="HeadItemhave5" text="" width="660" height="31" textcolor="#FF6c6c6c" disabledtextcolor="#FFA7A6AA" align="center" font="1" normalimage="headerctrl_normal.png" hotimage="headerctrl_hot.png" pushedimage="headerctrl_down.png" />
													            		</ListHeader>
													            </List>
                                    </Container>
                               			<Container name="container_for_v_scrollbar_for_list" width="20"> <!-- 这里不用设置准确的滚动条宽度,程序里会自动设置 -->
   		                         				<ScrollBar name="scrollbar_for_files_list" />
	                            			</Container>
                                </HorizontalLayout>
                            </Container>
                            <Container width="10" />
                        </HorizontalLayout>
                    </Container>
                    <Container height="80">
                        <Button name="btn_run_now" float="true" pos="390,11,0,0" width="197" height="59" textcolor="#FF000000" disabledtextcolor="#FFA7A6AA" align="center" normalimage="btn_run_now_n.png" hotimage="btn_run_now_h.png" pushedimage="btn_run_now_d.png" />
                        <Label name="Label_UI_MSG" float="true" pos="6,11,0,0" width="374" height="59" textcolor="#FF000000" disabledtextcolor="#FFA7A6AA" />
                    </Container>
                </VerticalLayout>
            </Container>
        </TabLayout>
    </Container>
</Window>


<!-- ListItem_Files.xml -->
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<Window size="666,61" >
    <Font name="微软雅黑" size="10" bold="false" italic="false" />
    <Font name="微软雅黑" size="11" bold="false" italic="false" />
    <Font name="微软雅黑" size="12" bold="false" italic="false" />
    <Font name="微软雅黑" size="13" bold="false" italic="false" />
    <Font name="微软雅黑" size="14" bold="false" italic="false" />
    <Font name="微软雅黑" size="15" bold="false" italic="false" />
    <Font name="微软雅黑" size="16" bold="false" italic="false" />
    <Font name="微软雅黑" size="17" bold="false" italic="false" />
    <Font name="微软雅黑" size="18" bold="false" italic="false" />
    <Font name="微软雅黑" size="19" bold="false" italic="false" />
    <ListContainerElement name="Container_file_list_item" width="660" height="61">
        <Container name="Container_1" width="258">
			<HorizontalLayout>
				<Container>
					<Button name="btn_row_file_icon" float="true" pos="11,6,0,0" width="48" height="48" textcolor="#FF000000" disabledtextcolor="#FFA7A6AA" align="center" normalimage="" hotimage="" pushedimage="" />
					<Label name="label_row_file_name" float="true" endellipsis="false" text="名称" textpadding="0,0,0,18" pos="66,0,0,0" width="600" height="61" textcolor="#FF2C2C2C" disabledtextcolor="#FFA7A6AA" font="1" align="wrap" />
				</Container>
			</HorizontalLayout>
        </Container>
        <Container name="Container_2" width="73">
 			<HorizontalLayout>
				<Container>
					<Label name="label_row_size" endellipsis="false" text="大小" float="true" pos="0,0,0,0" width="73" height="61" textcolor="#FF656565" disabledtextcolor="#FFA7A6AA" font="1" align="center" />
				</Container>
			</HorizontalLayout>
        </Container>
        <Container name="Container_3" width="73">
			<HorizontalLayout>
				<Container>
					<Label name="label_row_type" endellipsis="false" text="类型" float="true" pos="0,0,0,0" width="73" height="61" textcolor="#FF656565" disabledtextcolor="#FFA7A6AA" font="1" align="center" />
				</Container>
			</HorizontalLayout>
        </Container>
        <Container name="Container_4" width="170" >
			<HorizontalLayout>
				<Container>
					<Label name="label_row_time" endellipsis="false" text="时间" float="true" pos="0,0,0,0" width="170" height="61" textcolor="#FF656565" disabledtextcolor="#FFA7A6AA" font="1" align="center" />
				</Container>
			</HorizontalLayout>
        </Container>
    </ListContainerElement>
</Window>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: