Я пытаюсь создать графическую библиотеку с графическим контролем. Элемент управления позволяет добавлять элементы управления наложением. Графика в элементе управления использует DirectX и является частью библиотеки, в то время как элементы управления наложением предоставляются конечными пользователями библиотеки, которые не являются экспертами в области графики. Таким образом, наиболее важными являются стабильность и удобный API.Наложение элементов управления WinForms на содержимое DirectX
По техническим причинам мне нужно показать графику DirectX непосредственно на элементе управления и не может размещать сцену DirectX с использованием другой структуры в качестве WPF (для получения дополнительной информации см. Мой предыдущий вопрос: Stereoscopic 3D on WPF).
Я считаю, что наиболее проблемные вопросы:
- Прозрачность (и полупрозрачность ...) в зоне самого элемента управления.
- Анимация на элементе управления наложением: Вот почему управление растрированием (например, WPF) не является вариантом.
Мои попытки до сих пор:
Вслед за много сообщений обсуждали подобные вопросы, я решил использовать WS_EX_TRANSPARENT. Я был удивлен, увидев, что, хотя Airspace issue, я вижу содержимое DirectX в прозрачных областях элемента управления наложением. Однако элемент управления наложением не показывался, за исключением случаев, когда я изменил размер окна - затем он снова мигает и снова исчезает. Вот код управления наложением:
class GDIGraphicsControl : UserControl { private const int WS_EX_TRANSPARENT = 0x20; protected override CreateParams CreateParams { get { CreateParams p = base.CreateParams; p.ExStyle |= WS_EX_TRANSPARENT; return p; } } public GDIGraphicsControl() { this.Dock = DockStyle.Fill; } protected override void OnPaintBackground(PaintEventArgs e) { // Do nothing } protected override void OnPaint(PaintEventArgs e) { for (int i = 0; i < 10; ++i) { int alpha = 25 * i; int yPos = 10 * i; e.Graphics.FillRectangle( new SolidBrush(Color.FromArgb(alpha, Color.Green)), 5, 5 + yPos, 100, 10); } e.Graphics.FillEllipse(new SolidBrush(Color.Red), 110, 5, 100, 100); } }
Для анализа мигающей проблемы, я попытался сделать вещи проще. Сначала для цели отладки я попытался использовать GDI-рендеринг вместо DirectX. Я реализовал его так, что он будет очень похож на рендеринг DirectX - особенно вызов Form.SetStyle и Invalidate() в каждом OnPaint(), который, как я думал, является причиной этой проблемы. Проблема действительно существует и в GDI-рендеринге. Вот GDI-рендеринг код родительского контроля:
public partial class RenderingForm : Form { public RenderingForm() { InitializeComponent(); ControlStyles styles = ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.UserPaint | ControlStyles.Opaque; this.SetStyle(styles, true); Button button = new Button() { Text = "Just a button", Left = 5, Top = 210, Width = 200 }; this.Controls.Add(button); this.Controls.Add(new GDIGraphicsControl()); } protected override void OnPaintBackground(PaintEventArgs e) { // Do nothing } protected override void OnPaint(PaintEventArgs e) { e.Graphics.Clear(Color.Blue); this.Invalidate(); base.OnPaint(e); } }
Я пытался добавить простую кнопку наложения, чтобы проверить, если проблема существует, когда не используется никакой прозрачности (см в коде выше). Кнопка не мигает, но вместо кнопки я вижу мусор на экране, пока не изменит размер элемента управления в первый раз - тогда кнопка появится правильно.
Я попытался сделать недействительными элементы управления наложением ребенка, но он не имеет никакого эффекта. Я попытался сделать его недействительным как в родительском OnPaint, так и в дочернем OnPaint, чтобы создать эффект рендеринга сообщений-сообщений, и он не имеет никакого эффекта. Установка стиля элемента управления, как и в режиме родительского рендеринга, не разрешила проблему и заставила фон мигать черным цветом.
я также выполнил несколько попыток с использованием WPF, но вопрос достаточно долго, теперь без жесткого Airspace issue ...
Теперь вопросы:
Может кто-нибудь объяснить, как делает GDI накладывать на графическую работу DirectX? Особенно я этого не понимаю, потому что я знаю, что прозрачность WinForms работает тем, что дети управляют рендерингом в Контекст устройства родителя - и DirectX имеет контекст рендеринга оборудования. Означает ли это, что текстура DirectX копируется обратно в программное обеспечение?
Почему переопределение CreateParams заставляет элемент управления мигать и как его предотвратить?
Какова стоимость выполнения этих методов прозрачности (переопределение CreateParams, BackColorTransparency = True, Control.SetStyle + переопределение OnPainBackground)? Очень важно, чтобы базовая графика была рендерирована эффективно, но я не забочусь о производительности наложения (кроме легкой анимации).
Большое спасибо. На самом деле мне уже удалось установить элементы управления WPF над содержимым DirectX с помощью ElementHost и установить BackColorTransparent = True. Однако я хотел бы также поддерживать элементы управления WinForms. WPF ElementHost (и, я думаю, также Popup из вашего источника) не взаимодействует с другими элементами управления WinForms на одном уровне иерархии (он скрывает элементы управления WinForms, которые находятся под ним, даже в прозрачных областях). Кроме того, прозрачные WinForms мигают (без каких-либо элементов управления WPF, как в вашем примере), и ваш источник не обращается к этим элементам управления WinForms. – MaMazav
У вас есть пример также для WinForms через DirectX? Или предложения для моего понимания вопросов из вашего опыта? – MaMazav