Wie kann ich Fenster am Griff schließen?

Wie kann ich Fenster am Griff schließen?

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

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

Begründung:

Manchmal wird auf meinem Laptop ein modaler Dialog unter dem Hauptfenster geöffnet. Bei VS und Firefox ist das kein einziges Mal passiert. Sehr ärgerlich.

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

BEARBEITEN:

Eine Anwendung, die das Senden von Nachrichten an ein beliebiges Fenster erlaubt, ist auch gut. Ich denke, ich kann dann etwas wie WM_CLOSE oder was auch immer senden.

BEARBEITEN:

Ich möchte betonen, dass ich nicht daran interessiert bin, ein sichtbares Fenster zu schließen. Es geht darum, mit hässlichen Anomalien umzugehen, wenn ein modaler Dialog unter dem Besitzerfenster geöffnet wird, was bei mir bei der Arbeit mit VS und Firefox tatsächlich passiert ist, aber nicht ein einziges Mal. Die gewünschte Lösung besteht also darin, ein Fenster über seinen Handle zu schließen oder, wenn es möglich ist, verdeckte Fenster gezielt zu lokalisieren und sie hervorzubringen.

Antwort1

Okay, ich habe eine kleine App erstellt, die den Zweck erfüllt.

Bildschirmfoto

Sie können es herunterladenHier.

Verwendung:

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

Es sendet ein 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.

Antwort2

Ich nahm dies als Vorwand, 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 schließen mit

> ruby closewindow.rb "Untitled - Notepad"

oder wenn Sie den Griff kennen

> ruby closewindow.rb 15794730

Antwort3

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("%{F4}");
}

Und hier ist etwas Unterhaltung mit einem solchen Skript (bitte betrachten Sie dies nicht als Spam, ich versuche nur, eine Verwendung von PerlsWin32::GuiTest:http://www.youtube.com/watch?v=BAg7K_uwNZs

Antwort4

Diese Antwort beinhaltet das Herunterladen eines kostenlosen Script-RunnersLINQPadum das Skript auszuführen. Führen Sie es aus und Sie werden aufgefordert, den Cursor über das Fenster zu bewegen, das Sie schließen möchten. Es fragt das Fenster nach dem Titel ab, zeigt ihn Ihnen an und fragt Sie dann, 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 = {hWnd:nativeint; msg:int; wParam:nativeint; lParam:nativeint}
    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 = {PId:int;MainWindowHandle:nativeint; ProcessName:string}
let getWindowInfo hwnd = 
    hwnd
    |> PInvoke.getWindowThreadProcessId
    |> Option.map (Process.GetProcessById)
    |> Option.map (fun p ->
        {PId=p.Id; MainWindowHandle=p.MainWindowHandle; ProcessName=p.ProcessName}
    )

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

verwandte Informationen