2011-12-23 5 views
10

मैं अपने फॉर्म को तीर कुंजियों को संभालने के लिए चाहता हूं, और मैं इसे कर सकता हूं - जब तक फॉर्म पर कोई बटन न हो। ऐसा क्यों है?डेन्फी एक्सई और ट्रैपिंग एरो कुंजी ऑनकेडडाउन

+4

शानदार सवाल। इस तरह की चीजों की अंतर्निहित जटिलताओं में खुदाई विशेषज्ञों से पर्यटकों को अलग करती है। कीप आईटी उप! –

उत्तर

8

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

यदि आप संदेश लूप के माध्यम से एक कुंजी प्रेस को अपना रास्ता कैसे ढूंढते हैं, तो पूर्ण कम नीचे प्राप्त करना चाहते हैं, तो मैं A Key's Odyssey पढ़ने की अनुशंसा करता हूं। यदि आप नेविगेशन कुंजी बनने से पहले कुंजी प्रेस को अवरुद्ध करना चाहते हैं, तो आपको IsKeyMsg या उससे पहले ऐसा करने की आवश्यकता है। उदाहरण के लिए, Sertac का answer ऐसी एक संभावना देता है।

+0

पीटर नीचे (उस कुंजी के ओडिसी के लेखक) एक महत्वपूर्ण डेल्फी समुदाय लड़का (टीमबी) है, और एक महान जेवीसीएल योगदानकर्ता है। अच्छा लेख। –

3

क्योंकि उन्हें अगली उपलब्ध WinControl पर ध्यान केंद्रित करने के साथ सौदा करने का प्रयास किया जाता है।
(मुझे पूरा यकीन है कि यदि आप एक बटन के बजाय एक संपादन डालते हैं तो आप एक ही चीज़ देखते हैं)।

यदि आप उन्हें स्वयं संभालना चाहते हैं, तो आप एप्लिकेशन को ऑनमेसेज ईवेंट के साथ प्रदान कर सकते हैं जो उन्हें संसाधित करने से पहले फ़िल्टर करेगा और उन्हें स्वयं संभालेंगे।

10

मुख्य संदेश उन संदेशों द्वारा संसाधित किए जाते हैं जो इन संदेशों को प्राप्त करते हैं, यही कारण है कि जब आप एक बटन पर होते हैं तो फॉर्म संदेश प्राप्त नहीं कर रहा है। तो सामान्य रूप से आप इन नियंत्रणों उपवर्ग करने के लिए होता है, लेकिन VCL parenting प्रपत्र क्या करना है पूछने के लिए अगर प्रपत्र रुचि रखता है तरह पर्याप्त है:

type 
    TForm1 = class(TForm) 
    .. 
    private 
    procedure DialogKey(var Msg: TWMKey); message CM_DIALOGKEY; 
    .. 


procedure TForm1.DialogKey(var Msg: TWMKey); 
begin 
    if not (Msg.CharCode in [VK_DOWN, VK_UP, VK_RIGHT, VK_LEFT]) then 
    inherited; 
end; 

फ़्राँस्वा संपादन: ओपी मूल सवाल का जवाब देने के लिए, आप किसी भी तरह से केडडाउन पर कॉल करने की आवश्यकता है ताकि उसका इवेंट कोड काम करेगा (संपादित करने के लिए स्वतंत्र महसूस करें; एक टिप्पणी के लिए बहुत लंबा था)।

type 
    TForm1 = class(TForm) 
    Button1: TButton; 
    Button2: TButton; 
    Button3: TButton; 
    Button4: TButton; 
    procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); 
    private 
    { Private declarations } 
    procedure DialogKey(var Msg: TWMKey); message CM_DIALOGKEY; 
    public 
    { Public declarations } 
    end; 

var 
    Form1: TForm1; 

implementation 

{$R *.dfm} 

procedure TForm1.DialogKey(var Msg: TWMKey); 
begin 
    case Msg.CharCode of 
    VK_DOWN, VK_UP, VK_RIGHT, VK_LEFT: 
     if Assigned(onKeyDown) then 
     onKeyDown(Self, Msg.CharCode, KeyDataToShiftState(Msg.KeyData)); 
    else 
     inherited 
    end; 
end; 

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; 
    Shift: TShiftState); 
begin 
    case Key of 
    VK_DOWN: Top := Top + 5; 
    VK_UP: Top := Top - 5; 
    VK_LEFT: Left := Left - 5; 
    VK_RIGHT: Left := Left + 5; 
    end; 
end; 
+0

मुझे लगता है कि आपको 'CM_DIALOGKEY' के बारे में विशेष क्या है इसके बारे में थोड़ा और स्पष्टीकरण चाहिए। व्यवहार को बदलने के लिए यह निश्चित रूप से चालाक तरीका है। मेरे उत्तर के साथ ओवरलैप करने के लिए स्वतंत्र महसूस करें और मैंने जो किया है, उस कोड के साथ एक व्यापक उत्तर के बाद से इसे हटा दूंगा। –

+0

@ डेविड - मुझे डर है कि आप अपनी पोस्ट को हटाने में सक्षम नहीं होंगे :)। CM_DIALOGKEY के बारे में बहुत कुछ नहीं समझा जा सकता है, यह एक वीसीएल बनाया गया संदेश है जो महत्वपूर्ण संदेशों को प्रसारित करने के लिए उपयोग किया जाता है। यही मेरी सहायता फ़ाइल इसके बारे में बताती है: * "यह निरंतर नियंत्रण है। CM_DIALOGKEY" * :)। अद्यतन: [प्रलेखन] (http://docwiki.embarcadero.com/VCL/2010/en/Controls.CM_DIALOGKEY) में सुधार किया गया है: * "CM_DIALOGKEY एक नियंत्रण संदेश का प्रतिनिधित्व करता है और वीसीएल ढांचे द्वारा आंतरिक रूप से उपयोग किया जाता है।" * –

+0

हम्म, मैंने सोचा कि ऐसा लगता है कि यह 'TAplication.IsDlgMsg' से संबंधित था। वास्तव में 'TAplication.IsDlgMsg' यहां भी प्रासंगिक है या क्या वीसीएल विंडोज संवाद के बजाए इन नेविगेशन कुंजी को संभालता है? –

5

केवल ऑब्जेक्ट जिस पर फोकस है वह एक कीबोर्ड ईवेंट प्राप्त कर सकता है।

फॉर्म को तीर कुंजियों की घटना तक पहुंचने के लिए, फ़ॉर्म के सार्वजनिक भाग में MsgHandler घोषित करें। फॉर्म में कन्स्ट्रक्टर बनाएं, Application.OnMessage को इस MsgHandler में असाइन करें।

नीचे दिया गया कोड केवल तीर कुंजियों को तब भी रोकता है जब वे टीबीटन वंश से आ रहे हैं। आवश्यकतानुसार अधिक नियंत्रण जोड़ा जा सकता है।

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    Application.OnMessage := Self.MsgHandler; 
end; 

procedure TForm1.MsgHandler(var Msg: TMsg; var Handled: Boolean); 
var 
    ActiveControl: TWinControl; 
    key : word; 
begin 
    if (Msg.message = WM_KEYDOWN) then 
    begin 
     ActiveControl := Screen.ActiveControl; 
     // if the active control inherits from TButton, intercept the key. 
     // add other controls as fit your needs 
     if not ActiveControl.InheritsFrom(TButton) 
     then Exit; 

     key := Msg.wParam; 
     Handled := true; 
     case Key of // intercept the wanted keys 
     VK_DOWN : ; // doStuff 
     VK_UP : ; // doStuff 
     VK_LEFT : ; // doStuff 
     VK_RIGHT : ; // doStuff 
     else Handled := false; 
     end; 
    end; 
end; 
0
var 
KBHook: HHook; {this intercepts keyboard input} 

implementation 

{$R *.dfm} 

function KeyboardHookProc(Code: Integer; WordParam: Word; LongParam: LongInt): LongInt; stdcall; 
begin 
case WordParam of 
    vk_Space: ShowMessage ('space') ; 
    vk_Right:ShowMessage ('rgt') ; 
    vk_Left:ShowMessage ('lft') ; 
    vk_Up: ShowMessage ('up') ; 
    vk_Down: ShowMessage ('down') ; 
    end; {case} 
end; 

procedure TForm4.FormCreate(Sender: TObject); 
begin 
KBHook:=SetWindowsHookEx(WH_KEYBOARD,@KeyboardHookProc,HInstance,GetCurrentThreadId()); 
end; 

इस कोड को भी जब एक नियंत्रण केंद्रित है (बटन, listboxes) काम करेंगे, तो सावधान कुछ नियंत्रण अपने कुंजीपटल घटनाओं (पढ़ें डेविड haffernans जवाब) ढीला हो सकती है।

केंद्रित नियंत्रण

साथ कीबोर्ड की घटनाओं जैसे: आप अपने एप्लिकेशन में पाठ बॉक्स होने और पाठ recive (यदि ध्यान केंद्रित) भी है, तो

एक applicationevent1 जोड़ना चाहते हैं, तो

procedure TForm4.ApplicationEvents1Message(var Msg: tagMSG;var Handled: Boolean); 
begin 
if Msg.message = WM_KEYFIRST then 
    KBHook:=SetWindowsHookEx(WH_KEYBOARD,@KeyboardHookProc,HInstance,GetCurrentThreadId()); 
end; 

function KeyboardHookProc

UnhookWindowsHookEx(KBHook); 
012 के नीचे निम्न कोड जोड़ें

और OnCreate घटना से

KBHook:=SetWindowsHookEx(WH_KEYBOARD,@KeyboardHookProc, HInstance, 
GetCurrentThreadId()); 

को हटा दें।