Take a look at this picture:
This is how i got the handle of the window enclosed by black box.
Process[] processes = Process.GetProcessesByName("TopazChat");
foreach (Process p in processes)
{
MessageBox.Show(p.MainWindowHandle.ToString());
List<IntPtr> test = GetChildWindows(p.MainWindowHandle);
foreach (IntPtr IGotIt in test)
{
MessageBox.Show("I got the child windows");
}
}
My question is: how to get the handle of the windows that was enclosed by red box?
and is there something wrong with my approach?
any suggestions? I just use that approach because it is the only one that is familiar to me..
That other window is another a top-level window in the same process that implements one of the visible windows in the app. This is an old Delphi 7 app which implements a hidden top-level window that is outside the visible window hierarchy. That hidden window is the one you have found, highlighted in black, with class name TApplication.
If I were you I would p/invoke a call to EnumWindows to get all the top level windows which will include the visible main windows for that app. This would be implemented in a very similar way to your GetChildWindows method.
Related
I want to keep my app's window in front of another programs's window.
My app is created with WPF, I set owner with another window's hwnd like this:
// this: my wpf window
WindowInteropHelper helper = new WindowInteropHelper(this);
//The hwnd is handle of window that other program I want to follow
helper.Owner = new IntPtr(hwnd);
Everything is perfect, but I can't select text with mouse within RichEditComponent of the window (the hwnd window).
Any idea to fix this?
Don't know other program write with which language,maybe c++. Handle of other program's window obtained with windows api "FindWindowEx".
If your other program is a Winforms program, you need to add a reference to
System.Windows.Forms.Integration.dll
and add a call to ElementHost.EnableModelessKeyboardInterop(Window window) like shown below:
WindowInteropHelper helper = new WindowInteropHelper(this);
helper.Owner = new IntPtr(hwnd);
ElementHost.EnableModelessKeyboardInterop(this);
because apparently Winforms and WPF have different ways of handling text input (and therefore also affecting text selection - more specific, copy & paste of selected text - as well).
Other than that, the issue might be the HWND pointer - how do you obtain it?
e.g. this is how you can obtain the main window handle by specifying a process name:
Process process = Process.GetProcessesByName("...")[0];
IntPtr hwnd = process.MainWindowHandle;
I had resolved the question by detect Mouse drag event use global hook. When drag start,cancel set owner,and then,when drag finished,set owner with the follow window again.
Use MouseKeyHook to detect global mouse drag event.
https://www.nuget.org/packages/MouseKeyHook
Thanks #Thomas Flinkow again,for your help!
I'm new to C# and TestStack.White,
The application that I'm testing (trying ....) is a WPF application.
I have a window that has a popup child-window, and I want to close it.
I have no AutomationId to those popup windows :(
I have the MainWindow and MainWindow.HasPopup() returns true :)
But I don't know to to get a list of (TestStack.White.UIItems.WindowItems.Window) from my MainWindow so I can do:
Foreach _windItem ... _windItem .Close();
Thanks in advance !.
EyalS.
There should be a Popup property on the Window. The HasPopup is actually checking the popup property. I think a better way to do this would be to ask the application for all it's windows and then close all of them except the one that has a property that designates it as your main window. Here is an example in White for how to do this.
Application application = Application.Launch("Path to Application");
foreach (Window window in application.GetWindows())
{
if (window.AutomationElement.Current.AutomationId == "MainWindow") continue;
window.Close();
}
I also suggest looking into FlaUI because FlaUI's APIs make it alot easier to get at the information in the AutomationElement without having to add dependencies to the underlying framework that White is wrapping. Plus White has alot of properties which don't work the way you would think they would like the Popup property for instance.
I want to display a MessageBox that is modal to just a single form, and allows other top level windows on the thread to remain active. WinForms disables all windows on the current thread, whether displaying a custom modal form or using the MessageBox class.
I've tried a number of different approaches to solving the problem, including re-enabling any other top level windows (using the Win32 EnableWindow function) and p/invoking the native MessageBox function. Both of these approaches work, but leave keyboard shortcuts inoperable, including tab to move between controls, escape to cancel an open menu and most importantly menu shortcut keys.
I can make menu shortcut keys work by installing a keyboard hook when I display the MessageBox and then directly calling ProcessCmdKey on the active form, but other keyboard shortcuts still don't work. I guess I could press on and add more hacks to make these other cases work, but I was wondering if there was a better way.
Note, this is not about being non-blocking, but about not disabling all windows on the current thread. It happens that the solution may be similar, however.
The basic problem you are battling here is that MessageBox.Show() pumps its own message loop to make itself modal. This message loop is built into Windows and is thoroughly unaware of what the Winforms message loop looks like. So anything special that Winforms does in its message loop just won't happen when you use MessageBox. Which is keyboard handling: detecting mnemonics, implementing navigation and calling methods like ProcessCmdKey() so that a form can implement its own shortcut keystrokes. Not normally a problem since it is supposed to be modal and ignore user input.
The only practical way to revive this is to display the message box on its own thread. This is formally allowed in the winapi, the owner of a window can be a window owned by another thread. But that's a rule that Microsoft did not implement when they added the code to .NET 2.0 that detects threading mistakes. Working around that code requires an IWin32Window as the message box owner that is not also a Control.
Add a new class to your project and paste this code:
using System;
using System.Threading;
using System.Windows.Forms;
public class NonModalMessageBox : IWin32Window {
public NonModalMessageBox(Form owner, Action<IWin32Window> display) {
this.handle = owner.Handle;
var t = new Thread(new ThreadStart(() => display(this)));
t.SetApartmentState(ApartmentState.STA);
t.Start();
}
public IntPtr Handle {
get { return handle; }
}
private IntPtr handle;
}
And use it like this:
new NonModalMessageBox(this, (owner) => {
MessageBox.Show(owner, "Testing", "Non-modal");
});
Where this the Form object that should be disabled while the message box is displayed. There's little I can do to make you feel better about this hack, if the FUD is too overpowering then you really do need to re-implement MessageBox with your own Form class so you can use Show() instead of ShowDialog(). It has been done.
You could pass a reference to the Form, set Enabled property to false when you open the dialog, and set it back to true when the dialog closes.
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
I have an .NET application that always starts itself with its border style to 'None', as it is supposed to be an full-screen application with a fixed resolution.
However, i would like to add the window border (Fixed3D) to this window when the application starts so that I am able to move it around my desktop.
My first idea was to have a tray app running, monitoring event messages, and somehow change the window style when this specific application starts. However, I am not sure if this will work and how to do this.
Anyone that can point me in the right direction?
You should probably look into using the SetWindowLongPtr function of user32.dll.
You'll need to get the window handle associated with the application's main window. This could potentially be done using:
Process[] processes = Process.GetProcesses();
foreach (Process process in processes) {
if (process.MainModule.FileName == #"C:\Program Files\App\app.exe") {
IntPtr handle = process.MainWindowHandle;
// Call method to change window style here.
break;
}
}
You can then set the appropriate styles using the GWL_STYLE constant (value -16 in decimal) and SetWindowLongPtr.
Changing the Style of the Main Window should help you find the styles that you need.
You can inherit a class from a main class in the source code, and change its properties in the appropriate events. hat would be no modification of the source code, though it would be a different application.