OnNonClientAreaPaint() protected method

protected OnNonClientAreaPaint ( NonClientPaintEventArgs e ) : void
e NonClientPaintEventArgs
return void
Esempio n. 1
0
        private void PaintNonClientArea(IntPtr hWnd, IntPtr hRgn)
        {
            var windowRect = new NativeMethods.RECT();

            if (NativeMethods.GetWindowRect(hWnd, ref windowRect) == 0)
            {
                return;
            }

            var bounds = new Rectangle(
                0,
                0,
                windowRect.right - windowRect.left,
                windowRect.bottom - windowRect.top
                );

            if (bounds.Width == 0 || bounds.Height == 0)
            {
                return;
            }

            // The update region is clipped to the window frame. When wParam
            // is 1, the entire window frame needs to be updated.
            Region clipRegion = null;

            if (hRgn != (IntPtr)1)
            {
                clipRegion = Region.FromHrgn(hRgn);
            }

            // MSDN states that only WINDOW and INTERSECTRGN are needed,
            // but other sources confirm that CACHE is required on Win9x
            // and you need CLIPSIBLINGS to prevent painting on overlapping windows.

            var hDC = NativeMethods.GetDCEx(
                hWnd,
                hRgn,
                NativeMethods.DCX_WINDOW | NativeMethods.DCX_INTERSECTRGN | NativeMethods.DCX_CACHE | NativeMethods.DCX_CLIPSIBLINGS
                );

            if (hDC == IntPtr.Zero)
            {
                hDC = NativeMethods.GetWindowDC(hWnd);
            }

            if (hDC == IntPtr.Zero)
            {
                return;
            }

            try
            {
                var border = _chrome.AdjustedResizeBorderThickness;

                var clientArea = new Rectangle(
                    border.Left,
                    border.Top + _chrome.CaptionHeight,
                    _form.Width - border.Horizontal,
                    _form.Height - (border.Vertical + _chrome.CaptionHeight)
                    );

                if (!_chrome.DoubleBuffered)
                {
                    using (Graphics graphics = Graphics.FromHdc(hDC))
                    {
                        graphics.ExcludeClip(clientArea);

                        // Cliping rect is not cliping rect but actual rectangle.

                        _chrome.OnNonClientAreaPaint(new NonClientPaintEventArgs(
                                                         graphics,
                                                         bounds,
                                                         clipRegion,
                                                         IsMaximized,
                                                         IsActive
                                                         ));
                    }

                    // NOTE: The Graphics object would realease the HDC on Dispose.
                    // So there is no need to call NativeMethods.ReleaseDC(msg.HWnd, hDC);
                    // http://groups.google.pl/groups?hl=pl&lr=&c2coff=1&client=firefox-a&rls=org.mozilla:en-US:official_s&threadm=%23DDSaH7BFHA.3644%40TK2MSFTNGP15.phx.gbl&rnum=15&prev=/groups%3Fq%3DWM_NCPaint%2B%2BGetDCEx%26start%3D10%26hl%3Dpl%26lr%3D%26c2coff%3D1%26client%3Dfirefox-a%26rls%3Dorg.mozilla:en-US:official_s%26selm%3D%2523DDSaH7BFHA.3644%2540TK2MSFTNGP15.phx.gbl%26rnum%3D15
                    // http://groups.google.pl/groups?hl=pl&lr=&c2coff=1&client=firefox-a&rls=org.mozilla:en-US:official_s&threadm=cmo00r%24j9v%241%40mamut1.aster.pl&rnum=1&prev=/groups%3Fq%3DDCX_PARENTCLIP%26hl%3Dpl%26lr%3D%26c2coff%3D1%26client%3Dfirefox-a%26rls%3Dorg.mozilla:en-US:official_s%26selm%3Dcmo00r%2524j9v%25241%2540mamut1.aster.pl%26rnum%3D1
                }
                else
                {
                    // http://www.codeproject.com/csharp/flicker_free.asp
                    // http://www.pinvoke.net/default.aspx/gdi32/BitBlt.html

                    var compatiblehDc    = NativeMethods.CreateCompatibleDC(hDC);
                    var compatibleBitmap = NativeMethods.CreateCompatibleBitmap(hDC, bounds.Width, bounds.Height);

                    try
                    {
                        NativeMethods.SelectObject(compatiblehDc, compatibleBitmap);

                        // copy current screen to bitmap
                        // TODO: this is quite slow (80% of this method). Why?
                        NativeMethods.BitBlt(compatiblehDc, 0, 0, bounds.Width, bounds.Height, hDC, 0, 0, NativeMethods.SRCCOPY);

                        using (Graphics g = Graphics.FromHdc(compatiblehDc))
                        {
                            g.ExcludeClip(clientArea);

                            //cliping rect is not cliping rect but actual rectangle
                            _chrome.OnNonClientAreaPaint(new NonClientPaintEventArgs(
                                                             g,
                                                             bounds,
                                                             clipRegion,
                                                             IsMaximized,
                                                             IsActive
                                                             ));
                        }

                        // copy current from bitmap to screen
                        NativeMethods.BitBlt(hDC, 0, 0, bounds.Width, bounds.Height, compatiblehDc, 0, 0, NativeMethods.SRCCOPY);
                    }
                    finally
                    {
                        NativeMethods.DeleteObject(compatibleBitmap);
                        NativeMethods.DeleteDC(compatiblehDc);
                    }
                }
            }
            finally
            {
                NativeMethods.ReleaseDC(Handle, hDC);
            }
        }