Регистрация Главная Сообщество
Сообщения за день Справка Регистрация
Навигация
Zhyk.org LIVE! Реклама на Zhyk.org Правила Форума Награды и достижения Доска "почета"

Ответ
 
Опции темы
Старый 01.09.2010, 21:28   #1
-= Элитный Мастер =-
 Главнокомандующий
Аватар для Kitsune
 
Kitsune сломал счётчик популярности :(Kitsune сломал счётчик популярности :(Kitsune сломал счётчик популярности :(Kitsune сломал счётчик популярности :(Kitsune сломал счётчик популярности :(Kitsune сломал счётчик популярности :(Kitsune сломал счётчик популярности :(Kitsune сломал счётчик популярности :(Kitsune сломал счётчик популярности :(Kitsune сломал счётчик популярности :(Kitsune сломал счётчик популярности :(
Регистрация: 20.01.2010
Сообщений: 1,539
Популярность: 22780
Золото Zhyk.Ru: 600
Сказал(а) спасибо: 43
Поблагодарили 1,717 раз(а) в 538 сообщениях
 
По умолчанию Создаем Splash Screen к своей программе. C# version

> Создаем Splash Screen к своей программе <

В данной статье речь пойдет о том как добавить красочное "приветствие" нашему приложению.

Splash Screen с полной поддержкой Alpha канала

Конечный материал данной статьи (скрин):
  • [Ссылки могут видеть только зарегистрированные пользователи. ]

Теория:
  • Splash Screen - это окно, которое появляется до появления основного окна приложения. Цели он может нести разные: красоту, функциональную нагрузку, рекламу и т.д.
  • Принцип работы элементарен. Нам необходимо до вызова главной формы вызывать Splash Screen, производить какие нам нужны манипуляции и передавать управление главному окну.

Практика:
  1. Для начала создадим новый WinForms проект
  2. Затем создадим новый файл класс, я назвал его ExtendedForm.cs
    Данный класс будет у нас материнским для нашего Splash Screen'а и мы добавим весь необходимый функционал в него для красочности конечного продукта, а именно полную поддержку альфа канала.
  3. Поддержку альфа канала мы можем добавить в данном случаи через WinApi, для этого нам понадобится вызывать некоторые функции и передавать в них определенные структуры.
  4. Ниже приведен код, готового к работе класса ExtendedForm.cs
    Код:
    using System;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    
    namespace VisualTweak2
    {
        #region :: Win32 ::
        public class Win32
        {
            public enum Bool
            {
                False = 0,
                True
            }
    
            [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;
            }
    
            public const Int32 ULW_COLORKEY = 0x00000001;
            public const Int32 ULW_ALPHA = 0x00000002;
            public const Int32 ULW_OPAQUE = 0x00000004;
    
            public const byte AC_SRC_OVER = 0x00;
            public const byte AC_SRC_ALPHA = 0x01;
            
            [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("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 IntPtr CreateCompatibleDC(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);
        }
        #endregion
    
        public class ExtendedForm : Form
        {
            public ExtendedForm()
            {
                this.StartPosition = FormStartPosition.CenterScreen;
            }
    
            public void SetBitmap(Bitmap bitmap)
            {
                SetBitmap(bitmap, 255);
            }
    
            public void SetBitmap(Bitmap bitmap, byte opacity)
            {
                if (bitmap.PixelFormat != PixelFormat.Format32bppArgb)
                    throw new ApplicationException("The bitmap must be 32ppp with alpha-channel.");
    
                // Идея этого очень проста,
                // 1. Создаем совместимый контекст графического устройсва с экраном;
                // 2. Выбираем наш битмап с альфаканалом в контексте;
                // 3. Вызываем метод UpdateLayeredWindow.
    
                IntPtr screenDc = Win32.GetDC(IntPtr.Zero);
                IntPtr memDc = Win32.CreateCompatibleDC(screenDc);
                IntPtr hBitmap = IntPtr.Zero;
                IntPtr oldBitmap = IntPtr.Zero;
    
                try
                {
                    // Получаем GDI хендл из GDI+ bitmap
                    hBitmap = bitmap.GetHbitmap(Color.FromArgb(0)); 
                    oldBitmap = Win32.SelectObject(memDc, hBitmap);
    
                    // Инициализируем необходимые Win32 структуры
                    Win32.Size size = new Win32.Size(bitmap.Width, bitmap.Height);
                    Win32.Point pointSource = new Win32.Point(0, 0);
                    Win32.Point topPos = new Win32.Point(Left, Top);
                    Win32.BLENDFUNCTION blend = new Win32.BLENDFUNCTION();
                    blend.BlendOp = Win32.AC_SRC_OVER;
                    blend.BlendFlags = 0;
                    blend.SourceConstantAlpha = opacity;
                    blend.AlphaFormat = Win32.AC_SRC_ALPHA;
                    // Вызываем метод, который собственно и нарисует все как надо :)
                    Win32.UpdateLayeredWindow(Handle, screenDc, ref topPos, ref size, memDc, ref pointSource, 0, ref blend, Win32.ULW_ALPHA);
                }
                finally
                {
                    // По окончанию работы метода, освобождаем контекст
                    Win32.ReleaseDC(IntPtr.Zero, screenDc);
                    if (hBitmap != IntPtr.Zero)
                    {
                        // И удаляем объекты из памяти
                        Win32.SelectObject(memDc, oldBitmap);
                        Win32.DeleteObject(hBitmap);
                    }
                    Win32.DeleteDC(memDc);
                }
            }
    
    
            protected override CreateParams CreateParams
            {
                get
                {
                    if (!DesignMode)
                    {
                        CreateParams cp = base.CreateParams;
                        cp.ExStyle |= 0x00080000; // WS_EX_LAYERED
                        return cp;
                    }
                    else
                        return base.CreateParams;
                }
            }
        }
    }
  5. Теперь давайте разберемся, что же за код представлен выше. Он хоть весь и закомментирован(нужные куски), но все же...

    В блоке Win32 у нас описаны все нужным нам Win32 структуры и функции, которые мы импортируем из User32.dll b gdi32.dll.

    Сам класс ExtendedForm наследуется от класса Form, что означает то, что он полностью перенимает все его методы и свойства, вдобаков он обзавелся дополнительным нашими методам SetBitmap, который имеет перегрузку.

    SetBitmap - это "ядро" нашего класса, в этом методе происходит правильная отрисовка нашего изображения, с поддержкой альфаканала.

    Так же мы переопределяем свойство: CreateParams и возвращаем стиль формы + WS_EX_LAYERED. Это необходимо для правильной работы.
  6. После создания класса, мы займемся созданием будущего Splash Screen'a.
    Создадим новую форму и назовем её Startup.cs например, затем изменим её свойство:

    • FormBorderStyle = None

    [Ссылки могут видеть только зарегистрированные пользователи. ]

  7. Затем загрузите в ресурсы изображение, которое и будет нашим Splash Screen'ом. Учтите, что изображение должно быть 32 битным. Лучше всего подходит для этих целей png32 формат.
  8. После чего откроем код формы и начнем описывать поведение Splash Screen'a.
  9. Изменим наследование с Form на ExtendedForm
    Код:
    public partial class Startup : ExtendedForm
  10. Создадим служебные поля:
    Код:
    // Поле: таймер для реализации плавного появления и скрытия
    private Timer updateTimer;
    // Поле: служебная переменная хранящая значение текущей прозрачности
    private int opacityCounter = 0;
    // Поля: скорость проявления и скорость скрытия (1-255)
    private int fadeInSpeed = 10;
    private int fadeOutSpeed = 40;
    // Поле: флаг, отражающий, что сейачс происходит, проявление или скрытие
    private bool fadeout = false;
  11. В конструктор формы добавим:
    Код:
    Bitmap bmp = global::VisualTweak2.Properties.Resources.application2;
    // Устанавливаем наше изображение для отображение. Уровень прозрачности 0
    // Тоесть рисуется так, как есть
    SetBitmap(bmp, 0);
    
    // Устанавливаем наше изображение четко по центру экрана
    this.Location = new Point(
        Screen.PrimaryScreen.Bounds.Width / 2 - bmp.Width / 2,
        Screen.PrimaryScreen.Bounds.Height / 2 - bmp.Height / 2);
    
    // Инициализируем таймер
    updateTimer = new Timer()
    {
        Interval = 50, // Каждые 50 мс будет происходить тик
        Enabled = true // Включаем таймер
    };
    // Подписываемся на событие тик таймера
    updateTimer.Tick +=new EventHandler(updateTimer_Tick);
  12. Добавим наконец обработчик тика таймера и метод, которые будет вызыватся в обработчике каждый тик таймера.
    Код:
    private void FadeInOut()
    {
        // Если сплеш проявляется
        if (!fadeout)
        {
            // Увеличиваем уровень видимости
            opacityCounter += fadeInSpeed;
            // Осуществляем проверку, если уровень прозрачности у нас превысил 255, 
            // Возвращаем его к значеню 255 (ибо это максимум) и устанавливаем флаг,
            // что теперь у нас происходит скрытие
            if (opacityCounter > 255) { opacityCounter = 255; fadeout = true; }
        }
        // Если скрытие
        else
        {
            // Уменьшаем значение прозрачности
            opacityCounter -= fadeOutSpeed;
            // Если значение у нас получилось меньше 0,
            // то возвращаем его в 0 (ибо это минимум)
            // Затем выключаем таймер и закрываем нашу сплеш скрин
            if (opacityCounter < 0)
            {
                opacityCounter = 0; updateTimer.Enabled = false; this.Close();
            }
        }
        // Проверяем жив ли наш объект, и если он жив, то применяем настройки прозрачности
        if (!this.IsDisposed)
            SetBitmap(global::VisualTweak2.Properties.Resources.application2, (byte)opacityCounter);
    }
    
    // Обработчик события тик таймера
    private void updateTimer_Tick(object sender, EventArgs e)
    {
        FadeInOut();
    }
  13. Теперь финальный шаг... Нам надо вызывать наш Splash Screen до вызова главной формы. Для того, чтобы это сделать откроем файл Program.cs.
    Найдем там строку:
    Код:
    Application.Run(new Main()); // Main - это название моего главного класса приложения(формы в данном случаи), у вас может быть оно другим.
    Перед этой строкой добавим эту строку:
    Код:
    Application.Run(new Startup());
  14. В конечном счете у вас должно получится примерно следующее:
    Код:
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            // Запускаем сначала сплеш окно
            Application.Run(new Startup());
            // Затем, после того как оно будет закрыто, запустим
            // уже наше приложение
            Application.Run(new Main());
        }
    }

Заключение:
  • Готовый проект на Visual Studio 2010 вы можете скачать из вложения.
  • Видео пример можете посмотреть в атаче.
Вложения
Тип файла: rar VisualTweak2.rar (321.5 Кб, 143 просмотров)
Тип файла: rar splashtest.rar (991.2 Кб, 153 просмотров)
________________
Fireball - Быстрое снятие и загрузка скриншотов на хостинг.
  Ответить с цитированием
Пользователь сказал cпасибо:
the-boxi (06.03.2012)
Старый 05.02.2012, 20:55   #2
 Старший сержант
Аватар для Sinyss
 
Sinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака НоррисаSinyss троюродный дядя Чака Норриса
Регистрация: 29.07.2011
Сообщений: 197
Популярность: 8989
Сказал(а) спасибо: 45
Поблагодарили 175 раз(а) в 139 сообщениях
Отправить сообщение для Sinyss с помощью Skype™
 
По умолчанию Re: Создаем Splash Screen к своей программе. C# version

а зачем нам апишка винды? готов поспорить что хватит и встроенных функций таймера и формы...
  Ответить с цитированием
Старый 05.02.2012, 21:49   #3
 Пехотинец
Аватар для Puzer
 
Puzer определенно авторитетная личностьPuzer определенно авторитетная личностьPuzer определенно авторитетная личностьPuzer определенно авторитетная личностьPuzer определенно авторитетная личностьPuzer определенно авторитетная личностьPuzer определенно авторитетная личностьPuzer определенно авторитетная личностьPuzer определенно авторитетная личность
Регистрация: 02.09.2009
Сообщений: 55
Популярность: 1249
Сказал(а) спасибо: 7
Поблагодарили 191 раз(а) в 37 сообщениях
 
По умолчанию Re: Создаем Splash Screen к своей программе. C# version

Цитата:
Сообщение от TBX1nПосмотреть сообщение
Splash Screen с полной поддержкой Alpha канала

В стандартном winforms можно установить :
[Ссылки могут видеть только зарегистрированные пользователи. ] (допустим сделаем его красным #FF0000 - и теперь всё, что на форме красным цветом (включая и на картинках) будет прозрачным)
И [Ссылки могут видеть только зарегистрированные пользователи. ] (от 0 до 100%)
А в твоём случае можно установиться альфа канал для любого цвета в любом значении, я так понял ?
________________
  Ответить с цитированием
Старый 27.04.2012, 14:50   #4
 Разведчик
Аватар для ka11n
 
ka11n никому не известный тип
Регистрация: 27.04.2012
Сообщений: 2
Популярность: 10
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
 
По умолчанию Re: Создаем Splash Screen к своей программе. C# version

Цитата:
Сообщение от TBX1nПосмотреть сообщение
Изменим наследование с Form на ExtendedForm

как сделать чтобы класс ExtendedForm был "виден"

Ошибка. Не удалось найти имя типа или пространства имен "ExtendedForm" (пропущена директива using или ссылка на сборку?) D:\Projects\MKTSMonitor C#\Startup.cs 12 36 MKTSMonitor
  Ответить с цитированием
Старый 27.04.2012, 18:41   #5
Читер-спонсор
 Рыцарь-защитник
Аватар для Nickitee
 
Nickitee сломал счётчик популярности :(Nickitee сломал счётчик популярности :(Nickitee сломал счётчик популярности :(Nickitee сломал счётчик популярности :(Nickitee сломал счётчик популярности :(Nickitee сломал счётчик популярности :(Nickitee сломал счётчик популярности :(Nickitee сломал счётчик популярности :(Nickitee сломал счётчик популярности :(Nickitee сломал счётчик популярности :(Nickitee сломал счётчик популярности :(
Регистрация: 28.08.2009
Сообщений: 603
Популярность: 19129
Золото Zhyk.Ru: 500
Сказал(а) спасибо: 84
Поблагодарили 602 раз(а) в 321 сообщениях
 
По умолчанию Re: Создаем Splash Screen к своей программе. C# version

Цитата:
Сообщение от ka11nПосмотреть сообщение
как сделать чтобы класс ExtendedForm был "виден"

Ошибка. Не удалось найти имя типа или пространства имен "ExtendedForm" (пропущена директива using или ссылка на сборку?) D:\Projects\MKTSMonitor C#\Startup.cs 12 36 MKTSMonitor

Я не уверен, но вроде нейм спейс VisualTweak2
и тогда:
Код:
using VisualTweak2;
________________
We are Ducks. We are birds. We like bread. We cryack. Cryack.
  Ответить с цитированием
Старый 28.04.2012, 09:08   #6
 Разведчик
Аватар для ka11n
 
ka11n никому не известный тип
Регистрация: 27.04.2012
Сообщений: 2
Популярность: 10
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
 
По умолчанию Re: Создаем Splash Screen к своей программе. C# version

Цитата:
SetBitmap (bmp, 0);

Выдает ошибку...

Ошибка 1 Метод должен иметь тип возвращаемого значения D:\Projects\MKTSMonitor C#\Startup.cs 28 9 MKTSMonitor
  Ответить с цитированием
Ответ


Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
[Руководство] Создаем свой внешний вид окна (WinForms). C# version Kitsune C# 11 08.05.2016 03:19
[Скрипт] Expanded screen (JS) + WJ Script (AutoHotkey) FelikZ Transformice 17 07.11.2011 23:17
как добавить dll к программе? beautifulboy42 Архив 1 13.05.2010 19:41
[Файл] Lock Screen v.0.10.59 для Nokia 5800 Flapse Программы и приложения для смартфонов 0 14.03.2010 21:44

Заявление об ответственности / Список мошенников

Часовой пояс GMT +4, время: 10:00.

Пишите нам: [email protected]
Copyright © 2024 vBulletin Solutions, Inc.
Translate: zCarot. Webdesign by DevArt (Fox)
G-gaMe! Team production | Since 2008
Hosted by GShost.net