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

自定义Button控件如何使用原生Images/ImageIndex属性及异常解决

自定义Tdrawbutton控件改用原生Images和ImageIndex属性绘制按钮的问题

初始需求

我自定义了Tdrawbutton控件,原本通过本地BMP文件绘制按钮外观,现希望使用Button原生的Images和ImageIndex属性来绘制按钮。

原有绘制本地BMP的代码

void __fastcall Tdrawbutton::DrawImag(AnsiString path)
{
    ::Graphics::TBitmap *bmp= new ::Graphics::TBitmap;
    ::Graphics::TBitmap *newbmp= new ::Graphics::TBitmap;
    bmp->Transparent = true;//是否透明
    newbmp->Transparent = true;
    bmp->LoadFromFile(path);
    int OriginalWidth = bmp->Width;
    int OriginalHeight = bmp->Height;
    int TargetWidth = OriginalWidth * hor;
    int TargetHeight = OriginalHeight * hor;
    newbmp->SetSize(TargetWidth, TargetHeight);
    newbmp->Canvas->CopyRect(TRect(0, 0, TargetWidth, TargetHeight), bmp->Canvas, TRect(0, 0, OriginalWidth, OriginalHeight));
    Canvas_->Draw(0,0,newbmp);
    delete bmp;
}

绘制消息处理代码

void __fastcall Tdrawbutton::CNDrawItem(TMessage &Msg){
     // 获取 DRAWITEMSTRUCT
     const DRAWITEMSTRUCT* pDrawItem =reinterpret_cast<DRAWITEMSTRUCT*>(Msg.LParam);
     GetScreenDisplayScale();
     // 保存当前状态
     // 目标DC
     SaveDC(pDrawItem->hDC);
     // 绑定 Canvas_ 到目标 DC
     Canvas_->Handle = pDrawItem->hDC;
     try
          {
            // 提取状态标志...
            TOwnerDrawState state;
            // 按钮具有键盘焦点
            if (pDrawItem->itemState & ODS_FOCUS)
            {
              state = state << odFocused;
            }
            // 按钮已按下
            if (pDrawItem->itemState &
                ODS_SELECTED)
            {
              state = state << odSelected;
            }
            // 按钮禁用
            if (pDrawItem->itemState &
                ODS_DISABLED)
            {
              state = state << odDisabled;
            }
            // 绘制按钮外观
            DoDrawButtonFace(state);
            // 绘制按钮文本
            DoDrawButtonText(state);

          }
      catch (...)
      {
        // 清理资源
        Canvas_->Handle = NULL;
        RestoreDC(pDrawItem->hDC, -1);
      }
      // 清理资源
      Canvas_->Handle = NULL;
      RestoreDC(pDrawItem->hDC, -1);

      // 返回处理成功
      Msg.Result = TRUE;
}

//---------------------------------------------------------------------------

void __fastcall Tdrawbutton::DoDrawButtonFace(const TOwnerDrawState& state)
{
  //Brush->Style = bsClear;
  Canvas_->Brush = Brush;

  TRect RClient = ClientRect;

  if(style == 0){
        if (draw_as_default_ || state.Contains(odFocused))
      {
         DrawImag("UI\\down.bmp");
      }

      // 按钮按下状态...
      if (state.Contains(odSelected))
      {
          DrawImag("UI\\down.bmp");
      }

      // 按钮未按下状态...
      else
      {
          DrawImag("UI\\Normal.bmp");
      }
  }
  if(style == 1){
      if (selected)
      {
          DrawImag("UI\\down.bmp");
      }
      else
      {
          DrawImag("UI\\Normal.bmp");
      }

  }
}

请问如何使用原生的Images和ImageIndex属性在自定义按钮上绘制图像?


更新1:使用GetBitmap方法出现显示异常

我尝试用GetBitmap(Index,bmp)方法读取图像,但生成的BMP显示异常,像是读取了ImageIndex对应的预览图像。

测试代码

void __fastcall Tdrawbutton::DrawIcon()
{
    Canvas_->Brush = Brush;
    TRect RClient = ClientRect;
    ::Graphics::TBitmap *bmp= new ::Graphics::TBitmap;
    ::Graphics::TBitmap *newbmp = new::Graphics::TBitmap;
    this->Images->GetBitmap(ImageIndex,bmp);
    bmp->Transparent = true;
    newbmp->Transparent = true;
    int OriginalWidth = bmp->Width;
    int OriginalHeight = bmp->Height;
    int TargetWidth = OriginalWidth * hor;
    int TargetHeight = OriginalHeight * hor;
    newbmp->SetSize(TargetWidth, TargetHeight);
    newbmp->Canvas->CopyRect(TRect(0, 0, TargetWidth, TargetHeight),bmp->Canvas, TRect(0, 0, OriginalWidth, OriginalHeight));
    Canvas_->Draw(48,3,newbmp);
    delete bmp;
    delete newbmp;
}

[显示结果异常的截图]

这是什么原因?


更新2:调整ImageList的DrawingStyle解决部分问题

修改ImageList属性中的DrawingStyle后,设置为dsNormal或dsTransparent时显示正常,但设置为dsFocus和dsSelected时图像仍异常。根据VCL库帮助文档,dsFocus和dsSelected仅影响包含掩码的图像列表,但我的图像列表并未设置掩码,这一现象很奇怪,不过至少解决了部分问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 02:10:55