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





Думаю, это будет сложно без использования диспетчера окон рабочего стола, т.е. если вы хотите поддерживать Windows XP. Однако с DWM это похоже на довольно легко.
Если скорость не является проблемой, вы можете обойтись рендерингом на поверхность и последующим копированием визуализированного изображения в многоуровневое окно. Однако не ожидайте, что это будет быстро.
Беда, которая работает только с dx9, поскольку DWM в Vista - это dx9. Windows 7 будет использовать dx10, так что это будет хорошо.
Я нашел решение, которое работает в 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% прозрачным, и только ваш контент будет парить над всем.
WPF - также другой вариант.
Developed by Microsoft, the Windows Presentation Foundation (or WPF) is a computer-software graphical subsystem for rendering user interfaces in Windows-based applications.
Хотя эта ссылка может дать ответ на вопрос, лучше включить сюда основные части ответа и предоставить ссылку для справки. Ответы, содержащие только ссылки, могут стать недействительными, если ссылка на страницу изменится.
Обратите внимание, как на этот вопрос ответили почти 4 года назад, во время бета-тестирования? Вопросы и ответы тогда были экспериментальными. Это, конечно, не блестящий ответ, но это является ответ, причем жизнеспособный. Ссылка действительна, как и ее содержание.
Вы можете использовать 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.
Разве многослойные окна не вариант?