Winapi 从子视图更新WTL状态栏

Winapi 从子视图更新WTL状态栏,winapi,visual-c++,wtl,Winapi,Visual C++,Wtl,在我的SDI应用程序中,我使用文章中的CWTLTabViewCtrl类 我想知道如何从子视图更新主框架的状态栏 mainfrm.h处的代码: CreateSimpleStatusBar(); // create tabctrl CTabViewCtrl m_MainTabCtrl; m_hWndClient = m_MainTabCtrl.Create( m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE

在我的SDI应用程序中,我使用文章中的
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()
};
我的
ctabopele
类中的代码(从该视图中,我想更新
mainfrm.h
中的状态栏):

class-ctabopele:public-CWindowImpl,
公共场所
{
[剪报]
公众:
声明\u WND\u超类(NULL,CListViewCtrl::GetWndClassName())
BOOL预翻译信息(MSG*pMsg)
{
pMsg;
返回FALSE;
}
开始消息映射(CTabOple)
消息处理程序(WM\U CREATE,OnCreate)
消息处理程序(WM\U上下文菜单、OnContextMenu)
命令\u ID\u处理程序(IDM\u PROCESSTAB\u刷新,OnMenuRefresh)
反射的\u通知\u代码\u处理程序(LVN\u COLUMNCLICK,OnColumnClick)
链信息地图高度(CCustomDraw,1)
END_MSG_MAP()
LRESULT OnMenuRefresh(单词wNotifyCode、单词wID、HWND hWndCtl、BOOL和bHandled)
{
//这里我想更新mainfrm.h中创建的状态栏
//类似于UISetText(0,L“更新…”);
}
[剪报]
}
根据我所做的研究,似乎有两种方法可以更新状态栏:

  • 使用状态栏的句柄直接从
    CTabOple
    视图
  • 通过向mainfrm循环发送消息来更新状态栏
我的问题是如何在代码中实现上述选项之一


谢谢。

实现这一点的方法有很多:

  • 将主框架设为全局框架并添加成员函数(例如
    SetStatusText
    ):

  • 使用带有“this pointer”的静态成员函数:

    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可能是最适用的


    我没有测试过这方面的任何东西,但你有这个想法。:)

    实现这一点的方法有很多:

  • 将主框架设为全局框架并添加成员函数(例如
    SetStatusText
    ):

  • 使用带有“this pointer”的静态成员函数:

    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可能是最适用的


    我没有测试过这方面的任何东西,但你有这个想法。:)

    我的简单工作版本:

    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);
      //...
    }
    
    其他.cpp

    CMainFrame::this_ptr->SetStatusText(L"program ready");
    

    我的简单工作版本:

    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);
      //...
    }
    
    其他.cpp

    CMainFrame::this_ptr->SetStatusText(L"program ready");