こんにちは。
いつも参考にさせていただいております。
以前に「TDateTimePickerのドロップとクローズについて」という事で
下記の動作の実現方法をご質問をさせて頂き、以下のサンプルコードをご教授頂きました。
①TDateTimePickerにフォーカスセットでカレンダーをドロップダウン
②そのまま変更せずにENTER押下で、カレンダーをクローズし次のコントロールにフォーカス
procedure TForm1.DateTimePicker1Enter(Sender: TObject);
begin
keybd_event(VK_LMENU, 0, 0, 0);
keybd_event(VK_DOWN, 0, 0, 0);
keybd_event(VK_DOWN, 0, KEYEVENTF_KEYUP, 0);
keybd_event(VK_LMENU, 0, KEYEVENTF_KEYUP, 0);
end;
procedure TForm1.DateTimePicker1CloseUp(Sender: TObject);
begin
//フォーカス移動処理
end;
上記で私の望んでいました①②は実現出来たのですが、カレンダーが
ドロップダウンした状態でマウスで画面にあるボタンをClickすると、
複数連続しているDateTimePickerが次々とドロップダウンとクローズを
繰り返します。
OnCloseUpイベントにファーカス移動処理を書いているので当然なのですが、
このような動作を回避する手段はないものでしょうか?
どうかご教授下さいませ。
Delphi7を使っています。
Halbow です。
> ②そのまま変更せずにENTER押下で、カレンダーをクローズし次のコントロールにフォーカス
これをいかのようにしたらよいと思います。
procedure TForm1.DateTimePicker1KeyUp(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if Key = VK_RETURN then
//フォーカス移動処理
end;
Halbowさんありがとうございます。
早速試してみましたところ、一つ目のDateTimePickerにフォーカスが
移動した際に、一つ目と二つ目のDateTimePicker
が同時にドロップダウンされました。
フォーカスも二つ目に移動しています。
もう一度ENTER押下で、二つ目がクローズ、
三つ目がドロップダウンされ、一つ目はドロップダウン
されたままです。
どうやら、一つ目にはFormKeyPressでENTER押下時に行っている
フォーカス移動処理で移動し、DateTimePickerのKeyUpイベントで
さらにフォーカスが移動しているようです。
フォーカス移動処理は、
if Key = char(VK_RETURN) then
begin
FindNextControl(Form1.ActiveControl, True, True, False).SetFocus;
end;
で行っています。
もう一息という感じで、色々試しているのですが、
もしよい情報をお持ちの方がいらしゃいましたら、ご教授ください。
宜しくお願います。
Halbow です。
> どうやら、一つ目にはFormKeyPressでENTER押下時に行っている
> フォーカス移動処理で移動し、DateTimePickerのKeyUpイベントで
> さらにフォーカスが移動しているようです。
フォーカスの移動のコードがあちこちにあって、それを全部知らないと
これ以上のアドバイスはできないと思います。
度々ありがとうございます。
>フォーカスの移動のコードがあちこちにあって、それを全部知らないと
>これ以上のアドバイスはできないと思います。
ごもっともでございます。
フォーカス移動は、元々「FormKeyPressでENTER押下時のみ」です。
しかしこれだけでは、
ENTER押下 1回目 DateTimePickerがフォーカス取得、ドロップダウン
ENTER押下 2回目 DateTimePickerがフォーカスのまま、クローズ
ENTER押下 3回目 フォーカス移動
という動作になり、「ENTER押下でカレンダーをクローズし、次のコントロールにフォーカス」が実現出来なくて困っておりました。
そこで、アドバイス頂いたOnCloseUpイベントやOnKeyUpイベントにフォーカス移動処理を追加した、というのがこれまでの経緯です。
現在は「FormKeyPressでENTER押下時のみ」と「OnKeyUpイベントでENTER押下時のみ」の2箇所にフォーカス移動処理が入っています。
カレンダーがドロップダウンされている状態でENTER押下時に、FormKeyPressイベントが発生すれば問題ないのですが、そうもいかないようなのです。
何か情報を頂けないでしょうか。
回答というわけではありませんが、キー入力関連のイベントについて...
OnKeyPressイベントは、キーが押されかではなく文字が入力されたときに呼び出されます。厳密な意味でキーが押されたときに処理をしたければOnKeyDownイベントかOnKeyUpイベントを使うのが正解です。
通常、何かキーが押されると...
OnKeyDown(キーが押された)
↓
OnKeyPress(文字入力)
↓
OnKeyUp(キーを離された)
の順番に発生します。
ただし、押されたキーが文字キー以外またはコントロールが文字入力を受け付けないような場合、OnKeyPressは発生しません。
だから、TDateTimePickerのドロップダウン中にENTERキーを押してもOnKeyPressは発生しないし、OnKeyPressやOnKeyDownで強制的にフォーカス移動する場合など、続いて発生するOnKeyPress,OnKeyUpのことを考えてないと予想外の動作をするわけです。
よって、単純にTDateTimePickerの...
・OnEnterでカレンダーのドロップダウン
・OnKeyUpでENTERキーでフォーカス移動
とすればうまく行くと思いますよ。
masayanさん、ありがとうございます。
キー入力関連のイベントについて理解が深まりましたっ。
今回は正に
>予想外の動作をするわけです。
な訳です・・・
「OnKeyUpでENTERキーでフォーカス移動」によって、
TDateTimePickerからTDateTimePickerへの移動は問題なく行えています。
ただ、一つ目のTDateTimePickerへENTER押下でフォーカスが来た時だけ、
OnKeyUpイベントが2回走り、予想外な動作になっています。
TDateTimePickerにフォーカスが来た時に、カレンダーがドロップダウン
しているかどうかが判断出来れば、制御が出来そうに思うのですが、
そんな事は出来るのでしょうか?
(ヘルプで調べようとするもですが、英語しかないです・・・)
TDateTimePickerにDroppedDownというのがありますのでこれで判断できると思いますよ。
DroppedDownは、ドロップダウン中であればTrueを返します。(←ちなみに読み取り専用プロパティです。)
Halbowさん、masayanさんありがとう御座いました。
下記のように、ドロップダウンしている時はフォーカス移動処理は行わないように
する事で、上手くいっているようです。
度々のアドバイスありがとうございました。
procedure TForm1.procDtpKeyUp(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if Key = VK_RETURN then
begin
if TDateTimePicker(Sender).DroppedDown = true then
begin
exit;
end;
//フォーカス移動処理
end;
end;
ツイート | ![]() |