一定時間のアイドルでプログラムを終了したい

解決


かぐらなんばん  2011-12-09 22:39:18  No: 41313

delphi XE2です。
データベース接続をしたアプリを200人ほどで使用しています。
プログラムを終了しないで帰宅してしまう人が毎日いて困っています。
一定時間キーの操作がなかったら自動的にシャットダウンする機能を組み込みたいと思いますが、OnIdle等の項目で探しますが、うまくゆきません。
どなたか、ご教示お願いします。


monaa  2011-12-10 04:01:25  No: 41314

windowsの標準で用意されている動作なのでOSに任せるのが無難じゃないっすか?


かぐらなんばん  2011-12-10 07:48:04  No: 41315

質問が、適切ではありませんでした。
「シャットダウン」というのは、PCのシャットダウンではなく、プログラムの終了処理を実行するという意味です。訂正します。


monaa  2011-12-10 10:53:40  No: 41316

procedure TForm1.FormCreate(Sender: TObject);
begin
  fLastTouchMSec := GetTickCount;
  Timer1.Interval := 1000;
  Timer1.Enabled := True;
end;

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  fLastTouchMSec := GetTickCount;
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  fLastTouchMSec := GetTickCount;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
  IdleMSec:Cardinal;
begin
  IdleMSec := GetTickCount - fLastTouchMSec;
  Caption := '最後に触ってから' + IntToStr(IdleMSec div 1000) + '秒経過';
  //10sec
  if IdleMSec > 10*1000 then
    Close;
end;

50日以上PCを再起動しない場合があるときは、タイマーでカウントアップしたりしてください。
http://msdn.microsoft.com/ja-jp/library/cc429827.aspx

Vista,7なら似た様な関数でもっとバッファの大きな関数があります。
GetTickCount64
http://msdn.microsoft.com/ja-jp/site/ms724411
QueryUnbiasedInterruptTime
http://msdn.microsoft.com/ja-jp/site/dd405535
https://www.petitmonte.com/bbs/answers?question_id=7040


monaa  2011-12-10 11:02:08  No: 41317

失礼!大体10時間という程度の精度ならTDateTimeの方が適役です。

fLastTouchDate:TDateTime;

procedure TForm1.FormCreate(Sender: TObject);
begin
  fLastTouchDate := Now;
  Timer1.Interval := 1000;
  Timer1.Enabled := True;
end;

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  fLastTouchDate := Now;
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  fLastTouchDate := Now;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
  IdleSec:Cardinal;
begin
  IdleSec := Round((Now - fLastTouchDate) * 24 * 60 * 60);
  Caption := '最後に触ってから' + IntToStr(IdleSec) + '秒経過';
  //10sec
  if IdleSec > 10 then
    Close;
end;


かぐらなんばん  2011-12-11 15:34:40  No: 41318

monaaさん、ありがとうございました。
例示のソースで、小さなテストプログラムを作って成功しました。
しかし、実際のプログラムには、FormにEdit、DBEdit、ボタンほか、沢山のコントロールがのっかっています。
Formのエベントへの記載だけでは、たとえばEditの入力中にも時間が経過することになります。
「Edit等に入力中はタイマーが進行しないようにする」には、私の知識では、沢山あるすべてのコントロールのOnKeyDown、OnMoseMoveで、「fLastTouchDate := Now」を呼び出すこととしか思い浮かびません。
『プログラムがIdleでなくなったとき、 fLastTouchDate := Now 』みたいな、便利なエベントはないでしょうか。


KHE00221  2011-12-12 00:01:57  No: 41319

>一定時間キーの操作がなかったら自動的にシャットダウンする機能を組み込みたいと思いますが、OnIdle等の項目で探しますが、うまくゆきません。

他のアプリの操作なんかは除外?

スクリーンセーバー起動感知で終了させたら?


  2011-12-12 00:10:54  No: 41320

ApplicationEventsコンポーネントのOnMessageで、
WM_KeyDownが飛んできたらタイマーをリセットすると
いう方式では?


monaa  2011-12-12 00:44:30  No: 41321

>ApplicationEventsコンポーネントのOnMessageで
procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;
  var Handled: Boolean);
begin
  case Msg.message of
    WM_KEYDOWN,
    WM_MOUSEMOVE:
      fLastTouchDate := Now;
  end;
end;

他にも方法はあります。
自アプリをいじらないなら、
タスクスケジューラ起動でそのアプリを終了させるアプリを作るとか。


かぐらなんばん  2011-12-12 05:11:25  No: 41322

「あ」さん、「monaa」さん、ありがとうございました。
case Msg.message of
    WM_KEYDOWN,
    WM_MOUSEMOVE:
      fLastTouchDate := Now;
  end;
end;
を組み込んで、うまくゆきそうです。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加