Дизайн прозрачной формы C# (Windows Forms)

442
08 июля 2017, 07:15

Есть некоторые проблемы с дизайном прозрачной формы:

  1. Я не могу перемещать форму за саму форму, т.к. она прозрачная
  2. Я могу перемещать форму за буквы, но не за сам лейбл, что не очень удобно
  3. Если текст светлый, он искажается на светлом фоне
  4. Если текст тёмный, он искажается на тёмном фоне

Если мне тут помогут, я проект с исправленным дизайном, может кому-то это понадобится.

public partial class BlurForm : Form
{
    public BlurForm()
    {
        this.EnableBlur();
        SetStyle(ControlStyles.UserPaint, true);
        SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
        SetStyle(ControlStyles.SupportsTransparentBackColor, true);
        BackColor = Color.FromArgb(103, 65, 114);
        TransparencyKey = Color.FromArgb(103, 65, 114);
        InitializeComponent();
        FormBorderStyle = FormBorderStyle.None;
    }
}
public static class WindowExtension
{
    [DllImport("user32.dll")]
    static internal extern int SetWindowCompositionAttribute(IntPtr hwnd, ref WindowCompositionAttributeData data);
    public static void EnableBlur(this Form @this)
    {
        var accent = new AccentPolicy();
        accent.AccentState = AccentState.ACCENT_ENABLE_BLURBEHIND;
        var accentStructSize = Marshal.SizeOf(accent);
        var accentPtr = Marshal.AllocHGlobal(accentStructSize);
        Marshal.StructureToPtr(accent, accentPtr, false);
        var Data = new WindowCompositionAttributeData();
        Data.Attribute = WindowCompositionAttribute.WCA_ACCENT_POLICY;
        Data.SizeOfData = accentStructSize;
        Data.Data = accentPtr;
        SetWindowCompositionAttribute(@this.Handle, ref Data);
        Marshal.FreeHGlobal(accentPtr);
    }
}
enum AccentState
{
    ACCENT_DISABLED = 0,
    ACCENT_ENABLE_GRADIENT = 1,
    ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
    ACCENT_ENABLE_BLURBEHIND = 3,
    ACCENT_INVALID_STATE = 4
}
struct AccentPolicy
{
    public AccentState AccentState;
    public int AccentFlags;
    public int GradientColor;
    public int AnimationId;
}
struct WindowCompositionAttributeData
{
    public WindowCompositionAttribute Attribute;
    public IntPtr Data;
    public int SizeOfData;
}
enum WindowCompositionAttribute
{
    WCA_ACCENT_POLICY = 19
}
Answer 1

Есть некоторые проблемы с дизайном прозрачной формы: 1. Я не могу перемещать форму за саму форму, т.к. она прозрачная 2. Я могу перемещать форму за буквы, но не за сам лейбл, что не очень удобно

Это связано с тем, что по-умолчанию форму можно перемещать только за шапку, но у вас она отключена (FormBorderStyle = FormBorderStyle.None;). Поэтому нужно добавить обработчик вручную. Например так:

public BlurForm()
{
    this.EnableBlur();
    SetStyle(ControlStyles.UserPaint, true);
    SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
    SetStyle(ControlStyles.SupportsTransparentBackColor, true);
    BackColor = Color.FromArgb(103, 65, 114);
    TransparencyKey = Color.FromArgb(103, 65, 114);
    InitializeComponent();
    FormBorderStyle = FormBorderStyle.None;
    //это не обязательно писать явно, можно сделать мышкой в дизайнере
    MouseDown += BlurForm_MouseDown;
    MouseMove += BlurForm_MouseMove;
}
private Point _startPosition;
private void BlurForm_MouseDown(object sender, MouseEventArgs e)
{
    _startPosition = e.Location;
}
private void BlurForm_MouseMove(object sender, MouseEventArgs e)
{
    if(e.Button == MouseButtons.Left)
        Location = new Point(Location.X + e.X - _startPosition.X, Location.Y + e.Y - _startPosition.Y);
}

Также, полезно подписаться на аналогичные события для Label и других контролов, и обрабтать их соответствующим образом. Только нужно помнить, что в аргументах события мыши передаются координаты относительно контрола в котором событие произошло, поэтому требуется пересчитать их в соответствующие координаты. Но в предложенном варианте это не требуется, т.к. все задается в относительных величинах.

  1. Если текст светлый, он искажается на светлом фоне
  2. Если текст тёмный, он искажается на тёмном фоне

Тут причина довольно простая. Собственно сглаживание шрифта и вносит искажения которые вы видите. Чтобы искажения стали невидимыми, нужно сделать цвет текста и фона почти одинаковым, допустим если цвет фона формы (103, 65, 114) то цвет текста, например (103, 65, 115). Это позволит отработать фильтру прозрачности по заданному цвету и при сглаживании не будет резкого перепада цвета, из-за которого и появляется неприятная рваная граница.

Важно. Цвет фона прозрачной формы остается тем же, каким его задали, несмотря на прозрачность. Это легко проверить: отключаем в настройках Windows оформление Aero, Alt+PrtScrn и вставляем буфер в Paint. Сглаживание шрифта происходит цветами в промежутке между цветом шрифта и цветом фона формы, а то что просвечивает сквозь форму значения не имеет.

READ ALSO
Как в Unity3d использовать возможности C# 5/6/7?

Как в Unity3d использовать возможности C# 5/6/7?

Захотел я идти в ногу со временем, посмотрел новые фишки и плюшки C#6/7, воодушевилсяТам так всё вкусно и круто, что грех не пользоваться

478
Обработка исключения Format Exception

Обработка исключения Format Exception

Как корректно обработать исключение Format Exception на проверку введенных значений в TextBox?

304
Json запрос с массивом

Json запрос с массивом

Здравствуйте!

388
OWIN twitter ошибка 401 Asp.net mvc

OWIN twitter ошибка 401 Asp.net mvc

Сайт пишу на aspnet mvc 5, при аутентификации через соц

275