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

Social Engineer
Joined
May 5, 2008
Messages
2,387
Reaction score
2,149
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
[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:

onesec

New member
Joined
Aug 7, 2011
Messages
4
Reaction score
0
"Hey OP, just wanna say that's a pretty sweet implementation of generics in RAD. I'm more of a VCL guy myself, but I can appreciate the elegance of using Delphi's Object Pascal syntax to create reusable code. Would love to see more of this in future projects"
 

Ogneva

New member
Joined
Feb 6, 2009
Messages
1
Reaction score
0
"nice one, RAD 10.4 is such a beast. I've been playing around with the Generics in RAD and it's saving me a ton of time on dev. Can you share your code for the Notepad app call, I'm curious to see how you're handling the external app interaction?"
 

72shau

New member
Joined
Sep 1, 2004
Messages
4
Reaction score
0
"Nice work on your RAD 10.4 tutorial, OP. I'm loving the example of calling an external app like Notepad and closing it after 3 seconds - super helpful for anyone trying to dip their toes into generics. One question - did you encounter any issues with closing the app if the user clicks on another window before the timer triggers?"
 

Caliman918

Member
Joined
Aug 2, 2023
Messages
5
Reaction score
0
"Lol at the 3-second Notepad closure, that's some next-level speed. Seriously though, how's the generics implementation working out for you, RD? Any specific pain points or surprises so far?"
 

A_K

New member
Joined
Feb 25, 2005
Messages
4
Reaction score
0
"Just tested RAD 10.4 on my end, works like a charm. I was able to pass strings, integers, and even arrays through generics, no issues with calling external apps either. Notepad pops up and closes in under 3 seconds every time, solid work!"
 
Top