PDA

View Full Version : مقاله: استفاده از HotKey ها



Mahmood_M
شنبه 06 شهریور 1389, 16:37 عصر
به نام خدا

استفاده از HotKey

با سلام ، در اين مقاله در مورد نحوه ی ثبت و استفاده از HotKey ها بحث خواهیم کرد ...
HotKey ها کلیدهای میانبری هستند که در سطح ویندوز تعریف می شوند ، هر برنامه ای در محیط ویندوز می تواند یک یا چند HotKey تعریف کند ، زمانی که کلیدهای مربوط به HotKey های تعرفی شده توسط کاربر فشرده شوند ، ویندوز اطلاعات مربوط به HotKey فشرده شده را به برنامه ی ثبت کننده ی HotKey به عنوان یک Message ارسال میکند ...

براي استفاده از يک HotKey بايد کليدهاي مورد نظر را به عنوان يک HotKey در ويندوز Register کنيم که اين کار توسط تابع RegisterHotKey انجام مي شود ...
وقتي يک HotKey تعريف مي کنيم ، بايد Handle برنامه اي که قصد داريم HotKey را دريافت کند را به همراه يک شماره به عنوان ID براي HotKey و همچنین کليدهاي مورد نظر را مشخص نماييم ..
HotKey ها چون در خود ويندوز ثبت مي شوند در خارج از برنامه ما نيز کاربرد خواهند داشت ، به عنوان مثال اگر برنامه ي ما در حالت Minimize باشد و HotKey مورد نظر ما در محيط ويندوز فشرده شود ، باز هم HotKey به برنامه ي ما ارسال خواهد شد و مي توانيم در واکنش به اين HotKey به عنوان مثال برنامه را از حالت Minimize به حالت Maximize در بياوريم ...
وقتي کليد ( يا کليدهاي ترکيبي ) در ويندوز فشرده مي شود ، در صورتي که کليد ( کليدهاي ) فشرده شده در ليست HotKey هاي Register شده وجود داشته باشد ، ويندوز HotKey فشرده شده را به هندل ثبت شده براي HotKey به عنوان يک پيغام WM_HOTKEY ارسال مي کند ، پيغام ارسالي حاوي يک رکورد از نوع TWMHotKey است ، اين رکورد يک مقدار به نام HotKey دارد که حاوي مقدار ID مربوط به HotKey است ، با بررسي اين مقدار مي توانيم تشخيص دهيم که آيا HotKey فشرده شده همان HotKey مورد نظر ما است يا خير ...

خوب ، بهتر است يک مثال را بررسي نماييم :
مي خواهيم يک HotKey تعريف کنيم که با فشرده شدن آن برنامه ي ما يک پيغام را به کاربر نمايش دهد ، ابتدا به صورت زير در رويداد OnCreate فرم يک HotKey با مقدار کليدهاي " Ctrl+Alt+M " ثبت مي کنيم :
procedure TForm1.FormCreate(Sender: TObject);
begin
RegisterHotKey(Handle, 10, MOD_CONTROL + MOD_ALT, 77);
end;
مقدار برگشتي تابع RegisterHotKey يک Boolean است ، اگر اجراي تابع موفقيت آميز باشد ، مقدار True و در غير اينصورت مقدار False را برميگرداند .
به پارامترهاي RegisterHotKey دقت کنيد ، در اولين پارامتر ما Handle پنجره ي برنامه ي خودمان را وارد کرديم، اگر به اين پارامتر مقدار Nil بدهيد ، ويندوز پيغام HotKey را به Thread اي که پنجره ي ما توسط آن ساخته شده ارسال خواهد کرد ، دومين پارامتر مربوط به ID اي است که براي HotKey در نظر مي گيريم که در اينجا عدد 10 انتخاب شده ، در پارامتر سوم بايد کليدهايي را مشخص کنيد که مي خواهيد حالت فشرده داشته باشند ! ، به عنوان مثال وقتي مي خواهيم کليدهاي Ctrl + Alt + M را فشار دهيم بايد ابتدا Ctrl و Alt را در حالت فشرده نگه داريم و سپس M را فشار دهيم !! ، پس در پارامتر سوم تابع بايد Ctrl و Alt را به عنوان کليدهايي که بايد در حالت فشرده باشند مشخص کنيم ، مقادير اين پارامتر ، مقادير زير يا ترکيبي از آنها مي تواند باشد :

MOD_ALT : براي مشخص کردن حالت فشرده براي کليد ALT
MOD_SHIFT : براي مشخص کردن حالت فشرده براي کليد Shift
MOD_Control : براي مشخص کردن حالت فشرده براي کليد Control
MOD_WIN : براي مشخص کردن حالت فشرده براي کليد Win


پارامتر آخر هم مربوط به مقدار عددي کليد M است ، در اين پارامتر مي توانيد مقدار يکي از کليدهاي حروف يا عدد يا ... صفحه کليد را وارد نماييد .

خوب ، تا اينجا يک HotKey تعريف کرديم ، در پايان کار برنامه بايد Hotkey تعريف شده را UnRegister کنيم !
يک سئوال : چرا HotKey ي Register شده را UnRegister مي کنيم ، نمي توانيم در اجراهاي بعدي برنامه ، دوباره از آن استفاده نماييم ؟
جواب : به عهده ي خواننده !

براي حذف HotKey تعريف شده مي توانيم در رويداد OnClose فرم اصلي از تابع UnRegisterHotKey استفاده نماييم :
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
UnregisterHotKey(Handle, 10);
end;
اين تابع مقادير Handle و ID مربوط به HotKey مورد نظر را مي گيرد و آن را حذف ميکند ...
اما قسمت مهم کار ايجاد يک Message Handler است که توسط آن بتوانيم به HotKey ارسال شده به برنامه جواب دهيم !
Message Handler درواقع يک Procedure است که در زمان دريافت پيغام خاصي اجرا خواهد شد ، براي ساخت همچين Procedure اي از عبارت message در انتهاي تعريف Procedure استفاده ميکنيم ، بعد از عبارت Message هم بايد نوع پيغام را مشخص نماييم :
procedure MSG_Hotkey(var msg: TWMHotkey ); message WM_HOTKEY;
مي توانيد اين Procedure را در قسمت Private فرم اصلي تعريف نماييد ...
بعد از تعريف اين Procedure در بدنه ي کلاس مربوط به فرم بايد اعلان خارجي ( External Declaration ) آن را هم بنويسيم :
procedure TForm1.MSG_Hotkey(var msg: TWMHotKey);
begin
if msg.HotKey = 10 then
begin
ShowMessage('HotKey Pressed !');
end;
end;
همانطور که در بالا هم اشاره شد پيغامي که به برنامه ارسال ميشود از نوع WM_HOTKEY بوده و شامل يک رکورد از نوع TWMHotKey است ، اين رکورد عضوي به نام HotKey دارد که مقدار ID مربوط به HotKey را حمل ميکند ! ، در دستور بالا ابتدا مقدار آن را بررسي مي کنيم ، اگر HotKey مورد نظر ما ( با مقدار 10 ) بود ، يک پيغام را به کاربر نمايش خواهيم داد ...

خوب ، تا اينجا با نحوه ي ايجاد و حذف يک HotKey آشنا شديم ، اما در آخر بهتر است چند نکته ي ديگر را هم مرور کنيم :

در هنگام ثبت HotKey ، اگر يک HotKey با همان ID موجود باشد ، HotKey ما ثبت نخواهد شد و تابع RegisterHotKey مقدار False را برگشت خواهد داد ، براي حل اين مشکل ، به يک ID يکتا نياز داريم ، در ويندوز جدولي سيستمي به عنوان Atom - Table وجود دارد که مي توانيم يک رشته را در آن ثبت کرده و يک مقدار عددی يکتا تحويل بگيريم ! ، در اين صفحه (http://barnamenevis.org/forum/showthread.php?t=209445) در مورد Atom - Table و نحوه ی استفاده از آن توضیحات بیشتری داده شده
در هنگام ثبت HotKey اگر ID و Handle وارد شده تکراری باشند ، HotKey جدید با HotKey موجود تعویض خواهد شد و کلیدهای جدید وارد شده به عنوان HotKey ثبت می شوند
یک برنامه در محیط ویندوز نمی تواند برای سایر برنامه ها HotKey تعریف کند ، درواقع هر Thread می تواند تنها برای Handle هایی که خودش Create کرده HotKey ثبت کند
اگر در هنگام ثبت HotKey مقدار Handle مورد نظر را وارد نکنیم ، ویندوز پیغام مربوط به HotKey را به صف پیغامهای مربوط به Thread ای که HotKey را ثبت کرده می فرستد


خوب ، برای درک بهتر ، یک مثال را با هم مرور می کنیم ...
در این مثال می خواهیم سه HotKey ثبت کنیم ، برای هر کدام می توانیم از Atom - Table یک مقدار عددی به عنوان ID دریافت نماییم ، در رویداد OnCreate فرم اصلی به صورت زیر HotKey ها را ثبت میکنیم :
procedure TForm1.FormCreate(Sender: TObject);
begin
// Get an Integer Value as ID
ID1 := GlobalAddAtom('HOTKEY_1');
ID2 := GlobalAddAtom('HOTKEY_2');
ID3 := GlobalAddAtom('HOTKEY_3');

// Register HotKeys
RegisterHotKey(Handle, ID1, MOD_CONTROL, 77); // Ctrl + M
RegisterHotKey(Handle, ID2, MOD_ALT, 78); // Alt + N
RegisterHotKey(Handle, ID3, MOD_CONTROL+MOD_ALT, 65) // Ctrl + Alt + A
end;

توجه کنید که متغیرهای ID1 ، ID2 ، ID3 باید به صورت Global ( عمومی ) تعریف شوند تا در رویداد OnClose ( یا OnDestroy ) فرم برای حذف HotKey ها هم بتوانیم از آنها استفاده نماییم :
var
Form1: TForm1;
ID1, ID2, ID3 : Integer;

implementation

برای دریافت پیغام HotKey همانطور که در بالا توضیح داده شد باید یک Message Handler بسازیم :
private
Procedure MSG_Hotkey(var msg: TWMHotkey ); message WM_HOTKEY;
{ Private declarations }
در بدنه ی Message Handler متناسب با هر HotKey یک پیغام را نمایش خواهیم داد :
procedure TForm1.MSG_Hotkey(var msg: TWMHotKey);
begin
if msg.HotKey = ID1 then
ShowMessage('First HotKey Pressed ( Ctrl + M)');
if msg.HotKey = ID2 then
ShowMessage('First HotKey Pressed ( Alt + N)');
if msg.HotKey = ID3 then
ShowMessage('First HotKey Pressed ( Ctrl + Alt + A)');
end;

و در پایان هم برای حذف HotKey ها در رویداد OnClose ( یا OnDestroy ) فرم اصلی از تابع UnRegisterHotKey استفاده می نماییم ، توجه کنید که دیگر نیازی به رشته های ثبت شده در Atom - Table و مقدار های عددی آنها نداریم و بهتر است آنها را نیز حذف نماییم :
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
UnregisterHotKey(Handle, ID1); // Unregister First HotKey
GlobalDeleteAtom(ID1); // Delete String "HORKEY_1" from Atom - Table

UnregisterHotKey(Handle, ID2); // Unregister Second HotKey
GlobalDeleteAtom(ID2); // Delete String "HORKEY_2" from Atom - Table

UnregisterHotKey(Handle, ID3); // Unregister Third HotKey
GlobalDeleteAtom(ID3); // Delete String "HORKEY_3" from Atom - Table
end;

مثال بالا ضمیمه شده ...

امیدوارم مفید بوده باشه ، موفق باشید ...

debugsg
شنبه 16 بهمن 1389, 21:07 عصر
سلام. اگر بخواهیم برای کلیدی مثل F10 هات کی بشازیم ، پارامتر سوم در دستور registerHotkey چگونه باید باشد. یعنی اگر بخواهیم نیازی به فشردن کلیدهای ترکیبی نباشد. تنها فشردن یک کلید مثلا تابعی کافی باشد؟
متشکرم.

Mask
چهارشنبه 20 بهمن 1389, 17:25 عصر
سلام. اگر بخواهیم برای کلیدی مثل F10 هات کی بشازیم ، پارامتر سوم در دستور registerHotkey چگونه باید باشد. یعنی اگر بخواهیم نیازی به فشردن کلیدهای ترکیبی نباشد. تنها فشردن یک کلید مثلا تابعی کافی باشد؟
متشکرم.
به جاش 0 بزارید.