मैं अपने फॉर्म को तीर कुंजियों को संभालने के लिए चाहता हूं, और मैं इसे कर सकता हूं - जब तक फॉर्म पर कोई बटन न हो। ऐसा क्यों है?डेन्फी एक्सई और ट्रैपिंग एरो कुंजी ऑनकेडडाउन
उत्तर
तीर कुंजियों का उपयोग किसी फ़ॉर्म पर बटन के बीच नेविगेट करने के लिए किया जाता है। यह मानक विंडोज व्यवहार है। यद्यपि आप इस मानक व्यवहार को अक्षम कर सकते हैं, आपको मंच मानक के खिलाफ जाने से पहले दो बार सोचना चाहिए। तीर कुंजी नेविगेशन के लिए हैं।
यदि आप संदेश लूप के माध्यम से एक कुंजी प्रेस को अपना रास्ता कैसे ढूंढते हैं, तो पूर्ण कम नीचे प्राप्त करना चाहते हैं, तो मैं A Key's Odyssey पढ़ने की अनुशंसा करता हूं। यदि आप नेविगेशन कुंजी बनने से पहले कुंजी प्रेस को अवरुद्ध करना चाहते हैं, तो आपको IsKeyMsg
या उससे पहले ऐसा करने की आवश्यकता है। उदाहरण के लिए, Sertac का answer ऐसी एक संभावना देता है।
पीटर नीचे (उस कुंजी के ओडिसी के लेखक) एक महत्वपूर्ण डेल्फी समुदाय लड़का (टीमबी) है, और एक महान जेवीसीएल योगदानकर्ता है। अच्छा लेख। –
क्योंकि उन्हें अगली उपलब्ध WinControl पर ध्यान केंद्रित करने के साथ सौदा करने का प्रयास किया जाता है।
(मुझे पूरा यकीन है कि यदि आप एक बटन के बजाय एक संपादन डालते हैं तो आप एक ही चीज़ देखते हैं)।
यदि आप उन्हें स्वयं संभालना चाहते हैं, तो आप एप्लिकेशन को ऑनमेसेज ईवेंट के साथ प्रदान कर सकते हैं जो उन्हें संसाधित करने से पहले फ़िल्टर करेगा और उन्हें स्वयं संभालेंगे।
मुख्य संदेश उन संदेशों द्वारा संसाधित किए जाते हैं जो इन संदेशों को प्राप्त करते हैं, यही कारण है कि जब आप एक बटन पर होते हैं तो फॉर्म संदेश प्राप्त नहीं कर रहा है। तो सामान्य रूप से आप इन नियंत्रणों उपवर्ग करने के लिए होता है, लेकिन 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;
मुझे लगता है कि आपको 'CM_DIALOGKEY' के बारे में विशेष क्या है इसके बारे में थोड़ा और स्पष्टीकरण चाहिए। व्यवहार को बदलने के लिए यह निश्चित रूप से चालाक तरीका है। मेरे उत्तर के साथ ओवरलैप करने के लिए स्वतंत्र महसूस करें और मैंने जो किया है, उस कोड के साथ एक व्यापक उत्तर के बाद से इसे हटा दूंगा। –
@ डेविड - मुझे डर है कि आप अपनी पोस्ट को हटाने में सक्षम नहीं होंगे :)। CM_DIALOGKEY के बारे में बहुत कुछ नहीं समझा जा सकता है, यह एक वीसीएल बनाया गया संदेश है जो महत्वपूर्ण संदेशों को प्रसारित करने के लिए उपयोग किया जाता है। यही मेरी सहायता फ़ाइल इसके बारे में बताती है: * "यह निरंतर नियंत्रण है। CM_DIALOGKEY" * :)। अद्यतन: [प्रलेखन] (http://docwiki.embarcadero.com/VCL/2010/en/Controls.CM_DIALOGKEY) में सुधार किया गया है: * "CM_DIALOGKEY एक नियंत्रण संदेश का प्रतिनिधित्व करता है और वीसीएल ढांचे द्वारा आंतरिक रूप से उपयोग किया जाता है।" * –
हम्म, मैंने सोचा कि ऐसा लगता है कि यह 'TAplication.IsDlgMsg' से संबंधित था। वास्तव में 'TAplication.IsDlgMsg' यहां भी प्रासंगिक है या क्या वीसीएल विंडोज संवाद के बजाए इन नेविगेशन कुंजी को संभालता है? –
केवल ऑब्जेक्ट जिस पर फोकस है वह एक कीबोर्ड ईवेंट प्राप्त कर सकता है।
फॉर्म को तीर कुंजियों की घटना तक पहुंचने के लिए, फ़ॉर्म के सार्वजनिक भाग में 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;
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());
को हटा दें।
शानदार सवाल। इस तरह की चीजों की अंतर्निहित जटिलताओं में खुदाई विशेषज्ञों से पर्यटकों को अलग करती है। कीप आईटी उप! –