핸들이 주어지면 창을 닫는 응용 프로그램을 아는 사람이 있습니까? 명령줄이 좋습니다.
저는 해당 애플리케이션을 종료하는 것이 아니라 해당 애플리케이션이 소유한 모달 창을 종료하고 싶습니다.
이론적 해석:
가끔 내 노트북의 기본 창 아래에 모달 대화 상자가 열립니다. VS와 Firefox에서는 이런 일이 한 번도 발생하지 않았습니다. 매우 짜증나.
Spy++를 사용하여 창을 찾을 수 있지만 창을 종료할 수는 없습니다.
편집하다:
임의의 창에 메시지를 보낼 수 있는 응용 프로그램도 좋습니다. 그러면 WM_CLOSE 같은 것을 보낼 수 있을 것 같습니다.
편집하다:
보이는 창을 닫는 것은 흥미롭지 않다는 점을 강조하고 싶습니다. 요점은 모달 대화 상자가 소유 창 아래에 열릴 때 발생하는 추악한 이상 현상을 처리하는 것입니다. 이는 VS 및 Firefox로 작업하는 동안 한 번도 발생하지 않았습니다. 따라서 원하는 해결 방법은 핸들로 창을 닫거나, 가려진 창을 구체적으로 찾아서 표시하는 것입니다.
답변1
좋아, 나는 그 트릭을 수행하는 작은 앱을 만들었습니다.
당신은 그것을 다운로드 할 수 있습니다여기.
용법:
- 프로그램 시작
- 닫고 싶은 창 위에 마우스를 올려두세요. (클릭하지 마세요)
- 삭제를 누르세요.
마우스 커서 아래의 창에 wm_close를 보냅니다.
아래 델파이 코드는...
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.
답변2
나는 이것을 Ruby용 Win32API를 시험해 보기 위한 핑계로 삼았습니다.
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
이것을 사용하면 새로운 메모장을 닫을 수 있습니다
> ruby closewindow.rb "Untitled - Notepad"
아니면 핸들을 알고 있다면
> ruby closewindow.rb 15794730
답변3
이를 수행하는 Perl 스크립트는 다음과 같습니다.
#!/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}");
}
그리고 여기에 그러한 스크립트를 사용하는 몇 가지 오락이 있습니다. (이 스팸을 고려하지 마십시오. 나는 단지 Perl의 사용법을 설명하려고 노력하고 있습니다.Win32::GuiTest:http://www.youtube.com/watch?v=BAg7K_uwNZs
답변4
따라서 이 답변에는 무료 스크립트 실행기를 다운로드하는 것이 포함됩니다.LINQPad스크립트를 실행한 다음 실행합니다. 실행하면 닫으려는 창 위에 커서를 놓으라는 메시지가 표시됩니다. 해당 창에서 제목을 조사하여 표시한 다음 닫을 것인지 묻습니다.
// 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>
)