- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有一个始终在顶部的应用程序(基本上是一个状态显示),我想跟随另一个程序,并且总是位于最小化按钮的左侧。
我可以使用以下代码获取表示“目标”进程的 Rect
,然后我可以将其与偏移量配对以生成覆盖层的初始位置。
获取 HWnd IntPtr:
private IntPtr HWnd = Process.GetProcessesByName("targetapplication")[0].MainWindowHandle;
从 user32.dll
声明函数:
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
以及适当的结构
:
[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
然后按需调用。
但是,我想避免不断地轮询这个值,所以我想挂接到目标应用程序并在目标窗口移动时做出响应。
查看 user32.dll
文档,我能看到的唯一方法是使用 SetWindowsHookEx()
。然而,我并不完全确定我将如何从这里拦截事件。
我相信目标应用程序是基于 WinForms
构建的,但我不能确定。因此,让我响应目标的 Move
事件或直接响应某些 Windows 消息的解决方案都是有用的。
关于我如何继续的任何想法?
最佳答案
一种将 Windows 窗体 Hook 到另一个进程(在本例中为记事本)并跟随进程主窗口移动的方法,以创建可以与进程交互的工具栏,使用 SetWinEventHook() .
要获得 Hook 的窗口边界,GetWindowRect()不推荐。最好打电话DwmGetWindowAttribute()传递 DWMWA_EXTENDED_FRAME_BOUNDS
作为 DWMWINDOWATTRIBUTE
,它仍然返回一个 RECT
。这是因为 GetWindowRect()
不是 DpiAware,它可能会在某些情况下返回虚拟化度量,而且它在特定配置中包含窗口投影。
在此处阅读有关 DpiAwarenes、屏幕布局和虚拟屏幕的更多信息:
Using SetWindowPos with multiple monitors
还重构了 Hook
辅助类和 NativeMethods
声明。
▶ 要将工具窗口移动到前景,如动画中所示,当 Hook 的窗口变为前景窗口时,还要 Hook EVENT_SYSTEM_FOREGROUND
事件:您将收到前景窗口更改时的通知,然后与您 Hook 的窗口的句柄进行比较。
结果的可视化表示:
Form类初始化过程:
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public partial class Form1 : Form
{
private IntPtr notepadhWnd;
private IntPtr hWinEventHook;
private Process targetProc = null;
protected Hook.WinEventDelegate WinEventDelegate;
static GCHandle GCSafetyHandle;
public Form1()
{
InitializeComponent();
WinEventDelegate = new Hook.WinEventDelegate(WinEventCallback);
GCSafetyHandle = GCHandle.Alloc(WinEventDelegate);
targetProc = Process.GetProcessesByName("notepad").FirstOrDefault(p => p != null);
try {
if (targetProc != null) {
notepadhWnd = targetProc.MainWindowHandle;
if (notepadhWnd != IntPtr.Zero) {
uint targetThreadId = Hook.GetWindowThread(notepadhWnd);
hWinEventHook = Hook.WinEventHookOne(
NativeMethods.SWEH_Events.EVENT_OBJECT_LOCATIONCHANGE,
WinEventDelegate, (uint)targetProc.Id, targetThreadId);
var rect = Hook.GetWindowRectangle(notepadhWnd);
// Of course, set the Form.StartPosition to Manual
Location = new Point(rect.Right, rect.Top);
}
}
}
catch (Exception ex) {
// Log and message or
throw;
}
}
protected void WinEventCallback(
IntPtr hWinEventHook,
NativeMethods.SWEH_Events eventType,
IntPtr hWnd,
NativeMethods.SWEH_ObjectId idObject,
long idChild, uint dwEventThread, uint dwmsEventTime)
{
if (hWnd == notepadhWnd &&
eventType == NativeMethods.SWEH_Events.EVENT_OBJECT_LOCATIONCHANGE &&
idObject == (NativeMethods.SWEH_ObjectId)NativeMethods.SWEH_CHILDID_SELF)
{
var rect = Hook.GetWindowRectangle(hWnd);
Location = new Point(rect.Right, rect.Top);
}
}
protected override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
if (!e.Cancel) {
if (GCSafetyHandle.IsAllocated) GCSafetyHandle.Free();
Hook.WinEventUnhook(hWinEventHook);
}
}
protected override void OnShown(EventArgs e)
{
if (targetProc == null) {
this.Hide();
MessageBox.Show("Notepad not found!", "Target Missing", MessageBoxButtons.OK, MessageBoxIcon.Hand);
this.Close();
}
else {
Size = new Size(50, 140);
targetProc.Dispose();
}
base.OnShown(e);
}
用于引用 Windows API 方法的支持类:
using System.Runtime.InteropServices;
using System.Security.Permissions;
public class Hook
{
public delegate void WinEventDelegate(
IntPtr hWinEventHook,
NativeMethods.SWEH_Events eventType,
IntPtr hwnd,
NativeMethods.SWEH_ObjectId idObject,
long idChild,
uint dwEventThread,
uint dwmsEventTime
);
public static IntPtr WinEventHookRange(
NativeMethods.SWEH_Events eventFrom, NativeMethods.SWEH_Events eventTo,
WinEventDelegate eventDelegate,
uint idProcess, uint idThread)
{
return NativeMethods.SetWinEventHook(
eventFrom, eventTo,
IntPtr.Zero, eventDelegate,
idProcess, idThread,
NativeMethods.WinEventHookInternalFlags);
}
public static IntPtr WinEventHookOne(
NativeMethods.SWEH_Events eventId,
WinEventDelegate eventDelegate,
uint idProcess,
uint idThread)
{
return NativeMethods.SetWinEventHook(
eventId, eventId,
IntPtr.Zero, eventDelegate,
idProcess, idThread,
NativeMethods.WinEventHookInternalFlags);
}
public static bool WinEventUnhook(IntPtr hWinEventHook) =>
NativeMethods.UnhookWinEvent(hWinEventHook);
public static uint GetWindowThread(IntPtr hWnd)
{
return NativeMethods.GetWindowThreadProcessId(hWnd, IntPtr.Zero);
}
public static NativeMethods.RECT GetWindowRectangle(IntPtr hWnd)
{
NativeMethods.DwmGetWindowAttribute(hWnd,
NativeMethods.DWMWINDOWATTRIBUTE.DWMWA_EXTENDED_FRAME_BOUNDS,
out NativeMethods.RECT rect, Marshal.SizeOf<NativeMethods.RECT>());
return rect;
}
}
public static class NativeMethods
{
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
public Rectangle ToRectangle() => Rectangle.FromLTRB(Left, Top, Right, Bottom);
}
public static long SWEH_CHILDID_SELF = 0;
//SetWinEventHook() flags
public enum SWEH_dwFlags : uint
{
WINEVENT_OUTOFCONTEXT = 0x0000, // Events are ASYNC
WINEVENT_SKIPOWNTHREAD = 0x0001, // Don't call back for events on installer's thread
WINEVENT_SKIPOWNPROCESS = 0x0002, // Don't call back for events on installer's process
WINEVENT_INCONTEXT = 0x0004 // Events are SYNC, this causes your dll to be injected into every process
}
//SetWinEventHook() events
public enum SWEH_Events : uint
{
EVENT_MIN = 0x00000001,
EVENT_MAX = 0x7FFFFFFF,
EVENT_SYSTEM_SOUND = 0x0001,
EVENT_SYSTEM_ALERT = 0x0002,
EVENT_SYSTEM_FOREGROUND = 0x0003,
EVENT_SYSTEM_MENUSTART = 0x0004,
EVENT_SYSTEM_MENUEND = 0x0005,
EVENT_SYSTEM_MENUPOPUPSTART = 0x0006,
EVENT_SYSTEM_MENUPOPUPEND = 0x0007,
EVENT_SYSTEM_CAPTURESTART = 0x0008,
EVENT_SYSTEM_CAPTUREEND = 0x0009,
EVENT_SYSTEM_MOVESIZESTART = 0x000A,
EVENT_SYSTEM_MOVESIZEEND = 0x000B,
EVENT_SYSTEM_CONTEXTHELPSTART = 0x000C,
EVENT_SYSTEM_CONTEXTHELPEND = 0x000D,
EVENT_SYSTEM_DRAGDROPSTART = 0x000E,
EVENT_SYSTEM_DRAGDROPEND = 0x000F,
EVENT_SYSTEM_DIALOGSTART = 0x0010,
EVENT_SYSTEM_DIALOGEND = 0x0011,
EVENT_SYSTEM_SCROLLINGSTART = 0x0012,
EVENT_SYSTEM_SCROLLINGEND = 0x0013,
EVENT_SYSTEM_SWITCHSTART = 0x0014,
EVENT_SYSTEM_SWITCHEND = 0x0015,
EVENT_SYSTEM_MINIMIZESTART = 0x0016,
EVENT_SYSTEM_MINIMIZEEND = 0x0017,
EVENT_SYSTEM_DESKTOPSWITCH = 0x0020,
EVENT_SYSTEM_END = 0x00FF,
EVENT_OEM_DEFINED_START = 0x0101,
EVENT_OEM_DEFINED_END = 0x01FF,
EVENT_UIA_EVENTID_START = 0x4E00,
EVENT_UIA_EVENTID_END = 0x4EFF,
EVENT_UIA_PROPID_START = 0x7500,
EVENT_UIA_PROPID_END = 0x75FF,
EVENT_CONSOLE_CARET = 0x4001,
EVENT_CONSOLE_UPDATE_REGION = 0x4002,
EVENT_CONSOLE_UPDATE_SIMPLE = 0x4003,
EVENT_CONSOLE_UPDATE_SCROLL = 0x4004,
EVENT_CONSOLE_LAYOUT = 0x4005,
EVENT_CONSOLE_START_APPLICATION = 0x4006,
EVENT_CONSOLE_END_APPLICATION = 0x4007,
EVENT_CONSOLE_END = 0x40FF,
EVENT_OBJECT_CREATE = 0x8000, // hwnd ID idChild is created item
EVENT_OBJECT_DESTROY = 0x8001, // hwnd ID idChild is destroyed item
EVENT_OBJECT_SHOW = 0x8002, // hwnd ID idChild is shown item
EVENT_OBJECT_HIDE = 0x8003, // hwnd ID idChild is hidden item
EVENT_OBJECT_REORDER = 0x8004, // hwnd ID idChild is parent of zordering children
EVENT_OBJECT_FOCUS = 0x8005, // hwnd ID idChild is focused item
EVENT_OBJECT_SELECTION = 0x8006, // hwnd ID idChild is selected item (if only one), or idChild is OBJID_WINDOW if complex
EVENT_OBJECT_SELECTIONADD = 0x8007, // hwnd ID idChild is item added
EVENT_OBJECT_SELECTIONREMOVE = 0x8008, // hwnd ID idChild is item removed
EVENT_OBJECT_SELECTIONWITHIN = 0x8009, // hwnd ID idChild is parent of changed selected items
EVENT_OBJECT_STATECHANGE = 0x800A, // hwnd ID idChild is item w/ state change
EVENT_OBJECT_LOCATIONCHANGE = 0x800B, // hwnd ID idChild is moved/sized item
EVENT_OBJECT_NAMECHANGE = 0x800C, // hwnd ID idChild is item w/ name change
EVENT_OBJECT_DESCRIPTIONCHANGE = 0x800D, // hwnd ID idChild is item w/ desc change
EVENT_OBJECT_VALUECHANGE = 0x800E, // hwnd ID idChild is item w/ value change
EVENT_OBJECT_PARENTCHANGE = 0x800F, // hwnd ID idChild is item w/ new parent
EVENT_OBJECT_HELPCHANGE = 0x8010, // hwnd ID idChild is item w/ help change
EVENT_OBJECT_DEFACTIONCHANGE = 0x8011, // hwnd ID idChild is item w/ def action change
EVENT_OBJECT_ACCELERATORCHANGE = 0x8012, // hwnd ID idChild is item w/ keybd accel change
EVENT_OBJECT_INVOKED = 0x8013, // hwnd ID idChild is item invoked
EVENT_OBJECT_TEXTSELECTIONCHANGED = 0x8014, // hwnd ID idChild is item w? test selection change
EVENT_OBJECT_CONTENTSCROLLED = 0x8015,
EVENT_SYSTEM_ARRANGMENTPREVIEW = 0x8016,
EVENT_OBJECT_END = 0x80FF,
EVENT_AIA_START = 0xA000,
EVENT_AIA_END = 0xAFFF
}
//SetWinEventHook() Object Ids
public enum SWEH_ObjectId : long
{
OBJID_WINDOW = 0x00000000,
OBJID_SYSMENU = 0xFFFFFFFF,
OBJID_TITLEBAR = 0xFFFFFFFE,
OBJID_MENU = 0xFFFFFFFD,
OBJID_CLIENT = 0xFFFFFFFC,
OBJID_VSCROLL = 0xFFFFFFFB,
OBJID_HSCROLL = 0xFFFFFFFA,
OBJID_SIZEGRIP = 0xFFFFFFF9,
OBJID_CARET = 0xFFFFFFF8,
OBJID_CURSOR = 0xFFFFFFF7,
OBJID_ALERT = 0xFFFFFFF6,
OBJID_SOUND = 0xFFFFFFF5,
OBJID_QUERYCLASSNAMEIDX = 0xFFFFFFF4,
OBJID_NATIVEOM = 0xFFFFFFF0
}
public enum DWMWINDOWATTRIBUTE : uint
{
DWMWA_NCRENDERING_ENABLED = 1, // [get] Is non-client rendering enabled/disabled
DWMWA_NCRENDERING_POLICY, // [set] DWMNCRENDERINGPOLICY - Non-client rendering policy - Enable or disable non-client rendering
DWMWA_TRANSITIONS_FORCEDISABLED, // [set] Potentially enable/forcibly disable transitions
DWMWA_ALLOW_NCPAINT, // [set] Allow contents rendered In the non-client area To be visible On the DWM-drawn frame.
DWMWA_CAPTION_BUTTON_BOUNDS, // [get] Bounds Of the caption button area In window-relative space.
DWMWA_NONCLIENT_RTL_LAYOUT, // [set] Is non-client content RTL mirrored
DWMWA_FORCE_ICONIC_REPRESENTATION, // [set] Force this window To display iconic thumbnails.
DWMWA_FLIP3D_POLICY, // [set] Designates how Flip3D will treat the window.
DWMWA_EXTENDED_FRAME_BOUNDS, // [get] Gets the extended frame bounds rectangle In screen space
DWMWA_HAS_ICONIC_BITMAP, // [set] Indicates an available bitmap When there Is no better thumbnail representation.
DWMWA_DISALLOW_PEEK, // [set] Don't invoke Peek on the window.
DWMWA_EXCLUDED_FROM_PEEK, // [set] LivePreview exclusion information
DWMWA_CLOAK, // [set] Cloak Or uncloak the window
DWMWA_CLOAKED, // [get] Gets the cloaked state Of the window. Returns a DWMCLOACKEDREASON object
DWMWA_FREEZE_REPRESENTATION, // [set] BOOL, Force this window To freeze the thumbnail without live update
PlaceHolder1,
PlaceHolder2,
PlaceHolder3,
DWMWA_ACCENTPOLICY = 19
}
public static SWEH_dwFlags WinEventHookInternalFlags =
SWEH_dwFlags.WINEVENT_OUTOFCONTEXT |
SWEH_dwFlags.WINEVENT_SKIPOWNPROCESS |
SWEH_dwFlags.WINEVENT_SKIPOWNTHREAD;
[DllImport("dwmapi.dll", SetLastError = true)]
internal static extern int DwmGetWindowAttribute(IntPtr hwnd, DWMWINDOWATTRIBUTE dwAttribute, out RECT pvAttribute, int cbAttribute);
[DllImport("user32.dll", SetLastError = true)]
internal static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("user32.dll")]
internal static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr voidProcessId);
[DllImport("user32.dll", SetLastError = false)]
internal static extern IntPtr SetWinEventHook(
SWEH_Events eventMin,
SWEH_Events eventMax,
IntPtr hmodWinEventProc,
Hook.WinEventDelegate lpfnWinEventProc,
uint idProcess, uint idThread,
SWEH_dwFlags dwFlags);
[DllImport("user32.dll", SetLastError = false)]
internal static extern bool UnhookWinEvent(IntPtr hWinEventHook);
}
关于c# - 当外部应用程序的窗口移动时移动窗口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48767318/
https://github.com/mattdiamond/Recorderjs/blob/master/recorder.js中的代码 我不明白 JavaScript 语法,比如 (functio
在 iOS 7 及更早版本中,如果我们想在应用程序中找到 topMostWindow,我们通常使用以下代码行 [[[UIApplication sharedApplication] windows]
我已经尝试解决这个问题很长一段时间了:我无法访问窗口的 url,因为它位于另一个域上..有一些解决方案吗? function login() { var cb = window.ope
是否可以将 FFMPEG 视频流传递到 C# 窗口?现在它在新窗口中作为新进程打开,我只是想将它传递给我自己的 SessionWindow。 此时我像这样执行ffplay: public void E
我有一个名为 x 的矩阵看起来像这样: pTime Close 1 1275087600 1.2268 2 1275264000 1.2264 3 1275264300 1.2
在编译时,发生搜索,grep搜索等,Emacs会在单独的窗口中创建一个新的缓冲区来显示结果,有没有自动跳转到那个窗口的方法?这很有用,因为我可以使用 n 和 p 而不是 M-g n 和 M-g p 移
我有一个启动 PowerShell 脚本的批处理文件。 批处理文件: START Powershell -executionpolicy RemoteSigned -noexit -file "MyS
我有一个基于菜单栏的应用程序,单击图标时会显示一个窗口。在 Mac OS X Lion 上一切正常,但由于某种原因,在 Snow Leopard 和早期版本的 Mac OS X 上会出现错误。任何时候
在 macOS 中,如何在 Xcode 和/或 Interface Builder 中创建带有“集成标题栏和工具栏”的窗口? 这是“宽标题栏”类型的窗口,已添加到 OS X 10.10 Yosemit
在浏览器 (Chrome) 中 JavaScript: var DataModler = { Data: { Something: 'value' }, Process: functi
我有 3 个 html 页面。第 1 页链接到第 2 页,第 2 页链接到第 3 页(为了简单起见)。 我希望页面 2 中的链接打开页面 3 并关闭页面 1(选项卡 1)。 据我了解,您无法使用 Ja
当点击“创建节点”按钮时,如何打开一个新的框架或窗口?我希望新框架包含一个文本字段和下拉菜单,以便用户可以选择一个选项。 Create node Search node
我有一个用户控件,用于编辑应用程序中的某些对象。 我最近遇到一个实例,我想弹出一个新的对话框(窗口)来托管此用户控件。 如何实例化新窗口并将需要设置的任何属性从窗口传递到用户控件? 感谢您的宝贵时间。
我有一个Observable,它发出许多对象,我想使用window或buffer操作对这些对象进行分组。但是,我不想指定count参数来确定窗口中应包含多少个对象,而是希望能够使用自定义条件。 例如,
我有以下代码,它打开一个新的 JavaFX 阶段(我们称之为窗口)。 openAlertBox.setOnAction(e -> { AlertBox alert = AlertBox
我要添加一个“在新窗口中打开”上下文菜单项,该菜单项将以新的UIScene打开我的应用程序文档之一。当然,我只想在实际上支持多个场景的设备上显示该菜单项。 目前,我只是在检查设备是否是使用旧设备的iP
我正在尝试创建一个 AIR 应用程序来记录应用程序的使用情况,使用 AIR 从系统获取信息的唯一简单方法是使用命令行工具和抓取 标准输出 . 我知道像 这样的工具顶部 和 ps 对于 OS X,但它们
所以我有这个简单的 turtle 螺旋制作器,我想知道是否有一种方法可以打印出由该程序创建的我的设计副本。 代码: import turtle x= float(input("Angle: ")) y
我正在编写一个 C# WPF 程序,它将文本消息发送到另一个程序的窗口。我有一个宏程序作为我的键盘驱动程序 (Logitech g15) 的一部分,它已经这样做了,尽管它不会将击键直接发送到进程,而是
我尝试使用以下代码通过 UDP 发送,但得到了奇怪的结果。 if((sendto(newSocket, sendBuf, totalLength, 0, (SOCKADDR *)&sendAd
我是一名优秀的程序员,十分优秀!