在列表框画布上绘制 unicode 文本太慢

2023-11-28

我正在尝试使用以下格式在列表框中显示来自 RSS 的新闻,如下图所示。屏幕截图中的应用程序是通过设置列表框样式在 firemonkey 中开发的。我需要在我的 VCL 应用程序中显示相同的内容。

enter image description here

这种布局的要求是:

  • 新闻标题应为粗体文本
  • 简短的描述应该位于底部,并且应该是 如果它不适合单行,则换行(如图所示); 字体样式应该是正常的
  • 每个新闻项目都应该有一个图像

到目前为止我的代码:

procedure TfrmDatePicker.ListBox1DrawItem(Control: TWinControl; Index: Integer;
Rect: TRect; State: TOwnerDrawState);
var
  R: TRect;
begin
  ListBox1.Canvas.Font.Color := clBlack;
  ListBox1.Canvas.Font.Style := [fsBold];

  ListBox1.Canvas.Font.Size := 9;

  if Odd(Index) then ListBox1.Canvas.Brush.Color := clWhite
  else ListBox1.Canvas.Brush.Color := clBtnFace;

  ListBox1.Canvas.FillRect (Rect);
  ListBox1.Canvas.Pen.Color := clHighlight;

  if(odSelected in State) then
  begin
      ListBox1.Canvas.Font.Color := clHighlightText;
      ListBox1.Canvas.Brush.Color := clHighlight;
      ListBox1.Canvas.Rectangle(Rect.Left, Rect.Top, Rect.Right, Rect.Bottom);
      if(odFocused in State) then DrawFocusRect(ListBox1.Canvas.Handle, Rect);
  end;

  ImageList1.Draw(ListBox1.Canvas, Rect.Left + 2,
          Rect.top + (ListBox1.ItemHeight - ImageList1.Height) div 2, Index, true);


  ListBox1.Canvas.TextOut(Rect.Left + 70, Rect.Top + 4, 'कान्तिपुर समाचारआजकोपत्रिकामाकेहिछैन');

  ListBox1.Canvas.Font.Style := ListBox1.Canvas.Font.Style - [fsBold];

  R := Rect;
  R.Left := R.Left + 70;
  R.Top := R.Top + 32;
  R.Height := 30;

  DrawText(ListBox1.Canvas.Handle, PChar(ss), Length(ss), R, DT_LEFT or DT_WORDBREAK or DT_NOPREFIX);
  ListBox1.Canvas.TextOut(Rect.Right - 80, Rect.top + 4, '5 mins ago');
end;

这是我得到的输出:

When items with unicode text inserted

Problem

Unicode 文本绘制太慢,并且在滚动列表框或调整表单大小时闪烁太多。

Note

  • 字体已设置为@微软NeoGothic
  • 物品高度=70;样式 = 所有者绘制固定
  • 在中绘制相同的unicode文本没有问题 firemonkey 应用程序发布在第一个屏幕截图中。
  • 上面发布的代码对于正常的英文文本来说效果很好, 完全没有闪烁。该问题仅存在于 Unicode 文本中。

Update:看来问题出在DT_WORDBREAK的旗帜DrawText方法。每当我删除此标志时,尽管可以看到闪烁,但绘制文本的效果却有显着改善。

Unicoide 文本示例

तिम्रो त्यो बोलि ले मलाई बोलायो मिठो तिम्रो तयो मु स्कान मा मलाई झुलायो झुलाओ ह्स्द्जिः स ह्स्ध्फद्ज द्श्जड् स हस फग स्द्फ़ ग स्द्फ्ग फस ग्स्द्फ़ ग्दस्फ्ग द्स्फग्द तत म्रो त्यो बोलि ले मलाई बोलायो मिठो तिम्रो त्यो मुस्कान मा मलई स ह्स्ध्फद्ज द्श्जड्स हस फग स्द्फ़ ग स्द्फ्ग फस ग् स्द्फ़ ग्दस्फ्ग द्स्फग्द


如果您真的真的想使用标准列表框来显示 RSS 提要,我建议您使用双缓冲。这意味着您可以在内存中的位图上绘制内容,然后将其绘制到列表视图中。我从您的源代码中制作了一个小型演示,向您展示如何操作。我并没有解决所有问题,但我相信这是使用标准 VCL 组件可以获得的最佳效果。

unit Unit12;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ImgList;

type
  TForm12 = class(TForm)
    ListBox1: TListBox;
    ImageList1: TImageList;
    procedure ListBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState);
    procedure FormCreate(Sender: TObject);
    procedure FormResize(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    MemBitmap: TBitmap;
    OldListBoxWP: TWndMethod;
    procedure NewListBoxWP(var Message: TMessage);
  public
    { Public declarations }
  end;

var
  Form12: TForm12;

implementation

{$R *.dfm}

const
  NewsStr = 'तिम्रो त्यो बोलि ले मलाई बोलायो मिठो तिम्रो त्यो मुस्कान मा मलाई झुलायो झुल' +
    'ाओ ह्स्द्जिः स ह्स्ध्फद्ज द्श्जड्स हस फग स्द्फ़ ग स्द्फ्ग फस ग्स्द्फ़ ग्दस्फ्ग द्स्फग्द तिम्रो त्यो बोलि ले मलाई बोलायो मिठो तिम्रो त्यो मुस्कान मा मलाई स ह्स्ध्फद्ज द्श्जड्स हस फग स्द्फ़ ग स्द्फ्ग फस ग्स्द्फ़ ग्दस्फ्ग द्स्फग्द';

procedure TForm12.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  ListBox1.WindowProc := OldListBoxWP;
  MemBitmap.Free;
end;

procedure TForm12.FormCreate(Sender: TObject);
var
  i: Integer;
begin
  OldListBoxWP := ListBox1.WindowProc;
  ListBox1.WindowProc := NewListBoxWP;
  MemBitmap := TBitmap.Create;
  MemBitmap.SetSize(Width, Height);

  ListBox1.Items.BeginUpdate;
  for i := 0 to 10 do
    ListBox1.Items.Add(NewsStr);
  ListBox1.Items.EndUpdate;
end;

procedure TForm12.FormResize(Sender: TObject);
begin
  MemBitmap.SetSize(Width, Height);
end;

procedure TForm12.ListBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState);
var
  R: TRect;
begin
  MemBitmap.Canvas.Font.Color := clBlack;
  MemBitmap.Canvas.Font.Style := [fsBold];

  MemBitmap.Canvas.Font.Size := 9;

  if Odd(Index) then
    MemBitmap.Canvas.Brush.Color := clWhite
  else
    MemBitmap.Canvas.Brush.Color := clBtnFace;

  MemBitmap.Canvas.FillRect(Rect);
  MemBitmap.Canvas.Pen.Color := clHighlight;

  if (odSelected in State) then
  begin
    MemBitmap.Canvas.Font.Color := clHighlightText;
    MemBitmap.Canvas.Brush.Color := clHighlight;
    MemBitmap.Canvas.Rectangle(Rect.Left, Rect.Top, Rect.Right, Rect.Bottom);
    if (odFocused in State) then
      DrawFocusRect(MemBitmap.Canvas.Handle, Rect);
  end;

  ImageList1.Draw(MemBitmap.Canvas, Rect.Left + 2, Rect.Top + (ListBox1.ItemHeight - ImageList1.Height) div 2, Index, true);
  MemBitmap.Canvas.TextOut(Rect.Left + 70, Rect.Top + 4, 'कान्तिपुर समाचारआजकोपत्रिकामाकेहिछैन');

  MemBitmap.Canvas.Font.Style := MemBitmap.Canvas.Font.Style - [fsBold];

  R := Rect;
  R.Left := R.Left + 70;
  R.Top := R.Top + 32;
  R.Height := 30;

  DrawText(MemBitmap.Canvas.Handle, PChar(NewsStr), Length(NewsStr), R, DT_LEFT or DT_WORDBREAK or DT_NOPREFIX);
  MemBitmap.Canvas.TextOut(Rect.Right - 80, Rect.Top + 4, '5 mins ago');

  BitBlt(ListBox1.Canvas.Handle, Rect.Left - 1, Rect.Top - 1, Rect.Right - Rect.Left + 2, Rect.Bottom - Rect.Top + 2, MemBitmap.Canvas.Handle, Rect.Left - 1, Rect.Top - 1, SRCCOPY);
end;

procedure TForm12.NewListBoxWP(var Message: TMessage);
begin
  if Message.Msg = WM_ERASEBKGND then
    Message.Result := 0
  else
    OldListBoxWP(Message);
end;

end.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在列表框画布上绘制 unicode 文本太慢 的相关文章

  • 如何将 TGifImage 中的帧提取为位图?

    下面的演示尝试在表单的画布上绘制 GIF 这不起作用 图像不会前进 如何让它发挥作用 procedure TForm1 FormCreate Sender TObject begin GIF TGIFImage Create GIF Loa
  • 在 C# 中根据鼠标点击获取活动窗口名称

    我正在尝试使应用程序获取用户单击的窗口的鼠标单击位置和标题 名称 我目前使用的是 LowLevelMouseProc 它提供了良好的结果 但每当我单击 Google chrome 时 它 都会使应用程序崩溃 这是代码 using Syste
  • 如何追踪手柄泄漏?

    在我的一个应用程序中 我观察到句柄数量不断增加 在不使用应用程序的情况下 该数字大约每秒增加一次 因此后台处理代码的某些部分一定存在句柄泄漏 我如何追踪此类泄漏 有什么工具可以帮助解决这个问题吗 跟踪句柄泄漏时要寻找哪些模式 导致手柄泄漏的
  • ListView 多选行为?

    Comtl32 dll v6 0中的ListView进行多项选择 使用Shift键时 如下 x表示选择 00xxxx xxxxxx xxxx00 早期版本的 ListView 的做法如下 00xx00 00xx00 00xx00 有没有办法
  • 以 png 格式剪辑幻灯片 (Delphi 2010)

    I have a filmstrip of images in png format like this 我想知道如何剪辑每个图像并将这些图像放入 TImageList 控件中 并始终保留透明度 EDIT 是的 在设计时 RRUZ 提到的技
  • WINAPI/DWMAPI 不规则形状的模糊窗口

    注意 这不是关于无边框窗口的问题 因此 前几天我在 Windows 7 上浏览 开始 菜单时偶然发现了这个程序 它是一个本机 Windows 程序 称为 数学输入面板 现在 我对窗户的形状很好奇 我知道它并不是完全由 DWM 绘制的 因为边
  • 在TImageViewer中,如何获取用户点击图片的位置?

    在TImageViewer控件中 用户可以缩放或平移图片 我的问题是 当用户点击图片时 如何获取用户在图片上的点击位置 尤其是用户可以对图片进行放大 缩小或平移之后 如何获取对应的图片点击位置呢 As shown below How to
  • 获取保证具有完整(4 位)年份的 LOCALE_SSHORTDATE 的正确方法是什么?

    我想创建一个日期时间选择器控件 它显示日期和时间 作为DTS SHORTDATECENTURYFORMAT and DTS TIMEFORMAT风格 由于日期时间选择器中没有内置这种样式 因此我必须自己做GetLocaleInfoEx 我注
  • 如何带参数调用外部程序?

    我想在我的代码中调用一个 Windows 程序 并使用代码本身确定的参数 我不想调用外部函数或方法 而是调用 WinXP 环境中的实际 exe 或批处理 脚本文件 C 或 C 将是首选语言 但如果使用任何其他语言更容易完成此操作 请告诉我
  • 具有自定义镶边的 WPF 窗口在右侧和底部有不需要的轮廓

    我使用 Microsoft Windows Shell dll 创建了带有自定义镶边的 WPF 窗口 这是代码
  • 如何为 C++ Visual Studio 2019 指定应用程序图标?

    我见过本文档 https learn microsoft com en us visualstudio ide how to specify an application icon visual basic csharp view vs 2
  • 在Delphi 7中,为什么我可以给const赋值?

    我将一些 Delphi 代码从一个项目复制到另一个项目 发现它在新项目中无法编译 但在旧项目中可以编译 代码看起来像这样 procedure TForm1 CalculateGP const Price money 0 begin Pric
  • 如何保证对象只有一个线程

    我有以下代码 class Service public void start creates thread which creates window and goes to message loop void stop sends WM C
  • 使用 BitBlt 捕获程序窗口始终返回相同的图像

    我编写了以下代码 C Win32 来捕获游戏窗口屏幕并从图像中获取像素颜色数组 函数 autoB 完成这项工作 然后我将结果数组绘制到窗口中以直观地检查我得到的结果 问题是 这个程序在我启动计算机后只工作一次 在第一次 缓存 从游戏中获取的
  • 调整大小时在窗口中绘图留下未绘制的边框

    我遇到的问题看似微不足道 但我找不到解决的方法 这里是 我有一个窗口 里面有一些图形 为了简单起见 我们假设它是一个实心绿色矩形 填充了窗口的整个客户区域 我希望每次窗口改变大小时都重新绘制这个矩形并填充整个窗口 我最初做的就是这样的 我已
  • 如何查明 .exe 是否正在 C++ 中运行?

    给定进程名称 例如 程序 exe C 标准库没有这样的支持 您需要一个操作系统 API 来执行此操作 如果这是 Windows 那么您将使用 CreateToolhelp32Snapshot 然后使用 Process32First 和 Pr
  • 对象的引用计数

    在我的代码中 我使用一个小的数据存储类 它是在不同的地方创建的 为了避免内存泄漏并简化事情 我想使用引用计数 所以我这样做了 type TFileInfo class TInterfacedObject IInterface 并删除了我对
  • 是否可以通过 C#.NET 编写 Win32 .dll 文件?

    是否可以通过 C NET 编写 Win32 dll 文件 如果是的话 我在哪里可以找到一些教程 如果不是 那么您对编写 Win32 DLL 有什么建议 Thanks 对的 这是可能的 事实上有一个工具可以做到这一点 它在 Rainmeter
  • 如何使 StringGrid 的列适合网格的宽度?

    我已经寻找解决方案很长时间了 但没有任何运气 有谁知道一个简单的方法来做到这一点 例如 我想拉伸网格的第二列以适应网格的宽度 Use the ColWidths财产 像这样 with StringGrid1 do ColWidths 1 C
  • 防止多个实例 - 但还要处理命令行参数?

    我正在从我的应用程序处理与 Windows 相关的扩展文件 因此 当您在 Windows 中双击文件时 它将执行我的程序 然后我从那里处理该文件 如下所示 procedure TMainForm FormCreate Sender TObj

随机推荐

  • Android - 加速下降(粉碎)

    视频为不懂的人讲解 此答案未正确回答 请尝试使用其他解决方案来回答 100 赏金已过时 同样的问题 但更好的解释 这个问题被认为是正确的 但根本不是 我用我的旧设备 ZTE 尝试过 大部分时间都有效 但现在我有一台三星 Galazy A5
  • 异步/等待类构造函数

    目前 我正在尝试使用async await在类构造函数中 这样我就可以定制e mail我正在开发的 Electron 项目的标签 customElements define e mail class extends HTMLElement
  • 应用程序中的最大活动量?安卓

    Android 应用程序中有类似最大活动的东西吗 我想知道 因为我正在考虑创建具有铃声功能的声音应用程序 它将有大约 40 项活动 但只有 1 个会持续运行 是不是太多了 我应该寻找其他方法吗 解释为什么我需要 40 项活动 我有 30 个
  • Python 中的不变性 [重复]

    这个问题在这里已经有答案了 我试图了解 python 中的不变性是如何工作的 由于字符串在 python 中是不可变的 所以我希望每次执行字符串操作时 id 都会改变 但它没有按预期工作 例子 对 t 的最后一次操作不会更改其 id 有什么
  • 使用 Crypto++ 的 AES 示例 [关闭]

    Closed 这个问题不符合堆栈溢出指南 目前不接受答案 我一直在互联网上搜索goodc AES 代码示例 教程 教授加密技术的基础知识和库的使用 但到目前为止我还没有运气获得像样的材料 好 易于理解 只是移动学习的基础知识 官方文件加密
  • 运行 Heroku 控制台无法启动

    我正在尝试运行 Heroku 控制台 但在控制台中 我收到消息 运行连接到终端的控制台 但控制台没有启动 在 Heroku 日志中 我收到错误 Error no child processes attached 有什么帮助吗 我刚刚与 He
  • jsp:setproperty property="*" 是什么意思?

  • 在xaml中将html字符串内容绑定到Webview

    我的 xaml 中有一个 webview 如下所示
  • Safe Max Java 卡 APDU 数据命令和响应大小

    Java Card APDU 中建议的数据字段大小是多少 来自陈志群的Java Card Technology for Smart Cards Architecture and Programmer s Guide书中提到 Le 字段最多允
  • 关于从使用块返回的最佳实践[重复]

    这个问题在这里已经有答案了 哪种方法更好 从 an 内部的方法返回一个值using声明或声明一个变量之前 将其设置在里面并在之后返回它 public int Foo using return bar or public int Foo va
  • System.DllNotFoundException:无法在 Windows 2003 上加载 DLL

    我在我的c 项目中使用了c dll 它在我的window xp机器上运行良好 但是当我在window 2003服务器 x64 上复制我的调试项目时 我收到了下面的错误 任何人都可以告诉我这是什么问题吗 我该如何解决它 Thanks Syst
  • 在谷歌驱动器android的文件夹内创建一个文件夹

    我想将 Google Drive 与我的应用程序集成 我已在 Google Developers Console 中注册了我的应用程序 我得到了一个样本https github com googledrive android demos通过
  • 无法让 SQL Server Compact 3.5 / 4 与 ASP .NET MVC 2 一起使用

    我使用的是 Visual Studio 2008 专业版 我可能在这里遗漏了一些非常明显的东西 但我一直在尝试让 Sql Server Compact 4 的 CTP 在我的 asp net mvc 应用程序中工作 我几乎找不到有关如何设置
  • 在 Logstash 中转换时间戳时区作为输出索引名称

    在我的场景中 Logstash 接收的系统日志行的 时间戳 采用 UTC 格式 我们在 Elasticsearch 输出中使用事件 时间戳 output elasticsearch embedded gt false host gt loc
  • 在 ubuntu 上包含非自由 openCV 2.4.10

    我已经使用这个在 ubuntu 上安装了 OpenCVlink我正在尝试使用 SURF 描述符 我知道他们将这些类型的描述符的位置更改为非自由模块 因此我们需要包含它 如下所示 include opencv2 nonfree feature
  • 运行“npm start”时无法旁加载 Office 加载项

    我正在尝试使用运行 Outlook 加载项npm start 但这给了我一个错误 Sideloading the Office Add in Error Unable to start debugging Error Unable to s
  • Delphi 2010 - 源文件在编辑器中随机变为只读?

    还有其他人有这个问题吗 还是我的 Delphi 被诅咒了 我将在编辑器的选项卡中打开一堆表单和文件 然后我会不停地打字 然后突然一切都停止了 我的 pas 文件似乎随机地变成了只读 有时我可以右键单击顶部的选项卡并取消选中 只读 并继续 但
  • JavaScript 中的“文件对话框取消”事件

    我有一个文件输入
  • 如何将解析和更改的 DOM 文档保存在 xml 文件中?

    我有 xml 文件 我需要阅读它 进行一些更改并将新的更改版本写入某个新目的地 我设法读取 解析和修补这个文件 使用DocumentBuilderFactory DocumentBuilder Document等等 但我找不到保存该文件的方
  • 在列表框画布上绘制 unicode 文本太慢

    我正在尝试使用以下格式在列表框中显示来自 RSS 的新闻 如下图所示 屏幕截图中的应用程序是通过设置列表框样式在 firemonkey 中开发的 我需要在我的 VCL 应用程序中显示相同的内容 这种布局的要求是 新闻标题应为粗体文本 简短的