Non modal common dialog

Anyone know how to invoke the common dialog in such a way that it doesn't block events?  Would still like it to be "on top."  Is there an API solution, or must I build my own dialog?

Have an application which is receiving asynchronous events in the background from various devices.  These are being blocked by the common dialog.

Additionally, they are blocked by an ado "open recordset."  Need to eliminate that blockage too, but I'll ask that as a separate question later.
john_priceAsked:
Who is Participating?
 
amebaConnect With a Mentor Commented:
' ActiveX EXE Project ProjCD (has one class, form and module),
'     in Project properties select 'Thread per Object'
'     Compile and make ProjCD.exe
'
' class clsCD ---------------------------------------------
Option Explicit
Public Event FileSelected(ByVal Filename As String)
Private Declare Function SetParent Lib "user32" (ByVal hWndChild As Long, _
    ByVal hWndNewParent As Long) As Long

Public Sub ShowCD(frmHwnd As Long)
    Load frmCD
    frmCD.Move 100, -500, 100, 100
    SetParent frmCD.hWnd, frmHwnd
    frmCD.Show
End Sub

Private Sub Class_Initialize()
    Set ClassDialog = Me
End Sub

Public Property Let Filename(ByVal Filename As String)
    RaiseEvent FileSelected(Filename)
End Property


' Module1  ---------------------------------------
Option Explicit
Public ClassDialog As clsCD


' Form frmCD, add common dialog  ----------------
Option Explicit

Private Sub Form_Activate()
    Me.Hide
    CommonDialog1.ShowOpen
    ClassDialog.Filename = CommonDialog1.Filename
    Unload Me
End Sub


'---------------------------------------------------------------------
' Standard Exe Project (has only one form), add reference to ProjCD.exe
'
' Form1, add 2 buttons
Option Explicit
Private WithEvents CD As ProjCD.clsCD

' receive event when file is selected
Private Sub CD_FileSelected(ByVal Filename As String)
    Me.SetFocus
    MsgBox Filename
    Command1.Enabled = True
End Sub

' show common dialog
Private Sub Command1_Click()
    Command1.Enabled = False
    Set CD = New clsCD
    CD.ShowCD Me.hWnd
End Sub

' test multiple instances (this wont work in IDE, so compile ProjCD)
Private Sub Command2_Click()
    Dim x As Form1
   
    Set x = New Form1
    x.Left = Left + 1500
    x.Show
End Sub

Private Sub Form_Load()
    Command1.Caption = "Show CD"
    Command2.Caption = "New Form"
End Sub

Private Sub Form_Unload(Cancel As Integer)
    ' do not unload this form if file selection is in progress
    If Command1.Enabled = False Then Cancel = True
End Sub
0
 
spg01Commented:
create your own common dialog box and use the following code to keep the form ontop.

(I got this code from PeteWest)

     Option Explicit
     Public Const SWP_NOMOVE = 2
     Public Const SWP_NOSIZE = 1
     Public Const FLAGS = SWP_NOMOVE Or SWP_NOSIZE
     Public Const HWND_TOPMOST = -1
     Public Const HWND_NOTOPMOST = -2


     Declare Function SetWindowPos Lib "user32" Alias "SetWindowPos" (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

     Public Function SetTopMostWindow(hwnd As Long, Topmost As Boolean) As Long

        If Topmost = True Then 'Make the window topmost
           SetTopMostWindow = SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, FLAGS)
        Else
           SetTopMostWindow = SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,FLAGS)
           SetTopMostWindow = False
        End If
     End Function


To use this function just put the following in the Form_Load event of the form you want on top:

       Dim lRetVal as Long
       lRetVal = SetTopMostWindow(Me.Hwnd,True)

And then - in the Form_Unload event put:

       Dim lRetVal as Long
       lRetVal = SetTopMostWindow(Me.Hwnd,False)

This just stops it from being the topmost window.
0
 
Guy Hengel [angelIII / a3]Billing EngineerCommented:
I agree on the "Create your own Dialog form", but i disagree on the API calls. I use the
frmDialog.Show vbModeless, frmMain
code to display a form as topmost for my project, but not in front of everything!

Cheers
0
Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

 
spg01Commented:
fare comment, but if focus switches to another form then you dialog box will get lost behind the form that takes focus. Depends on the needs of the application I suppose.
0
 
spg01Commented:
fare comment, but if focus switches to another form then you dialog box will get lost behind the form that takes focus. Depends on the needs of the application I suppose.
0
 
john_priceAuthor Commented:
I know how to do the "on top" bit, thanks.  Was really asking about how to invoke the dialog modeless.  Guess you both agree that you can't.  Let me wait a day or two to see if anyone else has a suggestion.  I know you can invoke the dialog via API.  Wondering if there is a sendmessage or handle or thread management api that allows it to be non-blocking.
0
 
john_priceAuthor Commented:
I know how to do the "on top" bit, thanks.  Was really asking about how to invoke the dialog modeless.  Guess you both agree that you can't.  Let me wait a day or two to see if anyone else has a suggestion.  I know you can invoke the dialog via API.  Wondering if there is a sendmessage or handle or thread management api that allows it to be non-blocking.
0
 
john_priceAuthor Commented:
Further comment about creating my own dialog.  The file dialog is fairly complicated and includes some nice features users have gotten used to, such as "new folder."  I'd rather not reinvent all those wheels in order to get a modeless dialog if at all possible.
0
 
rspahitzCommented:
How about opening a new modeless window which invokes the common dialog box.  If you build it as a separate thread, it will become an independent structure that has the CDL box modal only for that thread, then YOUR app can keep going.
0
 
amebaCommented:
rspahitz is right. You can use another thread to show CommonDialog without blocking your application. Create ActiveX Exe, use 'Thread per Object' threading model ...
0
 
john_priceAuthor Commented:
Now, that's an idea.  I'll give that a try.  Have used the idea to provide a non-blocking activity, such as running a background animation to indicate a "busy" condition, but never thought of it for this.

Any way to split the points?  rspahitz gave the first answer, and ameba took the time to write and submit some code.  
0
 
amebaCommented:
>Any way to split the points?
 
You can ask a 0 point question "Please, split points" in Community Support topic area
http://www.experts-exchange.com/jsp/qList.jsp?ta=commspt

Make sure you give A grade! If you think my comment is not for A grade, just ignore it.
0
 
rspahitzCommented:
If it's too much of a hassle to split the points, then just award the points to ameba (A-grade!) since he gave you the answer.  I was actually impressed that he took the time to follow through that far!!! :)
0
 
john_priceAuthor Commented:
I've posted a question as you suggest requesting these points be split.  If they can't, I'm asking that an additional 50 points be awarded to rspahitz.  Thanks.
-- John
0
 
rspahitzCommented:
Thanks.  It appears to me that your split question (http://www.experts-exchange.com/jsp/qShow.jsp?ta=commspt&qid=20138002) properly addressed this issue.  These are usually be addressed within a week.
0
 
MoondancerCommented:
All adjustments have been made.

Points for rspahitz here, please comment co finalize:

http://www.experts-exchange.com/jsp/qManageQuestion.jsp?qid=20138152

Moondancer
Community Support Moderator @ Experts Exchange
0
 
MoondancerCommented:
CORRECTION ... Points for rspahitz here, please comment to finalize (problems posting Qs this morning, apologies):

http://www.experts-exchange.com/jsp/qManageQuestion.jsp?qid=20138156

Moondancer
Community Support Moderator @ Experts Exchange
0
 
rspahitzCommented:
Thanks, john_price.
0
 
john_priceAuthor Commented:
Thanks.  Have spent a good part of the day enhancing this code.  I want to be able to send in the dialogtitle, filter, etc, and get back the filename and filetitle.  Just about there...

Thanks guys.
0
 
amebaCommented:
Thanks for the points.

I know my code is just a start-point.

Instead of Form_Activate, maybe you can use a timer and avoid showing the frmCD completely.

Maybe you can also implement Left and Top properties - position of common dialog depends on frmCD's position.

Note that everything must be handled/passed the async way - programming this is not as simple as it is with 'normal' sync common dialog.  But it is simpler than hacking/ hooking commondialog via APIs.
0
 
john_priceAuthor Commented:
Form_Activate is fine.  The Hide statement works before it even paints, so I don't even see a flicker.  Besides, I made the form very small so that even if it did flicker, it would be unnoticable.  Tried invoking a form procedure, ShowDialog from the class which in turn showed the dialog, but that was enough to cause blocking.
By going through the several layers I've been able to make it *almost* like the regular dialog.  for example:

With cNMDialog
  .DialogTitle="Get File"
  .Filter-"Text Files|*.txt|All Files|*.*"
  .FilterIndex=1
  .InitDir="c:\Test"
  .FileName="TestStartFile.txt"
  .ShowOpen me.hwnd
End With

Private Sub cNMDialog_FileSelected(FileName As String, FileTitle As String)

debug.print FileName
debug.print FileTitle

End Sub



To code the use of the dialog in a simulated synchronous way, yet not block other events:
With cNMDialog
 ... invoke dialog like above
 Do Until m_blnFileSelected
  doevents
 Loop
 m_blnFileSelected = false ' reset for next time.
 debug.print .filename
 debug.print .filetitle
End With

Private Sub cNMDialog_FileSelected(FileName As String, FileTitle As String)
 m_blnFileSelected=True ' modular boolean variable
End sub

Thanks, ameba.  Sometimes solving a tough one can be fun.


0
 
amebaCommented:
Yes, nice idea, doevents loop will make client code nicer.
Good job!
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.