在Windows 8 Pro平板电脑上使用WinAPI时抛出AccessViolationException异常

10

我正在尝试使用Magnification API32位Windows 8专业版平板电脑编写一个无障碍应用程序。该应用程序可以完美地对全屏进行缩放,但是当缩放时,点击事件会发送到未缩放屏幕的错误位置,因此用户不能精确触摸所看到的内容。

为了解决这个问题,我尝试使用MagSetInputTransform(fSetInputTransform, rcSource, rcDest)。它在64位Windows 8桌面上运行良好,但是当我在平板电脑上测试时,出现以下错误:

System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
   at GTZoom.WinAPIMethods.MagSetInputTransform(Boolean fEnabled, RECT prcSource, RECT prcDest)
   at GTZoom.ZoomControl.SetInput(IntPtr hwndDlg, Boolean fSetInputTransform) in c:\Users\AlpayK\Desktop\GTMagnify\GTMagnify\ZoomControl.cs:line 113
   at GTZoom.ZoomControl.trackBar1_Scroll(Object sender, EventArgs e) in c:\Users\AlpayK\Desktop\GTMagnify\GTMagnify\ZoomControl.cs:line 37
   at System.Windows.Forms.TrackBar.OnScroll(EventArgs e)
   at System.Windows.Forms.TrackBar.WndProc(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
尝试为x86目标平台编译项目并在64位机器上测试时,会得到完全相同的错误。
总结如下:
Target platform x64 -> Tested under 64bit Windows 8 Desktop    OK
Target platform x86 -> Tested under 64bit Windows 8 Desktop    ERROR
Target platform x64 -> Tested under 64bit Windows 8 Tablet     ERROR
Target platform x86 -> Tested under 32bit Windows 8 Tablet     ERROR ?

我如何在32位的Windows 8平板电脑上使用这个WinAPI函数?

编辑1

这是产生错误的方法:

void SetInput(IntPtr hwndDlg, bool fSetInputTransform)
        {
            bool fContinue = true;

            RECT rcSource = new RECT();
            RECT rcDest = new RECT();

            // MagSetInputTransform() is used to adjust pen and touch input to account for the current magnification.
            // The "Source" and "Destination" rectangles supplied to MagSetInputTransform() are from the perspective
            // of the currently magnified visuals. The source rectangle is the portion of the screen that is 
            // currently being magnified, and the destination rectangle is the area on the screen which shows the 
            // magnified results.

            // If we're setting an input transform, base the transform on the current fullscreen magnification.
            if (fSetInputTransform)
            {
                // Assume here the touch and pen input is going to the primary monitor.
                rcDest.Right = screenWidth;
                rcDest.Bottom = screenHeight;

                float magnificationFactor = 0;
                int xOffset = 0;
                int yOffset = 0;

                // Get the currently active magnification.
                if (WinAPIMethods.MagGetFullscreenTransform(ref magnificationFactor, ref xOffset, ref yOffset))
                {
                    // Determine the area of the screen being magnified.
                    rcSource.Left = xOffset;
                    rcSource.Top = yOffset;
                    rcSource.Right = rcSource.Left + (int)(rcDest.Right / magnificationFactor);
                    rcSource.Bottom = rcSource.Top + (int)(rcDest.Bottom / magnificationFactor);
                }
                else
                {
                    // An unexpected error occurred trying to get the current magnification.
                    fContinue = false;
                }
            }

            if (fContinue)
            {
                // Now set the input transform as required.
                if (!WinAPIMethods.MagSetInputTransform(fSetInputTransform, rcSource, rcDest))
                {
                    MessageBox.Show("Err");
                }
            }
        }

编辑2

以下是pinvoke签名:

[DllImport("Magnification.dll", CallingConvention = CallingConvention.StdCall)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool MagGetFullscreenTransform(ref float magLevel, ref int xOffset, ref int yOffset);

[DllImport("Magnification.dll", CallingConvention = CallingConvention.StdCall)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool MagSetInputTransform(bool fEnabled, RECT prcSource, RECT prcDest);

这是我的RECT结构的样子,在这里查看更多信息。


你能发布与错误位置相关的源代码吗? - Roger Rowland
@RogerRowland 错误正好在我调用 MagSetInputTransform 方法的位置抛出。 - Alpay
谢谢 - 我看不出你的代码有什么问题,所以对我来说是个谜。如果可能的话,我会思考并回复.... - Roger Rowland
那么这个平板电脑运行的是桌面应用程序而不是Metro吗? - dsfgsho
@StevenHouben 这是一个普通的 Windows Forms 应用程序,不是 Metro。 - Alpay
显示剩余6条评论
1个回答

1
WinAPIMethods.MagSetInputTransform(fSetInputTransform, rcSource, rcDest)
WinAPIMethods.MagSetInputTransform(fSetInputTransform, ref rcSource, ref rcDest)

和 PInvoke

public static extern bool MagSetInputTransform(bool fEnabled, RECT prcSource, RECT prcDest);
public static extern bool MagSetInputTransform(bool fEnabled, ref RECT prcSource, ref RECT prcDest);
MagSetInputTransform接受LPRECT而不是RECT。我无法解释为什么它在一台机器上能够工作。

LPRECT和RECT结构之间有什么区别?我以为LP只是代表长指针。我已经尝试了你指出的两种替代方案。顺便说一句,我用纯C++编写了应用程序,一切都像魔法般运行。我认为问题就在于PInvoke签名。你觉得呢? - Alpay
1
这篇文章说明了 RECT* rect; // 指向 RECT 结构体的指针。 LPRECT rect; // 同上 PRECT rect; // 同样是一样的。 - Alpay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接