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

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).

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)

Drawing alpha-blended graphics over the desktop with Direct2D

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)?

g_main_loop_run() freeze the window

I am trying to create a video player in C# using the functions imported from the GStreamer library by Pinvoke. It's looking nice so far, but if I add g_main_loop_run(loop); my C# application freezes and I just can't click any button or move my window.
I think that the problem may involve gmaincontext, but I don't know exactly what the problem is or how to resolve it.
Here is my C++ code in my library:
GstElement *pipeline;
void seek_to_pos(double position) {
gint64 len;
gst_element_query_duration(pipeline, GST_FORMAT_TIME, &len);
gst_element_seek_simple(pipeline, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, len*position);
}
void play_file(char* path_to_file, void* hwnd_ptr_of_window){
gst_init(NULL, NULL);
HWND hwnd = (HWND)hwnd_ptr_of_window;
GMainLoop *loop = g_main_loop_new(NULL, FALSE);
pipeline = gst_element_factory_make("playbin", "player");
g_object_set (G_OBJECT (pipeline), "uri", path_to_file, NULL);
gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(pipeline), (guintptr)hwnd);
gst_element_set_state(pipeline, GST_STATE_PLAYING);
g_main_loop_run(loop);//problem
}
Without the g_main_loop_run(loop); string, all works fine, but of course I need it for some another things.
Also, I already know that I need to run GMainLoop in a
different thread to not block my C# application's event loop but I don't know exactly how I can do it.
So I need a code sample or link which describes how I can do it right. Thanks!

Is there any way I can integrate the MS Office Smooth Typing in a C# application?

In my opinion the MS Office Smooth Typing is a very innovative feature in the Office Suite, and I'd like to know if this feature is available for programmers in the .NET Framework, specifically in the C# language.
If so, could you please post in your answer a usage example and link to the documentation?
Thanks.
By "smooth typing" I'm referring to the typing animation, that makes the cursor slide during typing.
I don't own Office, so I can't look at the feature, but I needed to fiddle around with the caret in RichTextBoxes a while ago and decided that it wasn't worth the effort. Basically you are on your own. No helper functions from .NET, but everything is handled by the backing Win32 control. You will have a hard time defeating what already happens under the hood. And probably ending up intercepting window messages and lots of ugly code.
So my basic advice is: Don't do it. At least for basic form controls like the TextBox or RichTextBox. You may have more luck trying to remote access an running office from within .NET, but that is a totally different can of worms.
If you really insist on going the SetCaretPos - route, here is some code to get you up and running with a basic version where you can improve upon:
// import the functions (which are part of Win32 API - not .NET)
[DllImport("user32.dll")] static extern bool SetCaretPos(int x, int y);
[DllImport("user32.dll")] static extern Point GetCaretPos(out Point point);
public Form1()
{
InitializeComponent();
// target position to animate towards
Point targetCaretPos; GetCaretPos(out targetCaretPos);
// richTextBox1 is some RichTextBox that I dragged on the form in the Designer
richTextBox1.TextChanged += (s, e) =>
{
// we need to capture the new position and restore to the old one
Point temp;
GetCaretPos(out temp);
SetCaretPos(targetCaretPos.X, targetCaretPos.Y);
targetCaretPos = temp;
};
// Spawn a new thread that animates toward the new target position.
Thread t = new Thread(() =>
{
Point current = targetCaretPos; // current is the actual position within the current animation
while (true)
{
if (current != targetCaretPos)
{
// The "30" is just some number to have a boundary when not animating
// (e.g. when pressing enter). You can experiment with your own distances..
if (Math.Abs(current.X - targetCaretPos.X) + Math.Abs(current.Y - targetCaretPos.Y) > 30)
current = targetCaretPos; // target too far. Just move there immediately
else
{
current.X += Math.Sign(targetCaretPos.X - current.X);
current.Y += Math.Sign(targetCaretPos.Y - current.Y);
}
// you need to invoke SetCaretPos on the thread which created the control!
richTextBox1.Invoke((Action)(() => SetCaretPos(current.X, current.Y)));
}
// 7 is just some number I liked. The more, the slower.
Thread.Sleep(7);
}
});
t.IsBackground = true; // The animation thread won't prevent the application from exiting.
t.Start();
}
Use SetCaretPos with your own animation timing function. Create a new thread that interpolates the caret's position based on the previous location and the new desired location.

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