いつもお世話になります。いろいろ調べてみたのですが、判らずまた投稿させて頂きます。
1,Delphi2007+WinXPSP3です
2,メインフォーム(Form1)とフォーム2、フォーム3が自動生成設定。
3,やりたいこと:メインフォームのボタンをクリックすると、フォーム2を Hideし、その状態でキーボードの適当なキー操作で再度フォーム2を表示す る。
4,メインフォームのKeyPreviewをTrueにし、メインフォームに以下のコードを 実装します。
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if (GetKeyState(ord('Z')) < 0 )then Form2.Show;
end;
これで、メインフォームがフォーカスを持っている時は、フォーム2が表示されるのですが、フォーカスがフォーム3にある時は当然ながらキーボードイベントを受け取れません。操作する人がマウスでメインフォームをクリックすることなく、キー操作だけで、上記を実現することは出来ないのでしょうか?
よろしくお願いします。
そのアプリのどこかにフォーカスがあるとき、アプリ全体でキーボードを
監視できればいいんですよね。
D6以降は持ってないので確かめられませんが、すくなくともD6では、Application.OnMessage か、Additional タブのところにある TApplicationEvents コンポの OnMessage イベントで捕まえられます。
生のメッセージですから、自分でデコードしなければなりませんが。
どなたか試してくれませんか? 実行環境がないのでわたしはできません。
すみません。
Application系を使うなら、OnShortCutの方が
キーボードイベントしか来ない分扱いやすいかも。
Form1にActionListを置いてやって、アクションを一つ追加し
それのShortCutを設定するという方法もあります。
ちなみに、もし他のアプリケーションを操作中でもキーを受け取りたいという場合は
RegisterHotKeyあたりを使うことになります。
procedure TForm3.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if (GetKeyState(ord('Z')) < 0 )then Form2.Show;
end;
とするだけでは・・・・
過去に同じ悩みを持って、どっちみちドラッグドロップも使うので
兼業させた記憶があります。
どちらが正しい使い方かわかりませんが、教えてもらったまんま。
//=======AppMessageを使う場合=======
private
procedure AppMessage(var Msg: TMsg; var Handled: Boolean);overload;
procedure TForm1.FormCreate(Sender: TObject);
Application.OnMessage:= AppMessage;
DragAcceptFiles(TreeView1.Handle, True); //ドラッグドロップも使う場合
procedure TForm1.FormDestroy(Sender: TObject);
Application.OnMessage := nil;
procedure TForm1.AppMessage(var Msg: TMsg; var Handled: Boolean);
var
FileNames:array[0..255] of Char;
Files :Integer;
begin
if Msg.Message = WM_DROPFILES then
begin
DragQueryFile(Msg.wParam, 0, FileNames, Sizeof(FileNames) - 1);
Files := DragQueryFile(Msg.wParam, $FFFFFFFF, nil, 0);
if (FindDragTarget(Msg.pt,False) is TTreeView) then
begin
for i := 0 to Files - 1 do
begin
{ドラッグドロップの処理}
end;
end;
DragFinish(Msg.wParam);
Handled:= True;
end;
if GetAsyncKeyState(27)<>0 then
begin
Sleep(300);
{キーが押された場合の処理}
end;
end;
//======MsgHandler(を使う場合)=======
private
procedure MsgHandler(var Msg: TMsg; var Handled: Boolean);
procedure TForm1.FormCreate(Sender: TObject);
DragAcceptFiles(TreeView1.Handle, True);//ドラッグドロップも使う
Application.OnMessage := MsgHandler;
procedure TForm1.FormDestroy(Sender: TObject);
Application.OnMessage := nil;
procedure TForm1.MsgHandler(var Msg: TMsg; var Handled: Boolean);
var
FileNames:array[0..255] of Char;
Files :Integer;
begin
if Msg.Message = WM_DROPFILES then
begin
DragQueryFile(Msg.wParam, 0, FileNames, Sizeof(FileNames) - 1);
Files := DragQueryFile(Msg.wParam, $FFFFFFFF, nil, 0);
if (FindDragTarget(Msg.pt,False) is TTreeView) then
begin
for i := 0 to Files - 1 do
begin
{TreeViewへのドラッグドロップの処理}
end;
end;
DragFinish(Msg.wParam);
Handled:= True;
end;
if GetAsyncKeyState(27)<>0 then
begin
Sleep(300);
begin
{ESCキーキーが押されて時の処理}
end;
end;
end;
こんなやり方もあるということで。
procedure TForm3.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
Form1.FormKeyDown(Sender, Key, Shift);
end;
>ちなみに、もし他のアプリケーションを操作中でもキーを受け取りたいという場合は
>RegisterHotKeyあたりを使うことになります。
タイマーを使ってお手軽にやる場合の例。
procedure TForm1.Timer1Timer(Sender: TObject);
var
li_Code: SHORT;
begin
li_Code := GetAsyncKeyState(Ord('Z'));
if (BOOL(Hi(li_Code)) and BOOL(Lo(li_Code))) then begin
Beep;
end;
end;
皆様いろいろ情報有り難うございました。
Form3に同じコードを記述すれば良いのですが、フォームが増えていった場合には、同じコードをフォーム毎に記述するのは?と思いApplicationレベルで処理できないかと。
お陰様で解決致しました。有り難うございました。
ツイート | ![]() |