Link to home
Start Free TrialLog in
Avatar of koossa
koossa

asked on

Determine Deactivate on a borderless modal form

I have a Main Form and a Popup Form.
The Main Form is displayed as vbModal and that cannot be changed, so I must show the Popup Form also as vbModal.
The Popup Form works like a Popup Menu when the user clicks on a button on the main form.
I want the popup form to disappear when the user clicks on the main form while the popup form is visible.

Is there any way of doing this?
Avatar of koossa
koossa

ASKER

By the way, this is VB6
Avatar of GrahamSkan
By definition, nothing is processed (including any clicks on another form) until the current modal form is hidden or dismissed.
Avatar of koossa

ASKER

Hi Graham

Yes, I know that, but what I'm looking for is a work around.

Something like a custom control for each popup forms with a mouse click hook that will be triggered when clicked outside the form or anything similar
What you literally asked for isn't possible. You need to have something on the pop-up that closes itself.

Are you thinking of creating a small borderless modal form that looks like, say, a button on the main form and is positioned over an existing button there, so that a user thinks that it is the button on the main form that is being clicked? That sounds possible, but fiddly.
Use this (you can also use the sendinput api
in frmPopUpModalForm):

'/------------------------------------------------
'/ modStart
'/-------------------------------------------------
Option Explicit

Public Sub Main()
  frmMainModalForm.Show vbModal
End Sub

Public Function IsFormLoaded( _
                    f As Form _
                    ) As Boolean
                    
  Dim i As Integer
  
  For i = 0 To Forms.Count - 1
      If Forms(i) Is f Then
          IsFormLoaded = True
          Exit Function
      End If
  Next i
  IsFormLoaded = False

End Function



'/------------------------------------------------
'/ frmMainModalForm
'/-------------------------------------------------
Option Explicit

Private m_oPopUpModalForm As frmPopUpModalForm

' Show PopUpModalForm
Private Sub Command1_Click()
  On Error GoTo Err_Handler
  
  Set m_oPopUpModalForm = New frmPopUpModalForm
  
  m_oPopUpModalForm.ShowPopUp Me.hwnd, Me
  
  Command1.Enabled = (Not IsFormLoaded(m_oPopUpModalForm))

  Exit Sub

Err_Handler:
  Debug.Print "ERROR (frmMainModalForm.Command1_Click): " & Err.Description

End Sub


' Hide PopUpModalForm
Private Sub Command2_Click()
  If IsFormLoaded(m_oPopUpModalForm) Then
      Unload m_oPopUpModalForm
      Set m_oPopUpModalForm = Nothing
  End If
  
  Command1.Enabled = True

End Sub

Private Sub Form_Activate()
  Command1.Enabled = (Not IsFormLoaded(m_oPopUpModalForm))
End Sub

Private Sub Form_Unload(Cancel As Integer)
  
  If IsFormLoaded(m_oPopUpModalForm) Then
      Unload m_oPopUpModalForm
      Set m_oPopUpModalForm = Nothing
  End If

End Sub

'/------------------------------------------------
'/ frmPopUpModalForm
'/-------------------------------------------------
Option Explicit

Private Declare Function ShowWindow Lib "user32" (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long
Private Declare Function SetWindowLong Lib "user32" Alias  "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long

Private Const SW_SHOWNORMAL = 1
Private Const GWL_HWNDPARENT = (-8)

Private m_nOldOwner As Long
Private m_oParent As Object

Public Sub ShowPopUp( _
              hwndOwner As Long, _
              oParentForm As Form _
              )
               
  On Error GoTo Err_Handler

  ShowWindow Me.hwnd, SW_SHOWNORMAL
  m_nOldOwner = SetOwner(Me.hwnd, hwndOwner)
  Set m_oParent = oParentForm

  Exit Sub

Err_Handler:
  Debug.Print "ERROR (frmPopUpModalForm.ShowPopUp): " & Err.Description
  
End Sub


Private Sub Form_Unload(Cancel As Integer)
  SetOwner Me.hwnd, m_nOldOwner
  Set m_oParent = Nothing

End Sub


Function SetOwner(ByVal hWndToUse, ByVal hWndOfOwner) As Long
  SetOwner = SetWindowLong(hWndToUse, GWL_HWNDPARENT, hWndOfOwner)
End Function

Open in new window

The Main Form is displayed as vbModal and that cannot be changed...
Would showing it non-vbModal but Enabled = False (since you could then show your popup) work for you?
Avatar of koossa

ASKER

Hi eemit

I have more or less the same idea as your example, and it is working in concept and if you don't display frmMainModalForm as vbmodal.
As soon as you create a seperate form that show the frmMainModalForm as vbmodal, it does not want you to set focus on any control on the frmPopUpModalForm

MartinLiss
I cannot go for the vbModeless option, because there is simply too much code that I then need to rewrite.
ASKER CERTIFIED SOLUTION
Avatar of Martin Liss
Martin Liss
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
This is well suited for simulation of virtual keyboard using SendInput API.
Take a look here for SendInput example:
http://vb.mvps.org/samples/SendInput/

And then in frmPopUpModalForm e.g.:
Private Sub Image1_Click()
  m_oParent.ActiveControl.SetFocus
 
  Call MySendKeys("C")
  DoEvents

End Sub
Avatar of koossa

ASKER

Thank you.
Another Approach:
'--------------------------------------------------------------------------
' frmMainModalForm
'--------------------------------------------------------------------------
Private WithEvents m_oPopUpModalForm As frmPopUpModalForm

Private Sub Command1_Click()
  Set m_oPopUpModalForm = New frmPopUpModalForm
  
  m_oPopUpModalForm.Show vbModal
End Sub

Private Sub m_oPopUpModalForm_MouseLeave()
  Unload m_oPopUpModalForm
  Set m_oPopUpModalForm = Nothing
End Sub


'--------------------------------------------------------------------------
' frmPopUpModalForm
'--------------------------------------------------------------------------
Option Explicit

Private Declare Function SetCapture Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function ReleaseCapture Lib "user32" () As Long

Private m_oldState As Boolean ' old MouseIn-Status
Private m_bMouseIn As Boolean

Public Event MouseEnter()
Public Event MouseLeave()
Public Event Loaded()

Private Sub Form_Load()
  RaiseEvent Loaded
  
End Sub

Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
  
  Call CheckMouse(X, Y)
  If m_oldState <> m_bMouseIn Then
    
    If m_bMouseIn = True Then
        RaiseEvent MouseEnter
      
    Else
        RaiseEvent MouseLeave
      
    End If
  End If
  m_oldState = m_bMouseIn
 
End Sub


Private Sub CheckMouse(ByVal X As Single, ByVal Y As Single)
  With Me
    If X < 0 Or Y < 0 Or X > .ScaleWidth Or Y > .ScaleHeight Then
      ReleaseCapture
      m_bMouseIn = False
    Else
      SetCapture .hwnd
      m_bMouseIn = True
    End If
  End With
End Sub

Open in new window