PDA

View Full Version : سوال: آیا راهی برای طراحی ShortCut برای کامپوننت هست؟



mbshareat
چهارشنبه 29 شهریور 1391, 13:30 عصر
سلام
من یه کامپوننت دکمه دارم که میخوام با فشار یه ترکیب کلید کلیک بشه.
نمیخوام از HotKey استفاده کنم که اگه تو محیط برنامه هم نباشم کار کنه.
یه پروپرتی از نوع TShortCut تعریف کردم. توی Inspector اومد اما عملا با فشار ترکیب کلید تعریف شده توسط کاربر اتفاقی نمی افته! نمی دونم باید پیغامی رو هندل کنم و آیا اصلا ممکن هست یا مخصوص منو و Action هستش؟
لطفا راهنمایی کنین.

BORHAN TEC
چهارشنبه 29 شهریور 1391, 17:32 عصر
سلام
برای این کار شما مجبورید از RegisterHotKey استفاده کنید که نمونه ای در زیر وجود دارد:
http://www.swissdelphicenter.ch/torry/showcode.php?id=147

mbshareat
چهارشنبه 29 شهریور 1391, 23:07 عصر
سلام
ببخشید مزیت این روش(استفاده از GlobalAddAtom) چیه؟
من برنامه ای که در آدرس مذکور بود اجرا کردم مثل HotKey ساده وقتی توی برنامه دیگه هم هستیم کلید ها رو دریافت می کنه.
ولی من چیزی مثل بررسی کلیدها توسط KeyDown فرم با تنظیم ;KeyPreView:=True میخوام.
HotKey ساده تر کل نیازم رو برآورده نمی کنه. مگر اینکه پنجره فعال رو بررسی کنم!
ولی اونوقت نمی دونم اگه همون ترکیب کلید تو برنامه دیگه ای که در حال اجرا است کاربرد داشته باشه چطور کلید رو دریافت کنه؟
ساختار ساده زیر چه نیازی به GlobalAddAtom داره؟

TForm1 = class(TForm)
private
Procedure WMHotkey( Var msg: TWMHotkey ) ;message WM_HOTKEY;
public
..
end;
..
procedure TForm1.FormCreate(Sender: TObject);
begin
RegisterHotkey
(Handle, 1, MOD_Control, Ord('Q'));
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
UnRegisterHotkey( Handle, 1) ;
end;
Procedure TForm1.WMHotkey( Var msg: TWMHotkey ) ;
Begin
If msg.hotkey = 1 Then
Begin
If IsIconic( Application.Handle ) Then
Application.Restore;
BringToFront;
End;
End;

Felony
پنج شنبه 30 شهریور 1391, 16:53 عصر
من آخر نفهمیدم ؛ بلاخره میخواین تو سطح سیستم عامل این Hotkey رو ثبت کنید یا فقط برای پنجره برنامتون ، یک نمونه کامپوننت برای مورد اول براتون نوشتم .

موفق باشید .

mbshareat
جمعه 31 شهریور 1391, 00:19 صبح
سلام آقا مجتبی
فقط برای پنجره برنامه میخوام. نمیخوام مثل HotKey باشه که وقتی پنجره برنامه غیر فعال باشه هم کار کنه.
یه سوال هم در مورد کامپوننت شما داشتم. من کامپوننت رو نصب کردم Ctrl+E رو برای HotKey انتخاب کردم اما عمل نکرد.
من یه پیغام توی TMButton.WMHotKey قبل از بررسی (msg.WParam = 100) and ... گذاشتم اما با فشار کلید نمایش داده نمیشه.
گویا اصلا با فشار ترکیب کلید WMHotKey اجرا نشده.
کدتون درست به نظر میرسه اما برای من عمل نکرد. اگه ممکنه خوتون هم بررسی کنین.

vcldeveloper
دوشنبه 03 مهر 1391, 23:25 عصر
ساختار ساده زیر چه نیازی به GlobalAddAtom داره؟
هر Hotkey یک ID منحصر به فرد میخواد، تا بین اون و سایر Hotkeyها اختلال به وجود نیاد. GlobalAddAtom یک رشته میگیره و در یک فضای حافظه اشتراکی ذخیره میکنه، سپس یک ID برای اون رشته برگشت میده. اون وقت هر زمان که Process ایی نیاز به اون رشته داشته باشه، با داشتن ID اش، میتونه اون رو از سیستم عامل دریافت کنه. پس نقش GlobalAddAtom در اینجا فقط تولید ID منحصر به فرد برای Hotkey هست.

mbshareat
سه شنبه 04 مهر 1391, 08:44 صبح
آقای کشاورز سلام

با اینکه از GlobalAddAtom هم استفاده کردم باز کلید میانبر عمل نمی کنه.
کد مشکل داره یا اشکال از نسخه دلفی منه؟

unit ShortCutButton;

interface

uses
SysUtils, Classes, Controls, StdCtrls, Menus,
Windows, Messages, Dialogs;

type
TMButton = class(TButton)
private
FShortcut: TShortCut;
FKey: Word;
FModifiers: Uint;
HotKeyID:Integer;
function GetShortcut: TShortCut;
procedure SetShortcut(const Value: TShortCut);
procedure ShortCutToHotKey(HotKey: TShortCut; var Key: Word;
var Modifiers: Uint);
procedure WMHotKey(var msg: TMessage); message WM_HOTKEY;
{ Private declarations }
public
{ Public declarations }
destructor Destroy;
published
property HotKey: TShortCut read GetShortcut write SetShortcut;
end;

procedure Register;

implementation

procedure Register;
begin
RegisterComponents('Samples', [TMButton]);
end;

{ TMButton }

procedure TMButton.ShortCutToHotKey(HotKey: TShortCut; var Key: Word;
var Modifiers: Uint);
var
Shift: TShiftState;
begin
ShortCutToKey(HotKey, Key, Shift);
Modifiers := 0;
if (ssShift in Shift) then
Modifiers := Modifiers or MOD_SHIFT;
if (ssAlt in Shift) then
Modifiers := Modifiers or MOD_ALT;
if (ssCtrl in Shift) then
Modifiers := Modifiers or MOD_CONTROL;
end;

procedure TMButton.SetShortcut(const Value: TShortCut);
begin
FShortcut := Value;
ShortCutToHotKey(Value, FKey, FModifiers);
HotKeyID:=GlobalAddAtom('MButtonHotkey');
RegisterHotKey(Handle,HotKeyID,FModifiers,FKey);
end;

function TMButton.GetShortcut: TShortCut;
begin
Result := FShortcut;
end;

procedure TMButton.WMHotKey(var msg: TMessage);
begin
if (msg.WParam = HotKeyID) and (GetActiveWindow = GetParent(Handle)) then
Click;
{Caption:=BoolToStr(msg.WParam = HotKeyID)
+#13#10+Self.Parent.Name
+#13#10+IntToStr(GetParent(Handle))
+#13#10+IntToStr(GetActiveWindow);
Refresh;}
end;

destructor TMButton.Destroy;
begin
UnRegisterHotKey(Handle, HotKeyID);
GlobalDeleteAtom(HotKeyID);
end;

end.

MohsenB
سه شنبه 04 مهر 1391, 12:01 عصر
سلام

اگر که محدوده سطح عمل کلید فرم برنامه هست اصلا شما نیازی به استفاده از این روشها ندارید . از چندین راه ساده و اصولی تر میتونید استفاده کنید .

برای مثال :

یک ActionManager روی فرم قرار بدید و هر تعداد اکشنی که لازم دارید توی اون ایجاد کرده و با دوبار کلیک روی هر اکشن عمل مورد نظر خودتونو کدنویسی کنید . حالا برای انتصاب کلید میانبر کافیه بعد از انتخاب اکشن مورد نظر خصیصه ی ShortCut اون رو روی ترکیب مورد نظر قرار دهید .
این کار مزیت های زیادی داره . یکی ار اونا اینه که میتونید بعد از ساخت هر اکشن برای فراخونی اون بدون نیاز به اضافه کردن کد به برنامه فقط خصیصه Action از اون کنترل رو روی اکشن مورد نظر قرار دهید . همین .


همینطورند : ساخت منو و موارد مشابه


موفق باشید

mbshareat
سه شنبه 04 مهر 1391, 15:05 عصر
جناب MohsenB بحث طراحی کامپوننت بود. و اگه بشه برای خود دکمه به راحتی کلید میانبر کذاشت نیاز به دردسر طراحی Action و کار با کد مربوطه نیست!
یه مساله ای هست نمی دونم چرا GetActiveWindow = GetParent(Handle) نمیشه حتی وقتی پنجره فعال فرم برنامه باشه!
نمی دونم با وجود استفاده از GlobalAddAtom لازمه حتما پنجره فعال بررسی بشه؟

MohsenB
سه شنبه 04 مهر 1391, 19:05 عصر
جناب MohsenB بحث طراحی کامپوننت بود. و اگه بشه برای خود دکمه به راحتی کلید میانبر کذاشت نیاز به دردسر طراحی Action و کار با کد مربوطه نیست!
یه مساله ای هست نمی دونم چرا GetActiveWindow = GetParent(Handle) نمیشه حتی وقتی پنجره فعال فرم برنامه باشه!
نمی دونم با وجود استفاده از GlobalAddAtom لازمه حتما پنجره فعال بررسی بشه؟

سلام

ببخشید خوب مطالب رو نخوندم ، اصلا فکرم به این قضیه نبود .

خوب این چیزیو که گفتم هم بدرد میخوره ، شما برید درون کد منبعش ببینید چطور نوشته شده .

موفق باشید

mbshareat
سه شنبه 04 مهر 1391, 23:05 عصر
سلام
لطفا یه نفر این کدی که گذاشتم امتحان کنه ببینه مشکل از نسخه دلفی منه؟

mbshareat
چهارشنبه 05 مهر 1391, 14:06 عصر
سلام و درود
سالروز ولادت امام رضا (ع) رو پیشاپیش تبریک عرض می کنم.
این کد رو ملا حظه کنین:
unit ShortCutButton;

interface

uses
SysUtils, Classes, Controls, StdCtrls, Menus,
Windows, Messages, Dialogs;

type
TMButton = class(TButton)
private
FShortcut: TShortCut;
FKey: Word;
FModifiers: Uint;
ShortCutID:Integer;
function GetShortcut: TShortCut;
procedure SetShortcut(const Value: TShortCut);
procedure ShortCutToHotKey(ShortCut: TShortCut; var Key: Word;
var Modifiers: Uint);
procedure WMHotKey(var msg: TMessage); message WM_HOTKEY;
{ Private declarations }
public
{ Public declarations }
destructor Destroy;
published
property ShortCut: TShortCut read GetShortcut write SetShortcut;
end;

procedure Register;

implementation

procedure Register;
begin
RegisterComponents('Samples', [TMButton]);
end;

{ TMButton }

procedure TMButton.ShortCutToHotKey(ShortCut: TShortCut; var Key: Word;
var Modifiers: Uint);
var
Shift: TShiftState;
begin
ShortCutToKey(ShortCut, Key, Shift);
Modifiers := 0;
if (ssShift in Shift) then
Modifiers := Modifiers or MOD_SHIFT;
if (ssAlt in Shift) then
Modifiers := Modifiers or MOD_ALT;
if (ssCtrl in Shift) then
Modifiers := Modifiers or MOD_CONTROL;
end;
procedure TMButton.SetShortcut(const Value: TShortCut);
begin
FShortcut := Value;
ShortCutToHotKey(Value, FKey, FModifiers);
ShortCutID:=GlobalAddAtom('MButtonHotkey');
// FKey:=FKey+1;
// ShowMessage(Char(FKey));
RegisterHotKey(Handle,ShortCutID,FModifiers,FKey);
end;

function TMButton.GetShortcut: TShortCut;
begin
Result := FShortcut;
end;

procedure TMButton.WMHotKey(var msg: TMessage);
begin
if (msg.WParam = ShortCutID)
And (GetActiveWindow=GetParent(Handle)) then
Click;
end;

destructor TMButton.Destroy;
begin
UnRegisterHotKey(Handle, ShortCutID);
GlobalDeleteAtom(ShortCutID);
end;

end.
این کد به فشار کلید میانبر جواب نمیده.
یه مساله مضحک که پیش میاد اینه که اگه دو خط کدی که توی پروسیجر SetShortCut بعد از دو اسلش قرار دادم اسلش رو برداریم که اجرا بشه و بعد کاکتری که نمایش داده میشه به جای کلید ShortCut فشار بدیم جواب میده.
فرض کنین Ctrl+Q رو برای دکمه تعریف کردیم وقتی Ctrl+R رو بزنیم دکمه کلیک میشه!
کسی نظری نداره؟

mbshareat
شنبه 08 مهر 1391, 07:42 صبح
سلام به همگی
به این نتیجه رسیدم که پروسیجری که برای مقدار دهی به پروپرتی تعریف میشه برای مقدار دهی مفید نیست.
قبلا هم تو یه کامپوننت دیگه میخواستم بیت مپ رو مقدار دهی کنم نمیشد.
اگه اشتباه می کنم بفر مایین.
در هر صورت کامپوننت رو تغییر دادم و مقدار دهی HotKey رو توی یه پروسیجر دیگه انجام دادم مساله حل شد:
unit ShortCutButton;

interface

uses
SysUtils, Classes, Controls, StdCtrls, Menus,
Windows, Messages, Dialogs;

type
TShortCutButton = class(TButton)
private
FShortcut: TShortCut;
FKey: Word;
FModifiers: Uint;
ShortCutID:Integer;
function GetShortcut: TShortCut;
procedure SetHotKey;
procedure SetShortcut(const Value: TShortCut);
procedure ShortCutToHotKey(ShortCut: TShortCut; var Key: Word;
var Modifiers: Uint);
procedure WMHotKey(var msg: TMessage); message WM_HOTKEY;
{ Private declarations }
public
{ Public declarations }
destructor Destroy;
published
property ShortCut: TShortCut read GetShortcut write SetShortcut;
end;

procedure Register;

implementation

procedure Register;
begin
RegisterComponents('Samples', [TShortCutButton]);
end;

{ TShortCutButton }

procedure TShortCutButton.ShortCutToHotKey(ShortCut: TShortCut; var Key: Word;
var Modifiers: Uint);
var
Shift: TShiftState;
begin
ShortCutToKey(ShortCut, Key, Shift);
Modifiers := 0;
if (ssShift in Shift) then
Modifiers := Modifiers or MOD_SHIFT;
if (ssAlt in Shift) then
Modifiers := Modifiers or MOD_ALT;
if (ssCtrl in Shift) then
Modifiers := Modifiers or MOD_CONTROL;
end;
procedure TShortCutButton.SetHotKey();
begin
ShortCutToHotKey(FShortcut, FKey, FModifiers);
ShortCutID:=GlobalAddAtom('MButtonHotkey');
RegisterHotKey(Handle,ShortCutID,FModifiers,FKey);
end;
procedure TShortCutButton.SetShortcut(const Value: TShortCut);
begin
FShortcut := Value;
SetHotKey;
end;

function TShortCutButton.GetShortcut: TShortCut;
begin
Result := FShortcut;
SetHotKey;
end;

procedure TShortCutButton.WMHotKey(var msg: TMessage);
begin
if (msg.WParam = ShortCutID)
And (GetActiveWindow=GetParent(Handle)) then
Click;
end;

destructor TShortCutButton.Destroy;
begin
UnRegisterHotKey(Handle, ShortCutID);
GlobalDeleteAtom(ShortCutID);
end;

end.

mbshareat
یک شنبه 09 مهر 1391, 08:17 صبح
سلام
نمی دونم چی شده دیروز صبح به نظرم اومد کد بالا درست جواب میده ولی حالا هرچی امتحان می کنم کار نمی کنه؟

mbshareat
پنج شنبه 11 آبان 1391, 23:00 عصر
سلام
حالا کلید میانبر عمل می کنه اما Parent رو درست تشخیص نمیده!
اسم Parent رو اسم فرم گزارش می کنه اما هندلش اشتباه!
لطفا پروسیجر TTwoStatusBut.WMHotKey از یونیت زیر رو ملاحظه کنید: