2009-11-17 165 views
1

好吧,我知道这可能是一个非常福利局问题,但是当涉及到图形编程,我上午对于新手:)如何在.NET中重现Firefox褪色的图像/文本拖动效果?

如何火狐实现拖放在显示漂亮的褪色副本掉落效果所选图像或文字的?请参阅下面的SO徽标示例。

另外,我怎么能在C#/ VB.NET中重现这种效果? (最好是WinForms,因为我现在还不知道WPF)

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

我想我可以钻研源over at MDC,但我认为这里的某个人可能已经熟悉这种技术。

Firefox drag & 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); 
} 
+0

谢谢,很好的例子!这应该让我开始。 – 2009-11-17 21:00:52