5
votes

Well, I have the following problem:

I've painted the tree cells in different colors depending on some boolean vars. Example:

  • isProcessService,
  • isProcessInDebugger,
  • isProcessService,
  • isProcessElevated,
  • isProcessNet,
  • isProcessOwner,
  • isProcessinJob,
  • isProcessPacked,
  • isProcessMarkedForDeletion,
  • isProcessMarkedForCreation : Boolean;

So in BeforeCellPaint I'll paint the cells background color based on those booleans like:

procedure TMainForm.ProcessVstBeforeCellPaint(Sender: TBaseVirtualTree;
  TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
  CellPaintMode: TVTCellPaintMode; CellRect: TRect; var ContentRect: TRect);
var
  NodeData: PProcessData;
begin
 if Node = nil then
    Exit;

  NodeData := Sender.GetNodeData(Node);

  if NodeData = nil then
    Exit;

  if (NodeData^.isProcessOwner) then
  begin
    TargetCanvas.Brush.Color := $00AAFFFF;
    TargetCanvas.FillRect(TargetCanvas.ClipRect);
  end;

  if (NodeData^.isProcessInDebugger) then
  begin
    TargetCanvas.Brush.Color := $00E5A5A5;
    TargetCanvas.FillRect(TargetCanvas.ClipRect);
  end;

    if (NodeData^.pProcessID = 0) or (NodeData^.pProcessID = 4) then
  begin
    TargetCanvas.Brush.Color := $00FFCCAA;
    TargetCanvas.FillRect(TargetCanvas.ClipRect);
  end;

  if (NodeData^.isProcessElevated) and not(NodeData^.isProcessInDebugger) then
  begin
    TargetCanvas.Brush.Color := $0000AAFF;
    TargetCanvas.FillRect(TargetCanvas.ClipRect);
  end;

  if (NodeData^isProcessService) and
    not (NodeData^.isProcessPacked) and
    not(NodeData^.isProcessNet) then
  begin
    TargetCanvas.Brush.Color := $00FFFFCC;
    TargetCanvas.FillRect(TargetCanvas.ClipRect);
  end;

  if (NodeData^.isProcessMarkedForDeletion) then
  begin
    TargetCanvas.Brush.Color := $005D5DFF;
    TargetCanvas.FillRect(TargetCanvas.ClipRect);
  end;

  if (NodeData^.isProcessMarkedForCreation) then
  begin
    TargetCanvas.Brush.Color := $0061E15E;
    TargetCanvas.FillRect(TargetCanvas.ClipRect);
  end;

  if (NodeData^.isProcessNet) then
  begin
    TargetCanvas.Brush.Color := $005CE0BF;
    TargetCanvas.FillRect(TargetCanvas.ClipRect);
  end;
end;


The question is:

How could I paint the cell green or red depending on a process is going to be created or deleted (let the color stay for at least one second and then switch back to its original value?)

I other words, a process is created paint the cell green wait a second and then switch back to the original color depending on: isProcessService, is ProcessOwner and so on...

The biggest Problem is I need this in a non blocking mode (I can not use sleep otherwise the tree will freeze too so the color change will not be noticed)

If you still can not follow me, I'm trying to mimic the same behavior Process Explorer or Process Hacker does when a process is created or deleted. Both applications paints the cell background for those processes red or green for a second then switching back to the original color the cell had.

Just for information, I'll get notified of process creation or deletion via wmi.

1
Use CellRect, not TargetCanvas.ClipRect.Ondrej Kelle
How do you handle the changes in proccess list, do you constantly rebuild the tree or do you add/delete nodes as needed? BTW, the correct way to set cell's background color in VT is to use BeforeItemErase event (with EraseAction := eaColor), not BeforeCellPaint.ain
You're right got confused a littestOrM

1 Answers

5
votes

Whenever a process is created, start a timer associated with that process with a timeout of 1s. The isProcessMarkedForCreation is set to true and so the row is painted green. When the timer fires the handler sets isProcessMarkedForCreation to false and forces a repaint of that row which removes the green highlight. Now that the timer has done its work it should be deleted. The exact same approach can be used for deletion.