Recent

Author Topic: [SOLVED] Pass parameter to function without using global variable  (Read 3334 times)

pcurtis

  • Hero Member
  • *****
  • Posts: 951
I have this function :

Code: Pascal  [Select][+][-]
  1. function EnumWindowsProc(hWnd: HWND; {%H-}lParam: LPARAM): bool; stdcall;
  2. var
  3.   Title: array[0..255] of Char;
  4. begin
  5.   GetWindowText(hWnd, Title, 255);
  6.   if (IsWindowVisible(hWnd)) and (pos('JPEGView', Title) <> 0) then
  7.       AHandle := hWnd;
  8.   Result := True;
  9. end;
  10.  
  11. function GetJPGViewHandle : hWnd;
  12. begin
  13.   AHandle := 0;
  14.   EnumWindows(@EnumWindowsProc, 0);
  15.   Result := AHandle;
  16. end;
  17.  

I would like to pass a parameter (string) like this

function EnumWindowsProc(hWnd: HWND; {%H-}lParam: LPARAM): bool; stdcall;
var
  Title: array[0..255] of Char;
begin
  GetWindowText(hWnd, Title, 255);
  if (IsWindowVisible(hWnd)) and (pos(AValue, Title) <> 0) then
      AHandle := hWnd;
  Result := True;
end;

function GetJPGViewHandle(Avalue : string) : hWnd;
begin
  AHandle := 0;
  EnumWindows(@EnumWindowsProc, 0);
  Result := AHandle;
end;

withput using global variables. How can I do that?
« Last Edit: May 23, 2021, 05:43:41 am by pcurtis »
Windows 10 20H2
Laz 2.2.0
FPC 3.2.2

Zvoni

  • Hero Member
  • *****
  • Posts: 2330
Re: Pass parameter to function without using global variable
« Reply #1 on: May 21, 2021, 01:05:52 pm »
What i could find out, apparantly it's possible to use a nested function as a callback.
So in your case: Try it by nesting EnumWindowsProc within GetJPGViewHandle, and there you should be able to access your AValue-Argument
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

MarkMLl

  • Hero Member
  • *****
  • Posts: 6692
Re: Pass parameter to function without using global variable
« Reply #2 on: May 21, 2021, 01:16:44 pm »
What i could find out, apparantly it's possible to use a nested function as a callback.

Although I think that was added comparatively recently and might be mode-specific.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

pcurtis

  • Hero Member
  • *****
  • Posts: 951
Re: Pass parameter to function without using global variable
« Reply #3 on: May 21, 2021, 01:20:36 pm »
When I nest I can't reference the callback function

EnumWindows(@EnumWindowsProc, 0); fails

Dumb question - How can I update FPC, without updating Lazarus
« Last Edit: May 21, 2021, 01:25:05 pm by pcurtis »
Windows 10 20H2
Laz 2.2.0
FPC 3.2.2

440bx

  • Hero Member
  • *****
  • Posts: 4065
Re: Pass parameter to function without using global variable
« Reply #4 on: May 21, 2021, 01:30:35 pm »
I would like to pass a parameter (string) like this
Code: Pascal  [Select][+][-]
  1. function EnumWindowsProc(hWnd: HWND; {%H-}lParam: LPARAM): bool; stdcall;
  2. var
  3.   Title: array[0..255] of Char;
  4. begin
  5.   GetWindowText(hWnd, Title, 255);
  6.   if (IsWindowVisible(hWnd)) and (pos(AValue, Title) <> 0) then
  7.       AHandle := hWnd;
  8.   Result := True;
  9. end;
  10.  
  11. function GetJPGViewHandle(Avalue : string) : hWnd;
  12. begin
  13.   AHandle := 0;
  14.   EnumWindows(@EnumWindowsProc, 0);
  15.   Result := AHandle;
  16. end;
  17.  

withput using global variables. How can I do that?
I'm not completely sure this is what you want but, the following wouldn't require a global variable
Code: Pascal  [Select][+][-]
  1. function EnumWindowsProc(hWnd: HWND; {%H-}lParam: LPARAM): bool; stdcall;
  2. var
  3.   Title: array[0..255] of Char;
  4.  
  5.   MyBuffer : { whatever type is convenient here } absolute lparam;
  6.  
  7. begin
  8.   GetWindowText(hWnd, Title, 255);
  9.   if (IsWindowVisible(hWnd)) and (pos(AValue, Title) <> 0) then
  10.       AHandle := hWnd;
  11.  
  12.   { put whatever you want in MyBuffer and the calling function will have access to it }
  13.  
  14.   Result := True;
  15. end;
  16.  
  17. function GetJPGViewHandle(Avalue : string) : hWnd;
  18. var
  19.   BufferForEnumWindowsProc : packed array[0..8191] of char; { just some memory block }
  20.  
  21. begin
  22.   AHandle := 0;
  23.   EnumWindows(@EnumWindowsProc, @BufferForEnumWindowsProc);
  24.   Result := AHandle;
  25. end;
  26.  
  Note that the above just shows the concept.  You'll need declare the buffer and its type in accordance with what you need to do with the information you intend to gather.

Essentially, you allocate the buffer locally and pass a pointer to it to the enumwindows callback which supposedly will fill the buffer with whatever information the caller is interested in.

HTH.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

pcurtis

  • Hero Member
  • *****
  • Posts: 951
Re: Pass parameter to function without using global variable
« Reply #5 on: May 21, 2021, 01:54:19 pm »
I need it the other way round. Pass a string to the callback.
Windows 10 20H2
Laz 2.2.0
FPC 3.2.2

440bx

  • Hero Member
  • *****
  • Posts: 4065
Re: Pass parameter to function without using global variable
« Reply #6 on: May 21, 2021, 02:03:48 pm »
I need it the other way round. Pass a string to the callback.
In that case, instead of the caller passing a buffer, it passes a string (more accurately, pointer to a string.)
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

Zvoni

  • Hero Member
  • *****
  • Posts: 2330
Re: Pass parameter to function without using global variable
« Reply #7 on: May 21, 2021, 02:21:44 pm »
What i could find out, apparantly it's possible to use a nested function as a callback.

Although I think that was added comparatively recently and might be mode-specific.

MarkMLl

You might be right. The sample i found was on a german Delphi-Forum from 2018

Soooo.... --> mode delphi?

EDIT: Hmmm....
http://free-pascal-general.1045716.n5.nabble.com/Callbacks-as-nested-functions-td5730116.html
Look at post 5 of Matthias
« Last Edit: May 21, 2021, 02:25:42 pm by Zvoni »
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

MarkMLl

  • Hero Member
  • *****
  • Posts: 6692
Re: Pass parameter to function without using global variable
« Reply #8 on: May 21, 2021, 02:41:07 pm »
http://free-pascal-general.1045716.n5.nabble.com/Callbacks-as-nested-functions-td5730116.html
Look at post 5 of Matthias

Specifically, and in order for info to be in one place if somebody gets here via Google etc., the directive near the start of the example below:

Code: Pascal  [Select][+][-]
  1. program test1;
  2.  
  3. {$mode objfpc}{$H+}
  4. {$ModeSwitch nestedprocvars}
  5.  
  6. type
  7.   TCallback = procedure (a: integer) is nested;
  8.  
  9. procedure DoCallback;
  10.   procedure DoThis(a: integer);
  11.   begin
  12.     writeln(a);
  13.   end;
  14. var
  15.   callback: TCallback;
  16. begin
  17.   callback := @DoThis;
  18.   callback(100);
  19. end;
  20.  
  21. begin
  22.   DoCallback;
  23. end.
  24.  
  25. // Keep in mind what Sven wrote. You cannot use "callback" outside of
  26. // DoCallBack, because FPC does not yet support Delphi's "reference to".
  27.  

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

pcurtis

  • Hero Member
  • *****
  • Posts: 951
Re: Pass parameter to function without using global variable
« Reply #9 on: May 21, 2021, 02:54:11 pm »
I'm not a hardcore programmer.

I can't see  how to apply this to my code.
Windows 10 20H2
Laz 2.2.0
FPC 3.2.2

PascalDragon

  • Hero Member
  • *****
  • Posts: 5486
  • Compiler Developer
Re: Pass parameter to function without using global variable
« Reply #10 on: May 21, 2021, 04:54:23 pm »
I have this function :

Code: Pascal  [Select][+][-]
  1. function EnumWindowsProc(hWnd: HWND; {%H-}lParam: LPARAM): bool; stdcall;
  2. var
  3.   Title: array[0..255] of Char;
  4. begin
  5.   GetWindowText(hWnd, Title, 255);
  6.   if (IsWindowVisible(hWnd)) and (pos('JPEGView', Title) <> 0) then
  7.       AHandle := hWnd;
  8.   Result := True;
  9. end;
  10.  
  11. function GetJPGViewHandle : hWnd;
  12. begin
  13.   AHandle := 0;
  14.   EnumWindows(@EnumWindowsProc, 0);
  15.   Result := AHandle;
  16. end;
  17.  

I would like to pass a parameter (string) like this

function EnumWindowsProc(hWnd: HWND; {%H-}lParam: LPARAM): bool; stdcall;
var
  Title: array[0..255] of Char;
begin
  GetWindowText(hWnd, Title, 255);
  if (IsWindowVisible(hWnd)) and (pos(AValue, Title) <> 0) then
      AHandle := hWnd;
  Result := True;
end;

function GetJPGViewHandle(Avalue : string) : hWnd;
begin
  AHandle := 0;
  EnumWindows(@EnumWindowsProc, 0);
  Result := AHandle;
end;

withput using global variables. How can I do that?

As I had explained here in the other thread you can pass parameters through the lParam parameter of EnumWindows. As you should also get rid of the AHandle you can use a record:

Code: Pascal  [Select][+][-]
  1. type
  2.   TParamRec = record
  3.     handle: HWND;
  4.     title: String;
  5.   end;
  6.   PParamRec = ^TParamRec;
  7.  
  8. function EnumWindowsProc(hWnd: HWND; lParam: LPARAM): bool stdcall;
  9. var
  10.   Title: array[0..255] of Char;
  11.   args: PParamRec absolute lParam;
  12. begin
  13.   GetWindowText(hWnd, Title, 255);
  14.   if (IsWindowVisible(hWnd)) and (pos(args^.title, Title) <> 0) then
  15.       args^.handle := hWnd;
  16.   Result := True;
  17. end;
  18.      
  19. function GetJPGViewHandle(const aValue: String) : hWnd;
  20. var
  21.   args: TParamRec;
  22. begin
  23.   args.title := aValue;
  24.   args.handle := 0;
  25.   EnumWindows(@EnumWindowsProc, LPARAM(@args));
  26.   Result := args.handle;
  27. end;

pcurtis

  • Hero Member
  • *****
  • Posts: 951
Re: Pass parameter to function without using global variable
« Reply #11 on: May 21, 2021, 05:09:21 pm »
Thanks again.
Windows 10 20H2
Laz 2.2.0
FPC 3.2.2

 

TinyPortal © 2005-2018