以前「Windows画像とFAXビューアーを使えませんか」で質問させて頂いた新米です。
やっとFAXビューアーを使ったスライドショーのひな形を
「美味しい草なら 」さんのサンプルを元に、元来同一フォルダ内の再生用を
任意のフォルダのファイルを集めて
ファイルをListboxに取得してスライドショーをするように作りました。
質問は
(1)このアプリがFAXビューアーに隠れた状態で動くのが運命なので
キーアクションを取得するのにいろいろやってタイマーを付けておけばキーアクションを
取得してショーができましたが、タイマーのアクションに頼るのでレスポンスが悪い。
何かいい方法はないでしょうか。
(2)ShellExecute(Handle, 'OPEN', 'Rundll32.exe',PChar(・・で起動したFAXビューアーを
キーアクション(この例ではQ)で閉じることができないでしょうか。
参考サイトを見てやりましたが閉じてくれません。
以上2点ですっきりしません。よりよい方法をお願いします。
見苦しいコードですが最低動く要点を書いてみます。
var ListNo:integer;
//画像ファイルパスをListboxに登録する
procedure TForm1.Button1Click(Sender: TObject);
var
i:integer;
begin
Application.OnMessage := MsgHandler; //スライドショーのキーアクションキャッチ
ListBox1.Sorted:=true;
OpenDialog1.Options:=[ofAllowMultiSelect]; //複数のファイルを選択する
if OpenDialog1.Execute then
for i := 0 to OpenDialog1.Files.Count - 1 do
Listbox1.Items.Add(OpenDialog1.Files[i]);
ListNo:=0;
end;
//キーアクションの取得
procedure TForm1.MsgHandler(var Msg: TMsg; var Handled: Boolean);
var KeyNo:integer;
begin //次へZ
if (GetAsyncKeyState(90) <> 0) then begin Sleep(250);SlideShowDisp(1);exit;end
else //前へ A
if (GetAsyncKeyState(65) <> 0) then begin Sleep(250);SlideShowDisp(2);exit;end
else //Qは終了
if GetAsyncKeyState(81)<>0 then begin Sleep(250);SlideShowDisp(8);exit;end;
end;
//画像の表示
procedure TForm1.SlideShowDisp(const c:integer);
var
hd:HWND;
Path:string;
begin
if ListBox1.Items.Count=0 then exit;
case c of
1: begin ListNo:=ListNo+1;end; //------次へ Z
2: begin ListNo:=ListNo-1;end; //------前へ A
8: begin
hd := FindWindow('Rundll32.exe',nil);
SendMessage(hd, WM_CLOSE, 0, 0);
exit;
end;
else exit;
end;
if ListNo<0 then ListNo:=0;
if ListNo>ListBox1.Items.Count-1 then ListNo:=ListBox1.Items.Count-1;
Path:= 'shimgvw.dll,ImageView_Fullscreen '+ListBox1.Items.Strings[ListNo];
ShellExecute(Handle, 'OPEN', 'Rundll32.exe',PChar(Path), nil, SW_SHOW);
end;
//画面が隠れてもキーアクションをキャッチできるように
procedure TForm1.Timer1Timer(Sender: TObject);
begin
{nathing}
end;
だぶりました。すみません。自己レスです。
最初送信したら、サーバーがビジーです。と出たので
しばらくしてから、送信したら、二重になりました。
ご迷惑かけました。
とりあえず
1) Hotkey
2) CreateProcess
で実現可能だと思います。
1)KeyHook案もありますが、vistaの管理者制限を受けるため少ないキー数なら私はHotkeyをお勧めします。
2)ネットで調べた限りですが、ShellExecuteは投げ捨て関数らしくその後の制御はほぼできないらしいです。
1) タイマーで自分にメッセージを送って、無理やりメッセージループを回す
のはいかにも非効率ですね。自分でメッセージループを真似てループを回すと
いいです。
2) ビューワのクラス名は ShImgVw:CPreviewWnd なので
>hd := FindWindow('Rundll32.exe',nil);
ではなく
hd := FindWindow('ShImgVw:CPreviewWnd',nil);
とすると成功しますね。(Xp で確認)
とりあえずテストコードを示します。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls;
type
TForm1 = class(TForm)
OpenDialog1: TOpenDialog;
Button1: TButton;
ListBox1: TListBox;
procedure Button1Click(Sender: TObject);
private
{ Private 宣言 }
public
procedure GetKeyLoop;
procedure SlideShowDisp(const c:integer);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses
ShellAPI;
var
ListNo:integer;
flag :Boolean;
procedure TForm1.Button1Click(Sender: TObject);
var
i:integer;
begin
ListBox1.Sorted:=true;
OpenDialog1.Options:=[ofAllowMultiSelect]; //複数のファイルを選択する
if OpenDialog1.Execute then
for i := 0 to OpenDialog1.Files.Count - 1 do
Listbox1.Items.Add(OpenDialog1.Files[i]);
ListNo:=0;
flag := true;
GetKeyLoop;
end;
function IsKeyPushed(ch : Char): Boolean;
begin
result := (GetAsyncKeyState(ord(ch)) and $8000) <> 0;
end;
procedure TForm1.GetKeyLoop;
begin
while flag do
begin
Application.ProcessMessages;
Sleep(10);
if IsKeyPushed('Z') then begin Sleep(250);SlideShowDisp(1);end
else
if IsKeyPushed('A') then begin Sleep(250);SlideShowDisp(2);end
else
if IsKeyPushed('Q') then begin Sleep(250);SlideShowDisp(8);end
end;
end;
procedure TForm1.SlideShowDisp(const c:integer);
var
hd:HWND;
Path:string;
begin
if ListBox1.Items.Count=0 then exit;
case c of
1: begin ListNo:=ListNo+1;end; //------次へ Z
2: begin ListNo:=ListNo-1;end; //------前へ A
8: begin
hd := FindWindow('ShImgVw:CPreviewWnd',nil);
SendMessage(hd, WM_CLOSE, 0, 0);
flag := false;
exit;
end;
else exit;
end;
if ListNo<0 then ListNo:=0;
if ListNo>ListBox1.Items.Count-1 then ListNo:=ListBox1.Items.Count-1;
Path:= 'shimgvw.dll,ImageView_Fullscreen '+ListBox1.Items.Strings[ListNo];
ShellExecute(Handle, 'OPEN', 'Rundll32.exe',PChar(Path), nil, SW_SHOW);
end;
end.
皆さん有り難うございます。
monaaさんHOTkeyとはcontrolやshiftキーと組み合わせて登録する
ことですか、できれば一個のキーですませたいですが。
ShellExecuteはそれを覚えて閉じるとき使えないとサイトに書いてありました。起動した条件を覚えておいてそれを閉じるにはCreateProcess
でと書いてありましたが、C言語で理解できませんでした。
結構、「終了を知るには」はサイトが多くありますが、
閉じてしまうというのは意外とないです。
うんとさん、詳細な説明を有り難うございました。
正直まだまだ概論での説明では理解できないので助かりますし、
同時に実際のコードは勉強になります。
有り難うございました。
ツイート | ![]() |