Which is preferred way to toggle display of Form?
|
|
Thread rating:  |
Howard Kaikow - 30 Dec 2004 12:15 GMT I am using SetWindowPos to cause a Form to always appear on top.
However, the program displays Word Dialog boxes, which are then covered, entirely or partially, by the Form.
I've though of the following solutions:
1. Hide, then Show the Form. 2. Change the WindowState to minimize, then display the Form. 3. Use SetWindowState to change the Z-order using HWND_BOTTOM and HWND_TOP.
The drawback to Hide/Show is that I have to have the code remember whether use vbModeless or vbModal. If I use .Visible to Hide/Show the Form, does .Visible = True remember whether the Form was previously shown with vbModeless or not?
Which of he above methods is preferred? Is there a better way?
 Signature http://www.standards.com/; See Howard Kaikow's web site.
Randy Birch - 30 Dec 2004 16:27 GMT #3, though I'd probably just turn off the topmost rather than set it to the bottom.
 Signature Randy Birch MS MVP Visual Basic http://vbnet.mvps.org/
:I am using SetWindowPos to cause a Form to always appear on top. : [quoted text clipped - 14 lines] : Which of he above methods is preferred? : Is there a better way? Howard Kaikow - 30 Dec 2004 22:47 GMT I meant SetWindowsPos, not SetWindowsState.
Best I've been able to do so far with SetWindowsPos is minimize the Form, but that seems better using WindowsState.
Bye thee waye, I tried constructing a simplified example demomstrating the issue I raised.
I used a standard VB project and automated Word. I found that the problem does not occur in a standard project, only when the code is run via a DLL. In a standard project, the Word Dialog appears on top of the Form, even tho the Form is set to be on top.
The following is the code in the Form.
Private Sub btnByeBye_Click() Unload Me End Sub
Private Sub Form_Activate() 'Set the window position to topmost SetWindowPos Me.hWnd, HWND_TOPMOST, 0, 0, 0, 0, _ SWP_NOACTIVATE Or SWP_SHOWWINDOW Or SWP_NOMOVE Or SWP_NOSIZE End Sub
The following is the startup code
Public Const HWND_BOTTOM As Long = 1 Public Const HWND_NOTOPMOST = -2 Public Const HWND_TOPMOST = -1 Public Const SWP_HIDEWINDOW As Long = &H80 Public Const SWP_NOACTIVATE = &H10 Public Const SWP_NOMOVE = &H2 Public Const SWP_NOSIZE = &H1 Public Const SWP_SHOWWINDOW = &H40 Public Declare Sub 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)
Public Sub Main() Dim appWord As Word.Application
Set appWord = New Word.Application With frmSetWindowPos .Show vbModeless ' .WindowState = vbMinimized With appWord With .Dialogs(Word.wdDialogFileOpen) .addtomru = False If .Display = -1 Then MsgBox .Name End If End With .Quit End With ' .WindowState = vbNormal End With Set appWord = Nothing End Sub
Howard Kaikow - 31 Dec 2004 12:49 GMT I've constructed a simple example of how to reproduce the problem.
First, put the following in a Word template:
Public Sub RunTest() Dim cls As clsTestOnTop Set cls = New clsTestOnTop With cls .SetClass Word.Application .TestOnTop End With End Sub
Next, create an ActiveX DLL with the following:
A module that has:
Public gappWord As Word.Application
Public Const HWND_BOTTOM As Long = 1 Public Const HWND_NOTOPMOST = -2 Public Const HWND_TOPMOST = -1 Public Const SWP_HIDEWINDOW As Long = &H80 Public Const SWP_NOACTIVATE = &H10 Public Const SWP_NOMOVE = &H2 Public Const SWP_NOSIZE = &H1 Public Const SWP_SHOWWINDOW = &H40 Public Declare Sub 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)
A class named clsTestOnTop that has:
Public WithEvents appWord As Word.Application
Public Sub TestOnTop() frmSetWindowPos.Show vbModeless End Sub
Public Sub SetClass(appIs As Word.Application) Set appWord = appIs Set gappWord = appIs End Sub
Friend Property Get WordApp() As Word.Application Set appWord = WordApp Set gappWord = appWord End Property
Friend Property Set WordApp(ByVal appNew As Word.Application) Set appWord = appNew Set gappWord = appWord End Property
Private Sub Class_Terminate() Set appWord = Nothing End Sub
A Form named frmSetWindowPos that is made large enough to cover a good portion of the screen, and has two buttons, with the following code:
Private Sub btnByeBye_Click() Unload Me End Sub
Private Sub btnRunMe_Click() ' Me.WindowState = vbMinimized With gappWord With .Dialogs(Word.wdDialogFileOpen) .addtomru = False If .Display = -1 Then MsgBox .Name End If End With End With ' Me.WindowState = vbNormal End Sub
Private Sub Form_Activate() 'Set the window position to topmost SetWindowPos Me.hWnd, HWND_TOPMOST, 0, 0, 0, 0, _ SWP_NOACTIVATE Or SWP_SHOWWINDOW Or SWP_NOMOVE Or SWP_NOSIZE End Sub
Private Sub Form_Terminate() Set gappWord = Nothing End Sub
Now, add a reference to the class in the Word project. Run the code.
You should see the Form on top of the Word Dialog, if you made the Form large enough. Next, uncomment the two WindowState statements in the Form.
Now, when you run the code, the Word dialog will not be covered and the Form will re-appear.
Howard Kaikow - 31 Dec 2004 14:23 GMT I have found a way to reproduce the problem using an EXE, as well as the previously posted example of using a DLL.
The problem occurs because the Word Dialog is invoked from within the VB Form, DLL or EXE matters not.
To reproduce the problem, create a standard VB EXE project with the following:
A module with:
Public appWord As Word.Application Public Sub Main() Set appWord = New Word.Application frmSetWindowPos.Show vbModeless End Sub
A Form, large enough to be annoying, with:
Option Explicit Private Const HWND_BOTTOM As Long = 1 Private Const HWND_NOTOPMOST = -2 Private Const HWND_TOPMOST = -1 Private Const SWP_HIDEWINDOW As Long = &H80 Private Const SWP_NOACTIVATE = &H10 Private Const SWP_NOMOVE = &H2 Private Const SWP_NOSIZE = &H1 Private Const SWP_SHOWWINDOW = &H40 Private Declare Sub 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)
Private Sub btnByeBye_Click() Unload Me appWord.Quit Set appWord = Nothing End Sub
Private Sub btnRunMe_Click() ' Me.WindowState = vbMinimized With appWord With .Dialogs(Word.wdDialogFileOpen) .addtomru = False If .Display = -1 Then MsgBox .Name End If End With End With ' Me.WindowState = vbNormal End Sub
Private Sub Form_Activate() 'Set the window position to topmost SetWindowPos Me.hWnd, HWND_TOPMOST, 0, 0, 0, 0, _ SWP_NOACTIVATE Or SWP_SHOWWINDOW Or SWP_NOMOVE Or SWP_NOSIZE End Sub Make th emodule the startup object.
When you run the code, you will need to use Alt Tab to ge taccess to the Word dialog.
If you uncomment the WindowState statements, then the Form gets minimized out of the way.
|
|
|