【问题标题】:CStatic does not invalidate every time its text is changedCStatic 不会在每次更改其文本时都失效
【发布时间】:2013-09-06 13:12:55
【问题描述】:

我正在尝试动态更改CStatic 控件的文本。我的成员变量名为mStatic,类型为CStatic。我已将 ID 更改为 IDC_MYSTATIC 而不是 IDC_STATIC。

当我想更改控件的文本时,我正在调用mStatic.SetWindowText("asdfasdf")。我会定期在计时器中执行此操作。

现在我遇到的问题是,在我调用SetWindowText() 后,之前的文本没有被删除。它只是不断堆积,直到我在屏幕上弄得一团糟。

父窗口具有带位图背景的分层属性。我还设置了 color_key 属性,因此位图的某种颜色被视为透明(即它不会被绘制并会让鼠标消息通过)。 mStatic 控件绘制在具有位图背景的不透明部分上。

为什么窗口没有失效?

【问题讨论】:

  • 这听起来像是背景擦除问题。使用标准对话框,这可以很好地工作。给我们更多信息,给我们看更多代码。您的 mStatic 变量驻留在什么样的窗口中?等
  • 对不起,我不知道它所在的窗口会影响静态控件的绘制;问题已更新

标签: c++ text static mfc invalidation


【解决方案1】:

有同样的问题。以下code 修复了它:

mStatic.SetWindowText("New text");
CRect rect;
mStatic.GetWindowRect(&rect);
ScreenToClient(&rect);
InvalidateRect(&rect);
UpdateWindow();

【讨论】:

    【解决方案2】:

    也许您的静态文本控件启用了 SS_SIMPLE 样式。您可以检查资源文件上的样式标志或使用 GetStyle()。

    带有 SS_SIMPLE 样式的静态控件显示文本更快,但也 - 如MSDN describes - "SS_SIMPLE静态控件在显示文本时不清除控件的显示区域。如果显示较短的字符串,则显示原始字符串中比新的较短字符串长的部分。"

    从样式标志中清除 SS_SIMPLE,CStatic 将表现“正常”。

    【讨论】:

    • 更改或删除该样式对我来说根本没有帮助/修复此行为。移除 SS_SIMPLE 的静态控件仍会跳过背景擦除。
    【解决方案3】:

    这个knowledge base support article 描述了从另一个线程调用SetWindowText() 时的相同问题。那是你的计时器在做什么吗?

    如果是这样,解决方案可能只是:

      mStatic.SetWindowText("asdfasdf");
      CRect clientRect;
      mStatic.GetClientRect(clientRect);
      mStatic.InvalidateRect(clientRect);
    

    【讨论】:

    • 为什么不在mStatic.SetWindowText()之后直接调用mStatic.Invalidate()?
    【解决方案4】:

    正如其他人已经提到的,静态控件不一定会在绘制文本之前擦除其背景。

    我发现将静态控件子类化并从那里强制控件无效是一个更好的解决方案。这使人们可以轻松地在所有具有透明背景的静态文本上实现它,而无需进行额外的调用以使其父类中的控件无效。

    从控件本身捕获控件文本更改的一种方法是对WM_SETTEXT 消息做出反应并从那里强制失效:

    int CStaticT::OnSetText(LPCTSTR text)
    {
        LRESULT res = Default();
        Invalidate();
        UpdateWindow();
        return res;
    }
    

    以下是从我的一个类中提取的一个简短示例,说明此类子类控件的外观:

    //////////////////////////////////////////////////////////////////////////
    // Header
    //////////////////////////////////////////////////////////////////////////
    class CStaticT : public CStatic
    {
        DECLARE_DYNAMIC(CStaticT)
    
    public:
        CStaticT();
        virtual ~CStaticT();
    
    protected:
        afx_msg int OnSetText(LPCTSTR text);
        DECLARE_MESSAGE_MAP()
    
    private:
        BOOL m_InitialSet;
    };
    
    //////////////////////////////////////////////////////////////////////////
    // Implementation
    //////////////////////////////////////////////////////////////////////////
    IMPLEMENT_DYNAMIC(CStaticT, CStatic)
    CStaticT::CStaticT()
    {
        m_InitialSet = FALSE;
    }
    
    CStaticT::~CStaticT()
    {
    }
    
    BEGIN_MESSAGE_MAP(CStaticT, CStatic)
        ON_WM_SETTEXT()
    END_MESSAGE_MAP()
    
    int CStaticT::OnSetText(LPCTSTR text)
    {
        LRESULT res = Default();
    
        // I've noticed issues when this forces the invalidation
        // of the static control before the parent's background
        // is painted completely.
        // This is a cheap workaround, skipping the initial setting
        // of the text by the subclassing call.
        // You have to test if this works out for your environment.
        if (!m_InitialSet)
        {
            m_InitialSet = TRUE;
            return res;
        }
    
        // Force of the invalidation
        Invalidate();
        UpdateWindow();
    
        return res;
    }
    

    【讨论】:

      猜你喜欢
      • 2020-02-24
      • 1970-01-01
      • 2015-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-15
      • 2016-04-01
      相关资源
      最近更新 更多