自分をアクティブにするにはSetForegroundWindowでいけるのですが、自分を非アクティブにする方法はあるのでしょうか?
やりたいことは自分のひとつ前に起動したプログラムをアクティブにしたいんです。
ただひとつ前のプログラムはブラウザーでツールが何かは環境によって違うためFindWindowは使えません。
GetNextWindowでとれるかと思ったんですが無理でした。
ブラウザー起動、作成プログラム起動、ここでGetNextWindowのGW_HWNDNEXTかGW_HWNDPREVでブラウザー取れると思ったんですが、IMEやtooltips_class\32を拾ってだめでした。
単純にSetBackgroundWindowって命令があると思ったんですがないんですね。
> ここでGetNextWindowのGW_HWNDNEXTかGW_HWNDPREVでブラウザー取れると思ったんですが、IMEやtooltips_class\32を拾ってだめでした。
その方針で、画面に表示されていないウィンドウは飛ばすようにすればいいのではないでしょうか。
wnd := Application.Handle;
while IsWindow(wnd) do
begin
wnd := GetNextWindow(wnd, GW_HWNDNEXT);
if IsWindowVisible(wnd) then
begin
SetForegroundWindow(wnd);
Break;
end;
end;
もし自分自身がアクティブになるのを防ぎたいという目的だったら、
状況によってもっと適した方法がありそうですけれど。
torさん、レスありがとうございます。
IsWindowVisibleというのは知りませんでした。
入れてみたんですが「Button」「Shell_TrayWnd」「Afx:400000:b:401d7:5:10225」とかもそちらに入ってしまって判断は難しいですね。
ブラウザ起動してこのプログラム起動してるのでGetNextWindowですぐブラウザ見つけられると思ったんですがそんな単純ではないようですね。
やりたいのはIE系のプログラムを立ち上げ、このプログラムを起動して自動的に名前やメールアドレスを貼り付けるというものです。
名前やメールアドレスの貼り付けは出来たんですが、IE系のプログラムを見つけるのがうまくいかなくて。
ブラウザーを固定にすればGetNextWindowで条件の見つかるまで回せばいけてますがブラウザーツール変えると対応できないのでいろいろ試行錯誤してます。
自分が最小化(Minimize)すると、自分の前にアクティブだったプログラムが
アクティブになるけど、そういう使い方ではないのかな?
最小化するなら、GetForegroundWindowで拾えると思うけど。
>>入れてみたんですが「Button」「Shell_TrayWnd」「Afx:400000:b:401d7:5:10225」とかもそちらに入ってしまって判断は難しいですね。
これはたぶん子ウインドウを排除するようにすれば解決すると思います。
そこで、このことを考慮して、torさんのコードを少し変更してみました。
wnd:=Application.Handle;
while True do begin
wnd:=GetNextWindow(wnd,GW_HWNDNEXT);
if IsWindowVisible(wnd) then begin
//親ウィンドウのハンドルがある、つまり子ウインドウ
//子ウインドウは対象外
while GetParent(wnd)>0 do wnd:=GetParent(wnd);
SetForegroundWindow(wnd);
Break;
end;
end;
これで、作成プログラムの直前にアクティブだったウインドウが表示されます。
ただ、ブラウザの起動も作成されたプログラムから起動するようにすれば、その方法にもよるとは思いますが、ブラウザウインドウのハンドルも処理の一環で取得できて、スマートだと思います。
>IE系のプログラムを見つけるのがうまくいかなくて。
EnumWindows APIとEnumChildWindows APIを使うのが良いのではと思います。
多分「Internet Explorer_Server」というクラス名の子ウィンドウがあるのがIE系のブラウザだと思うので、まずEnumWindows APIでトップレベルのウィンドウを取得してからEnumChildWindows APIでInternet Explorer_Serverというクラス名の子ウィンドウがあるか探し、なければ次のトップレベルウィンドウの子ウィンドウを探索していく...というような流れで。
function ClassNameGet(hHandle: HWND): String;
//ウィンドウハンドルhHandleのクラス名を返す
const
lci_LEN = 256;
var
lp_Buff: PChar;
begin
Result := '';
lp_Buff := AllocMem(lci_LEN +1);
try
GetClassName(hHandle, lp_Buff, lci_LEN -1);
Result := String(lp_Buff);
finally
FreeMem(lp_Buff);
end;
end;
var
G_hIEWindow: HWND;
function EnumChildWindowProc(hHandle: HWND; iParam: LPARAM): Bool; stdcall;
//子ウィンドウを列挙して調べる
begin
if (ClassNameGet(hHandle) = 'Internet Explorer_Server') then begin
//IE系の子ウィンドウがあった
G_hIEWindow := hHandle;
Result := False;
end else begin
Result := True;
end;
end;
function EnumWindowProc(hHandle: HWND; iParam: LPARAM):BOOL; stdcall;
//トップレベルウィンドウを列挙
begin
if (IsWindowVisible(hHandle)) then begin
EnumChildWindows(hHandle, @EnumChildWindowProc, 0);
Result := (G_hIEWindow = 0);
end else begin
Result := True;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
//探すIE系プログラムが最小化されていると失敗することに注意
begin
//第2引数を利用して処理しようとするとややこしいのでグローバル変数を利用
G_hIEWindow := 0;
EnumWindows(@EnumWindowProc, 0);
if (G_hIEWindow = 0) then begin
ShowMessage('失敗');
end else begin
SetForegroundWindow(G_hIEWindow);
end;
end;
これで無理?
var
H: HWND;
procedure TForm1.FormActivate(Sender: TObject);
begin
SetForegroundWindow(H);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
H := GetForegroundWindow;
end;
ぽむぽむさん、それです! それでバッチリいけました!
ハンドルとる関数をこんな感じにしました。
begin
Application.Minimize;
hWindow :=GetForegroundWindow;
Application.Restore;
result:=hWindow;
end;
ありがとうございました!
おもさん、なぜかうまくいきませんでした。
IE関係でないものでbreakしてしまいました。
Dさん、ソースそのまま使わせてもらったらいけました!
IEでも別のブラウザーツールでもとれました。
ありがとうございました!
KHE00221さん、Shell_TrayWndが返ってきたり別のが返ってきたりでだめでした。
デスクトップからショートカット起動するタイミングでデスクトップがフォアになってしまうのでしょうかね。
みなさんのおかげで無事に目的の動きを再現できました。
どうもありがとうございました!
ツイート | ![]() |