【问题标题】:WTL update status bar from child viewWTL 从子视图更新状态栏
【发布时间】:2014-05-10 12:44:43
【问题描述】:

在我的 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 视图中
  • 通过向mainfrm循环发送消息来更新状态栏

我的问题是如何在我的代码中实现上述选项之一。

谢谢。

【问题讨论】:

    标签: winapi visual-c++ wtl


    【解决方案1】:

    有很多方法可以实现这一点:

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

      void CMainFrame::SetStatusText(CString strText)
      {
          CStatusBarCtrl sb(m_hWndStatusBar);
          sb.SetText(SB_SIMPLEID, strText);
      }
      
      LRESULT CTabPeople::OnMenuRefresh(...)
      {
          g_pMainFrame->SetStatusText(_T("Status text"));
      }
      
    2. 使用带有“this 指针”的静态成员函数:

      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"));
      }
      
    3. 使用带有自定义消息标识符的 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;
      }
      
    4. 如果您将状态栏句柄作为全局句柄,您也可以简单地发送SB_SETTEXT 消息:

      LRESULT CTabPeople::OnMenuRefresh(...)
      {
          ::SendMessage(g_hWndStatus, SB_SETTEXT, MAKEWPARAM(SB_SIMPLEID, 0), (LPARAM) _T("Status text"));
      }
      

    选项 3 和 4 显然取消了类(不是面向对象的)的意义。选项 2 可能是最适用的。

    我没有对此进行任何测试,但你有这个想法。 :)

    【讨论】:

      【解决方案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);
        //...
      }
      

      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());
      }
      

      其他.cpp

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-02-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-29
        • 2014-06-28
        • 1970-01-01
        相关资源
        最近更新 更多