The callback function is not declared correctly. You declare the last parameter as var LPARAM , which is incorrect. The lParam parameter is passed by value, not by reference. When you call EnumFontFamiliesEx() you pass a pointer to Boolean as the value of lParam .
Your callback is trying to write sizeof(LPARAM) number of bytes to a memory address that contains only SizeOf(Boolean) bytes (and why are you trying to write -1 in Boolean ?). So you rewrite the memory. When using a pointer to a local variable as lParam you most likely just overwrite the memory in the call stack of the calling function, which does not really matter, so you don't see a failure.
You need to either:
remove var and enter the lParam parameter in PBoolean :
function FindFontFace( lpelf: PLogFont; lpntm: PTextMetric; FontType: DWORD; lParam: LPARAM): Integer ; stdcall; begin PBoolean(lParam)^ := True; Result := 0; // 1 shot only please - not interested in any variations in style etc end;
Or:
function FindFontFace( lpelf: PLogFont; lpntm: PTextMetric; FontType: DWORD; lParam: PBoolean): Integer ; stdcall; begin lParam^ := True; Result := 0; // 1 shot only please - not interested in any variations in style etc end;
leave var , but change the parameter type to Boolean instead of lParam :
function FindFontFace( var lpelf: TLogFont; var lpntm: TTextMetric; FontType: DWORD; var lParam: Boolean): Integer ; stdcall; begin lParam := True; Result := 0; // 1 shot only please - not interested in any variations in style etc end;
Any approach will allow you to pass @Result as lParam to EnumFontFamiliesEx() both 32-bit and 64-bit:
function FindFontbyFaceName(ACanvas: TCanvas; const AFacename: string): Boolean; var lf: TLogFont; begin Result := False; FillChar(lf, SizeOf(lf), 0); StrLCopy(lf.lfFaceName, PChar(AFacename), 32); lf.lfCharSet := DEFAULT_CHARSET; EnumFontFamiliesEX(ACanvas.Handle, lf, @FindFontFace, LPARAM(@Result), 0); end;
For one thing, creating a TImage just to have a canvas for enumeration is wasteful. You do not need this at all:
function FindFontFace( lpelf: PLogFont; lpntm: PTextMetric; FontType: DWORD; lParam: LPARAM): integer ; stdcall; begin PBoolean(lParam)^ := True; Result := 0; // 1 shot only please - not interested in any variations in style etc end; function FindFont(const AFacename: string): Boolean; var lf: TLogFont; DC: HDC; begin Result := False; FillChar(lf, SizeOf(lf), 0); StrLCopy(lf.lfFaceName, PChar(AFacename), 32); lf.lfCharSet := DEFAULT_CHARSET; DC := GetDC(0); EnumFontFamiliesEx(DC, lf, @FindFontFace, LPARAM(@Result), 0); ReleaseDC(0, DC); end;
In doing so, you can simplify the code if you use the TScreen.Fonts property instead of directly calling EnumFontFamiliesEx() :
function FindFont(const AFacename: string): Boolean; begin Result := (Screen.Fonts.IndexOf(AFacename) <> -1); end;