Cover Form Controls - Hide Form Operations?

misscrf

Registered User.
Local time
Today, 19:13
Joined
Nov 1, 2004
Messages
158
This application is Access 2010, with a SQL backend.

I have a form, which has a tab control, with 2 pages. 1 page has 1 listbox and the other has 2 listboxes. I use some code, on change of the tab control, to determine the active page, and set the listbox(es) row source(s) for the one(s) on the active page, and clear it out on the inactive page. This takes a sec and the listboxes look yucky while this is happening.

To prevent the user from seeing this, I made a text box, with a colored background and the control source ="Please Wait One Moment..." with like 48 font. On load of the form, this textbox is visible = false. On click of the tab control, the text box is to be made visible, and it is big enough to cover then entire tab control. It does cover the tab control, but I can still see the listboxes through the text box. The text box has a back color and is not transparent. I tried right-clicking the listboxes in design view and choosing Position - Send to Back, and right-clicking the textbox and choosing Position - Send to Front.

This doesn't seem to work. Is anyone familiar with this issue? Figuring someone has tried a trick like this.

The meat of my code is all functioning properly, for this on change of the tab control. I have this code at the beginning:

Code:
DoCmd.Hourglass True
Me.txtPleaseWait.Visible = True
Me.Repaint
Application.Echo False
Debug.Print Me.txtPleaseWait.Visible

and this at the end:

Code:
Application.Echo True               
Me.txtPleaseWait.Visible = False    
Me.Repaint                          
Debug.Print Me.txtPleaseWait.Visible
DoCmd.Hourglass False               
Debug.Print "got to end of resting form state"
Does that make sense?

I researched a bit, and found that different controls have a different zorder (inherent position). It seems the listbox will always go in front of a text box, no matter what. So I changed this "please wait" control to a listbox, with a value list, and just this one value (the caption). It still shows the other listboxes through it. :banghead:

Is there a better way to handle this? A simpler way?

Thank you.
 
There are some things that you really shouldn't need to use. echo false is one of them.

I think you need to stop asking questions. Post a stripped down database (with sample data in Access) and say what you are trying to do.

edited due to reading fail ¬_¬
 
Last edited:
I had very little input into your other lengthy thread.
Just looking at this on its own

1. The 3 debug statements should be removed
2. The first repaint isn't needed. The second may not be either.

Unlike static, I can see the point of the echo statements and at times I've used a similar approach.
BUT I can't make any sense of your comments about listbox vs textbox

Overall, I think you are overthinking all of this as the basic idea isn't complicated
Agree with static about uploading.
 
So let me clear up some things. The rowsource and requery steps is working. That is not the issue here.

I have 2 pages on a tab control, and each page has 1 or 2 listboxes. when a user switches from one page to the other, I set the row source of the listboxes on the active page, and clear the rowsource on the inactive one. During that process, the form looks funky, like the listboxes are just hanging there. I wanted to cover them with a message. To accomplish that I tried a textbox, sized bigger than the tab control. Found that won't work. Then I tried making it a listbox. It's a dummy control. I'm just setting it to say "Please wait" in really big font, with a colored background, so you can't see the tab control, while I'm doing background operations. Then, when I finish, I make that control visible = false again and we can see the tab control, on the right page, with the right listbox(es) set to their appropriate row source.

Make sense?

I don't want to have more listboxes loaded with a row source, than I need. They both pull a view that brings in info from a linked sql server, to this backend's sql server, in a view. That means I'm querying against a lot of records and I want to cut down on the performance hit.
 
If you clear a list because the page changes you have to fill again if the page becomes active again. ?
As far as database performance is concerned, local memory isn't really the issue. Data traversing the network is, so leave the lists filled.
 
Just to make clear that I understood what you meant originally, please see attached 3 screenshots of a form that by chance I am currently using.

Screenshot 1: shows the form and a empty subform
Screenshot 2: The Run Analysis button is clicked,the subform & most of the form controls are hidden & a textbox message is shown in a very large font
Screenshot 3: When the analysis is completed, the message is hidden, the populated subform & the form controls are made visible again

Amazingly similar to your setup wouldn't you say... and it works

Here is the relevant part of the button click code:

Code:
The next 2 lines show/hide various controls & subform using the controlTag property
            ShowControls True, "I"
            ShowControls False, "F", "B", "X"
            DoCmd.Hourglass True
            
            DoEvents
            
            Application.Echo False
            
           ..other code here to run analysis ...                                     
                        
            DoCmd.Hourglass False
            
            'requery subform
            Me.fsubJSONStructure.Requery            
                   
            Application.Echo True
            
            'undo show/hide changes
            ShowControls False, "I"
            ShowControls True, "F", "B"
            DoEvents

Can you see why I'm saying it should be simple to implement?
 

Attachments

  • Capture1.PNG
    Capture1.PNG
    78.5 KB · Views: 295
  • Capture2.PNG
    Capture2.PNG
    61.4 KB · Views: 287
  • Capture3.jpg
    Capture3.jpg
    103.5 KB · Views: 299
Code:
Dim aiListHeight as Integer

aiListHeight = Me.Listbox.Height
Me.Listbox.Height = 0
Me.TextBox.Height = aiListHeight

DO STUFF

Me.TextBox.Height = 0
Me.ListBox.Height = aiListHeight

Will this accomplish your goal?
Replace DO STUFF with your existing code to clear out the source. I'd skip turning off echo, changing the cursor, and repainting.

I haven't tried this as I've not had a need to do something like this. As other's have posted, I'd leave the existing listbox alone in case they want to come back to it.
 
@Mark_ that is an interesting solution. Ridders, thanks for taking all the time to show me all that. It is very similar to what I am trying to accomplish. Those pics are the exact behavior, of how I wanted it to look.

I decided @static is right. I will just load them and not keep unloading and reloading them as the person switches between tabs.

For now I am just letting it be slow to open. I would like to do it one way, if it's possible, but I am moving on to other work I have to do, so I can get this completed.

The default page is the find. The add new is the second (index 1) page. When I load the form, I would like to load the find listbox, and only load the add listboxes the first time a user clicks on that page. I would need to somehow capture the first time they click on it, and not do that again after. They might be in the middle of adding multiple projects, might want to go back to find, to check for a project that may already be in system and then go back to add. I don't want to reset anything during that kind of behavior.

Is there a way to capture the first time they click on that page and make it active, maybe store a bit in a variable, and then only reset/load the initial queries if that bit is not set yet?

Like on load:
Dim AddLoadedAsInt (needs to be a public variable within the form module)
AddLoadedAs Int = 0


(on change of tab? )

If ActivePage = AddPage then

If AddLoaded = 0 then
set queries for listboxes and requery
addLoaded += 1
end if

And onload of the form, I would only set the find listbox

Does that make sense? would that help me?
 
Suggest that you use a Boolean variable instead of integer.

After the initial form load events set = true.
If something happens that requires your code to run again, reset =false.

Then use if statements so subsequent code only run if its false
 
Thanks, Ridders! That is smart. Then I don't have to count, which hurts my brain lol
 
Late to the game but as far as your original question rather than try and hide the tab control behind another object, why not just add another page to the tab control with a "please wait" label. Make it visible and active when needed.
 
Late to the game but as far as your original question rather than try and hide the tab control behind another object, why not just add another page to the tab control with a "please wait" label. Make it visible and active when needed.

That is an interesting suggestion. What I was finding was that no matter what I did, once I clicked on a different page, it was too late to hide the yucky painting. Same with on load. It just does all the work, before I have a chance to see the form and give them a better message.

I went a different route. I'm only loading the default find page listbox. If they click on the add page, I will then load those listboxes, but that way, if they never go there, I won't load them. Once loaded, it is easier to just leave them loaded. I did set my check as an integer, but I'm going to take ridders suggestion and make it boolean (T/F) so I don't have to count.

Thanks, all!
 
It is never too late to become what you could have been ~ George Eliot

Sorry to disagree with Ms Eliot but ....

I could have been young and handsome but its definitely too late to become either of those
 
Sorry to disagree with Ms Eliot but ....

I could have been young and handsome but its definitely too late to become either of those

Well I've succeeded at both! Unfortunately there are those who disagree with me.
 
I always used the other method to hide something that would only be revealed in transitional situations.

I put a BIG message, like 48 point red on yellow background and green border. But I left it in the "bottom" of the page's Z axis ("Move to Back"). Then I put my list box in front of this thing. In my case I had a command button so that I could do a "SetFocus" to prevent focus-related errors from being reported. But you might be able to set focus on the tab control itself. In any case, rather than make the big yellow/red message cover the list box, I made the list box .Visible=False (which is why the .SetFocus... you can't make the active control invisible.)

Reverse your logic and hide the thing you don't want seen via visibility, not by covering it.
 
Thanks, Doc Man. I found a solution that is working, so I will keep it for now. If I need to revisit this, for any reason, I will definitely look into that.
 
Just to say that the solution I showed in post #6 is exactly the same as Doc's suggestion.
I thought you'd already moved to using control.visible type code
 
This is how I ended up solving the problem. It doesn't require any of the following:

  • Hiding objects
  • setting, resetting and unsetting listboxes every time the tab changes
  • manage a please wait message

This is my code, which only sets the listbox on the default tab, on load of the form. Then, when and only if the tab control changes (the other page becomes active), I set the add listboxes. By setting a variable to 0, and then adding 1, any time I go to that change, I only set the listboxes when it's 0, so once.

As (I think Ridders) pointed out, the variable could be set to true and then false (or vise versa) and would only need the 1 change, instead of incrementing every change.

Code:
Option Compare Database
Option Explicit
Dim AddLoaded As Integer

Property Get ActivePage() As Access.Page
	'PROPERTY TO IDENTIFY WHICH TAB WE ARE ON, FOR FILTERING AND IDENTIFYING WHICH ACTIVE LISTBOX TO LOOK AT, FOR VALUES AND ACTIONS
	With Me.tbAddFind
		Set ActivePage = .Pages(.Value)
	End With
End Property

Private Sub Form_Load()
	Dim Listctrl As Control
	Dim cmd As ADODB.Command
	Set cmd = New ADODB.Command
	Dim cSQL As String

	AddLoaded = 0

	For Each Listctrl In Form.Controls
		If (Listctrl.ControlType = acListBox) Then
			With Listctrl
				.RowSource = ""
			End With
		End If
	Next Listctrl

	Me.tbAddFind.Value = 0

	cSQL = "SELECT vw_CMP_Projects.CM_CID, [vw_CMP_Projects]![ProjectName] &" & Chr$(34) & " (" & Chr$(34) & "& [vw_CMP_Projects]![ProjectNo] &" & Chr$(34) & ") " & Chr$(34) & " AS Projects FROM vw_CMP_Projects ORDER BY [vw_CMP_Projects]![ProjectName] &" & Chr$(34) & " (" & Chr$(34) & "& [vw_CMP_Projects]![ProjectNo] &" & Chr$(34) & ")" & Chr$(34)
	Me.lstProjects.RowSource = cSQL
	Me.lstProjects.Requery

End Sub

Private Sub tbAddFind_Change()
	Dim cmd As ADODB.Command
	Set cmd = New ADODB.Command
	Select Case Me.ActivePage.Name
		Case "pgAddProjects"
			If AddLoaded = 0 Then
				cmd.ActiveConnection = GetCatalog()
				cmd.CommandType = adCmdStoredProc
				cmd.CommandText = "sp_RefreshProjectsAdd"
				cmd.Execute

				Me.lstAllProjects.RowSource = "Select * From qryAddProjectsYes"
				Me.lstAllProjects.Requery
				Me.lstAddProjects.RowSource = "Select * From qryAddProjectsNo"
				Me.lstAddProjects.Requery

				AddLoaded = AddLoaded + 1
			End If
	End Select
End Sub
 

Users who are viewing this thread

Back
Top Bottom