From HWND to control - c#

Im using the FindWindow method from user32.dll to find a window and get the handle, but is it possible to get the form control from the handle? and the use it like an ordinary form? Example:
int myhwnd = FindWindow(null, "MyWindow");
form myform = SomeMagic.GetFormFromHandle(myhwnd);
myform.Visible = false;
or do I have to continue to use the methods in user32.dll to send a message to the window?

If it's a managed window (you've created it with System.Windows.Forms, and it has inherited from System.Windows.Forms.Control) you can get a reference to the Control object with
Control.FromHandle(myIntPtr);
Then you just get the parent of the control until you get the form.
If not, you can't get a Control object, what you can do though is to is to create a NativeWindow, and assign the IntPtr handle to the object with the AssignHandle. That will at least give you some access to the WndProc, and similar, but that's it.

Have you tried Control.FromHandle()? Forms are (inherit from) Controls. If you hit a nested control, you'll have to search up through its parents until you hit your Form.
This assumes there actually is a Form somewhere, and you've just used the user32 methods to locate its HWND.

It's very difficult to wrap a Form class around Win32 window handle. There is no full fledged implementation provided by Microsoft. So, you have to use Native functions only to communicate with a given handle.

If the window belongs to your application you can use Control.FromHandle Method. Otherwise you will have to continue using win api. For example to hide the window you need to call ShowWindow Function.

Related

Retrieving Window object from Form

I was wondering if it's possible to get the Window object for the current form in C#?
For example:
Window window = theCurrentlyOpenedForm
Not very clear what you mean by Window object.
To reference the current form, you use the keyword "this".
If you mean the hWnd value you use for pinvoke, then you would use the this.Handle property.

C# HwndSource from Process.MainWindowHandle

I am trying to "hook" in to the messages of a window to detect a minimize/maximize. I've looked around, and think that the only/best solution to do this, is to hook into the messages of a window, and check for the WM_WINDOWPOSCHANGED message, and then check it's status.
I've run into a problem.
System.Windows.Interop.HwndSource source = System.Windows.Interop.HwndSource.FromHwnd(System.Diagnostics.Process.GetProcessesByName("notepad")[0].MainWindowHandle);
System.Windows.Interop.HwndSourceHook hook = new System.Windows.Interop.HwndSourceHook(WndProc);
source.AddHook(hook);
It will give me a "Object refrence not set to the instance of an object." error on "source.AddHook...". When breakpointing, it also becomes clear that the source variable is null. In other words: It fails to get the HwndSource on the first line.
I know that it's possible by using an "WindowInteropHelper", but that is when you have the actual window as a Windows.Window available, but in my situation I do not.
Any workarounds/solutions would be very much appreciated,
René Sackers
P.S. I am 100% sure that Notepad is running when the code is executed, and it manages to find it, and it's main window handle.
HwndSource and HwndSourceHook don't do what you are thinking. They only exist for interop between WPF and standard Win32 windows - in the same process. They can't be used for hooking the window procedure of a window in a different process.
HwndSource.FromHwnd() doesn't create a new HwndSource object it "Returns the HwndSource object of the specified window." If the hWnd doesn't have one it associated, FromHwnd() will return null. It would be like calling System.Windows.Forms.Control.FromHandle on the hWnd from notepad - which would return null as well since the notepad window isn't a WinForms control.
The way to hook another process's window procedure is to use SetWindowsHookEx. And for to hook another process, the code has to be written in C or C++.
You are misusing WindowInteropHelper. The documentation for the constructor states:
Initializes a new instance of the WindowInteropHelper class for a specified Windows Presentation Foundation (WPF) window.
The notepad window is not a WPF window which is why FromHwnd returns null.
In fact, I don't believe it could ever work for a window in a separate process, even if the other window was a WPF window.

WPF equivalent of Form.ShowDialog(IWin32Window)

In WPF we have Window.ShowDialog() which allows showing a modal dialog box.
In WinForms there is similar functionality but it also has an overload Form.ShowDialog(IWin32Window) which allows an IWin32Window owner to be passed in. That way the new dialog is not modal, and always maintains a z-order directly above its owner.
How would I get this same functionality using WPF?
Use the Owner property on a Window.
To expand on #Jonathan.Peppers's answer:
Say you had a Window you named FooWindow, and in BarWindow.cs you wanted to create and execute an instance. You can create a modal version of FooWindow as simple as this:
new FooWindow(){ Owner = this }.ShowDialog();
That would assume you didn't need a reference to you instance, obviously, but you get the idea?

How can you get a Form object from the desktop's handle?

I want to know if it is possible to acquire the desktop's Form. I have tried to get the hWnd from the desktop and use Form.FromHandle to get the form. But it always returns null. So I assume this is not possible; if it is possible can someone show me an example code.
Here is the code that did not work below:
hWnd = GetDesktopWindow();
desktop = Form.FromHandle(hWnd) as Form;
System.Diagnostics.Debugger.Break();
P.S. Can someone also explain what I did wrong here.
You can't do this because the desktop window isn't a Form. FromHandle() tries to find the managed Control (in this case a Form) that corresponds to the given window handle. Since no such Control exists, it returns null.

WPF OpenFileDialog with Win32 parent window; window is not regaining focus when closed

I have a c++ windows app calling into a c++/cli library, which is calling into a managed library. The managed library is calling OpenFileDialog.Show with a WPF window parent which is owned by the Win32 window. I haven't found a better way to do this, and all the resources I've read here and searching google and social.msdn recommend doing what I'm doing.
The dialog opens just fine, but when I hit the cancel button, for instance, the app loses focus completely. I'm not sure why it's happening, but I can't seem to make it stop. I've tried a number of different things to no avail.
If I just launch the OpenFileDialog without creating a WPF Window, I don't see the problem.
If I don't set the owner of the WPF Window, I don't see the problem. If I call OpenFileDialog.Show and don't pass the parent, but still create the WPF Window and set its owner, I still see the problem.
I am able to hack it to set the parent app window to foreground after it loses focus, but I would like to not have to.
I have uploaded a small example solution for my scenario that illustrates the problem:
http://dl.dropbox.com/u/26054523/MixedExample.zip
Any help would be appreciated.
Have you tried inverting the hosting scenario? Right now it sounds like you're going unmanaged->bridge->managed->WPF->Winforms. Maybe you could go ...managed->WinForms->WPF using ElementHost http://msdn.microsoft.com/en-us/library/ms742215.aspx
In that way, the WPF window would just be a child control of the WinForms app and that might work out better for focus switches. WinForms controls are not really meant to work directly with WPF apps so well, two different UI threading setups are being used as you've noted.
I know that this is an old post but I think that this is a common problem and I have a good answer. If you have a Win32 window parent window called ParentWindow and a WPF child window called WPFChild you can do this:
using System.Windows.Interop;
void OpenWindow()
{
WPFChildWindow WPFChild = new WPFChildWindow();
WindowInteropHelper helper = new WindowInteropHelper(WPFChild)
{
Owner = new NativeWindowWrapper(ParentWindow.Hwnd).Handle
};
bool? ret = _stepsForm.ShowDialog();
}
This will cause the child window to remain on top of the parent and function as a dialog. Keep in mind that the WPF window does not return a DialogResult but rather a nullable bool.
NativeWindow wrapper is a simple class that takes casts an int as an IntPtr. It's actually from a .net Excel ref edit project located here: How to code a .NET RefEdit ControlT

Categories

Resources