2012-01-05 10 views
7

मैं कुछ ऐसे काम पर काम कर रहा हूं जिसके लिए कई रूपों की निगरानी की आवश्यकता होगी। फॉर्म के बाहर से, और फ़ॉर्म के अंदर कोई कोड डाले बिना, मुझे किसी भी तरह से इन रूपों से ईवेंट कैप्चर करने की ज़रूरत है, जो कि विंडोज संदेशों के रूप में सबसे अधिक संभावना है। लेकिन आप उस वर्ग के बाहर से विंडोज संदेशों को कैसे कैप्चर करेंगे, इससे संबंधित है?मैं फ़ॉर्म के बाहर से किसी फॉर्म की कुछ घटनाओं को कैसे पकड़ूं?

मेरी प्रोजेक्ट में एक ऑब्जेक्ट है जो प्रत्येक रूप को निगरानी रखता है, और मुझे लगता है कि यह हैंडलिंग इस ऑब्जेक्ट में जाएगी। अनिवार्य रूप से, जब मैं एक फॉर्म बनाता हूं जिसे मैं मॉनिटर करना चाहता हूं, तो मैं एक संबंधित वस्तु बना देता हूं जो बदले में सभी बनाए गए रूपों की सूची में जोड़ा जाता है। सबसे महत्वपूर्ण बात यह है कि जब वह फॉर्म बंद हो जाता है, तो मुझे पता होना चाहिए कि मैं सूची से इस फॉर्म की रैपर ऑब्जेक्ट को हटा सकता हूं।

इन घटनाओं में शामिल हैं:

:

  • कम से कम
  • अधिकतम
  • पुनर्स्थापित
  • बंद
  • फोकस/बाहर

क्या मैं नहीं चाहता हूँ में

  • किसी भी रूपों या इस से निपटने
  • जैसे OnClose किसी भी कस्टम धातु रूप
  • से रूपों विरासत प्रपत्र की घटनाओं का उपयोग के लिए प्रपत्र इकाइयों के अंदर किसी भी कोड है क्योंकि वे अन्य प्रयोजनों के

लिए उपयोग किया जाएगा क्या मैं चाहते हैं:

  • इन घटनाओं के लिए खिड़कियों संदेशों के हैंडलिंग
  • पर कोई युक्तियाँ कैसे जीई के लिए कक्षा के बाहर से टी खिड़कियों संदेशों
  • कौन सा विंडोज़ संदेशों मैं के लिए

प्रश्न सुनने की जरूरत है एक ही जानकारी है, लेकिन अलग दृष्टिकोण

+0

Hookin बिना आप जो भी करना चाहते हैं FindControl समारोह और Msg.hWnd का उपयोग लेकिन मुझे लगता है के रूप में यह था तुम भी कोड इंजेक्शन विचार कर सकते हैं कुछ एओपी ढांचे द्वारा किया गया। – menjaraz

+0

आप जानते हैं कि आप अपने खुद के हैंडलर के साथ प्रपत्र की घटनाओं की जगह लेकिन पुराने मूल्य के आसपास रख सकते हैं, और उसके बाद वर्ष हैंडलर, सही आह्वान, आपका प्लेसमेंट हैंडलर से कर रहे हैं? यह सच "कोड इंजेक्शन" या सच "हुकिंग" से भी आसान है। यह बहुत अधिक ऑपरेटिंग सिस्टम में "हस्तक्षेप हैंडलर" कैसे काम करता है। हम इसे "वेक्टर प्रतिस्थापन" कहते हैं। –

+0

@WarrenP मुझे यह पता है, और शायद यह होगा अगर डेविड ने क्लीनर विधि का उल्लेख नहीं किया था। लेकिन यह रणनीति (कम से कम मेरी राय में) शायद 90-95% प्रभावी है (मैं कुछ मुद्दों को देख सकता हूं जो इस स्थिति को गड़बड़ कर देंगे)। डेविड का समाधान 100% प्रभावी है। –

उत्तर

6
:

FOriginalWindowProc := Form.WindowProc; 
Form.WindowProc := NewWindowProc; 

अंत में, प्रतिस्थापन खिड़की प्रक्रिया लागू

डेविड द्वारा प्रदान किए गए समाधान का एक और पूरा उदाहरण यहां दिया गया है:

private 
    { Private declarations } 
    SaveProc : TWndMethod; 
    procedure CommonWindowProc(var Message: TMessage); 

... 

procedure TForm1.Button1Click(Sender: TObject); 
var 
    f : tForm2; 
begin 
    f := tForm2.Create(nil); 
    SaveProc := f.WindowProc; 
    f.WindowProc := CommonWindowProc; 
    f.Show; 
end; 

procedure TForm1.CommonWindowProc(var Message: TMessage); 
begin 
    case Message.Msg of 
    WM_SIZE : Memo1.Lines.Add('Resizing'); 
    WM_CLOSE : Memo1.Lines.Add('Closing'); 
    CM_MOUSEENTER : Memo1.Lines.Add('Mouse enter form'); 
    CM_MOUSELEAVE : Memo1.Lines.Add('Mouse leaving form'); 
    // all other messages will be available as needed 
    end; 
    SaveProc(Message); // Call the original handler for the other form 
end; 
1

काम करने की कोशिश की तुलना में एक बेहतर समाधान के साथ फिर से लिखा फॉर्म के बाहर प्रत्येक फॉर्म को एक सामान्य आधार रूप से उतरना होगा जो कार्यक्षमता को लागू करता है। फॉर्म इवेंट हैंडलर इस कोड को जोड़ने के लिए बिल्कुल सही जगह हैं लेकिन आप इसे सभी को पूर्वजों के रूप में लिखेंगे। कोई भी वंशज प्रपत्र अभी भी फॉर्म इवेंट्स का उपयोग कर सकता है और जब तक वे ईवेंट हैंडलर में कहीं भी विरासत में कॉल करते हैं तो पूर्वजों का कोड अभी भी निष्पादित होगा।

+1

मैं इस बात से सहमत है लेकिन कभी कभी आप अपनी परियोजना में 3 पार्टी कोड जो इस –

+0

प्राप्त करने के लिए यह मेरा मूल योजना थी कठिन बना सकते हैं शामिल कर रहे हैं, लेकिन क्योंकि प्रमुख कारण यह काम नहीं करेगा है - जैसे मेरे सवाल में उल्लेख किया है - मैं नहीं कर सकता इसके लिए किसी भी फॉर्म के अंदर कोई कोड डालें। आधार फॉर्म बनाना फॉर्म के अंदर कोड डालने से अलग नहीं है। –

+0

@Jerry - समझा लेकिन आप यह भी संकेत दिया है कि आप अंत में व्यक्तिगत रूप ईवेंट हैंडलर्स जो भी रूपों के अंदर कोड डाल रहा है पर कोड शामिल था। –

8

आपको फ़ॉर्म में दिए गए विशेष विंडोज संदेशों को सुनने की आवश्यकता है। ऐसा करने का सबसे आसान तरीका फॉर्म की WindowProc संपत्ति असाइन करना है। WindowProc के पिछले मान को पकड़ना याद रखें और इसे अपने प्रतिस्थापन से कॉल करें।

अपने आवरण वस्तु में इस तरह की एक क्षेत्र घोषित:

FOriginalWindowProc: TWndMethod; 

तब आवरण के निर्माता में ऐसा करते हैं:

procedure TFormWrapper.NewWindowProc(var Message: TMessage); 
begin 
    //test for and respond to the messages of interest 
    FOriginalWindowProc(Message); 
end; 
+0

यह आशाजनक लग रहा है, लेकिन यह सुनिश्चित करने के लिए अभी तक नहीं कह सकता है जब तक कि मैं घर नहीं लेता और इसे चलाने देता हूं। –

+0

मैं आप से पूछना कैसे 'NewWindowProc' में संदेशों को संभालने के लिए के बारे में था, लेकिन माइक मुझे यह करने के लिए हरा - मैं अब अपने जवाब को स्वीकार करने :(अभी भी मूल उत्तर के लिए +1 होगा –

+0

ओह मैंने सोचा था कि था आसान सा तो मैंने अभी कड़ी मेहनत की है। मैंने केवल संदेश अवरोध का सामना किया क्योंकि सवाल के पूरे फोकस और टिप्पणियां उस हिस्से थीं। –

0

विंडोज संदेशों का उपयोग वास्तव में प्राप्त कर सकते हैं एक fine granularity (हाँ, अपनी आवश्यकताओं के अपने हिस्सा!), लेकिन कुछ मामलों में जहां उपयोगकर्ता VCL Event Framework suffices पर सिर्फ भरोसा में, एक ऐसी ही समाधान का सुझाव दिया जा सकता है:

unit Host; 

interface 

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
    Dialogs, StdCtrls; 

type 
    THostForm = class(TForm) 
    Memo1: TMemo; 
    Button1: TButton; 
    procedure Button1Click(Sender: TObject); 
    private 
    FFormResize: TNotifyEvent; 
    FFormActivate: TNotifyEvent; 
    FFormDeactivate: TNotifyEvent; 
    FFormDestroy: TNotifyEvent; 

    procedure _FormResize(Sender: TObject); 
    procedure _FormActivate(Sender: TObject); 
    procedure _FormDeactivate(Sender: TObject); 

    procedure InternalEventHandlerInit(const AForm:TForm); 
    public 
    procedure Log(const Msg:string); 
    procedure Logln(const Msg:string); 
    end; 

var 
    HostForm: THostForm; 

implementation 

{$R *.dfm} 

procedure THostForm.Button1Click(Sender: TObject); 
var 
    frm: TForm; 
begin 
    frm := TForm.Create(nil); 
    frm.Name := 'EmbeddedForm'; 
    frm.Caption := 'Embedded Form'; 
    // 
    InternalEventHandlerInit(frm); 
    // 
    Logln('<'+frm.Caption+'> created.'); 
    // 
    frm.Show; 
end; 


procedure THostForm.InternalEventHandlerInit(const AForm: TForm); 
begin 
    FFormResize := AForm.OnResize; 
    AForm.OnResize := _FormResize; 
    // 
    FFormActivate := AForm.OnActivate; 
    AForm.OnActivate := _FormActivate; 
    // 
    FFormDeactivate := AForm.OnDeactivate; 
    AForm.OnDeactivate := _FormDeactivate; 
end; 

procedure THostForm.Log(const Msg: string); 
begin 
    Memo1.Lines.Add(Msg); 
end; 

procedure THostForm.Logln(const Msg: string); 
begin 
    Memo1.Lines.Add(Msg); 
    Memo1.Lines.Add(''); 
end; 

procedure THostForm._FormActivate(Sender: TObject); 
begin 
    Log('Before OnActivate <'+(Sender as TCustomForm).Caption+'>'); 
    // 
    if Assigned(FFormActivate) then 
    FFormActivate(Sender) // <<< 
    else 
    Log('No OnActivate Event Handler attached in <'+(Sender as TCustomForm).Caption+'>'); 
    // 
    Logln('After OnActivate <'+(Sender as TCustomForm).Caption+'>'); 
end; 

procedure THostForm._FormDeactivate(Sender: TObject); 
begin 
    Log('Before OnDeactivate <'+(Sender as TCustomForm).Caption+'>'); 
    // 
    if Assigned(FFormDeactivate) then 
    FFormDeactivate(Sender) 
    else 
    Log('No OnDeActivate Event Handler attached in <'+(Sender as TCustomForm).Caption+'>'); 
    // 
    Logln('After OnDeactivate <'+(Sender as TCustomForm).Caption+'>'); 
end; 

procedure THostForm._FormResize(Sender: TObject); 
begin 
    Log('Before OnResize <'+(Sender as TCustomForm).Caption+'>'); 
    // 
    if Assigned(FFormResize) then 
    FFormResize(Sender) 
    else 
    Log('No OnResize Event Handler attached in <'+(Sender as TCustomForm).Caption+'>'); 
    // 
    Logln('After OnResize <'+(Sender as TCustomForm).Caption+'>'); 
end; 

end. 
+3

यह तब तक ठीक है जब तक पीड़ित फॉर्म अपने स्वयं के ईवेंट हैंडलर और उसके खेल को संशोधित करने का फैसला नहीं करता है। –

+0

@ डेविड हेफरनन: आप सही हैं। अब मैं देखता हूं कि वे बिल्कुल सुरक्षित नहीं हैं। मुझे डर है कि इस मामले में इस तरह से जाने का एकमात्र तरीका "पीड़ित" रूप (अटकलें) में कुछ कोड इंजेक्शन करना है। – menjaraz

0

एक अन्य विकल्प TApplicationEvents बना सकते हैं और OnMessage घटना के लिए कोई हैंडलर निर्दिष्ट करते हैं। एक बार अगर यह निकाल दिया है, अगर यह tform प्रकार है की जाँच करें और मैं इतना यकीन नहीं है

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