在我的SDI应用程序中,我正在使用this文章中的CWTLTabViewCtrl
课程。
我想知道如何从子视图更新主框架的状态栏。
mainfrm.h上的代码:
CreateSimpleStatusBar();
// create tabctrl
CTabViewCtrl m_MainTabCtrl;
m_hWndClient = m_MainTabCtrl.Create(
m_hWnd, rcDefault, NULL,
WS_CHILD | WS_VISIBLE, WS_EX_STATICEDGE );
m_MainTabCtrl.AddPeopleTab(L"People);
CTabViewCtrl
类的代码:
class CTabViewCtrl : public CWTLTabViewCtrl
{
public:
CTabViewCtrl()
{
}
virtual ~CTabViewCtrl()
{
}
void AddPeopleTab(LPCTSTR inTabName)
{
auto tabPeople = CTabPeople;
tabPeople->Create(*this, rcDefault, nullptr, WS_CHILD, WS_EX_STATICEDGE);
AddTab(inTabName, *tabPeople, FALSE, 0, (LPARAM)theProcessesView);
}
public:
DECLARE_WND_SUPERCLASS(NULL, CWTLTabViewCtrl::GetWndClassName())
BOOL PreTranslateMessage(MSG* pMsg)
{
pMsg;
return FALSE;
}
BEGIN_MSG_MAP_EX(CTabViewCtrl)
REFLECT_NOTIFICATIONS()
CHAIN_MSG_MAP(CWTLTabViewCtrl)
END_MSG_MAP()
};
我CTabPeople
课程的代码(从此视图我想更新mainfrm.h
的状态栏):
class CTabPeople : public CWindowImpl<CTabPeople, CListViewCtrl>,
public CCustomDraw<CTabPeople>
{
[snip]
public:
DECLARE_WND_SUPERCLASS(NULL, CListViewCtrl::GetWndClassName())
BOOL PreTranslateMessage(MSG* pMsg)
{
pMsg;
return FALSE;
}
BEGIN_MSG_MAP(CTabPeople)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
MESSAGE_HANDLER(WM_CONTEXTMENU, OnContextMenu)
COMMAND_ID_HANDLER(IDM_PROCESSTAB_REFRESH, OnMenuRefresh)
REFLECTED_NOTIFY_CODE_HANDLER(LVN_COLUMNCLICK, OnColumnClick)
CHAIN_MSG_MAP_ALT(CCustomDraw, 1)
END_MSG_MAP()
LRESULT OnMenuRefresh(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL&bHandled)
{
// Here i would like to update the status bar created at the mainfrm.h
// something like UISetText(0, L"Updating..");
}
[snip]
}
从我所做的研究看来,有两种方法可以更新状态栏:
CTabPeople
视图我的问题是如何在我的代码中实现上述选项之一。
感谢。
答案 0 :(得分:4)
有很多方法可以实现这一目标:
使主框架成为全局框架并添加成员函数(比如SetStatusText
):
void CMainFrame::SetStatusText(CString strText)
{
CStatusBarCtrl sb(m_hWndStatusBar);
sb.SetText(SB_SIMPLEID, strText);
}
LRESULT CTabPeople::OnMenuRefresh(...)
{
g_pMainFrame->SetStatusText(_T("Status text"));
}
使用带有&#39;此指针的静态成员函数&#39;:
class CMainFrame;// Forward declaration
class CMainFrame : public ...
{
public:
CMainFrame() { this_ptr = this; }
static void SetStatusText(CString strText)
{
CStatusBarCtrl sb(this_ptr->m_hWndStatusBar);
sb.SetText(SB_SIMPLEID, strText);
}
static CMainFrame* this_ptr;
};
// Initialization (in .cpp file)
CMainFrame* CMainFrame::this_ptr = NULL;
LRESULT CTabPeople::OnMenuRefresh(...)
{
CMainFrame::SetStatusText(_T("Status text"));
}
将SendMessage API与自定义消息标识符一起使用。将消息发送到父控件(CTabViewCtrl
),然后父控件将消息传递给父控件或主框架,或直接将其发送到主框架。最后一种情况要求您知道有多少嵌套窗口,或者您可以使用主窗口句柄。
LRESULT CTabPeople::OnMenuRefresh(...)
{
// Parent control processes the message
::SendMessage(GetParent(), MY_STATUS_MSG, (WPARAM) _T("Status text"), 0);
// Main frame processes the message
::SendMessage(::GetParent(GetParent()), MY_STATUS_MSG, (WPARAM) _T("Status text"), 0);
::SendMessage(g_hWndMain, MY_STATUS_MSG, (WPARAM) _T("Status text"), 0);
}
在主框架中添加消息处理程序和/或CTabViewCtrl
:
BEGIN_MSG_MAP(CMainFrame)
...
MESSAGE_HANDLER(MY_STATUS_MSG, OnSetStatusMsg)
END_MSG_MAP()
LRESULT CMainFrame::OnSetStatusMsg(UINT, WPARAM wParam, LPARAM, BOOL&)
{
CStatusBarCtrl sb(m_hWndStatusBar);
sb.SetText(SB_SIMPLEID, (LPCTSTR) wParam);
return FALSE;
}
如果您将状态栏句柄设置为全局,则可以发送SB_SETTEXT
消息:
LRESULT CTabPeople::OnMenuRefresh(...)
{
::SendMessage(g_hWndStatus, SB_SETTEXT, MAKEWPARAM(SB_SIMPLEID, 0), (LPARAM) _T("Status text"));
}
选项3和4显然忽略了具有类(不是面向对象)的观点。选项2可能是最适用的。
我还没有测试过这个,但你有这个想法。 :)
答案 1 :(得分:0)
简单地使用我的版本:
为MainFrm.h:
class CMainFrame :
public CFrameWindowImpl<CMainFrame>,
public CUpdateUI<CMainFrame>,
public CMessageFilter, public CIdleHandler
{
public:
DECLARE_FRAME_WND_CLASS(NULL, IDR_MAINFRAME)
CMainFrame() { this_ptr = this; }
static CMainFrame* this_ptr;
void SetStatusText(std::wstring strText);
//...
}
MainFrm.cpp中
CMainFrame* CMainFrame::this_ptr = nullptr;
// m_hWndStatusBar is from atlframe.h
void CMainFrame::SetStatusText(std::wstring strText)
{
::SetWindowText(m_hWndStatusBar, strText.c_str());
}
other.cpp
CMainFrame::this_ptr->SetStatusText(L"program ready");