Source Code RAD 10.4 - my sample Create and Using Generics of various Type include calling External app (Notepad) do show resulted and close it in 3 seconds

emailx45

Бывалый
Staff member
Moderator
RAD 10.4 - my sample Create and Using Generics of various Type include calling External app (Notepad) do show resulted and close it in 3 seconds
scenary:
  • MSWindows 10 Enterprise 64bits in VirtualBox VM (with 3GB + 2 vCPU)
  • RAD Studio 10.4 SADness (9797) full installed
  • Console 32bits project
pastedimage1595199304092v1.png
[SHOWTOGROUPS=4,20]

Code:
program prjCON_Generics_Constructor_to_Integer_Type;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.Classes,
  System.SysUtils,
  Winapi.Windows,
  Winapi.Messages,
  ShellApi,
  VCL.Dialogs;

type
  // TData = record
  // Value: Integer;
  // end;

  TSomeClass<T: constructor> = class
  class var
    FValue: T;
    function GetGeneric: T;
    constructor Create;
  end;

  //
  TMyGroup = class
  private
    FName : string;
    FValue: string;
    function GetFValue: string;
    procedure SetFValue(const Value: string);
  published
    property name     : string read FName write FName;
    property somevalue: string read GetFValue write SetFValue;
  public
    constructor Create;
    destructor Destroy;
  end;

constructor TSomeClass<T>.Create;
begin
  inherited Create;
  FValue := T.Create; // constructor default because <T:Constructor> definition above!
end;

function TSomeClass<T>.GetGeneric: T;
begin
  Result := FValue;
end;

{ TMyGroup }

constructor TMyGroup.Create;
begin
  inherited Create;
end;

destructor TMyGroup.Destroy;
begin
  inherited Destroy;
end;

function TMyGroup.GetFValue: string;
begin
  Result := FValue;
end;

procedure TMyGroup.SetFValue(const Value: string);
begin
  if not(FValue = Value) then
    FValue := Value;
end;

// --------------------------------------------
var
  someClassT1: TSomeClass<Integer>;
  someClassT2: TSomeClass<string>;
  someClassT3: TSomeClass<Double>;
  someClassT4: TSomeClass<TDateTime>;
  someClassT5: TSomeClass<TMyGroup>;
  //
  i                  : Integer;
  lClassName         : string;
  lMyFileOutPut      : TextFile;
  lWinExecReturn     : Cardinal;
  lMyFindWindowReturn: HWND;
  lPostMessageReturn : LongBool;

procedure prcWaitMeSeeTheResulted(lCommandLineAndParam: PAnsiChar; lFindWindowText: PWideChar);
begin
  // ShellExecute(0, nil, 'MyFileOutPut.txt', nil, nil, SW_SHOWNORMAL);
  //
  lWinExecReturn := WinExec(lCommandLineAndParam, SW_SHOW);
  // ShowMessage('let me see it'); // more easy :)
  //
  if (lWinExecReturn > 0) then
    Sleep(10000); // thread main in wait mode...
  //
  lMyFindWindowReturn := FindWindow(nil, lFindWindowText);
  //
  if (lMyFindWindowReturn > 0) then
    lPostMessageReturn := PostMessage(lMyFindWindowReturn, WM_CLOSE, 0, 0);
  //
  // if (lMyFindWindowReturn > 0) then
  // BringWindowToTop(lMyFindWindowReturn);
end;

begin
  //
  ReportMemoryLeaksOnShutdown := true;
  //
  AssignFile(lMyFileOutPut, 'MyFileOutPut.txt');
  Rewrite(lMyFileOutPut);
  //
  try
    try
      someClassT1        := TSomeClass<Integer>.Create;
      someClassT1.FValue := 1234;
      i                  := someClassT1.GetGeneric;
      WriteLn(lMyFileOutPut, 'my i value: ', i);
      //
      someClassT2        := TSomeClass<string>.Create;
      someClassT2.FValue := '-1234-';
      i                  := StrToIntDef(someClassT2.GetGeneric, -9);
      WriteLn(lMyFileOutPut, 'my i value: ', i);
      //
      someClassT3        := TSomeClass<Double>.Create;
      someClassT3.FValue := 5.1234;
      { Round() = see TRoundingMode modes / exception = EInvalidOp = out limits }
      i := Round(someClassT3.GetGeneric);
      WriteLn(lMyFileOutPut, 'my i value: ', i);
      //
      someClassT4        := TSomeClass<TDateTime>.Create;
      someClassT4.FValue := now;
      i                  := Round(someClassT4.GetGeneric);
      WriteLn(lMyFileOutPut, 'my i value: ', i);
      //
      someClassT5             := TSomeClass<TMyGroup>.Create;
      someClassT5.FValue.name := 'Hello World';
      //
      someClassT5.FValue.somevalue := someClassT1.ClassName;
      WriteLn(lMyFileOutPut, 'my i value: ', i, ' ', someClassT5.FValue.name, ' ', someClassT5.FValue.somevalue);
      //
      someClassT5.FValue.somevalue := someClassT2.ClassName;
      WriteLn(lMyFileOutPut, 'my i value: ', i, ' ', someClassT5.FValue.name, ' ', someClassT5.FValue.somevalue);
      //
      someClassT5.FValue.somevalue := someClassT3.ClassName;
      WriteLn(lMyFileOutPut, 'my i value: ', i, ' ', someClassT5.FValue.name, ' ', someClassT5.FValue.somevalue);
      //
      someClassT5.FValue.somevalue := someClassT4.ClassName;
      WriteLn(lMyFileOutPut, 'my i value: ', i, ' ', someClassT5.FValue.name, ' ', someClassT5.FValue.somevalue);
      //
      someClassT5.FValue.somevalue := someClassT5.ClassName;
      WriteLn(lMyFileOutPut, 'my i value: ', i, ' ', someClassT5.FValue.name, ' ', someClassT5.FValue.somevalue);
      //
      // causing the AV ... :)))  i'm bad-guy!
      //
      someClassT1.FValue := StrtoInt('a1234');
      i                  := someClassT1.GetGeneric;
      WriteLn(lMyFileOutPut, 'my i value: ', i);
      //
    except
      on E: Exception do
        WriteLn(lMyFileOutPut, E.ClassName, ': ', E.Message);
    end;
  finally
    CloseFile(lMyFileOutPut);
    //
    if not(someClassT5.FValue = nil) then // free my TGroup class if necessary to avoid leak memory
    begin
      someClassT5.FValue.Free;
      //
      ShowMessage('Free my someClassT5.FValue = TGroup created');
    end;
    //
    if FileExists('MyFileOutPut.txt') then
      prcWaitMeSeeTheResulted(              { }
        'notepad.exe MyFileOutPut.txt',     { app.exe param }
        'MyFileOutPut.txt - Bloco de Notas' { filename.ext - Notepad }
        );
    //
  end;

end.
[/SHOWTOGROUPS]
 
Last edited:
Top