Page 1 of 2
Cum pot pune un CCtrlView pe un CComboBox ?
Posted: 10 Jan 2011, 14:58
by mesajflaviu
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 ...
Re: Cum pot pune un CCtrlView pe un CComboBox ?
Posted: 10 Jan 2011, 16:33
by Ovidiu Cucu
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.

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...
Re: Cum pot pune un CCtrlView pe un CComboBox ?
Posted: 10 Jan 2011, 23:08
by neagu_laurentiu
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.
Re: Cum pot pune un CCtrlView pe un CComboBox ?
Posted: 11 Jan 2011, 09:05
by mesajflaviu
Ma gandeam sa fac ceva de genu
http://img522.imageshack.us/i/58694322.png/
... va ma amintiti de Windows NT ?

Re: Cum pot pune un CCtrlView pe un CComboBox ?
Posted: 11 Jan 2011, 11:17
by Ovidiu Cucu
Ok, sa zicem...
Derivam CComboTreeCtrl din CComboBox, prindem CBN_DROPDOWN, cautam acel "Combo
LBox", 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.

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.
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.

Re: Cum pot pune un CCtrlView pe un CComboBox ?
Posted: 05 Feb 2011, 23:24
by mesajflaviu
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 ?
Re: Cum pot pune un CCtrlView pe un CComboBox ?
Posted: 06 Feb 2011, 14:36
by Ovidiu Cucu
- 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;
}
- 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);
}
- 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);
}
- 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.
- 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.
- 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);
}
- 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;
}
- 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 (37.44 KiB) Viewed 8998 times
Re: Cum pot pune un CCtrlView pe un CComboBox ?
Posted: 07 Feb 2011, 16:38
by mesajflaviu
O sa incerc solutia clasica , fara ActiveX , sa vad ce pot face ...
Re: Cum pot pune un CCtrlView pe un CComboBox ?
Posted: 07 Feb 2011, 18:01
by Ovidiu Cucu
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.

Re: Cum pot pune un CCtrlView pe un CComboBox ?
Posted: 07 Feb 2011, 18:38
by mesajflaviu
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.

Eu stiu de acum a cui iese mai frumos

dar tot incerc sa "impletesc" niste controale MFC ...
Re: Cum pot pune un CCtrlView pe un CComboBox ?
Posted: 07 Feb 2011, 19:22
by Ovidiu Cucu
mesajflaviu wrote:tot incerc sa "impletesc" niste controale MFC ...
Pai, ce spuneam eu e tot cu "MFC":

- MFC ActiveX ControlWizard.jpg (2.62 KiB) Viewed 8967 times
Re: Cum pot pune un CCtrlView pe un CComboBox ?
Posted: 09 Feb 2011, 13:12
by mesajflaviu
Am reusit ceva , mai trebuie sa vad cum recuperez datele din tree ...
Re: Cum pot pune un CCtrlView pe un CComboBox ?
Posted: 10 Feb 2011, 13:41
by mesajflaviu
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 ) ....
Re: Cum pot pune un CCtrlView pe un CComboBox ?
Posted: 10 Feb 2011, 16:52
by Ovidiu Cucu
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.

Re: Cum pot pune un CCtrlView pe un CComboBox ?
Posted: 11 Feb 2011, 10:23
by mesajflaviu
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 ...