Highlight controls in a Delphi theme application

Using Delphi Tokyo 10.2 with stylized themes. I am trying to highlight components in a form like EditTexts, ComboBoxes, etc. For example, if the user entered incorrect data, I would like to highlight the component.

In the past, we simply stained Red components, and the color was maintained by resizing / moving / reviewers in general. Now with the theme, we need to do a little more so that the color is displayed and saved.

I tried to disable each element of StyleElements [seFont, seClient, seBorder] to show the color. It works, but it seems kludgey, especially when there are many components that are tested. Also, just coloring the component in red may not look right with some themes.

I also tried just drawing a red rectangle around the components using WinAPI SetRop2 (..). For example, here is some kind of smart code, I tweaked it to take TWinControl and draw a red frame around it, I can also remove redbox using a similar call. It works,

enter image description here

... but apparently not saved. It seems that adding custom drawing methods might be redundant. Is there any better way?

Other things I reviewed:

All components sit on panels, and I considered using a secure hack to draw red rectangles on a panel canvas around components, but again there are more custom paint routines ...

I also consider dynamically drawing TShapes as needed, but that seems silly to me.

, , , Delphi, . ? SetRop2 (..), , , - . . .

, , TShapes . repaints TWinControl, , , .

, , .

//assuming owning control will be free'd properly and 
//will in turn free HI_LITE Box.
//
//tantamount to adding an instance variable, TShape, to existing Control,
//since class helpers don't allow.  And I don't want to descend 
//new controls just to have a hiLiteBox Instance Variable.

procedure HiLiteMe(aControl : TWinControl; HILITE_FLAG : Boolean = TRUE; aColor : TColor = clRed);
const OFFSET = 4;                         //specify the offset of the border size of the box.
const BOX_NAME_PREFIX = 'HI_LITE_BOX_';

var
   hiLiteBox : TShape;      //reference created on stack, but object created on the heap,
   uniqueBoxName : String;    //so use the persistent aControl owned component list to maintain the reference.
begin
  uniqueBoxName := BOX_NAME_PREFIX + aControl.Name;              //uniquename for each associated HiLiteBox.
  HiLiteBox := aControl.FindComponent(uniqueBoxName) as TShape;  //phishing for the HiLiteBox if it was previously created.

  if NOT Assigned(hiLiteBox) then         //create HiLiteBox and make persist outside this proc.
  begin
    if NOT HILITE_FLAG then exit;         //don't create a box if we're just going to hide it anyway.
    hiLiteBox := TShape.Create(aControl); //Create HiLiteBox, setting aControl as owner, quicker retrieval using aControl.findComponent
    hiLiteBox.Parent := aControl.Parent;  //Render the box on the control parent, eg, panel, form, etc.
    hiLiteBox.Name :=  uniqueBoxName;
    hiLiteBox.Pen.Color := aColor;        //Color the Pen
    hiLiteBox.Pen.Width := offset-1;      //Make the Pen just slightly smaller than the offset.
    hiLiteBox.Brush.Color := clWindow;    //Choose a brush color, to fill the space between the pen and the Control
    hiLiteBox.Left := aControl.Left - offset;
    hiLiteBox.Width := aControl.Width + offset*2;
    hiLiteBox.Top := aControl.Top - offset;
    hiLiteBox.Height := aControl.Height + offset*2;
  end;

  hiLiteBox.Visible := HILITE_FLAG; //Show/Hide HiLite as appropriate.
end;

HiLite ...

begin
  HiLiteMe(checkListBox1, TRUE, clRed);   //Draw a RedBox around the CheckListBox, eg, Invalid.
  HiLiteMe(bitBtn3, TRUE, clBlue);        //Draw a Blue Box around the Button, eg, Required.
end;

a blue flag indicates that a red flag indicates invalid

, HiLites...

begin
  HiLiteMe(checkListBox1, FALSE);   //Draw a RedBox around the CheckListBox, eg, Invalid.
  HiLiteMe(bitBtn3, FALSE);        //Draw a Blue Box around the Button, eg, Required.
end;
+4
1

TShape (, ), .

0

Source: https://habr.com/ru/post/1691481/


All Articles