- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在 Delphi 2007 中让 TCustomControl 与透明度一起工作时遇到问题。我目前已将问题简化为下面的代码。问题是最初创建表单时,控件以相反的顺序绘制,它们被添加到表单中。当窗体被调整大小时,它们以正确的顺序绘制。我究竟做错了什么?排除第 3 方解决方案,是否有更合适的路径可以遵循?
这是我的示例项目,演示了 Delphi 2007 中的问题。
unit Main;
interface
uses
Forms, Classes, Controls, StdCtrls, Messages,
ExtCtrls;
type
// Example of a TWinControl derived control
TMyCustomControl = class(TCustomControl)
protected
procedure CreateParams(var params: TCreateParams); override;
procedure WMEraseBkGnd(var msg: TWMEraseBkGnd);
message WM_ERASEBKGND;
procedure Paint; override;
end;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormPaint(Sender: TObject);
private
YellowBox: TMyCustomControl;
GreenBox: TMyCustomControl;
end;
var
Form1: TForm1;
implementation
uses
Windows, Graphics;
{$R *.dfm}
{ TForm1 }
procedure TForm1.FormCreate(Sender: TObject);
begin
self.OnPaint := FormPaint;
GreenBox := TMyCustomControl.Create(self);
GreenBox.Parent := self;
GreenBox.SetBounds(10,10,200,200);
GreenBox.color := clGreen;
YellowBox := TMyCustomControl.Create(self);
YellowBox.Parent := self;
YellowBox.SetBounds(100,100,200,200);
YellowBox.color := clYellow;
end;
// Paint bars on form background
procedure TForm1.FormPaint(Sender: TObject);
var
Idx: Integer;
begin
for Idx := 0 to ClientHeight div 8 do
begin
if Odd(Idx) then
Canvas.Brush.Color := clWhite
else
Canvas.Brush.Color := clSilver; // pale yellow
Canvas.FillRect(Rect(0, Idx * 8, ClientWidth, Idx * 8 + 8));
end;
end;
{ TMyCustomControl }
procedure TMyCustomControl.CreateParams(var params: TCreateParams);
begin
inherited;
params.ExStyle := params.ExStyle or WS_EX_TRANSPARENT;
end;
procedure TMyCustomControl.WMEraseBkGnd(var msg: TWMEraseBkGnd);
begin
SetBkMode (msg.DC, TRANSPARENT);
msg.result := 1;
end;
procedure TMyCustomControl.Paint;
begin
Canvas.Brush.Color := color;
Canvas.RoundRect(0,0,width,height,50,50);
end;
end.
最佳答案
错误的是您对控件绘制顺序的期望。控件接收顺序WM_PAINT
消息被记录为实际上是完全相反的顺序,最顶层的控件首先接收消息。稍后会详细介绍文档,因为有了 WS_EX_TRANSPARENT
风格的 sibling 让我们处于无证领域。正如您已经注意到的,您有一个接收控件的顺序 WM_PAINT
的情况。消息不是确定性的 - 调整窗口大小时,顺序会发生变化。
我已经修改了一些你的复制案例,看看发生了什么。修改包括两个面板和一个调试输出,当他们收到 WM_PAINT
时.
unit Unit1;
interface
uses
Forms, Classes, Controls, StdCtrls, Messages, ExtCtrls;
type
TMyCustomControl = class(TCustomControl)
protected
procedure CreateParams(var params: TCreateParams); override;
procedure WMEraseBkGnd(var msg: TWMEraseBkGnd);
message WM_ERASEBKGND;
procedure Paint; override;
procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
end;
TPanel = class(extctrls.TPanel)
protected
procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
end;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormPaint(Sender: TObject);
private
YellowBox: TMyCustomControl;
GreenBox: TMyCustomControl;
Panel1, Panel2: TPanel;
end;
var
Form1: TForm1;
implementation
uses
sysutils, windows, graphics;
{$R *.dfm}
{ TForm1 }
procedure TForm1.FormCreate(Sender: TObject);
begin
Width := 590;
Height := 270;
OnPaint := FormPaint;
GreenBox := TMyCustomControl.Create(self);
GreenBox.Parent := self;
GreenBox.SetBounds(20, 20, 140, 140);
GreenBox.color := clGreen;
GreenBox.Name := 'GreenBox';
//{
Panel1 := TPanel.Create(Self);
Panel1.Parent := Self;
Panel1.SetBounds(240, 40, 140, 140);
Panel1.ParentBackground := False;
Panel1.Color := clMoneyGreen;
Panel1.Name := 'Panel1';
Panel2 := TPanel.Create(Self);
Panel2.Parent := Self;
Panel2.SetBounds(260, 60, 140, 140);
Panel2.ParentBackground := False;
Panel2.Color := clCream;
Panel2.Name := 'Panel2';
//}
YellowBox := TMyCustomControl.Create(self);
YellowBox.Parent := self;
YellowBox.SetBounds(80, 80, 140, 140);
YellowBox.color := clYellow;
YellowBox.Name := 'YellowBox';
YellowBox.BringToFront;
end;
// Paint bars on form background
procedure TForm1.FormPaint(Sender: TObject);
var
Idx: Integer;
begin
for Idx := 0 to ClientHeight div 8 do
begin
if Odd(Idx) then
Canvas.Brush.Color := clWhite
else
Canvas.Brush.Color := clSilver; // pale yellow
Canvas.FillRect(Rect(0, Idx * 8, ClientWidth, Idx * 8 + 8));
end;
end;
{ TPanel }
procedure TPanel.WMPaint(var Message: TWMPaint);
begin
OutputDebugString(PChar(Format(' %s painting..', [Name])));
inherited;
end;
{ TMyCustomControl }
procedure TMyCustomControl.CreateParams(var params: TCreateParams);
begin
inherited;
params.ExStyle := params.ExStyle or WS_EX_TRANSPARENT;
end;
procedure TMyCustomControl.WMEraseBkGnd(var msg: TWMEraseBkGnd);
begin
msg.Result := 1;
end;
procedure TMyCustomControl.WMPaint(var Message: TWMPaint);
begin
OutputDebugString(PChar(Format(' %s painting..', [Name])));
inherited;
end;
procedure TMyCustomControl.Paint;
begin
Canvas.Brush.Color := Color;
Canvas.RoundRect(0, 0, Width, Height, 50, 50);
end;
end.
WM_PAINT
的调试输出消息是这样的:
Debug Output: Panel2 painting.. Process Project1.exe (12548)
Debug Output: Panel1 painting.. Process Project1.exe (12548)
Debug Output: YellowBox painting.. Process Project1.exe (12548)
Debug Output: GreenBox painting.. Process Project1.exe (12548)
WS_CLIPSIBLINGS
控件中的样式标志告诉操作系统,z 顺序中较高的同级控件占用的控件部分不会被绘制。
Clips child windows relative to each other; that is, when a particular child window receives a WM_PAINT message, the WS_CLIPSIBLINGS style clips all other overlapping child windows out of the region of the child window to be updated.
WM_PAINT
Panel1 的处理程序并查看操作系统的更新区域的外观。
{ TPanel }
// not declared in D2007
function GetRandomRgn(hdc: HDC; hrgn: HRGN; iNum: Integer): Integer; stdcall;
external gdi32;
const
SYSRGN = 4;
procedure TPanel.WMPaint(var Message: TWMPaint);
var
PS: TPaintStruct;
Rgn: HRGN;
TestDC: HDC;
begin
OutputDebugString(PChar(Format(' %s painting..', [Name])));
Message.DC := BeginPaint(Handle, PS);
Rgn := CreateRectRgn(0, 0, 0, 0);
if (Name = 'Panel1') and (GetRandomRgn(Message.DC, Rgn, SYSRGN) = 1) then begin
OffsetRgn(Rgn, - Form1.ClientOrigin.X + Width + 40, - Form1.ClientOrigin.Y);
TestDC := GetDC(Form1.Handle);
SelectObject(TestDC, GetStockObject(BLACK_BRUSH));
PaintRgn(TestDC, Rgn);
ReleaseDC(Form1.Handle, TestDC);
DeleteObject(Rgn);
end;
inherited;
EndPaint(Handle, PS);
end;
BeginPaint
将使用系统更新区域剪辑更新区域,然后您可以使用
GetRandomRgn
检索该区域。 .我已将裁剪的更新区域转储到表单右侧。不要介意
Form1
引用或缺少错误检查,我们只是在调试。无论如何,这会产生以下形式:
... The
WS_EX_TRANSPARENT
extended window style alters the painting algorithm as follows: If aWS_EX_TRANSPARENT
window needs to be painted, and it has any non-WS_EX_TRANSPARENT
windows siblings (which belong to the same process) which also need to be painted, then the window manager will paint the non-WS_EX_TRANSPARENT
windows first.
procedure TForm1.FormCreate(Sender: TObject);
begin
Width := 590;
Height := 270;
OnPaint := FormPaint;
GreenBox := TMyCustomControl.Create(self);
GreenBox.Parent := self;
GreenBox.SetBounds(20, 20, 140, 140);
GreenBox.color := clGreen;
GreenBox.Name := 'GreenBox';
//{
Panel1 := TPanel.Create(Self);
Panel1.Parent := Self;
Panel1.SetBounds(40, 40, 140, 140);
Panel1.ParentBackground := False;
Panel1.Color := clMoneyGreen;
Panel1.Name := 'Panel1';
Panel2 := TPanel.Create(Self);
Panel2.Parent := Self;
Panel2.SetBounds(60, 60, 140, 140);
Panel2.ParentBackground := False;
Panel2.Color := clCream;
Panel2.Name := 'Panel2';
//}
YellowBox := TMyCustomControl.Create(self);
YellowBox.Parent := self;
YellowBox.SetBounds(80, 80, 140, 140);
YellowBox.color := clYellow;
YellowBox.Name := 'YellowBox';
YellowBox.BringToFront;
end;
...
procedure TMyCustomControl.WMPaint(var Message: TWMPaint);
var
PS: TPaintStruct;
Rgn: HRGN;
TestDC: HDC;
begin
OutputDebugString(PChar(Format(' %s painting..', [Name])));
Message.DC := BeginPaint(Handle, PS);
Rgn := CreateRectRgn(0, 0, 0, 0);
if (Name = 'GreenBox') and (GetRandomRgn(Message.DC, Rgn, SYSRGN) = 1) then begin
OffsetRgn(Rgn, - Form1.ClientOrigin.X + Width + 260, - Form1.ClientOrigin.Y);
TestDC := GetDC(Form1.Handle);
SelectObject(TestDC, GetStockObject(BLACK_BRUSH));
PaintRgn(TestDC, Rgn);
ReleaseDC(Form1.Handle, TestDC);
DeleteObject(Rgn);
end;
inherited;
EndPaint(Handle, PS);
end;
WM_PAINT
命令。我把它留到最后的一个原因是它包含一个可能的解决方案(当然我们已经找到了一个解决方案,在透明控件之间散布一些非透明控件):
... If a window in the parent chain is composited (a window with WX_EX_COMPOSITED), sibling windows receive WM_PAINT messages in the reverse order of their position in the Z order. Given this, the window highest in the Z order (on the top) receives its WM_PAINT message last, and vice versa. If a window in the parent chain is not composited, sibling windows receive WM_PAINT messages in Z order.
WS_EX_COMPOSITED
在父表单上似乎有效。但我不知道它是否适用于您的情况。
关于delphi - 创建/恢复表单时,重叠的 TCustomControl 对象绘制顺序不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46006230/
这个问题已经有答案了: How to do case insensitive string comparison? (23 个回答) 已关闭 3 年前。 用户在我的输入栏中写入“足球”,然后执行第 6
啊,不习惯 javascript 中的字符串。 character_id= + id + correct= + correctOrIncorrect 这就是我需要制作成字符串的内容。如果您无法猜测字符
$(function() { var base_price = 0; CalculatePrice(); $(".math1").on('change', function(e) { Calc
我找不到任何文章回答问题:将Spinnaker部署到Spinnaker将管理的同一Kubernetes集群是否安全/正确?我主要是指生产,HA部署。 最佳答案 我认为Spinnaker和Kuberne
我正在使用MSVC在Windows上从源代码(官方源代码发布,而不是从仓库中)构建Qt5(Qt 5.15.0)。 我正在设置环境。变量,依赖项等,然后运行具有1600万个选项的configure,最后
我需要打印一个包含重复单词的数组。我的数组已经可以工作,但我不知道如何正确计算单词数。我已经知道,当我的索引计数器 (i) 为 49 时,并且当 (i) 想要计数到 50 时,我会收到错误,但我不知道
我正在遵循一个指南,该指南允许 Google map 屏幕根据屏幕尺寸禁用滚动。我唯一挣扎的部分是编写一个代码,当我手动调整屏幕大小时动态更改 True/False 值。 这是我按照说明操作的网站,但
我有一个类“FileButton”。它的目的是将文件链接到 JButton,FileButton 继承自 JButton。子类继承自此以使用链接到按钮的文件做有用的事情。 JingleCardButt
我的 friend 数组只返回一个数字而不是所有数字。 ($myfriends = 3) 应该是…… ($myfriends = 3 5 7 8 9 12). 如果我让它进入 while 循环……整个
这个问题在这里已经有了答案: Is there a workaround to make CSS classes with names that start with numbers valid?
我正在制作一个 JavaScript 函数,当调整窗口大小时,它会自动将 div 的大小调整为与窗口相同的宽度/高度。 该功能非常基本,但我注意到在调整窗口大小时出现明显的“绘制”滞后。在 JS fi
此问题的基本视觉效果可在 http://sevenx.de/demo/bootstrap-carousel/inc.carousel/tabbed-slider.html 获得。 - 如果你想看一看。
我明白,如果我想从函数返回一个字符串文字或一个数组,我应该将其声明为静态的,这样当被调用的函数被返回时,内容就不会“消亡”。 但我的问题是,当我在函数内部使用 malloc 分配内存时会怎样? 在下面
在 mySQL 数据库中存储 true/false/1/0 值最合适(读取数据消耗最少)的数据字段是什么? 我以前使用过一个字符长的 tinyint,但我不确定它是否是最佳解决方案? 谢谢! 最佳答案
我想一次读取并处理CSV文件第一行中的条目(例如打印)。我假设使用Unix风格的\n换行符,没有条目长度超过255个字符,并且(现在)在EOF之前有一个换行符。这意味着它是fgets()后跟strto
所以,我们都知道 -1 > 2u == true 的 C/C++ 有符号/无符号比较规则,并且我有一种情况,我想有效地实现“正确”比较。 我的问题是,考虑到人们熟悉的尽可能多的架构,哪种方法更有效。显
**摘要:**文章的标题看似自相矛盾。 本文分享自华为云社区《Java异常处理:如何写出“正确”但被编译器认为有语法错误的程序》,作者: Jerry Wang 。 文章的标题看似自相矛盾,然而我在“正
我有一个数据框,看起来像: dataDemo % mutate_each(funs(ifelse(. == '.', REF, as.character(.))), -POS) # POS REF
有人可以帮助我使用 VBScript 重新格式化/正确格式化带分隔符的文本文件吗? 我有一个文本文件 ^分界如下: AGREE^NAME^ADD1^ADD2^ADD3^ADD4^PCODE^BAL^A
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
我是一名优秀的程序员,十分优秀!