Standarddialog zur Pfadauswahl



  • Hallo.

    In meinem Programm soll der User die Möglichkeit bekommen, den Standardpfad für die Dateiablage ändern zu können. Ich war der Meinung es gäbe da einen Standarddialog, allerdings finde ich den nicht mehr. CFileDialog() ist aus meiner Sicht nicht unbedingt brauchbar, da ich nur den Pfad brauche und nicht eine ausgewählte Datei. Oder gibt es dafür ein Steuerelement, welches man in ein Dialogfenster einbauen kann?



  • Ich kenn nur CFileDialog. Aber aus den GetMethoden kann man sich doch den Pfad extrahieren.



  • SHBrowseForFolder() heisst die Funktion die du suchst. (WINAPI)



  • auch in der MFC -.- Hmm.. F.A.Q.



  • Zunächst vielen Dank.
    Also erstes habe ich folgenden Code ausprobiert:

    void CtestiniDoc::OnTestBrowse()
    {
    	// TODO: Fügen Sie hier Ihren Befehlsbehandlungscode ein.
    	CoInitialize(NULL); //funktioniert auch ohne diesen Aufruf
    	BROWSEINFO bi;
    	memset( &bi, 0, sizeof( BROWSEINFO ) );
    	bi.hwndOwner = AfxGetMainWnd()->GetSafeHwnd();
    	bi.lpszTitle = "Bitte wählen Sie ein Verzeichnis...";
    	bi.ulFlags = BIF_RETURNONLYFSDIRS;
    
    	ITEMIDLIST* pList = SHBrowseForFolder( &bi );
    	if( pList )
    		{
    			char szFolder[MAX_PATH+1]="";
    			if( SHGetPathFromIDList( pList, szFolder) )
    				{
    					TRACE("%s\n",szFolder);
                        //Sichern des Pfadstrings
    				}
    
    			LPMALLOC pMalloc=NULL;
    			if( S_OK == SHGetMalloc( &pMalloc ) )
    				{
    					pMalloc->Free( pList );
    					pMalloc->Release();
    				}
    		}
    	CoUninitialize();
    }
    

    Das funktioniert auch soweit ganz gut. Jetzt will ich aber beim Aufruf des Fensters ein voreingestelltes (vorselektiertes) Verzeichnis auswählen, ohne dieses Verzeichnis zum Root zu machen. Ich habe dann gesehen, dass heute schon mal jemand die gleiche Frage hatte. Im besagten Thread wurde auf http://forum.fachinformatiker.de/showthread.php?t=82656 verwiesen. Somit hab ich meinen Code wie folgt anpassen wollen:

    void CtestiniDoc::OnTestBrowse()
    {
    	// TODO: Fügen Sie hier Ihren Befehlsbehandlungscode ein.
    	CoInitialize(NULL);
    	BROWSEINFO bi;
    	memset( &bi, 0, sizeof( BROWSEINFO ) );
    	bi.hwndOwner = AfxGetMainWnd()->GetSafeHwnd();
    	bi.lpszTitle = "Bitte wählen Sie ein Verzeichnis...";
    	bi.ulFlags = BIF_RETURNONLYFSDIRS;
    	bi.lpfn = (BFFCALLBACK) &BrowseCallbackProc;
    	bi.lParam = (LPARAM)this;
    
    	ITEMIDLIST* pList = SHBrowseForFolder( &bi );
    	if( pList )
    		{
    			char szFolder[MAX_PATH+1]="";
    			if( SHGetPathFromIDList( pList, szFolder) )
    				{
    					TRACE("%s\n",szFolder);
                        //Sichern des Pfadstrings
    				}
    
    			LPMALLOC pMalloc=NULL;
    			if( S_OK == SHGetMalloc( &pMalloc ) )
    				{
    					pMalloc->Free( pList );
    					pMalloc->Release();
    				}
    		}
    	CoUninitialize();
    }
    
    int CALLBACK CtestiniDoc::BrowseCallbackProc(HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
    {
    	//tue irgendwas
    	return 0;
    }
    

    Der Compiler meckert immer bei der Zeile:

    bi.lpfn = (BFFCALLBACK) &BrowseCallbackProc;
    

    und bringt die Meldung:
    error C2276: '&': Ungültige Operation auf Ausdruck einer gebundenen Memberfunktion

    In dem Beispiel solls aber funktionieren. Was mach ich da falsch oder gibts da noch eine andere Möglichkeit?



  • AndyDD schrieb:

    In dem Beispiel solls aber funktionieren. Was mach ich da falsch oder gibts da noch eine andere Möglichkeit?

    In dem Beispiel ist es keine Memberfunktion (oder eine statische Memberfunktion).



  • Es ist aber doch eine Memberfunktion...

    int CALLBACK CMyDlg::BrowseCallbackProc(HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
    {
    return 0;
    }
    

    ...aufgerufen wird die ja aus

    void CMyDlg::OnBuFolder()
    {
    }
    

    Oder seh ich das falsch?
    Wie bekommt man das dann trotzfrm zum Laufen?



  • AndyDD schrieb:

    Es ist aber doch eine Memberfunktion...

    Ja, aber eine statische. Deine ist nicht statisch.



  • Sorry, aber ich glaube ich steh grad auf dem Schlauch. Ich seh nicht auf Anhieb, dass die statisch ist. Ich habs ja genauso implementiert wie es da steht.



  • AndyDD schrieb:

    Sorry, aber ich glaube ich steh grad auf dem Schlauch. Ich seh nicht auf Anhieb, dass die statisch ist.

    Das kannst du auch nicht. Dass die statisch ist, steht bei der Deklaration dieser Methode, innerhalb der Klassendeklaration.



  • Kannst Du mal die Stelle posten wo das steht?



  • Das steht explizit nirgendwo. Schaffst du es nicht, ohne Abschreibvorlage das Wörtchen static vor die Deklaration dieser Methode zu schreiben oder die Methode aus der Klasse rauszunehmen?



  • Doch das schaff ich, bin ja schon groß. Das war gleich das erste was ich ausprobiert habe. Bisher meckerte der Compiler an dieser Stelle. Hab jetzt aber nochmal bereinigt und jetzt gehts komischerweise...



  • Ich muss das Thema leider nochmal aufkochen. Wo bekomme ich zurück welche Taste (Ok oder Abbrechen) der Anwender gedrückt hat?
    Momentan wird immer läuft das Programm immer so als wären Änderungen gemacht und anschließen OK gedrückt worden. Blöd ist, wenn man nur das Fenster öffnet und gleich mit Abbrechen wieder schließt. 😮 Diesen Fall möchte ich abfangen.
    Weiß jemand wo das geht?

    Vorab vielen Dank.



  • AndyDD schrieb:

    Weiß jemand wo das geht?

    Die MSDN Library weiß das. Da steht über den Rückgabewert von SHBrowseForFolder:

    "If the user chooses the Cancel button in the dialog box, the return value is NULL."



  • Ja vielen Dank erst mal. Ich habe das ein wenig anders mit Hilfe einer boolschen Variable gelöst:

    BOOL bFolderChanged=FALSE;
    	CoInitialize(NULL);
    	BROWSEINFO bi;
    	memset( &bi, 0, sizeof( BROWSEINFO ) );
    	bi.hwndOwner = AfxGetMainWnd()->GetSafeHwnd();
    	bi.lpszTitle = "Bitte wählen Sie ein Verzeichnis...";
    	bi.ulFlags = BIF_RETURNONLYFSDIRS;
    	bi.lpfn = (BFFCALLBACK) &BrowseCallbackProc;
    	bi.lParam = (LPARAM)this;
    
    	ITEMIDLIST* pList = SHBrowseForFolder( &bi );
    	if( pList )
    		{
    			char szFolder[MAX_PATH+1]="";
    			if( SHGetPathFromIDList( pList, szFolder) )
    				{
    					m_csFolder=szFolder;
    					m_csIniPath=m_csFolder+m_csFilename;
    					bFolderChanged=TRUE;
    				}
    
    			LPMALLOC pMalloc=NULL;
    			if( S_OK == SHGetMalloc( &pMalloc ) )
    				{
    					pMalloc->Free( pList );
    					pMalloc->Release();
    				}
    		}
    	CoUninitialize();
    
    	//Sichern der Einstellungen in der Registry
    	if (bFolderChanged==TRUE)
    		{	
              //Übernehmen der Änderungen
            }
    

    Ist vielleicht nicht eine elegante Lösung aber sie funktioniert.


Anmelden zum Antworten