3

我正在 c# 上编写一个实现鼠标和键盘钩子的程序,一旦单击指定的键,它将去抓取前景窗口并将其 x、y、高度和宽度保存到 xml 文件中。

我不确定出了什么问题,但我不断收到错误的尺寸和错误的参数。

我很感激这方面的帮助,因为我现在已经为此苦苦挣扎了两天。

波纹管是相关代码。

标准声明:

//rectangle for the windows size
        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }


        //win API
        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern IntPtr GetForegroundWindow();

        [return: MarshalAs(UnmanagedType.Bool)]
        [DllImport("user32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
        public static extern bool SetForegroundWindow(IntPtr hwnd);

        [DllImport("user32.dll", SetLastError = true)]
        static extern bool GetWindowRect(IntPtr hWnd, ref RECT Rect);

以及相关代码本身

void mouseHook_MouseDown(object sender, MouseEventArgs e)
        {
            this.handle = GetForegroundWindow();   
        }

        #region keyboard pressed
        void keyboardHook_KeyDown(object sender, KeyEventArgs e)
        {            
            if (e.KeyCode == Keys.F9) //if slot selected
            {
                RECT Rect = new RECT();
                SetForegroundWindow(this.handle);
                //this.handle = GetForegroundWindow();    
                GetWindowRect(this.handle, ref Rect);

                Grid newSlot = new Grid();
                newSlot.topX = Rect.Top;
                newSlot.topY = Rect.Left;
                newSlot.width = Rect.Right - Rect.Left;
                newSlot.height = Rect.Bottom - Rect.Top;

                layoutGrid.Add(newSlot);
                lbl_slots.Text = layoutGrid.Count().ToString();
            }
            else if (e.KeyCode == Keys.F10) //if main stack slot selected
            {
                RECT Rect = new RECT();
                SetForegroundWindow(handle);
                GetWindowRect(GetForegroundWindow(), ref Rect);    
                for (int i = 0; i < layoutGrid.Count(); i++) //selecting slot for main stack
                {
                    layoutGrid[i].slot_number = i + 1; //setting slots numbers
                    if (layoutGrid[i].topX != Rect.Top && layoutGrid[i].topY != Rect.Left)
                        layoutGrid[i].is_stack = false;
                    else
                    {
                        layoutGrid[i].is_stack = true;
                        lbl_stackSlot.Text = (i + 1).ToString();

                    }
                }
            }
        }

编辑: 我尝试同时使用公共结构 RECT 和 Rectangle,我收到的 RECT 值似乎是随机的,我的意思是 left 和 top 以及 height 和 width,有时它会找到合适的点,但有时它似乎完全是随机的. 我用 Rectangle 收到的值似乎有正确的 left 和 top 但返回错误的高度和宽度。

4

2 回答 2

2

我终于找到了解决方案。如果有人遇到同样的问题,我会在此处发布。

我最终使用了 GetWindowInfo 而不是 GetWindowRect ,它的工作原理就像魅力一样。

从网上找到的代码示例和文章http://kenneththorman.blogspot.com/2010/08/c-net-active-windows-size-helper.html

感谢所有试图提供帮助的人。

于 2011-09-29T15:01:33.517 回答
0

使用System.Drawing.Rectangle不正确。字段不匹配。你的定义RECT是正确的。

我猜了一点,但您的问题可能与GetWindowRectMSDN 主题底部的评论有关。

Vista 下未与 WINVER=6 链接的应用程序将在此处收到一组误导性值,这些值不考虑 Vista Aero 应用于窗口的“玻璃”像素的额外填充。即使在 Aero Basic(不带 Glass)中似乎也会发生这种情况,以保持尺寸一致性。解决方法(如果你不想设置 WINVER=6)似乎是动态绑定到 dwmapi.dll 并使用 GetProcAddress() 获取 DwmGetWindowAttribute() 函数,并使用 DWMWA_EXTENDED_FRAME_BOUNDS 参数调用它以请求正版窗口框架尺寸。

于 2011-09-28T14:46:39.790 回答