internal unsafe static extern uint GetRegionData(
     IntPtr hRgn,
     uint dwCount,
     NativeStructs.RGNDATA *lpRgnData);
Exemplo n.º 2
0
        private static unsafe void GetRegionScans(IntPtr hRgn, out Rectangle[] scans)
        {
            uint bytes     = 0;
            int  countdown = 100;
            int  error     = 0;

            // HACK: It seems that sometimes the GetRegionData will return ERROR_INVALID_HANDLE
            //       even though the handle (the HRGN) is fine. Maybe the function is not
            //       re-entrant? I'm not sure, but trying it again seems to fix it.
            while (countdown > 0)
            {
                bytes = SafeNativeMethods.GetRegionData(hRgn, 0, (NativeStructs.RGNDATA *)IntPtr.Zero);
                error = Marshal.GetLastWin32Error();

                if (bytes == 0)
                {
                    --countdown;
                    System.Threading.Thread.Sleep(5);
                }
                else
                {
                    break;
                }
            }

            // But if we retry several times and it still messes up then we will finally give up.
            if (bytes == 0)
            {
                throw new Win32Exception(error, "GetRegionData returned " + bytes.ToString(CultureInfo.CurrentCulture) + ", GetLastError() = " + error.ToString(CultureInfo.CurrentCulture));
            }

            byte *data;

            // Up to 512 bytes, allocate on the stack. Otherwise allocate from the heap.
            if (bytes <= 512)
            {
                byte *data1 = stackalloc byte[(int)bytes];
                data = data1;
            }
            else
            {
                data = (byte *)Memory.Allocate(bytes, false).ToPointer();
            }

            try
            {
                NativeStructs.RGNDATA *pRgnData = (NativeStructs.RGNDATA *)data;
                uint result = SafeNativeMethods.GetRegionData(hRgn, bytes, pRgnData);

                if (result != bytes)
                {
                    throw new OutOfMemoryException("SafeNativeMethods.GetRegionData returned 0");
                }

                NativeStructs.RECT *pRects = NativeStructs.RGNDATA.GetRectsPointer(pRgnData);
                scans = new Rectangle[pRgnData->rdh.nCount];

                for (int i = 0; i < scans.Length; ++i)
                {
                    scans[i] = Rectangle.FromLTRB(pRects[i].left, pRects[i].top, pRects[i].right, pRects[i].bottom);
                }

                pRects   = null;
                pRgnData = null;
            }
            finally
            {
                if (bytes > 512)
                {
                    Memory.Free(new IntPtr(data));
                }
            }
        }
Exemplo n.º 3
0
 internal static extern unsafe uint GetRegionData([In()] IntPtr hrgn, [In()] uint nCount, [Out()] NativeStructs.RGNDATA *lpRgnData);