MFC - Minimize main MDI window only - c++

I have main MDI window and have custom CWnd derived window which I create dynamically run-time. I want to keep that window on the screen even when main MDI window is minimized but I dont want to have top-most window. I have tried use WS_EX_CONTROLPARENT | WS_EX_APPWINDOW styles, set parent to NULL and set owner to GetDesktopWindow() but nothing works.
Any ideas how I should do that?

When window is minimized, it takes down with it all of its child and owned windows.
This code creates a regular (not topmost) window which is not hidden when the main frame is minimized:
HWND hWnd = ::CreateWindow(L"button", L"test", WS_CAPTION|WS_VISIBLE,
100, 100, 200, 200, GetDesktopWindow(), 0, 0, 0);

Related

How to get the size and position of a button control of a dialog in a resource file?

I am trying to programmatically design a dialog menu that resizes based on the resolution of the screen, and I am able to get the size and positions of the dialog using the dialog's nameID following this question:
Get Dialog Size as defined in resource file
However, I'm having trouble trying to obtain the size and positions of the button controls within the dialog. Here's an example of what the dialog might look like in the resource file:
IDD_DLG DIALOG 0, 0, 300, 200
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP
BEGIN
DEFPUSHBUTTON "OK",IDOK,30,46,42,18
PUSHBUTTON "Cancel",IDCANCEL,145,46,42,18
END
I can obtain the dialog's size and positions using its nameID, i.e. IDD_DLG, but is it possible to obtain the same thing for the DEFPUSHBUTTON or PUSHBUTTON programmatically?
If so, how? Thanks!
MFC allows automatic repositioning/resizing of child buttons. In resource property page, click on dialog button, go to dynamic control section, enable dynamic resizing/move for each button.
To find the coordinates of the button, relative to top-left of dialog client window:
Use GetWindowRect to find the buttons rectangle in screen coordinates. Then convert the screen coordinates to client coordinates:
CMyDialog::OnInitDialog()
{
CDialog::OnInitDialog();
CRect rc;
CWnd *wnd = GetDlgItem(IDOK);
wnd->GetWindowRect(&rc);
ScreenToClient(rc);
...
//move/resize rc
wnd->SetWindowPos(NULL, rc.left, rc.top, rc.Width(), rc.Height(), SWP_SHOWWINDOW);
}

Maximized WS_POPUP window goes in front of the taskbar

I'm creating a window in C++ with that code:
HWnd = CreateWindow(wc.lpszClassName,
"myapp",
WS_POPUP |WS_VISIBLE,
10, 10, 1000, 800, 0, 0, hInst, NULL);
It appears as I want but when I maximize it with like this:
ShowWindow(hwnd, SW_SHOWMAXIMIZED);
then it's like a fullscreen window so that the taskbar is hidden.
I think it's because it is a POPUP window but this is like I want it to appear.
Do I need to create my own maximize function or is there a parameter to avoid that ?
Thanks
You can add WS_CAPTION | WS_SYSMENU | WS_MAXIMIZEBOX style.
If you want your window to be without caption then you will need to adjust window size manually to fit into desktop work area that you can query using SystemParametersInfo specifying SPI_GETWORKAREA flag.
This is a feature where the Taskbar will get out of your full-screen application:
If you want to create a fullscreen window that covers the taskbar, just create a fullscreen window and the taskbar will automatically get out of the way.
I’ve seen people hunt for the taskbar window and then do a ShowWindow(hwndTaskbar, SW_HIDE) on it. This is nuts for many reasons.
Don’t do any of this messing with the taskbar. Just create your fullscreen window and let the taskbar do its thing automatically.
Since this is Stackoverflow, a combination of Wikipedia and Reddit, i want this relevant information saved for the next guy asking this question.

Qt widget on top of other non qt window

I'm developing a plugin for a commercial program (I can't change it) that I use in Windows operating system. In this plugin I create a Qt Widget and when in the main program a button is clicked, the qt widget appears.
My problem is that the widget appears under the main program window, while I want it on top of it. It can be stay Always on top, if necessary.
Qt::WindowStaysOnTopHint does not seems to work here because I have no Qt parents.
I've found a way to put it on top, following the Qt wiki, and I've created a method that I call after widget constructor:
void RadiationPatternWidget::setWindowTopMost()
{
#ifdef Q_WS_WIN32
HWND hwnd = winId();
DWORD exStyle = ::GetWindowLong(hwnd, GWL_EXSTYLE);
DWORD style = ::GetWindowLong(hwnd, GWL_STYLE);
HWND parent = NULL;
if (parentWidget()) {
parent = parentWidget()->winId();
}
exStyle |= WS_EX_TOPMOST;
HWND newHwnd = ::CreateWindowEx(exStyle, L"#32770", NULL, style,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
parent, NULL, qWinAppInst(), NULL);
create(newHwnd, true, true);
#endif // Q_WS_WIN32
}
Then I call it after constructor:
m_pxRadiationPatternWidget = new RadiationPatternWidget();
m_pxRadiationPatternWidget->setWindowTopMost();
Now it stays on top, but I've some problem:
Inside the widget I use some QPushButton cannot and if window is raised they are not clickable. clicked() signals are not captured and button image does not change when I click on it with mouse.
Inside the widget I use a derived QGLWidget derived class. When I put it on top this widget is black, while if I don't call the method it works well.
How can I raise on top che QWidget correctly?
Before using your hack, check if widget->window()->raise() wouldn't work.
Using the window class "#32770" is an error. You need to use the same window class that Qt is already using for your window.
You need to retrieve the class used by Qt for the existing window, and only then create a new window with the same class.

Child window created by CreateEx() overlapped by sibling windows

I tried to create a child window using:
CreateWindowEx( NULL, NULL, "MyChild", WS_CHILD | WS_VISIBLE | WS_BORDER, 300, 300, 400, 200, hParentWnd, NULL, NULL );
where the parent HWND hParentWnd has many other child windows already. However, this created a child window hiding behind all the siblings. Windows Spy++ shows that it is on top (first) of the z-order among the child windows of hParentWnd. I have tried all different win32 commands including SetWindowPos(), BringWindowToTop(), SetForegroundWindow(), SetFocus(), SetActiveWindow(), SendMessage(WM_ACTIVATE, 0, 0), etc., but none brings it from behind the siblings. When I replaced WS_CHILD by WS_OVERLAPPEDWINDOW in the CreateWindowEx() command, the created non-child window has no problem showing as the topmost foreground active window. So what must I do to get the child window to the top from behind the siblings?
Thanks a million.
z/0
It is quite explicit in the MSDN article for CreateWindowEx():
If the created window is a child window, its default position is at the bottom of the Z-order. If the created window is a top-level window, its default position is at the top of the Z-order.
You'll need to move it to the top of the Z-order with SetWindowPos().

Win32: Bring a window to top

I have a Windows program which has two 2 windows in it:
hwnd (main interface)
hwnd2 (toplevel window, no parent, created by hwnd)
When I double click on hwnd, I need hwnd2 to pop up and show some data, so I use this function to bring hwnd2 to top:
BringWindowToTop(hwnd2);
hwnd2 is brought to top, but there is one thing odd. When I click on hwnd2 again, hwnd (main interface) pops itself up again automatically.
I tried to use the following function to solve this problem, but non of them works.
SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
//doesn't work
BringWindowToTop(hwnd2); //This is the function brings hwnd2 to top
SetForegroundWindow(hwnd2); //doesn't work
SetWindowPos(hwnd2, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
//doesn't work
SetWindowPos(hwnd2, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
// hwnd2 "always" on top, not what I want
SetActiveWindow(hwnd2); // doesn't work too (for replying to Magnus Skog, thanks)
SwitchToThisWindow(hwnd2, TRUE);// got the same problem with BringWindowToTop function
SwitchToThisWindow(hwnd2, FALSE);
How could I solve this problem?
Thanks in advance.
(for replying to aJ, hwnd2 doesn't have parent because it needs to be a toplevel window so it can be in front/back of other windows)
(hwnd2 is a media player which is composed of several windows, one of the windows is for video dispaly, two other trackbar controls for progress bar and volume bar, one Toolbar control for control panel.)
(There is one this might help, no matter which window I click on hwnd2, hwnd pops up automatically as loong as "the mouse is on top of hwnd in Z-order", including menu bar and non-client area, etc.)
(This media player is writen in Direct Show. I use IVideoWindow::put_Owner to put video window as the video owner, Direct Show internally creates a sub-video window as a child of the video window. Except for this sub-video window which I can't see the source code, I don't see any thing suspicious in hwnd2.)
I found the reason, which is because of Direct Show. I use multithread to execute it, and then the problem's solved. But...why??
This problem can be resolved by using PostMessage (rather than SendMessage).
try this,it is said coming from M$
HWND hCurWnd = ::GetForegroundWindow();
DWORD dwMyID = ::GetCurrentThreadId();
DWORD dwCurID = ::GetWindowThreadProcessId(hCurWnd, NULL);
::AttachThreadInput(dwCurID, dwMyID, TRUE);
::SetWindowPos(m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
::SetWindowPos(m_hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE);
::SetForegroundWindow(m_hWnd);
::SetFocus(m_hWnd);
::SetActiveWindow(m_hWnd);
::AttachThreadInput(dwCurID, dwMyID, FALSE);
In order to bring a window to top, you should get your window handle,thread handle, the windows thread handle who is in foreground
then we attach our thread to foreground window thread and get input by AttachThreadInput, then we set our window z order
to topmost and then restore its z order to normal, call SetForegroundWindow,SetFocus,SetActiveWindow to make sure our window is brought to top and is active and have focus
then deattach the input queue from the old foreground window thread, make our thread the only one who capture the input events
So why should We call AttachThreadInput, it is because
SetFocus sets the keyboard focus to the specified window. The window must be
attached to the calling thread's message queue.
What does AttachThreadInput do?
The AttachThreadInput function can be used to allow a set of threads
to share the same input state. By sharing input state, the threads
share their concept of the active window. By doing this, one thread
can always activate another thread's window. This function is also
useful for sharing focus state, mouse capture state, keyboard state,
and window Z-order state among windows created by different threads
whose input state is shared.
We use SetWindowPos to bring the windows to topmost and show the window if the window is hidding by using SWP_HIDEWINDOW
SetWindowPos function changes the size, position, and Z order of a
child, pop-up, or top-level window. These windows are ordered
according to their appearance on the screen. The topmost window
receives the highest rank and is the first window in the Z order
If your problem is your window is also minimized , you should add one line code to the end
ShowWindow(m_hWnd, SW_RESTORE);
Both work great:
::SetForegroundWindow(wnd)
or
::SetWindowPos(m_hWnd, // handle to window
HWND_TOPMOST, // placement-order handle
0, // horizontal position
0, // vertical position
0, // width
0, // height
SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE// window-positioning options
);
But remember that the last one sets the window always on top.
After many tries and errors.I found following solution to this problem:
SendMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0); // restore the minimize window
SetForegroundWindow(hwnd);
SetActiveWindow(hwnd);
SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE);
//redraw to prevent the window blank.
RedrawWindow(hwnd, NULL, 0, RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN );
The hwnd is your windows HWND . Please do not just copy and paste. You also need use GetLastError to check api error after every api call.
I have confirm following result on my win7:
Can restore minimize window and no error return.
If the window already top, the window title will blink and no error return.
If the window has closed, it will return the error "0x578 Invalid window handle."
It can bring the window to the top on all not top-most window and no error return.(For example it will behind the top-most taskmanager)
It do not make the window top-most. The user can make other window on top of it.
SwitchToThisWindow works best for me.
Have you tried SetActiveWindow()?
This will restore an app if minimized and bring it to the front:
ShowWindow(hWnd, SW_SHOW);
SetForegroundWindow(hWnd);
//work great!
Var
WndHandle:HWND;
begin
WndHandle :=FindWindowEx(0,0,nil,'Calculator');
PostMessage(WndHandle,WM_SHOWWINDOW,SW_RESTORE,0);
SetForegroundWindow(WndHandle);
end;