Fire窗口调整大小事件C#

时间:2015-01-10 12:06:18

标签: c# interop pinvoke win32-process

我正在开发一个项目,我必须先拆分,然后重新调整桌面上的窗口大小。我可以使用pinvoke服务TileWindows拆分桌面屏幕。但我被困在另一部分,以调整桌面上的窗口大小。因为首先我必须抓住一些窗口在桌面上重新调整大小的事件。为了抓住这个事件,我使用了在{答案>中回答的this代码。

[DllImport("user32.dll", SetLastError = true)]
internal static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc, WinEventProc lpfnWinEventProc, int idProcess, int idThread, uint dwflags);
[DllImport("user32.dll")]
internal static extern int UnhookWinEvent(IntPtr hWinEventHook);
internal delegate void WinEventProc(IntPtr hWinEventHook, uint iEvent, IntPtr hWnd, int      idObject, int idChild, int dwEventThread, int dwmsEventTime);

const uint WINEVENT_OUTOFCONTEXT = 0;
const uint EVENT_SYSTEM_FOREGROUND = 3;
private IntPtr winHook;
private WinEventProc listener;

public void StartListeningForWindowChanges()
{
    listener = new WinEventProc(EventCallback);
    //setting the window hook
    winHook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, IntPtr.Zero, listener, 0, 0, WINEVENT_OUTOFCONTEXT);
}

public void StopListeningForWindowChanges()
{
    UnhookWinEvent(winHook);
}

private static void EventCallback(IntPtr hWinEventHook, uint iEvent, IntPtr hWnd, int idObject, int idChild, int dwEventThread, int dwmsEventTime)
{
    MessageBox.Show("I am here");
}

我得到的问题是,即使我没有在屏幕上调整任何窗口大小,事件也会被触发。正如您所看到的,我在messageBox函数中添加了eventCallback并弹出,但有趣的是它在ok按钮上没有显示任何内容。

1 个答案:

答案 0 :(得分:0)

正如@HansPassant已经说过你应该使用

  • EVENT_SYSTEM_MOVESIZEEND = 0x000B常量,表示:窗口的移动或调整大小已经完成。

Event Constants

您也从任何窗口接收活动。如果你看一下SetWinEventHook function的签名:

HWINEVENTHOOK WINAPI SetWinEventHook(
  _In_  UINT eventMin,
  _In_  UINT eventMax,
  _In_  HMODULE hmodWinEventProc,
  _In_  WINEVENTPROC lpfnWinEventProc,
  _In_  DWORD idProcess,
  _In_  DWORD idThread,
  _In_  UINT dwflags
);
你会发现:

  • idProcess - 指定挂钩函数从中接收事件的进程的ID。指定零(0)以从当前桌面上的所有进程接收事件。

然而,在您的代码中,您已将0空格:

winHook = SetWinEventHook(
    EVENT_SYSTEM_FOREGROUND, 
    EVENT_SYSTEM_FOREGROUND, 
    IntPtr.Zero, 
    listener, 
    0, // <--- idProcess
    0, 
    WINEVENT_OUTOFCONTEXT);

您需要获取进程的ID才能只收听有关窗口的事件。为此,您可以使用Process.Id Property。我认为这应该有效(对我有用):

const uint EVENT_SYSTEM_MOVESIZESTART = 0x000B;

Process currentProcess = Process.GetCurrentProcess();

winHook = SetWinEventHook(
    EVENT_SYSTEM_MOVESIZEEND, 
    EVENT_SYSTEM_MOVESIZEEND, 
    IntPtr.Zero, 
    listener, 
    currentProcess.Id, 
    0, 
    WINEVENT_OUTOFCONTEXT);