How to call AnimateWindow function to animate a external window/process - c#

I'm using the ShowWindow function to hide and show the main window of a external process. Now, I would like to use the AnimateWindow function before calling ShowWindow to animate that window when I show or hide it, however, as the documentation says on MSDN, the Animatewindow function will fail if the thread (on which I'm calling Animatewindow) does not own the window that I want to animate...
Is there any solution for this?, I can "own" the thread in some way to remotely execute the Animatewindow function on the UI thread of that external process, or any other simpler solution to do this?. At least I know the window handle, and I can retrieve the thread id of the thread that created that window with the GetWindowThreadProcessId function.
So, this can be done in any way?.
If this info could be helpful: the external process is a .NET executable (a WPF desktop app), and I want to animate its main window. That application has support for plugins in form of dll files that the application wil load at startup, so I'm calling ShowWindow and AnimateWindow within a class library, running my code in a new thread on which I run a message-loop (for other needs). I don't have access to the source-code of that application to implement any kind of Inter-process communication features like named pipes or shared memory blocks.
I'm asking for a solution using C# or VB.NET, does not matter.

As the documentation says, only the thread that owns the window can call AnimateWindow() on the window.
You can't take ownership of someone else's threads or windows. So, the only way to accomplish your goal is to inject code into the thread that owns the window.
Have your plugin DLL call GetWindowThreadProcessId() to get the ID of the thread that owns the window, and then call SetWindowsHookEx() to install a thread-specific message hook for that thread.
Then, you can send a custom message to the window, and your message hook handler will run in the context of the thread that owns the window, and can then call AnimateWindow() on the window.

Related

How to create a pop-up window that's independent of modal windows (.NET Windows Forms)

I'm trying to implement a 'step-by-step guide' feature in my Windows Forms application. The guides are just step-by-step descriptions of how to do common tasks. I'm intending for users to work through the instructions while reading the guides. The window in which they're displayed therefore needs to be accessible when modal dialogs are being displayed.
Is this possible? If so, how do I do it?
When a modal is displayed, you cannot interact with any other windows in the same UI thread. It is possible (but probably not the best idea in the world) to run two distinct UI threads in the same process in C#-- but you will have to be very careful to keep things stable. In the main thread, run your normal modal form. In the secondary thread, you can run a non-modal form at the same time-- just keep a dedicate windows message pump running in that thread until you are done with the UI, and then shut down the message pump and exit the thread.
Thanks for andLabs, Tim and IInspectable for giving me the information I needed to solve the problem. The following does what I needed:
Thread myFormThread = new Thread(delegate()
{
Application.Run(new MyForm());
});
myFormThread.SetApartmentState(ApartmentState.STA);
myFormThread.Start();
It works fine. Obviously you need to be careful to use myForm.BeginInvoke if you need to access the controls on myForm from an event-handler of the main form. You also need to help the user to manage access to the form as it can get lost behind other windows.

Can a thread own other handles?

http://msdn.microsoft.com/en-us/library/zyzhdc6b.aspx
Executes the specified delegate on the thread that owns the control's
underlying window handle.
According to the MSDN article, a thread can own other handles.
My best guess, is that the thread is some special super kernel object, with a handle that other handles can refer too?
like:
Handle | Thread-Handle-Reference
3201 | 20
4882 | 20
4827 | 7
In these terms, yes.
Basically, behind the scenes of the Windows GUI is a "message loop", which is a two-way communication between the Windows OS (which knows about the mouse, keyboard and other input hardware) and your program (which doesn't need to know the specifics, but does need to be responsive to user input within your app based on these input devices). There is a thread in your program (the main program execution thread, usually) that maintains this loop, listening for messages coming into the program from Windows, and parsing and passing messages to the various GUI controls and other code objects. This "GUI messaging thread" knows and maintains references to all the window handles of all GUI objects in your program; it must, because if it doesn't, it cannot pass messages to them and will not be listening for messages from them.
It is generally a bad idea to try to do something to a GUI control instance from outside the thread that is connected to the message loop. By doing so, it is possible for the control or sub-controls owned by the control to become detached from the message loop, or to never be attached in the first place. The "GUI message thread" then no longer knows about that control, and is no longer passing messages to or from it. Those controls become "rogue"; neither the program nor Windows can tell the control to move, redraw itself, or go away. The only thing Windows can do at that point to "control" the window is to shut down the process that owns it, thus terminating your entire program.
To avoid this, GUI controls have a special method "Invoke" (and an asynchronous cousin "BeginInvoke") designed to be used from outside the GUI messaging thread. These methods basically send a message from the window to itself through the Windows message loop that causes the main GUI thread to execute the delegate specified in the Invoke call. By doing so, any new GUI objects created within or as a result of that code will be known to the main GUI thread.
A custom thread can own handles when the handle is created in the custom thread. Actually i don't think that you can switch the owner of the handle. Sharing should be not possible too.
A thread can own multiple handles at once.
Every window is owned by the thread which created the window. Many window operations can only be performed on that thread, so it's important to have a mechanism to ensure that code is executed on the window's thread.
Forms.Invoke is one such mechanism.

Register to window messages using 'hwnd'

Assuming I have a valid hWnd to an active window (it was retrieved using ‘GetForegroundWindow’ or FindWindow, for example), can I register to windows message of this hWnd, from another application, of course? Is there any Win32 API for this, or a built-in C# method?
Example: In my console application I have a hWnd to the ‘Notepad’ window (running in the background). Can I register somehow to messages indicating the ‘Notepad’ window had moved, changed size, minimized, closed, etc.?
Thanks,
Elad
You have to inject a DLL into the process that owns the window. Use SetWindowsHookEx(), WH_CALLWNDPROC hook. You cannot write such a DLL using the C# language, the process won't have a CLR initialized and ready to run your code. Native code is required. Check this project.
If you just need to know about it moving or closing, then check out SetWinEventHook. You'll have to write a P/Invoke wrapper for this, since there's no equivalent in the .Net API. You can use this without needing to inject a DLL (use the WINEVENT_OUTOFCONTEXT
flag), so can keep everything in C# (and it also avoids the hassle of having to communicate between a separate DLL and your main process).
You'll likely want the events EVENT_OBJECT_LOCATIONCHANGE and EVENT_OBJECT_DESTROY. Note that you get these for all HWNDs on the thread you are listening to, so you'll need to filter by HWND in your callback.
Note that when you use WINEVENT_OUTOFCONTEXT, your own code will need to have a message loop running on the thread that calls SetWinEventHook. Also, the notifications that you receive are not delivered instantly, but with a slight delay (similar to PostMessage), but that may still be fast enough for your purposes that you can avoid doing an in-proc hook.
You can use the Accessible Event Watcher app (AccEvent) that's part of the Windows SDK to see what messages are available from notepad before you start writing code.

Open InternetExplorer COM object to do some automation using Wating from WPF app, but keep UI responsive. is this possible?

I have an app that runs a process which needs to open an internet explorer, go to an url, and do some stuff there, input some data, and return.
This usually takes a while (several pages that need to be filled, doesn't matter). The problem is, while this process is being done, the calling app (a standard wpf app) UI is unresponsive/frozen. When the process returns, i have some info that i need to set in one of the WPF app's objects
The main problem is that since IE needs to be called from within an STA thread, if I try to call it from within the dispatcher asynchronously or synchronously, for some reason the UI is blocked (i have tried with different DispatcherPriority-es but didn't get lucky).
If i start a new BackgroundWorker, that thread is in MTA mode (and i can't switch it back), so there's a problem and i have an exception
I'm really lost here, could anyone put some light into this? maybe what i want to do is simply not possible.
Have you tried creating your own background thread (not relying on BackgroundWorker), and set its ApartmentState to STA?

how to close a window from a different process

I have a c# application which I want to instruct to shutdown nicely, from a different process.
I also want to be able to ask it to open its main window.
I have a reference to its main window handle.
I know I can do it using elaborate schemes such as remoting or WCF.
the question is can I do it using simpler mechanisms such as window messages, or the OnClose event handlers of the window in the c# application
Pinvoke SendMessage() to send the WM_CLOSE message to the app's main window. Asking it to open its main window is probably going to be quite difficult, you cannot obtain the window handle until the window is created. Process.Start() would be the normal way.
A low cost alternative to WCF and superior to pinvoke is a named pipe or a socket to interface with the app. This requires being able to modify the source code of the app.
Process.CloseMainWindow
http://msdn.microsoft.com/en-us/library/system.diagnostics.process.closemainwindow.aspx
I think that you could probably use FindWindow to find the correct child window and then SendMessage or PostMessage to send a WM_CLOSE.
Here's another StackOverflow question that deals with doing this in C#.
Edit: Though as the other answer says in that question, you might be able to use Process.CloseMainWindow instead.
I would first make my target application "aware" of the fact that some other process might like to trigger its closing or opening of a window or doing any action. This should be implemented similar to calling any method on another process through the target app's api or public methods. ..unless you are trying to do something with 3rd party applications, I think you shouldn't attempt to directly send them messages to close or shutdown.

Categories

Resources