How to get the specific foreground window of the application - windows

Can I somehow get the specific foreground window of the application? For example, not the HWND of the whole Skype application, but some currently selected internal window of this application (maybe it's chat window's text edit).
Thanks in advance.

You can use EnumChildWindows.
Basically, it goes through the child windows of a given window until you find the one that has the characteristics you want. And - it is good to know that the "parent" of all application windows is HWND_DESKTOP
Here is code:
EnumChildWindows(HWND_PARENT,findChildWithClass,(LPARAM)"NetUIHWND");
And somewhere else:
BOOL CALLBACK findChildWithClass(HWND hwndTest,LPARAM lParam) {
char *pszClass = (char *)lParam;
char szClass[64];
GetClassName(hwndTest,szClass,64);
if ( strlen(szClass) < 1 ) return TRUE;
if ( 0 == _strnicmp(pszClass,szClass,min(strlen(pszClass),strlen(szClass))) ) {
hwndFoundChild = hwndTest;
return FALSE;
}
EnumChildWindows(hwndTest,findChildWithClass,lParam);
if ( hwndFoundChild )
return FALSE;
return TRUE;
}
So, the function "findChildWithClass" will be repeatedly called by Windows with the handle to the next child of the specified parent.
When the characteristics of that child window match what you are looking for, in this case class name, the function sets the value of a global static and returns FALSE to indicate the enumeration should stop.
You can get the class name of any window using Spy++, in this case, I used spy++ to find the name of the MS Word frame window. However, since the particular code will also look at every child of every child sent to it - you could have also found an "inner" window of MS Word using it. Also - you don't have to use class name, perhaps something else (window contents ?) is unique to the application you are trying to discover the window for ( Skype ? )

Related

Window is invisible, but IsWindow + IsWindowVisible + IsWindowEnabled return true and GetWindowRect returns plausible values

I'm iterating through all windows on the Windows desktop in order to allow disable patients select them easily in order to type into them.
I get all windows using
hw = GetDesktopWindow()
' It's first child is the 1st top level window
hw = GetWindow(hw, GW_CHILD)
'Now loop through all windows
etc.
There are many windows which are invisible or disabled, and I simply skip them because the user should not be able to select them. He wouldn't be able to type into them anyway.
Now I am confronted with a strange window.
Its title is "Groove Music".
It's a window from the Window Groove music app, and I can see it in the taskmanager.
I use the following API calls to check if this is a valid window that the user should be able to select:
IsWindow
IsWindowEnabled
IsWindowVisible
The declarations of these API calls are 100% perfect, I use them since years already.
And last, I even check its GetWindowRect values to see if it's in the screen at all.
And then I even check if it's a layered window (like an overlay that some apps use for non-clickable messages):
Public Function IsWindowLayered(ByVal uHwnd As Long) As Boolean
Dim lret&
lret = GetWindowLong(uHwnd, GWL_EXSTYLE)
If (lret And WS_EX_LAYERED) = WS_EX_LAYERED Then
IsWindowLayered = True
End If
End Function
It returns false.
The funny thing how is that the window is actually invisible.
So the user should not be able to select it.
Which function may I have missed to check if the window is actually visible?
Thank you!
Edit: It's also the calculator window (calc.exe) after I had opened it and closed it again.
Edit 2:
I also check for WS_VISIBLE like that, but even that return true for that window:
Public Function IsWindowVisibleEx(ByVal uHwnd As Long) As Boolean
Dim lret&
lret = GetWindowLong(uHwnd, GWL_STYLE)
If (lret And WS_VISIBLE) = WS_VISIBLE Then
IsWindowVisibleEx = True
End If
End Function
Edit 3: The taskmanager says that Calculator.exe and Groove have the status "Suspended".

Questions regarding GetWindowPlacement return data

I'm a bit unsure of the meaning of some of the return values from a call to the GetWindowPlacement() function, so I'd like your help, please.
I'll be calling this to obtain the normal dimensions of a hidden window.
First, where do the values of the showCmd field come from? In the Microsoft documentation of the return structure (WINDOWPLACEMENT structure, all the descriptions of the possible values use verbs/action words; e.g., "SW_MAXIMIZE: Maximizes the specified window", or "SW_SHOWNOACTIVATE: Displays a window in its most recent size and position."
I want to obtain the dimensions of the hidden window without unhiding/restoring it first, so with the verbs it seems that I would have to call SetWindowPlacement() with showCmd set to SW_SHOWNOACTIVATE before calling GetWindowPlacement. Is that correct?
So do I understand correctly that the primary (and perhaps only) way that field gets its various values is by an explicit call to SetWindowPlacement() somewhere?
My second question relates to the rcNormalPosition return values. Do those data include the window decorations, or are they client values?
Thank you for your time!
The meaning of the showCmd member of the WINDOWPLACEMENT struct is a bit confusing because Win32 is reusing the SW_* commands used by ShowWindow().
Luckily, the meaning is documented on the GetWindowPlacement() function.
If the window identified by the hWnd parameter is maximized, the
showCmd member is SW_SHOWMAXIMIZED. If the window is minimized,
showCmd is SW_SHOWMINIMIZED. Otherwise, it is SW_SHOWNORMAL.
So, based on which of those 3 values is returned, you can tell whether the window is currently maximized, minimized or, normal (restored). And if you'd like to know what the normal placement is, you can just use the rcNormalPosition member. You do not need to call SetWindowPlacement() at all.
However, heed the warning that GetWindowPlacement() returns workspace coordinates rather than screen coordinates, which differ based on taskbar position and size. This is not a problem if you are only using the coordinates returned by GetWindowPlacement() to call SetWindowPlacement(). Otherwise, you might have to find a way to convert from workspace to screen coordinates.
I found these 2 functions to work for me.
void MyDialog::LoadDialogPlacement()
{
static WINDOWPLACEMENT last_wp = {};
// Load last stored DB version
WINDOWPLACEMENT *wp = new WINDOWPLACEMENT;
GetStoredWindowPlacement(&wp);
if (memcmp((void *)&last_wp, (const void *)wp, sizeof(WINDOWPLACEMENT)) == 0) return;
memcpy((void *)&last_wp, (const void *)wp, sizeof(WINDOWPLACEMENT));
SetWindowPlacement(wp);
delete[] wp;
}
void MyDialog::SaveDialogPlacement()
{
static WINDOWPLACEMENT last_wp = {};
if (IsWindowVisible())
{
WINDOWPLACEMENT wp = {};
wp.length = sizeof(WINDOWPLACEMENT);
GetWindowPlacement(&wp);
if (memcmp((void *)&last_wp, (const void *)&wp, wp.length) == 0) return;
memcpy((void *)&last_wp, (const void *)&wp, wp.length);
StoreWindowPlacement(&wp);
}
}

Get the last ShowWindow state for a window in winapi

When you click a window in your taskbar (Windows users) it will retain it's last state - maximised or normal scalable window. I'm trying to do a similar thing, but programatically and without the window gaining focus (eg. becoming foreground and disturbing my current activity in another window).
Can I do that? Current window state can be obtained using this API call:
//Empty Window placement structure
WinDefExt.WINDOWPLACEMENT placement = new WinDefExt.WINDOWPLACEMENT();
//winapi call to external User32.dll file
UserExt.GetWindowPlacement(hwnd, placement);
//showCmd should be equal to one of the SW_ constants (here: https://msdn.microsoft.com/en-us/library/windows/desktop/ms633548%28v=vs.85%29.aspx)
placement.showCmd;
ShowWindow isn't a "state", it's an "action". There's no GetShowState command. You can infer a value from the current state of the window, but there's no way to find out the actual last value used with ShowWindow.
if (!IsWindowVisible(hWnd))
swState = SW_HIDE;
else
if (IsIconic(hWnd))
swState = SW_MINIMIZE;
else
if (IsZoomed(hWnd))
swState = SW_MAXIMIZE;
else
{
// not hidden, minimized or zoomed, so we are a normal visible window
// last ShowWindow flag could have been SW_RESTORE, SW_SHOW, SW_SHOWNA, etc
// no way to tell
swState = SW_SHOW;
}

Implementing multiple dialogs with similar processing

We have multiple dialogs in our MFC program that are very similar. Each one of these dialogs contain similar controls (i.e., they all contain a name, date, address, etc). Because of this, we've had to code out the display code multiple times for the windows despite the fact that the processing of these controls is identical. I'm looking for suggestions on how to change up our guis so that i have to only do the processing at one spot and not have to do it multiple times.
My thought was to have a class that would do the processing and pass pointers to the controls to display to that class, though i feel that is not a very good OO design.
Thoughts?
Create a base class derived from CDialog (say CMyDlgBase), place all your common functions there and derive your dialog classes from CMyDlgBase instead of CDialog.
You can now call the functions in CMyDlgBase as if they were declared directly in your dialog classes.
EDIT sample code to validate an item common to dialogs (CDlg1 and CDlg2 are derived from CMyDlgBase), error checking code not included:
BOOL CMyDlgBase::ValidateName(UINT nID)
{ CString ss;
CEdit *pEdit = GetDlgItem(nID);
pEdit->GetWindowText(ss);
if (ss.Find(_T("A")) < 0) // some kind of validation
{ MessageBox(_T("Name should contain the character 'A'"));
pEdit->SetFocus();
return FALSE;
}
return TRUE;
}
CDlg1::OnOK()
{ if (!ValidateName(IDC_DLG1_NAME)) // resource id value = 101
return;
CDialog::OnOK(); // This will close the dialog and DoModal will return.
}
CDlg2::OnOK()
{ if (!ValidateName(IDC_DLG2_NAME)) // resource id value = 102
return;
CDialog::OnOK(); // This will close the dialog and DoModal will return.
}

WinApi, hide cursor inside window client area

I want hide cursor inside window client area without borders and title bar (it is simple opengl application). So, function
ShowCursor(FALSE);
is not suitable. After some searching the winapi i find this solution:
//when create window class for application window
WNDCLASSEX WndClass;
//...
BYTE CursorMaskAND[] = { 0xFF };
BYTE CursorMaskXOR[] = { 0x00 };
WndClass.hCursor = CreateCursor(NULL, 0,0,1,1, CursorMaskAND, CursorMaskXOR);
Is this a good way to solve this typical task? What way is the best?
MSDN says that you can set the WNDCLASSEX hCursor field to NULL, in which case you must explicitly set the cursor in your window procedure (which means handling the WM_SETCURSOR message). For example:
if (Msg == WM_SETCURSOR && LOWORD(lParam) == HTCLIENT)
{
SetCursor(NULL);
return TRUE;
}
// Remainder of window procedure code
Checking for HTCLIENT ensures that the cursor is only hidden in the client area, and that the window frame and caption will use the correct cursors.
The SetCursor() call you're using doesn't take a BOOL - it takes an HCURSOR. So you're calling SetCursor( NULL ) which means "hide that cursor". What I found in the old days on Windows is that this is video driver dependent and many drivers don't respect it. The most consistent way to handle this is to make a transparent cursor resource in your app, and return a handle to that cursor in the WM_SETCURSOR message from your main window.
I found that first setting hCursor to NULL:
wc.hCursor = NULL;
and then setting the cursor to NULL:
SetCursor(NULL);
will make it disappear.
From MSDN, I read that the application will set its own cursor by default if one is not defined in hCursor. That's what the first line of code is doing.
Then, after the application sets its own cursor, I mess with it with the second line of code. Or at least, I think that's what happens.

Resources