Drawing unicode text on listbox canvas is too slow

前端 未结 1 516
离开以前
离开以前 2021-01-13 01:47

I am trying to display news from a RSS in a listbox using the following format as shown in the image below. The application on the screenshot has been developed in firemonke

1条回答
  •  北荒
    北荒 (楼主)
    2021-01-13 02:35

    If you REALY REALY REALY want to use a standard ListBox for displaying you RSS feed I suggest you use double Buffering. Meaning you draw your stuff on a bitmap in memory and den draw that to you listView. From you Sourcecode i've made a small demo showing you how to do.I doesn't solve all the problems but I belive this is the best you can get with a standard VCL component.

    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.
    

    0 讨论(0)
提交回复
热议问题