📄 treeoptionsctrl.cpp
字号:
r.top = rPrimaryControl.top;
r.bottom = rPrimaryControl.bottom;
r.left = rPrimaryControl.right;
r.right = rItem.right;
//Create the new spin control
ASSERT(m_pSpin);
m_pSpin->SetEditBuddy(m_pEdit);
//Create the spin control
VERIFY(m_pSpin->Create(m_pSpin->GetWindowStyle(), r, this, TREE_OPTIONS_SPINCTRL_ID));
//Setup the buddy and the default range
m_pSpin->SetBuddy(m_pEdit);
int nLower = 0;
int nUpper = 0;
m_pSpin->GetDefaultRange(nLower, nUpper);
m_pSpin->SetRange(nLower, nUpper);
//set the font the edit box should use based on the font in the tree control
m_pSpin->SetFont(&m_Font);
}
else
ASSERT(FALSE); //Your class must be derived from CTreeOptionsSpinCtrl
}
void CTreeOptionsCtrl::CreateBrowseButton(CRuntimeClass* pRuntimeClassBrowseButton, CRect rItem, CRect rText)
{
ASSERT(pRuntimeClassBrowseButton);
if (pRuntimeClassBrowseButton->IsDerivedFrom(RUNTIME_CLASS(CTreeOptionsBrowseButton)))
{
if (m_pEdit)
{
//work out the rect for the button
CRect rEdit;
m_pEdit->GetWindowRect(&rEdit);
ScreenToClient(&rEdit);
CRect r;
r.top = rItem.top;
r.bottom = rEdit.bottom;
r.right = rItem.right;
r.left = r.right - m_pButton->GetWidth(); //Ask the browse button for the width to use
//Create the new browse button
ASSERT(m_pButton);
m_pButton->SetEditBuddy(m_pEdit);
VERIFY(m_pButton->Create(m_pButton->GetCaption(), m_pButton->GetWindowStyle(), r, this, TREE_OPTIONS_BROWSEBUTTONCTRL_ID));
m_pButton->SetOwner(m_pEdit);
}
else if (m_pCombo)
{
//work out the rect for the button
CRect rCombo;
m_pCombo->GetWindowRect(&rCombo);
ScreenToClient(&rCombo);
CRect r;
r.top = rItem.top;
r.bottom = rCombo.bottom;
r.right = rItem.right;
r.left = r.right - m_pButton->GetWidth(); //Ask the browse button for the width to use
//Create the new browse button
ASSERT(m_pButton);
m_pButton->SetComboBuddy(m_pCombo);
VERIFY(m_pButton->Create(m_pButton->GetCaption(), m_pButton->GetWindowStyle(), r, this, TREE_OPTIONS_BROWSEBUTTONCTRL_ID));
m_pButton->SetOwner(m_pCombo);
}
else
{
//work out the rect for the button
CRect r;
r.top = rText.top;
r.bottom = rText.bottom;
r.right = rItem.right;
r.left = r.right - m_pButton->GetWidth(); //Ask the browse button for the width to use
//Create the browse button
ASSERT(m_pButton);
VERIFY(m_pButton->Create(m_pButton->GetCaption(), m_pButton->GetWindowStyle(), r, this, TREE_OPTIONS_BROWSEBUTTONCTRL_ID));
}
//set the font the edit box should use based on the font in the tree control
m_pButton->SetFont(&m_Font);
}
else
ASSERT(FALSE); //Your class must be derived from CTreeOptionsBrowseButton
}
CString CTreeOptionsCtrl::GetEditText(HTREEITEM hItem) const
{
//Just call the combo box version as currently there is no difference
return GetComboText(hItem);
}
void CTreeOptionsCtrl::SetEditText(HTREEITEM hItem, const CString& sEditText)
{
//Just call the combo box version as currently there is no difference
SetComboText(hItem, sEditText);
}
BOOL CTreeOptionsCtrl::OnSelchanged(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
if (!m_bBeingCleared)
{
//Destroy the old combo or edit box if need be
if (m_hControlItem)
{
UpdateTreeControlValueFromChildControl(m_hControlItem);
DestroyOldChildControl();
m_hControlItem = NULL;
}
//Create the new control if need be
if (pNMTreeView->itemNew.hItem != NULL)
{
CTreeOptionsItemData* pItemData = (CTreeOptionsItemData*) GetItemData(pNMTreeView->itemNew.hItem);
if (pItemData && pItemData->m_pRuntimeClass1)
CreateNewChildControl(pNMTreeView->itemNew.hItem);
}
}
*pResult = 0;
return FALSE;
}
BOOL CTreeOptionsCtrl::OnItemExpanding(NMHDR* /*pNMHDR*/, LRESULT* pResult)
{
//Clean up any controls currently open we used (assuming it is a standard
//scroll message and not from one of our spin controls)
if (m_hControlItem)
{
UpdateTreeControlValueFromChildControl(m_hControlItem);
DestroyOldChildControl();
}
*pResult = 0;
return FALSE;
}
void CTreeOptionsCtrl::Clear()
{
m_bBeingCleared = TRUE;
HTREEITEM hRoot = GetRootItem();
m_hControlItem = NULL;
if (hRoot)
MemDeleteAllItems(hRoot);
m_bBeingCleared = FALSE;
}
void CTreeOptionsCtrl::MemDeleteAllItems(HTREEITEM hParent)
{
HTREEITEM hItem = hParent;
while (hItem)
{
HTREEITEM hNextItem = CTreeCtrl::GetNextItem(hItem, TVGN_NEXT);
if (ItemHasChildren(hItem))
MemDeleteAllItems(GetChildItem(hItem));
CTreeOptionsItemData* pItem = (CTreeOptionsItemData*)CTreeCtrl::GetItemData(hItem);
if (pItem)
delete pItem;
SetItemData(hItem, 0);
//let the base class do its thing
CTreeCtrl::DeleteItem(hItem);
//Move on to the next item
hItem = hNextItem;
}
}
void CTreeOptionsCtrl::OnDestroy()
{
//Destroy the old combo or edit box if need be
DestroyOldChildControl();
//Delete all the items ourselves, rather than calling CTreeCtrl::DeleteAllItems
Clear();
//Let the parent class do its thing
CTreeCtrl::OnDestroy();
}
BOOL CTreeOptionsCtrl::DeleteAllItems()
{
Clear();
//Let the base class do its thing
return CTreeCtrl::DeleteAllItems();
}
void CTreeOptionsCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
if (!(pScrollBar && pScrollBar->IsKindOf(RUNTIME_CLASS(CTreeOptionsSpinCtrl))))
{
//Clean up any controls currently open we used (assuming it is a standard
//scroll message and not from one of our spin controls)
if (m_hControlItem)
{
UpdateTreeControlValueFromChildControl(m_hControlItem);
DestroyOldChildControl();
}
//Let the parent class do its thing
CTreeCtrl::OnVScroll(nSBCode, nPos, pScrollBar);
}
}
void CTreeOptionsCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
//Clean up any controls currently open we used
if (m_hControlItem)
{
UpdateTreeControlValueFromChildControl(m_hControlItem);
DestroyOldChildControl();
}
//Let the parent class do its thing
CTreeCtrl::OnHScroll(nSBCode, nPos, pScrollBar);
}
BOOL CTreeOptionsCtrl::OnClick(NMHDR* /*pNMHDR*/, LRESULT* pResult)
{
//If the mouse was over the label or icon and the item is a combo box
//or edit box and editing is currently not active then create the
//new control
UINT uFlags=0;
CPoint point = GetCurrentMessage()->pt;
ScreenToClient(&point);
HTREEITEM hItem = HitTest(point, &uFlags);
if (hItem)
{
CTreeOptionsItemData* pItemData = (CTreeOptionsItemData*) GetItemData(hItem);
if ((uFlags & TVHT_ONITEM) && pItemData && pItemData->m_pRuntimeClass1 && m_hControlItem == NULL)
CreateNewChildControl(hItem);
//Auto select the control if configured to do so
if (m_bAutoSelect)
PostMessage(WM_TOC_SETFOCUS_TO_CHILD);
}
*pResult = 0;
return FALSE;
}
void CTreeOptionsCtrl::OnKillFocus(CWnd* pNewWnd)
{
//Clean up any controls currently open if we are losing focus to something else
BOOL bForeignWnd = (m_hControlItem && (pNewWnd != m_pCombo) && (pNewWnd != m_pEdit) &&
(pNewWnd != m_pDateTime) && (pNewWnd != m_pIPAddress) && (pNewWnd != m_pButton));
if (bForeignWnd && m_pCombo)
bForeignWnd = !m_pCombo->IsRelatedWnd(pNewWnd);
if (bForeignWnd && m_pDateTime)
bForeignWnd = !m_pDateTime->IsRelatedWnd(pNewWnd);
if (bForeignWnd && m_pIPAddress)
bForeignWnd = !m_pIPAddress->IsRelatedWnd(pNewWnd);
if (bForeignWnd)
{
UpdateTreeControlValueFromChildControl(GetSelectedItem());
DestroyOldChildControl();
}
//Let the parent class do its thing
CTreeCtrl::OnKillFocus(pNewWnd);
}
void CTreeOptionsCtrl::HandleChildControlLosingFocus()
{
//Clean up any controls currently open we used
//if we are losing focus to something else
UpdateTreeControlValueFromChildControl(GetSelectedItem());
DestroyOldChildControl();
}
int CTreeOptionsCtrl::GetIndentPostion(HTREEITEM hItem) const
{
UINT uIndent = GetIndent();
int nAncestors = -1;
while (hItem)
{
hItem = GetParentItem(hItem);
++nAncestors;
}
return nAncestors * uIndent;
}
BOOL CTreeOptionsCtrl::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
{
NMTVCUSTOMDRAW* pCustomDraw = (NMTVCUSTOMDRAW*) pNMHDR;
switch (pCustomDraw->nmcd.dwDrawStage)
{
case CDDS_PREPAINT:
{
*pResult = CDRF_NOTIFYITEMDRAW; //Tell the control that we are interested in item notifications
break;
}
case CDDS_ITEMPREPAINT:
{
//Just let me know about post painting
*pResult = CDRF_NOTIFYPOSTPAINT;
break;
}
case CDDS_ITEMPOSTPAINT:
{
HTREEITEM hItem = (HTREEITEM) pCustomDraw->nmcd.dwItemSpec;
BOOL bDrawColor = FALSE;
CTreeOptionsItemData* pItemData = (CTreeOptionsItemData*) GetItemData(hItem);
if (pItemData && pItemData->m_Type == CTreeOptionsItemData::ColorBrowser && pItemData->m_bDrawColorForIcon)
bDrawColor = TRUE;
if (bDrawColor)
{
//Draw the icon of the tree view item using the specified color
CDC dc;
dc.Attach(pCustomDraw->nmcd.hdc);
CRect r;
r.top = pCustomDraw->nmcd.rc.top;
r.bottom = pCustomDraw->nmcd.rc.bottom;
r.left = pCustomDraw->nmcd.rc.left;
//Allow for the indent
r.left += GetIndentPostion(hItem);
r.right = r.left + 16;
dc.FillSolidRect(&r, GetColor(hItem));
dc.Detach();
}
*pResult = CDRF_DODEFAULT;
break;
}
default:
{
break;
}
}
return TRUE; //Allow the message to be reflected again
}
BOOL CTreeOptionsCtrl::AddDateTime(HTREEITEM hItem, CRuntimeClass* pRuntimeClassDateTime, DWORD dwItemData)
{
//Add the date time control as the primary control
BOOL bSuccess = AddComboBox(hItem, pRuntimeClassDateTime, dwItemData);
//Setup the item type
CTreeOptionsItemData* pItemData = (CTreeOptionsItemData*) GetItemData(hItem);
ASSERT(pItemData);
pItemData->m_Type = CTreeOptionsItemData::DateTimeCtrl;
return bSuccess;
}
void CTreeOptionsCtrl::GetDateTime(HTREEITEM hItem, SYSTEMTIME& st) const
{
CTreeOptionsItemData* pItemData = (CTreeOptionsItemData*) GetItemData(hItem);
ASSERT(pItemData);
CopyMemory(&st, &pItemData->m_DateTime, sizeof(SYSTEMTIME));
}
void CTreeOptionsCtrl::SetDateTime(HTREEITEM hItem, const SYSTEMTIME& st)
{
CTreeOptionsItemData* pItemData = (CTreeOptionsItemData*) GetItemData(hItem);
ASSERT(pItemData);
CopyMemory(&pItemData->m_DateTime, &st, sizeof(SYSTEMTIME));
//Also update the text while we are at it
CTreeOptionsDateCtrl* pTempDateTime = (CTreeOptionsDateCtrl*) pItemData->m_pRuntimeClass1->CreateObject();
ASSERT(pTempDateTime);
ASSERT(pTempDateTime->IsKindOf(RUNTIME_CLASS(CTreeOptionsDateCtrl))); //Your class must be derived from CTreeOptionsDateCtrl
CString sDateTime = pTempDateTime->GetDisplayText(st);
SetEditText(hItem, sDateTime);
delete pTempDateTime;
}
BOOL CTreeOptionsCtrl::AddIPAddress(HTREEITEM hItem, CRuntimeClass* pRuntimeClassDateTime, DWORD dwItemData)
{
//Add the date time control as the primary control
BOOL bSuccess = AddComboBox(hItem, pRuntimeClassDateTime, dwItemData);
//Setup the item type
CTreeOptionsItemData* pItemData = (CTreeOptionsItemData*) GetItemData(hItem);
ASSERT(pItemData);
pItemData->m_Type = CTreeOptionsItemData::IPAddressCtrl;
return bSuccess;
}
DWORD CTreeOptionsCtrl::GetIPAddress(HTREEITEM hItem) const
{
CTreeOpti
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -