如何将我的表单粘贴到第三方应用程序的窗口?

时间:2015-08-05 12:23:42

标签: c# winforms

我试图将表单粘贴到另一个应用程序的窗口(让我们说微软Outlook)。当我移动Outlook窗口时,我的表单仍然应该放在它的右侧。

目前,我正在while(true)循环(使用sleep())监控Outlook的排名并调整我的表单位置。

以下是两个问题:

  • 如果sleep()持续时间太短,检查Outlook的位置并经常调整我的表单需要很高的性能。
  • 如果sleep()持续时间太长,我的表单在调整到Outlook时速度太慢(滞后)。

是否有本地解决方案呢?

3 个答案:

答案 0 :(得分:2)

你必须抓住这个过程并听取事件

这应该给你一个很好的起点

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

答案 1 :(得分:1)

您可以使用任何窗口挂钩函数WH_GETMESSAGEWH_GETMESSAGERETWH_SYSMSGFILTERWH_MSGFILTER

在这种情况下,您会对WM_MOVEWM_MOVING感兴趣,其中移动窗口后发送WM_MOVE(也称为已移动),WM_MOVING为窗口移动时发送(所以你会得到很多那些)。

从这里开始阅读:

https://msdn.microsoft.com/en-us/library/windows/desktop/ms644959(v=vs.85).aspx

答案 2 :(得分:0)

Fredou的答案就是答案。

我在我的应用程序中使用它,但得到一个例外“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);
    }
...

请参阅CallbackOnCollectedDelegate at Application.Run(new Form1())