Wie kann ich Fenster am Griff schließen?

5659
mark

Kennt jemand eine Anwendung, die ein Fenster aufgrund seines Griffs schließen würde? Befehlszeile ist gut.

Beachten Sie, dass ich die jeweilige Anwendung nicht beenden möchte, sondern ein modales Fenster, das dieser Anwendung gehört.

Begründung:

Manchmal öffnet sich auf meinem Laptop ein modaler Dialog unter dem Hauptfenster. Dies geschah nicht einmal für VS und Firefox. Sehr nervig.

Ich kann das Fenster mit Spy ++ lokalisieren, habe aber keine Möglichkeit, es zu töten.

BEARBEITEN:

Eine Anwendung, die das Senden von Nachrichten an ein beliebiges Fenster ermöglicht, ist ebenfalls gut. Ich schätze, ich kann etwas wie WM_CLOSE oder was auch immer senden.

BEARBEITEN:

Ich möchte betonen, dass es mich nicht interessiert, ein sichtbares Fenster zu schließen. Der springende Punkt ist, sich mit hässlichen Anomalien zu befassen, wenn ein modaler Dialog unter dem besitzenden Fenster geöffnet wird, was passiert ist und nicht einmal für mich bei der Arbeit mit VS und Firefox. Die gewünschte Lösung besteht also darin, ein Fenster am Griff zu schließen oder, wenn es verdeckte Fenster gezielt lokalisieren und hervorbringen könnte.

3
Alt-Tab bringt den modalen Dialog normalerweise wieder in den Vordergrund. Remus Rusanu vor 14 Jahren 0
Nun, nicht in meinen Szenarien. Dies geschieht nur, wenn der modale Dialog mit einem bestimmten Fensterstil geöffnet ist (nicht genau erinnern), wodurch der Dialog in der Taskleiste angezeigt wird. vor 14 Jahren 0

6 Antworten auf die Frage

4
Wouter van Nifterick

Okay, ich habe eine kleine App gemacht, die den Trick macht.

Bildschirmfoto

Sie können es hier herunterladen .

Verwendungszweck:

  1. Starten Sie das Programm
  2. Halten Sie die Maus über das Fenster, das Sie schließen möchten (klicken Sie nicht darauf).
  3. Löschen drücken

Es sendet eine wm_close an das Fenster unter dem Mauszeiger.

Delphi-Code unten ...

unit uCloseWindow;  interface  uses Windows, Forms, Messages, SysUtils, Variants, Classes, Controls;  type TfrmMain = class(TForm) procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); public end;  var frmMain: TfrmMain;  implementation  {$R *.dfm}  procedure TfrmMain.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); var HandleUnderCursor:HWND; begin if Key=VK_DELETE then begin HandleUnderCursor := WindowFromPoint(Mouse.CursorPos); SendMessage(HandleUnderCursor,WM_CLOSE,0,0) end; end;  end. 
Nicht gut. Wie gesagt, das Fenster ist hinter einem anderen Fenster versteckt. Der ganze Zweck geht es um diese hässlichen Fälle. vor 14 Jahren 0
Siehe das zweite EDIT in meinem Beitrag. vor 14 Jahren 0
Nein, Sie sagten, es sei "unter" einem anderen Fenster (was eine y-Position impliziert), und Sie haben nicht erwähnt, dass das Fenster nicht sichtbar ist. Es ist ein bisschen unhöflich von dir, nach der Anstrengung, die ich unternommen habe, um dir zu helfen, das Votum abzugeben. vor 14 Jahren 3
Beim zweiten Gedanken haben Sie recht. Ich hätte mich besser erklären sollen. Sie können meine Frage im Gegenzug ablehnen, weil diese Klarheit fehlt, ich verdiene sie recht. vor 14 Jahren 0
Es gibt keinen Grund, diese Antwort abzustimmen. Es ist eine gültige * Programmierung * Antwort auf eine nicht so programmierrelevante Frage. Das wechselseitige Downvoting ist kaum produktiv. Sinan Ünür vor 14 Jahren 0
2
Jonas Elfström

Ich nahm dies als Ausrede, um die Win32API für Ruby auszuprobieren.

require 'Win32API'  WM_CLOSE = 0x0010 FindWindow = Win32API.new('user32', 'FindWindow', ["P", "P"], "L") SendMessage = Win32API.new('user32', 'SendMessage', ["L", "L", "P", "P"], "L")  def Send_WM_CLOSE(title) handle = FindWindow.call(nil, title) SendMessage.call(handle, WM_CLOSE, nil, nil) if handle != 0 end  if ARGV[0].to_i==0 title=String.new(ARGV[0]) Send_WM_CLOSE(title) else SendMessage.call(ARGV[0].to_i, WM_CLOSE, nil, nil) end 

Damit können Sie einen neuen Notizblock mit schließen

> ruby closewindow.rb "Untitled - Notepad" 

oder wenn Sie den Griff kennen

> ruby closewindow.rb 15794730 
Schön, aber ich werde Ruby dafür nicht installieren :-) vor 14 Jahren 0
Es gibt ein Installationsprogramm mit einem Klick, falls Sie Ihre Meinung ändern. http://rubyforge.org/projects/rubyinstaller/ Jonas Elfström vor 14 Jahren 0
1
Sinan Ünür

Hier ist ein Perl-Skript, um das zu tun:

#!/usr/bin/perl  use strict; use warnings;  use Win32::GuiTest qw(FindWindowLike SendKeys SetForegroundWindow);  die "Need pattern to match against window titles\n" unless @ARGV; my ($windowtitle) = @ARGV;  my ($myhandle) = FindWindowLike(0, qr/winclose\.pl/);  my @windows = FindWindowLike(0, qr/\Q$windowtitle\E/i);  for my $handle ( @windows ) { next if $handle == $myhandle; SetForegroundWindow($handle); SendKeys("%"); } 

Und hier ist etwas Unterhaltung, die ein solches Skript verwendet (bitte berücksichtigen Sie diesen Spam nicht. Ich versuche nur, eine Verwendung von Perls Win32 :: GuiTest zu veranschaulichen : http://www.youtube.com/watch?v=BAg7K_uwNZs

Süß. Aber ich habe keine Lust, Perl nur dafür zu installieren. vor 14 Jahren 0
1
P Daddy

Dies wäre erstaunlich einfach für sich selbst zu kochen. Ich sehe, du hast Perl abgelehnt. Was ist deine Lieblingssprache?

Hier ist ein einfaches C-Beispiel (nicht getestet, vom Speicher ausgehend):

#include <windows.h> #include <stdio.h>  int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){ HWND hWnd;  if(!sscanf(lpCmdLine, "%i", &hWnd)){ MessageBox(null, "Invalid argument", "Close Window", MB_OK | MB_ICONERROR); return 1; }  PostMessage(hWnd, WM_CLOSE, 0, 0); } 

Dies ist ein einfaches C # -Beispiel (wiederum nicht getestet):

using System; using System.Runtime.Interop;  static class Program{ [DllImport("user32.dll", CharSet=CharSet.Auto)] static extern int PostMessage(int hWnd, int msg, int wParam, int lParam);  const int WM_CLOSE = 16;  static void Main(string[] args){ int hWnd; if(args.Length == 1 && int.TryParse(args[0], out hWnd)) PostMessage(hWnd, WM_CLOSE, 0, 0); else MessageBox.Show("Invalid Argument", "CloseWindow", MessageBoxButtons.OK, MessageBoxIcon.Error); } } 
Du hast recht. Ich habe mich gefragt, ob es benutzerfreundlichere Lösungen gibt. Obwohl ich erwähnt habe, dass die einfache Befehlszeile gut genug ist, erwartet man normalerweise eine nette Benutzeroberfläche, mit der man das Fenster auswählen kann, alle möglichen Informationen darüber usw. usw. Ab jetzt muss ich es noch mit Spy ++ koppeln . Aber du hast trotzdem recht. vor 14 Jahren 0
Eine GUI zu erstellen, würde nicht viel mehr dauern, außer für eine kleine Investition in der Zeit. Das Verhalten von Spy ++ zum Ziehen von Ziel und Hervorheben eines Fensters lässt sich mit einem entsprechenden Symbol und Cursor relativ leicht duplizieren. Die Fenster-Hervorhebung ist mit den WinAPI-Funktionen `GetWindowRgn` und` FrameRgn` problemlos möglich. Es gibt andere API-Funktionen, die Ihnen Informationen zu dem von Ihnen gesuchten Fenster geben. Mit SetWindowPos können Sie den Zieldialog an die Spitze der Z-Reihenfolge bringen, damit Sie ihn sehen und mit ihm interagieren können, anstatt ihn nur zu schließen. vor 14 Jahren 0
Alles ist einfach und alles braucht Zeit, die wir nicht haben. Warum ein Rad erfinden, wenn es wahrscheinlich schon erfunden ist? Ich weiß, wie das funktioniert, Sie entwickeln ein kleines schickes Hilfsprogramm für den Eigengebrauch, erweitern es dann, debuggen es, um Fehler zu beheben, und es ist leicht, ein paar Tage für etwas zu verschwenden, das bereits von anderen getestet und getestet wurde. vor 14 Jahren 0
Du hast einen guten Punkt. Andererseits glaube ich jedoch, dass in einem solchen Fall mehr Zeit für die Suche nach einer vorhandenen Lösung aufgewendet werden muss, als eine Lösung zu entwickeln. Nicht jedes esoterische Bedürfnis wird bereits zufriedenstellend durch ein bestehendes Produkt erfüllt - eine Tatsache, der ich meinen Wohlstand verdanke. vor 14 Jahren 0
0
recursive

Drücken Sie Alt+ Esc, um das aktuelle Vordergrundfenster nach hinten zu senden. Drücken Sie diese Taste so oft, bis Sie zum Dialog kommen. Dies führt Sie durch gerade Fenster, die sich nicht in der Alt+ TabListe befinden.

0
Maslow

Diese Antwort beinhaltet also das Herunterladen eines kostenlosen Skriptläufers LINQPad, um das Skript auszuführen und anschließend auszuführen. Führen Sie es aus und Sie werden aufgefordert, den Mauszeiger über dem Fenster zu platzieren, das Sie schließen möchten. Es fragt das Fenster nach dem Titel ab, zeigt es Ihnen an und fragt, ob Sie es schließen möchten.

// close an app's foremost window - will try to just close whatever window the mouse is over first, see if that does the trick // close works when linqpad runs as administrator. Used to close a modal in linqpad that was stuck open System.Drawing  module PInvoke =  type WindowHandle = nativeint module Native =  open System.Drawing open System.Runtime.InteropServices   //http://pinvoke.net/default.aspx/user32.SendMessage // IntPtr would be fine here, nativeint is more idiomatic [<DllImport("User32", SetLastError=true)>] extern nativeint private SendMessage(WindowHandle hWnd, int Msg, nativeint wParam, nativeint lParam)  [<DllImport("User32", EntryPoint="WindowFromPoint", ExactSpelling = true)>] extern WindowHandle private WindowFromPoint (Point point)  // https://stackoverflow.com/questions/18184654/find-process-id-by-windows-handle //https://stackoverflow.com/a/18184700/57883 [<DllImport("User32", SetLastError=true)>] extern int private GetWindowThreadProcessId(WindowHandle hWnd, int& processId)  // https://stackoverflow.com/questions/1316681/getting-mouse-position-in-c-sharp [<DllImport("User32", SetLastError=true)>] extern bool private GetCursorPos(Point& lpPoint);  //https://stackoverflow.com/questions/647236/moving-mouse-cursor-programmatically // claims sendInput is better than send messages for clicking [<DllImport("User32", SetLastError=true)>] extern System.Int64 SetCursorPos(int x, int y); // let dll = DllImportAttribute("")  // But, if you need to get text from a control in another process, GetWindowText() won't work. Use WM_GETTEXT instead. // another mapping for StringBuilder out // you might need to get the string length from another call before calling this: https://www.pinvoke.net/default.aspx/user32.getwindowtext [<DllImport("User32",CharSet=CharSet.Auto,EntryPoint="SendMessage")>] extern nativeint SendWMText(WindowHandle hWnd, int msg, nativeint wParam, StringBuilder sb);  open Native  type SendMessageRaw =  type Message<'t> =  | Close of windowHandle:nativeint | GetText of windowHandle:nativeint * withReturn :(string -> unit) | [<Obsolete("Use only for testing, don't leave things unmapped")>] Raw of SendMessageRaw  let ptToParam (pt:System.Drawing.Point) = nativeint (pt.Y <<< 16 ||| pt.X) let sendMessage message =  let sendMessage a b c d = SendMessage(a,b,c,d) match message with | Close hwnd -> let WM_CLOSE = 0x0010 printfn "Attempting close" sendMessage hwnd WM_CLOSE IntPtr.Zero IntPtr.Zero | GetText (hWnd,f) ->  let WM_GETTEXTLENGTH = 0x000E printfn "Getting text length" let length: int =int<|SendMessage(hWnd,WM_GETTEXTLENGTH, IntPtr.Zero, IntPtr.Zero) printfn "Got text length: %i " length let mutable sb = StringBuilder(length + 1)  let WM_GETTEXT = 0x000D  let result = SendWMText(hWnd,WM_GETTEXT,nativeint (length + 1),sb) printfn "Text returned is length %i" sb.Length sb.ToString() |> f result | Raw x -> SendMessage(x.hWnd, x.msg, x.wParam, x.lParam)  let windowFromPoint(pt:Point) =  let mutable pt = pt let hwnd = WindowFromPoint(pt) if hwnd <> IntPtr.Zero then Some hwnd else None let getCursorPos() =  let mutable pt = Point() match GetCursorPos(&pt) with | true -> Some pt | false -> None let getWindowThreadProcessId hwnd =  let mutable pId = 0 let result = GetWindowThreadProcessId(hwnd, &pId) if pId <> 0 then Some pId else None  type WindowInfo =  let getWindowInfo hwnd =  hwnd |> PInvoke.getWindowThreadProcessId |> Option.map (Process.GetProcessById) |> Option.map (fun p ->  )  Util.ReadLine("Put the cursor of the desired window") |> ignore let currentPt = PInvoke.getCursorPos() printfn "Current Pos is %A" currentPt currentPt |> Option.bind(fun pt -> PInvoke.windowFromPoint pt ) |> Option.map(fun hWnd -> printfn "Current hWnd is %A" hWnd let wi = getWindowInfo hWnd printfn "CurrentWindowInfo is %A" wi wi.Dump() let pid = PInvoke.getWindowThreadProcessId hWnd printfn "With pId = %A" pid hWnd ) |> Option.iter(fun hWnd -> let text = let mutable text:string = null let r = PInvoke.sendMessage <| PInvoke.GetText(hWnd, (fun s ->  printfn " got text?" text <- s)) text printfn "Window text:%s" text if Util.ReadLine<bool>("Attempt close?") then PInvoke.sendMessage (PInvoke.Message.Close( hWnd)) |> ignore<nativeint> )