前几天工程中使用了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);
}