Tabstops


  • Mod

    Du hast doch en CScrollView! Dann nutze das doch.
    ScrollWindow ist IMHO der falsche Ansatz. Zur Not (wenn kein CScrollView im Spiel ist) sende einen WM_xSCROLL/thumb Nachricht an Dich selbst und behandle das dort.

    Rollen musst da jetzt auch schon können. Es macht doch keinen Sinn, den Rollmechanismus überall in Deiner Klasse zu streuen.

    Bei einem Scrollview ist das ganz einfach:

    // pView ist ein CScrollView
    // Diese Werte Brauchen wir
    	CRect rcControl, rcParent;
    
    	// Erstmal das Client
    	pView->GetClientRect(&rcParent);
    	// Fenster Koordinaten bzgl. des Parents
    	Wnd()->GetWindowRect(&rcControl);
    	pView->ScreenToClient(&rcControl);
    
    	// Aktuelle Position bestimmen
    	CPoint ptScrollPosition= pView->GetScrollPosition();
    	// Verticales rollen?
    	CPoint ptNewScrollPosition = ptScrollPosition;
    
    	// Eine Unit Platz lasen
    	CSize sOffset = CSize(irgendwasx,irgendwasy);
    
    	// Vertikales rollen 
    	if (rcControl.left < rcParent.left)
    		// Verschieben nach links (Distanz ist Negativ)
    		ptNewScrollPosition.x += rcControl.left-rcParent.left-sOffset.cx;
    	else if (rcControl.right > rcParent.right)
    		// Verschieben nach rechts (Distanz ist positv)
    		ptNewScrollPosition.x += rcControl.right-rcParent.right+sOffset.cx;
    
    	// Horizontales rollen 
    	if (rcControl.top < rcParent.top)
    		// Verschieben nach oben (Distanz ist Negativ)
    		ptNewScrollPosition.y += rcControl.top-rcParent.top-sOffset.cy;
    	else if (rcControl.bottom > rcParent.bottom)
    		// Verschieben nach unten (Distanz ist positv)
    		ptNewScrollPosition.y += rcControl.bottom-rcParent.bottom+sOffset.cy;
    
    	/* Nun bliebt die Frage ob durch diesen Scroll Vorgang etwa
    		* die linke obere Ecke aus dem Fenster gerät */
    	rcControl.OffsetRect(ptScrollPosition-ptNewScrollPosition);
    	if (rcControl.left<0)
    		ptNewScrollPosition.x += rcControl.left;
    	if (rcControl.top<0)
    		ptNewScrollPosition.y += rcControl.top;
    
    	// Scroll nur wenn notwendig
    	if (ptScrollPosition!=ptNewScrollPosition)
    		pView->ScrollToPosition(ptNewScrollPosition);
    


  • Hi Martin,

    vieeelen Daaaank, da wäre ich wohl noch zwei Tage dran gesessen...

    Wie ich mir dachte, ein Problem gelöst schon taucht das nächste auf 😡 Meine Anwendung springt nur in die OnCommand wenn ich durch das Drücken der Tab-Taste auf eine Combo-Box komme, erreiche ich einen Button, komme ich erst garnicht in die OnCommand. Muss ich jetzt wieder irgendwelche "Spezialänderungen" an meiner Anwendung vornehmen oder muss ich das Ganze in einen Timer verlagern, sobald ich Buttons einsetze?


  • Mod

    Buttons haben keine Benachrichtigung für Focus bekommen/verlieren.

    Also Subclass Hook setzen und WM_SETFOCUS abfangen oder Timer nutzen. (Sagte ich das nicht schon...)



  • fehlpost



  • Hi,

    Ich hab den Thread gestartet, und mich auch inzwischen angemeldet. Ich hab das Ganze jetzt versucht zu implementieren, aber bin auf ein Problem gestoßen

    In einer Klasse die von CFormView abgeleitet ist gibt es die Methode ScrollToPosition(...) und die funktioniert auch ganz prima, aber in meiner Klasse, die von CDialog abgeleitet ist gibt es das leider nicht.

    Da gibt es nur folgende zwei Methoden

    SetScrollPos(...);
    ScrollWindow(...);

    Ich hab OnHScroll(...) überschrieben und ich komm mit dem Zusammenspiel beider Methoden (SetScrollPos / ScrollWindow) und (OnHScroll / Timer) nicht klar.

    void CExpertModeDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
    {
    	int iDelta;
    	switch (nSBCode)
    	{
    		case SB_LINERIGHT:
    				if (m_iHScrollPos >= m_iHScrollWidth)
    				{
    					return;
    				}
    				iDelta = 5;
    
    				break;
    
    		case SB_LINELEFT:
    				if (m_iHScrollPos <= 0)
    				{
    					return;
    				}
    				iDelta = -5;
    
    				break;
    
    		case SB_PAGERIGHT:
    				if (m_iHScrollPos >= m_iHScrollWidth)
    				{
    					return;
    				}
    				iDelta = 5;
    				break;
    
    		case SB_THUMBTRACK:
    		case SB_THUMBPOSITION:
    				iDelta = (int)nPos - m_iHScrollPos;
    				break;
    
    		case SB_PAGELEFT:
    				if (m_iHScrollPos <= 0)
    				{
    					return;
    				}
    				iDelta = -5;
    				break;
    
    		default:
    				return;
    		}
    		m_iHScrollPos += iDelta;
    		SetScrollPos(SB_HORZ, m_iHScrollPos);
    		ScrollWindow(-iDelta, 0);
    		CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
    }
    

    m_iHScrollPos ist die aktuelle Position des "Scrollers"

    m_iHScrollWidth ergibt sich aus der Breite des anzuzeigenden Bereichs (tatsächliche Breite) minus der aktuellen Breite des Fensters.

    Ich bin jetzt einfach wie folgt im Timer vorgegangen, aber dann wird immer mein ganzes Fenster verschoben und ich kann nicht zurückscrollen.

    Implementierung im Timer

    CWnd* pWnd =  GetFocus();
    CRect rcControl, rcParent; 
    int iDelta = 0;
    
    GetClientRect(&rcParent); 
    pWnd -> GetWindowRect(rcControl);
    ScreenToClient(&rcControl); 
    
    // Aktuelle Position bestimmen 
    CPoint ptScrollPosition = GetScrollPos(SB_HORZ); 
    CPoint ptNewScrollPosition = ptScrollPosition; 
    
    // Eine Unit Platz lasen 
    CSize sOffset = CSize(20,20); 
    
    if (rcControl.left < rcParent.left) 
    {
            iDelta = rcControl.left - rcParent.left - sOffset.cx;
    	ptNewScrollPosition.x += iDelta;
    }
    else if (rcControl.right > rcParent.right) 
    {
    	iDelta = rcControl.right - rcParent.right + sOffset.cx;
    	ptNewScrollPosition.x += iDelta;
    }
    
    rcControl.OffsetRect(ptScrollPosition-ptNewScrollPosition); 
    if (rcControl.left < 0)
    {
    	ptNewScrollPosition.x += rcControl.left; 
    }
    if (rcControl.top < 0)
    {
    	ptNewScrollPosition.y += rcControl.top; 
    }
    
    if (ptScrollPosition!=ptNewScrollPosition) 
    {
    	m_iHScrollPos += iDelta;
    	SetScrollPos(SB_HORZ, m_iHScrollPos);
    	ScrollWindow(-iDelta, ptNewScrollPosition.y);
    }
    

    Grüße
    Chris


  • Mod

    Und warum benutzt Du einen Dialog?
    Stilistisch halte ich von rollbaren Dialogen gar nichts. Nimm ein CPropetySheet mit mehreren Seiten um die Dialoge vernünftig aufzuteilen.

    Ansonsten:
    http://www.codeproject.com/KB/dialog/scrolling_support.aspx



  • Hi Martin,

    ich habe ein kleines Problem mit deinem Code, den du für mich gepostet hast.

    Zunächst habe ich den Code so abgeändert, dass überprüft wird ob sich der Focus geändert hat, da ich
    den Code in einem Timer implementiert habe. Sonst würde die Bedienung mit der Maus nicht funktionieren.

    m_LastControl = m_CurControl;		
    m_CurControl  = GetFocus();
    
    if(m_CurControl != m_LastControl)
    {
    	CRect rcControl, rcParent; 
    
    	GetClientRect(&rcParent); 
    	m_CurControl->GetWindowRect(rcControl);
    	ScreenToClient(&rcControl); 
    
    	CPoint ptScrollPosition = GetScrollPosition(); 
    	CPoint ptNewScrollPosition = ptScrollPosition; 
    	CSize sOffset = CSize(20,20); 
    
    	if (rcControl.left < rcParent.left) 
    	{
    	  ptNewScrollPosition.x += rcControl.left-rcParent.left - sOffset.cx; 
    	}
    	else if (rcControl.right > rcParent.right) 
    	{
    	  ptNewScrollPosition.x += rcControl.right-rcParent.right + sOffset.cx; 
    	}
    
    	if (rcControl.top < rcParent.top) 
    	{
    	  ptNewScrollPosition.y += rcControl.top-rcParent.top + sOffset.cy; 
    	}
    	else if (rcControl.bottom > rcParent.bottom) 
    	{
    	  ptNewScrollPosition.y += rcControl.bottom-rcParent.bottom + sOffset.cy; 
    	}
    
    	rcControl.OffsetRect(ptScrollPosition-ptNewScrollPosition); 
    	if (rcControl.left < 0)
    	{
    	  ptNewScrollPosition.x += rcControl.left; 
    	}
    	if (rcControl.top < 0)
    	{
    	  ptNewScrollPosition.y += rcControl.top; 
    	}			
    	if (ptScrollPosition!=ptNewScrollPosition) 
    	{
    	  ScrollToPosition(ptNewScrollPosition);
    	}
    }
    

    Nun zum Problem, die Bedienung mit der Tastatur funktioniert einwandfrei, nur bei der Bedienung mit der Maus gibt gibt es Probleme.

    Wie bereits erwähnt habe ich dynamische Controls, das letze Control ist ein Button.
    Durch das Klicken auf den Buttton wird ein Dialog geöffnet. Dieser Dialog ist breiter, als die Standrdgröße des Hauptfensters, wenn es minimiert ist.

    Öffnet sich der Dialog, dann verschiebt sich der Fensterinhalt meines Hauptfensters nach links.
    Beim Start der Anwendung hat das TabControl den Focus und genau um die Größe dieses Reiters wird der Inhalt nach links geschoben, auch wenn ich den Focus mit der Tab-Taste auf ein anderes Control setze (z. B. den Button auf den ich klicke.

    Und was noch seltsamer ist, ist dass sich der Inhalt des Hauptfensters noch mehr nach links verschiebt, wenn ich mit der Tab-Taste durch die
    Controls des Dialogs navigiere. Ich habe auch keine Scrollbar in meinem Dialog, wie CChris das hat.

    Danke und Lg
    Kerberos



  • Hi,

    weiß wirklich keiner wie ich den Fehler beheben kann? Ich will ja nicht aufdränglich sein, aber ich komm an dieser stelle einfach nicht weiter... ist wahrscheinlich nur 'ne Kleinigkeit. Durch Debuggen komm ich auch nicht weiter und ich weiß auch nicht wonach ich mit google oder hier im Forum suchen soll.

    Danke und Lg
    Kerberos


  • Mod

    Du solltest das Rollen natürlich nur dann machen, wenn das Fenster, dass den Focus hat auch zu Deinem Dialog gehört oder. Was macht es bitte für einen Sinn, ein beliebiges Control, dass den Focus hat zur Basis Deiner Berechnung zu nutzen.
    Zudem kann m_CurControl NULL werden! Und ich sehe nicht, dass Du Dir m_CurControl auch wirklich merkst!

    Also:

    if (m_CurControl!=NULL && IsChild(m_curControl) && m_CurControl!=m_LastControl)
    {
    


  • --


  • Mod

    😕 Kerberos CChris 😕

    Wer nun?



  • looooool, so einen Zufall hab ich ja noch nie erlebt.

    ( Hallo CChris 😃 😃 )

    Bin heute nicht im Praktum beim Arbeiten, sondern am stationären PC zuhause, wo ich schon länger nicht mehr war. Dachte eigentlich, ich wäre da noch eingeloggt.

    Hab meinen Bruder, der sich wohl als CChris hier registriert hat (Chris passt vom Namen her und dass ein Login-Fehler durch die Boardsoftware aufgetreten ist, kann ich mir nicht vorstellen), nach einer Lösung für das Problem gefragt weil der sich auch mit der MFC beschäftigt hat.

    Also entweder interessiert es ihn wirklich, oder er wollte nur so dar stehen als hätte "er" eine Lösung fürs Problem gefunden.... kommt ja heute abend auf 😃

    ... Sachen gibt es ... unglaublich.

    lg Kerberos


Anmelden zum Antworten