Как нарисовать прозрачный контент DirectX в прозрачном окне?

StackOverflow https://stackoverflow.com/questions/148275

Вопрос

Я хочу рисовать содержимое DirectX так, чтобы оно казалось плавающим поверх рабочего стола и любых других запущенных приложений.Мне также нужно иметь возможность сделать содержимое DirectX полупрозрачным, чтобы другие вещи были видны.Есть ли способ сделать это?

Я использую Managed DX с C#.

Это было полезно?

Решение

Я нашел решение, которое работает в Vista, начиная со ссылки, предоставленной OregonGhost.Это основной процесс в синтаксисе C#.Этот код находится в классе, унаследованном от Form.Кажется, это не работает, если в UserControl:

//this will allow you to import the necessary functions from the .dll
using System.Runtime.InteropServices;

//this imports the function used to extend the transparent window border.
[DllImport("dwmapi.dll")]
static extern void DwmExtendFrameIntoClientArea(IntPtr hWnd, ref Margins pMargins);

//this is used to specify the boundaries of the transparent area
internal struct Margins {
    public int Left, Right, Top, Bottom;
}
private Margins marg;

//Do this every time the form is resized. It causes the window to be made transparent.
marg.Left = 0;
marg.Top = 0;
marg.Right = this.Width;
marg.Bottom = this.Height;
DwmExtendFrameIntoClientArea(this.Handle, ref marg);

//This initializes the DirectX device. It needs to be done once.
//The alpha channel in the backbuffer is critical.
PresentParameters presentParameters = new PresentParameters();
presentParameters.Windowed = true;
presentParameters.SwapEffect = SwapEffect.Discard;
presentParameters.BackBufferFormat = Format.A8R8G8B8;

Device device = new Device(0, DeviceType.Hardware, this.Handle,
CreateFlags.HardwareVertexProcessing, presentParameters);

//the OnPaint functions maked the background transparent by drawing black on it.
//For whatever reason this results in transparency.
protected override void OnPaint(PaintEventArgs e) {
    Graphics g = e.Graphics;

    // black brush for Alpha transparency
    SolidBrush blackBrush = new SolidBrush(Color.Black);
    g.FillRectangle(blackBrush, 0, 0, Width, Height);
    blackBrush.Dispose();

    //call your DirectX rendering function here
}

//this is the dx rendering function. The Argb clearing function is important,
//as it makes the directx background transparent.
protected void dxrendering() {
    device.Clear(ClearFlags.Target, Color.FromArgb(0, 0, 0, 0), 1.0f, 0);

    device.BeginScene();
    //draw stuff here.
    device.EndScene();
    device.Present();
}

Наконец, форма с настройками по умолчанию будет иметь стеклянный, частично прозрачный фон.Установите для FormBorderStyle значение «none», и он будет на 100% прозрачным, и над всем будет плавать только ваш контент.

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

Вы можете использовать DirectComposition, LayeredWindows, DesktopWindowManager или WPF.Все методы имеют свои преимущества и недостатки:

-DirectComposition является наиболее эффективным, но требует Windows 8 и ограничен частотой 60 Гц.

- В LayeredWindows сложно работать с D3D через взаимодействие Direct2D с использованием DXGI.

-WPF относительно легко использовать через D3DImage, но он также ограничен 60 Гц и DX9 и не имеет MSAA.Возможно взаимодействие с более высокими версиями DX через DXGI, также можно использовать MSAA, когда цель MSAA-Rendertarget разрешается в исходную поверхность без MSAA.

-DesktopWindowManager отлично подходит для высокой производительности, доступной начиная с Windows Vista, но версии DirectX, похоже, ограничены версией, которую использует DWM (все еще DX9 в Vista).Обходные пути для более высоких версий DX должны быть возможны через DXGI, где это возможно.

Если вам не нужен попиксельный aplha, вы также можете использовать значение непрозрачности полупрозрачной формы.

Или вы используете собственный метод Win32 для глобальной альфа-версии окна (помните, что альфа, равная 0, не будет улавливать ввод мыши):

SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
COLORREF color = 0;
BYTE alpha = 128;
SetLayeredWindowAttributes(hWnd, color, alpha, LWA_ALPHA);

Мне удалось использовать все описанные методы с C# и SharpDX, но в случае DirectComposition, LayeredWindows и собственного Win32 потребовалось немного C++-Wrappercode.Для начала я бы предложил использовать WPF.

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

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

WPF это еще один вариант.

Windows Presentation Foundation (или WPF), разработанная Microsoft, представляет собой графическую подсистему компьютерного программного обеспечения для рендеринга пользовательских интерфейсов в приложениях на базе Windows.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top