We help IT Professionals succeed at work.

Check out our new AWS podcast with Certified Expert, Phil Phillips! Listen to "How to Execute a Seamless AWS Migration" on EE or on your favorite podcast platform. Listen Now

x

Preventing the focus from ever leaving my program.

helpmealot
helpmealot asked
on
Medium Priority
461 Views
Last Modified: 2013-11-20
Hello,

I am writing a security program, and was wondering if anyone could tell me how to prevent the input focus from ever leaving my program.

The program is dialog based, it is not an SDI or MDI.  It is not full screen, and I'd really like to keep it that way.

I have tried setting a timer (50ms) and seeing if the active window is ever NOT mine, but, to my dismay, the timer messages aren't sent when my main window isn't active.

Also, for some reason, the following doesn't work:
void CLockoutDlg::OnKillFocus (CWnd* pNewWnd)
{ //CDialog::OnKillFocus(pNewWnd);
  SetFocus ();
}

I wouldn't mind hearing any methods for preventing task switching.  So far, I've managed to disable ALT-TAB, but the user can still click on another program behind mine, thereby bringing it into focus.

Anyone have any ideas?

Note: If it turns out that the solution is more complex than it seems, I'll increase the number of points.

Thanks.
HelpMeAlot!
Comment
Watch Question

Author

Commented:
Edited text of question

Commented:
Not an answer but maybe something to look at.  The MessageBox has a flag called SYSTEMMODAL that is doing what you want.  Here's the doc.

MB_SYSTEMMODAL   All applications are suspended until the user responds to the message box. System-modal message boxes are used to notify the user of serious, potentially damaging errors that require immediate attention and should be used sparingly.

If there was a way to apply it to a dialog instead of the message box (which is a dialog), then you have an answer!

Phillip

Author

Commented:
Hmm... There is something similar to the MB_SYSTEMMODAL, however it doesn't work in Windows 95 or NT, only in Windows 3.1.

Thanks for the help.

Author

Commented:
Adjusted points to 50

Commented:
OK, no one else is suggesting anything so how about another shot in the dark.

How about OnNcActivate?

Description:
The framework calls this member function when the nonclient area needs to be changed to indicate an active or inactive state. The default implementation draws the title bar and title-bar text in their active colors if bActive is TRUE and in their inactive colors if bActive is FALSE.

Suggestion:
If OnNcActivate is executed, I believe your application is going to know that another program is about to become active.  Then the key is to override the de-activation of your program.  OnNcMouseMove was a more kludgy idea.

Speaking of kludgy, how about making your application full screen without resizing, and forcing to be top-most using the SetWindowPos and wndTopMost as it's pWndInsertAfter.  Any other application or window will fall behind yours.

I said it was kludgy :)

Phillip





This question is anything else but easy.

Read the MFC knowledge base article PSS ID Number: Q125614.

Article is is not exactly encouraging but it does say

"ALT+TAB and ALT+ESC may be disabled while a particular application is
running if that application registers hotkeys for those combinations with
Register HotKey()."

While I have not tried this, you can go ahead and try

Another alteranative suggested though not recommended is as follows

" CTRL+ESC may disabled on a system-wide basis by replacing the NT Task
Manager. " 
It points on further to article number

ARTICLE-ID:Q89373
TITLE     :Replacing the Windows NT Task Manager

I got access to this articles by searching phrase "task switching" in VC++ 4.1 compiler
Help Query box. Iam responding from Home and do not VC 5.0 at home. I DID NOT use quotes in the search string.

If needed, I can post the article from my office machine

Author

Commented:
Phillip: Does OnNcActivate work with dialog based applications?  That's what I'm using, but from what the documentation says, it sounds like that function would only work with an SDI or MDI based application.

About the "make the window full-screen always on top" idea... :-), a better way would be appreciated, but I would really like to figure out how to prevent the focus from ever leaving just so I can at least do it again in the future if need be.  If we can't figure this out, that's just what I might resort to.

SamratAshok:  I have already disabled alt-tab, ctrl-esc etc etc... by tricking the computer into thinking a screen saver is running (long story, point is, it works great).  I am trying to figure out how to prevent the focus from leaving the program by the user clicking to the side of it to activate another application.

I seemed to have figured something out, that works, somewhat.  I have overridden the OnActivateApp function with the following:

void CLockoutDlg::OnActivateApp (BOOL bActive, HTASK hTask)
{ if (bActive == FALSE)
  { if (GetFocus () != this)
    { SetFocus ();           // Do all this to make sure.... :-)
      SetActiveWindow ();
      SetForegroundWindow ();
    }
  }

  //CDialog::OnActivateApp (bActive, hTask);
}

There is an interesting side effect however.  If I click outside the program, the focus will still leave my program but whatever I click on will not gain the focus.  This basically makes everything out of focus.

Is there a way I can modify the code to make my program stay in focus?

Thanks.

Author

Commented:
Edited text of question

Commented:
I'm not sure if OnNcActivate goes to a dialog.  Looking at class wizard, I didn't see an option for NcActivate appearing.  An alternative is to use the CFormView in a SDI application instead of the dialog.  Not much visual difference...

A third idea would be to implement a 'ScreenSaver' type approach to the application.  There are ways (not that I know of any great ones) that the screen saver would continue to run, a dialog box pops up and requests the password.  Once the password is corret, then the screen saver finishes and the background screen appears. ;)

Phillip

Commented:
You could make your dialog the size of the screen and a child of the desktop using the SetWindowPos API.  Additionally you can make it topmost (all using this api).

I don't know if you want it to be the whole screen.


Author

Commented:
Hi again,

I'm not really too keen on making the dialog box full screen.  Every dialog box looks bad full screen.  I would really like to just prevent the focus from being able to leave my application.

Any other ideas?
Thanks.

Author

Commented:
Hi again,

I'm not really too keen on making the dialog box full screen.  Every dialog box looks bad full screen.  I would really like to just prevent the focus from being able to leave my application.

Any other ideas?
Thanks.

Author

Commented:
Edited text of question

Commented:
Did you investigate using the CFormView and the OnNcActivate?  What where your impressions?

Phillip

Commented:
Yeah I agree full page dialogs don't always look too hot.    Perhaps a hookproc would do the trick.

WM_MOUSEMOVES -- if you get one and its out of bounds of your window, change the attributes to be within your window, then let the message through and it will correct itself.

Stuff like that.

Commented:
Another shot in the dark, is to create a new desktop and make your dialog a child of that desktop.  The user will have no where to go except for your dialog...

But you need to trap ctl-alt-del... YOu don't want some user terminating your process...
Commented:
Unlock this solution and get a sample of our free trial.
(No credit card required)
UNLOCK SOLUTION

Commented:
Sorry, those gRect's should be myRect's.

Commented:
HelpMeALot,

DS_SYSMODAL
 Creates a system-modal dialog box. This style causes the dialog box to have the WS_EX_TOPMOST style, but otherwise has no effect on the dialog box or the behavior of other windows in the system when the dialog box is displayed.

The new type of MB_SYSTEMMODAL that we used in Win3.1.  Try it here instead.  That might just do what you want!

Phillip


Commented:
You know, if I would just read the descriptions instead of assuming what it did, I could reduce these unnecessary postings.

Phillip

Author

Commented:
Musashi,

Thank you, your answer seems to work great.  One last thing, however, what class function would you recommend I put that code in?  I have tried putting it in the OnPaint function, but it has this weird side effect of occasionally stopping while I'm dragging the window around.  If I release the mouse button and then begin dragging the window around again, it will work fine.  It's almost like the window hits an invisible line which it cannot cross.

Then I tried putting it in the OnMouseMove function, but that has the unfortunate side effect of not working until the mouse is moved into the window.  This means that the user could simply keep the mouse out of the security box and continue doing whatever they wanted (of course, with my SetFocus and all that, it is very difficult to do anything behind the program).
Any ideas?

Also, try going to this address to find out about the SPI_SCREENSAVERRUNNING thing:
http://www.codeguru.com/misc/disable_alt_tab.shtml

But in the online documentation for Visual C++, it says that the SPI_SCREENSAVERRUNNING is not implemented at all in NT, sorry.

Thanks again!

Commented:
Helpmealot, you are welcome and I am glad it solves your problem.

I assume that your security app, like mine, gets triggered (at user logon, browser startup, etc) and basically needs to own the system to get the user's attention.  The user now needs to attend to the dialog box somehow to get his system back.  The user does NOT need to move the box anywhere at this point, therefore the box does not need the title bar (drag point).  If you create the dialog box without the title bar style, all of the (Microsoft) problems associated with ClipCursor() go away.  You lose the System menu this way, but only the "About" choice is possibly relevant, and you can put an "About" button right on the dialog box if you really need it. So, to answer your question, you should place the ClipCursor() code right in the function that causes the Dialog Box to appear.  If your app is a one-time event at logon, it should occur in OnInitDialog().  If your app lurks in the background waiting for the user to start up a browser (like mine does), the code should occur in whatever function gets triggered to make the Dialog Box automagically appear on the screen.

Here is how my code *basically* works:

Rect gFullScreenRect; // Global!!! (use to undo clipping later)
CMyDlgBox *gMyDlgBox;  // Global!!! (use to call functions

BOOL CMyApp::InitInstance()
    {
    [...]
    // my code here to install a callback function that
    // gets triggered when a browser gets started
    // (see DDEInitialize())
    CMyDlgBox dlg;
    gMyDlgBox = &dlg;
    [...]
    }

BOOL CMyDlgBox::OnInitDialog()
    {
    ::GetClipCursor (&gFullScreenRect); // save to restore later
    // Init Dialog Box as needed here, but make it hidden
    }

MyTriggerFunction (/*parms*/)
    {
    if (NowIsTheTimeToDisplayDialogBox)
        gMyDlgBox->DisplayDialogBox();
    }

CMyDlgBox::DisplayDialogBox()
    {
    // code to unhide Dialog Box here
    Rect DialogBoxRect;
    ::GetWindowRect (m_hwnd, &DialogBoxRect);
    ::ClipCursor    (&DialogBoxRect);  // lock user in Box
    }

CMyDlgBox::OnUserAgreesToProperBrowserUsage()
    {
    ::ClipCursor (&gFullScreenRect); // Restore mouse
    // Hide Dialog Box Code here (goes back underground)
    }

CMyDlgBox::OnUserDoesNotAgreeToProperBrowserUsage()
    {
    ::ClipCursor (&gFullScreenRect); // Restore mouse
    // code to tell Browser to Shut Down here
    // code to Hide Dialog Box here (goes back underground)
    }

Author

Commented:
Thank you, you have been most helpful.  This solves my problems completely.  As it turns out, my security program is not a triggered event, although I can see why that would be useful.  My program was intended to be used if, say, you wanted to go away from your computer for awhile, and not want anyone else touching it unless they knew the password.

Thank you very much!
Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a sample view!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.