Die Community zu .NET und Classic VB.
Menü

VB 5/6-Tipp 0346: Öffnen/Speichern-Dialog mit eigenen Steuerelementen erweitern

 von 

Beschreibung 

Dieser Tipp besteht aus einer Klasse, mit der man den Standard-Öffnen/Speichern-Dialog (aus den Common Controls) um eigene Controls erweitern kann, z.B. um Infos zu der gewählten Datei anzeigen zu lassen.

Schwierigkeitsgrad:

Schwierigkeitsgrad 2

Verwendete API-Aufrufe:

RtlMoveMemory (CopyMemory), GetOpenFileNameA (GetOpenFileName), GetParent, GetSaveFileNameA (GetSaveFileName), GetSystemMetrics, GetWindowRect, MoveWindow, PathFileExistsA (PathFileExists), PathIsDirectoryA (PathIsDirectory), SendMessageA (SendMessageString), SetParent

Download:

Download des Beispielprojektes [8,13 KB]

'Dieser Quellcode stammt von http://www.activevb.de
'und kann frei verwendet werden. Für eventuelle Schäden
'wird nicht gehaftet.

'Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum.
'Ansonsten viel Spaß und Erfolg mit diesem Source!

'------- Anfang Projektdatei pCustomCommonDialog.vbp  -------
'------- Anfang Formular "frmTest" alias frmTest.frm  -------
' Steuerelement: Bildfeld-Steuerelement "Picture1"
' Steuerelement: Beschriftungsfeld "lblFileName" auf Picture1
' Steuerelement: Beschriftungsfeld "Label1" auf Picture1
' Steuerelement: Schaltfläche "Command1"
' Steuerelement: Beschriftungsfeld "Label2"

Option Explicit

'Teile des Codes stammen von
'http://vbaccelerator.com/home/index.asp

Private WithEvents X As cCommonDialog

Private Sub Command1_Click()
X.ControlToSetNewParent = Picture1

'X.ControlAlign = Bottom
'X.OpenInitialDir = "H:\Dateien von Ingmar"
'X.OpenFlags = X.OpenFlags Xor OFN_HIDEREADONLY ' Xor zum entfernen von Flags
'X.OpenFlags = X.OpenFlags + OFN_ALLOWMULTISELECT ' + zum hinzufügen von Flags

Debug.Print X.ShowOpen(Me.hWnd)

End Sub

Private Sub Form_Load()
Set X = New cCommonDialog
Set ccClass = X ' Nicht vergessen!
End Sub

Private Sub X_DialogClosed()
'MsgBox "CLOSED!"
End Sub

Private Sub X_DialogInitialized()
'MsgBox "INITIALIZED!"
End Sub

Private Sub X_FileChanged(ByVal FileName As String)
' Hier kann man viele tolle Sachen machen...
lblFileName.Caption = Mid(FileName, InStrRev(FileName, "\") + 1)
End Sub

Private Sub X_FolderChanged(ByVal Path As String)
'MsgBox "FOLDER: " & Path
End Sub

Private Sub X_PressedOKButton()
'MsgBox "I'M DONE!"
End Sub
'-------- Ende Formular "frmTest" alias frmTest.frm  --------
'--- Anfang Klasse "cCommonDialog" alias cCommonDialog.cls  ---

Option Explicit

'#############################################################
' Modul: cCommonDialog.cls
' Ermöglicht es, den Standard-Öffnen/Speichern-Dialog mit eigenen
' Controls zu erweitern
' benötigt wird: basCommonDialog.bas
'
' © by I.Runge 2003 (mastermind@ircastle.de)
'
'#############################################################


' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
' DEKLARATION DER KONSTANTEN

' Windows-Nachrichten:
Const WM_USER = &H400
Const WM_DESTROY = &H2
Const WM_NOTIFY = &H4E
Const WM_NCDESTROY = &H82
Const WM_GETDLGCODE = &H87
Const WM_INITDIALOG = &H110

' Benachrichtigungen, wenn sich im Dialog etwas ereignet:
Const CDN_FIRST = (-601)
Const CDN_LAST = (-699)
Const CDN_INITDONE = (CDN_FIRST - &H0)
Const CDN_SELCHANGE = (CDN_FIRST - &H1)
Const CDN_FOLDERCHANGE = (CDN_FIRST - &H2)
Const CDN_SHAREVIOLATION = (CDN_FIRST - &H3)
Const CDN_HELP = (CDN_FIRST - &H4)
Const CDN_FILEOK = (CDN_FIRST - &H5)
Const CDN_TYPECHANGE = (CDN_FIRST - &H6)
Const CDN_INCLUDEITEM = (CDN_FIRST - &H7)

' Nachrichten, die an die Dialog-Elemente gesandt werden können:
Const CDM_FIRST = (WM_USER + 100)
Const CDM_LAST = (WM_USER + 200)
Const CDM_GETSPEC = (CDM_FIRST + &H0)
Const CDM_GETFILEPATH = (CDM_FIRST + &H1)
Const CDM_GETFOLDERPATH = (CDM_FIRST + &H2)
Const CDM_GETFOLDERIDLIST = (CDM_FIRST + &H3)
Const CDM_SETCONTROLTEXT = (CDM_FIRST + &H4)
Const CDM_HIDECONTROL = (CDM_FIRST + &H5)
Const CDM_SETDEFEXT = (CDM_FIRST + &H6)

' GetSystemMetrics-Konstanten zur Bestimmung von Fensterabmaßen
Const SM_CXDLGFRAME = 7 ' Breite des unteren/oberen Fensterrahmens
Const SM_CYDLGFRAME = 8 ' Breite des rechten/linken Fensterrahmens
Const SM_CYCAPTION = 4  ' Höhe der Titelzeile

Const MAX_PATH = 260

' Konstanten für die Optionen der Dialoge:
Public Enum CdlFlags
    OFN_ALLOWMULTISELECT = &H200 ' mehrere Dateien können gewählt werden
    OFN_CREATEPROMPT = &H2000
    OFN_ENABLEHOOK = &H20
    OFN_ENABLETEMPLATE = &H40
    OFN_ENABLETEMPLATEHANDLE = &H80
    
    ' Dateien werden durch Null-Zeichen getrennt
    OFN_EXPLORER = &H80000
    
    OFN_EXTENSIONDIFFERENT = &H400
    
    ' Es können nur Dateien gewählt werden, die auch existieren
    OFN_FILEMUSTEXIST = &H1000
    
    ' Die Checkbox "schreibgeschützt öffnen" wird nicht angezeigt
    OFN_HIDEREADONLY = &H4
    
    OFN_LONGNAMES = &H200000
    
    ' geht nicht
    OFN_NOCHANGEDIR = &H8
    
    OFN_NODEREFERENCELINKS = &H100000
    OFN_NOLONGNAMES = &H40000
    OFN_NONETWORKBUTTON = &H20000
    OFN_NOREADONLYRETURN = &H8000&
    OFN_NOTESTFILECREATE = &H10000
    OFN_NOVALIDATE = &H100
    
    ' Es wird gefragt, bevor eine Datei überschrieben wird
    OFN_OVERWRITEPROMPT = &H2
    
    ' Es können nur Dateien in Ordnern gewählt werden, die auch existieren
    OFN_PATHMUSTEXIST = &H800
    
    OFN_READONLY = &H1
    OFN_SHAREAWARE = &H4000
    OFN_SHAREFALLTHROUGH = 2
    OFN_SHARENOWARN = 1
    OFN_SHAREWARN = 0
    OFN_SHOWHELP = &H10
End Enum

Public Enum eCCDLG_AlignConstants
    Right = 0
    Bottom = 1
End Enum


' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
' DEKLARATION DER TYPEN-STRUKTUREN

Private Type RECT
   Left As Long
   Top As Long
   Right As Long
   Bottom As Long
End Type

' Windows-Message-Typ:
Private Type NMHDR
    hwndFrom As Long
    IDfrom As Long
    Code As Long
End Type

' Struktur für Aufruf der APIs:
Private Type OPENFILENAME
    lStructSize As Long
    hwndOwner As Long
    hInstance As Long
    lpstrFilter As String
    lpstrCustomFilter As String
    nMaxCustFilter As Long
    nFilterIndex As Long
    lpstrFile As String
    nMaxFile As Long
    lpstrFileTitle As String
    nMaxFileTitle As Long
    lpstrInitialDir As String
    lpstrTitle As String
    flags As Long
    nFileOffset As Integer
    nFileExtension As Integer
    lpstrDefExt As String
    lCustData As Long
    lpfnHook As Long
    lpTemplateName As String
End Type

' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
' DEKLARATION DER API-Funktionen

' Kernel32-Library
Private Declare Sub CopyMemory Lib "kernel32.dll" _
                    Alias "RtlMoveMemory" ( _
                    Destination As Any, _
                    Source As Any, _
                    ByVal Length As Long)
                    
' Shlwapi-Library
Private Declare Function PathIsDirectory Lib "shlwapi.dll" _
                         Alias "PathIsDirectoryA" ( _
                         ByVal pszPath As String) As Long
                         
Private Declare Function PathFileExists Lib "shlwapi.dll" _
                         Alias "PathFileExistsA" ( _
                         ByVal pszPath As String) As Long
                         
' User32-Library
Private Declare Function GetSystemMetrics Lib "user32" ( _
                         ByVal nIndex As Long) As Long
                         
Private Declare Function GetParent Lib "user32" ( _
                         ByVal hWnd As Long) As Long
                         
Private Declare Function SetParent Lib "user32" ( _
                         ByVal hWndChild As Long, _
                         ByVal hWndNewParent As Long) As Long
                         
Private Declare Function MoveWindow Lib "user32" ( _
                         ByVal hWnd As Long, _
                         ByVal X As Long, _
                         ByVal Y As Long, _
                         ByVal nWidth As Long, _
                         ByVal nHeight As Long, _
                         ByVal bRepaint As Long) As Long
                         
Private Declare Function GetWindowRect Lib "user32" ( _
                         ByVal hWnd As Long, _
                         lpRect As RECT) As Long
                         
Private Declare Function SendMessageString Lib "user32.dll" _
                         Alias "SendMessageA" ( _
                         ByVal hWnd As Long, _
                         ByVal wMsg As Long, _
                         ByVal wParam As Long, _
                         ByVal lParam As String) As Long
                         
' ComDlg32-Library
Private Declare Function GetOpenFileName Lib "comdlg32.dll" _
                         Alias "GetOpenFileNameA" ( _
                         pOFN As OPENFILENAME) As Long
                         
Private Declare Function GetSaveFileName Lib "comdlg32.dll" _
                         Alias "GetSaveFileNameA" ( _
                         pOFN As OPENFILENAME) As Long

' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
' Variablen zum internen Speichern der Werte der Eigenschaften

Private m_fOpenFlags As CdlFlags
Private m_fSaveFlags As CdlFlags
Private m_sOpenFilter As String
Private m_sSaveFilter As String
Private m_lOpenMaxFileLen As Long
Private m_lSaveMaxFileLen As Long
Private m_sOpenDialogTitle As String
Private m_sSaveDialogTitle As String
Private m_sOpenInitialDir As String
Private m_sSaveInitialDir As String
Private m_cControl As Control
Private m_eAlign As eCCDLG_AlignConstants

' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
' EREIGNISSE

' Eine andere Datei wurde gewählt
Public Event FileChanged(ByVal FileName As String)

' Ein anderer Ordner wurde gewählt
Public Event FolderChanged(ByVal Path As String)

' Dialog wird gezeigt
Public Event DialogInitialized()

' Dialog wird geschlossen
Public Event DialogClosed()

' Es wurde "Öffnen" bzw. "Speichern" gedrückt
Public Event PressedOKButton()

' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
' EIGENSCHAFTEN

' Control, das in das Dialog-Fenster "gebeamt" werden soll:
Property Get ControlToSetNewParent() As Control
    Set ControlToSetNewParent = m_cControl
End Property

Property Let ControlToSetNewParent(cNew As Control)
    Set m_cControl = cNew
End Property


' Flags zum Öffnen-Dialog
Property Get OpenFlags() As CdlFlags
    OpenFlags = m_fOpenFlags
End Property

Property Let OpenFlags(fNew As CdlFlags)
    m_fOpenFlags = fNew
End Property


' Filter für den Öffnen-Dialog
Property Get OpenFilter() As String
    OpenFilter = m_sOpenFilter
End Property

Property Let OpenFilter(sNew As String)
    m_sOpenFilter = sNew
End Property


' Ausrichtung des Controls, unten oder rechts
Property Get ControlAlign() As eCCDLG_AlignConstants
    ControlAlign = m_eAlign
End Property

Property Let ControlAlign(ByVal eNew As eCCDLG_AlignConstants)
    m_eAlign = eNew
End Property


' Fenstertitel für den Öffnen-Dialog
Property Get OpenDialogTitle() As String
    OpenDialogTitle = m_sOpenDialogTitle
End Property

Property Let OpenDialogTitle(sNew As String)
    m_sOpenDialogTitle = sNew
End Property


' Startverzeichnis für den Öffnen-Dialog
Property Get OpenInitialDir() As String
    OpenInitialDir = m_sOpenInitialDir
End Property

Property Let OpenInitialDir(sNew As String)
    m_sOpenInitialDir = sNew
End Property


' Maximale Zeichenanzahl des Dateinamens im Öffnen-Dialog
Property Get OpenMaxFileLen() As String
    OpenMaxFileLen = m_lOpenMaxFileLen
End Property

Property Let OpenMaxFileLen(lNew As String)
    m_lOpenMaxFileLen = lNew
End Property


' Startverzeichnis für den Speichern-Dialog
Property Get SaveInitialDir() As String
    SaveInitialDir = m_sSaveInitialDir
End Property

Property Let SaveInitialDir(sNew As String)
    m_sSaveInitialDir = sNew
End Property


' Optionen für den Speichern-Dialog
Property Get SaveFlags() As CdlFlags
    SaveFlags = m_fSaveFlags
End Property

Property Let SaveFlags(fNew As CdlFlags)
    m_fSaveFlags = fNew
End Property


' Filter für den Speichern-Dialog
Property Get SaveFilter() As String
    SaveFilter = m_sSaveFilter
End Property

Property Let SaveFilter(sNew As String)
    m_sSaveFilter = sNew
End Property


' Fenstertitel für den Speichern-Dialog
Property Get SaveDialogTitle() As String
    SaveDialogTitle = m_sSaveDialogTitle
End Property

Property Let SaveDialogTitle(sNew As String)
    m_sSaveDialogTitle = sNew
End Property


' Maximale Zeichenanzahl des Dateinamens im Speichern-Dialog
Property Get SaveMaxFileLen() As String
    SaveMaxFileLen = m_lSaveMaxFileLen
End Property

Property Let SaveMaxFileLen(lNew As String)
    m_lSaveMaxFileLen = lNew
End Property

' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
' HAUPT-FUNKTIONEN

' Zeigt das Öffnen-Dialog-Fenster an und liefert die ausgewählte Datei zurück.
Public Function ShowOpen(ByVal hwndOwner As Long) As String
    Dim sBuf As String
    Dim r As Long
    Dim OFN As OPENFILENAME
    
    ' Buffer erstellen
    sBuf = String(m_lOpenMaxFileLen, 0)
    
    If (m_fOpenFlags And OFN_ENABLEHOOK) <> OFN_ENABLEHOOK Then
        m_fOpenFlags = m_fOpenFlags + OFN_ENABLEHOOK
    End If
    
    ' Struktur füllen
    With OFN
        .lStructSize = Len(OFN)
        .flags = m_fOpenFlags
        .hInstance = App.hInstance
        .hwndOwner = hwndOwner
        .lpfnHook = addr(AddressOf ComDlgCallback)
        .lpstrFile = sBuf
        .lpstrFilter = Replace(m_sOpenFilter, "|", vbNullChar)
        .lpstrInitialDir = m_sOpenInitialDir
        .lpstrTitle = m_sOpenDialogTitle
        .nFilterIndex = 1
        .nMaxFile = Len(sBuf)
        
        ' API-Aufruf
        r = GetOpenFileName(OFN)
        
        ' Hat alles geklappt?
        If r <> 0 Then
            ShowOpen = Left(.lpstrFile, InStr(.lpstrFile, vbNullChar) - 1)
        End If
    End With
End Function

Public Function ShowSave(ByVal hwndOwner As Long) As String
    Dim sBuf As String
    Dim r As Long
    Dim OFN As OPENFILENAME
    
    ' Buffer erstellen
    sBuf = String(m_lSaveMaxFileLen, 0)
    If (m_fSaveFlags And OFN_ENABLEHOOK) <> OFN_ENABLEHOOK Then
        m_fSaveFlags = m_fSaveFlags + OFN_ENABLEHOOK
    End If
    
    ' Struktur füllen
    With OFN
        .lStructSize = Len(OFN)
        .flags = m_fSaveFlags
        .hInstance = App.hInstance
        .hwndOwner = hwndOwner
        .lpfnHook = addr(AddressOf ComDlgCallback)
        .lpstrFile = sBuf
        .lpstrFilter = Replace(m_sSaveFilter, "|", vbNullChar)
        .lpstrInitialDir = m_sSaveInitialDir
        .lpstrTitle = m_sSaveDialogTitle
        .nFilterIndex = 1
        .nMaxFile = Len(sBuf)
        
        ' API-Aufruf
        r = GetSaveFileName(OFN)
        
        ' Hat alles geklappt?
        If r <> 0 Then
            ShowSave = Left(.lpstrFile, InStr(.lpstrFile, vbNullChar) - 1)
        End If
    End With
End Function

' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
' HILFS-FUNKTIONEN

' Wertet die vom Dialogfeld eingehenden Nachrichten aus
Public Sub pIncomingMessage(ByVal hWndDlg As Long, ByVal Msg As Long, _
    ByVal wParam As Long, ByVal lParam As Long)

    Dim tNMH As NMHDR
    Dim tR As RECT
    Dim lBorderSize As Long
    Dim lCaptionSize As Long
    Dim scHeight As Long
    Dim scWidth As Long
    Dim s As String
    Static OldhWnd As Long
    
    Select Case Msg
        Case WM_INITDIALOG
            If Not m_cControl Is Nothing Then
                
                ' Hier wird das Control ins Dialogfeld gesetzt:
                m_cControl.Visible = True
                
                ' Das alte Parent-Fenster speichern
                OldhWnd = GetParent(m_cControl.hWnd)
                lBorderSize = GetSystemMetrics(SM_CXDLGFRAME)
                lCaptionSize = GetSystemMetrics(SM_CYCAPTION)
                
                'Das Control auf dem neuen Fenster anzeicgen
                SetParent m_cControl.hWnd, GetParent(hWndDlg)
                
                ' Die Fensterausmaße des Dialog-Fensters erfassen
                GetWindowRect GetParent(hWndDlg), tR
                scHeight = Screen.Height / Screen.TwipsPerPixelY
                scWidth = Screen.Width / Screen.TwipsPerPixelX
                
                
                If m_eAlign = Right Then
                    
                    ' Das Dialog-Fenster platzieren:
                    MoveWindow GetParent(hWndDlg), tR.Left, tR.Top, _
                        tR.Right - tR.Left + m_cControl.Width \ _
                        Screen.TwipsPerPixelX + lBorderSize * 2, tR.Bottom - tR.Top, 1
                    
                    ' Das neue Control platzieren:
                    MoveWindow m_cControl.hWnd, tR.Right - tR.Left - lBorderSize, 4&, _
                        m_cControl.Width \ Screen.TwipsPerPixelX, _
                        tR.Bottom - tR.Top - lCaptionSize - _
                        GetSystemMetrics(SM_CYDLGFRAME) * 2 - 8, 1
                Else
                    
                    ' Das Dialog-Fenster platzieren:
                    MoveWindow GetParent(hWndDlg), tR.Left, tR.Top, _
                        tR.Right - tR.Left, tR.Bottom - tR.Top + _
                        m_cControl.Height \ Screen.TwipsPerPixelY - lBorderSize * 2, 1
    
                    ' Das neue Control platzieren:
                    MoveWindow m_cControl.hWnd, 4, _
                        tR.Bottom - tR.Top - lCaptionSize - _
                        GetSystemMetrics(SM_CYDLGFRAME) * 2 - 10, _
                        tR.Right - tR.Left - lBorderSize * 2 - 8, _
                        m_cControl.Height \ Screen.TwipsPerPixelY, 1
                                    
                End If
            End If
            
            RaiseEvent DialogInitialized
            
        Case WM_NOTIFY
            CopyMemory tNMH, ByVal lParam, Len(tNMH)
            
            Select Case tNMH.Code
                
                ' Auswahl gewechselt
                Case CDN_SELCHANGE
                    s = GetDlgPath(CDM_GETFILEPATH, hWndDlg)
                    If PathIsDirectory(s) = False And _
                        CBool(PathFileExists(s)) Then _
                        RaiseEvent FileChanged(s)
                    
                ' Ordner hat sich geändert
                Case CDN_FOLDERCHANGE
                    RaiseEvent FolderChanged(GetDlgPath(CDM_GETFOLDERPATH, _
                    hWndDlg))
                
                ' OK geklickt
                Case CDN_FILEOK
                    RaiseEvent PressedOKButton
                    
                'Case CDN_HELP
                '    RaiseEvent PressedHelpButton
                ' Es gibt keinen Help-Button...!?
                    
                Case CDN_TYPECHANGE
                    ' Datei-Typ-Liste hat gewechselt
                    
            End Select
        
        ' Das wars...!
        Case WM_DESTROY
            If Not m_cControl Is Nothing Then
                
                ' Das Control wieder auf den Platz zurücksetzen
                SetParent m_cControl.hWnd, OldhWnd
                m_cControl.Visible = False
            End If
            
            RaiseEvent DialogClosed
    End Select
End Sub

' Hilfsfunktion zur Bestimmung der Funktions-Adresse
Private Function addr(ByVal a As Long) As Long
    addr = a
End Function

' Fragt den aktuellen Datei- oder Ordner-Pfad ab
' (je nach Konstante)
Private Function GetDlgPath(ByVal lConst As Long, hWndDlg As Long) As String
    Dim sBuf As String
    Dim lPos As Long
    Dim hWnd As Long
    
    hWnd = GetParent(hWndDlg)
    sBuf = String(MAX_PATH, 0)
    SendMessageString hWnd, lConst, MAX_PATH, sBuf
    lPos = InStr(1, sBuf, vbNullChar)

    If lPos > 0 Then
          GetDlgPath = Left(sBuf, lPos - 1)
    Else
        GetDlgPath = sBuf
    End If
End Function

Private Sub Class_Initialize()
    ' Standard-Werte setzen:
    m_fOpenFlags = OFN_EXPLORER + OFN_ENABLEHOOK + _
        OFN_PATHMUSTEXIST + OFN_HIDEREADONLY + OFN_FILEMUSTEXIST
        
    m_fSaveFlags = OFN_EXPLORER + OFN_ENABLEHOOK + _
        OFN_HIDEREADONLY + OFN_OVERWRITEPROMPT + OFN_PATHMUSTEXIST
        
    m_sOpenFilter = "Alle Dateien (*.*)|*.*"
    m_sSaveFilter = "Alle Dateien (*.*)|*.*"
    m_lOpenMaxFileLen = MAX_PATH
    m_lSaveMaxFileLen = MAX_PATH
End Sub
'--- Ende Klasse "cCommonDialog" alias cCommonDialog.cls  ---
'--- Anfang Modul "basCommonDialog" alias basCommonDialog.bas ---

Option Explicit

'#############################################################
' Modul: basCommonDialog.bas.cls
' gehört zu: cCommonDialog.cls
'
' © by I.Runge 2003 (mastermind@ircastle.de)
'
'#############################################################

'An welche Klasse sollen die Messages geschickt werden?
Public ccClass As cCommonDialog

' Message-Empfänger, kann ohne größeren Aufwand nur in einem Modul sein
Public Function ComDlgCallback(ByVal hWndDlg As Long, ByVal Msg As Long, _
    ByVal wParam As Long, ByVal lParam As Long) As Long

If Not ccClass Is Nothing Then _
    ccClass.pIncomingMessage hWndDlg, Msg, wParam, lParam
End Function
'--- Ende Modul "basCommonDialog" alias basCommonDialog.bas ---
'-------- Ende Projektdatei pCustomCommonDialog.vbp  --------

Tipp-Kompatibilität:

Windows/VB-VersionWin32sWin95Win98WinMEWinNT4Win2000WinXP
VB4
VB5
VB6

Hat dieser Tipp auf Ihrem Betriebsystem und mit Ihrer VB-Version funktioniert?

Ja, funktioniert!

Nein, funktioniert nicht bei mir!

VB-Version:

Windows-Version:

Ihre Meinung  

Falls Sie Fragen zu diesem Artikel haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.

Archivierte Nutzerkommentare 

Klicken Sie diesen Text an, wenn Sie die 6 archivierten Kommentare ansehen möchten.
Diese stammen noch von der Zeit, als es noch keine direkte Forenunterstützung für Fragen und Kommentare zu einzelnen Artikeln gab.
Aus Gründen der Vollständigkeit können Sie sich die ausgeblendeten Kommentare zu diesem Artikel aber gerne weiterhin ansehen.

Kommentar von Mario Kretzschmar am 10.04.2010 um 13:17

Bei mir funktioniert es nur beim erstmaligen
"Öffnen". Schließe ich den Dialog und will
ein zweites Mal öffnen, dann bleibt die Picture-
box leer und der Dateiname (unten, nicht im Label)
wird auch nicht mehr angezeigt ?
System: XP SR2

Kommentar von Joe am 02.06.2006 um 11:01

Wenn ich den Parameter fuer Mehrfachauswahl angebe und auch mehrere Dateien auswaehle, werden diese nicht zurueckgeliefert ! (WinXP)
Sind die Berichtigungen von Ralf Brostedt eingearbeitet worden ?

Kommentar von Ralf Brostedt am 30.09.2004 um 14:12

An sich ein schöner Tipp, der allerdings ein paar Schwächen hat.
1. Selektiert man einen Ordner (ohne in ihn zu wechseln) und hatte man vorher eine Datei selektiert, dann gibt GetDlgPath(CDM_GETFILEPATH, hWndDlg) nach wie vor den noch im Textfeld stehenden Namen der Datei zurück (statt des selektierten Ordners). Ich habe keinen Weg gefunden, dieses Verhalten abzustellen.
2. Ab W2K hat der CommonDialog diese tolle "Places-Bar" (Arbeitsplatz, Desktop, etc.). Dieser Tipp kann das nicht, aber es ist machbar. Und zwar muss dazu die Struktur OPENFILENAME um drei weitere Elemente (Long, Long und das dritte hab ich vergessen, siehe msdn.microsoft.com) erweitert werden. Schon ist dieses Element auch da! Hat allerdings einen kleinen Haken: Unter älteren Windows-Versionen (Win9x, NT4) schmiert das Programm dann ab, weil die die erweiterte Struktur nicht kennen. Aber auch dafür gibt es Abhilfe: Man ermittelt die aktuelle Windowsversion (siehe entsprechender Tipp - einfach suchen), die MajorVersion reicht völlig aus. Ist diese 5 oder größer, dann ist lStructSize = Len(OFN), ansonsten ist lStructSize = 76 (das ist die Größe der "alten" OPENFILENAME Struktur. Das funktioniert perfekt!
4. Da generell die HookFunction verwendet wird, sollten die Zeilen

Flags = Flags + OFN_ENABLEHOOK
geändert werden in
Flags = Flags Or OFN_ENABLEHOOK Or OFN_EXPLORER

Setzt der Benutzer nämlich eigene Flags und vergisst dabei OFN_EXPLORER, kann es (zumindest auf älteren Windows-Versionen) knallen! (siehe MSDN zur OPENFILENAME Struktur)
3. Im API-Viewer fehlen ein paar OFN_-Kostanten für die Dialog-Flags, u.a. OFN_ALLOWRESIZE. Auch das kann man setzen, dann ist der Dialog vom Benutzer in der Größe änderbar. Allerdings wird die Hook-Function nicht aufgerufen, wenn die Größe sich ändert, da der Hook nicht am Dialog selbst, sondern an einem (unsichtbaren) Client-Control im Dialog hängt. Ich habe dazu mit GetParent() das hWnd des Dialogs genommen und mit SetWindowLong auch das Dialog-Fenster "ge-subclassed". Bei WM_INITDIALOG wird dann nur noch Position und Größe des Dialogs angepaßt und in der zweiten WindowProc erhält das (ggf. gesetzte) eigene Control bei WM_WINDOWPOSCHANGED seine eigentliche Position und Größe. Dabei darf man nicht vergessen, auch die alte WindowProc noch aufzurufen. Ändert man die Position und/oder Größe des Controls, sollte die alte WindowProc sogar VORHER aufgerufen werden (weil die das Control auch schon - allerdings nicht wie gewünscht - an die neue Größe anpaßt).
Außerdem hab ich für mich die Implemtierung noch ein wenig optimiert, wenn ich mal Zeit habe, kann ich den verbesserten Code (mit den o.g. Änderungen) ja noch hier reinsetzen (ich hoffe, solche langen Beiträge läßt das System zu).

Kommentar von Fritz Webering am 09.01.2004 um 17:57

Hi

Das Problem kann man auch einfacher lösen:

Statt Right$ einfach Strings.Right$ schreiben.
Strings ist nämlich das Modul in dem die Funktionen für die Bearbeitung von Strings stehen.

Greetz Fritz

Kommentar von Ingmar Runge am 25.08.2003 um 15:52

Hi!
Ja, hast du Recht. Kannst du aber einfach überall in der Klasse z.B. in [i]ccdlgRight[/i] und [i]ccdlgBottom[/i] ändern.

Kommentar von Jonathan Haas am 24.08.2003 um 14:53

Folgende Deklaration ergibt bei mir ein Problem:

Public Enum eCCDLG_AlignConstants
Right = 0
Bottom = 1
End Enum


Dadurch kann man die Right$() oder Right()-Funktion nicht mehr benutzen, weil VB jetzt irgendwie mit Right diese Konstante verknüpft...

Habe VB6