// ComboOXTree.cpp: implementation of the CComboOXTree class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "ComboOXTree.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CComboOXTree::CComboOXTree() : m_container(this), m_pCombo(NULL), m_rectValid(0,0,0,0), m_hLastSelectedItem(NULL) { } CComboOXTree::~CComboOXTree() { } BOOL CComboOXTree::PreCreateWindow(CREATESTRUCT& cs) { // create container window // ASSERT(!::IsWindow(m_container.GetSafeHwnd())); if(::IsWindow(m_container.GetSafeHwnd())) { return FALSE; } static CString sContainerWndClass=AfxRegisterWndClass(CS_SAVEBITS); if((cs.dwExStyle & (WS_EX_CLIENTEDGE|WS_EX_STATICEDGE|WS_EX_WINDOWEDGE|WS_EX_DLGMODALFRAME))==0) { cs.dwExStyle|=WS_EX_DLGMODALFRAME; } if(!m_container.CreateEx(cs.dwExStyle,sContainerWndClass,_T(""), (cs.style & 0xffff0000 & ~(WS_CHILD|WS_VISIBLE|WS_HSCROLL|WS_VSCROLL))| WS_POPUP|MFS_SYNCACTIVE,cs.x,cs.y,cs.cx,cs.cy,cs.hwndParent,NULL)) { return FALSE; } // /////////////////////////////////////////////// // change create data cs.style&=~(WS_VISIBLE|WS_POPUP); // must have buttons cs.style|=WS_CHILD; cs.dwExStyle=0; cs.hwndParent=m_container.GetSafeHwnd(); cs.x=cs.y=0; CRect rect; m_container.GetClientRect(rect); cs.cx=rect.Width(); cs.cy=rect.Height(); return COXTreeCtrl::PreCreateWindow(cs); } LRESULT CComboOXTree::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { LRESULT lResult=0; switch(message) { case WM_KILLFOCUS: OnKillFocus(CWnd::FromHandle((HWND)wParam)); break; case WM_LBUTTONDOWN: OnLButtonDown((UINT)wParam,CPoint(LOWORD(lParam),HIWORD(lParam))); break; case WM_LBUTTONDBLCLK: OnLButtonDblClk((UINT) wParam, CPoint(LOWORD(lParam),HIWORD(lParam))); break; case WM_MOUSEMOVE: OnMouseMove((UINT)wParam,CPoint(LOWORD(lParam),HIWORD(lParam))); break; case WM_KEYDOWN: OnKeyDown((UINT)wParam,LOWORD(lParam),HIWORD(lParam)); break; default: lResult=COXTreeCtrl::WindowProc(message,wParam,lParam); break; } return lResult; } void CComboOXTree::OnKillFocus(CWnd* pNewWnd) { COXTreeCtrl::OnKillFocus(pNewWnd); if(pNewWnd!=this && m_pCombo!=NULL) { m_pCombo->PostMessage(CB_SHOWDROPDOWN,FALSE); } } void CComboOXTree::OnLButtonDown(UINT nFlags, CPoint point) { COXTreeCtrl::OnLButtonDown(nFlags,point); HTREEITEM hItem=COXTreeCtrl::GetSelectedItem(); if (hItem) SelectItem(hItem); // } } void CComboOXTree::OnMouseMove(UINT nFlags, CPoint point) { COXTreeCtrl::OnMouseMove(nFlags,point); } void CComboOXTree::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { if(m_pCombo!=NULL) { if(nChar==VK_ESCAPE || nChar==VK_RETURN) { if(nChar==VK_RETURN) { HTREEITEM hItem=GetSelectedItem(); if(hItem!=NULL) { m_hLastSelectedItem=hItem; } } m_pCombo->ShowDropDown(FALSE); m_pCombo->SetFocus(); return; } } COXTreeCtrl::OnKeyDown(nChar,nRepCnt,nFlags); } void CComboOXTree::AutoResize() { ASSERT(::IsWindow(GetSafeHwnd())); if(!::IsWindow(GetSafeHwnd())) { return; } CRect rectCurrent; GetWindowRect(rectCurrent); CRect rectBest=GetBestRect(); CRect rect=rectBest; ASSERT(m_sizeMinWidthHeight.cx<=m_sizeMaxWidthHeight.cx || m_sizeMinWidthHeight.cx==-1 || m_sizeMaxWidthHeight.cx==-1); ASSERT(m_sizeMinWidthHeight.cy<=m_sizeMaxWidthHeight.cy || m_sizeMinWidthHeight.cy==-1 || m_sizeMaxWidthHeight.cy==-1); if(m_sizeMaxWidthHeight.cx>=0 && rect.Width()>m_sizeMaxWidthHeight.cx) { rect.right=rect.left+m_sizeMaxWidthHeight.cx; } if(m_sizeMaxWidthHeight.cy>=0 && rect.Height()>m_sizeMaxWidthHeight.cy) { rect.bottom=rect.top+m_sizeMaxWidthHeight.cy; } if(m_sizeMinWidthHeight.cx>=0 && rect.Width()=0 && rect.Height()rect.Height() && rect.Width()0) { CRect rect; VERIFY(GetItemRect(0,rect,FALSE)); return rect.Height(); } else { return OXCOMBOPICKER_DEFAULTITEMHEIGHT; } } BOOL CComboOXTree::IsThereSelectedItem() { if(!::IsWindow(GetSafeHwnd())) { return FALSE; } return (m_hLastSelectedItem!=NULL); } CImageList* CComboOXTree::GetSelectedItemImage() { if(!IsThereSelectedItem()) { return NULL; } int nItemImage=-1; int nItemSelectedImage=-1; GetItemImage(m_hLastSelectedItem,nItemImage,nItemSelectedImage); if(nItemImage==-1) { return NULL; } CImageList* pImageList=GetImageList(TVSIL_NORMAL); if(pImageList==NULL) { return NULL; } ASSERT(nItemImageGetImageCount()); CImageList* pSelectedItemImageList=new CImageList(); if(!pSelectedItemImageList->Create(pImageList)) { delete pSelectedItemImageList; return NULL; } for(int nIndex=pSelectedItemImageList->GetImageCount()-1; nIndex>=0; nIndex--) { if(nIndex!=nItemImage) { VERIFY(pSelectedItemImageList->Remove(nIndex)); } } return pSelectedItemImageList; } CString CComboOXTree::GetSelectedItemText() { if(!IsThereSelectedItem()) { return _T(""); } return GetItemText(m_hLastSelectedItem); } CFont* CComboOXTree::GetSelectedItemFont() { if(!IsThereSelectedItem()) { return NULL; } return GetFont(); } COLORREF CComboOXTree::GetSelectedItemTextColor() { return ::GetSysColor(COLOR_WINDOWTEXT); } void CComboOXTree::ResetContent() { if(::IsWindow(GetSafeHwnd())) { DeleteAllItems(); } } void CComboOXTree::OnAttachToComboPicker() { ASSERT(m_pCombo!=NULL); if(m_pCombo!=NULL && ::IsWindow(m_pCombo->GetSafeHwnd()) && ::IsWindow(GetSafeHwnd())) { ASSERT(::IsWindow(m_container.GetSafeHwnd())); CRect rect; m_pCombo->GetWindowRect(rect); CRect rectCalc=rect; m_container.CalcWindowRect(rectCalc); // set the minimum width for the control CSize sizeMinWidthHeight=GetMinWidthHeight(); sizeMinWidthHeight.cx=2*rect.Width()-rectCalc.Width(); SetMinWidthHeight(sizeMinWidthHeight); } } void CComboOXTree::OnChangeMinMaxWidthHeight() { if(::IsWindow(GetSafeHwnd())) { AutoResize(); } } void CComboOXTree::OnChangeOwnerComboSize() { ASSERT(m_pCombo!=NULL); if(m_pCombo!=NULL && ::IsWindow(m_pCombo->GetSafeHwnd()) && ::IsWindow(GetSafeHwnd())) { // set the minimum width for the control ASSERT(::IsWindow(m_container.GetSafeHwnd())); CRect rect; m_pCombo->GetWindowRect(rect); CRect rectCalc=rect; m_container.CalcWindowRect(rectCalc); SetMinWidthHeight(2*rect.Width()-rectCalc.Width(),-1); } } void CComboOXTree::ShowDropDown(BOOL bShowIt/*=TRUE*/) { if(m_pCombo!=NULL) { if(bShowIt) { m_hLastSelectedItem=GetSelectedItem(); // ASSERT(CanSelectItem(m_hLastSelectedItem)); // adjust size of window AutoResize(); // make sure the selected item is visible if(m_hLastSelectedItem!=NULL) { EnsureVisible(m_hLastSelectedItem); } } else { //ASSERT(CanSelectItem(m_hLastSelectedItem)); if (CanSelectItem(m_hLastSelectedItem)) SelectItem(m_hLastSelectedItem); } } } BOOL CComboOXTree::CanSelectItem(HTREEITEM hItem) { UNUSED_ALWAYS(hItem); return TRUE; } void CComboOXTree::ForwardMouseMessage(UINT message, UINT nFlags, CPoint point) { ASSERT(::IsWindow(GetSafeHwnd())); if(!::IsWindow(GetSafeHwnd())) { return; } CPoint ptScreen=point; ClientToScreen(&ptScreen); CWnd* pTargetWnd=CWnd::WindowFromPoint(ptScreen); if(pTargetWnd==NULL) { return; } ASSERT(pTargetWnd!=this); if(pTargetWnd==this) { return; } WPARAM wParam=nFlags; int nHitTest= (int)pTargetWnd->SendMessage(WM_NCHITTEST,0,MAKELONG(ptScreen.x,ptScreen.y)); if(nHitTest==HTCLIENT) { pTargetWnd->ScreenToClient(&ptScreen); } else { switch(message) { case WM_LBUTTONDOWN: { message=WM_NCLBUTTONDOWN; break; } case WM_RBUTTONDOWN: { message=WM_NCRBUTTONDOWN; break; } case WM_MBUTTONDOWN: { message=WM_NCMBUTTONDOWN; break; } case WM_LBUTTONUP: { message=WM_NCLBUTTONUP; break; } case WM_RBUTTONUP: { message=WM_NCRBUTTONUP; break; } case WM_MBUTTONUP: { message=WM_NCMBUTTONUP; break; } case WM_LBUTTONDBLCLK: { message=WM_NCLBUTTONDBLCLK; break; } case WM_RBUTTONDBLCLK: { message=WM_NCRBUTTONDBLCLK; break; } case WM_MBUTTONDBLCLK: { message=WM_NCMBUTTONDBLCLK; break; } case WM_MOUSEMOVE: { message=WM_NCMOUSEMOVE; break; } } wParam=nHitTest; } LPARAM lParam=MAKELONG(ptScreen.x,ptScreen.y); pTargetWnd->SendMessage(message,wParam,lParam); } void CComboOXTree::OnLButtonDblClk( UINT nFlags, CPoint point ) { UNUSED_ALWAYS(point); UNUSED_ALWAYS(nFlags); HTREEITEM hItem=GetSelectedItem(); if(hItem!=NULL) { m_hLastSelectedItem=hItem; } m_pCombo->ShowDropDown(FALSE); m_pCombo->SetFocus(); }