みなさんよろしくお願いします。環境はWindows7 Delphi6Personalです。
やりたいこと:
Vキーを押したら、画像を表示し、最前画面にFormをだす。
次に、Zキーを押したら、画像のパスをLabelにコピーしたい。
現象:
Zキーが効かない。Form1をクリックすれば、効きます。
画像を表示した後も、引き続きキーが効くようにする方法を教えて頂けませんか。よろしくお願いします。
type
TForm1 = class(TForm)
Label1: TLabel; //ココへパスをコピーする
Edit1: TEdit; //表示する画像のパスを置く
Button1: TButton; //当初フォーカスを置いておく
procedure FormCreate(Sender: TObject);
private
procedure MsgHandler(var Msg: TMsg; var Handled: Boolean);
public
end;
var
Form1: TForm1;
implementation
uses ShellAPI;
{$R *.dfm}
//Vキーを押すと画像を表示する。
//次にzキーを押してEdit1.textをコピーしたいがキーが効かない。
procedure TForm1.MsgHandler(var Msg: TMsg; var Handled: Boolean);
begin
if (GetAsyncKeyState(Ord('V')) and $8000)<>0 then
begin Sleep(300);
ShellExecute(Handle, 'OPEN', PChar(trim(Edit1.Text)+#0),nil, nil, SW_SHOWNORMAL);
SetWindowPos(Handle,HWND_TOPMOST,0,0,0,0,SWP_NOSIZE or SWP_NOMOVE);//最前面に表示する
end;
if (GetAsyncKeyState(Ord('Z')) and $8000)<>0 then
begin Sleep(300);
Label1.Caption:=Edit1.Text;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Application.OnMessage:= MsgHandler;
Edit1.Text:='C:\Users\yokoi\Desktop\xxx.JPG';//サンプル画像
ActiveControl:=Button1;//キーでEditに入力しないように
end;
簡単そうでなかなかうまくいかないものでした・・・
一応以下でできましたが・・・環境は同じです
procedure TForm1.MsgHandler(var Msg: TMsg; var Handled: Boolean);
procedure SetForceForegroundWindow(hTarget: HWND);
var
dwTargetID: DWORD;
dwActiveID: DWORD;
begin
dwTargetID := GetWindowThreadProcessId(hTarget, nil);
dwActiveID := GetWindowThreadProcessId(GetForegroundWindow, nil);
SetForegroundWindow(hTarget);
AttachThreadInput(dwTargetID, dwActiveID, True);
BringWindowToTop(hTarget);
AttachThreadInput(dwTargetID, dwActiveID, False);
end;
begin
if (GetAsyncKeyState(Ord('V')) and $8000) <> 0 then begin
ShellExecute(Handle, 'OPEN', PChar(trim(Edit1.Text)+#0),nil, nil, SW_SHOWNORMAL);
Sleep(300);
SetForceForegroundWindow(Application.Handle);
Application.ProcessMessages;
SetForegroundWindow(Form1.Handle);
end;
if (GetAsyncKeyState(Ord('Z')) and $8000) <>0 then begin
Label1.Caption:=Edit1.Text;
end;
end;
おそらく横井さんのやりたいこととは違うと思いますが、ご参考までに。
(なお、、、なぜApplication.OnMessageを使っているのか、私には分からないのですが…??)
uses
ShellAPI;
procedure TForm1.FormCreate(Sender: TObject);
begin
Self.FormStyle:=fsStayOnTop;
Self.KeyPreview:=True;
Edit1.Text:='C:\Users\yokoi\Desktop\xxx.JPG'; // サンプル画像
Self.ActiveControl:=Button1;
end;
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
case Key of
Ord('V'): ShellExecute(Self.Handle, 'open', PChar(Trim(Edit1.Text)), nil, nil, SW_SHOWNA); // SW_SHOWNOACTIVATE
Ord('Z'): Label1.Caption:=Edit1.Text;
end;
end;
>簡単そうでなかなかうまくいかないものでした・・・
アプリケーションウィンドウに対応した,Vista 対応バージョンの Delphi だと
以下のようなコードでも動作しますね.
他のバージョンの Delphi をお持ちの方への参考として.
動作確認環境は,Windows 7 U64(SP1) + Delphi 2007-R2, Delphi 2009, 2010, XE
if Msg.message = WM_KEYDOWN then begin
if Chr(Msg.wParam and $FF) = 'V' then begin
ShellExecute(Handle,
'OPEN',
PChar(Trim(Edit1.Text)),
nil,
nil,
SW_SHOWNA);
//時間は起動するアプリによっては,もっと必要な場合がある
Sleep(100);
SetForegroundWindow(Handle);
Label1.Caption := Chr(Msg.wParam and $FF);
end else
if Chr(Msg.wParam and $FF) = 'Z' then begin
Label1.Caption := Edit1.Text;
end;
end;
>アプリケーションウィンドウに対応した,Vista 対応バージョンの Delphi だと
>以下のようなコードでも動作しますね.
>他のバージョンの Delphi をお持ちの方への参考として.
ゴメンナサイ.
IDE から実行した場合はそうなりますが,EXE を直接起動した場合は
フォーカス移動しませんでした.
やっぱり工夫が必要ですね.
deldelさん、Harryさん、Mr.XRAY さんありがとうございます。
私ごときが理解できるレベルではないでした。
現実にはありそうな処理ですが
実際のコードはもっと複雑で、テストしております。
結果が出たらまた報告させて頂きます。
今回は解決とさせて頂きます。
ありがとうございました。
>環境はWindows7 Delphi6Personalです。
Windows 7 で JPEG 画像を表示するんですよね.
Windows フォトビューワ が起動していると思います.
ShellExecute の引数を以下のようにして,Windows フォトビューワを指定して起動してみてください.
var
ViewerdllPath : String;
ImagePath : String;
begin
ViewerdllPath := 'C:\Windows\system32\shimgvw.dll, ImageView_Fullscreen ';
ImagePath := Trim(Edit1.Text);
ShellExecute(Handle,
'OPEN',
'Rundll32.exe',
PChar(ViewerdllPath + ImagePath),
nil,
SW_SHOWNORMAL);
Sleep(300);
SetForegroundWindow(Handle);
動作確認は Windows 7 U64(SP1) + Delphi 7 Pro です.
Delphi 6 は現在使えない状態なので.
(質問のレス用に,正常に起動できないテストをして,そのままなので)
確実にやるには,ShellExecuteEx か CreateProcess で起動して,
Windows フォトビューワが完全に起動完了したのを確認してから
SetForegroundWindow(Handle); を実行するようにします.
しかし,Windows 7 で Delphi 6 は厳しいですね.
>私ごときが理解できるレベルではないでした。
理解できるできないに関わらず,やってみることだと思いますよ.
でなければ永遠に理解できませんからね.
もし,上のコードが理解できないからやらない,というのであれば,無視してください.
他の方にも参考にはなると思いますのでレスしておきます.
テストの結果を報告させて頂きます。
deldel さん。
ほぼ完璧でした、使わせて頂きます。
ただキーのチャタリング防止のSleep(300);はあった方がよいようなきがしました。
Sleep(300);
ShellExecute(Handle, 'OPEN', PChar(trim(Edit1.Text)+#0),nil, nil, SW_SHOWNORMAL);
Sleep(300);
Harry さん、ありがとうございました。
おっしゃるとおりMsgHandlerでメッセージをつかまえ
外部アプリを起動後に、フォーカスを取り戻すのがテーマでした。
ので目的が違いました。
Mr.XRAY さん、ありがとうございました。
起動したForm1を画像が表示されるだろう場所に移動して実行すると
Sleep(300);
SetForegroundWindow(Handle);
では、少なくとも私の環境では、Form1が画像の後面になりキーも効きませんでした。
以上報告させて頂きました。
おかげで解決しました。ありがとうございました。
>起動したForm1を画像が表示されるだろう場所に移動して実行すると
> Sleep(300);
> SetForegroundWindow(Handle);
>では、少なくとも私の環境では、Form1が画像の後面になりキーも効きませんでした。
え !?
質問された方が動作すれば,コードは何でもいいのですが.
フォトビューアの起動が重たい (時間がかかる,遅い) のかな ?
でも,スレッドアタッチでは 300 ms で動作しているんだから ....
う〜む.困った.
いえ,横井さんには関係ないけど,個人的に悩みが増えました.