我正在写一个简单的程序,列出屏幕上显示的每个窗口。我可以从列表中选择一个窗口用矩形围绕它。我正在将矩形直接绘制到桌面窗口。我需要清除画布之前,因为我想选择我希望的窗口,一个窗口一次选择。在窗口周围绘制框架的无效桌面窗口
我试图使桌面窗口无效,这实际上工作,但它使很多闪烁。
InvalidateRect(0, 0, True);
在这种情况下直接在桌面上绘制是否正确?任何其他的想法,以避免闪烁?
谢谢。
我正在写一个简单的程序,列出屏幕上显示的每个窗口。我可以从列表中选择一个窗口用矩形围绕它。我正在将矩形直接绘制到桌面窗口。我需要清除画布之前,因为我想选择我希望的窗口,一个窗口一次选择。在窗口周围绘制框架的无效桌面窗口
我试图使桌面窗口无效,这实际上工作,但它使很多闪烁。
InvalidateRect(0, 0, True);
在这种情况下直接在桌面上绘制是否正确?任何其他的想法,以避免闪烁?
谢谢。
通常,当您直接绘制到桌面时,防止出现文物的唯一方法是不断重新绘制整个屏幕。这可能变得沉重,并且破坏了视频缓存的全部目的。
我见过的应用程序不是通过直接画到屏幕的画布来实现,而是通过创建4个不同的“边缘”窗口。例如,您希望“框架化”的窗口的顶部,左侧,右侧和底部边缘都会有一个窗口。顶部和底部窗口的高度可以为5px,左右边缘的宽度为5px。将这些窗口(无边框样式)放置在窗口边缘周围,为每个窗体着色,例如绿色,然后在窗口周围有一个绿色边框。
例如:
bsNone
fsStayOnTop
使用此方法,您不必担心无效。可以从一个单一的形式做到这一点,但是你必须担心透明度等问题。对每个边缘使用4个表单确保用户仍然可以在没有任何透明度的情况下点击聚焦的表单。
快速样品...
单位:uMain.pas
unit uMain;
interface
uses
Winapi.Windows, Winapi.Messages,
System.SysUtils, System.Variants, System.Classes,
Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TfrmMain = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
FTop: TForm;
FLeft: TForm;
FRight: TForm;
FBottom: TForm;
procedure PositionBorder(const ARect: TRect; const Thickness: Integer;
const Color: TColor);
procedure HideBorder;
public
function FormRect: TRect;
end;
var
frmMain: TfrmMain;
implementation
{$R *.dfm}
procedure TfrmMain.FormCreate(Sender: TObject);
begin
//Create each form
FTop:= TForm.Create(nil);
FLeft:= TForm.Create(nil);
FRight:= TForm.Create(nil);
FBottom:= TForm.Create(nil);
//Default position
FTop.Position:= poDefault;
FBottom.Position:= poDefault;
FLeft.Position:= poDefault;
FRight.Position:= poDefault;
//Border Style
FTop.BorderStyle:= bsNone;
FBottom.BorderStyle:= bsNone;
FLeft.BorderStyle:= bsNone;
FRight.BorderStyle:= bsNone;
//Form Style
FTop.FormStyle:= fsStayOnTop;
FBottom.FormStyle:= fsStayOnTop;
FLeft.FormStyle:= fsStayOnTop;
FRight.FormStyle:= fsStayOnTop;
end;
procedure TfrmMain.FormDestroy(Sender: TObject);
begin
FTop.Free;
FBottom.Free;
FLeft.Free;
FRight.Free;
end;
procedure TfrmMain.PositionBorder(const ARect: TRect; const Thickness: Integer; const Color: TColor);
var
Thick: Integer;
HalfThick: Integer;
begin
Thick:= Thickness;
if Thick < 1 then Thick:= 1;
HalfThick:= Thickness div 2;
if HalfThick < 1 then HalfThick:= 1;
//Color
FTop.Color:= Color;
FBottom.Color:= Color;
FLeft.Color:= Color;
FRight.Color:= Color;
//Thickness
FTop.Height:= Thick;
FBottom.Height:= Thick;
FLeft.Width:= Thick;
FRight.Width:= Thick;
//Lengths
FTop.Width:= ARect.Width + Thick;
FBottom.Width:= ARect.Width + Thick;
FLeft.Height:= ARect.Height + Thick;
FRight.Height:= ARect.Height + Thick;
//Positions
FTop.Left:= ARect.Left - HalfThick;
FTop.Top:= ARect.Top - HalfThick;
FBottom.Left:= ARect.Left - HalfThick;
FBottom.Top:= ARect.Bottom + HalfThick;
FLeft.Left:= ARect.Left - HalfThick;
FLeft.Top:= ARect.Top - HalfThick;
FRight.Left:= ARect.Right + HalfThick;
FRight.Top:= ARect.Top - HalfThick;
//Show windows
FTop.Show;
FBottom.Show;
FLeft.Show;
FRight.Show;
end;
procedure TfrmMain.HideBorder;
begin
FLeft.Hide;
FTop.Hide;
FRight.Hide;
FBottom.Hide;
end;
function TfrmMain.FormRect: TRect;
begin
Result.Left:= Left;
Result.Top:= Top;
Result.Width:= Width;
Result.Height:= Height;
end;
procedure TfrmMain.Button1Click(Sender: TObject);
begin
PositionBorder(FormRect, 5, clGreen);
end;
end.
表:uMain.dfm
对象
frmMain: TfrmMain
Left = 315
Top = 113
Caption = 'frmMain'
ClientHeight = 204
ClientWidth = 368
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
Position = poScreenCenter
OnCreate = FormCreate
OnDestroy = FormDestroy
PixelsPerInch = 96
TextHeight = 13
object Button1: TButton
Left = 64
Top = 80
Width = 209
Height = 25
Caption = 'Button1'
Default = True
TabOrder = 0
OnClick = Button1Click
end
end
这是假设你有一个按钮Button1
。这个电话就像...
PositionBorder(WindowRect, 5, clGreen);
...其中WindowRect =一个TRect记录,窗口的坐标被“框住”,5是该帧的厚度,clGreen是帧的颜色。
呃,这实际上是一个很好的选择,我只是做了一个例子,它工作得很好。 PS:感谢您的快速代码:) – ThePirateCat
...我再次更新了代码,不依赖于4个创建的窗口,此版本在一个单元中处理整个位。由于某些原因,虽然第一次点击并不能正常工作,但在其余时间内仍能正常工作。 –
我终于使用这个技巧,谢谢你的选择! – ThePirateCat
'GetWindow(GetDesktopWindow,0)'?寻找桌面的兄弟姐妹?曾经测试过GetWindow的返回? –
@SertacAkyuz你是对的好先生,我的错不复制我的实际代码... – ThePirateCat
@ThePirate - 哦!我想知道它是否工作,因为InvalidateRect与HWND_DESKTOP没有问题,它也是0.但是没关系。请始终发布实际的代码;)。 –