自分を非アクティブにしたい

解決


ロック  2010-07-07 00:39:19  No: 38767

自分をアクティブにするにはSetForegroundWindowでいけるのですが、自分を非アクティブにする方法はあるのでしょうか?

やりたいことは自分のひとつ前に起動したプログラムをアクティブにしたいんです。
ただひとつ前のプログラムはブラウザーでツールが何かは環境によって違うためFindWindowは使えません。

GetNextWindowでとれるかと思ったんですが無理でした。
ブラウザー起動、作成プログラム起動、ここでGetNextWindowのGW_HWNDNEXTかGW_HWNDPREVでブラウザー取れると思ったんですが、IMEやtooltips_class\32を拾ってだめでした。

単純にSetBackgroundWindowって命令があると思ったんですがないんですね。


tor  2010-07-07 01:30:47  No: 38768

> ここで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;

もし自分自身がアクティブになるのを防ぎたいという目的だったら、
状況によってもっと適した方法がありそうですけれど。


ロック  2010-07-07 22:20:10  No: 38769

torさん、レスありがとうございます。

IsWindowVisibleというのは知りませんでした。
入れてみたんですが「Button」「Shell_TrayWnd」「Afx:400000:b:401d7:5:10225」とかもそちらに入ってしまって判断は難しいですね。
ブラウザ起動してこのプログラム起動してるのでGetNextWindowですぐブラウザ見つけられると思ったんですがそんな単純ではないようですね。

やりたいのはIE系のプログラムを立ち上げ、このプログラムを起動して自動的に名前やメールアドレスを貼り付けるというものです。
名前やメールアドレスの貼り付けは出来たんですが、IE系のプログラムを見つけるのがうまくいかなくて。
ブラウザーを固定にすればGetNextWindowで条件の見つかるまで回せばいけてますがブラウザーツール変えると対応できないのでいろいろ試行錯誤してます。


ぽむぽむ  2010-07-07 23:40:56  No: 38770

自分が最小化(Minimize)すると、自分の前にアクティブだったプログラムが
アクティブになるけど、そういう使い方ではないのかな?
最小化するなら、GetForegroundWindowで拾えると思うけど。


おも  2010-07-08 05:01:46  No: 38771

>>入れてみたんですが「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;

これで、作成プログラムの直前にアクティブだったウインドウが表示されます。

ただ、ブラウザの起動も作成されたプログラムから起動するようにすれば、その方法にもよるとは思いますが、ブラウザウインドウのハンドルも処理の一環で取得できて、スマートだと思います。


D  2010-07-08 06:08:18  No: 38772

>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;


KHE00221  2010-07-08 12:05:13  No: 38773

これで無理?

var
  H: HWND;

procedure TForm1.FormActivate(Sender: TObject);
begin
    SetForegroundWindow(H);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
    H := GetForegroundWindow;
end;


ロック  2010-07-09 00:27:00  No: 38774

ぽむぽむさん、それです!  それでバッチリいけました!
ハンドルとる関数をこんな感じにしました。

begin
  Application.Minimize;
  hWindow :=GetForegroundWindow;
  Application.Restore;
  result:=hWindow;
end;

ありがとうございました!

おもさん、なぜかうまくいきませんでした。
IE関係でないものでbreakしてしまいました。

Dさん、ソースそのまま使わせてもらったらいけました!
IEでも別のブラウザーツールでもとれました。
ありがとうございました!

KHE00221さん、Shell_TrayWndが返ってきたり別のが返ってきたりでだめでした。
デスクトップからショートカット起動するタイミングでデスクトップがフォアになってしまうのでしょうかね。

みなさんのおかげで無事に目的の動きを再現できました。
どうもありがとうございました!


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

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






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