10

I am trying to write an accesibility app for 32bit Windows 8 Pro tablet PC using Magnification API. App can perfectly zoom-in and zoom-out full screen, but when zoomed in, the click events are sent to wrong places of the unmagnified screen, so user can' t touch what he sees exactly.

To solve this, I tried MagSetInputTransform(fSetInputTransform, rcSource, rcDest). It works on 64bit Windows 8 desktop but when I test it on tablet, I get the following error:

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)

The exactly same error is obtained, when I try to compile project for x86 target platform and test under 64bit machine.

To summarize;

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 ?

How can I use this WinAPI function in 32bit Windows 8 tablet?

EDIT1

Here is the method that produces the error:

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

EDIT2

Here are the pinvoke signatures:

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

And this is how my RECT structure looks like.

Alpay
  • 1,350
  • 2
  • 24
  • 56
  • Can you post the source code that relates to the error location? – Roger Rowland May 29 '13 at 07:51
  • @RogerRowland error is thrown exactly where I call `MagSetInputTransform` method – Alpay May 29 '13 at 08:57
  • Thanks - I can't see anything wrong with your code, so a mystery to me too. I will ponder and return if possible .... – Roger Rowland May 29 '13 at 09:08
  • @RogerRowland Thank you in advance... I actually copied and converted above piece of code from [this](http://msdn.microsoft.com/tr-tr/library/windows/desktop/hh162715(v=vs.85).aspx) Microsoft page. It runs without any problem, when compiled for target platform x64 and tested under 64bit Windows 8 Pro desktop machine. I just can' t run it on x86 based Windows 8 Pro tablet pc. – Alpay May 29 '13 at 10:17
  • Have you made sure that you have the [uiAccess](http://msdn.microsoft.com/en-us/library/bb384691.aspx) privilege? Sorry I don't know C#, so I have to ask if it is correct that you have left out the 0 initialization of "left" and "top" in "rcDest". – typ1232 Jun 02 '13 at 16:40
  • So the tablet runs a desktop application not Metro? – dsfgsho Jun 03 '13 at 09:03
  • @StevenHouben It is a regular Windows Forms Application, not Metro. – Alpay Jun 03 '13 at 11:00
  • @typ1232 Yes, I got uiAccess privilage. It should be unnecessary to memset the fields of RECT structure. – Alpay Jun 03 '13 at 11:02
  • And what is the PInvoke signature of MagGetFullscreenTransform? – dsfgsho Jun 03 '13 at 12:53
  • @StevenHouben I edited the question and added my pinvoke structures. BTW MagGetFullscreenTransform works succesfully. MagSetInputTransform gives me the pain – Alpay Jun 03 '13 at 14:36
  • Are you sure your P/Invoke signature is correct? The c++ signature is `_In_ const LPRECT` and MSDN explains: _"For example, LPRECT is a pointer to a RECT, where RECT is a structure that describes a rectangle"_[Link](http://msdn.microsoft.com/en-us/library/windows/desktop/ff381404(v=vs.85).aspx) – dsfgsho Jun 03 '13 at 16:35

1 Answers1

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

and 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 takes LPRECTs, not RECTs

I can't explain why it worked on one machine though.

typ1232
  • 5,535
  • 6
  • 35
  • 51
  • What is the difference between LPRECT and RECT structures? I tought LP just stands for Long Pointer. I already tried both alternatives you pointed. BTW, I wrote the app in pure C++ and everything works like a charm. I think the problem is right in the pinvoke signatures. What do you think? – Alpay Jun 05 '13 at 06:08
  • 1
    [This](http://msdn.microsoft.com/en-us/library/windows/desktop/ff381404(v=vs.85).aspx) article tells that `RECT* rect; // Pointer to a RECT structure.` `LPRECT rect; // The same` `PRECT rect; // Also the same.` all of these are the same. – Alpay Jun 05 '13 at 06:11