pyscripter / MustangpeakEasyListView

Mustangpeak EasyListview is a fast and very customizable TListview replacement. It can also be used with the VirtualShellTools component of the MustangPeak Library.
Other
6 stars 2 forks source link

Access Violation when using custom paint method #17

Closed raelb closed 4 years ago

raelb commented 5 years ago

Hello,

Perhaps you can help me with this problem. I am using the following custom paint routine for elv (View = elsList):

  TCustomViewSmallIconItem = class(TEasyViewSmallIconItem)
  public
    procedure PaintBefore(Item: TEasyItem; Column: TEasyColumn; const Caption:
        string; ACanvas: TCanvas; RectArray: TEasyRectArrayObject; var Handled:
        Boolean); override;
  end;
....

procedure TCustomViewSmallIconItem.PaintBefore(Item: TEasyItem; Column:
    TEasyColumn; const Caption: string; ACanvas: TCanvas; RectArray:
    TEasyRectArrayObject; var Handled: Boolean);
var
  Icon: TIcon;
  PrevColor: TColor;
  R: TRect;
  TagInfo: TTagInfo;
  Text: string;
  TextLength: Integer;
  V_OFFSET: Integer;
  LStyle: TCustomStyleServices;
begin
  inherited;

  R := RectArray.TextRect;

  LStyle := TStyleManager.ActiveStyle;
  if not LStyle.IsSystemStyle then
  begin
    if not (esosSelected in Item.State) then
    begin
      ACanvas.Font.Color := LStyle.GetSystemColor(clWindowText);
      DrawTextW(ACanvas.Handle, PWideChar(Caption), Length(Caption),
        R, DT_CENTER or DT_VCENTER or DT_SINGLELINE or DT_END_ELLIPSIS or
        DT_MODIFYSTRING);
      Handled := True;
    end;
  end;

  if Item.Data = nil then
  begin
    ACanvas.Font.Style := [fsBold];
    ACanvas.Font.Color := $00CC6600;
    DrawTextW(ACanvas.Handle, PWideChar(Caption), Length(Caption), R, DT_CENTER or DT_VCENTER or 
DT_SINGLELINE);
    ACanvas.Font.Style := [];
    Handled := True;
  end
  else
  begin
    TagInfo := TTagInfo(Item.Data);
    Text := '(' + TagInfo.Count.ToString + ')';
    R.Left := R.Right + 6;
    R.Right := RectArray.BoundsRect.Right - 2;

    TextLength := R.Right + 2 - RectArray.TextRect.Left;
    begin
      PrevColor := ACanvas.Font.Color;
      ACanvas.Font.Color := clBtnShadow;
      DrawText(ACanvas.Handle, pChar(Text), Length(Text), R,
        {DT_CENTER or} DT_VCENTER or DT_SINGLELINE or DT_END_ELLIPSIS or
        DT_MODIFYSTRING);
      ACanvas.Font.Color := PrevColor;
    end;
  end;
end;

image

It has worked fine for me on other occasions, however in this project it gives an error if I resize the main window after the app starts. Perhaps it is due to large number of items. If I first scroll through all items, and then resize the main window, then the AV does not occur. (perhaps some initialization is taking place that is required..) The AV also occurs after entering some search terms.

I am using the latest code from pyscripter Mustangpeak ELV and CommonLib, although I get the same problem using the TurboPack branch. I'm using Tokyo on Window 10 x64.

Sample project attached. EasyListView AV Test.zip

raelb commented 5 years ago

Using FastMM shows there is a memory leak. If I comment out this bit in the second last line of code, the problem does not occur:

or DT_END_ELLIPSIS or DT_MODIFYSTRING

Although I'm not sure why this would cause memory problems..

pyscripter commented 4 years ago

From the Microsoft documentation of Dray text.

If uFormat includes DT_MODIFYSTRING, the function could add up to four additional characters to this string. The buffer containing the string should be large enough to accommodate these extra characters.

You are not doing that and there is memory overrun. All sort of problems could occur.