FindWindowByCaption function finding window handle that doesn't exist yet - c#

I am writing a C# application that requires moving gnuplot graphs to specific positions on the user's screen. To do this I am using DllImport to bring in several functions into my program. Specifically FindWindowByCaption and MoveWindow and a few others. This has been working fine for me thus far, but suddenly the graphs have stopped moving.
I figured out that the graphs are taking longer to generate and it tries to execute the MoveWindow function before the window is created so the window is not actually moved. I am not sure why this is a problem now because it was fine in earlier versions of the code.
For some reason the FindWindowByCaption function finds the window handle before the window actually exists.
I have the find window function in a loop that is supposed to try to execute until it finds the proper handle. The name changes for each graph.
IntPtr windowId = IntPtr.Zero;
while (windowId == IntPtr.Zero)//keeps trying to get the id until it has it
windowId = FindWindowByCaption(IntPtr.Zero, "p " + polyValue + " s " + (dataLocation + 1));
For some reason it finds the handle for the gnuplot graph before it actually is created and then it tries to run the MoveWindow function too soon, so that when the graph is actually generated it does not go to the right place.
Any suggestions would be helpful
Thanks,
-Jake

Related

Poor performance when running Unity as embedded window in application

I am trying to run a Unity application via the following code:
IntPtr parentHandle = Process.GetCurrentProcess().MainWindowHandle;
ProcessStartInfo procInfo = new ProcessStartInfo(_pathToUnityExe);
Logging.Log_Critical.Send("Starting process at " + _pathToUnityExe);
if (_useEmbeddedWindow)
{
procInfo.Arguments = "-parentHWND " + parentHandle + " " + Environment.CommandLine;
procInfo.UseShellExecute = true;
procInfo.CreateNoWindow = true;
}
_externalAppProcess = Process.Start(procInfo);
I've been noticing somewhat poor performance on the parent WPF app side, namely sluggish responsiveness and hitching with animations and media. This seems to occur whether the Unity app is loading a complex scene or a completely blank one.
Since the Unity app is being started through a process, I don't imagine there is threading/blocking problem, but I'm not sure what else it could be unless this is an issue in Unity.
Does anyone have thoughts or experience with this?
I'm open to other approaches as well if needed, I mainly just need to be able to control the Unity window's size and position. I'm mostly suspicious of the -parentHWND argument causing weird behavior on Unity's side.
However, this code doesn't seem to remove the window title bar on its own, is there a way to do that without using the -parentHWND argument?
procInfo.CreateNoWindow = true;
My solution ended up being to simply not use the embedded window flag when starting the Unity executable as a process. I then didn't need any arguments to be set in the StartProcessInfo object.
On the Unity side of things, I have a script that is in the initial scene which ensures the Unity application doesn't have the Windows title bar decorations. In that script's start override method I have:
Screen.fullScreen = true;

C# Find and handle child processes of a process

i need help finding the child processes (they are 2) of a process and handle them in order to set each of them foreground when needed.
The main process is Java Platform SE binary whose indicative name is javaw.
Using this code:
Process[] arrProcesses = Process.GetProcessesByName("javaw");
I can get the main process, so with:
IntPtr ipHwnd = arrProcesses[0].MainWindowHandle;
SetForegroundWindow(ipHwnd);
I can set it foreground.
My problem is that the handled process is the "last used" process...
Explaning better: on application bar of Windows I have 2 application(A, B) using java, if i click on A, when i use the code above, the application A gets foreground, insted, if i click on application B, with that code the B gets foreground.
What i want to do is decide which of two set foreground.
Anyone can help me?

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!

How to make form system modal using C#?

I need to show form as top level system-wide, e.g. over /all/ other windows on screen. I do realize this is usually /bad UI practice/, but I have very specific scenario in mind.
We intend to use normal Windows PCs for POS cash registrators. There is an option on the screen to open cash drawer. It would be rather bad for someone just to press something on a screen and get access to money when clerk isn't looking. So we equiped PCs with RFID readers and each clerk has his/her own RFID card which will be used for authentication.
I need however an mechanism to lock the computer (or make it unusable) when clerk goes away. Logging off seems too much of a nuisance.
Any ideas welcome.
LP,
Dejan
Well, after a day of trial and error I came to sort of solution.
It involves the following steps:
1.
When "Lock" button is pressed new (empty) /desktop/ is created.
Program is run in this desktop with full screen form and login procedure.
There is nothing else to switch to or run on this desktop.
2.
Task manager is disabled via registry.
Of course, somebody uninvited can still access the Ctrl-Alt-Delete menu, but there is nothing of particular harm he can do there.
3.
Alt-F4 and such are disabled.
4.
When authentication is made, program switches back to original desktop and everything proceeds as normal.
There is some P/Invoking required, of course.
If someone wants to do something similar, perhaps s/he will find my bare bones example helpful - link text
LP,
Dejan
I think you'll need to look into calling down to the Win32 API to achieve this.
You'll need to look into:
ShowWindow
and
SetWindowPos
and invoke them with code similar to the following (note this is pseudo-code):
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
static void ShowTopmost(Form frm)
{
ShowWindow(frm.Handle, SW_SHOWMAXIMIZED);
SetWindowPos(frm.Handle.ToInt32(), HWND_TOPMOST,
0, 0, [width of desktop], [height of desktop],
SWP_SHOWWINDOW);
}
Form has a TopMost property.
set Form.TopMost = true

.NET (C#): Getting child windows when you only have a process handle or PID?

Kind of a special case problem:
I start a process with System.Diagnostics.Process.Start(..)
The process opens a splash screen -- this splash screen becomes the main window.
The splash screen closes and the 'real' UI is shown. The main window (splash screen) is now invalid.
I still have the Process object, and I can query its handle, module, etc. But the main window handle is now invalid.
I need to get the process's UI (or UI handle) at this point. Assume I cannot change the behavior of the process to make this any easier (or saner).
I have looked around online but I'll admit I didn't look for more than an hour. Seemed like it should be somewhat trivial :-(
If you don't mind using the Windows API, you could use EnumWindowsProc, and check each of the handles that that turns up using GetWindowThreadProcessId (to see that it's in your process), and then maybe IsWindowVisible, GetWindowCaption and GetWindowTextLength to determine which hWnd in your process is the one you want.
Though if you haven't used those functions before that approach will be a real pain, so hopefully there's a simpler way.
#ageektrapped is on the right track, however FindWindow will not search child windows.
For that you will need to use FindWindowEx
Thank you for your answers. Thanks to you here, I figured out how to know if the main window of a process is in front or not:
N.B : of course this needs System.Diagnostic and System.Runtime.Interrop
public bool IsWindowActive(Int32 PID)
{
return IsWindowActive(Process.GetProcessById(PID));
}
[DllImport("user32.dll")]
private static extern
IntPtr GetForegroundWindow();
public bool IsWindowActive(Process proc)
{
proc.Refresh();
return proc.MainWindowHandle.Equals(GetForegroundWindow());
}
You may find that if you call .Refresh() that you get the new top-level window.
If you know the window's title, you can use the Win32 call, FindWindow, through P/Invoke.
You can find the signature here on pinvoke.net
From what I understand MainWindowHandle property of the process you are starting is not valid. If that's the case, you can use FindWindow function (from Win32 SDK) which returns the window handle you need. All you need is the class name of target application's main window. You can obtain it using Spy++ or Winspector. You also need to ensure you have the right window by checking that window's process id using GetWindowThreadProcessId.
At last, I have to say I am not an expert on Win32 and there might be a better solution for your case.
Use Process.GetProcessById(proc.Id); where proc was your splash screen.
Works for me.
Now, how do you get to main window properties in System.Windows.Forms to give it focus w/o using win32?
After all .net is supposed to be a one-stop solution - is it not?
Somewhere in the code, the "real" main window is created. You can just save the window handle at that time and then after the splash screen closes you can set Application.MainWindow to the real window.
The MainWindowHandle property is cached after it is first accessed which is why you don't see it changing even after the handle becomes invalid. GregUzelac's information is correct. Calling Proces.Refresh will causes the next call to Process.MainWindowHandle to re-do the logic to find a new main window handle. Michael's logic also works because the new Process doesn't have a cached version of the MainWindowHandle.

Categories

Resources