Example #1
0
        public HwndWrapper(
            int classStyle,
            int style,
            int exStyle,
            int x,
            int y,
            int width,
            int height,
            string name,
            IntPtr parent,
            HwndWrapperHook[] hooks)
        {
            _ownerThreadID = new SecurityCriticalDataForSet <int>(Thread.CurrentThread.ManagedThreadId);


            // First, add the set of hooks.  This allows the hooks to receive the
            // messages sent to the window very early in the process.
            if (hooks != null)
            {
                for (int i = 0, iEnd = hooks.Length; i < iEnd; i++)
                {
                    if (null != hooks[i])
                    {
                        AddHook(hooks[i]);
                    }
                }
            }


            _wndProc = new SecurityCriticalData <HwndWrapperHook>(new HwndWrapperHook(WndProc));

            // We create the HwndSubclass object so that we can use its
            // window proc directly.  We will not be "subclassing" the
            // window we create.
            HwndSubclass hwndSubclass = new HwndSubclass(_wndProc.Value);

            // Register a unique window class for this instance.
            NativeMethods.WNDCLASSEX_D wc_d = new NativeMethods.WNDCLASSEX_D();

            IntPtr hNullBrush = UnsafeNativeMethods.CriticalGetStockObject(NativeMethods.NULL_BRUSH);

            if (hNullBrush == IntPtr.Zero)
            {
                throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
            }

            IntPtr hInstance = UnsafeNativeMethods.GetModuleHandle(null);

            // We need to keep the Delegate object alive through the call to CreateWindowEx().
            // Subclass.WndProc will install a better delegate (to the same function) when it
            // processes the first message.
            // But this first delegate needs be held alive until then.
            NativeMethods.WndProc initialWndProc = new NativeMethods.WndProc(hwndSubclass.SubclassWndProc);

            // The class name is a concat of AppName, ThreadName, and RandomNumber.
            // Register will fail if the string gets over 255 in length.
            // So limit each part to a reasonable amount.
            string appName;

            if (null != AppDomain.CurrentDomain.FriendlyName && 128 <= AppDomain.CurrentDomain.FriendlyName.Length)
            {
                appName = AppDomain.CurrentDomain.FriendlyName.Substring(0, 128);
            }
            else
            {
                appName = AppDomain.CurrentDomain.FriendlyName;
            }

            string threadName;

            if (null != Thread.CurrentThread.Name && 64 <= Thread.CurrentThread.Name.Length)
            {
                threadName = Thread.CurrentThread.Name.Substring(0, 64);
            }
            else
            {
                threadName = Thread.CurrentThread.Name;
            }

            // Create a suitable unique class name.
            _classAtom = 0;
            string randomName = Guid.NewGuid().ToString();
            string className  = String.Format(CultureInfo.InvariantCulture, "HwndWrapper[{0};{1};{2}]", appName, threadName, randomName);

            wc_d.cbSize        = Marshal.SizeOf(typeof(NativeMethods.WNDCLASSEX_D));
            wc_d.style         = classStyle;
            wc_d.lpfnWndProc   = initialWndProc;
            wc_d.cbClsExtra    = 0;
            wc_d.cbWndExtra    = 0;
            wc_d.hInstance     = hInstance;
            wc_d.hIcon         = IntPtr.Zero;
            wc_d.hCursor       = IntPtr.Zero;
            wc_d.hbrBackground = hNullBrush;
            wc_d.lpszMenuName  = "";
            wc_d.lpszClassName = className;
            wc_d.hIconSm       = IntPtr.Zero;

            // Register the unique class for this instance.
            // Note we use a GUID in the name so we are confident that
            // the class name should be unique.  And RegisterClassEx won't
            // fail (for that reason).
            _classAtom = UnsafeNativeMethods.RegisterClassEx(wc_d);

            // call CreateWindow
            _isInCreateWindow = true;
            try {
                _handle = new SecurityCriticalDataClass <IntPtr>(UnsafeNativeMethods.CreateWindowEx(exStyle,
                                                                                                    className,
                                                                                                    name,
                                                                                                    style,
                                                                                                    x,
                                                                                                    y,
                                                                                                    width,
                                                                                                    height,
                                                                                                    new HandleRef(null, parent),
                                                                                                    new HandleRef(null, IntPtr.Zero),
                                                                                                    new HandleRef(null, IntPtr.Zero),
                                                                                                    null));
            }
            finally
            {
                _isInCreateWindow = false;
                if (_handle == null || _handle.Value == IntPtr.Zero)
                {
                    // Because the HwndSubclass is pinned, but the HWND creation failed,
                    // we need to manually clean it up.
                    hwndSubclass.Dispose();
                }
            }
            GC.KeepAlive(initialWndProc);
        }