Пример #1
0
        /// <summary>
        /// Override for the main forms WndProc method
        /// This is used to intercept the forms movement so that we can move
        /// blended background form at the same time, as well as check for
        /// when the form is activated so we can ensure the Z-order of our
        /// forms remains intact.
        /// </summary>
        /// <param name="m">Windows Message</param>
        protected override void WndProc(ref Message m)
        {
            if (this.DesignMode)
            {
                base.WndProc(ref m);
                return;
            }

            Win32.Message msgId   = (Win32.Message)m.Msg;
            bool          UseBase = true;

            switch (msgId)
            {
            case Win32.Message.WM_LBUTTONUP:
            {
                //Just in case
                if (Win32.GetCapture() != IntPtr.Zero)
                {
                    Win32.ReleaseCapture();
                }
            }
            break;

            case Win32.Message.WM_ENTERSIZEMOVE:
            {
            }
            break;

            case Win32.Message.WM_EXITSIZEMOVE:
            {
                //We've stopped dragging the form, so lets make sure that our values are correct
                m_isDown.Left = false;
                m_moving      = false;

                if (m_enhanced)
                {
                    this.SuspendLayout();
                    foreach (Control ctrl in m_hiddenControls)
                    {
                        ctrl.Visible = true;
                    }
                    m_hiddenControls.Clear();
                    this.ResumeLayout();
                    updateLayeredBackground(this.ClientSize.Width, this.ClientSize.Height, m_layeredWnd.LayeredPos, false);
                }
            }
            break;

            case Win32.Message.WM_MOUSEMOVE:
                //It's unlikely that we will get here unless this we really have captured the mouse
                //because the entire thing is transparent, but we check anyway just to make sure
                if (Win32.GetCapture() != IntPtr.Zero && m_moving)
                {
                    //In enhanced mode we draw the main window to the layered window and then hide the main
                    //window. This is so that we can have perfectly smooth motion when dragging the form, as
                    //we cannot gurantee that the forms will ever be moved together otherwise
                    if (m_enhanced)
                    {
                        //Setup the device contexts we are going to use
                        IntPtr hdcScreen = Win32.GetWindowDC(m_layeredWnd.Handle);                                      //Screen DC that the layered window will draw to
                        IntPtr windowDC  = Win32.GetDC(this.Handle);                                                    //Window DC that we are going to copy
                        IntPtr memDC     = Win32.CreateCompatibleDC(windowDC);                                          //Temporary DC that we draw to
                        IntPtr BmpMask   = Win32.CreateBitmap(this.ClientSize.Width,
                                                              this.ClientSize.Height, 1, 1, IntPtr.Zero);               //Mask bitmap so that we only draw areas of the form that are visible

                        Bitmap backImage = m_useBackgroundEx ? m_backgroundFull : m_background;
                        IntPtr BmpBack   = backImage.GetHbitmap(Color.FromArgb(0));                                     //Background Image

                        //Create mask
                        Win32.SelectObject(memDC, BmpMask);
                        uint oldCol = Win32.SetBkColor(windowDC, 0x00FF00FF);
                        Win32.BitBlt(memDC, 0, 0, this.ClientSize.Width, this.ClientSize.Height, windowDC, 0, 0, Win32.TernaryRasterOperations.SRCCOPY);
                        Win32.SetBkColor(windowDC, oldCol);

                        //Blit window to background image using mask
                        //We need to use the SPno raster operation with a white brush to combine our window
                        //with a black backround before putting it onto the 32-bit background image, otherwise
                        //we end up with blending issues (source and destination colours are ANDed together)
                        Win32.SelectObject(memDC, BmpBack);
                        IntPtr brush = Win32.CreateSolidBrush(0x00FFFFFF);
                        Win32.SelectObject(memDC, brush);
                        Win32.MaskBlt(memDC, 0, 0, backImage.Width, backImage.Height, windowDC, 0, 0, BmpMask, 0, 0, 0xCFAA0020);
                        //Win32.BitBlt(memDC, 0, 0, backImage.Width, backImage.Height, windowDC, m_offX, m_offY, Win32.TernaryRasterOperations.SRCCOPY);

                        Point zero = new Point(0, 0);
                        Size  size = m_layeredWnd.LayeredSize;
                        Point pos  = m_layeredWnd.LayeredPos;
                        Win32.BLENDFUNCTION blend = new Win32.BLENDFUNCTION();
                        blend.AlphaFormat         = (byte)Win32.BlendOps.AC_SRC_ALPHA;
                        blend.BlendFlags          = (byte)Win32.BlendFlags.None;
                        blend.BlendOp             = (byte)Win32.BlendOps.AC_SRC_OVER;
                        blend.SourceConstantAlpha = (byte)(this.Opacity * 255);

                        Win32.UpdateLayeredWindow(m_layeredWnd.Handle, hdcScreen, ref pos, ref size, memDC, ref zero, 0, ref blend, Win32.BlendFlags.ULW_ALPHA);

                        //Clean up
                        Win32.ReleaseDC(IntPtr.Zero, hdcScreen);
                        Win32.ReleaseDC(this.Handle, windowDC);
                        Win32.DeleteDC(memDC);
                        Win32.DeleteObject(brush);
                        Win32.DeleteObject(BmpMask);
                        Win32.DeleteObject(BmpBack);

                        //Hide controls that are visible
                        this.SuspendLayout();
                        foreach (Control ctrl in this.Controls)
                        {
                            if (ctrl.Visible)
                            {
                                m_hiddenControls.Add(ctrl);
                                ctrl.Visible = false;
                            }
                        }
                        this.ResumeLayout();
                    }

                    //If we do not release the mouse then Windows will not start dragging the form, also
                    //it will mess up mouse input to any border on our form and other windows on the desktop
                    Win32.ReleaseCapture();
                    Win32.SendMessage(this.Handle, (int)Win32.Message.WM_NCLBUTTONDOWN, (int)Win32.Message.HTCAPTION, 0);
                }
                break;

            case Win32.Message.WM_SIZE:
            {
                //The updateLayeredSize function will check the width and height
                //we pass in, so we don't need to worry about updating the window
                //with the same size it already had
                int width  = m.LParam.ToInt32() & 0xFFFF;
                int height = m.LParam.ToInt32() >> 16;
                this.updateLayeredSize(width, height);
            }
            break;

            case Win32.Message.WM_WINDOWPOSCHANGING:
            {
                Win32.WINDOWPOS posInfo = (Win32.WINDOWPOS)Marshal.PtrToStructure(m.LParam, typeof(Win32.WINDOWPOS));

                //We will cancel this movement, and send our own messages to position both forms
                //this way we can ensure that both forms are moved together and that
                //the Z order is unchanged.
                Win32.WindowPosFlags move_size = Win32.WindowPosFlags.SWP_NOMOVE | Win32.WindowPosFlags.SWP_NOSIZE;
                if ((posInfo.flags & move_size) != move_size)
                {
                    //Check for my own messages, which I do by setting to hwndInsertAfter to our
                    //own window, which from what I can gather only happens when you resize your
                    //window, never when you move it
                    if (posInfo.hwndInsertAfter != this.Handle)
                    {
                        IntPtr hwdp = Win32.BeginDeferWindowPos(2);
                        if (hwdp != IntPtr.Zero)
                        {
                            hwdp = Win32.DeferWindowPos(hwdp, m_layeredWnd.Handle, this.Handle, posInfo.x + m_offX, posInfo.y + m_offY,
                                                        0, 0, (uint)(posInfo.flags | Win32.WindowPosFlags.SWP_NOSIZE | Win32.WindowPosFlags.SWP_NOZORDER));
                        }
                        if (hwdp != IntPtr.Zero)
                        {
                            hwdp = Win32.DeferWindowPos(hwdp, this.Handle, this.Handle, posInfo.x, posInfo.y, posInfo.cx, posInfo.cy,
                                                        (uint)(posInfo.flags | Win32.WindowPosFlags.SWP_NOZORDER));
                        }
                        if (hwdp != IntPtr.Zero)
                        {
                            Win32.EndDeferWindowPos(hwdp);
                        }

                        m_layeredWnd.LayeredPos = new Point(posInfo.x + m_offX, posInfo.y + m_offY);

                        //Update the flags so that the form will not move with this message
                        posInfo.flags |= Win32.WindowPosFlags.SWP_NOMOVE;
                        Marshal.StructureToPtr(posInfo, m.LParam, true);
                    }

                    if ((posInfo.flags & Win32.WindowPosFlags.SWP_NOSIZE) == 0)
                    {
                        //Form was also resized
                        int diffX = posInfo.cx - this.Size.Width;
                        int diffY = posInfo.cy - this.Size.Height;
                        if (diffX != 0 || diffY != 0)
                        {
                            this.updateLayeredSize(this.ClientSize.Width + diffX, this.ClientSize.Height + diffY);
                        }
                    }

                    UseBase = false;
                }
            }
            break;


            case Win32.Message.WM_ACTIVATE:
            {
                //If WParam is Zero then the form is deactivating and we don't need to do anything
                //Otherwise we need to make sure that the background form is positioned just behind
                //the main form.
                if (m.WParam != IntPtr.Zero)
                {
                    //Check for any visible windows between the background and main windows
                    IntPtr prevWnd = Win32.GetWindow(m_layeredWnd.Handle, Win32.GetWindow_Cmd.GW_HWNDPREV);
                    while (prevWnd != IntPtr.Zero)
                    {
                        //If we find a visiable window, we stop
                        if (Win32.IsWindowVisible(prevWnd))
                        {
                            break;
                        }

                        prevWnd = Win32.GetWindow(prevWnd, Win32.GetWindow_Cmd.GW_HWNDPREV);
                    }

                    //If the visible window isn't ours reset the position of the background form
                    if (prevWnd != this.Handle)
                    {
                        Win32.SetWindowPos(m_layeredWnd.Handle, this.Handle, 0, 0, 0, 0, (uint)(Win32.WindowPosFlags.SWP_NOSENDCHANGING | Win32.WindowPosFlags.SWP_NOACTIVATE | Win32.WindowPosFlags.SWP_NOSIZE | Win32.WindowPosFlags.SWP_NOMOVE));
                    }
                }
            }
            break;
            }

            if (UseBase)
            {
                base.WndProc(ref m);
            }
        }
Пример #2
0
    protected override void WndProc(ref Message m)
    {
        if (this.DesignMode)
        {
            base.WndProc(ref m);
            return;
        }
        Win32.Message msgId   = (Win32.Message)m.Msg;
        bool          UseBase = true;

        switch (msgId)
        {
        case Win32.Message.WM_LBUTTONUP:
        {
            if (Win32.GetCapture() != IntPtr.Zero)
            {
                Win32.ReleaseCapture();
            }
        }
        break;

        case Win32.Message.WM_ENTERSIZEMOVE:
        {
        }
        break;

        case Win32.Message.WM_EXITSIZEMOVE:
        {
            m_isDown.Left = false;
            m_moving      = false;

            if (m_enhanced)
            {
                this.SuspendLayout();
                foreach (Control ctrl in m_hiddenControls)
                {
                    ctrl.Visible = true;
                }
                m_hiddenControls.Clear();
                this.ResumeLayout();
                updateLayeredBackground(this.ClientSize.Width, this.ClientSize.Height, m_layeredWnd.LayeredPos, false);
            }
        }
        break;

        case Win32.Message.WM_MOUSEMOVE:
            if (Win32.GetCapture() != IntPtr.Zero && m_moving)
            {
                if (m_enhanced)
                {
                    IntPtr hdcScreen = Win32.GetWindowDC(m_layeredWnd.Handle);
                    IntPtr windowDC  = Win32.GetDC(this.Handle);
                    IntPtr memDC     = Win32.CreateCompatibleDC(windowDC);
                    IntPtr BmpMask   = Win32.CreateBitmap(this.ClientSize.Width,
                                                          this.ClientSize.Height, 1, 1, IntPtr.Zero);

                    Bitmap backImage = m_useBackgroundEx ? m_backgroundFull : m_background;
                    IntPtr BmpBack   = backImage.GetHbitmap(Color.FromArgb(0));

                    Win32.SelectObject(memDC, BmpMask);
                    uint oldCol = Win32.SetBkColor(windowDC, 0x00FF00FF);
                    Win32.BitBlt(memDC, 0, 0, this.ClientSize.Width, this.ClientSize.Height, windowDC, 0, 0, Win32.TernaryRasterOperations.SRCCOPY);
                    Win32.SetBkColor(windowDC, oldCol);

                    Win32.SelectObject(memDC, BmpBack);
                    IntPtr brush = Win32.CreateSolidBrush(0x00FFFFFF);
                    Win32.SelectObject(memDC, brush);
                    Win32.MaskBlt(memDC, 0, 0, backImage.Width, backImage.Height, windowDC, 0, 0, BmpMask, 0, 0, 0xCFAA0020);

                    Point zero = new Point(0, 0);
                    Size  size = m_layeredWnd.LayeredSize;
                    Point pos  = m_layeredWnd.LayeredPos;
                    Win32.BLENDFUNCTION blend = new Win32.BLENDFUNCTION();
                    blend.AlphaFormat         = (byte)Win32.BlendOps.AC_SRC_ALPHA;
                    blend.BlendFlags          = (byte)Win32.BlendFlags.None;
                    blend.BlendOp             = (byte)Win32.BlendOps.AC_SRC_OVER;
                    blend.SourceConstantAlpha = (byte)(this.Opacity * 255);

                    Win32.UpdateLayeredWindow(m_layeredWnd.Handle, hdcScreen, ref pos, ref size, memDC, ref zero, 0, ref blend, Win32.BlendFlags.ULW_ALPHA);
                    Win32.ReleaseDC(IntPtr.Zero, hdcScreen);
                    Win32.ReleaseDC(this.Handle, windowDC);
                    Win32.DeleteDC(memDC);
                    Win32.DeleteObject(brush);
                    Win32.DeleteObject(BmpMask);
                    Win32.DeleteObject(BmpBack);

                    this.SuspendLayout();
                    foreach (Control ctrl in this.Controls)
                    {
                        if (ctrl.Visible)
                        {
                            m_hiddenControls.Add(ctrl);
                            ctrl.Visible = false;
                        }
                    }
                    this.ResumeLayout();
                }

                Win32.ReleaseCapture();
                Win32.SendMessage(this.Handle, (int)Win32.Message.WM_NCLBUTTONDOWN, (int)Win32.Message.HTCAPTION, 0);
            }
            break;

        case Win32.Message.WM_SIZE:
        {
            int width  = m.LParam.ToInt32() & 0xFFFF;
            int height = m.LParam.ToInt32() >> 16;
            this.updateLayeredSize(width, height);
        }
        break;

        case Win32.Message.WM_WINDOWPOSCHANGING:
        {
            Win32.WINDOWPOS      posInfo   = (Win32.WINDOWPOS)Marshal.PtrToStructure(m.LParam, typeof(Win32.WINDOWPOS));
            Win32.WindowPosFlags move_size = Win32.WindowPosFlags.SWP_NOMOVE | Win32.WindowPosFlags.SWP_NOSIZE;
            if ((posInfo.flags & move_size) != move_size)
            {
                if (posInfo.hwndInsertAfter != this.Handle)
                {
                    IntPtr hwdp = Win32.BeginDeferWindowPos(2);
                    if (hwdp != IntPtr.Zero)
                    {
                        hwdp = Win32.DeferWindowPos(hwdp, m_layeredWnd.Handle, this.Handle, posInfo.x + m_offX, posInfo.y + m_offY,
                                                    0, 0, (uint)(posInfo.flags | Win32.WindowPosFlags.SWP_NOSIZE | Win32.WindowPosFlags.SWP_NOZORDER));
                    }
                    if (hwdp != IntPtr.Zero)
                    {
                        hwdp = Win32.DeferWindowPos(hwdp, this.Handle, this.Handle, posInfo.x, posInfo.y, posInfo.cx, posInfo.cy,
                                                    (uint)(posInfo.flags | Win32.WindowPosFlags.SWP_NOZORDER));
                    }
                    if (hwdp != IntPtr.Zero)
                    {
                        Win32.EndDeferWindowPos(hwdp);
                    }

                    m_layeredWnd.LayeredPos = new Point(posInfo.x + m_offX, posInfo.y + m_offY);
                    posInfo.flags          |= Win32.WindowPosFlags.SWP_NOMOVE;
                    Marshal.StructureToPtr(posInfo, m.LParam, true);
                }

                if ((posInfo.flags & Win32.WindowPosFlags.SWP_NOSIZE) == 0)
                {
                    int diffX = posInfo.cx - this.Size.Width;
                    int diffY = posInfo.cy - this.Size.Height;
                    if (diffX != 0 || diffY != 0)
                    {
                        this.updateLayeredSize(this.ClientSize.Width + diffX, this.ClientSize.Height + diffY);
                    }
                }
                UseBase = false;
            }
        }
        break;


        case Win32.Message.WM_ACTIVATE:
        {
            if (m.WParam != IntPtr.Zero)
            {
                IntPtr prevWnd = Win32.GetWindow(m_layeredWnd.Handle, Win32.GetWindow_Cmd.GW_HWNDPREV);
                while (prevWnd != IntPtr.Zero)
                {
                    if (Win32.IsWindowVisible(prevWnd))
                    {
                        break;
                    }

                    prevWnd = Win32.GetWindow(prevWnd, Win32.GetWindow_Cmd.GW_HWNDPREV);
                }

                if (prevWnd != this.Handle)
                {
                    Win32.SetWindowPos(m_layeredWnd.Handle, this.Handle, 0, 0, 0, 0, (uint)(Win32.WindowPosFlags.SWP_NOSENDCHANGING | Win32.WindowPosFlags.SWP_NOACTIVATE | Win32.WindowPosFlags.SWP_NOSIZE | Win32.WindowPosFlags.SWP_NOMOVE));
                }
            }
        }
        break;
        }

        if (UseBase)
        {
            base.WndProc(ref m);
        }
    }