処理の流れを一時停止するには?

解決


武田  2007-01-24 23:36:26  No: 24579

処理の一時停止の件を教えて頂けませんか。
環境はWindows XP  Delphi6 Personalです。
スライドショーを作成しています。
スペースバーを押されるまで待機して、押されたら次のファイルを表示するようにしています。
これでも動くのですが、待機中CPU使用率を見ると100%で気になります。
キーを押されるまで処理の流れを停止しておく何か他の方法はないかと調べたらコンソールアプリで  Readln;の例がありましたが、
コンソールアプリでないのでI/Oエラー6がでます。
よろしくお願いいたします。

repeat
   ImageDisp(ListBox1.Items[ListNo]);//指定した画像ファイルを表示する
   ・・
   ・・
   Sleep(400); //チャタリング防止
   //スペースキーを押されるまで待っている
   while (GetAsyncKeyState(VK_SPACE) = 0) do        
   begin
       Application.ProcessMessages;
     if  GetAsyncKeyState(VK_ESCAPE)<>0 then 
     begin SlideStop:=true;break;end;//ESCキーが押されたら終了
   end;
   ・・
   if GetAsyncKeyState(VK_SPACE) <> 0 then 
     ListNo:=ListNo+1; //スペースキーなら次の画像ファイルを指定
   ・・
until SlideStop=true;//終了フラグで抜け出す。


えーとね  2007-01-25 00:37:21  No: 24580

ループで待機するのではなく
TForm のOnKeyDown イベントなどを使ったら、どうでしょう。


武田  2007-01-25 07:23:32  No: 24581

え〜とさん、さっそく教えて頂いてありがとうございます。
実際はPageControlにTabsheetを貼り付けてそこにImageを動的に貼り付けて表示させています。
スライドショーはやってみると意外に難しくわたしの実力には荷が重いですが、動画があったときはImageにではなく、WindowsMediaPlayerを起動するようにしていますが、このときフォームにフォーカスはないのですがOnkeyDownが効くのか、動画再生中でもかまわず次の画像を指定するときなど、作用するのか判りませんが、いまからトライしてみます。

ありがとうございました。
また何かありましたら教えてください。


武田  2007-01-25 08:48:38  No: 24582

さっそくやってみましたが反応しません。何か基本的なことを忘れているのでしょう。
procedure TfrmMain.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
     ShowMessage('キーが押されました');
end;

PageControlにもImageにもOnkeyDownイベントがありませんでした。
引き続きトライしてみます。


えーとね  2007-01-25 09:53:27  No: 24583

> さっそくやってみましたが反応しません。
すみません。OnKeyPressでした。

> このときフォームにフォーカスはないのですが
TFormのイベントでは無理ですね。


orz  2007-01-25 17:21:20  No: 24584

Form.KeyPreview = True ってのは?


武田  2007-01-25 20:08:39  No: 24585

えーとねさん、orzさんさっそく教えて頂いてありがとうございます。
OnkeyPress でトライしてみます。
また、Form.KeyPreview = True は初めて知りましたが、OnkeyPressなどと組み合わせてできないがトライしてみます。
ただ、ヘルプによるとアスキーコード以外は発生しないと書いてありますから定番の矢印キーなど使えないのではと想像しますが文字キーなどに割り当てればいいのかなと考えます。
これらを工夫しながらトライしてみます。
今まで、ビューワーソフトにはさんざんお世話になっていたのですが、「ぱっぱっとファイルを切り替えるだけじゃないか」と軽く考えていました。
また何かあったら教えてください。
では。


さどやま  URL  2007-01-25 20:47:12  No: 24586

例えば

procedure TForm1.FormKeyUp(Sender: TObject;
                           var Key: Word;
                           Shift: TShiftState);
begin
  Case Key of
    VK_Space: Timer1.Interval := 500;
  end;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  // NextImage を表示するコード
end;

これは連続して次から次へ表示する場合です。
一つ一つ手動で表示したいのなら(質問ではそう読める)
TTimer は使用せず、Timer1.Interval := 500;
の行の変わりに、次の画像を表示するコードを入れます。

TEdit 等のように優先的にフォーカスを取り込むコントロールがある場合には、
Form1.KeyPreview := true にして FormKeyUp を有効にします。


武田  2007-01-26 02:38:54  No: 24587

さどやまさん、ありがとうございました。
未だ解決せず悪戦苦闘しています。
おっしゃるとおり手動で表示する場合です。
さっそくトライします。
では。


武田  2007-01-26 03:34:32  No: 24588

さどやまさん、結果報告をいたします。
スライドショーですからEditのようなコントロールはないのですが、ShellTreeView1でフォルダを選択させてフォルダにフォーカスが当たるので、
実行すると最初の一回は実行しますが次回は実行しませんでした。
procedure TformMDI.ShellTreeView1KeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  Case Key of
    VK_Space: ShowMessage('キーが押されました');
  end;
end;
以前、TRichEditの欠陥問題でTabキーが効かない対策として、どこかのサイトで見つけたものがあります。
理屈は判りませんが、たしかに、Tabキーが正常に作動します。
private
procedure CMDialogKey(var Msg: TMessage); message CM_DIALOGKEY;
・・・
procedure TformRich.CMDialogKey(var Msg: TMessage);
begin
    if (Msg.WParam = VK_TAB) and (ActiveControl = RichEdit1) then
       Msg.Result := 0
    else  Inherited;
end;
これも毎回キーを押されたのを監視しているので使えないかと試して見たのですが、Tabキー、矢印キー以外は検知しないようです。
文字キーや他のキーを検知するMessageでもあるのかなとトライしています。
では。
また、何かありましたら教えてください。


さどやま  URL  2007-01-26 05:35:07  No: 24589

> 未だ解決せず悪戦苦闘しています。
戦闘場所がどこか不明ですが、単純なコード例を示します。(Delphi3)
これにいろいろ加えていくとどこかで実現しなくなるのでしょう。
そこが本当の戦闘地域です。

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls,
  Forms, Dialogs, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    Image1: TImage;
  private
    FileList: TStringList;
    CurrentID: Integer;
  public
  end;

var
  Form1: TForm1;

implementation

procedure TForm1.FormCreate(Sender: TObject);
begin
  FileList := TStringList.Create;
//  KeyPreview := true;     // 必要に応じ
  FileList.Add('000.bmp');
  FileList.Add('001.bmp');
  FileList.Add('002.bmp');
  CurrentID := 0;   // 必要ないが
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FileList.Free;
end;

procedure TForm1.FormKeyUp(Sender: TObject;
                           var Key: Word;
                           Shift: TShiftState);
begin
  Case Key of
    VK_Space:
      begin
        Image1.Picture.LoadFromFile(FileList[CurrentID]);

        Inc(CurrentID);
        if CurrentID = FileList.Count then  CurrentID := 0;
      end;
  end;
end;

end.


さどやま  URL  2007-01-26 06:41:20  No: 24590

> 「ぱっぱっとファイルを切り替えるだけじゃないか」と軽く考えていました
  スライドショーに関して言えば、そう軽く考えていただいて結構です。

  ShellTreeView を使った事がないのですが、試してみました。
  Button1 をクリックすると MainPath に、現在選択されているフォルダが得られます。(Delphi7)

unit Unit3;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics,
  Controls, Forms, Dialogs, ExtCtrls, ComCtrls, ShellCtrls, StdCtrls;

type
  TForm1 = class(TForm)
    ShellTreeView1: TShellTreeView;
    Image1: TImage;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormKeyUp(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
    FileList: TStringList;
    CurrentID: Integer;
    MainPath: String;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  FileList := TStringList.Create;
  KeyPreview := true;     // 必要に応じ
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FileList.Free;
end;

procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  Case Key of
    VK_Space:
      begin
        Image1.Picture.LoadFromFile(FileList[CurrentID]);

        Inc(CurrentID);
        if CurrentID = FileList.Count then  CurrentID := 0;
        Key := 0;  // Button1.Click を無効にする
      end;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  MainPath := ShellTreeView1.Path + '\';
  // MainPath とFindFirst,Nextを使ってFileListにファイル名を
  // リストアップしたとする
  FileList.Add('000.bmp');
  FileList.Add('001.bmp');
  FileList.Add('002.bmp');

end;

end.


武田  2007-01-26 08:35:13  No: 24591

さどやまさん、ありがとうございました。
解決しました。
わたくしも、いろいろ、ない知識をかきむしりながら、なにかキーアクションを捕まえる方法がないものかと、ふと思い出して過去ログの
「WebBrowserでの入力が・・・」のなかに
本来、WebBrowser1で表示したページのテキストボックスの入力バグ対策があります。苦し紛れに考えたことですが
PageControlにWeb表示をしたり、Imageを表示したりするのだからと考え
procedure TForm1.MsgHandler(var Msg: TMsg; var Handled: Boolean);
の頭に取り出し口をもうけて
if (PageControl1.ActivePage as TTabSheet).Caption='スライドショー')  then
  begin
    if (GetAsyncKeyState(VK_SPACE) <> 0) then 
    begin Sleep(300);SlideShowDisp(1);end;//自前描画処理手続きへ
  end;
まことに無粋な方法ですが、上に動画ソフトが被さっていても実行しました。
しかしこれでは何か問題が起こるかもしれません。
助かりました。
ありがとうございました。


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

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






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