2013-12-12 4 views
1

Я пытаюсь создать графическую библиотеку с графическим контролем. Элемент управления позволяет добавлять элементы управления наложением. Графика в элементе управления использует DirectX и является частью библиотеки, в то время как элементы управления наложением предоставляются конечными пользователями библиотеки, которые не являются экспертами в области графики. Таким образом, наиболее важными являются стабильность и удобный API.Наложение элементов управления WinForms на содержимое DirectX

По техническим причинам мне нужно показать графику DirectX непосредственно на элементе управления и не может размещать сцену DirectX с использованием другой структуры в качестве WPF (для получения дополнительной информации см. Мой предыдущий вопрос: Stereoscopic 3D on WPF).

Я считаю, что наиболее проблемные вопросы:

  • Прозрачность (и полупрозрачность ...) в зоне самого элемента управления.
  • Анимация на элементе управления наложением: Вот почему управление растрированием (например, WPF) не является вариантом.

Мои попытки до сих пор:

  1. Вслед за много сообщений обсуждали подобные вопросы, я решил использовать 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); 
        } 
    } 
    
  2. Для анализа мигающей проблемы, я попытался сделать вещи проще. Сначала для цели отладки я попытался использовать 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); 
        } 
    } 
    
  3. Я пытался добавить простую кнопку наложения, чтобы проверить, если проблема существует, когда не используется никакой прозрачности (см в коде выше). Кнопка не мигает, но вместо кнопки я вижу мусор на экране, пока не изменит размер элемента управления в первый раз - тогда кнопка появится правильно.

  4. Я попытался сделать недействительными элементы управления наложением ребенка, но он не имеет никакого эффекта. Я попытался сделать его недействительным как в родительском OnPaint, так и в дочернем OnPaint, чтобы создать эффект рендеринга сообщений-сообщений, и он не имеет никакого эффекта. Установка стиля элемента управления, как и в режиме родительского рендеринга, не разрешила проблему и заставила фон мигать черным цветом.

я также выполнил несколько попыток с использованием WPF, но вопрос достаточно долго, теперь без жесткого Airspace issue ...

Теперь вопросы:

  1. Может кто-нибудь объяснить, как делает GDI накладывать на графическую работу DirectX? Особенно я этого не понимаю, потому что я знаю, что прозрачность WinForms работает тем, что дети управляют рендерингом в Контекст устройства родителя - и DirectX имеет контекст рендеринга оборудования. Означает ли это, что текстура DirectX копируется обратно в программное обеспечение?

  2. Почему переопределение CreateParams заставляет элемент управления мигать и как его предотвратить?

  3. Какова стоимость выполнения этих методов прозрачности (переопределение CreateParams, BackColorTransparency = True, Control.SetStyle + переопределение OnPainBackground)? Очень важно, чтобы базовая графика была рендерирована эффективно, но я не забочусь о производительности наложения (кроме легкой анимации).

ответ

1

Я провел много исследований в этой области, и я пришел к выводу, что Airspace - это путь. Я собрал источники из многочисленных проектов по сети и поместил их в один проект, который позволяет интегрировать WPF с XNA. Я также сделал версию этого, которая была чистой DirectX, но, честно говоря, версия XNA намного более проста и лучше подходит для C#. Мне не хватает места, чтобы опубликовать все подробности здесь, но вы можете download the demo from my website и, вероятно, выяснить, куда идти оттуда. Удачи!

+0

Большое спасибо. На самом деле мне уже удалось установить элементы управления WPF над содержимым DirectX с помощью ElementHost и установить BackColorTransparent = True. Однако я хотел бы также поддерживать элементы управления WinForms. WPF ElementHost (и, я думаю, также Popup из вашего источника) не взаимодействует с другими элементами управления WinForms на одном уровне иерархии (он скрывает элементы управления WinForms, которые находятся под ним, даже в прозрачных областях). Кроме того, прозрачные WinForms мигают (без каких-либо элементов управления WPF, как в вашем примере), и ваш источник не обращается к этим элементам управления WinForms. – MaMazav

+0

У вас есть пример также для WinForms через DirectX? Или предложения для моего понимания вопросов из вашего опыта? – MaMazav

Смежные вопросы