Как придать стеклу элемент управления под украшением? - PullRequest
0 голосов
/ 24 марта 2020

Я пытаюсь "размыть" пользовательский элемент управления windows 10, когда над ним размещается рекламный элемент.

Точнее, у меня есть элемент управления сеткой данных в окне пользователя wpf. Когда ячейка в сетке данных выбрана, над элементом управления сеткой данных создается редактор редактирования.

public DataGridAnnotationAdorner(DataGrid adornedDataGrid, IVisit visit, DateTime TableDate)
            : base(adornedDataGrid)
        {
            Control = new DataGridAnnotationControl(visit, TableDate);

            AddLogicalChild(Control);
            AddVisualChild(Control);

            Loaded += DataGridAnnotationAdorner_Loaded;    
        }

        private void DataGridAnnotationAdorner_Loaded(object sender, RoutedEventArgs e)
        {
            EnableBlur(AdornedElement);
        }

Затем загруженное событие вызывает (довольно стандартный) метод эффекта Blurr / glass:

   internal void EnableBlur(UIElement dataGrid)
    {
        HwndSource source = (HwndSource)PresentationSource.FromVisual(dataGrid);
        IntPtr hwnd = source.Handle;

        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(hwnd, ref data);

        Marshal.FreeHGlobal(accentPtr);
    }

Об ошибках не сообщается .... Но это не работает.

Итак, как я могу придать элементу «под стеклом» «стеклянный» вид?

TIA

1 Ответ

1 голос
/ 26 марта 2020

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

В WinForms (и C ++ I думаю), каждый элемент управления является своего рода «мини-окном». Под этим я подразумеваю, что каждый элемент управления получает свой собственный «дескриптор» от ОС, и ОС рассматривает их как отдельные объекты на экране. WPF отличается, иллюзия «отдельных элементов управления» в окне - это иллюзия, созданная платформой WPF. Насколько ОС знает, существует только одна сущность: Window и все последующие логики c обрабатываются внутри WPF. Это только в основном правда, хотя, как я расскажу позже.

Причина, по которой я вообще это поднимаю, заключается в том, что ваша строка кода PresentationSource.FromVisual(dataGrid) даст вам дескриптор Window, в котором размещается DataGrid, а не дескриптор, уникальный для самого DataGrid (поскольку у DataGrid нет дескриптора ). И поэтому все остальное, что вы делаете, используя этот дескриптор, на самом деле предназначено для всего WPF Window в целом.

Весь рендеринг внутри WPF Window обрабатывается внутренне платформой WPF (плюс ваши код), а не непосредственно ОС (как в WinForms и C ++), поэтому использование собственного метода, который сообщает ОС, как визуализировать что-либо, не будет работать с указанным c элементом внутри Window.

Насколько я понимаю, есть два пути, по которым вы можете попытаться создать этот эффект:

  • Вы можете попытаться воссоздать "стеклянный" эффект внутри WPF. Это может включать воссоздание или использование любого алгоритма, который используется для визуального искажения области для получения этого эффекта, а затем каким-то образом реализовать его в элементе управления. Я не знаю, с чего начать, кроме Google.

  • Вы можете попробовать воспользоваться другими элементами WPF, которые do имеют свои собственные ручки ,

    • Два основных элемента WPF, о которых я знаю, имеют свои собственные ручки: Window и Popup. Возможно, вы сможете создать один из них и расположить его там, где вам это нужно, так же, как вы делаете это сейчас со своим поклонником. Это будет сложно, хотя, потому что эти элементы на самом деле вне Window, которые породили их и на самом деле не связаны с ними. Поэтому, когда вы перемещаете основной Window через рабочий стол, Popup или sub Window не будут перемещаться вместе с ним. Вы также можете перетаскивать другие windows между окном WPF и всплывающим всплывающим окном (хотя и не уверены в этом).

    • Возможно, есть еще одна возможность под этим заголовком и это элемент управления WindowsFormsHost. Это элемент управления WPF, который содержит элемент управления WinForms в окне WPF . Предполагается, что элементы управления WinForms, размещенные внутри, имеют собственный дескриптор ОС (поскольку именно так работает WinForms). Это может быть вашим лучшим выбором, за исключением того, что я никогда не пробовал, и я понятия не имею, как WindowsFormsHost будет взаимодействовать с другими элементами, которые находятся вокруг или под ним. Так что это также может не работать вообще для того, что вам нужно.

Удачи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...