Cum pot pune un CCtrlView pe un CComboBox ?

Intrebari legate de programarea cu biblioteci precum MFC, ATL, WTL si GDI+.
mesajflaviu
Membru++
Membru++
Posts: 687
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Cum pot pune un CCtrlView pe un CComboBox ?

Post by mesajflaviu » 10 Jan 2011, 14:58

Cum pot pune un CCtrlView peste un CComboBox ? Mi-ar trebui pe acel CComboBox o lista care are checkbox-uri (CCheckListBox), dar sant cazuri cand e util un CTreeView (CTreeCtrl) acolo ...



User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Cum pot pune un CCtrlView pe un CComboBox ?

Post by Ovidiu Cucu » 10 Jan 2011, 16:33

La urma urmei, un view (inclusiv unul derivat din CCtrlView) il poti pune unde vrea muschii tai. Numai ca un view e proiectat de la mama lui sa stea intr-un frame intr-o aplicatie SDI/MDI si o sa ai cam mut de bibilit si de luat antinevralgice.
Un tree control (fara view-ul de rigoare) ar merge un pic mai bine. Destul de usor, cred ca l-ai putea amplasa intr-un dialog pe care sa-l arati in locul la lista care apare by default cand dai click pe combo. Dar si cu asta cred ca-i destul de bibilit.

Intreb: ti se pare util tree intr-un combo? La fel si despre check listbox.
S-au chinuit unii, de exemplu sa faca strutocamile gen "treelistview"... whiskey, iarba, fete, distractie... + munca in zadar. :D
Un tree si-o lista separata nu era mai bine?

In fine, nu zic neaparat sa nu te apuci de-asa ceva. Even just for fun. Mai vorbim...

neagu_laurentiu
Membru++
Membru++
Posts: 919
Joined: 23 Jul 2007, 11:32

Re: Cum pot pune un CCtrlView pe un CComboBox ?

Post by neagu_laurentiu » 10 Jan 2011, 23:08

Ovidiu Cucu wrote:ti se pare util tree intr-un combo?
E util. Cand alegi un element trebuie sa vezi ansamblul si de multe ori el e intr-un tree.
La fel tree multicoloana si toate inventiile care nu-s Windows standard. Daca faci programe cu prezetare date, statistici, pivot table cu tot felul de totalizari si nebunii din zona economica absolut toate sunt utile.

mesajflaviu
Membru++
Membru++
Posts: 687
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Re: Cum pot pune un CCtrlView pe un CComboBox ?

Post by mesajflaviu » 11 Jan 2011, 09:05

Ma gandeam sa fac ceva de genu

http://img522.imageshack.us/i/58694322.png/

... va ma amintiti de Windows NT ? :D

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Cum pot pune un CCtrlView pe un CComboBox ?

Post by Ovidiu Cucu » 11 Jan 2011, 11:17

Ok, sa zicem...

Derivam CComboTreeCtrl din CComboBox, prindem CBN_DROPDOWN, cautam acel "ComboLBox", ii dam in cap si-n loc o punem pe Claudia Schiffer. :)
Pardon, punem o mica fereastra cu un tree control.
Buuuun...
Acuma hai sa aruncam in paralel o privire atenta la functiile lui CComboBox si la cele ale lui CTreeCtrl.

Q: Seamana?
A: Semana, dar nu rasare. ;)

Ce facem? Derivam din amandoua? Nuuu faceti prostii, copii! Nenea a glumit. :D
Asa ca, pornim voiniceste sa ascundem sub presul lui CComboTreeCtrl, mai toate "mizeriile" din CComboBox, apoi coacem la foc ptrivit ce vedem prin CTreeCtrl.
Mai ramane o problema. Unde tinem datele pentru tree? In mod normal, controlul Windows "standard" are grija de ele.
Ar fi cateva idei dar trec peste ele ca sa inchei.

Q: Mai ramane ceva din combobox-ul (respectiv CComboBox-ul) initial?
A: Da. Mai raman vreo 2-3 metode, vreo 2-3 mesaje, mult cod de pomana si-un dreptunghi cu sagetutza pe fatzau. :D

Concluzie: in cazul acesta e mai usor si mai inginereste de facut un control from scratch adicatelea cap-coada.
Poate fi foarte bine un ActiveX.

// Am facut pana acum N contoale "mutante". De fiecare data am masurat de trei ori si-am taiat o singura data. ;)

mesajflaviu
Membru++
Membru++
Posts: 687
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Re: Cum pot pune un CCtrlView pe un CComboBox ?

Post by mesajflaviu » 05 Feb 2011, 23:24

Am incercat sa pun un CTreeCtrl pe un CComboBox :

Code: Select all

#include "ComboTreeCtrl.h"	// Added by ClassView >>> ( derivat din CTreeCtrl )

class CTreeComboBox : public CComboBox
{
// Construction
public:
	CTreeComboBox();

protected:
	virtual void PreSubclassWindow();
	//}}AFX_VIRTUAL

// Implementation
public:
	CComboTreeCtrl m_Tree;
	virtual ~CTreeComboBox();

	// Generated message map functions
protected:
	//{{AFX_MSG(CTreeComboBox)
	afx_msg void OnDropdown();
	afx_msg void OnCloseup();
	//}}AFX_MSG

	DECLARE_MESSAGE_MAP()
};

Code: Select all

void CTreeComboBox::PreSubclassWindow() 
{
	// TODO: Add your specialized code here and/or call the base class

	DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_TABSTOP | CS_DBLCLKS | WS_BORDER | TVS_HASBUTTONS | TVS_LINESATROOT | TVS_HASLINES | TVS_DISABLEDRAGDROP;
	m_Tree.Create(dwStyle,CRect(0,0,100,100),this,0x1005);
	m_Tree.ShowWindow(SW_HIDE);

	CComboBox::PreSubclassWindow();
}
apoi , in CBN_DROPDOWN am incercat :

Code: Select all

void CTreeComboBox::OnDropdown() 
{
	// TODO: Add your control notification handler code here

	CRect rect;
	GetDroppedControlRect(&rect);
//	m_Tree.MoveWindow(rect.left,rect.top,rect.Width(),rect.Height());
	m_Tree.InsertItem("One",NULL,NULL);
	HTREEITEM hTwo = m_Tree.InsertItem("Two",NULL,NULL);
	m_Tree.InsertItem("TwentyFive",0,0,hTwo);
	m_Tree.InsertItem("Three",NULL,NULL);
	m_Tree.ShowWindow(SW_NORMAL);
}
si in CBN_DROPDOWN ascund tree-ul :

Code: Select all

void CTreeComboBox::OnCloseup() 
{
	// TODO: Add your control notification handler code here

	m_Tree.ShowWindow(SW_HIDE);
}
dar ramane o problema , tree-ul este intotdeauna in spatele listei drop-down a combobox-ului , daca comentez linia m_Tree.MoveWindw(...) vad ceva din tree dar nu pot sa intind tree-ul peste lista dropdown ... cum pot rezolva aceasta problema ?

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Cum pot pune un CCtrlView pe un CComboBox ?

Post by Ovidiu Cucu » 06 Feb 2011, 14:36

  1. Banui ca prima data ai incercat sa ascunzi lista pe CBN_DROPDOWN si n-a mers.
    Asta s-ar rezolva destul de usor postand un mesaj custom, cam asa:

    Code: Select all

    #define CB_APP_POSTDROPDOWN (CB_MSGMAX+ 1)
    class CTreeComboBox : public CComboBox
    {
    // ...
       afx_msg LRESULT OnAppPostDropDown(WPARAM wParam, LPARAM lParam);
    };

    Code: Select all

       ON_MESSAGE(CB_APP_POSTDROPDOWN, OnAppPostDropDown)
    END_MESSAGE_MAP()
    // ...
    void CTreeComboBox::OnDropdown() 
    {
       // ...
       PostMessage(CB_APP_POSTDROPDOWN);
    }
    
    LRESULT CTreeComboBox::OnAppPostDropDown(WPARAM wParam, LPARAM lParam)
    {
       HWND hWnd = _GetDropdownListBox();
       ::ShowWindow(hWnd, SW_HIDE);
       return 0;
    }
  2. Tree-ul "dropdown" pe care vrei sa-l folosesti nu poate fi child pentru combobox.
    Deci trebuie creat cam asa:

    Code: Select all

    void CTreeComboBox::PreSubclassWindow() 
    {
       DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_TABSTOP | CS_DBLCLKS 
          | WS_BORDER | TVS_HASBUTTONS | TVS_LINESATROOT | TVS_HASLINES | TVS_DISABLEDRAGDROP;
       BOOL bRet = m_tree.Create(dwStyle, CRect(0,0,0,0), CWnd::GetDesktopWindow(), 0);
       ASSERT(bRet);
    }
  3. Eliminam glumitza cu "acoperitul" listei dropdown, facem tree-ul fereastra top-most si-i calculam pozitia si size-ul.
    Functia CTreeComboBox::OnDropdown ar arata cam asa, desi ar mai fi de lucru la ea:

    Code: Select all

    void CTreeComboBox::OnDropdown() 
    {
       CRect rcCombo;
       GetWindowRect(rcCombo);
       GetParent()->ScreenToClient(rcCombo);
       int nHeight = 200; // magic number just for demo; it must be calculated.
       CRect rcDropdown(rcCombo.left, rcCombo.bottom, rcCombo.right, rcCombo.bottom + nHeight);
       GetParent()->ClientToScreen(rcDropdown);
    
       UINT nFlags = SWP_SHOWWINDOW;
       m_tree.SetWindowPos(&CWnd::wndTopMost, // make it top-most window
          rcDropdown.left, rcDropdown.top, rcDropdown.Width(), rcDropdown.Height(), nFlags);
    
       PostMessage(CB_APP_POSTDROPDOWN);
    }
  4. Notificarea CBN_CLOSEUP nu mai foloseste la nimic, din moment ce am inlocuit lista cu tree-ul.
    Trebie gasit un alt mijloc de a inchide dropdown-ul.
  5. Am facut tree-ul top-level, deci nu mai are parinte caruia sa-i trimita notificari.
    Nashpa, deci ar trebui sa derivez din CTreeControl sa handluiesc direct WM_LBUTTONDOWN s.a.m.d. si in final sa trimit mesaje custom la combo sau la parintele astuia.
  6. Ar trebui implemetat in CTreeComboBox metodele specifice pentru tree, de exemplu

    Code: Select all

    inline HTREEITEM CTreeComboBox::InsertItem(LPCTSTR lpszItem, HTREEITEM hParent /*= TVI_ROOT*/, 
                                        HTREEITEM hInsertAfter /*= TVI_LAST*/)
    {
       return m_tree.InsertItem(lpszItem, hParent, hInsertAfter);
    }
  7. Ar trebui "ascunse sub pres" metodele din CComboBox care acum nu mai au sens.
    Exemplu:

    Code: Select all

    inline int CTreeComboBox::AddString(LPCTSTR lpszString)
    {
       ASSERT(FALSE); // Nonsense, Dude!
       return CB_ERR;
    }
  8. si-ar mai fi...
Desi la prima vedere combo + tree pare o strutzocamila simpla nu-i chiar asa.
Daca cineva demonstreaza contrariul, no problem, dau o bere virtuala. ;)

Finally:
As lasa CComboBox-ul si as face un control ActiveX care subclaseaza COMBOBOX, deci nu chiar cap-coada cum spuneam initial (vezi poza).
E si acolo de sapat, sunt cred cam aceleasi probeme la partea cu dropdown-ul, dar cel putin scap de o multime de mizerii de ascuns sub pres.
TreeComboBox.jpg
TreeComboBox.jpg (37.44 KiB) Viewed 8697 times

mesajflaviu
Membru++
Membru++
Posts: 687
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Re: Cum pot pune un CCtrlView pe un CComboBox ?

Post by mesajflaviu » 07 Feb 2011, 16:38

O sa incerc solutia clasica , fara ActiveX , sa vad ce pot face ...

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Cum pot pune un CCtrlView pe un CComboBox ?

Post by Ovidiu Cucu » 07 Feb 2011, 18:01

Ok, cum vrei tu. Nu te obliga nimeni...

Poate o sa fac eu un OCX de felul asta si cred ca o sa merg pe varianta "from scratch". Un pic mai incolo, acuma nu prea am timp.
Sa vedem a cui iese mai frumos. :D

mesajflaviu
Membru++
Membru++
Posts: 687
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Re: Cum pot pune un CCtrlView pe un CComboBox ?

Post by mesajflaviu » 07 Feb 2011, 18:38

Ovidiu Cucu wrote:Ok, cum vrei tu. Nu te obliga nimeni...

Poate o sa fac eu un OCX de felul asta si cred ca o sa merg pe varianta "from scratch". Un pic mai incolo, acuma nu prea am timp.
Sa vedem a cui iese mai frumos. :D
Eu stiu de acum a cui iese mai frumos :biggrin: dar tot incerc sa "impletesc" niste controale MFC ...

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Cum pot pune un CCtrlView pe un CComboBox ?

Post by Ovidiu Cucu » 07 Feb 2011, 19:22

mesajflaviu wrote:tot incerc sa "impletesc" niste controale MFC ...
Pai, ce spuneam eu e tot cu "MFC":
MFC ActiveX ControlWizard.jpg
MFC ActiveX ControlWizard.jpg (2.62 KiB) Viewed 8666 times

mesajflaviu
Membru++
Membru++
Posts: 687
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Re: Cum pot pune un CCtrlView pe un CComboBox ?

Post by mesajflaviu » 09 Feb 2011, 13:12

Am reusit ceva , mai trebuie sa vad cum recuperez datele din tree ...
Attachments
TestTreeCombo.rar
(80.24 KiB) Downloaded 293 times

mesajflaviu
Membru++
Membru++
Posts: 687
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Re: Cum pot pune un CCtrlView pe un CComboBox ?

Post by mesajflaviu » 10 Feb 2011, 13:41

Am rezolvat aproape totul in afara de un lucru : nu pot sa mai prind mesajele combo-box-ului : de exemplu CBN_CLOSEUP , ca sa stiu cand user-ul a inchis tree-ul ( combo-box-ul ) ....
Attachments
TestTreeCombo.rar
(83.28 KiB) Downloaded 256 times

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Cum pot pune un CCtrlView pe un CComboBox ?

Post by Ovidiu Cucu » 10 Feb 2011, 16:52

Pai, eu vorbesc...
Ovidiu Cucu wrote:
  • 4. Notificarea CBN_CLOSEUP nu mai foloseste la nimic, din moment ce am inlocuit lista cu tree-ul.
    Trebie gasit un alt mijloc de a inchide dropdown-ul.
...si se pare ca tot eu aud. ;)

mesajflaviu
Membru++
Membru++
Posts: 687
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Re: Cum pot pune un CCtrlView pe un CComboBox ?

Post by mesajflaviu » 11 Feb 2011, 10:23

Poate vreau o prostie , dar tot o spun :

pentru a ajunge pe forma pe care e pus controlul asta mutant , la evenimentul OnCloseUp ,

Code: Select all

void CTestTreeComboView::OnCloseupCombo1() 
{
	// TODO: Add your control notification handler code here

	TRACE("\n user-ul a inchis tree-ul \n");
}
in tree , la evenimentul OnKillfocus , printr-un pointer la combobox :

Code: Select all

void CComboTreeCtrl::OnKillfocus(NMHDR* pNMHDR, LRESULT* pResult) 
{
	// TODO: Add your control notification handler code here

	m_pCombo->SetDroppedCloseTitle();
	m_pCombo->TreeCtrlDone();
}
apelez o metoda care mi-ar putea provoca CBN_ONCLOSEUP , in combobox :

Code: Select all

void CTreeComboBox::TreeCtrlDone()
{
	OnCloseUp();
}
si asta se si intampla :

Code: Select all

void CTreeComboBox::OnCloseup() 
{
	// TODO: Add your control notification handler code here

	TRACE("\n CTreeComboBox::OnCloseup() \n");
}
doar ca nu mai vad asta si in forma , sa stiu cand user-ul a inchis tree-ul... ca de inchis / deschis tree-ul , am rezolvat ...

Post Reply