Is there a bug in the Delphi list view control when using custom drawing?

后端 未结 2 1743
我在风中等你
我在风中等你 2020-12-03 14:25

QC#101189

I\'m trying to custom draw a progress bar in a Delphi TListView as suggested by NGLN\'s answer to another SO question. This works fine, apart

相关标签:
2条回答
  • 2020-12-03 14:56

    I don't have a clue for the black rectangle at the text position, but the missing hot tracking is due to the DefaultDraw := False; in your code. OnCustomDrawSubItem is only called for subitem <> 0, so the first column is drawn as default while the second uses your code. Custom drawing of the first column can be made with OnCustomDrawItem.

    0 讨论(0)
  • 2020-12-03 15:07

    This is a workaround for the defective behavior rather than being an answer to the question if there's a bug in the VCL, and a few thoughts.

    The workaround is to set the background mode of the device context assigned by the common control for item painting cyle to transparent after carrying out custom drawing:

    procedure TForm1.ListViewCustomDrawSubItem(Sender: TCustomListView;
      Item: TListItem; SubItem: Integer; State: TCustomDrawState;
      var DefaultDraw: Boolean);
    var
      R: TRect;
    begin
      if not [CustomDrawing] then  // <- If we're not gonna do anything do not
        Exit;                      //    fiddle with the DC in any way
    
      DefaultDraw := False;
      ListView_GetSubItemRect(Sender.Handle, Item.Index, SubItem, LVIR_BOUNDS, @R);
      Sender.Canvas.MoveTo(R.Left, R.Top);
      Sender.Canvas.LineTo(R.Right-1, R.Bottom-1);
    
      SetBkMode(Sender.Canvas.Handle, TRANSPARENT); // <- will effect the next [sub]item
    end; 
    



    In an [sub]item paint cycle, the painting is always done in a top-down fashion, items having a lower index are sent NM_CUSTOMDRAW notification prior to ones with higher indexes. When the mouse is moved from one row to another, two rows need to be re-drawn - the one loosing the hot state, and the one gaining it. It would seem, when custom drawing is in-effect, drawing the row that's loosing the hot-state leaves the DC in an undesirable state. This is not a problem when moving the mouse upwards, because that item gets drawn last.

    Custom drawing ListView and TreeView controls are different than custom drawing other controls and somewhat complicated (see: Custom Draw With List-View and Tree-View Controls). But you have full control over the entire process. The code in the NM_CUSTOMDRAW case of TCustomListView.CNNotify in 'comctrls.pas' of the VCL is equally complicated. But despite being provided a bunch of custom drawing handlers (half of them being advanced), you have no control over what the VCL does. For instance you can't return the CDRF_xxx you'd like or you can't set the clrTextBk you want. My biased opinion is that, there's a bug/design issue in the Delphi list view control, but I have nothing more concrete than an intuition as in finding a workaround.

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