gpt4 book ai didi

delphi - 在列表框 Canvas 上绘制 unicode 文本太慢

转载 作者:行者123 更新时间:2023-12-03 15:14:30 25 4
gpt4 key购买 nike

我正在尝试使用以下格式在列表框中显示来自 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

问题

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

注意

  • 字体已设置为@Microsoft NeoGothic
  • 项目高度=70;style=ownerdrawfixed
  • 在中绘制相同的unicode文本没有问题firemonkey 应用程序发布在第一个屏幕截图中。
  • 上面发布的代码对于正常的英文文本来说效果很好,完全没有闪烁。仅 Unicode 文本存在此问题。

更新:问题似乎出在 DrawText 方法的 DT_WORDBREAK 标志中。每当我删除此标志时,尽管闪烁是可见的,但绘制文本的效果却有显着改善。

Unicoide 文本示例

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

最佳答案

如果您真的真的想使用标准列表框来显示 RSS 提要,我建议您使用双缓冲。这意味着您可以在内存中的位图上绘制内容,然后将其绘制到 ListView 中。我从您的源代码中制作了一个小演示,向您展示如何操作。我并没有解决所有问题,但我相信这是使用标准 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.

关于delphi - 在列表框 Canvas 上绘制 unicode 文本太慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33149592/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com