DuiLib::CTreeViewUI 的基本用法

前几天工程中使用了DuiLib::CTreeViewUI, 由于以前改原生DuiLib时, 没有考虑到DuiLib::CTreeNodeUI时的情况.

出现了DuiLib::CTreeViewUI 不显示的情况, 但是原生的DuiLib是可以的. 

找这个问题用了6天,  还好任务不是很紧, 如果是在试用期, 估计要跑路了^_^

找了6天之后, 改了1句代码. 修改的地方也是自己以前改别的效果时, 改动的.

因为工程中以前没有用到树控件, 当时要发现这个问题, 也有些困难.

void CListContainerElementUI::SetPos(RECT rc)
{
    int i = 0;
    int nCount = 0;
    TListInfoUI* pInfo = NULL;
    CControlUI *pHorizontalLayout = NULL;
    RECT rt;

    do 
    {
        CContainerUI::SetPos(rc);

        /// 以下的处理是为了调整拖动List题头后, 每行字段位置和题头宽度匹配所做的处理
        if (NULL == m_pIListOwner_on_ListContainerElementUI)
            break;

        pInfo = m_pIListOwner_on_ListContainerElementUI->GetListInfo();

        /// 这里是对 CTreeNodeUI做的处理, 防止CTreeView的节点文字显示不出来
        /// 对于 CTreeNodeUI, (pInfo->nColumns == 0)为实际值
        if (pInfo->nColumns <= 0)
            break;

        nCount = m_items.GetSize();
        for (i = 0; i < nCount; i++)
        {
            pHorizontalLayout = static_cast<CControlUI*>(m_items[i]);
            if (NULL == pHorizontalLayout)
                continue;

            rt = pHorizontalLayout->GetPos();
            rt.left = pInfo->rcColumn[i].left;
            rt.right = pInfo->rcColumn[i].right;

            /// 对于 CTreeNodeUI, 不能执行这里
            /// 防止 ((0 == rt.left) && (0 == rt.right)), 
            /// 导致CControlUI::DoPaint判断条件过不了,不继续刷新
            /// 文字显示不出来.
            /// RECT {上,下,左,右}
            /// org rc = {0,18,10,240}
            /// 对于CTreeNodeUI, 如果执行到这里,变成 rc = {0,18,0,0}
            /// 导致不是一个值得刷新的区域, 如果不刷新, 文字不显示
            pHorizontalLayout->SetPos(rt);
        }
    } while (0);
}

调用链:

是WM_PAINT引发的DuiLib::CListContainerElementUI::SetPos

 	dlgNotify.exe!DuiLib::CListContainerElementUI::SetPos(tagRECT rc)  Line 1881	C++
 	dlgNotify.exe!DuiLib::CListBodyUI::SetPos(tagRECT rc)  Line 1189 + 0x3d bytes	C++
 	dlgNotify.exe!DuiLib::CVerticalLayoutUI::SetPos(tagRECT rc)  Line 122 + 0x3d bytes	C++
 	dlgNotify.exe!DuiLib::CListUI::SetPos(tagRECT rc)  Line 303	C++
 	dlgNotify.exe!DuiLib::CContainerUI::SetPos(tagRECT rc)  Line 602 + 0x2b bytes	C++
 	dlgNotify.exe!DuiLib::CVerticalLayoutUI::SetPos(tagRECT rc)  Line 122 + 0x3d bytes	C++
 	dlgNotify.exe!DuiLib::CContainerUI::SetPos(tagRECT rc)  Line 602 + 0x2b bytes	C++
 	dlgNotify.exe!DuiLib::CHorizontalLayoutUI::SetPos(tagRECT rc)  Line 118 + 0x3d bytes	C++
 	dlgNotify.exe!DuiLib::CContainerUI::SetPos(tagRECT rc)  Line 602 + 0x2b bytes	C++
 	dlgNotify.exe!DuiLib::CVerticalLayoutUI::SetPos(tagRECT rc)  Line 122 + 0x3d bytes	C++
 	dlgNotify.exe!DuiLib::CContainerUI::SetPos(tagRECT rc)  Line 602 + 0x2b bytes	C++
 	dlgNotify.exe!DuiLib::CTabLayoutUI::SetPos(tagRECT rc)  Line 181 + 0x2b bytes	C++
 	dlgNotify.exe!DuiLib::CContainerUI::SetPos(tagRECT rc)  Line 602 + 0x2b bytes	C++
 	dlgNotify.exe!DuiLib::CPaintManagerUI::SysMessageProc_Process_WM_PAINT_AlphaBackground_no(unsigned int uMsg, unsigned int wParam, long lParam, long & lRes)  Line 803 + 0x31 bytes	C++
>	dlgNotify.exe!DuiLib::CPaintManagerUI::SysMessageProc_Process_WM_PAINT(unsigned int uMsg, unsigned int wParam, long lParam, long & lRes)  Line 906	C++
 	dlgNotify.exe!DuiLib::CPaintManagerUI::SysMessageProc(unsigned int uMsg, unsigned int wParam, long lParam, long & lRes)  Line 946 + 0x18 bytes	C++
 	dlgNotify.exe!DuiLib::WindowImplBase::WndMessageProc(unsigned int uMsg, unsigned int wParam, long lParam)  Line 434 + 0x1b bytes	C++
 	dlgNotify.exe!CXmlWnd::WndMessageProc(unsigned int uMsg, unsigned int wParam, long lParam)  Line 185	C++
 	dlgNotify.exe!CMainDlg::WndMessageProc(unsigned int uMsg, unsigned int wParam, long lParam)  Line 443 + 0x14 bytes	C++
 	dlgNotify.exe!DuiLib::CWindowWnd::__WndProc(HWND__ * hWnd, unsigned int uMsg, unsigned int wParam, long lParam)  Line 461 + 0x1b bytes	C++

BUG排查思路:

  * 写一个小Demo出来, 重现这个问题.  由于这个问题是自己改版的DuiLib库有误, 所以Bug总是重现的.

    写小Demo的目的, 减少无关控件的影响. 减少跟踪代码的复杂度, 提高可操作性.

  * 因为是显示相关的BUG, 跟进WM_PAINT处理.

  * 在经过的控件类中用GetClassNameW 和 GetName 来定位我们需要跟踪的 DuiLib::CTreeViewUI 实例.
  * 在自画过程中追吧, 看看到底在哪除了问题? 是不显示? 还是返回了没有画? 还是将size, RECT等数据结构的数据填错了.


修正后, 写了一个小Demo留念. 

工程下载点 : prj_dlg_show_tree_view.zip

DuiLib::CTreeViewUI的用法参照了新版原生DuiLib中自带的FileTree, 其它调用参照了改版的DuiLib中的代码.

效果图:


工程预览:

/// @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,
};

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

    /// 安装相关
    DWORD m_dwMainTID;

public:
    void ThreadProcStart();
    void ThreadProcEnd();
    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);
    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_TreeView();
    void AddRootNode_TreeView(const WCHAR* pcDispData);
    void InsertRow2DirTree(DuiLib::CTreeNodeUI* pNodeParent, const WCHAR* pcDirNow, const WCHAR* pcDispData, OUT DuiLib::CTreeNodeUI*& pNodeNew);
    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;

    DuiLib::CTreeViewUI* m_pTreeView; ///< 树控件
    DuiLib::CTreeNodeUI* m_pTreeNode; ///< 树控件的根节点

    ns_base::CThreadManager     m_ThreadManager;
    BOOL m_bRunObjProgNow;
};

#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)
{
    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_TreeView()
{
    if (NULL == m_pTreeView)
    {
        m_pTreeView = (CTreeViewUI*)m_PaintManager.FindControl(L"tree_view_for_test");
        _ASSERT(NULL != m_pTreeView);

        m_pTreeView->EnableScrollBar(true, true);
    }

}

void CMainDlg::AddRootNode_TreeView(const WCHAR* pcDispData)
{
    do 
    {
        if ((NULL == m_pTreeView)
            || (NULL != m_pTreeNode))
        {
            break;
        }

        /// 设置第1层文件夹
        m_pTreeNode = new CTreeNodeUI;
        _ASSERT(NULL != m_pTreeNode);

        /// 高度要设置的和文件夹图标一样高
        m_pTreeNode->SetAttribute(L"height", L"17");
        m_pTreeNode->SetAttribute(L"width", L"200");

        /// 设置文件夹图标(17x19), dir.png
        m_pTreeNode->GetFolderButton()->SetAttribute(L"width", L"17");
        m_pTreeNode->GetFolderButton()->SetAttribute(L"height", L"19");
        m_pTreeNode->GetFolderButton()->SetAttribute(L"normalimage", L"dir.png");
        m_pTreeNode->GetFolderButton()->SetAttribute(L"hotimage", L"dir.png");
        m_pTreeNode->GetFolderButton()->SetAttribute(L"pushedimage", L"dir.png");
        m_pTreeNode->GetFolderButton()->SetAttribute(L"selectedimage", L"dir.png");

        m_pTreeNode->SetName(L"root_dir");
        m_pTreeNode->SetUserData(L"/");
        m_pTreeNode->SetItemText((NULL != pcDispData) ? pcDispData : L"root dir");
        m_pTreeNode->SetTag(1000);

        m_pTreeNode->GetItemButton()->SetAttribute(L"align", L"left");

        /// 设置padding, 让文字看起来Y方向居中
        m_pTreeNode->GetItemButton()->SetAttribute(L"padding", L"4,-2,0,0");
        m_pTreeNode->GetItemButton()->SetAttribute(L"font", L"6"); ///< 这里font6 是14ppx

        m_pTreeNode->SetItemTextColor(RGB(0x7f,0x7f,0x7f));

        /// 在文件夹图标和文字内容中间的是CheckBox
        /// 我们不需要
        m_pTreeNode->SetVisibleCheckBtn(false);

        m_pTreeView->Add(m_pTreeNode);
        m_pTreeNode->Select(true);
    } while (0);
}

void CMainDlg::InsertRow2DirTree(
    DuiLib::CTreeNodeUI* pNodeParent, 
    const WCHAR* pcDirNow, 
    const WCHAR* pcDispData, 
    OUT DuiLib::CTreeNodeUI*& pNodeNew)
{
    std::wstring strDirNow = (NULL != pcDirNow) ? pcDirNow : L"";
    std::wstring strPathNameFindData = L"";
    std::wstring strItemText = L"";
    std::wstring::size_type nPos = std::wstring::npos;

    do 
    {
        if (NULL == pNodeParent)
        {
            break;
        }

        strPathNameFindData = (NULL != pcDispData) ? pcDispData : L"invalid data";
        strDirNow = (NULL != pcDirNow) ? pcDirNow : L"invalid dir";

        /// 建立新节点
        pNodeNew = new CTreeNodeUI;
        _ASSERT(NULL != pNodeNew);

        /// 高度要设置的和文件夹图标一样高
        pNodeNew->SetAttribute(L"height", L"18");
        pNodeNew->SetAttribute(L"width", L"200");

        /// 设置文件夹图标(17x19), dir.png
        pNodeNew->GetFolderButton()->SetAttribute(L"width", L"17");
        pNodeNew->GetFolderButton()->SetAttribute(L"height", L"19");
        pNodeNew->GetFolderButton()->SetAttribute(L"normalimage", L"dir.png");
        pNodeNew->GetFolderButton()->SetAttribute(L"hotimage", L"dir.png");
        pNodeNew->GetFolderButton()->SetAttribute(L"pushedimage", L"dir.png");
        pNodeNew->GetFolderButton()->SetAttribute(L"selectedimage", L"dir.png");

        pNodeNew->SetName(strPathNameFindData.c_str());

        strItemText = strPathNameFindData.c_str();
        nPos = strItemText.rfind(L'/');
        if (std::wstring::npos != nPos)
        {
            strItemText = strItemText.substr(nPos + 1, -1);
        }
        pNodeNew->SetItemText(strItemText.c_str());
        pNodeNew->SetUserData(strDirNow.c_str());
        // pNodeNew->SetTag(1000 + 1);

        pNodeNew->GetItemButton()->SetAttribute(L"align", L"left");

        /// 设置padding, 让文字看起来Y方向居中
        pNodeNew->GetItemButton()->SetAttribute(L"padding", L"4,-2,0,0");
        pNodeNew->GetItemButton()->SetAttribute(L"font", L"6"); ///< 这里font6 是14ppx

        pNodeNew->SetItemTextColor(RGB(0x7f, 0x7f, 0x7f));

        /// 在文件夹图标和文字内容中间的是CheckBox
        /// 我们不需要
        pNodeNew->SetVisibleCheckBtn(false);

        pNodeParent->AddAt(pNodeNew, 0);
    } while (0);
}


void CMainDlg::UiInit()
{
    CContainerUI* pContainer = NULL;
    DuiLib::CTreeNodeUI* pNodeNew = NULL;
    DuiLib::CTreeNodeUI* pSubNodeNew = NULL;

    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_TreeView();
        AddRootNode_TreeView(L"根目录");

        /// 在根节点上加2个子节点
        InsertRow2DirTree(m_pTreeNode, L"/tmp", L"临时目录", pNodeNew);
        InsertRow2DirTree(m_pTreeNode, L"/cache", L"缓存目录", pNodeNew);

        /// 在子节点上增加一个子子节点
        InsertRow2DirTree(pNodeNew, L"/cache/log", L"日志目录", pNodeNew);

        switch_view(e_view_index_start_prog);

        /// 将窗体放到桌面右下角
        MoveMyWindowToDesktopRightBottom();
        ThreadProcStart();
    } while (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_pTreeView = NULL;
    m_pTreeNode = 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;
}

/**
LRESULT WindowImplBase::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
LONG styleValue = 0;

styleValue = GetStyle();
::SetWindowLong(*this, GWL_STYLE, styleValue);

styleValue = GetExStyle();
::SetWindowLong(*this, GWL_EXSTYLE, styleValue);

*/

/// 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;
}

LRESULT CMainDlg::WndMessageProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    BOOL    bNeedDefaultProcess = FALSE;
    do 
    {
        switch (uMsg)
        {
        /// 如果窗口的扩展风格 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);
            ThreadProcEnd();
            bNeedDefaultProcess = TRUE;
            break;

        default:
            bNeedDefaultProcess = TRUE;
            break;
        }

        if (bNeedDefaultProcess)
            return __super::WndMessageProc(uMsg, wParam, lParam);
        else
            return S_OK;
    } 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)
{
    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));
    }
}

void CMainDlg::ThreadProcEnd()
{
    m_ThreadManager.StopThread(TRUE, L"m_ThreadManager");
}

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()
{
    do 
    {
        ::Sleep(20);

        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);
    return S_OK;
}

void CMainDlg::RunObjProg()
{
    ns_base::CreateProcessEx(L"C:\\Windows\\System32\\notepad.exe", L"", FALSE, TRUE);
}


 

  


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值