2

Whenever I had to use API callbacks, like with EnumChildWindows, I typically wrote them like this:

procedure TMyClass.FindChildWindowAndDoSomething(
        AParent: HWND; 
        ASomeCriterion: Integer; 
  const AData: Pointer);
type
  TEnumWndParam = record
    Criterion: Integer;
    Data: Pointer;
  end;
  PEnumWndParam  = ^TEnumWndParam;

  function EnumProc(AHandle: HWND; AParam: PEnumWndParam): Boolean; stdcall;
  begin
    Result := not {AHandle satisfies AParam^.Criterion};
    if not Result then
      {Do something to AHandle, possibly using AParam^.Data}
    else
      Result := True;
  end;

var
  lParam: TEnumWndParam;
begin
  lParam.Criterion := ASomeCriterion;
  lParam.Data := AData;
  EnumChildWindows(AParent, @EnumProc, Winapi.Windows.LPARAM(@lParam));
end;

This still works fine with 32bit Delphi XE3, but with the 64bit compiler things are a little different: It still compiles without problems, but when EnumProc gets called, the arguments it gets fed contain garbage. The only way I found to make this work was to move the local declarations (the param record and the enum function) into the global space.

I really dislike this as it unnecessarily broadens the scope of these declarations and clutters the namespace. Is there some other way to get this to work with the 64bit compiler? Has this maybe been fixed in XE4 already?

Oliver Giesen
  • 9,129
  • 6
  • 46
  • 82
  • 2
    This was never valid, even in the Win32 compiler and only worked by accident. You got away with it because the Windows header translations use untyped pointers for the callback parameters which has always been a terrible mistake. If `EnumChildWindows` is correctly declared using a procedural type for the callback, then your code won't compile in the Win32 compiler. – David Heffernan Jul 18 '13 at 09:13
  • @David : OK, feel free to close as duplicate or post your answer again here and I will accept it. Still bugs me that I'm forced into cluttering the namespace... :-/ – Oliver Giesen Jul 18 '13 at 09:25
  • It should be closed as a dupe I think. – David Heffernan Jul 18 '13 at 09:26
  • Procedures are not namespaces. procedures are stackframes with local variables, and jumping into nested procedfure is just like `GOTO` into the middle of nested loops. If you bother about namespace - then enclose your callback into the new unit or into the extended records. http://stackoverflow.com/questions/830168/when-were-extended-records-introduced – Arioch 'The Jul 18 '13 at 09:34
  • You can create a class or record that contains your callback declared as a static class method. That's how to put it in a private namespace. – David Heffernan Jul 18 '13 at 09:39
  • Yep, but that class or record itself would still have a broader scope than would have been strictly necessary IMO. – Oliver Giesen Jul 18 '13 at 09:54
  • That may be so, but it is what it is – David Heffernan Jul 18 '13 at 10:23
  • @DavidHeffernan Classes ? Class method would expect SELF passed among parameters. I'd avoid class members for Win32 callbacks – Arioch 'The Jul 18 '13 at 10:37
  • @Arioch'The Read carefully. I said "static class method". So, a method of the form `class procedure; static;` can be assigned to a procedural variable of type `TProcedure = procedure;` – David Heffernan Jul 18 '13 at 10:38
  • @DavidHeffernan can you suggest "ifdef" tag at http://stackoverflow.com/tags/conditional-compilation/synonyms ? – Arioch 'The Jul 18 '13 at 10:46
  • @DavidHeffernan you imply that for class static methods SELF is not passed but is hardcoded into ? – Arioch 'The Jul 18 '13 at 10:47
  • @Arioch'The This is a well-documented area: http://docwiki.embarcadero.com/RADStudio/en/Methods#Class_Static_Methods and I suggested your ifdef synonym for you. Do you need more rep to do that? – David Heffernan Jul 18 '13 at 10:49
  • @DavidHeffernan As far as i can see, i need not "just rep" but i need specific rep in "conditional-compilation" tag. And that is hen and egg problem. Rare tags need merging more often. Yet for rare tags you can hardly get large rep just for statistical reasons. http://imgur.com/8iiJQKF – Arioch 'The Jul 18 '13 at 10:52
  • @Arioch'The I must admit, I've never got into tags and synonyms. This page made me chuckle though: http://stackoverflow.com/tags/conditional-compilation/topusers Who knew?!! – David Heffernan Jul 18 '13 at 10:57
  • 1
    @DavidHeffernan 1% of 200k is 100% of 2K :-) – Arioch 'The Jul 18 '13 at 11:15

0 Answers0