You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何禁用TLabel自动绘制?解决跨显示器切换显示异常问题

问题与解决方案

问题详情

我有一个包含TTreeView和TPanel的TForm,Panel上关联了一个TLabel作为标题。TreeView中存在文本过长的节点,自动生成了滚动条。我通过TextOutA在TreeView位置变化时绘制Label标题,功能正常,但切换到第二显示器时,Label会自动重绘导致显示异常。已尝试在Form的OnPaint事件中调用HeadlineDrawing()但无效,也确认了绘制位置正确,寻求解决办法。

现有代码

void __fastcall TShortView2Form::HeadlineDrawing(void)
{
    TRect LabelRect;

    LabelRect = TitelLabel->ClientRect;
    TitelLabel->Canvas->Brush->Color = Panel1->Color;
    LabelRect.Left = DefaultLeftPosition - 20;
    TitelLabel->Canvas->FillRect(LabelRect);  // Fill the Pannel, with his Background Color, therefore it is blank

    LabelRect.Left = DefaultLeftPosition - 20; // -20, for the Correct Position of the Drawing
    TitelLabel->Canvas->Font->Color = clBlack;
    TitelLabel->Canvas->Font->Style += TitelLabel->Canvas->Font->Style << fsBold;
    TitelLabel->Canvas->TextOutA(LabelRect.Left, LabelRect.Top, TitelLabel->Caption);

    TitelLabel->Canvas->Font->Style -= TitelLabel->Canvas->Font->Style << fsBold;
}

void __fastcall TShortView2Form::TreeView1AdvancedCustomDrawItem(TCustomTreeView *Sender,
    TTreeNode *Node, TCustomDrawState State, TCustomDrawStage Stage,
    bool &PaintImages, bool &DefaultDraw)
{
    bool bHeadlineDraw = true;
    if (Node->Level == 0)
    {
        TRect Rect;
        Rect = Node->DisplayRect(true);

        if (DefaultLeftPosition != Rect.Left)
        {
            DefaultLeftPosition = Rect.Left;

            if (Stage == cdPostPaint)
            {
                HeadlineDrawing();
                bHeadlineDraw = false;
            }
        }
    }

    Sender->Canvas->Brush->Color = clWhite;
    Sender->Canvas->Font->Color = clBlack;

    bool bIsSelected = State.Contains(cdsFocused);
    if (bIsSelected && bHeadlineDraw && Stage == cdPostPaint)
    {
        HeadlineDrawing();
        bHeadlineDraw = false;
    }
}

效果对比

  • 正常显示:标题文本与TreeView节点对齐,显示正常
  • 切换显示器后异常:标题文本位置偏移或被默认Label内容覆盖

解决办法

问题根源

切换显示器时,Label会触发默认重绘逻辑,覆盖你通过TreeView事件执行的自定义绘制;Form的OnPaint事件无法阻止Label自身的重绘,导致自定义内容丢失。

具体修正步骤

  1. 接管Label的OnPaint事件
    将自定义绘制逻辑移到Label自己的Paint事件中,确保每次Label需要重绘时都执行你的绘制代码,避免被默认重绘覆盖。

  2. 修正字体样式操作
    原代码中字体样式的叠加逻辑错误,会导致样式重复累加,需先保存原有样式再修改,绘制完成后恢复。

  3. 处理显示器切换时的位置更新
    监听Form的OnDisplayChanged事件,在显示器切换时重新获取TreeView根节点的位置,更新DefaultLeftPosition并触发Label重绘。

修改后的代码示例

// 修正后的HeadlineDrawing函数
void __fastcall TShortView2Form::HeadlineDrawing(void)
{
    TRect LabelRect = TitelLabel->ClientRect;
    // 保存Label原有字体样式
    TFontStyles originalStyle = TitelLabel->Canvas->Font->Style;

    // 用Panel背景色填充Label区域,清除默认内容
    TitelLabel->Canvas->Brush->Color = Panel1->Color;
    TitelLabel->Canvas->FillRect(LabelRect);

    // 计算正确的绘制位置
    int drawLeft = DefaultLeftPosition - 20;
    // 设置绘制字体属性
    TitelLabel->Canvas->Font->Color = clBlack;
    TitelLabel->Canvas->Font->Style = originalStyle << fsBold;

    // 绘制标题文本
    TitelLabel->Canvas->TextOutA(drawLeft, LabelRect.Top, TitelLabel->Caption);

    // 恢复原有字体样式
    TitelLabel->Canvas->Font->Style = originalStyle;
}

// 给TitelLabel添加OnPaint事件处理
void __fastcall TShortView2Form::TitelLabelPaint(TObject *Sender)
{
    HeadlineDrawing();
}

// Form的OnDisplayChanged事件(处理显示器切换)
void __fastcall TShortView2Form::FormDisplayChanged(TObject *Sender)
{
    // 重新获取根节点位置,更新DefaultLeftPosition
    if (TreeView1->Items->Count > 0)
    {
        TTreeNode* rootNode = TreeView1->Items->Item[0];
        if (rootNode)
        {
            TRect nodeRect = rootNode->DisplayRect(true);
            DefaultLeftPosition = nodeRect.Left;
        }
    }
    // 强制Label重绘
    TitelLabel->Invalidate();
}

额外注意事项

  • 确保DefaultLeftPosition初始值正确,可在Form的OnCreate事件中提前获取根节点位置初始化。
  • 若TreeView节点动态变化,需在节点添加/删除后更新DefaultLeftPosition并触发Label重绘。

内容的提问来源于stack exchange,提问作者killa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 16:52:11