Lock the MFC Screen - mfc

I have an MFC Application in which I have Wizards which is created using CPropertySheet. I have few controls and 'Next' button. When I press 'Next' button I will be doing various operations, On that time, I want to lock the screen so that user won't be able to click or do any operations on the screen. Please suggest me some way to handle this scenario?

Best would be to invoke a dialog box using DoModal with 'Close' disabled and no buttons to discard the dialog. In that dialogbox you can actually give out some meaningful messages about the progress or even show a progress bar. This way you effectively lock out the user from doing anything with the application and also give him some feedback, so that he knows some work is being done.

You can 'lock' a window by using EnableWindow. That's only a single window, mind you, the user can still interact with other windows/applications for which you haven't called that function.
HWND hWnd;
CWnd *pWnd;
// do stuff
// lock window
::EnableWindow(hWnd, FALSE);
// do stuff
//unlock window
::EnableWindow(hWnd, TRUE);
// lock window
pWnd->EnableWindow(FALSE);
// do stuff
// unlock window
pWnd->EnableWindow(TRUE);

Related

Is it possible to create an MDI window to the dialog-based window instead of the frame window?

I know you can create an MDI window to Frame window but what about dialog-based window is it possible to create MDI window to it too or it is just exclusive for Frame window only?
or Is it possible to create an MDI client window then create an MDI child Frame window to dialog-based window?
Can it be done? Probably. Is it a good idea? Probably not.
The main issue is that both MDI and dialogs want to control focus and keyboard handling.
You definitely need to use CreateDialog and not DialogBox to create the main window because you need control of the message loop. TranslateMDISysAccel and IsDialogMessage can help you a little bit but you probably need some custom handling that determines if the active/focused window is a MDI child frame or a normal dialog control and prioritize messages for MDI or the dialog. The most difficult being tabbing out of the MDI child frame window and back into the dialog. The last one you could work around by adding a custom key like F6 to set the focus back to the dialog.
Raymond Chen did a blog post series about dialogs, some of them about how you can write your own dialog class and/or custom dlgproc handling.
Even with full control of the message loop and some control over the dialog, you might still end up having to subclass the dialog and/or the MDI client window to handle specific messages.

SW_SHOWNOACTIVATE does not work if program is minimized by clicking the taskbar button

My application can receive a message from another application. If the app is minimized, I want to restore it to the previous state without giving focus to it.
I'm doing it by calling
::ShowWindow(hWnd, SW_SHOWNOACTIVATE);
It works well if the app was minimized using the Minimize button in the title bar, but if the app was minimized by clicking its button in the Windows task bar, then the app will receive focus.
Can this be fixed or worked around?
You could do the following HWND hwndForegroundWindow = GetForegroundWindow() before your ShowWindow function call. Afterwards you can restore the foreground window with SetForegroundWindow(hwndForegroundWindow). It depends on what you mean with focus though, foreground window and focus are something different (For element focus use GetFocus and SetFocus).

How to keep window inactive on simulated clicks?

I made a program in C++ that simulates clicks on an inactive window using:
PostMessage (z, WM_LBUTTONDOWN, 0,MAKELONG(t.left+x,t.top+y));
But whenever it makes a click it activates the window and the window moves to the top.
Is there a way I can make the window stay inactive or another way to click it?
I used SetWindowPos(z , HWND_BOTTOM,....) to make that window be at the bottom of the z-order list but it still activates.
EDIT: the window is a game console
Try switching from PostMessage to SendInput and see if you get the same effect.

Use dialog controls without stealing focus

I have a modeless CDialog that contains controls, some CButtons and a CScrollbar. The CDialog is parented off of an edit box that I want to keep focus at all times. The problem is that whenever the user uses the controls, clicking a button or on the scrollbar, the control steals focus from the edit box, causing both the parent window to draw without focus (grayed-out header bar), and causing the control to take all the keyboard input. Is there a way for the controls to respond to mouse actions but not steal focus?
The controls and the dialog are all created with WS_CHILD. The controls are parented off the dialog, and the dialog is parented off of the edit box.
I've tried setting focus back after the controls are used, but that causes the parent window to flicker as it loses and then regains focus. Basically I want something that works like a combo box, where the scroll bar can be clicked or dragged around, but keyboard input still goes to the dialog itself, not just the scroll bar, and the whole thing never loses focus.
I haven't done anything like this for a long time, so I'm sure there are a million little details, but I think the starting point is to override the handling of WM_MOUSEACTIVATE.
I am a little confused about child-parent relationship you described.
Can you explain what do you mean by:
The CDialog is parented off of an edit box that I want to keep focus at all times
Any window hosting other windows inside of the client area is a parent of those windows. It is impossible to create window without WS_CHILD that is contained by other window.
Therefore all dialog’s controls are children of this dialog. It is also possible that child window hosts another child window.
CDialog is just an MFC representation of a dialog window; the same applies to other controls. For example CButton is an MFC class that wraps handle of the window’s window that is predefined as window button control.
Dialog never has focus unless is empty (does not have any controls). If dialog contains even one control, this control always has focus.
What focus means is that any given window receives mouse and keyboard messages. Only one control can have focus at any given time. In order for scroll bar to process mouse click or keyboard to move slider, scroll bar must have focus; therefore some other control must give it up.
Combo box drop box (I think this is what you are referring to) is not a child of the dialog. It is a popup window that for the duration has keyboard focus and captures mouse. When it drops down, dialog is deactivated and once dropdown hides, dialog state is changed back to active hence focus never changes, it returns to the control that had focus when dialog was deactivated.
What you are trying to do is probably possible but it would require a lot of coding. Probably hooking messages would do the job but I think it would be going against the stream.

Hide main MFC window while modal dialog is active?

I have a native C++ MFC app. It has a main window based on CWnd, and user action can create a modal dialog. While the dialog is active, I want the main window to disappear, the dialog to be visible, and the main window's icon to remain in the task bar.
How can I accomplish this?
If I hide the main window (ShowWindow(SW_HIDE)), the task bar icon disappears. If I minimize the main window (SW_MINIMIZE), the icon remains. However, since the dialog is owned by the main window, this also hides the dialog.
After the dialog is created, clicking on the task bar icon makes the dialog visible. Naturally, I do not want to require the user to do this.
Even if I insert ShowWindow(SW_SHOW) in the dialog's OnInit handler, the dialog remains not visible. Spy++ shows that its visible bit is set, though. Same is true if I add SetWindowActive to OnInit.
I am not interested in changing the UI design. While the dialog is active, the user interacts only with it, and is not interested in anything in the main window. Therefore, the main window should disappear.
Using Windows VS2005 under WinXP32.
Well, in the block of code where you create the dialog and show it modal, you can do whatever you want to the main window of your app (show/hide) as long as you make the desktop window the parent of your dialog. Usually, the constructor for CDialog and derivatives takes a default argument of NULL for the parent window in which the framework ends up substituting AfxGetMainWnd(). Instead pass CWnd::GetDesktopWindow() as the parent of your dialog and then you should probably be able to hide your main window. However, you still might have a problem with the taskbar--but I'll let someone else give hints since I know nothing offhand about it.
In OnInitDialog, add following codes
//Set windows size zero, the windows disappear.
MoveWindow(0,0,0,0);
//If you want it invisible on taskbar. add following codes.
DWORD dwStyle = GetWindowLong(GetSafeHwnd(), GWL_EXSTYLE);
dwStyle &=~WS_EX_APPWINDOW;
dwStyle |= WS_EX_TOOLWINDOW;
SetWindowLong(GetSafeHwnd(), GWL_EXSTYLE, dwStyle);
You're fighting the OS. A modal dialog, by definition, disables but does not hide the "main" (parent) window. If you wanted another window, make a second one, but don't tell the OS to treat it as a modal dialog over the first window.
Perhaps you can resize the main window to a really small size and always keep it behind the modal dialog.