Форма с прозрачным элементом

В C# в Windows 11 у меня есть форма со сплошным фоном и прозрачным PictureBox. Форма загружается, и PictureBox на самом деле прозрачен, но когда я навожу указатель мыши на прозрачную область, обработка мыши передается объектам за формой.

Поскольку я хочу, чтобы форма обрабатывала события наведения курсора мыши на прозрачные области, я добавил переопределение для WndProc, которое перехватывает сообщение NCHITTEST и возвращает значение HTCLIENT, равное 1. Я думаю, что это правильно, основываясь на Документе сообщения Microsoft WM_NCHITTEST.

С помощью этого обновленного WndProc я могу видеть сообщения от Form_MouseMove; но ни одного из PictureBox_MouseMove. А объекты, видимые через прозрачный элемент за формой, управляют мышью.

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

using System;
using System.Drawing;
using System.Windows.Forms;

namespace TransparentFormExample
{
    public class TransparentForm : Form
    {
        private PictureBox pictureBox;

        public TransparentForm()
        {
            // Set form properties
            this.TransparencyKey = Color.LimeGreen;
            this.Size = new Size(500, 800);
            this.TopMost = true;

            // Initialize and set PictureBox properties
            pictureBox = new PictureBox
            {
                BackColor = Color.LimeGreen,
                Size = new Size(200, 200),
                Location = new Point(150, 300) // Centered in the form
            };

            // Add PictureBox to the form
            this.Controls.Add(pictureBox);

            // Add event handlers
            this.MouseMove += new MouseEventHandler(Form_MouseMove);
            pictureBox.MouseMove += new MouseEventHandler(PictureBox_MouseMove);
        }

        // Override WndProc to handle WM_NCHITTEST message
        protected override void WndProc(ref Message m)
        {
            const int WM_NCHITTEST = 0x84;
            const int HTCLIENT = 0x1;

            if (m.Msg == WM_NCHITTEST)
            {
                m.Result = (IntPtr)HTCLIENT;
                return;
            }

            base.WndProc(ref m);
        }

        private void Form_MouseMove(object sender, MouseEventArgs e)
        {
            Console.WriteLine("Mouse over form");
        }

        private void PictureBox_MouseMove(object sender, MouseEventArgs e)
        {
            // extra spaces to make it easier to spot if it happens
            Console.WriteLine("             Mouse over PictureBox");
        }

        public void Start () 
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault( false );
            
            Application.Run( this ); 
        }
    }
}

Я запускаю форму с помощью следующей оболочки PowerShell, поскольку у меня нет возможности создавать DLL, компилировать .cs и запускать файлы .exe.

write-host "load main.cs"

add-type -path "TransparentForm.cs" -ReferencedAssemblies @(
    "System.Windows.Forms"
    "System.Drawing"
    "System.Drawing.Primitives"
    )
$ProgramInstance = [TransparentFormExample.TransparentForm]::New()
[System.Windows.Forms.Application]::Run( $ProgramInstance )

Это Windows Forms, WPF, MAUI или какая-то другая технология?

Uwe Keim 29.06.2024 17:47

Это использование System.Windows.Forms

Ro Yo Mi 29.06.2024 17:56

Для ваших нужд вы устанавливаете для PictureBox «BackColor» значение «Color.Transparent». Установка цвета TransparencyKey фактически заставляет его «исчезать».

Gerry Schmitz 29.06.2024 19:10

Вы можете воспользоваться старой ошибкой в ​​Win7+: использовать Color.Red для ключа прозрачности и заднего цвета pb.

Hans Passant 29.06.2024 22:09

При установке для PictureBox.BackColor значения Color.Transparent PictureBox становится прозрачным, но в результате вы видите сквозь PictureBox фон формы. Цель состоит в том, чтобы иметь возможность видеть другие окна через прозрачное отверстие в форме, но при этом сохранять контроль над мышью в форме.

Ro Yo Mi 29.06.2024 23:01

Вы пробовали использовать Красный (вместо Лаймового), как предлагал Ганс Пассант?

Loathing 30.06.2024 08:54

@ Ненависть, да. Я попробовал Color.Red, и это привело к той же проблеме.

Ro Yo Mi 30.06.2024 16:23

@RoYoMi Я попробовал это на Win8, и красный трюк сработал. Другая идея — очистить экран рабочего стола (за исключением формы), а затем нарисовать содержимое PictureBox. Или вы можете встроить элемент управления WPF.

Loathing 01.07.2024 20:56

@RoYoMi Пример для WPF: прозрачное плавающее окно, которое остается за формой и фиксирует события мыши.

Loathing 01.07.2024 20:58
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
9
76
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Начиная как минимум с Windows 11, прозрачные элементы в System.Windows.Forms не получают события мыши. Даже если вы создаете собственный метод переопределения WndProc. Этот метод не вызывается, когда указатель мыши находится над прозрачным элементом.

Возможно, это новая ошибка, или они изменили, какая функция вызывается при проверке прозрачности элемента формы.

Суть в том, что это невозможно сделать без использования ошибок пользовательского интерфейса, которые могут существовать, а могут и не существовать в Windows 11. Такое решение, скорее всего, в какой-то момент выйдет из строя, и, возможно, это уже произошло, поскольку «трюк» Color.Red, похоже, не работает.

Единственное решение — создать вторую форму, которая использует почти нулевое значение непрозрачности, которая для всех практических целей будет выглядеть прозрачной, но позволит этой форме получать события мыши, которые затем можно будет передать в форму с прозрачными элементами.

Лично я надеялся избежать клуджа, но это кажется единственным выходом.

Другие вопросы по теме