Solved

Preventing the focus from ever leaving my program.

Posted on 1998-07-25
23
426 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!
0
Comment
Question by:helpmealot
  • 10
  • 6
  • 3
  • +2
23 Comments
 

Author Comment

by:helpmealot
ID: 1319737
Edited text of question
0
 
LVL 7

Expert Comment

by:psdavis
ID: 1319738
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

0
 

Author Comment

by:helpmealot
ID: 1319739
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.
0
 

Author Comment

by:helpmealot
ID: 1319740
Adjusted points to 50
0
 
LVL 7

Expert Comment

by:psdavis
ID: 1319741
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




0
 
LVL 2

Expert Comment

by:SamratAshok
ID: 1319742

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

0
 

Author Comment

by:helpmealot
ID: 1319743
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.
0
 

Author Comment

by:helpmealot
ID: 1319744
Edited text of question
0
 
LVL 7

Expert Comment

by:psdavis
ID: 1319745
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

0
 
LVL 2

Expert Comment

by:duneram
ID: 1319746
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.


0
 

Author Comment

by:helpmealot
ID: 1319747
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.
0
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 

Author Comment

by:helpmealot
ID: 1319748
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.
0
 

Author Comment

by:helpmealot
ID: 1319749
Edited text of question
0
 
LVL 7

Expert Comment

by:psdavis
ID: 1319750
Did you investigate using the CFormView and the OnNcActivate?  What where your impressions?

Phillip

0
 
LVL 2

Expert Comment

by:duneram
ID: 1319751
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.
0
 
LVL 2

Expert Comment

by:duneram
ID: 1319752
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...
0
 
LVL 1

Accepted Solution

by:
Musashi earned 70 total points
ID: 1319753
Helpmealot, with what you've already implemented, the following should solve your problem:

Rect myRect;  // may need to be global depending on your app

::GetWindowRect (m_hWnd, &gRect);// Get RECT of Dialog Box
BOOL result = ::ClipCursor(&gRect);// Confine mouse to Box

I too am working on a security program in a non-full screen dialog box.  I have a number of timers that work fine, but I have not yet implemented one of your features, perhaps you could show me how you did it, namely:

      Disable Alt-Tab, Ctrl-Esc, etc.

Hopefully you have a method that works in NT4.0SP3 as wells as Win95/98.  I have fooled with the SPI_SCREENSAVERRUNNING in NT, but have not gotten it to work yet.

Thanks.
Musashi



0
 
LVL 1

Expert Comment

by:Musashi
ID: 1319754
Sorry, those gRect's should be myRect's.
0
 
LVL 7

Expert Comment

by:psdavis
ID: 1319755
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


0
 
LVL 7

Expert Comment

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

Phillip

0
 

Author Comment

by:helpmealot
ID: 1319757
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!
0
 
LVL 1

Expert Comment

by:Musashi
ID: 1319758
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)
    }

0
 

Author Comment

by:helpmealot
ID: 1319759
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!
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Rewrite URL With Encoded Characters 6 64
Folder Comparison 12 52
maxBlock challenge 30 100
MaxSpan challenge 9 67
Introduction: Database storage, where is the exe actually on the disc? Playing a game selected randomly (how to generate random numbers).  Error trapping with try..catch to help the code run even if something goes wrong. Continuing from the seve…
Introduction: Dialogs (1) modal - maintaining the database. Continuing from the ninth article about sudoku.   You might have heard of modal and modeless dialogs.  Here with this Sudoku application will we use one of each type: a modal dialog …
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now