2017-02-15 11 views
5

में विंडोज कॉलबैक से रिटर्निंग परिणाम मेरे पास कुछ कोड है जो यह निर्धारित करने के लिए EnumFontFamiliesEX का उपयोग करता है कि कोई विशेष फ़ॉन्ट (इसके "facename" का उपयोग कर) स्थापित है या नहीं। कोड 32-बिट में ठीक काम कर रहा था। जब मैं इसे 64-बिट के रूप में संकलित और चलाता हूं, तो उसने कॉलबैक रूटीन में अपवाद फेंक दिया।64-बिट XE6

मैं अब दोनों के तहत काम करने के लिए यह मिल गया है, लेकिन केवल EnumFontFamiliesEX को 4 पैरामीटर के रूप में समारोह FindFontbyFaceName के परिणाम में उत्तीर्ण होने की बजाय अगर, मैं एक स्थानीय (या वैश्विक) चर पारित - इस मामले में MYresult। (और उसके बाद परिणाम सेट करें)। मुझे समझ में नहीं आता कि क्या हो रहा है? क्या कोई मुझे बेहतर तरीके से समझा सकता है या इंगित कर सकता है। (मैं मूल कॉलबैक यांत्रिकी के रूप में फोंट के यांत्रिकी में इतनी दिलचस्पी नहीं रखता हूं)।

// single font find callback 
function FindFontFace( {$IFDEF CPUX86} lpelf: PLogFont;  {$ENDIF} 
         {$IFDEF CPUX64} lpelf: PEnumLogFontEx; {$ENDIF} 
         lpntm: PNewTextMetricEx; 
         AFontType: DWORD; var Aresult: lparam): integer ; stdcall; 
begin 
    result := 0;  // 1 shot only please - not interested in any variations in style etc 
    if (lpelf <> nil) then 
    Aresult := -1   // TRUE 
    else 
    Aresult := 0; 
end; 


function FindFontbyFaceName(ACanvas: TCanvas; const AFacename: string): boolean; 
var 
    lf: TLogFont; 
    Myresult: boolean; 
begin 
    MYresult := false; 

    FillChar(lf, SizeOf(lf), 0); 
    StrLCopy(lf.lfFaceName, PChar(AFacename), 32); 
    lf.lfCharSet := DEFAULT_CHARSET; 

    // this works in both 32 and 64 bit 
    EnumFontFamiliesEX(ACanvas.Handle, lf, @FindFontFace, lparam(@MYresult), 0); 
    result := MYresult; 

    // this works in 32 bit but throws exception in callback in 64 bit 
// EnumFontFamiliesEX(ACanvas.Handle, lf, @FindFontFace, lparam(@result), 0); 
end; 


function FindFont(const AFacename: string): boolean; 
var 
    AImage: TImage; 
begin 
    AImage := Timage.Create(nil); 
    try 
    result := FindFontbyFaceName(AImage.Canvas, Afacename); 
    finally 
    Aimage.Free; 
    end; 
end; 
+0

LPARAMs विभिन्न आकारों Win32 में हैं और Win64। MyResult बनाने के लिए सबसे आसान होगा: LPARAM और फिर परिणाम दें: = (MyResult = -1)। – FredS

+0

@FredS धन्यवाद। मुख्य सवाल यह है कि मुझे उस स्थानीय/वैश्विक चर की आवश्यकता क्यों है? मैं सीधे परिणाम का उपयोग क्यों नहीं कर सकता? – TomB

+0

@TomB: आपका कॉलबैक स्मृति को मिटा रहा है। मेरा जवाब देखें –

उत्तर

10

आपका कॉलबैक फ़ंक्शन सही ढंग से घोषित नहीं किया गया है। आप अंतिम पैरामीटर को var LPARAM के रूप में घोषित कर रहे हैं, जो गलत है। lParam पैरामीटर मान द्वारा पारित किया गया है, संदर्भ के अनुसार नहीं। EnumFontFamiliesEx() पर कॉल करते समय आप Boolean पर lParam मान के रूप में एक पॉइंटर पास कर रहे हैं।

आपका कॉलबैक (और क्यों आप एक एक Boolean को -1 लिखने की कोशिश कर रहे हैं?) एक स्मृति पता ही SizeOf(Boolean) बाइट्स उपलब्ध है कि करने के लिए बाइट्स की sizeof(LPARAM) संख्या लिखने की कोशिश कर रहा है। तो आप स्मृति को ओवरराइट कर रहे हैं। lParam के रूप में स्थानीय चर के लिए पॉइंटर का उपयोग करते समय, आप शायद कॉलिंग फ़ंक्शन के कॉल स्टैक पर स्मृति को ओवरराइट कर रहे हैं जो वास्तव में कोई फर्क नहीं पड़ता है, इसलिए आपको कोई क्रैश दिखाई नहीं देता है।

  1. var को हटाने और एक PBoolean को lParam पैरामीटर टाइपकास्ट:

    आप या तो करने की जरूरत है

    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 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; 
    
  2. var लेकिन परिवर्तन छोड़ परम BooleanLPARAM के बजाय करने के लिए eter प्रकार:,

    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; 
    

    एक तरफ ध्यान दें पर बनाने:

    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; 
    

या तो दृष्टिकोण आप दोनों 32bit और 64bit में EnumFontFamiliesEx() को lParam रूप @Result पारित करने के लिए अनुमति देगा एक TImage सिर्फ एक कैनवास के साथ गणना करने के लिए अपमानजनक है। आप यह बिल्कुल जरूरत नहीं है: यदि आप TScreen.Fonts संपत्ति बजाय EnumFontFamiliesEx() सीधे बुलाने की का उपयोग

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; 

कहा जा रहा है, तो आप कोड को आसान बनाने में कर सकते हैं:

function FindFont(const AFacename: string): Boolean; 
begin 
    Result := (Screen.Fonts.IndexOf(AFacename) <> -1); 
end; 
+0

विस्तृत उत्तर के लिए धन्यवाद। और यह समझ में आता है। (कैनवास वास्तविक कोड से सिर्फ एक अवशेष था जो कैनवास का उपयोग करता है।) मैंने स्क्रीन.फोंट को देखा लेकिन ठीक प्रिंट में, कुछ फोंट शामिल नहीं थे और रुचि का फ़ॉन्ट प्रिंटर फ़ॉन्ट (बस) हो सकता है। बहुत बहुत धन्यवाद। – TomB

संबंधित मुद्दे