2012-07-15 19 views
14

इस post जिसका स्वीकार किए जाते हैं जवाब देने के लिए इसके अलावा बहुत गुप्त रहता है:TProc <TObject> TNotifyEvent को

@Button1.OnClick := pPointer(Cardinal(pPointer(procedure (sender: tObject) begin ((sender as TButton).Owner as TForm).Caption := 'Freedom to anonymous methods!' end)^) + $0C)^; 

मुझे आश्चर्य है कि मौसम यह एक सरल और सुरुचिपूर्ण तरीका जैसा चिंतन करना संभव है:

Button.OnClick := 
        AnonProc2NotifyEvent (
        procedure (Sender: TObject) 
        begin 
         ((Sender as TButton).Owner as TForm).Caption := 'Freedom to anonymous methods!' 
        end 
        ); 
इतनी के रूप में

उसी उद्देश्य को प्राप्त करने के लिए और जहां AnonProc2NotifyEvent निम्नलिखित हस्ताक्षर के साथ बटन के मालिक का एक तरीका है:

TOwnerOfButton = class(TForm) 
    Button: TButton; 
    ... 
private 
    ... 
protected 
    function AnonProc2NotifyEvent(aProc: TProc<TObject>): TNotifyEvent; 
public 
    ... 
end; 

क्या यह व्यवहार्य है और यदि ऐसा है तो इसे कैसे कार्यान्वित किया जाए?

+0

आप शायद [DSharp.Core.Events.pas] (http://code.google.com/p/delphisorcery/source/browse/trunk/Source/Core/DSharp.Core.Events] पर एक नज़र डालना चाहेंगे .pas)। –

+0

@Stefan Glienke: मुझे यह याद दिलाने के लिए धन्यवाद, मैंने वास्तव में अपने बॉक्स पर डीएसएचआरपी स्थापित किया है और मुझे यह याद आया (मेरी बर्खास्तगी के लिए, मैं अक्सर इसका उपयोग अक्सर नहीं करता) लेकिन मेरा मानना ​​है कि मैं इसकी शुरुआत के बाद इसका पालन करता हूं (बीवीटी I मैं डेल्फीप्रैक्सिस का सदस्य भी हूं, जर्मन में बहुत अच्छा नहीं बल्कि उत्साही जर्मन डेल्फी दृश्य पर नजर रखने का प्रयास करता हूं)। निश्चित रूप से जेनेरिक मेरा अगला कदम है। धन्यवाद * स्टीवी * :-) – menjaraz

उत्तर

21

यह काम आसानी से पर्याप्त करना होगा:

type 
    TNotifyEventWrapper = class(TComponent) 
    private 
    FProc: TProc<TObject>; 
    public 
    constructor Create(Owner: TComponent; Proc: TProc<TObject>); 
    published 
    procedure Event(Sender: TObject); 
    end; 

constructor TNotifyEventWrapper.Create(Owner: TComponent; Proc: TProc<TObject>); 
begin 
    inherited Create(Owner); 
    FProc := Proc; 
end; 

procedure TNotifyEventWrapper.Event(Sender: TObject); 
begin 
    FProc(Sender); 
end; 

function AnonProc2NotifyEvent(Owner: TComponent; Proc: TProc<TObject>): TNotifyEvent; 
begin 
    Result := TNotifyEventWrapper.Create(Owner, Proc).Event; 
end; 

AnonProc2NotifyEvent में Owner पैरामीटर है ताकि आवरण वस्तु के जीवनकाल प्रबंधित किया जा सकता। इस तरह के कुछ के बिना आप TNotifyEventWrapper के उदाहरण रिसाव करेंगे।

Owner के रूप में पास करें, जिस घटक से आप ईवेंट को जोड़ रहे हैं। उदाहरण के लिए:

Button1.OnClick := AnonProc2NotifyEvent(
    Button1, 
    procedure(Sender: TObject) 
    begin 
    (Sender as TButton).Caption := 'Clicked'; 
    end 
); 

तो, जब बटन नष्ट हो जाता है, TNotifyEventWrapper भी नष्ट हो जाएगा। रैपर ऑब्जेक्ट कम से कम तब तक जीवित रहना चाहिए जब तक ऑब्जेक्ट की घटनाओं से संबंधित हो। और इसलिए Button1 की पसंद मालिक के रूप में प्राकृतिक और स्पष्ट है।

+0

धन्यवाद डेविड! यह मेरे दिमाग को कभी पार नहीं करता है कि एक रैपर करेगा और यह घटक बनाने के लिए एक अच्छा उम्मीदवार है: संक्षिप्त, स्वच्छ और सुरुचिपूर्ण समाधान। – menjaraz

5

संदर्भ के लिए यह है कि क्या मैं पर हो रही है, मैं अध्ययन किया Barry Kelly के ब्लॉग post पहले अतः जैसा कि ऊपर उल्लेख पोस्ट में जिक्र किया गया और इस समाधान के साथ आया था:

function TMainForm.Proc2NotifyEvent(const aProc: TNotifyReference): TNotifyEvent; 
type 
    TVtable = array[0..3] of Pointer; 
    PVtable = ^TVtable; 
    PPVtable = ^PVtable; 
begin 
    TMethod(Result).Code := PPVtable((@aProc)^)^^[3]; 
    TMethod(Result).Data := Pointer((@aProc)^); 
end; 

फिर भी गुप्त लेकिन encapsuled, इसलिए आसान प्रारंभिक विधि की तुलना में कोडर का कार्य।

मैं MethRefToMethPtr और MakeNotify साफ और यह सब एक विधि में डालने की कोशिश की।

सूचना नहीं थी (एक मामूली) विधि के हस्ताक्षर में परिवर्तन, तर्क aProcस्थिरांक बन गया।

+1

+1 यह बुरा है !! – ComputerSaysNo

+0

आपको अभी भी ऑब्जेक्ट को जीवित रखने के लिए कुछ करने की आवश्यकता है जो एनन प्रो इंटरफ़ेस लागू करता है। बैरी उस महत्वपूर्ण विवरण का जिक्र करता है। –

+0

@ डेविड हेफरनन: क्या मुझे कहीं संदर्भ रखना चाहिए? – menjaraz