How to make a Common Save File Dialog inside another window?

Posted on 1998-09-30
Last Modified: 2008-02-01
What I want to do is to place the CommonDialog (which I have made through API calls) inside a window of any kind...
If you don't know what I mean take a look at VB and click on for example the formbutton, then you'll get a dialog where the savefile thing is captured on one of the tabs and the other tab consists of other things...
I've found info on how to do this in C, but I can't understand it... something about using the OFN_ENABLETEMPLATE constant or something.

Please help...
Question by:Grdv
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 10
  • 5
  • 4
  • +3
LVL 14

Expert Comment

ID: 1437326
You have two solutions :
  - Use the set parent API
 Declare Function SetParent Lib "user32" Alias "SetParent" (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long

  - Design entirely in VB what you need.


Author Comment

ID: 1437327
hmm, might have said something wrong there...
by doing that, I only get the topleft corner of the save file dialog in the topleftcorner of the form I want to have it ON.
what I want is to make the save file dialog a part of the other window...

Author Comment

ID: 1437328
look at the page:

<a href="">This one</a>

which is a microsoftpage about; "Using the Common Dialogs Under Windows 95"
shortly after the label "Using the OFN_EXPLORER Flag" there is a text on how to perform it in C, but I don't understand how to translate it into Visual Basic...

SharePoint Admin?

Enable Your Employees To Focus On The Core With Intuitive Onscreen Guidance That is With You At The Moment of Need.

LVL 13

Expert Comment

ID: 1437329
Waty was almost right. You have to change the style of the window. See the code below.
The OFN_ENABLETEMPLATE style cannot be used in VB. This is based on dialog resources, which are not supported in VB.

Private Declare Function SetParent Lib "user32.dll" (ByVal childHwnd As Long, ByVal ParentHwnd 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 Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
Private Declare Function ShowWindow Lib "user32" (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long
Private Const GWL_EXSTYLE = (-20)
Private Const WS_EX_CONTROLPARENT = &H10000
Private Const GWL_STYLE = (-16)
Private Const WS_CHILD = &H40000000
Private Const WS_TABSTOP = &H10000
Private Const WS_VISIBLE = &H10000000
Private Const WS_CAPTION = &HC00000
Private Const WS_BORDER = &H800000
Private Const WS_THICKFRAME = &H40000
Private Const WS_SYSMENU = &H80000
Private Const WS_MINIMIZEBOX = &H20000
Private Const WS_MAXIMIZEBOX = &H10000
Private Const SW_NORMAL = 1
Private Const SW_HIDE = 0
Private Const SW_SHOWNA = 8
        m_oldstyle = GetWindowLong(m_currentform.hwnd, GWL_STYLE)
        Call SetWindowLong(m_currentform.hwnd, GWL_STYLE, (m_oldstyle Or WS_CHILD) And Not (WS_CAPTION Or WS_BORDER Or WS_THICKFRAME Or WS_SYSMENU Or WS_MINIMIZEBOX Or WS_MAXIMIZEBOX))
        m_currentform.Width = m_currentform.Width - 10 ' Workaround to force repaint
        m_currentform.Width = m_currentform.Width + 10 ' Workaround to force repaint
        m_oldparent = SetParent(m_currentform.hwnd, ClipFrame.hwnd)
        ShowWindow m_currentform.hwnd, SW_SHOWNOACTIVATE


Author Comment

ID: 1437330
To err is human... this time it's me i think... :)
well... this certainly feel like the right thing... now there's just some small things left for me to understand:

1. m_currentform and ClipFrame, which is what... so to say...?
2. how do I get the .hWnd property from the SaveFileDialog?

thx in advance..
// DonutVillage
LVL 13

Expert Comment

ID: 1437331
1) Oh, I'm sorry. I just copied some of my code. They are just to forms. Clipframe is the child form and m_currentform is the parent form.
2) Oeps, Common dialog does not have a hwnd property. So setparent cannot be used in your case

Just reject my answer, altough it's likely there isn't a solution to your problem

Expert Comment

ID: 1437332
Here is Source Code To A Program That Captures a Window with the Given Caption Only, it have tested it with Commondialogs and it does work. It uses the FindWindow API Call to find the Window with the Given Caption(since it is a CommonDialog then you will be able to set the caption yourself and this won't be a problem...)

To Make It easier for you to use this example here is the form header for the controls...

Begin VB.Form Form1
   Caption         =   "Form1"
   ClientHeight    =   3195
   ClientLeft      =   165
   ClientTop       =   735
   ClientWidth     =   4680
   LinkTopic       =   "Form1"
   ScaleHeight     =   3195
   ScaleWidth      =   4680
   StartUpPosition =   3  'Windows Default
   Begin VB.PictureBox picCage
      Align           =   2  'Align Bottom
      Enabled         =   0   'False
      Height          =   1605
      Left            =   0
      ScaleHeight     =   1545
      ScaleWidth      =   4620
      TabIndex        =   3
      Top             =   1590
      Width           =   4680
   Begin VB.CommandButton cmdRelease
      Caption         =   "Release"
      Enabled         =   0   'False
      Height          =   345
      Left            =   1860
      TabIndex        =   2
      Top             =   990
      Width           =   1065
   Begin VB.CommandButton cmdCage
      Caption         =   "Capture"
      Default         =   -1  'True
      Height          =   345
      Left            =   1860
      TabIndex        =   1
      Top             =   600
      Width           =   1065
   Begin VB.TextBox txtCaption
      Appearance      =   0  'Flat
      BeginProperty Font
         Name            =   "MS Sans Serif"
         Size            =   8.25
         Charset         =   0
         Weight          =   700
         Underline       =   0   'False
         Italic          =   0   'False
         Strikethrough   =   0   'False
      Height          =   255
      Left            =   90
      TabIndex        =   0
      Text            =   "Start Menu"
      Top             =   240
      Width           =   4455
   Begin VB.Label Label1
      AutoSize        =   -1  'True
      Caption         =   "Caption of Form To Capture:"
      Height          =   195
      Left            =   300
      TabIndex        =   4
      Top             =   0
      Width           =   1995
   Begin VB.Menu mnuPB
      Caption         =   "Picture Box"
      Begin VB.Menu mnuPBEnabled
         Caption         =   "Enabled"
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
End Form Header

Begin Form Code

Private Declare Function 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) As Long

Private Declare Function SetParent& Lib "user32" (ByVal hWndChild As Long, ByVal hWndNewParent As Long)
Private Declare Function SetWindowText Lib "user32" _
    Alias "SetWindowTextA" (ByVal hWnd As Long, _
    ByVal lpString As String) As Long
Private Declare Function FindWindow& Lib "user32" Alias "FindWindowA" (ByVal lpClassName$, ByVal lpWindowName$)
Dim MyGivenhWnd&
Private Function EnslaveWindow(ObjCage As Object, WindowCaption$, Optional NewWindowCaption$) As Long
Dim m_lngCagedWindow&
m_lngCagedWindow = FindWindow(ByVal vbNullString, ByVal WindowCaption) 'The Caption isn't Case Sensitive
If m_lngCagedWindow = 0 Then Exit Function
SetParent m_lngCagedWindow, ObjCage.hWnd
SetWindowPos m_lngCagedWindow, ByVal 0&, ByVal 0&, ByVal 0&, ObjCage.Width / 15, ObjCage.Height / 15, ByVal 0&
If Not NewWindowCaption = "" Then
SetWindowText m_lngCagedWindow, NewWindowCaption
End If
ObjCage.Enabled = False'If you want the user to interact with the window then simply remove this line
EnslaveWindow = m_lngCagedWindow
End Function

Public Sub ReleaseWindow(hWnd As Long)
SetParent hWnd, 0
End Sub

Private Sub cmdCage_Click()
If LCase(txtCaption) = LCase(Caption) Then Exit Sub
Dim GivenhWnd&
GivenhWnd = EnslaveWindow(picCage, txtCaption)
If GivenhWnd = 0 Then Exit Sub
cmdCage.Default = False
cmdCage.Enabled = False
cmdRelease.Default = True
cmdRelease.Enabled = True
MyGivenhWnd = GivenhWnd
End Sub

Private Sub cmdRelease_Click()
cmdRelease.Default = False
cmdRelease.Enabled = False
cmdCage.Default = True
cmdCage.Enabled = True
ReleaseWindow MyGivenhWnd
MyGivenhWnd = 0
End Sub

Private Sub Form_Resize()
picCage.Height = ScaleHeight - (cmdRelease.Height + cmdRelease.Top)
End Sub

Private Sub Form_Unload(Cancel As Integer)
On Error Resume Next
If cmdRelease.Enabled Then ReleaseWindow MyGivenhWnd
End Sub

Private Sub mnuPBEnabled_Click()
pbEnabled = Not pbEnabled
End Sub

Public Property Get pbEnabled() As Boolean
pbEnabled = picCage.Enabled
mnuPBEnabled.Checked = picCage.Enabled
End Property

Public Property Let pbEnabled(ByVal vpbEnabled As Boolean)
picCage.Enabled = vpbEnabled
mnuPBEnabled.Checked = vpbEnabled
End Property
LVL 13

Expert Comment

ID: 1437333
Hmmm, this only works after the window is visible....

Author Comment

ID: 1437334
I rejected the answer out of two reasons:
1. what mirkwood said, about how it only works after the window is visible... I can work around it, but it's still no good solution
2. I don't understand how to remove the caption and so on... I don't want the complete dialog inside the form, just the contents of the dialog... (look in VB as I mentioned in the question if you don't understand)
LVL 13

Expert Comment

ID: 1437335
2) To remove the caption and so one see my answer. The SetWindowLong will do this trick for you.

Author Comment

ID: 1437336
nope, it won't... I've tried with the hwnd I retrieved from findwindow, I thought it would work fine, b/c SetWindowPos changes the width of the window to match with the picturebox in AllenC_Jr's example...
but, what happens when that window is the CommonSaveFileDialog, well to be short...
so, can you guess how much happens with the SetWindowLong function???
nothing... unfortunately...
just discovered that I must have done something wrong b/c the titlebar does not disappear for any window and so on... strange...
must have done something wrong...

Expert Comment

ID: 1437337
Basically You want just to view the contents of a folder through a form?

If so I can give you a link to a site that has made a copy of this object(uses api calls to get the info on each file).

If that is what you want just say so...

Author Comment

ID: 1437338
well, basicly yes... but as you see in my question, I also want to know if it's possible with the commondialog...

Expert Comment

ID: 1437339
the common dialog control is an invisible control that uses simple api calls to a dll, it was not intended for you to view the contents of a folder through the use of that control. If there is a Way to do what you have done then even I would like to know

Expert Comment

ID: 1437340
Well, If I understand this all you want is a browse for files in a form.
Why don't you just put a Drive control, a Dir control, and a File list control?
And link them together?
You can make it look just as you want

Author Comment

ID: 1437341
That was not what i was looking for... of course I know I can do it that way... I just wanted to know if it is possible to have the common save file dialog inside another window in Visual Basic...

Expert Comment

ID: 1437342
If You know the way to set the dialog's left and top to negative positions before it is loaded then show it and capture it with the procedure I gave you...

Accepted Solution

AnswerTheMan earned 200 total points
ID: 1437343
in Visual C++ 5.0 u can inherit that Dialog into your dialog class, and add controls of yours around it, but even there - you
can't access the inside of the CommonDialog.
i had a long fight against that CommonDialog using C++, and finally i quit.
in less time that that fight took me - i built my own in VB, which is much better and flexible.
i advise u to do the same.

Author Comment

ID: 1437344
well, by now I'm fairly convinced that it's quite troublesome... if you have done one yourself, you could pass the source code, couldn't you?
It would feel unnescesary to redo the same thing once again.. and also it would save me a lot of time...


Expert Comment

ID: 1437345's a whole ActiveX control. ppl use to sale such things....
it's not just a piece of code to paste here.
sorry man, but it's really not hard thing to do.
make the user interface first - and then put a little code here and there.

Expert Comment

ID: 1437346
who is that refering to? (Grdv)

did you get the e-mail i sent you?

Author Comment

ID: 1437347
well, I'll look into it, and see if I have time to do my own control... might have to discard the idea... :(
don't have time right now... unfortunately...
AllenC_Jr: just want to know, who you are reffering to, if the email thingie is to me, then no... I haven't got any mail from you...

Author Comment

ID: 1437348
well, this was not really what I was looking for, but as noone came up with a good solution...


Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Most everyone who has done any programming in VB6 knows that you can do something in code like Debug.Print MyVar and that when the program runs from the IDE, the value of MyVar will be displayed in the Immediate Window. Less well known is Debug.Asse…
Background What I'm presenting in this article is the result of 2 conditions in my work area: We have a SQL Server production environment but no development or test environment; andWe have an MS Access front end using tables in SQL Server but we a…
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question