m-khorsandi
یک شنبه 08 بهمن 1385, 21:54 عصر
مفهوم و طرز کار رویدادهای کیبورد در دلفی
OnKeyDown, OnKeyUp, OnKeyPress
رویدادهای کیبورد به همراه رویدادهای Mouse ،اساس اولیه ارتباط کاربر با برنامه شماست. این مطلب درباره سه رویدادی ست که شما را قادر می سازند کلیدهای فشرده شده توسط کاربر را دریافت و کنترل کنید.
برنامه های دلفی میتوانند از دو متد برای دریافت ورودی از کیبورد استفاده کنند. اگر یک کاربر عناصر مختلفی در یک برنامه داشته باشد، ساده ترین راه برای دریافت ورودی ها، استفاده از کنترلی ست که به صورت خودکار به کلیدهای فشرده شده پاسخ دهد، مانند Edit .
هر چند که در موقعیتهای متفاوت و برای مقاصد عمومی ، میتوانیم پروسیجری را در فرم ایجاد کنیم که سه رویداد را توسط فرم و یا هر کامپوننتی که ورودی کیبورد را قبول میکند، تشخیص دهد .
میتوانیم متدهایی را برای پاسخگویی به کلیدها یا ترکیب کلیدهای فشرده شده توسط کابر در زمان اجرای برنامه، بنویسیم :
OnKeyDown : موقعی فراخوانی میشود که کلیدی روی کیبورد فشار داده شود.
OnKeyUp : موقعی فراخوانی میشود که کلید فشرده شده روی کیبورد ، رها شود.
OnKeyPress : موقعی فراخوانی میشود که کلید متناظر با یک کاراکتر اسکی فشار داده شود.
همه رویدادهای کیبورد یک پارامتر عمومی دارند. پارامتر Key ، کلیدی روی کیبورد هست و به صورت by reference ارسال میشود. پارامتر Shift (در OnKeyDown و OnKeyUp) ، که در اثر فشار دادن یکی از کلیدهای Shift ، Alt یا Ctrl به عنوان کلیدهای ترکیبی مقدار دهی میشود. پارامتر Sender هم اشاره به کنترلی دارد که این متد را فراخوانی کرده ست.
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState) ;
...
procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState) ;
...
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char) ;
نیازی نیست برای Short-cut های تعریف شده، مانند Short-cut هایی که برای آیتم های منو تعریف کرده ایم ، متدی از این دست برای پاسخگویی بنویسیم.
Focus
فوکوس ، قابلیتی ست برای دریافت ورودیهای کاربر توسط کیبورد یا موس. فقط object یی که روی آن فوکوس شده میتواند رویدادهای کیبورد را دریافت کند. در زمان اجرای برنامه در هر فرم فقط یک کامپوننت میتواند فعال باشد یا به عبارت دیگر فقط روی یک کامپوننت میتوان فوکوس کرد.
روی بعضی از کامپوننتها مانند TImage، TPaintBox، TPanel و TLabel نمیتوان فوکوس کرد. در حالت کلی، کامپوننتهایی که از کلاس TGraphicControl مشتق میشوند ،قابلیت فوکوس پذیری ندارند به اضافه اینکه روی کامپوننتهایی که در زمان اجرا دیده نمیشوند نیز نمیتوان فوکوس کرد، مانند TTimer
OnKeyDown, OnKeyUp
هر دو رویداد OnKeyDown و OnKeyUp توانایی پاسخگویی به تمام کلیدهای کیبورد را دارند که شامل کلید های F1...F12 و کلیدهای ترکیبی (Shift, Ctrl, Alt) ست.
رویدادهای کیبورد ناسازگاری با هم ندارند، شاید تصور این باشد که وقتی کلیدی فشار داده میشود ، تداخلی بین رویدادهای OnKeyDown و OnKeyPress به وجود می آید، در صورتیکه چنین نیست.
وقتی کاربر کلیدی را فشار میدهد، رویدادهای OnKeyDown و OnKeyPress ایجاد میشوند و وقتی هم که کلید رها میشود ، رویداد OnKeyUp تولید میشود. هنگام فشاردادن کلیدی اگر رویداد OnKeyPress قادر به تشخیص آن نباشد، فقط رویداد OnKeyDown رخ میدهد و در ادامه آن هم OnKeyUp. ولی از نظر اولویت ،ابتدا OnKeyPress و سپس OnKeyDown اجرا میشوند.
وقتی کلیدی را پائین نگه میدارید، رویداد OnKeyUp بعد از اجرای تمام OnKeyDown ها و OnKeyPress ها اجرا میشود.
OnKeyPress
رویداد OnKeyPress کد اسکی متفاوتی را برای کارکترهای 'G'و 'g' برمیگرداند، اما OnKeyDown و OnKeyUp تفاوتی بین حروف بزرگ و کوچک قائل نمیشوند.
پارامترهای Key و Shift
وقتی که پارامتر Key به صورت by reference ارسال میشود ، رویداد مربوطه قابلیت تغییر کلید را دارد تا برنامه ، کلیدی متفاوت با آنچه فشار داده شده، ببیند. این راهی ست برای محدود کردن دسته ای از کاراکترهایی که کاربر میتواند وارد کند – برای مثال : جلوگیری از تایپ کاراکترهای حرفی توسط کاربر، با کد زیر :
if Key in ['a'..'z'] + ['A'..'Z'] then
Key := #0
دستور بالا پارامتر Key را برای دو دسته از کاراکترها، یعنی حروف بزرگ کاراکترها و حروف کوچک کاراکترها چک میکند. اگر کلید در این دو مجموعه بود، برای جلوگیری از ورود آن ، مقدار 0 به کلید تخصیص داده میشود در واقع کلید فشار داده شده بی اثر میشود(در مثال بالا فقط میخواهیم اعداد را دریافت کنیم).
برای کاراکترهای غیر حرفی-عددی میتوانید از virtual key code ها استفاده کنید. ویندوز برای کلیدهایی که کاربر میتواند فشار دهد ثابتهای ویژه ای تعریف کرده ست. برای مثال VK_RIGHT کد مجازی کلید "جهتی راست" هست (Right Arrow Key)
KeyPreview : هدایت رویدادهای کیبورد به سمت فرم
برای دریافت کلیدها در سطح فرم به جای پاس دادن کلید به کامپوننتهای روی فرم، ویژگی KeyPreview فرم را با True مقداردهی کنید. تصور نکنید که از این پس رویدادهای کیبورد روی کامپوننتها (کامپوننتهای روی فرم) اجرا نمیشوند، بلکه موقع فشار دادن یک کلید ابتدا رویدادهای فرم اجرا میشوند.
فرض کنید چند کامپوننت Edit روی فرم دارید و متد Form.OnKeyPress شبیه کد زیر هست :
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char) ;
begin
if Key in ['0'..'9'] then
Key := #0
end;
اگر فوکوس روی یکی از Edit ها باشد و ویژگی KeyPreview فرم مقدار False داشته باشد، این کد اجرا نخواهد شد. به این شکل که اگر کاربر کلید '5' را فشار دهد، کاراکتر '5' در کامپوننت Edit فوکوس شده ، نمایش داده میشود.
اما اگر ویژگی KeyPreview را با True مقداردهی کنید، OnKeyPress متعلق به فرم قبل از قرار گرفتن کلید فشار داده شده در کامپوننت Edit اجرا می شود ، یعنی اگر کاربر کلید '5' را فشار دهد ، if موجود در کد بالا مقدار 0 را به کلید می دهد و آن را بی اثر میکند.
سه رویداد نامبرده ، معادلی نیز در پیغام های ویندوز دارند. این پیغامها همگی از خانواده TWMKEY هستند که نشان دهنده پیغامی جهت کلید فشارداده شده ست.
رویداد OnKeyPress از پیغام WM_CHAR استفاده میکند.
رویداد OnKeyDown از پیغام WM_KEYDOWN استفاده می کند.
رویداد OnKeyUp از پیغام WM_KEYUP استفاده می کند.
نوشتن یک پروسیجر برای کنترل پیغام های ویندوز ، خیلی تفاوتی با نوشتن یک پروسیجر معمولی ندارد.
مواردی که میبایست در تعریف رعایت شوند ، عبارتند از : پارامتری از نوع خانواده پیغام مورد نظر، رهنمود message و نوع پیغام.
مثال:
تعریف :
procedure WMChar(var Msg: TWMChar); message WM_CHAR;
پیاده سازی :
procedure TForm1.WMChar(var Msg: TWMChar(;
begin
if Msg.CharCode = 13 then
// ShowMessage('Press');
end;
این متد دقیقاً رفتار رویداد OnKeyPress را برای فرم دارد.
OnKeyDown, OnKeyUp, OnKeyPress
رویدادهای کیبورد به همراه رویدادهای Mouse ،اساس اولیه ارتباط کاربر با برنامه شماست. این مطلب درباره سه رویدادی ست که شما را قادر می سازند کلیدهای فشرده شده توسط کاربر را دریافت و کنترل کنید.
برنامه های دلفی میتوانند از دو متد برای دریافت ورودی از کیبورد استفاده کنند. اگر یک کاربر عناصر مختلفی در یک برنامه داشته باشد، ساده ترین راه برای دریافت ورودی ها، استفاده از کنترلی ست که به صورت خودکار به کلیدهای فشرده شده پاسخ دهد، مانند Edit .
هر چند که در موقعیتهای متفاوت و برای مقاصد عمومی ، میتوانیم پروسیجری را در فرم ایجاد کنیم که سه رویداد را توسط فرم و یا هر کامپوننتی که ورودی کیبورد را قبول میکند، تشخیص دهد .
میتوانیم متدهایی را برای پاسخگویی به کلیدها یا ترکیب کلیدهای فشرده شده توسط کابر در زمان اجرای برنامه، بنویسیم :
OnKeyDown : موقعی فراخوانی میشود که کلیدی روی کیبورد فشار داده شود.
OnKeyUp : موقعی فراخوانی میشود که کلید فشرده شده روی کیبورد ، رها شود.
OnKeyPress : موقعی فراخوانی میشود که کلید متناظر با یک کاراکتر اسکی فشار داده شود.
همه رویدادهای کیبورد یک پارامتر عمومی دارند. پارامتر Key ، کلیدی روی کیبورد هست و به صورت by reference ارسال میشود. پارامتر Shift (در OnKeyDown و OnKeyUp) ، که در اثر فشار دادن یکی از کلیدهای Shift ، Alt یا Ctrl به عنوان کلیدهای ترکیبی مقدار دهی میشود. پارامتر Sender هم اشاره به کنترلی دارد که این متد را فراخوانی کرده ست.
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState) ;
...
procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState) ;
...
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char) ;
نیازی نیست برای Short-cut های تعریف شده، مانند Short-cut هایی که برای آیتم های منو تعریف کرده ایم ، متدی از این دست برای پاسخگویی بنویسیم.
Focus
فوکوس ، قابلیتی ست برای دریافت ورودیهای کاربر توسط کیبورد یا موس. فقط object یی که روی آن فوکوس شده میتواند رویدادهای کیبورد را دریافت کند. در زمان اجرای برنامه در هر فرم فقط یک کامپوننت میتواند فعال باشد یا به عبارت دیگر فقط روی یک کامپوننت میتوان فوکوس کرد.
روی بعضی از کامپوننتها مانند TImage، TPaintBox، TPanel و TLabel نمیتوان فوکوس کرد. در حالت کلی، کامپوننتهایی که از کلاس TGraphicControl مشتق میشوند ،قابلیت فوکوس پذیری ندارند به اضافه اینکه روی کامپوننتهایی که در زمان اجرا دیده نمیشوند نیز نمیتوان فوکوس کرد، مانند TTimer
OnKeyDown, OnKeyUp
هر دو رویداد OnKeyDown و OnKeyUp توانایی پاسخگویی به تمام کلیدهای کیبورد را دارند که شامل کلید های F1...F12 و کلیدهای ترکیبی (Shift, Ctrl, Alt) ست.
رویدادهای کیبورد ناسازگاری با هم ندارند، شاید تصور این باشد که وقتی کلیدی فشار داده میشود ، تداخلی بین رویدادهای OnKeyDown و OnKeyPress به وجود می آید، در صورتیکه چنین نیست.
وقتی کاربر کلیدی را فشار میدهد، رویدادهای OnKeyDown و OnKeyPress ایجاد میشوند و وقتی هم که کلید رها میشود ، رویداد OnKeyUp تولید میشود. هنگام فشاردادن کلیدی اگر رویداد OnKeyPress قادر به تشخیص آن نباشد، فقط رویداد OnKeyDown رخ میدهد و در ادامه آن هم OnKeyUp. ولی از نظر اولویت ،ابتدا OnKeyPress و سپس OnKeyDown اجرا میشوند.
وقتی کلیدی را پائین نگه میدارید، رویداد OnKeyUp بعد از اجرای تمام OnKeyDown ها و OnKeyPress ها اجرا میشود.
OnKeyPress
رویداد OnKeyPress کد اسکی متفاوتی را برای کارکترهای 'G'و 'g' برمیگرداند، اما OnKeyDown و OnKeyUp تفاوتی بین حروف بزرگ و کوچک قائل نمیشوند.
پارامترهای Key و Shift
وقتی که پارامتر Key به صورت by reference ارسال میشود ، رویداد مربوطه قابلیت تغییر کلید را دارد تا برنامه ، کلیدی متفاوت با آنچه فشار داده شده، ببیند. این راهی ست برای محدود کردن دسته ای از کاراکترهایی که کاربر میتواند وارد کند – برای مثال : جلوگیری از تایپ کاراکترهای حرفی توسط کاربر، با کد زیر :
if Key in ['a'..'z'] + ['A'..'Z'] then
Key := #0
دستور بالا پارامتر Key را برای دو دسته از کاراکترها، یعنی حروف بزرگ کاراکترها و حروف کوچک کاراکترها چک میکند. اگر کلید در این دو مجموعه بود، برای جلوگیری از ورود آن ، مقدار 0 به کلید تخصیص داده میشود در واقع کلید فشار داده شده بی اثر میشود(در مثال بالا فقط میخواهیم اعداد را دریافت کنیم).
برای کاراکترهای غیر حرفی-عددی میتوانید از virtual key code ها استفاده کنید. ویندوز برای کلیدهایی که کاربر میتواند فشار دهد ثابتهای ویژه ای تعریف کرده ست. برای مثال VK_RIGHT کد مجازی کلید "جهتی راست" هست (Right Arrow Key)
KeyPreview : هدایت رویدادهای کیبورد به سمت فرم
برای دریافت کلیدها در سطح فرم به جای پاس دادن کلید به کامپوننتهای روی فرم، ویژگی KeyPreview فرم را با True مقداردهی کنید. تصور نکنید که از این پس رویدادهای کیبورد روی کامپوننتها (کامپوننتهای روی فرم) اجرا نمیشوند، بلکه موقع فشار دادن یک کلید ابتدا رویدادهای فرم اجرا میشوند.
فرض کنید چند کامپوننت Edit روی فرم دارید و متد Form.OnKeyPress شبیه کد زیر هست :
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char) ;
begin
if Key in ['0'..'9'] then
Key := #0
end;
اگر فوکوس روی یکی از Edit ها باشد و ویژگی KeyPreview فرم مقدار False داشته باشد، این کد اجرا نخواهد شد. به این شکل که اگر کاربر کلید '5' را فشار دهد، کاراکتر '5' در کامپوننت Edit فوکوس شده ، نمایش داده میشود.
اما اگر ویژگی KeyPreview را با True مقداردهی کنید، OnKeyPress متعلق به فرم قبل از قرار گرفتن کلید فشار داده شده در کامپوننت Edit اجرا می شود ، یعنی اگر کاربر کلید '5' را فشار دهد ، if موجود در کد بالا مقدار 0 را به کلید می دهد و آن را بی اثر میکند.
سه رویداد نامبرده ، معادلی نیز در پیغام های ویندوز دارند. این پیغامها همگی از خانواده TWMKEY هستند که نشان دهنده پیغامی جهت کلید فشارداده شده ست.
رویداد OnKeyPress از پیغام WM_CHAR استفاده میکند.
رویداد OnKeyDown از پیغام WM_KEYDOWN استفاده می کند.
رویداد OnKeyUp از پیغام WM_KEYUP استفاده می کند.
نوشتن یک پروسیجر برای کنترل پیغام های ویندوز ، خیلی تفاوتی با نوشتن یک پروسیجر معمولی ندارد.
مواردی که میبایست در تعریف رعایت شوند ، عبارتند از : پارامتری از نوع خانواده پیغام مورد نظر، رهنمود message و نوع پیغام.
مثال:
تعریف :
procedure WMChar(var Msg: TWMChar); message WM_CHAR;
پیاده سازی :
procedure TForm1.WMChar(var Msg: TWMChar(;
begin
if Msg.CharCode = 13 then
// ShowMessage('Press');
end;
این متد دقیقاً رفتار رویداد OnKeyPress را برای فرم دارد.