DuiLib::CTreeViewUI 的基本用法
来源:互联网 发布:数据库培训哪家好 编辑:程序博客网 时间:2024/05/01 00:09
前几天工程中使用了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 1881C++ dlgNotify.exe!DuiLib::CListBodyUI::SetPos(tagRECT rc) Line 1189 + 0x3d bytesC++ dlgNotify.exe!DuiLib::CVerticalLayoutUI::SetPos(tagRECT rc) Line 122 + 0x3d bytesC++ dlgNotify.exe!DuiLib::CListUI::SetPos(tagRECT rc) Line 303C++ dlgNotify.exe!DuiLib::CContainerUI::SetPos(tagRECT rc) Line 602 + 0x2b bytesC++ dlgNotify.exe!DuiLib::CVerticalLayoutUI::SetPos(tagRECT rc) Line 122 + 0x3d bytesC++ dlgNotify.exe!DuiLib::CContainerUI::SetPos(tagRECT rc) Line 602 + 0x2b bytesC++ dlgNotify.exe!DuiLib::CHorizontalLayoutUI::SetPos(tagRECT rc) Line 118 + 0x3d bytesC++ dlgNotify.exe!DuiLib::CContainerUI::SetPos(tagRECT rc) Line 602 + 0x2b bytesC++ dlgNotify.exe!DuiLib::CVerticalLayoutUI::SetPos(tagRECT rc) Line 122 + 0x3d bytesC++ dlgNotify.exe!DuiLib::CContainerUI::SetPos(tagRECT rc) Line 602 + 0x2b bytesC++ dlgNotify.exe!DuiLib::CTabLayoutUI::SetPos(tagRECT rc) Line 181 + 0x2b bytesC++ dlgNotify.exe!DuiLib::CContainerUI::SetPos(tagRECT rc) Line 602 + 0x2b bytesC++ dlgNotify.exe!DuiLib::CPaintManagerUI::SysMessageProc_Process_WM_PAINT_AlphaBackground_no(unsigned int uMsg, unsigned int wParam, long lParam, long & lRes) Line 803 + 0x31 bytesC++>dlgNotify.exe!DuiLib::CPaintManagerUI::SysMessageProc_Process_WM_PAINT(unsigned int uMsg, unsigned int wParam, long lParam, long & lRes) Line 906C++ dlgNotify.exe!DuiLib::CPaintManagerUI::SysMessageProc(unsigned int uMsg, unsigned int wParam, long lParam, long & lRes) Line 946 + 0x18 bytesC++ dlgNotify.exe!DuiLib::WindowImplBase::WndMessageProc(unsigned int uMsg, unsigned int wParam, long lParam) Line 434 + 0x1b bytesC++ dlgNotify.exe!CXmlWnd::WndMessageProc(unsigned int uMsg, unsigned int wParam, long lParam) Line 185C++ dlgNotify.exe!CMainDlg::WndMessageProc(unsigned int uMsg, unsigned int wParam, long lParam) Line 443 + 0x14 bytesC++ dlgNotify.exe!DuiLib::CWindowWnd::__WndProc(HWND__ * hWnd, unsigned int uMsg, unsigned int wParam, long lParam) Line 461 + 0x1b bytesC++
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中的代码.
效果图:
工程预览:
/// @fileMainDlg.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__
/// @fileMainDlg.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 0
- DuiLib::CTreeViewUI 的基本用法
- duilib 修复CTreeViewUI复选功能判断不准确的bug
- 关于duilib的CTreeViewUI扩展以支持节点拖放的手记
- duilib 修复CTreeViewUI控件动态添加子控件时,对是否显示判断不足的bug
- duilib使用CTreeViewUI添加CTreeNodeUI注意
- DuiLib(7)——CTreeViewUI使用攻略
- duilib基本框架
- duilib基本流程
- rpm的基本用法
- sfc的基本用法
- vi 的基本用法
- JProgressBar 的基本用法
- NPlot的基本用法
- JAR的基本用法
- tar的基本用法
- MessageBox的基本用法
- LIKE的基本用法
- sfc的基本用法
- 事务隔离级别
- leetcode: Add Digits
- POJ 3737 UmBasketella(三分模板)
- POJ Flip Game(BFS + 位运算)
- QT程序自适应屏幕大小
- DuiLib::CTreeViewUI 的基本用法
- bbs项目bug
- Android PopupWindow的简单使用
- hdoj 1028
- 二叉树差值最大(阿里2015)
- 自定义控件(支持模板)
- nucleo stmcubemx 按键中断测试
- 长短信与短信签名
- UITableView整理