Como posso fechar as janelas pelo seu identificador?

3

Alguém sabe de um aplicativo que fecha uma janela devido à sua manipulação? Linha de comando é boa.

Note que não desejo matar o respectivo aplicativo, e sim uma janela modal de propriedade desse aplicativo.

Justificativa:

Em algum momento, uma caixa de diálogo modal é aberta abaixo da janela principal do meu laptop. Isso não aconteceu uma vez para o VS e o Firefox. Muito chato.

Eu posso localizar a janela com o Spy ++, mas não tenho como matá-la.

EDITAR:

Um aplicativo que permite enviar mensagens para uma janela arbitrária também é bom, eu acho que posso enviar algo como WM_CLOSE ou qualquer outra coisa.

EDITAR:

Gostaria de enfatizar que não sou interessante em fechar uma janela visível. O ponto principal é lidar com anormalidades desagradáveis quando uma caixa de diálogo modal fica aberta sob a janela de propriedade, o que aconteceu e não uma vez para mim enquanto trabalhava com o VS e o Firefox. Portanto, a solução desejada é fechar uma janela pela alça ou, se puder, localizar especificamente janelas obscuras e trazê-las adiante.

    
por mark 26.08.2009 / 20:54

6 respostas

4

Ok, eu fiz um pequeno aplicativo que faz o truque.

Vocêpodebaixá-lo aqui .

Uso:

  1. Iniciar o programa
  2. Mantenha o mouse sobre a janela que deseja fechar (não clique nela)
  3. Pressione excluir.

Envia um wm_close para a janela sob o cursor do mouse.

Código Delphi abaixo ...

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.
    
por 27.08.2009 / 00:35
2

Eu peguei isso como uma desculpa para experimentar o Win32API para Ruby.

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

Usando isso, você pode fechar um novo bloco de notas com

> ruby closewindow.rb "Untitled - Notepad"

ou se você conhece o identificador

> ruby closewindow.rb 15794730
    
por 26.08.2009 / 21:32
1

Aqui está um script em Perl para fazer isso:

#!/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}");
}

E aqui está algum entretenimento usando tal script (por favor, não considere este spam, eu estou apenas tentando ilustrar um uso do Perl's Win32 :: GuiTest : link

    
por 27.08.2009 / 01:08
1

Isso seria simplesmente simples de cozinhar para você. Eu vejo que você rejeitou Perl. Qual sua língua favorita?

Aqui está um exemplo simples de C (não testado, saindo da memória):

#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);
}

Este é um exemplo simples em C # (novamente, não testado):

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);
    }
}
    
por 27.08.2009 / 03:02
0

Pressione Alt + Esc para enviar a janela atual em primeiro plano para o verso. Continue pressionando até chegar ao diálogo. Isso irá percorrer até janelas que não estejam na lista Alt + Tab .

    
por 29.08.2009 / 05:06
0

Portanto, esta resposta envolve o download de um runner de script gratuito LINQPad para executar o script e executá-lo. execute-o e pede que você coloque o cursor sobre a janela que deseja fechar. Ele interroga a janela do título, mostra para você e pergunta se você deseja fechá-lo.

// 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>
)
    
por 16.10.2018 / 18:41