You can use a form's Painting property to disable updates to that form, but some activities still seem to show through or cause flashing on the screen. Is there any way to hide screen activity?
Sometimes you need more control over screen repainting than you get with either Form.Painting. You may also need to investigate the Application.Echo method. By passing this method a True or a False value, you can indicate whether you want to display updating within the main Access window. You can also optionally pass the method a second parameter?a string indicating text to be displayed within the status bar while screen updating is disabled.
Load and run frmLockScreen (Figure 4-9) from 04-04.MDB. This sample form simply opens three reports in design mode and then closes them. The form includes a checkbox that allows you to run the test with screen updates enabled or disabled. Try it both ways; you should see a clear difference between the two ways of running the test. With the checkbox set, the underlying code disables screen updates, so you shouldn't see the reports' icons pop up. Without the checkbox set, you will see the reports open and minimize, in design view.
To use Application.Echo to disable screen updates in your own applications, follow these steps:
Import the module basLockScreen from 04-04.MDB. This module includes the simple code that's required in order to disable updates to the Access main window.
When you want to disable screen updates, call the acbShowUpdates subroutine, passing it a False value. To reenable screen updates, call the subroutine again, passing it a True value. In other words, your code that uses acbShowUpdates should take the following form:
Call acbShowUpdates(False) ' Do your work in here... Call acbShowUpdates(True)
The Application.Echo method is simple to use, but many developers miss it, allowing their applications to appear somewhat dizzying as objects appear and disappear from the screen. The acbShowUpdates method really doesn't do much besides what a direct call to Application.Echo does:
Sub acbShowUpdates(blnShow As Boolean) If blnShow Then Application.Echo True Else Application.Echo False End If End Sub
As a matter of fact, the reason this procedure exists at all is because the techniques used in this topic work great in Access 2002 and later, but may not work correctly in earlier versions?it may be that if you're running Access 2000 or earlier, using Application.Echo to turn off screen updating while opening a report in design view may not hide screen updates. In that case, you may want to try an alternate technique, calling the parallel acbShowUpdatesAPI method.
The acbShowUpdatesAPI subroutine (in basLockScreen) does its work by calling the Windows API function LockWindowUpdate. This function takes as its only parameter a window handle. If that handle is nonzero, Windows simply stops updating the contents of that window on screen. If the handle is 0, Windows reenables screen updates to the locked window.
Because the only window you care about locking in Access is the main Access window itself, the acbShowUpdatesAPI routine shields you from any of the details. If you pass it a False value, it blocks window updates. If you pass it a True value, it reenables updates. It finds the Access window handle for you, if necessary, and then calls LockWindowUpdate. Its source code is simple:
Sub acbShowUpdatesAPI (blnShow As Integer) If blnShow Then acb_apiLockWindowUpdate 0 Else acb_apiLockWindowUpdate Application.hWndAccessApp End If End Sub
You may find, depending on the version of Access you're using, that this method of disabling screen updates isn't perfect. Because Access has no idea that you've turned them off, Access itself occasionally turns on screen updates. For example, depending on how you open forms and reports in design mode, completely hiding the properties sheet may be difficult. In the sample application, 04-04.MDB, the reports' properties sheet isn't showing. If you open one of the reports, open the properties sheet, and then save the report, no combination of Application.Echo and calls to LockWindowUpdate will completely remove that properties sheet from the screen when you open the report in design view.
In older versions of Access, you had to resort to hacks to hide reports in design view. Fortunately, that is no longer necessary in Access 2002 and later, because Microsoft has finally supplied a WindowMode parameter that can be used to hide a report when you open it, even if it's opened in design view. Also, many of the printer settings that made it necessary to open reports in design view are no longer necessary starting in Access 2002 because of the Printer object (see Chapter 5 for several examples).
If you are working in Access 97, you can take advantage of an undocumented but effective technique for hiding the hard-to-hide properties windows of reports that are open in design view. Be warned, however, that this method is totally undocumented, is unsupported by Microsoft, and doesn't work in Access 2000 or later.
The Application object in Access supports the GetOption and SetOption methods, which allow you to get and set global options. Most of these options are documented (see the online help topics for GetOption/SetOption), while a few items are not documented but do useful work. One such option allows you to retrieve and set the coordinates for the form or report properties sheet (in versions of Access prior to Access 2000) and to set whether or not you want the properties sheet to be visible when you open a form or report in design view.
To retrieve the information about the report properties sheet in Access 97 or 95, use a call like this:
strInfo = Application.GetOption("_26")
This will retrieve a string containing information on the report properties sheet's location and whether or not to display it when you open a report in design view. The string will be in this format:
For example, it might look like this:
indicating that the properties sheet will be visible when you load a report and that when it does show up it will be at 510, 433 with a width of 835 and a height of 683.
To make sure that your application doesn't show the properties sheet while it does its work, you can retrieve this property, set the first character to 0, and then save it. The code might look like this:
Dim strInfo As String strInfo = Application.GetOption("_26") strInfo = "0" & Mid(strInfo, 2) Application.SetOption "_26", strInfo
The only way this will have any influence is if you call this code before you've loaded any reports in design mode. Access looks at this information only once, when it loads the properties sheet for the first time. Once it has loaded the properties sheet, it doesn't look at these values again. Every time you leave design mode Access stores information about the properties sheet, so if you're going to try to set these values for the next time you start Access, make sure you do it when there's no report open in design mode. Otherwise, Access will override your settings when it saves them itself.
To use this technique for forms, use option "_24" instead. It's not nearly as useful with forms as it is with reports, however, because in older versions of Access you can open hidden forms but not hidden reports.
Never Turn off the Screen Without an Error Handler!
Though this same advice goes for using Application.Echo or Form.Painting, it's especially true for using LockWindowUpdate. Any time you turn off the screen display, you absolutely must include an error handler in your routine that will immediately reenable screen updates if an error occurs. Sooner or later, a runtime error will occur, and your code must react to this and clean up. Users tend to do unpleasant things, such as rebooting their computers, when their screens stop dead (that's what would happen if an error occurred while you had screen updates turned off ). This can be detrimental to their data and to your application, so never consider turning off the screen unless you also include an error handler to turn it back on.
As an example of an error handler that resets screen updates, the code executed by frmLockScreen handles errors by using the normal exit route from the routine:
Private Sub cmdOpenReports_Click( ) Dim intI As Integer Dim intSuccess As Integer On Error GoTo HandleErr If Me.chkHideUpdates Then If Me.chkUseAPI Then Call acbShowUpdatesAPI(False) Else Call acbShowUpdates(False) End If End If For intI = 1 To 3 Call acbOpenReport("rptReport" & intI, acDesign) Next intI For intI = 1 To 3 DoCmd.Close acReport, "rptReport" & intI Next intI ExitHere: If Me.chkHideUpdates Then If Me.chkUseAPI Then Call acbShowUpdatesAPI(True) Else Call acbShowUpdates(True) End If End If Exit Sub HandleErr: MsgBox Err.Number & ": " & Err.Description Resume ExitHere End Sub
If an error occurs while this subroutine is active, the code will jump to the HandleErr label and from there will resume at the ExitHere label. The code will re-enable screen updates and then exit the routine. Your own code may not look exactly like this, but you must handle errors so that the screen never remains locked up when an error occurs.
For more information on working with the Windows API, see Chapter 11.