?
Solved

In MS ACCESS 2007, I lose control of ability to setfocus after using SetWindowPos

Posted on 2011-10-10
11
Medium Priority
?
531 Views
Last Modified: 2012-06-27
I have a login screen that I want to pop and it be ontop of everything  (we have one app that places itself on top, and if I dont do this, the login screen will never be seen)
The symptom is that once I use the SetWindowPos, I can no longer setfocus to my textbox. I can see how this might make sense, seeming that MS ACCESS form controls dont have handles.

Private Sub Form_Load()
    Me.txt_NTLogInUserId.SetFocus ' I have focus, verified that I do before adding setwindowpos
    Dim ScreenRect As RECT
    Me.Visible = False  
   ' SetTopMostWindow Me.hwnd, True 'Tried this setwindowpos from a seperate module

' Here I am trying to control it from the actual form load, I have tried different switches
   SetWindowPos Me.hwnd, HWND_TOP, glFormLeft, glFormTop, 0, 0, SWP_NOSIZE Or SWP_NOOWNERZORDER Or SWP_ASYNCWINDOWPOS

'Tried to use windows API "SETFOCUS" Aliased to putfocus to get focus to the window (which I do have, just was trying it...)
 '   PutFocus Me.hwnd

'tryed to no force the window back to access control by not making it topmost, again, just reaching for straws)
 '    SetTopMostWindow Me.hwnd, False

     Me.Visible = True

     Me.SetFocus

    Me.txt_NTLogInUserId.SetFocus
'If I start typing, it does not enter the text in the window, but if I hit return, it do activate the "Submit" button, so I do have the FORM WINDOW in focus, but NOT the    txt_NTLogInUserId

    On Error GoTo ErrorPoint
      txt_NTLogInPassword = ""                             'Initialize password textbox (txt_NTLogInPassword)
    lbl_NTLogIn2.Caption = ""
   txt_NTLogInUserId = ""                           '  Initialize username textbox (txt_NTLogInUserId)



ExitPoint:
    Exit Sub
ErrorPoint:
    MsgBox "The following error has occurred:" _
           & vbNewLine & "Error Number: " & Err.Number _
           & vbNewLine & "Error Description: " & Err.Description _
           , vbExclamation, "Unexpected Error"
    Resume ExitPoint
End Sub

0
Comment
Question by:Bruj
  • 6
  • 5
11 Comments
 
LVL 75
ID: 36943823
This might help ... I have a database loader app. When it first starts loading, a list is loaded with database names. Then more stuff happens, and finally the focus ends up on the list box.
Note that you can get the Form handle.


Call SetWindowPos(Form_frmLoader.hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE Or SWP_SHOWWINDOW)

' more code

The net result is ... the loader window is on top of ALL other windows that may be open, no matter what the app (Excel, Lotus Notes, etc).

Once the loaded is finished doing its thing ... I do this:

         ' restore the db app window to 'normal' positioning, so that other app windows can be on top ...
Call SetWindowPos(obj.hWndAccessApp, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE Or SWP_SHOWWINDOW)

mx
0
 
LVL 75
ID: 36943860
Oh ... you can get the handle of a Control: (not sure you need this ... I didn't)

hWnd of Controls
http://access.mvps.org/access/api/api0027.htm

NOTE:  The mvps.org site has been up and down lately. First time I tried it a minute ago, it was down ... no up (@10:51 10-10-2011 pdt).  Here is the code just in case:

(Q) How can I get handle to a control at runtime?

(A) Access controls are not standard VB controls.  They're drawn on the screen at runtime. As such, unlike VB controls, they do not have a unique hWnd.

    When an Access control on a form receives the focus, it becomes a true window and it's possible to retrieve it's handle by using the GetFocus API.   Note that because Access controls do not behave like VB controls, there's not a whole lot that we can do with the hWnd.

'********* Code Start *************
' This code was originally written by Dev Ashish.
' It is not to be altered or distributed,
' except as part of an application.
' You are free to use it in any application,
' provided the copyright notice is left unchanged.
'
' Code Courtesy of
' Dev Ashish
'
Private Declare Function apiGetFocus Lib "user32" _
        Alias "GetFocus" _
         () As Long
         
Function fhWnd(ctl As Control) As Long
    On Error Resume Next
    ctl.SetFocus
    If Err Then
        fhWnd = 0
    Else
        fhWnd = apiGetFocus
    End If
    On Error GoTo 0
End Function
'*********** Code End *************

mx
0
 

Author Comment

by:Bruj
ID: 36944550
Hey DatabaseMX,Regarding:
>>>
Call SetWindowPos(Form_frmLoader.hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE Or SWP_SHOWWINDOW)

' more code

The net result is ... the loader window is on top of ALL other windows that may be open, no matter what the app (Excel, Lotus Notes, etc).

Once the loaded is finished doing its thing ... I do this:

         ' restore the db app window to 'normal' positioning, so that other app windows can be on top ...
Call SetWindowPos(obj.hWndAccessApp, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE Or SWP_SHOWWINDOW)
>>>
This is pretty much what I do. The FORM is ON TOP. Thats not the problem. What is the issue (and it is a minor one really), is that the TEXTBOX no longer has FOCUS. You HAVE to MOUSE to it!
As you can see from my code, I am trying to FORCE setfocus back to it, but that does not seem to work after the setwindowspos is used. (I have seen that when I push my invalid password form and it returns back to the screen, then the cursur will be in the textbox.
I am going to try a bastardized tweak I just thought of to see it it will work in the same manner. That is to pop a static cody of the form for a few millisecs and then clear it and see if control flows back. Kludgy, but I will let you know if it work.
Any other ideas?

As far as the getfocus, I can get the handle, but ... well it does not respond to apiSetFocus.. kinda figured that though..

Thanks!
0
What is SQL Server and how does it work?

The purpose of this paper is to provide you background on SQL Server. It’s your self-study guide for learning fundamentals. It includes both the history of SQL and its technical basics. Concepts and definitions will form the solid foundation of your future DBA expertise.

 

Author Comment

by:Bruj
ID: 36944639
Well That seems to work, not graceful, a definite kludge... but..

Im gonna leave this question open for a day or so to see if anybody has any ideas how to work around this issue more gracefully.

Thnaks
0
 
LVL 75
ID: 36944763
Humm ... well ... the last thing I do after that initial API call is

Me.lstDb.SetFocus

and the list box has the focus.  User then makes a choice ... more code runs, then finally the last API call to return to normal.

Not sure why you get different results ...
0
 
LVL 75

Accepted Solution

by:
DatabaseMX (Joe Anderson - Microsoft MVP, Access and Data Platform) earned 2000 total points
ID: 36944806
OK ... sorry, what I posted is not quite right.  Forgot about some AutoExec code.  So ... this is what happens before I set focus to the list box - and the API stuff is below:

   'Hide the Application window
    Call ShowWindow(ByVal Application.hWndAccessApp, ByVal SW_HIDE)
   
   'The next two lines of code MUST appear in this order, such that the focus will go to lstDb on the Form.
   'Open Form on top of other modal windows.
    ''SetWindowPos Form_frmLoader.hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE Or SWP_SHOWWINDOW
    SetWindowPos Form_frmLoader.hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE Or SWP_SHOWWINDOW
   
   'Make Form the foreground window - open it in front of other application windows.
    SetForegroundWindow& (Form_frmLoader.hWnd)

====

   'Hide App window Peter's method ... makes form system modal
    Public Const SW_NORMAL = 1     ' Show Window
    Public Const SW_RESTORE = 9
    Public Const SWP_NOZORDER = &H4
    Public Const SWP_NOMOVE = &H2
    Public Const SWP_NOSIZE = &H1
    Public Const SWP_SHOWWINDOW = &H40
    Public Const HWND_TOP = 0
    Public Const HWND_TOPMOST = -1
    Public Const HWND_NOTOPMOST = -2
    Public Const SW_HIDE = 0       ' Hide window
    Public Declare Function SetForegroundWindow& Lib "user32" (ByVal hWnd As Long)
    Public Declare Function IsIconic Lib "user32" (ByVal hWnd As Long) As Long
    Public Declare Function ShowWindow Lib "user32" (ByVal hWnd As Long, ByVal nCmdShow As Long) As Long
    Public Declare Function SetWindowPos Lib "user32" (ByVal hWnd As Long, ByVal hWndInsertAfter As Long, ByVal X As Long, ByVal Y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long

====

mx
0
 

Author Comment

by:Bruj
ID: 36944994
yeah... I tried that... (as shown in code above) I have tried that, I tried to setfocus to the form and then the field...
I tried toggleing the enable and also the visibility for the textbox.
I tried to set not to top just trying to get it from under the "api control" (I dont know what else to call it.. It should not be under windows control, but full control is not back to ACCESS until I do the little form dance. (it is smooth an not user noticable , but not clean code wise.) Im thinksing maybe make a transparent form just for this. Then I can use the same thing if I run into similair isses with other forms (I am pushing them all to the topmost)

Thanks for your input and thoughts!  Just wish something would work. I cant seem to find anything on google either. I would think this would be a fairly common issue, or maybe I just ran into a bug.... Good thing I have a big can of RAID!
Once you clean out all of the steps I added to resolve the issue, it is very clean code. Not much there! and very very little before it as this is the first form to get shown. All I am doing before is dim statements and setting varibles...

Still looking though!
0
 

Author Comment

by:Bruj
ID: 36945039
Oh... Calling it TWICE! I would not think that the SWP_NOMOVE Or SWP_NOSIZE  flags would effect anything, but I am going to try it just as you have it!

Ill let you know
(Im not even hiding Access or anything at this point. I will probably add that next week)

I am NOT using     SetForegroundWindow& (Form_frmLoader.hWnd)
Again, I will add it as listed:)
Thanks!


0
 

Author Closing Comment

by:Bruj
ID: 36945160
Well! You have gone after those points and you are gonna get them!!!!
Works like a charm!
I did remove the "nomove" flag as I do want to move the window.

Here is the code!


Private Sub Form_Load()
    Dim ScreenRect As RECT
    Me.Visible = False
 
    SetWindowPos Me.hWnd, HWND_TOPMOST, glFormLeft, glFormTop, 0, 0, SWP_NOSIZE Or SWP_SHOWWINDOW
   
   
    '************************************************************ Changed 10/10/11 - Bruce Johnson
    'below changes made as per databaseMX from Experts Exchange to resolve issue with cursur not being in correct box
    SetWindowPos Me.hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE Or SWP_SHOWWINDOW
    SetForegroundWindow& (Me.hWnd)
     '************************************************************
     
    On Error GoTo ErrorPoint
    txt_NTLogInUserId = ""                           '  Initialize username textbox (txt_NTLogInUserId)
    txt_NTLogInPassword = ""                         'Initialize password textbox (txt_NTLogInPassword)
    lbl_NTLogIn2.Caption = "NT User Name and Password"
    txt_NTLogInUserId = ""                           '  Initialize username textbox (txt_NTLogInUserId)
    Me.txt_NTLogInUserId.SetFocus

ExitPoint:
    Exit Sub
ErrorPoint:
    MsgBox "The following error has occurred:" _
           & vbNewLine & "Error Number: " & Err.Number _
           & vbNewLine & "Error Description: " & Err.Description _
           , vbExclamation, "Unexpected Error"
    Resume ExitPoint
End Sub
[/code]

Thnks very much!
0
 

Author Comment

by:Bruj
ID: 36945176
Crud! I for got to put in one of the code tags....

Well! You have gone after those points and you are gonna get them!!!!
Works like a charm!
I did remove the "nomove" flag after I got it working, as I do want to move the window.

Here is the code!

Private Sub Form_Load()
    Dim ScreenRect As RECT
    Me.Visible = False
 
    SetWindowPos Me.hWnd, HWND_TOPMOST, glFormLeft, glFormTop, 0, 0, SWP_NOSIZE Or SWP_SHOWWINDOW
    
    
    '************************************************************ Changed 10/10/11 - Bruce Johnson
    'below changes made as per databaseMX from Experts Exchange to resolve issue with cursur not being in correct box
    SetWindowPos Me.hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE Or SWP_SHOWWINDOW
    SetForegroundWindow& (Me.hWnd)
     '************************************************************
     
    On Error GoTo ErrorPoint
    txt_NTLogInUserId = ""                           '  Initialize username textbox (txt_NTLogInUserId)
    txt_NTLogInPassword = ""                         'Initialize password textbox (txt_NTLogInPassword)
    lbl_NTLogIn2.Caption = "NT User Name and Password"
    txt_NTLogInUserId = ""                           '  Initialize username textbox (txt_NTLogInUserId)
    Me.txt_NTLogInUserId.SetFocus

ExitPoint:
    Exit Sub
ErrorPoint:
    MsgBox "The following error has occurred:" _
           & vbNewLine & "Error Number: " & Err.Number _
           & vbNewLine & "Error Description: " & Err.Description _
           , vbExclamation, "Unexpected Error"
    Resume ExitPoint
End Sub

Open in new window


Thnks very much!
0
 
LVL 75
ID: 36945183
Yeah ... sorry for the initial confusion. Forgot about my AutoExec startup code ... which does the initial API calls.

You are welcome ...

mx
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Instead of error trapping or hard-coding for non-updateable fields when using QODBC, let VBA automatically disable them when forms open. This way, users can view but not change the data. Part 1 explained how to use schema tables to do this. Part 2 h…
Microsoft Access has a limit of 255 columns in a single table; SQL Server allows tables with over 255 columns, but reading that data is not necessarily simple.  The final solution for this task involved creating a custom text parser and then reading…
The viewer will learn how to create two correlated normally distributed random variables in Excel, use a normal distribution to simulate the return on different levels of investment in each of the two funds over a period of ten years, and, create a …
Look below the covers at a subform control , and the form that is inside it. Explore properties and see how easy it is to aggregate, get statistics, and synchronize results for your data. A Microsoft Access subform is used to show relevant calcul…

807 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