【问题标题】:How can I reproduce the Firefox faded image/text dragging effect in .NET?如何在 .NET 中重现 Firefox 褪色的图像/文本拖动效果?
【发布时间】:2009-11-17 20:11:52
【问题描述】:

好的,我知道这可能是一个相当新人的问题,但是在图形编程方面,我一个新人:)

Firefox 如何在显示所选图像或文本的漂亮褪色副本的同时实现拖放效果?请参阅下面的带有 SO 徽标的示例。

另外,如何在 C#/VB.NET 中重现这种效果? (最好是 WinForms,因为我还不太了解 WPF。)

我还注意到“淡入淡出”的来源是基于图像中的光标位置(继续,现在试试,你会明白我的意思!)

我想我可以深入研究源代码over at MDC,但我想这里的人可能已经熟悉这种技术了。

【问题讨论】:

    标签: .net firefox drag-and-drop


    【解决方案1】:

    我会在鼠标周围的鼠标位置创建一个新的Layered Window。新窗口将从所需的内容(图像或文本)中获取其内容,这些内容将使用 Alpha 通道进行渲染,该通道会随着它远离鼠标而减小。

    将文本或图像渲染为带有 Alpha 通道的 GDI+ 位图,循环遍历像素并将 Alpha 通道设置为鼠标光标位置的函数。在分层窗口上设置位图,并根据鼠标的位置更新它的位置。

    在 C# 中创建分层窗口(取自其他来源):

        public class SplashScreenForm : Form
    {
    
        public SplashScreenForm()
        {
    
            this.TopMost = true;
            this.Show();
            SelectBitmap(Properties.Resources.splashblended);
        }
    
        // Sets the current bitmap
        public void SelectBitmap(Bitmap bitmap) 
        {
            // Does this bitmap contain an alpha channel?
            if (bitmap.PixelFormat != PixelFormat.Format32bppArgb)
            {
                throw new ApplicationException("The bitmap must be 32bpp with alpha-channel.");
            }
    
            // Get device contexts
            IntPtr screenDc = APIHelp.GetDC(IntPtr.Zero);
            IntPtr memDc = APIHelp.CreateCompatibleDC(screenDc);
            IntPtr hBitmap = IntPtr.Zero;
            IntPtr hOldBitmap = IntPtr.Zero;
    
            try 
            {
                // Get handle to the new bitmap and select it into the current device context
                hBitmap = bitmap.GetHbitmap(Color.FromArgb(0));
                hOldBitmap = APIHelp.SelectObject(memDc, hBitmap);
    
                // Set parameters for layered window update
                APIHelp.Size newSize = new APIHelp.Size(bitmap.Width, bitmap.Height);   // Size window to match bitmap
                APIHelp.Point sourceLocation = new APIHelp.Point(0, 0);
                APIHelp.Point newLocation = new APIHelp.Point(this.Left, this.Top);     // Same as this window
                APIHelp.BLENDFUNCTION blend = new APIHelp.BLENDFUNCTION();
                blend.BlendOp             = APIHelp.AC_SRC_OVER;                        // Only works with a 32bpp bitmap
                blend.BlendFlags          = 0;                                          // Always 0
                blend.SourceConstantAlpha = 255;                                        // Set to 255 for per-pixel alpha values
                blend.AlphaFormat         = APIHelp.AC_SRC_ALPHA;                       // Only works when the bitmap contains an alpha channel
    
                // Update the window
                APIHelp.UpdateLayeredWindow(Handle, screenDc, ref newLocation, ref newSize,
                    memDc, ref sourceLocation, 0, ref blend, APIHelp.ULW_ALPHA);
            }
            finally 
            {
                // Release device context
                APIHelp.ReleaseDC(IntPtr.Zero, screenDc);
                if (hBitmap != IntPtr.Zero) 
                {
                    APIHelp.SelectObject(memDc, hOldBitmap);
                    APIHelp.DeleteObject(hBitmap);                                      // Remove bitmap resources
                }
                APIHelp.DeleteDC(memDc);
            }
        }
    
        protected override CreateParams CreateParams    
        {
            get 
            {
                // Add the layered extended style (WS_EX_LAYERED) to this window
                CreateParams createParams = base.CreateParams;
                createParams.ExStyle |= APIHelp.WS_EX_LAYERED;
                return createParams;
            }
        }
    }
    
    // Class to assist with Win32 API calls
    internal class APIHelp 
    {
        // Required constants
        public const Int32  WS_EX_LAYERED   = 0x80000;
        public const Int32  HTCAPTION       = 0x02;
        public const Int32  WM_NCHITTEST    = 0x84;
        public const Int32  ULW_ALPHA       = 0x02;
        public const byte   AC_SRC_OVER     = 0x00;
        public const byte   AC_SRC_ALPHA    = 0x01;
    
        public enum Bool 
        {
            False = 0,
            True = 1
        }
    
        [StructLayout(LayoutKind.Sequential)]
        public struct Point 
        {
            public Int32 x;
            public Int32 y;
    
            public Point(Int32 x, Int32 y) { this.x = x; this.y = y; }
        }
    
        [StructLayout(LayoutKind.Sequential)]
        public struct Size 
        {
            public Int32 cx;
            public Int32 cy;
    
            public Size(Int32 cx, Int32 cy) { this.cx = cx; this.cy = cy; }
        }
    
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        struct ARGB 
        {
            public byte Blue;
            public byte Green;
            public byte Red;
            public byte Alpha;
        }
    
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        public struct BLENDFUNCTION 
        {
            public byte BlendOp;
            public byte BlendFlags;
            public byte SourceConstantAlpha;
            public byte AlphaFormat;
        }
    
        [DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
        public static extern Bool UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst, ref Point pptDst, ref Size psize, IntPtr hdcSrc, ref Point pprSrc, Int32 crKey, ref BLENDFUNCTION pblend, Int32 dwFlags);
    
        [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
        public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
    
        [DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
        public static extern IntPtr GetDC(IntPtr hWnd);
    
        [DllImport("user32.dll", ExactSpelling = true)]
        public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
    
        [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
        public static extern Bool DeleteDC(IntPtr hdc);
    
        [DllImport("gdi32.dll", ExactSpelling = true)]
        public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
    
        [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
        public static extern Bool DeleteObject(IntPtr hObject);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-14
      • 1970-01-01
      • 2013-04-12
      • 2016-07-17
      • 1970-01-01
      • 2017-07-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多