Iterating any window open and having top z order on environment, how can I verify window is not any pop up(tool tip pop up, combo pop up, etc )?
using WinApi method:
HWND WINAPI GetWindow(
_In_ HWND hWnd,
_In_ UINT uCmd
);
for (IntPtr childWindow = WinAPI.GetWindow(WinAPI.GetDesktopWindow(), WinAPI.GetWindow_Cmd.GW_CHILD);
childWindow != IntPtr.Zero;
childWindow = WinAPI.GetWindow(childWindow, WinAPI.GetWindow_Cmd.GW_HWNDNEXT))
{
//todo if
}
Thanks for all those who comment, You lead me to solution. Here is a method i test it with Spy++.
please if you have tips/ideas, i will appreciate.
public const long WS_POPUP = 0x80000000L;
public static bool IsWindowPopup(IntPtr hHandle)
{
long style = WinAPI.GetWindowLongPtr(hHandle, -16);
bool isPopup = ((style & WS_POPUP) != 0);
return isPopup;
}
Related
I want to set the foreground of a window in Visual Studio.
What i've tried:
When i have 2 windows "docked" side by side i can't set the foreground of a window under the mouse in VS.
I'm using GetCursorPos and WindowFromPoint which usually works for standard windows. I also tried to use EnumChildWindows from pinvoke.net (sample code 2 -https://www.pinvoke.net/default.aspx/user32.enumchildwindows) but it returns 0 when i pass the WindowFromPoint or MainWindowHandle of the process.
I assume it's not a typical child window technically or something else that i don't understand?
public static IntPtr GetProcessMainWindowHandle()
{
Process process = null;
if (GetCursorPos(out Point point))
{
IntPtr hWnd = WindowFromPoint(point);
GetWindowThreadProcessId(hWnd, out uint pid);
process = Process.GetProcessById((int)pid);
}
return process.MainWindowHandle;
}
public static IntPtr GetHandle()
{
IntPtr hWnd = IntPtr.Zero;
if (GetCursorPos(out Point point))
{
hWnd = WindowFromPoint(point);
}
return hWnd;
}
As mentioned in the comments from Lars, it could be a WPF window.
I can see that i can only get the handle for the parent window as described for WPF behaviour but i get still null with the following code. Maybe i have something wrong? (Any hint would be great.)
public static void GetWPFObject(IntPtr handle)
{
HwndSource source = HwndSource.FromHwnd(handle) as HwndSource;
}
My problem is not being able to get the a flash child control inside Internet Explorer but I can do it within a webbrowser control. The webbrowser control is buggy with the flash object, so I need to do the work through Internet explorer and automate flash testing.
Below is the code for the webbrowser control which I am trying to replicate in IE 11.
private async Task<bool> clickCoorindate(Point point)
{
IntPtr handle = null;
Process[] processes = Process.GetProcessesByName("iexplore");
foreach (Process p in processes)
{
handle = p.MainWindowHandle;
}
//webBrowser1.Focus();
int x = point.X;
int y = point.Y;
// IntPtr handle = webBrowser1.Handle;
StringBuilder className = new StringBuilder(100);
while (className.ToString() != "MacromediaFlashPlayerActiveX")
{
handle = GetWindow(handle, 5); // Get a handle to the child window
GetClassName(handle, className, className.Capacity);
}
IntPtr lParam = (IntPtr)((y << 16) | x); // The coordinates
IntPtr wParam = IntPtr.Zero; // Additional parameters for the click (e.g. Ctrl)
const uint downCode = 0x201; // Left click down code
const uint upCode = 0x202; // Left click up code
const uint moveCode = 0x200;
SendMessage(handle, downCode, wParam, lParam); // Mouse button down
SendMessage(handle, upCode, wParam, lParam); // Mouse button up
Thread.Sleep(20);
SendMessage(handle, downCode, wParam, lParam); // Mouse button down
SendMessage(handle, upCode, wParam, lParam); // Mouse button up
return true;
}
When I use Spy++, the Flash object window is a child window of the IE window.
When I pass the IE mainwindow handle in the code above, it never finds the MacromediaFlashPlayerActiveX handle.
When testing this code in webbrowser control and passing the webbrowser control handle, it finds the flash object fine.
Any idea how to make this work with IE?
Someone asked a question similar here and found the solution, but unfortunately did not add it.
private static bool EnumWindow(IntPtr handle, IntPtr pointer) doesn't run
The solution comment from link above:
I found the solution :). Basically the iexplorer process had defined many different windows handlers. I had to use the EnumThreadWindows and get all the Windows Handler for that process. After that, just look for the Class Name I was interested in.
I have handles to the main form of the Winforms application, and the window that I'm trying to check (which may or may not be part of the application). I've tried iterating using GetParent, but it doesn't seem to work.
What I'm essentially trying to do is detect a modal window (such as a MsgBox), get it's controls, and send a button click message if the controls fulfill some requirements (like be a Button).
Now, while I can detect if a modal window is open, and can find the currently focused window, I have no idea if the currently focused window is the modal window that was detected. Essentially, if I open a model window and then open up a completely different program, it tries to find the controls of that external program.
The code is below:
if (pF.Visible && !pF.CanFocus) //Is a Modal Window
{
///TODO: Check if currently active window is a child of the main window
///Gets information of currently active window
string currentActiveWindow = GetActiveWindowTitle();
IntPtr currentActiveHandle = GetActiveWindowHandle();
///Gets 'children' or controls of currently active window
var hwndChild = EnumAllWindows(currentActiveHandle);
///Iterate over all child windows
foreach (IntPtr element in hwndChild) {
const int nChars = 256;
StringBuilder Buff = new StringBuilder(nChars);
IntPtr handle = GetForegroundWindow();
string windowElementType = GetWindowClassName(element);
///Check if the "windows" are buttons
if (GetWindowText(element, Buff, nChars) > 0 && windowElementType=="Button")
{
string windowElement = Buff.ToString();
if (windowElement.ToLower()=="ok")
{
///Send Button click message
const int BM_CLICK = 0x00F5;
SendMessage(element, BM_CLICK, IntPtr.Zero, IntPtr.Zero);
}
}
}
}
A convenience function (C++) to determine whether two windows identified by their HWND belong to the same process would look like this:
bool OwnedBySameProcess(HWND hWnd1, HWND hWnd2) {
if ( ::IsWindow(hWnd1) && ::IsWindow(hWnd2) ) {
DWORD procId1 = 0x0;
DWORD procId2 = 0x0;
::GetWindowThreadProcessId(hWnd1, &procId1);
::GetWindowThreadProcessId(hWnd2, &procId2);
return ( procId1 == procId2 );
}
return false;
}
The GetWindowThreadProcessId is not subject to UIPI (User Interface Privilege Isolation) and will always succeed given valid input. The return values are IDs and do not need to be cleaned up.
Translated to C#:
public class Helper
{
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool IsWindow(IntPtr hWnd);
[DllImport("user32.dll")]
static extern uint GetWindowThreadProcessId(IntPtr hWnd,
out uint lpdwProcessId);
public static bool OwnedBySameProcess(IntPtr hWnd1, IntPtr hWnd2)
{
if ( !IsWindow(hWnd1) )
throw new ArgumentException("hWnd1");
if ( !IsWindow(hWnd2) )
throw new ArgumentException("hWnd2");
uint procId1 = 0;
GetWindowThreadProcessId(hWnd1, out procId1);
uint procId2 = 0;
GetWindowThreadProcessId(hWnd2, out procId2);
return ( procId1 == procId2 );
}
}
In one of my programs I need to test if the user is currently focusing the desktop/shell window. Currently I'm using GetShellWindow() from user32.dll and compare the result to GetForegroundWindow().
This approach is working until someone changes the desktop wallpaper, but as soon as the wallpaper is changed the handle from GetShellWindow() doesn't match the one from GetForegroundWindow() anymore and I don't quite get why that is. (OS: Windows 7 32bit)
Is there a better approach to check if the desktop is focused? Preferably one that won't be broken if the user changes the wallpaper?
EDIT: I designed a workaround: I'm testing the handle to have a child of class "SHELLDLL_DefView". If it has, the desktop is on focus. Whilst it's working at my PC that doesn't mean it will work all the timeā¦
The thing changed a little bit since there are slideshows as wallpaper available in Windows 7.
You are right with WorkerW, but this works only with wallpaper is set to slideshow effect.
When there is set the wallpaper mode to slideshow, you have to search for a window of class WorkerW and check the children, whether there is a SHELLDLL_DefView.
If there is no slideshow, you can use the good old GetShellWindow().
I had the same problem some months ago and I wrote a function for getting the right window. Unfortunately I can't find it. But the following should work. Only the Win32 Imports are missing:
public enum DesktopWindow
{
ProgMan,
SHELLDLL_DefViewParent,
SHELLDLL_DefView,
SysListView32
}
public static IntPtr GetDesktopWindow(DesktopWindow desktopWindow)
{
IntPtr _ProgMan = GetShellWindow();
IntPtr _SHELLDLL_DefViewParent = _ProgMan;
IntPtr _SHELLDLL_DefView = FindWindowEx(_ProgMan, IntPtr.Zero, "SHELLDLL_DefView", null);
IntPtr _SysListView32 = FindWindowEx(_SHELLDLL_DefView, IntPtr.Zero, "SysListView32", "FolderView");
if (_SHELLDLL_DefView == IntPtr.Zero)
{
EnumWindows((hwnd, lParam) =>
{
if (GetClassName(hwnd) == "WorkerW")
{
IntPtr child = FindWindowEx(hwnd, IntPtr.Zero, "SHELLDLL_DefView", null);
if (child != IntPtr.Zero)
{
_SHELLDLL_DefViewParent = hwnd;
_SHELLDLL_DefView = child;
_SysListView32 = FindWindowEx(child, IntPtr.Zero, "SysListView32", "FolderView"); ;
return false;
}
}
return true;
}, IntPtr.Zero);
}
switch (desktopWindow)
{
case DesktopWindow.ProgMan:
return _ProgMan;
case DesktopWindow.SHELLDLL_DefViewParent:
return _SHELLDLL_DefViewParent;
case DesktopWindow.SHELLDLL_DefView:
return _SHELLDLL_DefView;
case DesktopWindow.SysListView32:
return _SysListView32;
default:
return IntPtr.Zero;
}
}
In your case you would call GetDesktopWindow(DesktopWindow.SHELLDLL_DefViewParent); to get the top-level window for checking whether it is the foreground window.
Here is a workaround that uses GetClassName() to detect if the desktop is active:
When Windows first starts, the desktop's Class is "Progman"
After changing the wallpaper, the desktop's Class will be "WorkerW"
You can test against these to see if the desktop is focused.
[DllImport("user32.dll")]
static extern int GetForegroundWindow();
[DllImport("user32.dll")]
static extern int GetClassName(int hWnd, StringBuilder lpClassName, int nMaxCount);
public void GetActiveWindow() {
const int maxChars = 256;
int handle = 0;
StringBuilder className = new StringBuilder(maxChars);
handle = GetForegroundWindow();
if (GetClassName(handle, className, maxChars) > 0) {
string cName = className.ToString();
if (cName == "Progman" || cName == "WorkerW") {
// desktop is active
} else {
// desktop is not active
}
}
}
I'm writing a sample application that is both GDI and WPF. I have a WPF window that has a button with a click handler with the following body:
this.DialogResult = true;
This closes the WPF dialog as it should. However, when closing this dialog, there is no "fade" effect on Windows 7/Vista. Alternatively, using a GDI window, the fade works. I'm either doing something wrong or this is the default behavior when closing WPF windows. Additionally, using the X button to close performs the same unwanted behaviour.
Ideally, I'd like both types of windows to close with the same style. Has anyone else encountered this? Is this something easily fixed for all of my WPF windows?
EDIT: Ok so I noticed something very interesting. When the window to closed is not over the parent window (e.g. it's moved to a different monitor) and closed, the usual fade fires correctly! However, if the window to close is over the parent window, no fade occurs. Lovely!
If your window is borderless,
<Window
xmlns="blahblahblah"
AllowsTransparency="True" WindowStyle="None">
you can likely get away with making a fade animation to transparent, and write a close event handler that calls the animation then completes the close. If the window has a border, I am pretty sure the border will stay there and will look wierd.
I've come up with a solution, although I think it's still quite the hack to actually have fade working. I also tested with a pure WPF application and the window will still only fade when not overlapping its parent window. If anyone has a better solution than the code below, please let me know!
public class WindowBase : Window
{
private bool hasFadeCompleted = false;
protected override void OnClosing(CancelEventArgs e)
{
if (this.hasFadeCompleted)
{
base.OnClosing(e);
return;
}
e.Cancel = true;
var hWnd = new WindowInteropHelper(this).Handle;
User32.AnimateWindow(hWnd, 1, AnimateWindowFlags.AW_BLEND | AnimateWindowFlags.AW_HIDE);
Task.Factory.StartNew(() =>
{
this.Dispatcher.Invoke(new Action(() =>
{
this.hasFadeCompleted = true;
this.Close();
}), DispatcherPriority.Normal);
});
}
}
public static class User32
{
[DllImport("user32.dll")]
public static extern bool AnimateWindow(IntPtr hWnd, int time, uint flags);
}
public static class AnimateWindowFlags
{
public const uint AW_HOR_POSITIVE = 0x00000001;
public const uint AW_HOR_NEGATIVE = 0x00000002;
public const uint AW_VER_POSITIVE = 0x00000004;
public const uint AW_VER_NEGATIVE = 0x00000008;
public const uint AW_CENTER = 0x00000010;
public const uint AW_HIDE = 0x00010000;
public const uint AW_ACTIVATE = 0x00020000;
public const uint AW_SLIDE = 0x00040000;
public const uint AW_BLEND = 0x00080000;
}
I'm still surprised that this hasn't been an issue for anyone else.