I am trying to determine a window control's visibility that has been hidden or enabled with CWnd::ShowWindow(). (or ::ShowWindow(hWnd,nCmdShow))
I cannot simply use ::IsWindowVisible(hWnd) as the control is on a tab sheet, which may itself be switched out, causing IsWindowVisible to return FALSE.
Is there a way to get the SW_SHOW/HIDE (or others) window status or do I need to use the retun value of ShowWindow() and reset accordingly?
edit:
as the control is enabled (or disabled) to show, but may not be currently visible, as the tab is switched ot, I would think that it's SW_SHOW status would remain the same, even if the window itself is not actually switched in. If I'm unrealistic in my expectations that that's fine.
So really I'm looking for 'can this window/control be shown'
Call GetWindowLong( handle, GWL_STYLE), check the returned value for WS_VISIBLE style presence.
Use GetWindowPlacement. It fills WINDOWPLACEMENT structure, which has field showCmd.
showCmd
Specifies the current show state of the window. This member can be one of the following values.
I would use GetWindowPlacement, however I am not sure if I understood what you want.
It fills in a WINDOWPLACEMENT structure and then use the showCmd member.
GetWindowPlacement() function will work only if the window is maximized or minimized. Otherwise, showCmd member will return SW_SHOWNORMAL also when window is hidden, as pointed out in this StackOverflow answer: WINDOWPLACEMENT's showCmd... always 1?
You can use the more straightforward boolean function IsWindowVisible() to get if the specified Window is in a visible state or not.
If it is a multi-tab dialog and not a control, then override as
void MyClass::OnShowWindow(BOOL bShow, UINT nStatus)
{
m_nCmdShow = bShow;
CDialog::OnShowWindow(bShow, nStatus);
}
In BEGIN_MESSAGE_MAP, add ON_WM_SHOWWINDOW().
m_nCmdShow now has the status if the window is SW_SHOW or SW_HIDE.
I don't know if there is a proper method for this task but I would try WindowFromPoint Function.
Remarks
The WindowFromPoint function does not retrieve a handle to a hidden or
disabled window, even if the point is
within the window. An application
should use the ChildWindowFromPoint
function for a nonrestrictive search.
For example I would convert control's corner coords into screen coords and then try to get it's handle from those points.
Related
I have a dialog containing controls (edits, combobox, etc...) some are visible and some or not.
What in a function, I want is looping on all controls and get the last shown control.
I want to add that when creating the dialog, I set the visibility to some controls as SW_HIDE and others to SW_SHOW.
What I did is using the ::IsWindowVisible, but returns false even if I set the visibility to SW_SHOW.
NB: the function is called just after the creation of the dialog, the dialog is not yet visible.
The control is not visible at the time you call the function, because the dialog that contains it is not visible. As per the documentation for the IsWindowVisible function:
If the specified window, its parent window, its parent's parent window, and so forth, have the WS_VISIBLE style, the return value is nonzero. Otherwise, the return value is zero.
This not only explains the behavior that you're seeing, but also suggests a possible solution. If you want to know whether a particular window has the WS_VISIBLE style bit set (and don't care about any of its ancestors), then just retrieve that window's styles and test for the presence of the WS_VISIBLE bit directly. For example:
LONG_PTR wndStyles = GetWindowLongPtr(hwndCtrl, GWL_STYLE);
bool isVisible = (wndStyles & WS_VISIBLE) == WS_VISIBLE;
That said, I don't really understand why you would need to do this. If your dialog-initialization code sets the visibility of controls, then you know what their visibility is. You don't need to retrieve it dynamically at run-time. In other words, this sounds like an X-Y problem. I suspect there is a better way to write your code so that this whole issue is a non-issue.
There are two methods to get window icon if i know his handle:
SendMessage(HWND,0x7F lParam, wParam)
and
GetClassLong(HWND, -14|-34)
But even if I get icon from window with GetClassLong i can't set new icon with SetClassLong, but successfully set new icon with SendMessage.
I need to know: why in some times work second get method, but doen't work first method. And why always from SendMessage(WN_SETICON) and doen't work SetClassLong(HWND, -14|-34, HICON)?
GetClassLong retrieves longs from the window class.
A window class is a blueprint for creating a window of a specified type, not the window itself.
It can contain quite a lot of defaults, like the default icon, and the default small icon.
But a window is only based on it, it can override everything.
Thus, setting the windowclass' icon does not modify any already created classes, you must send a message to the window instead.
And reading the windowclass-data gets you stale data, which might or might not still be relevant to the window.
As an aside, -14|-34 would be GCL_HICON|GCL_HICONSM, or -2, which does not actually make sense.
Explicitly say that you read with both indices one after the other.
-14 is GCL_HICON which is the (optional resource) icon for the class specified when its registered.
A specific window can subsequently specify its own icon (WM_SETICON), subsequent changes to
GCL_HICON won't affect it.
I also doubt you can attempt to pull GCL_HICON | GCL_HICONSM, if they were different what would the value be?
A few additional things:
1) Don't use magic numbers for Windows API constant values. Use WM_GETICON, not 0x7F. Use the GCL_ names as mentioned by the other answers.
2) You switched wParam and lParam in your SendMessage(). wParam comes first.
3) Don't use GetClassLong(); it is not 64-bit safe (and icon handles are pointers). Use GetClassLongPtr() instead. Also substitute GCLP_ for GCL_ in your named constants.
4) Don't try to replace | in your GetClassLong() with || or with an array of indices and expect that to work either. You don't have a choice but to make two calls.
Is there way to get the HWND handler of my window?
I'm using win32.
You could call GetActiveWindow to get the active control in your application, then repeatedly call GetParent on the returned handle until it returns NULL. The last valid handle you get should be the handle of your main window.
The easier way as someone else said is to store the returned value from CreateWindow somewhere.
It's probably good to understand why there is no simple way. It all boils down to "which window?". You'll likely have multiple windows visible on your screen, right now. For instance, the taskbar at the bottom of your screen is a window. even your own app typically has more than one. For instance, the "File Save" dialog is a window. Even the simple MessageBox is a window.
So, how do you identify which window you're talking about? The common answer is that you identify them by their HWND. So, to get the position of the "File Save" dialog window, you ask for the position associated with that HWND. Obviously, you can get any property that way, except the HWND itself ! It makes sense to ask the X/Y position of HWND(0x5e21), but it's stupid to ask which HWND belongs to HWND(0x5e21).
Now, it may happen that you have another more-or-less unique property and you want to get the HWND from that. For instance, you may have an X/Y position. In that case, WindowFromPoint(xy) will return the HWND at that position.
But the most common case is that you need to react to a Windows message for your window. In that case, you get the HWND of your window as the first argument of your WindowProc().
So, unless you tell us what unique information you do have, we can't tell you how to find the matching HWND.
Didn't you create your window via CreateWindow() or CreateWindowEx()? The CreateWindowEx() function and the CreateWindow() function both return the HWND of the newly created window.
Also, the operating system passes you the HWND of your window(s) via your window procedure. It's not a function that you call; it's a function that the operating system calls to let your application do any processing that's needed.
HWND button = CreateWindowEx(0, "BUTTON", ...);
SetFocus(button); // Button no get focus! :(
Also, I have other controls on my form that I am able to SetFocus() to.
Thanks, Martin
It has been FOREVER since I've had to do this, but...
Were this a dialog, I would tell you to send a WM_NEXTDLGCTL via PostMessage(). The default dialog item message handler would take care of the rest for you setting keyboard focus and selection activation. However, this is a different case if I read this correctly. You're creating both parent and child windows raw on the fly. If this is the case, SetFocus() to the parent window, and handle WM_SETFOCUS on the parent window by bringing it to top, then setting focus on the child window. WM_SETFOCUS, and WM_KILLFOCUS were designed to allow you to switch the 'activated' state of your controls, and most handle it for you (unless your window is an owner draw control or some such). But in a raw window, when your base parent window is sent the focus, you need to appropriately ensure the proper child has it if you're hosting any (think of it as managing your own 'dialog'). Again, normally this is done by the default dialog procedure for you if this were a dialog, but being raw windows you're kind of stuck managing it all yourself.
Though I can't imagine how, I hope that helped somewhat.
SetFocus is a function, not a procedure. Call it as a function and check its returned value. Either the retuned value is null because you made an error in the CreateWindowEx() call and "button" isn't a valid handle or it's a window not associated with your thread's message queue, or the return value is not null (it's now the prior focused window's handle) and you do have the focus (but are somehow failing to detect it).
Try setting the WS_TABSTOP style on the button.
If you create that button in respond of the WM_INITDIALOG message you should return FALSE to prevent dialog box procedure to change the focus.
How can I tell if my window is the current active window?
My current guess is to do GetForegroundWindow and compare the HWND with that of my window.
Is there a better method than that?
I'm using Win32 API / MFC.
Yes, that's the only way that I'm aware of.
But you have to handle the fact that GFW can return NULL. Typically, this happens when another desktop (e.g. the screen saver desktop) is active. Note that use of a saver password can affect whether a different desktop is used (this is windows version-dependent and I can't remember the details of how different versions work).
Also this code won't work properly in debug mode under Visual Studio, because you will get VS's window handle.
Other than that everything's peachy :-)
You can try to use WM_ACTIVATEAPP message.
First define a bool variable bool wActive = false, in the WndProc procedure, here is the next piece of code:
case WM_ACTIVATEAPP:
wActive = (bool)wParam;
return 0;
You can go to MSDN to find more information about WM_ACTIVATEAPP
Yes you are correct unless otherwise you want to check activewindow of every thread.
I assume that you mean the window which has the input focus when you say "active window"?
In that case, forget the GetForegroundWindow() API. That will return the topmost window - not always the window which has the input focus.
Use GetFocus() instead.
Yea, GetForgroundWindow() is a good way to check, behaves correctly even with a "Always on top" window aka HWND_TOPMOST .
Another way is with GetActiveWindow()
HWND temp = GetActiveWindow();
if (temp == hWnd) // Then your current window has focus
Alternatively the following messages report if the focus has changed
case WM_KILLFOCUS:
// windowHasFocus = false
break;
case WM_SETFOCUS:
// windowHasFocus = true;
break;