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

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

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


person Garth    schedule 29.09.2008    source источник
comment
Разве многослойные окна не вариант?   -  person Agnel Kurian    schedule 06.11.2008
comment
msdn.microsoft.com/en-us/library/ms997507.aspx   -  person Agnel Kurian    schedule 06.11.2008


Ответы (4)


Я нашел решение, которое работает в 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% прозрачным, и только ваш контент будет парить над всем.

person Garth    schedule 30.09.2008

Вы можете использовать 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, если они доступны.

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

Или вы используете собственный метод Win32 для глобальной альфы Window (помните, что альфа, равная 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.

person thewhiteambit    schedule 18.01.2015

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

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

person OregonGhost    schedule 29.09.2008
comment
Беда, которая работает только с dx9, поскольку DWM в Vista - это dx9. Windows 7 будет использовать dx10, так что это будет хорошо. - person Simon Buchan; 20.02.2009

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

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

person OJ.    schedule 27.10.2008
comment
Хотя эта ссылка может дать ответ на вопрос, лучше включить сюда основные части ответа и предоставить ссылку для справки. Ответы, содержащие только ссылки, могут стать недействительными, если ссылка на страницу изменится. - person fglez; 31.08.2012
comment
Обратите внимание, как на этот вопрос ответили почти 4 года назад, во время бета-тестирования? Вопросы и ответы тогда были экспериментальными. Это, конечно, не блестящий ответ, но это ответ, причем жизнеспособный. Ссылка действительна, как и ее содержание. - person OJ.; 01.09.2012