Recent

Author Topic: How to use a form as I/O device for a classical pascal program  (Read 2981 times)

Pieter

  • New Member
  • *
  • Posts: 23
I brought a classical Pascal program (no objects) to Lazarus 2.2.2, running on an Intel i5 laptop under Windows 11 Pro. It gets its user input and output by means of a window created by the WINAPI function CreateWindow and related WINAPI functions. In this way, the program can migrate to another OS by replacing these input and output functions.

I can't help you with your code, but if you want to migrate your program to another OS, why don't you just use Lazarus' forms? Then you don't have to change anything in your code. You just compile it in another OS, or you can also crosscompile to another OS.

Continuing your proposal, I made the following code, i.e. a classical console program including a form that should serve for the input and output.

Code: Pascal  [Select][+][-]
  1. {$APPTYPE CONSOLE}
  2. program FrmInCnsl;
  3.  
  4. {$mode objfpc}{$H+}
  5.  
  6. uses
  7.   {$IFDEF UNIX}
  8.   cthreads,
  9.   {$ENDIF}
  10.   Classes, Interfaces, // this includes the LCL widgetset
  11.   Forms, Windows, MyUnit1
  12.   { you can add units after this };
  13.  
  14. // {$R *.res}  not necessary?
  15. var
  16.   cont: boolean;
  17. begin
  18.   Application.Initialize;
  19.   writeln('Start');
  20.   Application.CreateForm(TForm1, Form1);
  21.   writeln('Form Created');
  22.   Form1.Show;
  23.   Form1.Canvas.TextOut(1,1,'My Text');
  24.   readln;
  25. end {main program}.
  26.  
  27.  
  28. {*** unit ***}  
  29. unit MyUnit1;
  30.  
  31. {$mode ObjFPC}{$H+}
  32.  
  33. interface
  34.  
  35. uses
  36.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs;
  37.  
  38. type
  39.  
  40.   { TForm1 }
  41.  
  42.   TForm1 = class(TForm)
  43.     procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  44.   private
  45.  
  46.   public
  47.  
  48.   end;
  49.  
  50. var
  51.   Form1: TForm1;
  52.  
  53. implementation
  54.  
  55. {$R *.lfm}
  56.  
  57. { TForm1 }
  58.  
  59. procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState
  60.   );
  61. begin
  62.   writeln('key:', Key:2);
  63. end;
  64.  
  65. end.
  66.    
  67.  


As you can see, output is not a problem but how can I make the form react to keystrokes? The form has the procedure FormKeyDown, which should do this. My problem is how to tell this to the form in a classical pascal program. So, a want a piece of code that transfers control from a classical main program to the form, that then waits for a keystroke. When the keystroke has happened, control give this result back to the place in the main program where the form was activated. Could anyone show me the way? Thanks.

dseligo

  • Hero Member
  • *****
  • Posts: 1668
Re: How to use a form as I/O device for a classical pascal program
« Reply #1 on: July 26, 2022, 12:27:40 pm »
Try to set KeyPreview property of form to True.

If it doesn't work, could you post complete test project here?

Roland57

  • Hero Member
  • *****
  • Posts: 578
    • msegui.net
Re: How to use a form as I/O device for a classical pascal program
« Reply #2 on: July 26, 2022, 01:07:19 pm »
Hello. Not exactly the answer to your question, but do you know InputBox and InputQuery functions?

You can call these functions from a console program. I have just tried (under Linux).

Just in case, here are two projects ready to compile, with the code examples from this page.

Regards.

Roland
My projects are on Codeberg.

Pieter

  • New Member
  • *
  • Posts: 23
Re: How to use a form as I/O device for a classical pascal program
« Reply #3 on: July 26, 2022, 01:27:11 pm »
Try to set KeyPreview property of form to True.

If it doesn't work, could you post complete test project here?

Thanks, dseligo, The KeyPreview property had no effect. I attached the zipped folder of the test project. Looking forward to your comments.

Pieter

  • New Member
  • *
  • Posts: 23
Re: How to use a form as I/O device for a classical pascal program
« Reply #4 on: July 26, 2022, 01:30:34 pm »
Hello. Not exactly the answer to your question, but do you know InputBox and InputQuery functions?

You can call these functions from a console program. I have just tried (under Linux).

Just in case, here are two projects ready to compile, with the code examples from this page.

Regards.

Roland

Thanks, Roland, this is too limited. IN a later stage, I also want to use the canvas of the form for graphical output.

Roland57

  • Hero Member
  • *****
  • Posts: 578
    • msegui.net
Re: How to use a form as I/O device for a classical pascal program
« Reply #5 on: July 26, 2022, 02:18:19 pm »
Another idea. We could create a window with ptcGraph. Example attached.  :)


My projects are on Codeberg.

Roland57

  • Hero Member
  • *****
  • Posts: 578
    • msegui.net
Re: How to use a form as I/O device for a classical pascal program
« Reply #6 on: July 26, 2022, 02:27:20 pm »
There is an interesting example (using LCL) here. Project attached.  :)
« Last Edit: July 26, 2022, 06:37:20 pm by Roland57 »
My projects are on Codeberg.

Pieter

  • New Member
  • *
  • Posts: 23
Re: How to use a form as I/O device for a classical pascal program
« Reply #7 on: July 26, 2022, 03:13:53 pm »
Another idea. We could create a window with ptcGraph. Example attached.  :)

Thanks, under windows, it does compile but I get the runtime error ' ... raised exception class TPTCError with message: cannot recycle because it is not already open'



Pieter

  • New Member
  • *
  • Posts: 23
Re: How to use a form as I/O device for a classical pascal program
« Reply #8 on: July 26, 2022, 03:17:28 pm »
There is an interesting example (using LCL) here. Project attached.  :)

Does compile correclty, but gives runtime error 'Failed to create win32 control, error: cannot find window class

Roland57

  • Hero Member
  • *****
  • Posts: 578
    • msegui.net
Re: How to use a form as I/O device for a classical pascal program
« Reply #9 on: July 26, 2022, 05:38:30 pm »
@Pieter

Sorry. Both programs work here (Linux 64).
My projects are on Codeberg.

Fred vS

  • Hero Member
  • *****
  • Posts: 3787
    • StrumPract is the musicians best friend
Re: How to use a form as I/O device for a classical pascal program
« Reply #10 on: July 26, 2022, 10:01:23 pm »
Hello:

For the fun and the game, here project using a msegui form compiled as library and the console app who loads that library and uses the exported methods.

The console app:
Code: Pascal  [Select][+][-]
  1. {$APPTYPE CONSOLE}
  2. program consform;
  3. {$ifdef FPC}{$mode objfpc}{$h+}{$endif}
  4.  
  5. uses
  6.  {$ifdef FPC}{$ifdef unix}cthreads,{$endif}{$endif}
  7.  dynlibs,Classes, ctypes, Math, sysutils;
  8.  
  9.  type
  10.   TformThread = class(TThread)
  11.     protected
  12.       procedure execute;
  13.       override;
  14.     public
  15.       constructor Create(CreateSuspended: boolean; AParent: TObject;
  16.                          Const StackSize: SizeUInt = DefaultStackSize); overload;  virtual;
  17.                          
  18.       procedure closelibform;  
  19.       procedure changetitlelibform;                  
  20.    end;
  21.  
  22.  
  23.  var
  24.    formThread : TformThread;
  25.    astr : string;
  26.    isworking : boolean = true;
  27.  
  28.  mainproc: procedure() ;cdecl;
  29.  closeform: procedure() ;cdecl;
  30.  changetitle: procedure(newtitle : string) ;cdecl;
  31.  
  32.  msegui_Handle:TLibHandle=dynlibs.NilHandle;
  33.  
  34. constructor TformThread.Create(CreateSuspended: boolean; AParent: TObject;
  35.                               Const StackSize: SizeUInt);
  36.                    
  37. begin
  38.   FreeOnTerminate := true;
  39.   inherited Create(CreateSuspended, StackSize);
  40. end;
  41.  
  42. procedure TformThread.closelibform;  
  43. begin
  44. closeform;
  45. end;
  46.  
  47. procedure TformThread.changetitlelibform;  
  48. begin
  49. changetitle('New title at ' + timetostr(now));
  50. end;
  51.  
  52. procedure TformThread.Execute;
  53. begin
  54.  mainproc;
  55. end;
  56.  
  57. begin
  58.  writeln('Start');
  59.  
  60.   //msegui_Handle :=DynLibs.SafeLoadLibrary('/home/fred/consoleform/mselibform.so');
  61.  
  62.  msegui_Handle :=DynLibs.SafeLoadLibrary('mselibform.dll');
  63.  Pointer(mainproc):=DynLibs.GetProcedureAddress(msegui_Handle,PChar('mainproc'));
  64.  Pointer(closeform):=DynLibs.GetProcedureAddress(msegui_Handle,PChar('closeform'));
  65.  Pointer(changetitle):=DynLibs.GetProcedureAddress(msegui_Handle,PChar('changetitle'));
  66.  
  67.  formThread := tformThread.Create(false,nil);
  68.  
  69.  writeln('Form Created');
  70.  
  71.   while isworking do
  72.  begin
  73.   writeln('Write something');
  74.   readln(astr);
  75.   writeln(astr+' was entered.');
  76.   writeln();
  77.  
  78.   if astr = 'changetitle' then
  79.  begin
  80.   changetitle('New title at ' + timetostr(now));
  81.  end;
  82.    
  83.  if astr = 'quit' then
  84.  begin
  85.   isworking := false;
  86.  end;
  87.    
  88. end;
  89. closeform;
  90.  
  91. formThread.terminate;
  92.  
  93.  writeln('Bye bye...');
  94.  
  95.   DynLibs.UnloadLibrary(msegui_Handle);
  96.   msegui_Handle:=DynLibs.NilHandle;
  97.  
  98. end.
  99.  

The form as library:
Code: Pascal  [Select][+][-]
  1. library mselibform;
  2. {$ifdef FPC}{$mode objfpc}{$h+}{$endif}
  3. uses
  4.  {$ifdef FPC}{$ifdef unix}cthreads,{$endif}{$endif}
  5.  msegui, msegraphics, msegraphutils, main;
  6.  
  7. procedure MainProc; cdecl;
  8. begin
  9.   application.createform(tmainfo,mainfo);
  10.   application.run;
  11. end;
  12.  
  13. procedure closeform; cdecl;
  14. begin
  15.   mainfo.destroy;
  16. end;
  17.  
  18. procedure changetitle(newtitle:string); cdecl;
  19. begin
  20.   mainfo.caption := newtitle;
  21. end;
  22.  
  23. procedure showform; cdecl;
  24. begin
  25.   mainfo.visible := true;
  26. end;
  27.  
  28. exports
  29.   {Here the only-one exported procedure...}
  30.   MainProc name 'mainproc',
  31.   closeform name 'closeform',
  32.   changetitle name 'changetitle',
  33.   showform name 'showform';
  34.  
  35. end.

And the code of the main form:
Code: Pascal  [Select][+][-]
  1. unit main;
  2. {$ifdef FPC}{$mode objfpc}{$h+}{$endif}
  3. interface
  4. uses
  5.  msetypes, mseglob, mseguiglob, mseguiintf, mseapplication, msestat, msemenus, msegui,
  6.  msegraphics, msegraphutils, mseevent, mseclasses, msewidgets, mseforms, msesysutils;
  7.  
  8. type
  9.  tmainfo = class(tmainform)
  10.    procedure onkey(const sender: twidget; var ainfo: keyeventinfoty);
  11.  end;
  12. var
  13.  mainfo: tmainfo;
  14. implementation
  15. uses
  16.  main_mfm;
  17.  
  18. procedure tmainfo.onkey(const sender: twidget; var ainfo: keyeventinfoty);
  19. begin
  20. debugwriteln('Form Key pressed = ' + ainfo.chars);
  21. end;
  22.  
  23. end.
  24.  


Here video of the thing in action:
https://user-images.githubusercontent.com/3421249/181095567-74942a28-fcf0-4620-adf1-6d344f2f392a.mp4

Here binay of the app and the library for windows. (of course it works for Linux too)
https://github.com/mse-org/mseide-msegui/files/9192967/consoleform-windows.zip

In attachment, source of the project.
« Last Edit: July 27, 2022, 01:08:35 am by Fred vS »
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

Pieter

  • New Member
  • *
  • Posts: 23
Re: How to use a form as I/O device for a classical pascal program
« Reply #11 on: July 27, 2022, 02:00:05 pm »
Hello:

For the fun and the game, here project using a msegui form compiled as library and the console app who loads that library and uses the exported methods.
[LEFT OUT]
Here video of the thing in action:
https://user-images.githubusercontent.com/3421249/181095567-74942a28-fcf0-4620-adf1-6d344f2f392a.mp4

Here binay of the app and the library for windows. (of course it works for Linux too)
https://github.com/mse-org/mseide-msegui/files/9192967/consoleform-windows.zip

In attachment, source of the project.

Thanks, Fred, very interesting. A couple of questions:
What do I have to do to compile the source files, including the library?
What are the basic functions/methods available for the form?
Is this all open source?

Fred vS

  • Hero Member
  • *****
  • Posts: 3787
    • StrumPract is the musicians best friend
Re: How to use a form as I/O device for a classical pascal program
« Reply #12 on: July 27, 2022, 02:34:32 pm »
What do I have to do to compile the source files, including the library?
What are the basic functions/methods available for the form?
Is this all open source?

Hello Pieter:

To (easy) compile the sources that are all open source you need:

- The Free Pascal Compiler to compile all the souce.

- The MSEgui source.

- A ide to easy compie MSEgui projects, there is MSEide and ideU.

All the mehods used in the lib-form are provided by the MSEgui source.

Fre;D
« Last Edit: July 27, 2022, 02:45:18 pm by Fred vS »
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

Pieter

  • New Member
  • *
  • Posts: 23
Re: How to use a form as I/O device for a classical pascal program
« Reply #13 on: July 27, 2022, 02:47:08 pm »
What do I have to do to compile the source files, including the library?
What are the basic functions/methods available for the form?
Is this all open source?

Hello Pieter:

To (easy) compile the sources that are all open source you need:

- The Free Pascal Compiler to compile all the souce.

- The MSEgui source.

- A ide to easy compie MSEgui projects, there is MSEide and ideU.

All the mehods used in he lib-form are provided by the MSEgui source.

Fre;D

Thanks for the quick answer, Fred. How can I use Lazarus for the compilation of MSEgui projects?

Fred vS

  • Hero Member
  • *****
  • Posts: 3787
    • StrumPract is the musicians best friend
Re: How to use a form as I/O device for a classical pascal program
« Reply #14 on: July 27, 2022, 03:05:43 pm »
How can I use Lazarus for the compilation of MSEgui projects?

Sorry, I dont know, I never try this.  :-[
Maybe somebody knows how to translate a MSEgui .prj into a Lazarus .lpi project and will be welome to explain us how to do.

[EDIT:] It should be easy to translate a MSE prj projet into a Lazarus lpi but the form designer of Lazarus will not be able to render the MSEgui forms. But compilation + debug should be OK.

(I know the reverse, how to translate a .lpi project into a .prj project, ready to use for MSEide or ideU.)

Fre;D
« Last Edit: July 27, 2022, 03:12:52 pm by Fred vS »
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

 

TinyPortal © 2005-2018