Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > WPF и Silverlight > WebBrowser: непрозрачность при прозрачном окне


Автор: V0fka 7.7.2014, 19:44
Привет!

Есть окно, в котором находится WebBrowser, который должен отображать html текст, который ему передается в виде строки. Понадобилось сделать скругленные углы у окна. Для этого помимо всего прочего сделал Background="Transparent" и AllowsTransparency="True". Окно обрело нужный вид. Но появилась беда: содержимое WebBrowser-а стало "невидимым". Искал в интернете информацию по теме, пишут, что WPF-ный веббраузер очень "деревянный" и по нормальному с ним так сделать то, что мне надо - не получится.

Подскажите, пожалуйста, как можно решить эту проблему?

Автор: Ilya81 8.7.2014, 07:03
Цитата(V0fka @  7.7.2014,  19:44 Найти цитируемый пост)
 Искал в интернете информацию по теме, пишут, что WPF-ный веббраузер очень "деревянный" и по нормальному с ним так сделать то, что мне надо - не получится.

Это действительно так. Стандартный WebBrowser не является полностью WPF-control'ом, а содержит контейнер, в котором помещён COM-объект от IE. Сам IE таких настроек не содержит ни в каком варианте, поэтому эффекты для содержимого недоступны.

Цитата(V0fka @  7.7.2014,  19:44 Найти цитируемый пост)
Подскажите, пожалуйста, как можно решить эту проблему? 

Варианты:
1). Найти сторонний модуль с Web browser на чистом WPF без встроенного COM;
2). Наложить эффекты поверх самого WebBrowser (всякие Border и т. п.), а не непосредственно применяя к нему, хотя, само окно прозрачным сделать не получится, по можно изобразить что-то похожее.

Автор: V0fka 8.7.2014, 12:52
Ilya81, вот беда.

Цитата(Ilya81 @  8.7.2014,  07:03 Найти цитируемый пост)
1). Найти сторонний модуль с Web browser на чистом WPF без встроенного COM;

Пошарил в интернете и нашел вот это: http://wpfchromium.codeplex.com/releases/view/49484 . Но там один проект, как я понял, на С++ и когда я пробую всё решение открыть в Visual Studio, то этот проект пишется как "недоступен" и без него не запускается другой. Не могли бы вы глянуть хотя б 1 глазом туда?

Цитата(Ilya81 @  8.7.2014,  07:03 Найти цитируемый пост)
2). Наложить эффекты поверх самого WebBrowser (всякие Border и т. п.), а не непосредственно применяя к нему

Проблема в том, сам html в этом браузере не отображается. Причем, если я на html отображаю там ссылку, то при наведении курсора туда он принимает соответствующий вид. И ссылка даже на клик реагирует. Но она просто невидимая (прозрачная?) получается (как и все остальное содержимое).

Я понял, что лучше показать XAML smile :

Код

<Border Background="#FFFFF0C5" CornerRadius="10,10,10,10" Name="WindowBorder" Padding="0">
        <Grid>
            <DockPanel Margin="0 0 0 0" LastChildFill="True">
                <WebBrowser x:Name="WebBrowser" Margin="5 5 5 5" DockPanel.Dock="Top"/>
            </DockPanel>
        </Grid>
    </Border>


Может я уже тут неправильно что-то делаю?

Цитата(Ilya81 @  8.7.2014,  07:03 Найти цитируемый пост)
хотя, само окно прозрачным сделать не получится, по можно изобразить что-то похожее. 

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

Автор: Ilya81 8.7.2014, 14:21
Цитата(V0fka @  8.7.2014,  12:52 Найти цитируемый пост)
то этот проект пишется как "недоступен"

Какой именно? Там их несколько.

Цитата(V0fka @  8.7.2014,  12:52 Найти цитируемый пост)
Может я уже тут неправильно что-то делаю?

А если оставить только AllowsTransparency="True", выводится? Т. е. сделать не всё окно прозрачным? Смысл DockPanel не понял, думаю, хватило б Grid.

Автор: V0fka 9.7.2014, 10:07
Цитата(Ilya81 @  8.7.2014,  14:21 Найти цитируемый пост)
Какой именно? Там их несколько.

Cjc.AwesomiumWrapper

Цитата(Ilya81 @  8.7.2014,  14:21 Найти цитируемый пост)
А если оставить только AllowsTransparency="True", выводится?

Получается вот что:
user posted image

А если только Background="Transparent" тогда так:
user posted image
То, где выводится qqq - это веб браузер.

Автор: Ilya81 9.7.2014, 11:27
Цитата(V0fka @  9.7.2014,  10:07 Найти цитируемый пост)
Cjc.AwesomiumWrapper

Посмотрел получше, вроде это единственный проект на C++. Компоненты для С++ установлены?

Цитата(V0fka @  9.7.2014,  10:07 Найти цитируемый пост)
А если только Background="Transparent" тогда так:

Это требует какой-то модификации? И какой, если требует?

Автор: V0fka 9.7.2014, 13:49
Цитата(Ilya81 @  9.7.2014,  11:27 Найти цитируемый пост)
Посмотрел получше, вроде это единственный проект на C++. Компоненты для С++ установлены?

Целенаправленно для С++ ничего не ставилось. Я даже не в курсе что надо ставить.

Цитата(Ilya81 @  9.7.2014,  11:27 Найти цитируемый пост)
Это требует какой-то модификации? И какой, если требует? 

Простите, не понял. Что "это" и о какой модификации речь? Тот скрин, который я приводил вторым (Background="Transparent") не устраивает тем, что там есть "темные" уголки по краям, которые не являются прозрачными.

Автор: Ilya81 9.7.2014, 14:36
Цитата(V0fka @  9.7.2014,  13:49 Найти цитируемый пост)
Целенаправленно для С++ ничего не ставилось. Я даже не в курсе что надо ставить.

В Visual Studio там есть установка компонентов для C++ и много ещё каких. Т. е. нужно запустить установщик в режиме изменения установленных компонентов.

Цитата(V0fka @  9.7.2014,  13:49 Найти цитируемый пост)
не устраивает тем, что там есть "темные" уголки по краям, которые не являются прозрачными

Понятно. В принципе, можно сделать два окна и следить за координатами/размерами верхнего, а нижнее без значка со скруглёнными углами чуть больших размеров.

Автор: V0fka 10.7.2014, 09:25
Цитата(Ilya81 @  9.7.2014,  14:36 Найти цитируемый пост)
В Visual Studio там есть установка компонентов для C++ и много ещё каких. Т. е. нужно запустить установщик в режиме изменения установленных компонентов.

Доустановил таким образом "Microsoft Foundation Classes для С++", но всеравно не завелось. Попробовал удалить/добавить заново конкретно этот проект - но тоже не помогло. Видно не судьба.

Цитата(Ilya81 @  9.7.2014,  14:36 Найти цитируемый пост)
Понятно. В принципе, можно сделать два окна и следить за координатами/размерами верхнего, а нижнее без значка со скруглёнными углами чуть больших размеров. 

Был бы очень признательный если бы вы рассказали подробней или выложили бы примерчик. smile 

Кстати,
Цитата(Ilya81 @  8.7.2014,  14:21 Найти цитируемый пост)
Смысл DockPanel не понял, думаю, хватило б Grid. 

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

Автор: Ilya81 10.7.2014, 11:23
Цитата(V0fka @  10.7.2014,  09:25 Найти цитируемый пост)
Был бы очень признательный если бы вы рассказали подробней или выложили бы примерчик.

Что-то вроде:
Код

_shadowWindow = new Window//в конструкторе
{
 ShowInTaskbar = false
 WindowStyle = WindowStyle.None
};


protected override void OnLocationChanged(EventArgs e)
{
  _shadowWindow.Left = Left - HorizontalOffset;
  _shadowWindow.Top = Top - VerticalOffset;
}

(надеюсь, совсем полностью не нужно).

Цитата(V0fka @  10.7.2014,  09:25 Найти цитируемый пост)
Доустановил таким образом "Microsoft Foundation Classes для С++", но всеравно не завелось. Попробовал удалить/добавить заново конкретно этот проект - но тоже не помогло. Видно не судьба.

MFC здесь и не нужен, это обёртка для chromium, в нём нет MFC. В окне Output что пишет о неоткрывшемся проекте?

Автор: V0fka 11.7.2014, 13:17
Ilya81,
Цитата(Ilya81 @  10.7.2014,  11:23 Найти цитируемый пост)
Что-то вроде

идея вроде ясна, спасибо! Не факт, конечно, что у меня получится, но буду пробовать. По результатам отпишусь.

Цитата(Ilya81 @  10.7.2014,  11:23 Найти цитируемый пост)
MFC здесь и не нужен, это обёртка для chromium, в нём нет MFC. В окне Output что пишет о неоткрывшемся проекте?

Привожу список ошибок (в Output то же самое пишет):
user posted image
Есть подозрения, что если устранить ошибку №1, то остальные пропадут. Но я не знаю что оно хочет.

Автор: Ilya81 11.7.2014, 14:15
Цитата(V0fka @  11.7.2014,  13:17 Найти цитируемый пост)
Есть подозрения, что если устранить ошибку №1, то остальные пропадут. Но я не знаю что оно хочет.

Там написано. Нужно выбрать указанный пункт контекстного меню этого проекта.

Автор: V0fka 13.7.2014, 13:49
Ilya81, попробовал сделать как вы выше посоветовали и что-то даже получилось smile . Но есть одна существенная проблема. Получается, что _shadowWindow по бокам вылазит за основное окно (т.к. оно по размерам немного больше) и если туда клацнуть мышкой, то оно получает фокус и основное окно уходит на задний план (со всем своим содержимым). Можно это поведение изменить: чтобы _shadowWindow не реагировало на клики (не забирало фокус)?

Цитата(Ilya81 @  11.7.2014,  14:15 Найти цитируемый пост)
Там написано. Нужно выбрать указанный пункт контекстного меню этого проекта. 

Чукча не читатель smile . Клацнул, обновил VC++ (или что-то типа того), но все равно не запускается:
Цитата
1>------ Перестроение всех файлов начато: проект: Cjc.AwesomiumWrapper, Конфигурация: Debug Win32 ------
1>  Stdafx.cpp
1>  AssemblyInfo.cpp
1>AssemblyInfo.cpp(40): warning C4947: RequestMinimum: помечен как устаревший
1>          Сообщение: "Assembly level declarative security is obsolete and is no longer enforced by the CLR by default. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information."
1>  Cjc.AwesomiumWrapper.cpp
1>i:\...\cjc.chromiumbrowserdemo (.net 4.0)\cjc.awesomiumwrapper\Cjc.AwesomiumWrapper.h(12): fatal error C1083: Не удается открыть файл включение: WebCore.h: No such file or directory
1>  Создание кода...
========== Перестроение всех: успешно: 0, с ошибками: 1, пропущено: 0 ==========

Ну пёс с ним, в принципе. Мне кажется лучше будет сделать так, как вы предложили с окном-тенью (по крайней мере на чистом C# будет). Тем более вроде даже почти получилось smile .

Автор: Ilya81 14.7.2014, 08:05
Цитата(V0fka @  13.7.2014,  13:49 Найти цитируемый пост)
Получается, что _shadowWindow по бокам вылазит за основное окно (т.к. оно по размерам немного больше) и если туда клацнуть мышкой, то оно получает фокус и основное окно уходит на задний план (со всем своим содержимым). Можно это поведение изменить: чтобы _shadowWindow не реагировало на клики (не забирало фокус)?

Можно попробовать установить свойство
Код

<Window
  ...
  Focusable="False" ... />

либо в обработчике события GotFocus вызывать метод Focus основного окна. Можно заодно внутреннюю часть дополнительного окна сделать прозрачной, чтоб, даже оказавшись на переднем плане, оно не закрывало содержимое основого окна.

Автор: V0fka 14.7.2014, 12:59
Цитата(Ilya81 @  14.7.2014,  08:05 Найти цитируемый пост)
Можно попробовать установить свойство
Код

<Window
  ...
  Focusable="False" ... />

Увы, но не работает.

Цитата(Ilya81 @  14.7.2014,  08:05 Найти цитируемый пост)
либо в обработчике события GotFocus вызывать метод Focus основного окна

Тоже не работает.

Насколько я сейчас понимаю, то нужно наверное не фокусом управлять, а именно "положением" окна что-ли. Сделал в "тени" отлов события Activated и в нем у основного окна вызываю Activate(). Не знаю как насчет правильности использования такого подхода, но по крайней мере вроде бы работает smile .

Цитата(Ilya81 @  14.7.2014,  08:05 Найти цитируемый пост)
Можно заодно внутреннюю часть дополнительного окна сделать прозрачной, чтоб, даже оказавшись на переднем плане, оно не закрывало содержимое основого окна. 

У дополнительного окна установлены свойства Background="Transparent" и AllowsTransparency="True". При этом если на него клацнуть, то оно выходит на передний план и заступает содержимое окна, которое под ним. Или вы не это имели ввиду?

В любом случае, огромное спасибо вам за помощь, похоже, что задача решена! smile

Автор: Ilya81 14.7.2014, 13:52
Если не срабатывает через свойства, возможно, понадобятся прямые вызовы user32.dll. Например, функции
Код

        public static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
        public static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2);
        public static readonly IntPtr HWND_TOP = new IntPtr(0);
        public static readonly IntPtr HWND_BOTTOM = new IntPtr(1);

        public struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }

        public enum UFlags : uint
        {
            SWP_NOSIZE = 0x0001,
            SWP_NOMOVE = 0x0002,
            SWP_NOZORDER = 0x0004,
            SWP_NOREDRAW = 0x0008,
            SWP_NOACTIVATE = 0x0010,
            SWP_FRAMECHANGED = 0x0020,
            SWP_SHOWWINDOW = 0x0040,
            SWP_HIDEWINDOW = 0x0080,
            SWP_NOCOPYBITS = 0x0100,
            SWP_NOOWNERZORDER = 0x0200,
            SWP_NOSENDCHANGING = 0x0400
        }

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);

        [DllImport("user32.dll")]
        public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, UFlags uFlags);

Здесь нужно получить координаты окна в пикселях первой функцией и во второй задать заодно подходящие значения UFlags (описание на MSDN). Для получения hWnd (дескриптор окна) можно использовать http://msdn.microsoft.com/en-us/library/system.windows.interop.windowinterophelper.

Автор: V0fka 16.7.2014, 09:15
Ilya81, на первый взгляд кажется, что этот способ сложнее чем так, как я сделал:
Цитата(V0fka @  14.7.2014,  12:59 Найти цитируемый пост)
Сделал в "тени" отлов события Activated и в нем у основного окна вызываю Activate()

Но за ещё один полезный совет спасибо, я попробую поэкспериментировать как-то.

Собственно, вопрос можно считать закрытым! Большое спасибо вам за помощь!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)