Drawing alpha-blended graphics over the desktop with Direct2D - c#

I am building a UI using pure Direct2D and C# with SharpDX.
This UI is meant to be user-friendly and good-looking, while being efficient.
For the sake of demonstration, I built a prototype using hacky undocumented APIs (see this question), but in no way I am going to production with this, being backward-compatibility the first and foremost reason:
var accent = new User32.AccentPolicy { AccentState = AccentState };
int accentStructSize = Marshal.SizeOf(accent);
// allocate space for the struct
IntPtr accentPtr = Marshal.AllocHGlobal(accentStructSize);
Marshal.StructureToPtr(accent, accentPtr, false);
// set composition data
var data = new User32.WindowCompositionAttributeData {
Attribute = User32.WindowCompositionAttribute.WCA_ACCENT_POLICY,
SizeOfData = accentStructSize,
Data = accentPtr
};
// change window composition attributes and release resources
User32.SetWindowCompositionAttribute(Handle, ref data);
Marshal.FreeHGlobal(accentPtr);
I know the instant response to this is to use WPF, but I'm fairly limited to raw Direct2D calls, as I'm intending to move all the UI logic to a DLL for injection in DirectX apps (which, albeit not being sure how I'm going to do this, is out of the scope of this question.)
On Windows 8.1, there is DirectComposition, which enables efficient alpha-blending on top of transparent windows.
But there's no such thing in Windows Vista and 7 (even with the Platform Update).
Is there a way I can use pure, non-hacky Direct2D/DirectX code to make this UI work across all Windows versions (preferably Vista SP2 upwards)?

Related

Take screenshot of external OpenGL game C# with BitBlt (CopyFromScreen)

I am trying to create some kind of antycheat for counter strike (hl) game. Of course funcionality of making a screenshot in-game is built-in, but exploited (detected) by antyss applications, so every time screenshot is taken from the game, antyss is disabling the cheats (so that no cheats are visible on the screenshots)
For the last few days, I've read dozens of threads regarding this topic. Most of them are outdated and are using libraries, that are obsolete right now.
I've read about the approach with mirage driver (which is not working on windows 10), about injecting to the application (of course application/game is not part of my code) and using/incjeting some code with OPEN GL/D3D library (to read backbuffer). Probably this could be in the end the only solution.
But right now I have almost a working solution. I write "almost" because it is working but giving me only some kind of "cached" data. It is giving me a correct screenshot, but if I take another screenshot - still the same screenshot is taken as last time. If while being in-game I minimize the application (full-screen mode) and then get back to the game, the new screenshot taken will have up to date screenshot, but then again, the next screenshot would be exactly the same.
I don't know if it is "by design" or is it "some sort of bug" Nevertheless my question is: Can I force somehow this "reloading" without having to programmatically call some kind of "alt+tab" and then focusing on the application once again?
In this topic:
How to take screenshots of a game with OpenGL
#Andon M. Coleman wrote:
Are you on Windows? In fullscreen mode starting with Windows Vista, there is trouble with anything that tries to capture the front-buffer (including the built-in Alt + PrintScreen). The easiest solution is to change your buffer swap behavior to Copy Swap (PFD_SWAP_COPY, slower but guaranteed to work). Often if you Alt+TAB out and back in after making the fullscreen mode switch that will fix it too; though I have never been able to explain that ;) If you did not write the game in the question, then the second solution may be your only choice if you want to use that code.
This is exactly the problem I am facing. As he wrote: "Alt+Tab" is fixing the problem (although he did not know whether it is a feature or a bug) He proposed to change the buffer swap behavior to Copy Swap(PFD_SWAP_COPY) Any tips on how to change my code with that will also be most welcome (I can try this one) But if I understood correctly, this approach is the viable solution only if you can change this in the game (and this is not my case)
Here is my working code (which in topics about such scenarios was claiming that in this approach the screenshot is BLACK. But it is working for me)
private const int SW_RESTORE = 9;
public void TakeScreenShot()
{
var guid = Guid.NewGuid();
string procName = "hl";
Process proc;
try
{
proc = Process.GetProcessesByName(procName)[0];
}
catch (IndexOutOfRangeException e)
{
return;
}
// Focus on the application
SetForegroundWindow(proc.MainWindowHandle);
ShowWindow(proc.MainWindowHandle, SW_RESTORE);
Thread.Sleep(1000);
Rect rect = new Rect();
IntPtr error = GetWindowRect(proc.MainWindowHandle, ref rect);
while (error == (IntPtr)0)
{
error = GetWindowRect(proc.MainWindowHandle, ref rect);
}
int width = rect.right - rect.left;
int height = rect.bottom - rect.top;
using (Bitmap printscreen = new Bitmap(width, height, PixelFormat.Format32bppArgb))
{
using (var graphics = Graphics.FromImage(printscreen))
{
graphics.CopyFromScreen(rect.left,
rect.top,
0,
0,
new Size(width, height),
CopyPixelOperation.SourceCopy);
printscreen.Save($#"{Path.GetTempPath()}\{guid.ToString()}.jpg", ImageFormat.Jpeg);
}
}
}
I want this application to work on Windows7, Windows8, Windows 10. The best would be to cover full screen and windowed mode (but fullscreen is probably more important)
Any advice how to proceed (or why I am getting the "cached" data) would be nice :)
Of course if someone will say (with full authority), that what i want to achieve is impossible with CopyFromScreen (and there is no hack to fix that, apart from minimizing and maximazing the screen) i will consider option with injecting the code. But normally i would want to stay away from this one, as this could be treated as cheat and can lead to VAC ban.
====== UPDATE ======
You can try reproduce the process of taking screenshot by downloading the game (is small one, 260 MB):
https://cssetti.pl/Api/GameDownload.php?GameDownloadId=v43
Then you can copy-paste my code to Linqpad (or any other editor) and run the code. The application after launching will launch the HL process which is then use to try to grab the screenshot.
====== UPDATE 2 ======
In windows mode everything works correctly (the printscreens are ok)

GStreamer# equivalent for video overlay functions

I have a C#/Mono application for rendering video streams and, until recently, I've been using my own in-house developed InterOp bindings.
I'm now moving from that method to use those of GStreamer#, since that's likely to be much less maintenance effort, at least for me :-)
Since I need to bind independent video streams to a specific DrawableArea widgets, my method captured the GStreamer messages then checked them with the function gst_is_video_overlay_prepare_window_handle_message(msg)(a).
If that returned true, I then responded with a call to gst_video_overlay_set_window_handle(xid), where xid was the handle for the widget obtained earlier with gdk_x11_window_get_xid().
My problem is this: searching through the GStreamer# code, I cannot find an equivalent function for doing the binding so I was wondering how this is meant to be done.
Anyone have any advice or information to offer?
The source code for those two functions are in gst-plugins-base-1.4.4/gst-libs/gst/video/videooverlay.c so, in a pinch, I could dummy up my own functions to do the job (or just stick with our bindings for that one little bit) but it seems to me this would have been included in GStreamer# since rendering to specific widgets seems like a very handy facility.
(a) Those GStreamer wags. They must replace their keyboards quite a bit with all that unnecessary typing :-)
Turns out those functions are available, but in a separate library and sub-namespace to the baseline GStreamer stuff.
The getting of the Xid is still done with a self-made InterOp binding, to wit:
[DllImport("libgdk-3", EntryPoint = "gdk_x11_window_get_xid")]
private extern static IntPtr GdkX11WindowGetXid(IntPtr window);
You also have instance-level variables for the playbin, bus and X11 window ID:
private IntPtr windowXid;
private Gst.Element playBin;
private Gst.Bus bus;
Then, when instantiating the class, you capture the Realized signal and ensure that all messages on the GStreamer bus go to your callback function:
this.Realized += OnRealized;
playBin = Gst.ElementFactory.Make('playbin', 'playbin');
bus = playBin.Bus;
bus.AddSignalWatch();
bus.Message += MessageCallback;
In that realisation function, you save the Xid for later use (in an instance variable):
void OnRealized(object o, EventArgs args) {
windowXid = GdkX11WindowGetXid(this.Window.Handle);
}
and, when asked by GStreamer, provide this handle in response to the request:
private void MessageCallback(object o, MessageArgs args) {
Gst.Message msg = args.Message;
if (! Gst.Video.Global.IsVideoOverlayPrepareWindowHandleMessage(msg))
return;
Gst.Element src = msg.Src as Gst.Element;
if (src == null)
return;
Gst.Element overlay = null;
if (src is Gst.Bin)
overlay = ((Gst.Bin)src).GetByInterface
Gst.Video.VideoOverlayAdapter = new Gst.Video.VideoOverlayAdapter(overlay.Handle);
adapter.WindowHandle = windowXid;
}
Note that I've fully qualified all the GStreamer objects so it's absolutely clear where they can be found. The code would probably be a lot cleaner without them (and with using var for the variables) but I wanted to ensure all information was available.

C++ hybrid (native managed) +sdl + opengl & c# winforms

I'm working on a interactive rendering software using opengl in sdl written in c++.
The project evolving, I wanted to have a HIM/GUI to manipulate my rendering engine.
So I started to search some easy/fast HIM coding ways to do it.
Finnaly I decided to use winforms and c# to create HIM, because its offer a way to design and code easily a HIM.
At first i started to create an hybrid dll with native and managed c++. OK.
After I try to use this dll inside a c# application. OK.
Now my goal is: insert the opengl rendering inside the winforms application.
My questions are:
Can I bind my SDLcontext/SDLwindows(C++) to a winforms object?
Can I bind a c# bitmap to an array of byte from my dll ? (aim to update pixels of it by the dll)
if ok: do I have to call a function to refresh my GUI(winforms) on pixel change ?
Do you think it will be interesting to drop SDL and use only winforms for this kind of work ?
Any suggestion ?
EDIT: add information about my investigation
Thanks to Lawrence Kok I pursue my research.
So I tried to bind my SDL windows to a Panel form
private void LaunchEngine(string str)
{
unsafe
{
byte[] bytes = Encoding.ASCII.GetBytes(str);
sbyte[] sbyt = (sbyte[])(Array)bytes;
fixed (sbyte* p = sbyt)
{
// Engine is a managed class that bridge my c++ to c#
// all it's function are static
Engine.LOAD_CONTENT_FROM_FILE(p);
Engine.PRINTCONFIGURATION();
if (Engine.LOAD_ENGINE_DATA() && Engine.INITIALISE_ENGINE_DATA())
{
// Bind attempt here
_SdlWindowHandle = Engine.GETHANDLE();
SetWindowPos(_SdlWindowHandle, this.Handle, 0, 0, 0, 0, (SetWindowPosFlags.SWP_NOSIZE | SetWindowPosFlags.SWP_SHOWWINDOW));
// Make the SDL Window the child of our Panel
SetParent(_SdlWindowHandle, m_SdlPanel.Handle);
ShowWindow(_SdlWindowHandle, ShowWindowCommand.SW_SHOWNORMAL);
// In futur i will put this loop in another thread
// but for now I'm trying to validate my prototype
for (; ; )
{
Engine.UPDATE_ENGINE_DATA();
Engine.DRAW_ENGINE_DATA();
}
}
}
}
Actually, the change the parent of my sdl windows, close it, and my engine is running, but my panel is completely blank.
I think I'm missing something here but i can't figured what.
here is how i get the SDL window handle (from SDL2)
// coming from c++ native library
// and represent by Engine.GETHANDLE();
// from managed c++ lib
HWND SDLWindowManager::GetHandle()
{
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
/*if (SDL_GetWMInfo(&info) < 0)
return 0;*/
SDL_GetWindowWMInfo(_mainWindow, &info);
return info.info.win.window;
}
EDIT: problem solved
I forget to add the panel to winforms control:
public Form1()
{
InitializeComponent();
m_SdlPanel = new Panel();
m_SdlPanel.Size = new Size(512, 512);
m_SdlPanel.Location = new Point(0, 0);
Controls.Add(m_SdlPanel);
}
Given that your target platform is Windows, there is a very easy way to insert your opengl rendering into your windows form application. You can simply make a window with your favorite package of choice, sdl, sfml, plain winapi code. When you obtain the handle of the window in question, just change the style of the window so that it becomes a child window, and put it as a child window of your window of choice. As for the parent window, what I like to do is subclass special panel-type control for this purpose.
After that you can just use the composition of the controls as normal. Only the airspace problems might influence the presentation (https://msdn.microsoft.com/en-us/library/aa970688%28v=vs.110%29.aspx).

C# opengl context handle getter returns wrong address

Problem solved!
Deleted pragma of sharing from kernel string.(using opencl 1.2)
Reordered GL-VBO-creating and CL-Context-Creating. First create CL-context from gl-context. Then create GL-VBO. Then acquire it by cl. Then compute. Then release by cl. Then bind by gl. Draw. Finish gl. Start over. Use clFinish always to ensure it synchs with gl. For more speed, clflush can be okay maybe even an implicit sync can be done which I did not try.
[original question from here]
In C#, context construction for opencl-gl-interop fails because handle getter function gives wrong address and causes System.AccessViolationException.
C# part:
[DllImport("opengl32.dll",EntryPoint="wglGetCurrentDC")]
extern static IntPtr wglGetCurrentDC();//CAl
[DllImport("opengl32.dll", EntryPoint = "wglGetCurrentContext")]
extern static IntPtr wglGetCurrentContext();// DCAl
C++ part in opencl(this is in a wrapper class of C++ opencl):
pl = new cl_platform_id[2];
clGetPlatformIDs( 1, pl, NULL);
cl_context_properties props[] ={ CL_GL_CONTEXT_KHR, (cl_context_properties)CAl,
CL_WGL_HDC_KHR, (cl_context_properties)DCAl,CL_CONTEXT_PLATFORM,
(cl_context_properties)&pl[0], 0};
ctx=cl::Context(CL_DEVICE_TYPE_GPU,props,NULL,NULL,NULL);//error comes from here
//ctx=cl::Context(CL_DEVICE_TYPE_GPU); this does not interop >:c
What is wrong in these parts? When I change "opengl32.dll" to "opengl64.dll" compiler/linker cannot find it.
Calling wglGetCurrentDC() and wglGetCurrentContext() after glControl1 is loaded but these seem to be giving wrong addresses. Calling wglMakeCurrent() or glControl1.MakeCurrent() before those did not solve the problem too.
OS: 64 bit windows7
Host: fx8150
Device: HD7870
MSVC2012(windows forms application) + OpenTK(2010_10_6) + Khronos opencl 1.2 headers
Build target is x64(release).
Note: opencl part is working well for computing(sgemm) and opengl part is drawing VBO well (some plane built of triangles with some color and normals) but opencl part(context) refuses to interop.
Edit: Adding #pragma OPENCL EXTENSION cl_khr_gl_sharing : enable into kernel string did not solve the problem.
Edit: Creating GL VBOs "after" the construction of cl context, error vanishes but nothing is updated by opencl kernel. Weird. PLus, when I delete cl_khr_sharing pragma, the 3D shape starts artifacting which means opencl is doing something now but its just random deleted pixels and some cropped areas which I did not wrote in kernel. Weirdier. You can see this in below picture(I am trying to make the flat blue sheet disappear but it doesnt fully disappear and also i try changing color and that is not changing)
Edit: CMSoft's opencltemplate looks like what I need to learn/do but their example code consists only 6-7 lines of code! I dont know where to put compute kernel and where to get/set initial data, but that example works great(gives hundreds of "WARNING! ComputeBuffer{T}(575296656) leaked." by the way).
Edit: In case you wonder, here is kernel arguments' construction in C++:
//v1,v2,v3,v4 are unsigned int taken from `bindbuffer` of GL in C#
//so v1 is buf[0] and v2 is buf[1] and so goes like this
glBuf1=cl::BufferGL(ctx,CL_MEM_READ_WRITE,v1,0);
glBuf2=cl::BufferGL(ctx,CL_MEM_READ_WRITE,v2,0);
glBuf3=cl::BufferGL(ctx,CL_MEM_READ_WRITE,v3,0);
glBuf4=cl::BufferGL(ctx,CL_MEM_READ_WRITE,v4,0);
and here is how set into command queue:
v.clear();
v.push_back(glBuf1);
v.push_back(glBuf2);
v.push_back(glBuf3);
v.push_back(glBuf4);
cq.enqueueAcquireGLObjects(&v,0,0);
cq.finish();
and here is how I set as arguments of kernel:
kernel.setArg(0,glBuf1);
kernel.setArg(1,glBuf2);
kernel.setArg(2,glBuf3);
kernel.setArg(3,glBuf3);
here is how executed:
cq.enqueueNDRangeKernel(kernel,referans,Global,Local);
cq.flush();
cq.finish();
here is how released:
cq.enqueueReleaseGLObjects(&v,0,0);
cq.finish();
Simulation iteration:
for (int i = 0; i < 200; i++)
{
GL.Finish(); // lets cl take over
//cl acquires buffers in glTest
clh.glTest(gci.buf[0], gci.buf[1], gci.buf[2], gci.buf[3]);// then computes
// then releases
Thread.Sleep(50);
glControl1.MakeCurrent();
glControl1.Invalidate();
gci.ciz(); //draw
}

Should I call Application.EnableVisualStyles() on terminal services?

In a terminal services/citrix environment, should I call
Application.EnableVisualStyles() in my .NET 3.5 WinForms app when my program
starts? Or, is it better to refrain from doing that?
I am looking for the option that gives the best performance, and do not need any controls drawn with
themes.
Visual styles are the colors, fonts, and other visual elements that form an operating system theme. Controls will draw with visual styles if the control and the operating system support it. To have an effect, EnableVisualStyles() must be called before creating any controls in the application; typically, EnableVisualStyles() is the first line in the Main function.
So, if you need to have your application look in line with the current OS theme, you need to call this. If the classic Windows look is enough for you, you can skip this. I personally never enable visual styles for my server-only apps (like control panels, etc.).
Below is a configurator tool without the visual styles enabled. It's good looking for me this way so EnableVisualStyles was skipped:
A quick look into Application.EnableVisualStyles() method with reflector revealed below code in the method EnableVisualStyles -> EnableVisualStylesInternal -> CreateActivationContext:
if (!contextCreationSucceeded && OSFeature.Feature.IsPresent(OSFeature.Themes))
{
enableThemingActivationContext = new ACTCTX();
enableThemingActivationContext.cbSize = Marshal.SizeOf(typeof(ACTCTX));
enableThemingActivationContext.lpSource = dllPath;
enableThemingActivationContext.lpResourceName = (IntPtr) nativeResourceManifestID;
enableThemingActivationContext.dwFlags = 8;
hActCtx = CreateActCtx(ref enableThemingActivationContext);
contextCreationSucceeded = hActCtx != new IntPtr(-1);
}
If OSFeature.Feature.IsPresent(OSFeature.Themes) returns false, EnableVisualStyles has absolutely no effect so calling it or not makes no difference.

Categories

Resources