如何根据在服务器端绘制的区域在远程屏幕(客户端)上的两个表单中创建相同的孔?
How make the same hole in two Form's on remote screen (client side), based on area drawn on server side?
我有以下代码,想根据在服务器端绘制的区域,在远程屏幕(客户端)的两个表单中绘制相同的孔。
我在两侧(服务器和客户端)都有相同的表单 (Form3),这是一个 "mirror",我在其中绘制了一个必须留在内部的区域在客户端使用相同的表格。
The Form3 in server side have 50% of max AlphaBlend
value, this is necessary to see remote screen behind Form3.
Before all, i want say that i'm receiving the remote screen on server side and and mouse click positions works like expected.
那我就麻烦了:
以下代码产生上图所示的结果。我认为这段代码是正确的,但缺少将此孔与 Form3.
对齐
有人可以帮忙吗?抱歉,如果这是一个糟糕的问题,但这是我真正的麻烦,我尝试用我能做到的更好的方式表达这个问题中的所有内容。
这是所有相关代码:
服务器端:
Form2(我看到远程屏幕的地方):
unit Unit2;
interface
uses
Unit1;
type
TForm2 = class(TForm)
Panel1: TPanel;
CheckBox1: TCheckBox;
ScrollBox1: TScrollBox;
Image1: TImage;
PaintBox1: TPaintBox;
procedure PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure PaintBox1MouseMove(Sender: TObject; Shift: TShiftState;
X, Y: Integer);
procedure PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure PaintBox1Paint(Sender: TObject);
private
{ Private declarations }
FSelecting: Boolean;
FSelection: TRect;
pos1, pos2, pos3, pos4: Integer;
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
procedure TForm2.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if CheckBox1.Checked then
begin
FSelection.Left := X;
FSelection.Top := Y;
FSelecting := true;
end;
end;
procedure TForm2.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState;
X, Y: Integer);
begin
if FSelecting then
begin
FSelection.Right := X;
FSelection.Bottom := Y;
pbRec.Invalidate;
end;
end;
procedure TForm2.PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if CheckBox1.Checked then
begin
FSelecting := false;
FSelection.Right := X;
FSelection.Bottom := Y;
PaintBox1.Invalidate;
FSelection.NormalizeRect;
if FSelection.IsEmpty then
begin
// None selection was made on PaintBox
end
else
begin
pos1 := FSelection.Left;
pos2 := FSelection.Top;
pos3 := X;
pos4 := Y;
end;
end;
end;
procedure TForm2.PaintBox1Paint(Sender: TObject);
begin
if CheckBox1.Checked then
begin
PaintBox1.Canvas.Brush.Style := bsClear;
PaintBox1.Canvas.Pen.Style := psSolid;
PaintBox1.Canvas.Pen.Color := clRed;
PaintBox1.Canvas.Rectangle(FSelection);
end;
end;
procedure TForm2.Button1Click(Sender: TObject);
var
Socket: TCustomWinSocket;
begin
Socket := TCustomWinSocket(Form1.LV1.Selected.SubItems.Objects[0]);
if CheckBox1.Checked then
begin
Socket.SendText(intToStr(pos1) + ';' + intToStr(pos2) + ';' +
intToStr(pos3) + ';' + intToStr(pos4));
end;
end;
procedure TForm2.Button2Click(Sender: TObject);
begin
Form3 := TForm3.Create(Self);
Form3.Show;
end;
Form2 .DFM:
object Panel1: TPanel
Left = -1
Top = 0
Width = 773
Height = 89
Anchors = [akTop]
BevelEdges = [beLeft, beRight]
ParentDoubleBuffered = False
TabOrder = 0
end
object ScrollBox1: TScrollBox
Left = 0
Top = 0
Width = 765
Height = 472
HorzScrollBar.Smooth = True
HorzScrollBar.Tracking = True
VertScrollBar.Smooth = True
VertScrollBar.Tracking = True
Align = alClient
TabOrder = 1
object Image1: TImage
Left = 0
Top = 0
Width = 1362
Height = 621
AutoSize = True
end
object PaintBox1: TPaintBox
Left = 0
Top = 0
Width = 1362
Height = 621
Align = alClient
OnMouseDown = PaintBox1MouseDown
OnMouseMove = PaintBox1MouseMove
OnMouseUp = PaintBox1MouseUp
OnPaint = PaintBox1Paint
ExplicitWidth = 1364
ExplicitHeight = 622
end
Form3(在客户端也是一样的"mirror"Form),这个Form根据远程屏幕分辨率集中:
unit Unit3;
interface
uses
...
type
TForm3 = class(TForm)
Panel1: TPanel;
Image1: TImage;
Label1: TLabel;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
procedure CreateParams(var pr: TCreateParams); override;
public
{ Public declarations }
end;
var
Form3: TForm3;
implementation
uses
Unit1;
{$R *.dfm}
procedure TForm3.FormCreate(Sender: TObject);
var
MyString: String;
Splitted: TArray<String>;
begin
MyString := Form1.LV1.Selected.SubItems[6]; // Resolution of remote screen
Splitted := MyString.Split(['x']);
Self.Left := (Integer(Splitted[0]) - Self.Width) div 2;
Self.Top := (Integer(Splitted[1]) - Self.Height) div 2;
end;
procedure TForm3.CreateParams(var pr: TCreateParams);
begin
inherited;
pr.WndParent := Form2.Handle;
pr.ExStyle := pr.ExStyle or WS_EX_TOPMOST or WS_EX_TRANSPARENT;
pr.ExStyle := WS_EX_TRANSPARENT or WS_EX_TOPMOST;
end;
Form3 .DFM:
object Form3: TForm3
Left = 328
Top = 143
BorderStyle = bsNone
ClientHeight = 567
ClientWidth = 526
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
Position = poScreenCenter
OnCreate = FormCreate
PixelsPerInch = 96
TextHeight = 13
object Panel1: TPanel
Left = 0
Top = 0
Width = 801
Height = 569
TabOrder = 0
object Image1: TImage
Left = 1
Top = 1
Width = 799
Height = 567
Align = alClient
ExplicitLeft = 2
ExplicitTop = 0
ExplicitHeight = 447
end
object Label1: TLabel
Left = 92
Top = 69
Width = 28
Height = 13
Caption = 'Nome'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
ParentColor = False
ParentFont = False
end
客户端:
Form2 ("locker" 表格):
unit Unit2;
private
{ Private declarations }
procedure CreateParams(var Params: TCreateParams); override;
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
procedure TForm2.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.WndParent := Application.Handle;
Params.ExStyle := Params.ExStyle or WS_EX_TOPMOST or WS_EX_TRANSPARENT;
Params.ExStyle := WS_EX_TRANSPARENT or WS_EX_TOPMOST;
end;
procedure TForm2.FormCreate(Sender: TObject);
begin
windowstate := wsmaximized;
Top := 0;
Left := 0;
Height := Screen.Height;
Width := Screen.Width;
end;
{
Properties of Form2:
Align => alNone
AlphaBlend => True
BorderStyle => BsNone
}
end.
Form3(服务器端相同):
unit Unit3;
interface
uses
...
type
TForm3 = class(TForm)
Panel1: TPanel;
Label1: TLabel;
procedure FormShow(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
procedure CreateParams(var pr: TCreateParams); override;
public
{ Public declarations }
end;
var
Form3: TForm3;
implementation
uses
Unit2;
{$R *.dfm}
procedure TForm3.FormCreate(Sender: TObject);
begin
Self.Left := (GetSystemMetrics(SM_CXSCREEN) - Self.Width) div 2;
Self.Top := (GetSystemMetrics(SM_CYSCREEN) - Self.Height) div 2;
end;
procedure TForm3.FormShow(Sender: TObject);
begin
ShowWindow(Application.Handle, SW_HIDE);
end;
procedure TForm3.CreateParams(var pr: TCreateParams);
begin
inherited;
pr.WndParent := Form2.Handle;
end;
{
Properties of Form3:
Align => alNone
BorderStyle => BsNone
}
end.
客户端接收区域:
procedure CS1_Read(Self: Pointer; Sender: TObject; Socket: TCustomWinSocket);
var
X1, X2, Y1, Y2: Integer;
List: TStrings;
FormRegion, HoleRegion: HRGN;
StrCommand: string;
begin
if Pos(';', StrCommand) > 0 then
begin
List := TStringList.Create;
try
ExtractStrings([';'], [], PChar(StrCommand), List);
Form3 := TForm3.Create(Form2); // The Form2 already was created and is showing
X1 := Round(StrToIntDef(List[0], 0) - Form2.Left);
Y1 := Round(StrToIntDef(List[1], 0) - Form2.Top);
X2 := Round(StrToIntDef(List[2], 0) - Form2.Left);
Y2 := Round(StrToIntDef(List[3], 0) - Form2.Top);
FormRegion := CreateRectRgn(0, 0, Form3.Width, Form3.Height);
HoleRegion := CreateRectRgn(X1, Y1, X2, Y2);
CombineRgn(FormRegion, FormRegion, HoleRegion, RGN_DIFF);
SetWindowRgn(Form3.handle, FormRegion, true);
FormRegion := CreateRectRgn(0, 0, Form2.Width, Form2.Height);
HoleRegion := CreateRectRgn(X1, Y1, X2, Y2);
CombineRgn(FormRegion, FormRegion, HoleRegion, RGN_DIFF);
SetWindowRgn(Form2.handle, FormRegion, true);
Form3.ShowModal;
Form3.Release;
finally
List.Free;
end;
end;
end;
在客户端,您有一个具有屏幕大小的半透明灰色表单 (Form2)。在该窗体之上,您有一个位于屏幕中心的不透明白色窗体 (Form3)。在 Form3
中,您在 Top = Y
和 Left = X
处有一个矩形孔,坐标为 Form3
.
我了解到您的问题是您想在 Form2 中绘制一个与 Form3 中的孔对齐的孔。
您需要将 Form3
的坐标系转换为 Form2
的坐标系,只需简单地添加:
Form2.Hole.Left := Form3.Left + Form3.Hole.Left;
Form2.Hole.Top := Form3.Top + Form3.Hole.Top;
这将使孔对齐。你似乎在你的计算中尝试了类似的东西,但你指的是 Form2.Left
和 Form2.Top
这是无用的,因为它们都是 0.
如果我误解了你的问题,而你实际上希望 Form3
孔与 Form2
孔对齐,那么你需要将 Form3
移动到左上角屏幕而不是居中 ...
... 或者,考虑您的评论:如果我在远离 Form3
(客户端)的区域的服务器端绘图,例如在屏幕左侧更多,请绘图只有 Form2
的孔,如果我在屏幕中间绘制更多,绘制对齐的两个孔 将通过简单地交换术语来完成:
Form3.Hole.Left := Form2.Hole.Left - Form3.Left
Form3.Hole.Top := Form2.Hole.Top - Form3.Top
这会将 Form2
坐标转换为 Form3
坐标,在您的例子中可能会变成负值(在表格之外)。
根据您的代码调整上述内容,您需要首先用收到的 Form2.Hole
坐标处理 Form2 区域 ,然后减去 Form3
坐标(Left
and Top
) from X1..Y2 and 然后处理Form3 region*.
X1 := Round(StrToIntDef(List[0], 0) - Form2.Left); // Form2 props can be removed as hardcoded to 0
Y1 := Round(StrToIntDef(List[1], 0) - Form2.Top); // -"-
X2 := Round(StrToIntDef(List[2], 0) - Form2.Left); // -"-
Y2 := Round(StrToIntDef(List[3], 0) - Form2.Top); // -"-
FormRegion := CreateRectRgn(0, 0, Form2.Width, Form2.Height);
HoleRegion := CreateRectRgn(X1, Y1, X2, Y2);
CombineRgn(FormRegion, FormRegion, HoleRegion, RGN_DIFF);
SetWindowRgn(Form2.handle, FormRegion, true);
X1 := X1 - Form3.Left;
Y1 := Y1 - Form3.Top;
X2 := X2 - Form3.Left;
Y2 := Y2 - Form3.Top;
FormRegion := CreateRectRgn(0, 0, Form3.Width, Form3.Height);
HoleRegion := CreateRectRgn(X1, Y1, X2, Y2);
CombineRgn(FormRegion, FormRegion, HoleRegion, RGN_DIFF);
SetWindowRgn(Form3.handle, FormRegion, true);
编辑
您的 Server.Form2
与屏幕尺寸不同(因此 Client.Form2
)似乎违反直觉。但也许我从来没有真正理解设置的实际用途。
无论如何,如果 Form3
的大小相同,居中,但服务器和客户端的屏幕尺寸不同,您需要将客户端的 Form3.Hole
坐标调整为一半的差异服务器和客户端屏幕范围,或者,由于 Form3
表格居中,您可以像
一样计算水平和垂直校正
ResolutionCorrectionX := Server.Form3.Left - Client.Form3.Left;
ResolutionCorrectionY := Server.Form3.Top - Client.Form3.Top;
然后添加到 Form3 HoleRegion
的 X 和 Y 坐标。
X1 := X1 - Form3.Left + ResolutionCorrectionX; // and similar for X2, Y1 and Y2
顺便说一句,出于好奇,您为什么使用 Round()
进行基于整数的计算?
我有以下代码,想根据在服务器端绘制的区域,在远程屏幕(客户端)的两个表单中绘制相同的孔。
我在两侧(服务器和客户端)都有相同的表单 (Form3),这是一个 "mirror",我在其中绘制了一个必须留在内部的区域在客户端使用相同的表格。
The Form3 in server side have 50% of max
AlphaBlend
value, this is necessary to see remote screen behind Form3.
Before all, i want say that i'm receiving the remote screen on server side and and mouse click positions works like expected.
那我就麻烦了:
以下代码产生上图所示的结果。我认为这段代码是正确的,但缺少将此孔与 Form3.
对齐有人可以帮忙吗?抱歉,如果这是一个糟糕的问题,但这是我真正的麻烦,我尝试用我能做到的更好的方式表达这个问题中的所有内容。
这是所有相关代码:
服务器端:
Form2(我看到远程屏幕的地方):
unit Unit2;
interface
uses
Unit1;
type
TForm2 = class(TForm)
Panel1: TPanel;
CheckBox1: TCheckBox;
ScrollBox1: TScrollBox;
Image1: TImage;
PaintBox1: TPaintBox;
procedure PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure PaintBox1MouseMove(Sender: TObject; Shift: TShiftState;
X, Y: Integer);
procedure PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure PaintBox1Paint(Sender: TObject);
private
{ Private declarations }
FSelecting: Boolean;
FSelection: TRect;
pos1, pos2, pos3, pos4: Integer;
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
procedure TForm2.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if CheckBox1.Checked then
begin
FSelection.Left := X;
FSelection.Top := Y;
FSelecting := true;
end;
end;
procedure TForm2.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState;
X, Y: Integer);
begin
if FSelecting then
begin
FSelection.Right := X;
FSelection.Bottom := Y;
pbRec.Invalidate;
end;
end;
procedure TForm2.PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if CheckBox1.Checked then
begin
FSelecting := false;
FSelection.Right := X;
FSelection.Bottom := Y;
PaintBox1.Invalidate;
FSelection.NormalizeRect;
if FSelection.IsEmpty then
begin
// None selection was made on PaintBox
end
else
begin
pos1 := FSelection.Left;
pos2 := FSelection.Top;
pos3 := X;
pos4 := Y;
end;
end;
end;
procedure TForm2.PaintBox1Paint(Sender: TObject);
begin
if CheckBox1.Checked then
begin
PaintBox1.Canvas.Brush.Style := bsClear;
PaintBox1.Canvas.Pen.Style := psSolid;
PaintBox1.Canvas.Pen.Color := clRed;
PaintBox1.Canvas.Rectangle(FSelection);
end;
end;
procedure TForm2.Button1Click(Sender: TObject);
var
Socket: TCustomWinSocket;
begin
Socket := TCustomWinSocket(Form1.LV1.Selected.SubItems.Objects[0]);
if CheckBox1.Checked then
begin
Socket.SendText(intToStr(pos1) + ';' + intToStr(pos2) + ';' +
intToStr(pos3) + ';' + intToStr(pos4));
end;
end;
procedure TForm2.Button2Click(Sender: TObject);
begin
Form3 := TForm3.Create(Self);
Form3.Show;
end;
Form2 .DFM:
object Panel1: TPanel
Left = -1
Top = 0
Width = 773
Height = 89
Anchors = [akTop]
BevelEdges = [beLeft, beRight]
ParentDoubleBuffered = False
TabOrder = 0
end
object ScrollBox1: TScrollBox
Left = 0
Top = 0
Width = 765
Height = 472
HorzScrollBar.Smooth = True
HorzScrollBar.Tracking = True
VertScrollBar.Smooth = True
VertScrollBar.Tracking = True
Align = alClient
TabOrder = 1
object Image1: TImage
Left = 0
Top = 0
Width = 1362
Height = 621
AutoSize = True
end
object PaintBox1: TPaintBox
Left = 0
Top = 0
Width = 1362
Height = 621
Align = alClient
OnMouseDown = PaintBox1MouseDown
OnMouseMove = PaintBox1MouseMove
OnMouseUp = PaintBox1MouseUp
OnPaint = PaintBox1Paint
ExplicitWidth = 1364
ExplicitHeight = 622
end
Form3(在客户端也是一样的"mirror"Form),这个Form根据远程屏幕分辨率集中:
unit Unit3;
interface
uses
...
type
TForm3 = class(TForm)
Panel1: TPanel;
Image1: TImage;
Label1: TLabel;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
procedure CreateParams(var pr: TCreateParams); override;
public
{ Public declarations }
end;
var
Form3: TForm3;
implementation
uses
Unit1;
{$R *.dfm}
procedure TForm3.FormCreate(Sender: TObject);
var
MyString: String;
Splitted: TArray<String>;
begin
MyString := Form1.LV1.Selected.SubItems[6]; // Resolution of remote screen
Splitted := MyString.Split(['x']);
Self.Left := (Integer(Splitted[0]) - Self.Width) div 2;
Self.Top := (Integer(Splitted[1]) - Self.Height) div 2;
end;
procedure TForm3.CreateParams(var pr: TCreateParams);
begin
inherited;
pr.WndParent := Form2.Handle;
pr.ExStyle := pr.ExStyle or WS_EX_TOPMOST or WS_EX_TRANSPARENT;
pr.ExStyle := WS_EX_TRANSPARENT or WS_EX_TOPMOST;
end;
Form3 .DFM:
object Form3: TForm3
Left = 328
Top = 143
BorderStyle = bsNone
ClientHeight = 567
ClientWidth = 526
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
Position = poScreenCenter
OnCreate = FormCreate
PixelsPerInch = 96
TextHeight = 13
object Panel1: TPanel
Left = 0
Top = 0
Width = 801
Height = 569
TabOrder = 0
object Image1: TImage
Left = 1
Top = 1
Width = 799
Height = 567
Align = alClient
ExplicitLeft = 2
ExplicitTop = 0
ExplicitHeight = 447
end
object Label1: TLabel
Left = 92
Top = 69
Width = 28
Height = 13
Caption = 'Nome'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
ParentColor = False
ParentFont = False
end
客户端:
Form2 ("locker" 表格):
unit Unit2;
private
{ Private declarations }
procedure CreateParams(var Params: TCreateParams); override;
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
procedure TForm2.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.WndParent := Application.Handle;
Params.ExStyle := Params.ExStyle or WS_EX_TOPMOST or WS_EX_TRANSPARENT;
Params.ExStyle := WS_EX_TRANSPARENT or WS_EX_TOPMOST;
end;
procedure TForm2.FormCreate(Sender: TObject);
begin
windowstate := wsmaximized;
Top := 0;
Left := 0;
Height := Screen.Height;
Width := Screen.Width;
end;
{
Properties of Form2:
Align => alNone
AlphaBlend => True
BorderStyle => BsNone
}
end.
Form3(服务器端相同):
unit Unit3;
interface
uses
...
type
TForm3 = class(TForm)
Panel1: TPanel;
Label1: TLabel;
procedure FormShow(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
procedure CreateParams(var pr: TCreateParams); override;
public
{ Public declarations }
end;
var
Form3: TForm3;
implementation
uses
Unit2;
{$R *.dfm}
procedure TForm3.FormCreate(Sender: TObject);
begin
Self.Left := (GetSystemMetrics(SM_CXSCREEN) - Self.Width) div 2;
Self.Top := (GetSystemMetrics(SM_CYSCREEN) - Self.Height) div 2;
end;
procedure TForm3.FormShow(Sender: TObject);
begin
ShowWindow(Application.Handle, SW_HIDE);
end;
procedure TForm3.CreateParams(var pr: TCreateParams);
begin
inherited;
pr.WndParent := Form2.Handle;
end;
{
Properties of Form3:
Align => alNone
BorderStyle => BsNone
}
end.
客户端接收区域:
procedure CS1_Read(Self: Pointer; Sender: TObject; Socket: TCustomWinSocket);
var
X1, X2, Y1, Y2: Integer;
List: TStrings;
FormRegion, HoleRegion: HRGN;
StrCommand: string;
begin
if Pos(';', StrCommand) > 0 then
begin
List := TStringList.Create;
try
ExtractStrings([';'], [], PChar(StrCommand), List);
Form3 := TForm3.Create(Form2); // The Form2 already was created and is showing
X1 := Round(StrToIntDef(List[0], 0) - Form2.Left);
Y1 := Round(StrToIntDef(List[1], 0) - Form2.Top);
X2 := Round(StrToIntDef(List[2], 0) - Form2.Left);
Y2 := Round(StrToIntDef(List[3], 0) - Form2.Top);
FormRegion := CreateRectRgn(0, 0, Form3.Width, Form3.Height);
HoleRegion := CreateRectRgn(X1, Y1, X2, Y2);
CombineRgn(FormRegion, FormRegion, HoleRegion, RGN_DIFF);
SetWindowRgn(Form3.handle, FormRegion, true);
FormRegion := CreateRectRgn(0, 0, Form2.Width, Form2.Height);
HoleRegion := CreateRectRgn(X1, Y1, X2, Y2);
CombineRgn(FormRegion, FormRegion, HoleRegion, RGN_DIFF);
SetWindowRgn(Form2.handle, FormRegion, true);
Form3.ShowModal;
Form3.Release;
finally
List.Free;
end;
end;
end;
在客户端,您有一个具有屏幕大小的半透明灰色表单 (Form2)。在该窗体之上,您有一个位于屏幕中心的不透明白色窗体 (Form3)。在 Form3
中,您在 Top = Y
和 Left = X
处有一个矩形孔,坐标为 Form3
.
我了解到您的问题是您想在 Form2 中绘制一个与 Form3 中的孔对齐的孔。
您需要将 Form3
的坐标系转换为 Form2
的坐标系,只需简单地添加:
Form2.Hole.Left := Form3.Left + Form3.Hole.Left;
Form2.Hole.Top := Form3.Top + Form3.Hole.Top;
这将使孔对齐。你似乎在你的计算中尝试了类似的东西,但你指的是 Form2.Left
和 Form2.Top
这是无用的,因为它们都是 0.
如果我误解了你的问题,而你实际上希望 Form3
孔与 Form2
孔对齐,那么你需要将 Form3
移动到左上角屏幕而不是居中 ...
... 或者,考虑您的评论:如果我在远离 Form3
(客户端)的区域的服务器端绘图,例如在屏幕左侧更多,请绘图只有 Form2
的孔,如果我在屏幕中间绘制更多,绘制对齐的两个孔 将通过简单地交换术语来完成:
Form3.Hole.Left := Form2.Hole.Left - Form3.Left
Form3.Hole.Top := Form2.Hole.Top - Form3.Top
这会将 Form2
坐标转换为 Form3
坐标,在您的例子中可能会变成负值(在表格之外)。
根据您的代码调整上述内容,您需要首先用收到的 Form2.Hole
坐标处理 Form2 区域 ,然后减去 Form3
坐标(Left
and Top
) from X1..Y2 and 然后处理Form3 region*.
X1 := Round(StrToIntDef(List[0], 0) - Form2.Left); // Form2 props can be removed as hardcoded to 0
Y1 := Round(StrToIntDef(List[1], 0) - Form2.Top); // -"-
X2 := Round(StrToIntDef(List[2], 0) - Form2.Left); // -"-
Y2 := Round(StrToIntDef(List[3], 0) - Form2.Top); // -"-
FormRegion := CreateRectRgn(0, 0, Form2.Width, Form2.Height);
HoleRegion := CreateRectRgn(X1, Y1, X2, Y2);
CombineRgn(FormRegion, FormRegion, HoleRegion, RGN_DIFF);
SetWindowRgn(Form2.handle, FormRegion, true);
X1 := X1 - Form3.Left;
Y1 := Y1 - Form3.Top;
X2 := X2 - Form3.Left;
Y2 := Y2 - Form3.Top;
FormRegion := CreateRectRgn(0, 0, Form3.Width, Form3.Height);
HoleRegion := CreateRectRgn(X1, Y1, X2, Y2);
CombineRgn(FormRegion, FormRegion, HoleRegion, RGN_DIFF);
SetWindowRgn(Form3.handle, FormRegion, true);
编辑
您的 Server.Form2
与屏幕尺寸不同(因此 Client.Form2
)似乎违反直觉。但也许我从来没有真正理解设置的实际用途。
无论如何,如果 Form3
的大小相同,居中,但服务器和客户端的屏幕尺寸不同,您需要将客户端的 Form3.Hole
坐标调整为一半的差异服务器和客户端屏幕范围,或者,由于 Form3
表格居中,您可以像
ResolutionCorrectionX := Server.Form3.Left - Client.Form3.Left;
ResolutionCorrectionY := Server.Form3.Top - Client.Form3.Top;
然后添加到 Form3 HoleRegion
的 X 和 Y 坐标。
X1 := X1 - Form3.Left + ResolutionCorrectionX; // and similar for X2, Y1 and Y2
顺便说一句,出于好奇,您为什么使用 Round()
进行基于整数的计算?