OpenFileDialog & Fensterfocus



  • Hi, mir ist eben ein komischer Effekt aufgefallen.

    Ich hab einen button mit nem openfiledlg hinterlegt. Bevor ich draufklicke ist das GUI-Fenster so im Focus wie es sein soll, schließen ist rot und die anderen in rahmenfarbe. sobald ich den button klicke und eine datei öffne oder den filedlg abrreche, bekommt die gui keinen focus, das heißt, der schließen button oben rechts wird nicht mehr rot, erst wenn ich in irgendein anderes programmfenster klicke oder in der taskleiste auf mein programm zum minimieren maximieren klicke wirds wieder normal. jemand ne ahnung was das sein könnte.

    ich hab den gleiche quellcode für den openfiledlg genommen wie auch für ein anderes programm, da gehts:

    CString pathName;  
    TCHAR szFilters[]= _T("Text Files (*.txt)|*.txt|All Files (*.*)|*.*||"); 
    CFileDialog fileDlg( TRUE, _T("txt"), _T("*.txt"), OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, szFilters); 
    
    if( fileDlg.DoModal() == IDOK) 
    {...}
    

    da ich nicht glaube dass es am code liegt frage ich mich, was kann das sein? ich mache immer die gleichen einstellungen bei der projekterstellung, immer dialogbasierend mit statisch gelinkten libs...



  • da ich nicht weiß ob mein problem richtig verstandne wurde, frag ich nochmal nach. wisst ihr was ich meine?
    ich wills echt verstehen und lernen, aber das hier ist mir ein rätsel



  • Schwer zu sagen. Ich wüsste auf Anhieb nicht, woran das genau liegen sollte.
    Du kannst aber nach dem Schließen des FileDialogs noch SetFocus auf einem deiner Fenster aufrufen.



  • Dasselbe Problem habe ich auch in einer MFC-Anwendung. Bisher habe ich auch noch keine Lösung gefunden. Und um die MFC zu debuggen, war es mir nicht wichtig genug. (Ernsthafte GUIs mache ich eh mit der VCL.)

    Seltsamerweise hat das zuletzt fokussierte Control des Parent-Fensters nach dem Schließen des Dialogs wieder den Fokus, d.h. man kann es bedienen und mit Tab/Shift+Tab darin navigieren. Aber das Top-Level-Fenster scheint keinen Fokus zu haben oder wahrzunehmen. Möglicherweise hängt es damit zusammen, wie der Dialog als Child-Control in das Top-Level-Fenster eingebunden wird, oder mit einem Mißverständnis bei der Message-Loop-Behandlung (bei Dialogen wird das Message-Dispatching ein bißchen anders gehandhabt als bei gewöhnlichen Fenstern, evtl. bringen die MFC da etwas durcheinander).



  • ok, ich bin schonmal nicht der einzige 😃 setfocus hilft nicht, komischerweise ist der fensterfocus nach nach dem schließen des filedlgs weg, aber sobald ich in einen anderes programm klicke oder auf den desktop bekommt die anwendung den focus wieder. ich mache das an dem roten schließen-x rechts oben fest.

    hab gestern mal alle guis die ich bisher gemacht hab durchgesehen, bei einer gehts richtig. weiß der teufel wieso 😃



  • Das liegt daran dass ihr euren Dialog von der falschen Klasse ableitet!
    Kann man das so sagen? (Ich weiß es nicht, bin ja eigentlich Hardware-Entwickler, daher bitte ich um Nachsicht und um Korrektur wenn ich manche Begriffe falsch benutze)

    Jedenfalls müsst ihr, wenn euch das so sehr stört, in eurer xyzDlg.h bei der Erstellung der Dialogklasse, CDialogEx durch CDialog ersetzen:

    class CxyzDlg : public CDialogEx
    

    wird zu

    class CxyzDlg : public CDialog
    

    Anschließend in eurer xyzDlg.cpp ebenfalls.

    Abrakadabra, 3 mal schwarzer Kater... den Rest kennt ihr ja.


  • Mod

    Ich würde eherdarauf tippen, dass Du dem Dialog das Parent Window korrekt mit übergibst.

    Die MFC versucht zwar das Parent zu ermitteln, aber das klappt oft genug nicht richtig.



  • Martin Richter schrieb:

    Ich würde eherdarauf tippen, dass Du dem Dialog das Parent Window korrekt mit übergibst.

    Bitte, das war das erste, was ich probiert habe. Das ändert nichts, außerdem ist das nur Rumgestochere.

    Stutzpeter schrieb:

    Das liegt daran dass ihr euren Dialog von der falschen Klasse ableitet!

    Das war zwar der Wizard und nicht ich, aber ich hab mal versucht, von CDialog abzuleiten, und siehe da, es funktioniert.

    Der Grund ist, daß CDialogEx die OnNcActivate() -Methode überschreibt und (absichtlich) nicht die Basisklassen-Methode aufruft:

    BOOL CDialogEx::OnNcActivate(BOOL bActive)
    {
    	m_Impl.OnNcActivate(bActive);
    
    	// Do not call the base class because it will call Default()
    	// and we may have changed bActive.
    	return(BOOL) DefWindowProc(WM_NCACTIVATE, bActive, 0L);
    }
    

    Wenn man den DefWindowProc() -Aufruf durch einen konditionellen Aufruf der überschriebenen Funktion ersetzt, dann funktioniert es:

    BOOL CDialogEx::OnNcActivate(BOOL bActive)
    {
    	BOOL oldValue = bActive;
    	m_Impl.OnNcActivate(bActive);
    
    	// Only call the base class if bActive was unchanged because
    	// it will call Default() which for some reason seemed undesirable
    	// to the original authors of this code
    	if (bActive != oldValue)
    		return(BOOL) DefWindowProc(WM_NCACTIVATE, bActive, 0L);
    	else
    		return CDialog::OnNcActivate(bActive);
    }
    

    Die Diskussion in [1] legt allerdings nahe, daß das so gewollt ist, und daß man für Dialoge mit herkömmlichem Fokusverhalten von CDialog statt CDialogEx erben sollte. Kommt mir nur etwas seltsam vor, daß deshalb das Standardverhalten von dem der Basisklasse abweichen muß.

    [1] https://social.msdn.microsoft.com/Forums/de-DE/0d863f9f-cee5-4bda-9ec3-d9e2c525eeb6/why-is-a-modal-cdialogex-does-not-flash-when-you-click-outside-of-it?forum=vcgeneral



  • audacia schrieb:

    Stutzpeter schrieb:

    Das liegt daran dass ihr euren Dialog von der falschen Klasse ableitet!

    Das war zwar der Wizard und nicht ich, aber ich hab mal versucht, von CDialog abzuleiten, und siehe da, es funktioniert.

    Vollkommen richtig, umso mehr ein Zeichen dafür, dass es gewollt ist. Warum auch immer...


Anmelden zum Antworten