Parent beschneidet Child

Palador

Grünschnabel
Hallo allerseits.
Erstmal worums geht: Ein Adressfeld ähnlich dem eines Browsers. Man gibt etwas ein und es erscheint eine ListBox mit allen besuchten Seiten, bei deren Adresse die Anfangsbuchstaben mit der Eingabe übereinstimmen. Mein Editfeld soll aber keine Adressen beinhalten sondern Strings aus einem beliebigen CStringArray. Es funktioniert schon einwandfrei, bis auf...

Das kleine Problem: bietet die Listbox eine viele Einträge an wird sie nur bis zum Rand des Parents (das gleiche wie von dem Editfeld, also meist der Dialog) gezeichnet und alles danach abgeschnitten. Wie kann ich das verhindern?

Folgendes hab ich schon versucht:
-parent von ListBox auf NULL --> absturz
-parent von ListBox auf GetDesktopWindow() --> andere Dialoge flackern durch die LB
-ListBox::ModifyStyleEx(0, WS_EX_TOPMOST);

das wars soweit
weis wer rat?
 
Meinst du mit Listbox das Listenfeld einer Combobox? Falls du die Combobox im Dialogdesigner erstellt hast, klicke dort auf den Drop-Down-Pfeil und du kannst die Größe der aufgeklappten Liste festlegen (auch über die Parentgrenzen hinaus).

Gruß
MCoder
 
nein, so mein ich das nicht. die Listbox wird in Laufzeit seperat erstellt, hab also eine Listbox und ein Editfeld.
Ich lade einfach mal das Projekt hoch...
 

Anhänge

  • 27299attachment.zip
    14,6 KB · Aufrufe: 15
Hab ein paar Änderungen reingefummelt. Ist noch nicht perfekt, aber die Listbox kommt, sieht vernünftig aus und geht auch fast wieder weg.

Dein Hauptproblem: Du hast die Listbox mit WS_CHILD erzeugt. Dann wird die immer aufs Parent zurechtgestutzt.

Was noch nicht so klappt:

o Die Listbox geht nicht immer weg, wenn sie den Fokus verliert
o Dadurch, dass die Listbox jetzt kein Parent hat, verliert der Hauptdialog den Fokus (siehe Caption) -> ich meine, da kann man mit dem Owner rumspielen

Hier die einzelnen Code-Änderungen:

Code:
BOOL CSelectionEditList::Create(CWnd* pEdit)
{
	CRect rClient;

	m_pEdit = pEdit;

	pEdit->GetWindowRect(rClient);

  // um die Höhe der Edit nach unten
  rClient.OffsetRect( 0, rClient.Height() );
  rClient.bottom += 200;
  //return CListBox::CreateEx( WS_EX_TOOLWINDOW, "LISTBOX", "", LBS_HASSTRINGS|LBS_SORT|WS_VISIBLE|WS_VSCROLL, rClient, NULL, 0);

  /*
  HWND    hwndBox = ::CreateWindowEx( WS_EX_TOOLWINDOW, "LISTBOX", "", LBS_HASSTRINGS|LBS_SORT|WS_VISIBLE|WS_VSCROLL,
    rClient.left, rClient.top, rClient.Width(), rClient.Height(), NULL, NULL, NULL, 0 );

  return Attach( hwndBox );
  */

  return CListBox::CreateEx( WS_EX_TOOLWINDOW, "LISTBOX", "", WS_POPUP | WS_BORDER | LBS_HASSTRINGS|LBS_SORT|WS_VISIBLE|WS_VSCROLL, rClient, NULL, 0);

}

Code:
void CSelectionEdit::OnChange() 
{
	int i, iMax, iStr;
	CRect rClient, rList;
	CPoint pEdit;
	WINDOWPLACEMENT wndPlacement;
	UINT nLines, nLengthNew, nLengthOld;
	CString strInput;

	if(!m_listSel)
	{
		//Erstelle Dialog
		GetParent()->GetClientRect(rClient);
		m_listSel.Create( this );
	}
  else
  {
    // neu positionieren, der Dialog könnte sich verschoben haben
    GetWindowRect( rClient );

    // um die Höhe der Edit nach unten
    rClient.OffsetRect( 0, rClient.Height() );
    rClient.bottom += 200;

    // setzt ausser der Position auch die Listbox wieder über den Dialog
    m_listSel.SetWindowPos( GetParent(), rClient.left, rClient.top, 0, 0, SWP_NOSIZE );

  }

	GetWindowText(strInput);

	//Manage Listbox content
	nLengthNew = strInput.GetLength();
	nLengthOld = m_strLastInput.GetLength();
	if(nLengthOld == 0 || nLengthNew < nLengthOld || strncmp(m_strLastInput, strInput, nLengthOld) != 0) //Falls Eingabe nur erweitert...
	{
		m_strArrayFit.RemoveAll();
		m_strArrayFit.Copy(*m_pStrArray);
	}
	iMax = m_strArrayFit.GetSize();
	if(nLengthNew == 0)
	{
		m_listSel.ResetContent();
	}
	else
	{
		for(i=0; i<iMax; i++)
		{
			iStr = FindStringInLB(m_listSel, m_strArrayFit[i]);
			if( _strnicmp(m_strArrayFit[i], strInput, nLengthNew) != 0)
			{
				m_listSel.DeleteString(	iStr );
				m_strArrayFit.RemoveAt(i);
				i--;
				iMax--;
			}
			else if(iStr == LB_ERR)
				m_listSel.AddString(m_strArrayFit[i]);
		}
	}
	m_strLastInput = strInput;

	//Show ListBox
	GetWindowPlacement(&wndPlacement);
	pEdit = CPoint( wndPlacement.rcNormalPosition.left, wndPlacement.rcNormalPosition.top );
	GetClientRect(rClient);

	nLines = m_strArrayFit.GetSize();
	if(nLines > 8)
		nLines = 8;
	
	if(nLines > 0 && nLengthNew > 0)
	{
		rList.SetRect(pEdit, CPoint( pEdit.x + rClient.Width(), pEdit.y + nLines*rClient.Height() ));
		rList.OffsetRect(0, rClient.Height()*2);
                                // habe ich zum Testen auskommentiert, da mir das die Listbox immer sonstwohin geschoben hat
		//m_listSel.MoveWindow( rList );
		m_listSel.ShowWindow(SW_SHOWNOACTIVATE);
		m_listSel.SetCurSel(0);
	}
	else
		m_listSel.ShowWindow(SW_HIDE);
}
 
Ich hab deinen Code ausprobiert. Der Ansatz ist gut, zieht aber auch weitere Probleme nach sich. Sicher kann man diese lösen, aber nötig ist das nur, wenn es wirklich nicht geht, das ein Child über sein Parent hinaus gezeichnet werden kann.
Wie auch immer, danke für die Mühe, würde mich freuen wenn du noch weiter kommst, ich experimentiere auch noch ein wenig rum.

Kann es vieleicht sein, dass sich SetWindowPos und ShowWindow ungewollt wechselwirken?
 

Neue Beiträge

Zurück