使用Delphi Tokyo

时间:2017-12-28 22:08:51

标签: delphi winapi themes

使用Delphi Tokyo 10.2,带有程式化主题。我正在尝试突出显示表单上的组件,例如ComboBoxesEditTexts等。例如,如果用户输入了无效数据,我想突出显示该组件。

在过去,我们只是对组件Red进行着色,并且通常会通过调整大小/移动/重绘来保持颜色。现在有了主题,我们需要做更多的事情才能让颜色显示并持续存在。

我尝试禁用每个组件的StyleElements [seFont, seClient, seBorder]属性以强制显示颜色。这有效但似乎很糟糕,特别是当有许多组件被验证时。此外,简单地将组件着色为红色可能看起来不适合某些主题。

我还尝试使用WinAPI SetRop2(..)在组件周围绘制一个红色矩形。例如,here是一些聪明的代码,我调整为围绕它TWinControlDraw redbox进行调整;我也可以使用类似的电话删除redbox。这有效:

enter image description here

显然,但是并没有通过重绘来坚持下去。似乎添加自定义绘画方法可能在这里有点过分。除非,有更好的方法吗?

我考虑的其他事项:

所有组件都放在面板上,我考虑使用受保护的黑客在组件周围的面板画布上绘制红色rect,但同样,更多的自定义绘图例程...

我也在考虑根据需要动态绘制TShapes,但这让我觉得很傻。

在相同情况下必须有其他人,例如,数据输入验证在旧版本的Delphi中工作得很好,但在主题时看起来并不那么好。使用主题时最好的方法是什么? SetRop2(..)方法似乎是最干净的,但有人可以建议一种简单的方法来保持颜色的持久性吗?我也欢迎其他想法。谢谢。

修改 也许,只是动态地绘制无效响应周围的TShapes并不是那么糟糕。他们坚持重绘并且不会从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's 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's parent, e.g., 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, e.g., Invalid.
  HiLiteMe(bitBtn3, TRUE, clBlue);        // Draw a Blue Box around the Button, e.g., Required.
end;

blue box indicates required, red box indicates invalid

这样称为删除HiLites ...

begin
  HiLiteMe(checkListBox1, FALSE);   // Draw a RedBox around the CheckListBox, e.g., Invalid.
  HiLiteMe(bitBtn3, FALSE);        // Draw a Blue Box around the Button, e.g., Required.
end;

1 个答案:

答案 0 :(得分:1)

我建议只在控件的一侧(例如左侧或底部)显示或隐藏一个红色TShape。