C# 如何将我的表格粘贴到第三方申请的窗口?
我正试图将我的表单粘贴到另一个应用程序(比如Microsoft Outlook)的窗口。当我移动Outlook窗口时,我的窗体仍应粘贴在它的右侧 目前,我正在C# 如何将我的表格粘贴到第三方申请的窗口?,c#,winforms,C#,Winforms,我正试图将我的表单粘贴到另一个应用程序(比如Microsoft Outlook)的窗口。当我移动Outlook窗口时,我的窗体仍应粘贴在它的右侧 目前,我正在while(true)循环(使用sleep())中监视Outlook的位置,并调整窗体的位置以适应它 这里有两个问题: 如果sleep()持续时间太短,那么检查Outlook的位置并经常调整我的表单需要很大的性能 如果sleep() 没有本机解决方案吗?您可以使用任何windows钩子函数WH\u GETMESSAGE,WH\u GET
while(true)
循环(使用sleep()
)中监视Outlook的位置,并调整窗体的位置以适应它
这里有两个问题:
- 如果
持续时间太短,那么检查Outlook的位置并经常调整我的表单需要很大的性能sleep()
- 如果
sleep()
没有本机解决方案吗?您可以使用任何windows钩子函数
WH\u GETMESSAGE
,WH\u GETMESSAGERET
,WH\u SYSMSGFILTER
或WH\u MSGFILTER
在这种情况下,您可能会对WM\u MOVE
和WM\u MOVING
感兴趣,其中WM\u MOVE
是在移动窗口后发送的(也称为完成移动),而WM\u MOVING
是在移动窗口时发送的(因此您将得到很多这样的信息)
从这里开始阅读:
你必须对这个过程有一个钩子,并倾听这个事件 这应该给你一个很好的起点
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private const uint WINEVENT_OUTOFCONTEXT = 0x0000;
private const uint EVENT_OBJECT_LOCATIONCHANGE = 0x800B;
private const uint EVENT_SYSTEM_MOVESIZESTART = 0x000A;
private const uint EVENT_SYSTEM_MOVESIZEEND = 0x000B;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
this.Width = 100;
this.Height = 100;
this.TopMost = true;
int processId = Process.GetProcessesByName("OUTLOOK")[0].Id;
//this will also be triggered by mouse moving over the process windows
//NativeMethods.SetWinEventHook(EVENT_OBJECT_LOCATIONCHANGE, EVENT_OBJECT_LOCATIONCHANGE, IntPtr.Zero, WinEventProc, (uint)processId, (uint)0, WINEVENT_OUTOFCONTEXT);
NativeMethods.SetWinEventHook(EVENT_SYSTEM_MOVESIZESTART, EVENT_SYSTEM_MOVESIZEEND, IntPtr.Zero, WinEventProc, (uint)processId, (uint)0, WINEVENT_OUTOFCONTEXT);
}
private void WinEventProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
Rect move = new Rect();
if (eventType == EVENT_SYSTEM_MOVESIZESTART)
{
NativeMethods.GetWindowRect(hwnd, ref move);
Debug.WriteLine("EVENT_SYSTEM_MOVESIZESTART");
}
else if (eventType == EVENT_SYSTEM_MOVESIZEEND)
{
NativeMethods.GetWindowRect(hwnd, ref move);
Debug.WriteLine("EVENT_SYSTEM_MOVESIZEEND");
}
this.Left = move.Left;
this.Top = move.Top;
}
}
public struct Rect
{
public int Left { get; set; }
public int Top { get; set; }
public int Right { get; set; }
public int Bottom { get; set; }
}
static class NativeMethods
{
[DllImport("user32.dll")]
public static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);
public delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
[DllImport("user32.dll")]
public static extern bool GetWindowRect(IntPtr hwnd, ref Rect rectangle);
}
}
弗雷多的回答是最正确的 我在应用程序中使用了它,但出现了一个异常“callbackoncollecteddelegate”。 要使其正常工作,有必要在属性上附加WinEventProc
...
private NativeMethods.WinEventDelegate winEventProc;
private void Form1_Load(object sender, EventArgs e)
{
this.Width = 100;
this.Height = 100;
this.TopMost = true;
int processId = Process.GetProcessesByName("OUTLOOK")[0].Id;
//this will also be triggered by mouse moving over the process windows
//NativeMethods.SetWinEventHook(EVENT_OBJECT_LOCATIONCHANGE, EVENT_OBJECT_LOCATIONCHANGE, IntPtr.Zero, WinEventProc, (uint)processId, (uint)0, WINEVENT_OUTOFCONTEXT);
this.winEventProc = new NativeMethods.WinEventDelegate(WinEventProc);
NativeMethods.SetWinEventHook(EVENT_SYSTEM_MOVESIZESTART, EVENT_SYSTEM_MOVESIZEEND, IntPtr.Zero, this.winEventProc, (uint)processId, (uint)0, WINEVENT_OUTOFCONTEXT);
}
...
请参见不要在睡眠的while循环中进行调整:使用计时器。另外,在设置属性之前,请先测试位置是否不变。您可以使用SetWinEventHook()、EVENT\u OBJECT\u LOCATIONCHANGE notification来执行此操作。在您的链接问题中可能重复的@MA Maddin与我的问题相当,因为我的问题比我的问题早了2年多。@halloei完全正确,先用另一种方式执行此操作,但后来发现了这个元QA:有没有办法监听事件的大小调整?例如,如果用户将Outlook窗体向下拖动上边框,则只有在完成调整大小后,窗体才会重新定位,因此会出现明显的延迟。