Как я могу воспроизвести эффект перетаскивания изображения / текста Firefox в .NET? - PullRequest
1 голос
/ 17 ноября 2009

Хорошо, я знаю, что это, вероятно, довольно новый вопрос, но когда дело доходит до графического программирования, я am новичок:)

Как Firefox достигает эффекта перетаскивания при отображении красивой блеклой копии выбранного изображения или текста? См. Ниже пример с логотипом SO.

Кроме того, как я могу воспроизвести этот эффект в C # / VB.NET? (желательно WinForms, поскольку я еще не знаю WPF.)

Я также заметил, что происхождение «затухания» основано на положении курсора на изображении (попробуйте, попробуйте сейчас, вы поймете, что я имею в виду!)

Полагаю, я мог бы углубиться в источник в MDC , но я подумал, что кто-то здесь уже может быть знаком с этой техникой.

Firefox drag & drop

1 Ответ

1 голос
/ 17 ноября 2009

Я бы создал новое Многослойное окно в позиции мыши, которая следует за мышью вокруг. В новом окне его содержимое будет получено из нужного содержимого (изображения или текста), которое будет отображаться с использованием альфа-канала, который уменьшается по мере удаления от мыши.

Визуализация текста или изображения в растровое изображение GDI + с альфа-каналом, циклическое переключение между пикселями и установка альфа-канала в зависимости от положения курсора мыши. Установите растровое изображение в многослойном окне и обновите его положение в зависимости от того, где находится мышь.

Создание многослойного окна в 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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...