Jump to content
flashcoder

How align a same form in client side and server side respectively?

Recommended Posts

My project is a remote administration tool where i have a same Form in client and server. The form on server side is a "mirror" that is useful to i draw two aligned holes in client side, this Form is centralized according client screen resolution. These holes in client side are made: one in a "locker form" in fullscreen (that have a screenshot of desktop in grayscale) and other made on Form that is the same that have on server (like said above, the "mirror"), the owner of this Form is the "locker form".

 

This explanation above can be better expressed by image attached.

 

Then my trouble here not is to align these holes (in client and server) and yes align the Forms ("mirror" Form of server side and your clone in client side), like you can see on image above, the "mirror" Form (on server side) is showed more to top of screen while your clone (on client side) is showed more below when both are compared.

Like you also saw on image above, exists a ScrollBox component on server, then in my tests if i adjust scrolling (manually) to down this can align both Forms ("mirror" Form on server and your clone on client). But will be that exists something that can align automatcally using Delphi code?

 

Code example to better understand this trouble:

 

SERVER SIDE:

 

  • "Form2" (where is displayed the remote screen in a Image component) =>

 

unit Unit2;

interface

uses
  Unit3;

type
  TForm2 = class(TForm)
    Panel1: TPanel;
    ScrollBox1: TScrollBox;
    Image1: TImage;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

// Button1 can stay on Panel1
procedure TForm2.Button1Click(Sender: TObject);
begin
  Form3 := TForm3.Create(Self);
  Form3.AlphaBlendValue := 127;
  Form3.Show;
end;

 

.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

 

  • "Form3" (the "mirror Form" semitransparent to be possible see remote screen behind) =>

 

unit Unit3;

interface

uses .. .

  type TForm3 = class
  (TForm) procedure FormCreate(Sender: TObject);
private
  { Private declarations }
  procedure CreateParams(var pr: TCreateParams);
  override;
public
  { Public declarations }
  end;

var
  Form3: TForm3;

implementation

uses
  Unit1, Unit2;

{$R *.dfm}

procedure TForm3.FormCreate(Sender: TObject);
var
  MyString: String;
  Splitted: TArray<String>;
begin
  MyString := Form1.ListView1.Selected.SubItems[6]; // Resolution of remote screen
  Splitted := MyString.Split(['x']);

  Left := (Integer(Splitted[0]) - Width) div 2;
  Top := (Integer(Splitted[1]) - 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;

 

.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

 

CLIENT SIDE:

 

  • "Form2" (Form "locker screen") =>

 

unit Unit2;

interface

uses
 ...

type
  TForm2 = class(TForm)
  Image1: TImage;
  procedure FormShow(Sender: TObject);

  private
    { Private declarations }
    procedure CreateParams(var Params: TCreateParams); override;

  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

procedure GetGrayscaleOf(ASrc, AGray: TBitmap);
var
  x, y: Integer;
  vLineSrc: PRGBTriple;
  vLineGray: PRGBTriple;
  vGrayValue: Byte;
begin

  ASrc.PixelFormat := pf24bit;
  AGray.PixelFormat := pf24bit;

  AGray.Width := ASrc.Width;
  AGray.Height := ASrc.Height;

  for y := 0 to AGray.Height - 1 do
  begin

    vLineSrc := ASrc.ScanLine[y];
    vLineGray := AGray.ScanLine[y];

    for x := 0 to AGray.Width - 1 do
    begin

      vGrayValue := Round(0.3 * vLineSrc^.rgbtRed + 0.59 * vLineSrc^.rgbtGreen +
        0.11 * vLineSrc^.rgbtBlue);

      vLineGray^.rgbtRed := vGrayValue;
      vLineGray^.rgbtGreen := vGrayValue;
      vLineGray^.rgbtBlue := vGrayValue;

      Inc(vLineSrc);
      Inc(vLineGray);
    end;
  end;
end;

procedure ColorGray;
var
  vSrc: TBitmap;
  vGray: TBitmap;
begin
  if Image1.Picture.Graphic = nil then
    Exit;

  vSrc := TBitmap.Create;
  try

    vSrc.PixelFormat := pf24bit;

    vSrc.Width := Image1.Picture.Graphic.Width;
    vSrc.Height := Image1.Picture.Graphic.Height;
    vSrc.Canvas.Draw(0, 0, Image1.Picture.Graphic);

    vGray := TBitmap.Create;
    try
      GetGrayscaleOf(vSrc, vGray);

      Image1.Picture.Graphic := vGray;
    finally
      vGray.Free;
    end;
  finally
    vSrc.Free;
  end;
end;

function CaptureScreen: TBitmap;
var
  dc: HDC;
  BMP: TBitmap;
  cv: TCanvas;
begin
   BMP:= TBitmap.Create;
   BMP.Width:= Screen.Width;
   BMP.Height:= Screen.Height;
   dc:= GetDC(0);
   cv:= TCanvas.Create;
   cv.Handle:= dc;
   BMP.Canvas.CopyRect(Rect(0,0,Screen.Width,Screen.Height),
   cv,Rect(0,0,Screen.Width,Screen.Height));
   Result:= BMP;
   cv.Free;
   ReleaseDC(0,dc);
end;

procedure TForm2.FormShow(Sender: TObject);
begin
  Image1.Picture.Assign(CaptureScreen);
  ColorGray;
end;

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;

{

Properties of Form2:

Align => alNone
AlphaBlend => True
BorderStyle => BsNone
WindowState => wsmaximized

---------------------------

Image1:

Align => alNone
AutoSize => True

}

 

  • "Form3" (the same "Form3" of server) =>

 

unit Unit3;

interface

uses
 ...

type
  TForm3 = class(TForm)
    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
  Left := (GetSystemMetrics(SM_CXSCREEN) - Width) div 2;
  Top := (GetSystemMetrics(SM_CYSCREEN) - Height) div 2;
end;

procedure TForm3.CreateParams(var pr: TCreateParams);
begin
  inherited;
  pr.WndParent := Form2.Handle;
end;

{

Properties of Form3:

Align => alNone
BorderStyle => BsNone

}

 

form.png

Share this post


Link to post

Wouldn't it be easier to render everything on the client side and just transfer the data needed from the server? Some form of JSON should suffice. All controls and their states should be listed and you can build the form accordingly. The hardest part would be the communication between client and server.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×