VB 5/6-Tipp 0346: Öffnen/Speichern-Dialog mit eigenen Steuerelementen erweitern
von I. Runge
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: | Verwendete API-Aufrufe: RtlMoveMemory (CopyMemory), GetOpenFileNameA (GetOpenFileName), GetParent, GetSaveFileNameA (GetSaveFileName), GetSystemMetrics, GetWindowRect, MoveWindow, PathFileExistsA (PathFileExists), PathIsDirectoryA (PathIsDirectory), SendMessageA (SendMessageString), SetParent | Download: |
'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-Version | Win32s | Win95 | Win98 | WinME | WinNT4 | Win2000 | WinXP |
VB4 | |||||||
VB5 | |||||||
VB6 |
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_ENABLEHOOKgeä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