?? treecombobox.cpp
字號:
/****************************************************************/
/* */
/* TreeComboBox.cpp */
/* */
/* Implementation of the CTreeComboBox class */
/* */
/* Author: John Melas */
/* http://www.cc.ece.ntua.gr/~jmelas */
/* jmelas@cc.ece.ntua.gr */
/* */
/* Last updated: August 5, 2004 */
/* */
/****************************************************************/
#include "stdafx.h"
#include "TreeComboBox.h"
#define BUTTON_SIZE 16
#define ICON_SIZE 16
WNDPROC CTreeComboBox::m_parentWndProc = NULL;
CTreeComboBox* CTreeComboBox::m_pActiveCombo = NULL;
IMPLEMENT_DYNAMIC(CTreeComboBox, CButton)
int compare( const void *arg1, const void *arg2 )
{
return _stricmp( * ( char** ) arg1, * ( char** ) arg2 );
}
void Sort(CString &str)
{
char seps[] = "\r\n";
CString items[256];
char *token;
int i;
for (i=0, token = strtok(str.GetBuffer(256), seps); i<256 && token!=NULL; i++, token = strtok(NULL, seps))
items[i] = token;
int max = i;
qsort( (void *)items, (size_t)max, sizeof( char * ), compare );
str = "";
for (i=0; i<max; i++)
str += items[i] + "\r\n";
str.TrimRight("\r\n");
}
void CTreeComboBox::PreSubclassWindow()
{
CButton::PreSubclassWindow();
//create m_edit
CRect rect;
GetClientRect(&rect);
m_multiline = (rect.Height()>(BUTTON_SIZE*2));
if (m_multiline)
rect.DeflateRect(2,2,BUTTON_SIZE+2,2);
else
rect.DeflateRect(ICON_SIZE+6,4,BUTTON_SIZE+2,4);
DWORD plus = 0;
if (m_multiline)
plus = WS_VSCROLL|ES_MULTILINE|ES_WANTRETURN;
m_edit.Create(WS_CHILD|WS_VISIBLE
|ES_AUTOHSCROLL|ES_AUTOVSCROLL|plus,
rect,this,IDC_TEXTCOMBO); //0x401
m_font.CreatePointFont(8,"MS Sans Serif");
m_edit.SetFont(&m_font);
m_edit.SetCombo((CComboBox*)this);
m_edit.SetWindowPos(&wndTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
m_edit.ModifyStyle(0,WS_TABSTOP);
CString text;
GetWindowText(text);
text.Replace(", ","\r\n");
m_edit.SetWindowText(text);
m_edit.UpdateTooltip();
//create m_tree
//m_tree.Create(
m_tree.Create(WS_BORDER|
TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS|TVS_SHOWSELALWAYS|TVS_DISABLEDRAGDROP,
CRect(0,0,0,0),
GetParent(),
0);
DWORD dwStyle = GetWindowLong(m_tree.m_hWnd, GWL_STYLE);
SetWindowLong(m_tree.m_hWnd, GWL_STYLE, (dwStyle | WS_POPUP));
m_tree.SetParent(NULL);
m_tree.SetCombo((CComboBox*)this);
//m_tree.ModifyStyleEx(0,WS_EX_TOOLWINDOW);
if (m_multiline)
m_tree.AllowFolders(FALSE);
InterceptParentWndProc();
}
void CTreeComboBox::InterceptParentWndProc()
{
// ASSERT
CWnd *pwndParent = GetParent();
if (!pwndParent) return;
if (!pwndParent->GetSafeHwnd()) return;
// GET Parent WinProc & SET our function
if (m_parentWndProc)
return;
m_parentWndProc = (WNDPROC)::SetWindowLong(
pwndParent->GetSafeHwnd(),
GWL_WNDPROC,
(long)(WNDPROC)ParentWindowProc);
}
void CTreeComboBox::UnInterceptParentWndProc()
{
// ASSERT
CWnd *pwndParent = GetParent();
if (!pwndParent) return;
if (!pwndParent->GetSafeHwnd()) return;
// SET Parent WinProc = UNINTERCEPT
(WNDPROC)::SetWindowLong(
pwndParent->GetSafeHwnd(),
GWL_WNDPROC,
(long)(WNDPROC)m_parentWndProc);
}
void CTreeComboBox::OnDestroy()
{
// CALL Parent
CButton::OnDestroy();
// UNINTERCEPT
UnInterceptParentWndProc();
}
BEGIN_MESSAGE_MAP(CTreeComboBox, CButton)
//{{AFX_MSG_MAP(CTreeComboBox)
ON_WM_DESTROY()
ON_WM_LBUTTONDOWN()
ON_WM_KILLFOCUS()
ON_WM_SETFOCUS()
ON_WM_LBUTTONUP()
ON_WM_LBUTTONDBLCLK()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void CTreeComboBox::OnLButtonDown(UINT nFlags, CPoint point)
{
// CALL Parent
CButton::OnLButtonDown(nFlags, point);
m_pressed = TRUE;
// SHOW Tree
ShowDropDown();
}
LRESULT CTreeComboBox::WindowProc( UINT message, WPARAM wParam, LPARAM lParam )
{
// CATCH DropDown Keys
switch (message){
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
switch ((int) wParam){
case VK_DOWN:
case VK_UP:
ShowDropDown();
return NULL; // INTERCEPT
case VK_SPACE:
return NULL; // INTERCEPT
}
}
// CALL Parent
return CButton::WindowProc(message, wParam, lParam);
}
HTREEITEM CTreeComboBox::GetNextTreeItem(HTREEITEM hItem)
{
// we return the next HTEEITEM for a tree such as:
// Root (1)
// Child1 (2)
// xxxx (3)
// yyyy (4)
// Chiled2 (5)
// Item (6)
// has this item got any children
if (m_tree.ItemHasChildren(hItem))
{
return m_tree.GetNextItem(hItem, TVGN_CHILD);
}
else if (m_tree.GetNextItem(hItem, TVGN_NEXT) != NULL)
{
// the next item at this level
return m_tree.GetNextItem(hItem, TVGN_NEXT);
}
else
{
// return the next item after our parent
hItem = m_tree.GetParentItem(hItem);
if (hItem == NULL)
{
// no parent
return NULL;
}
while (m_tree.GetNextItem(hItem, TVGN_NEXT) == NULL)
{
if (!hItem)
return NULL;
else
hItem = m_tree.GetParentItem(hItem);
}
// next item that follows our parent
return m_tree.GetNextItem(hItem, TVGN_NEXT);
}
}
BOOL CTreeComboBox::FindItemByText(CString strfind)
{
HTREEITEM hItem = m_tree.GetRootItem();
while (hItem != NULL)
{
CString str = m_tree.GetItemText(hItem);
if (str == strfind)
{
m_tree.SelectItem(hItem);
//updateimage
int pos = -1;
int dummy;
m_tree.GetItemImage(hItem,pos,dummy);
if (m_tree.GetImageList(TVSIL_NORMAL)!=NULL)
UpdateIcon(m_tree.GetImageList(TVSIL_NORMAL)->ExtractIcon(pos));
return TRUE;
}
hItem = GetNextTreeItem(hItem);
}
/*CString str;
m_edit.GetWindowTextA(str);
if (str != "")*/
return FALSE;
}
void CTreeComboBox::Accept()
{
HTREEITEM item = m_tree.GetSelectedItem();
if (item!=NULL)
{
CString str = m_tree.GetItemText(item);
int strpos = -1;
if (m_multiline)
{
CString cur;
m_edit.GetWindowText(cur);
strpos = cur.Find(str);
if (strpos==-1)
{
cur.TrimRight("\r\n ");
cur+="\r\n"+str;
cur.TrimLeft("\r\n");
if (m_sort)
Sort(cur);
strpos = cur.Find(str);
}
str = cur;
}
//update string
SetText(str);
//updateimage
int pos = -1;
int dummy;
m_tree.GetItemImage(item,pos,dummy);
if (m_tree.GetImageList(TVSIL_NORMAL)!=NULL)
UpdateIcon(m_tree.GetImageList(TVSIL_NORMAL)->ExtractIcon(pos));
HideDropDown();
m_edit.SelectText(m_multiline,strpos);
m_edit.SetFocus();
}
}
void CTreeComboBox::DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct )
{
//get dc and rect
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
CRect rc = lpDrawItemStruct->rcItem;
//draw frame
pDC->DrawEdge(rc, EDGE_SUNKEN, BF_RECT);
//draw bg
rc.DeflateRect(2, 2);
//if (m_multiline)
//{
// int scrollbar_width = GetSystemMetrics(SM_CXVSCROLL);
// rc.DeflateRect(scrollbar_width,0,0,0);
//}
if (!m_multiline)
pDC->FillSolidRect(&rc, GetSysColor(COLOR_WINDOW));
//calc button rect
CRect rcButton = rc;
rcButton.left = rcButton.right - BUTTON_SIZE;
if (rcButton.left < rc.left)
rcButton.left = rc.left;
//calc image rect
CRect rcImage = rc;
rcImage.right = rcButton.left - 1;
if (rcImage.right < rcImage.left)
rcImage.right = rcImage.left;
//draw image
if (!m_multiline && m_icon!=NULL)
{
pDC->DrawState(CPoint(rcImage.left+1,rcImage.top),CSize(ICON_SIZE,ICON_SIZE),m_icon,DST_ICON,HBRUSH(0));
rcImage.DeflateRect(ICON_SIZE+2,0,0,0);
}
//draw focus
/*rcImage.DeflateRect(1,1,0,1);
if (lpDrawItemStruct->itemState & ODS_FOCUS)
{
COLORREF c=GetSysColor(COLOR_HIGHLIGHT);
pDC->FillSolidRect(rcImage,RGB(255-GetRValue(c),255-GetGValue(c),255-GetBValue(c)));
pDC->DrawFocusRect(rcImage);
}
rcImage.DeflateRect(1,1,1,1);
// GET Caption
CString strText;
GetWindowText(strText);
// DRAW Caption
if (lpDrawItemStruct->itemState & ODS_FOCUS)
{
pDC->SetBkColor(GetSysColor(COLOR_HIGHLIGHT));
pDC->SetTextColor(GetSysColor(COLOR_HIGHLIGHTTEXT));
pDC->FillSolidRect(rcImage,GetSysColor(COLOR_HIGHLIGHT));
rcImage.DeflateRect(1,0,0,0);
pDC->DrawText(strText, &rcImage, DT_SINGLELINE | DT_VCENTER );
}
else
{
pDC->SetBkColor( GetSysColor(COLOR_WINDOW) );
pDC->SetTextColor(RGB(0, 0, 0));
rcImage.DeflateRect(1,0,0,0);
pDC->DrawText(strText, &rcImage, DT_SINGLELINE | DT_VCENTER );
}*/
//draw button
//pDC->FillSolidRect(rcButton,RGB(234,232,228));
if (m_multiline)
{
// rcButton.OffsetRect(0,rcButton.Height()-rcButton.Width());
// rcButton.bottom=rcButton.top+rcButton.Width();
}
CRect frect = rcButton;
CBrush brBtnShadow(GetSysColor(COLOR_BTNSHADOW));
CBrush brBtnFace(GetSysColor(COLOR_BTNFACE));
//if (lpDrawItemStruct->itemState & ODS_SELECTED)
if (m_pressed && m_pActiveCombo!=NULL)
{
pDC->FrameRect(frect, &brBtnShadow);
frect.DeflateRect(1, 1);
pDC->FillRect(&frect, &brBtnFace);
frect.DeflateRect(1, 3, 0, 0);
}
else
{
pDC->FrameRect(frect, &brBtnFace);
//frect.DeflateRect(1, 1, 0, 0);
//DrawFrameControl(lpDrawItemStruct->hDC, &frect, DFC_BUTTON, uStyle);
pDC->Draw3dRect(frect,GetSysColor(COLOR_BTNFACE),GetSysColor(COLOR_3DDKSHADOW));
frect.DeflateRect(1, 1, 1, 1);
pDC->Draw3dRect(frect,GetSysColor(COLOR_3DHILIGHT),GetSysColor(COLOR_3DSHADOW));
frect.DeflateRect(1, 1, 1, 1);
pDC->FillRect(&frect, &brBtnFace);
}
//draw arrow
//if (lpDrawItemStruct->itemState & ODS_SELECTED)
if (m_pressed && m_pActiveCombo!=NULL)
rcButton.DeflateRect(1,1,0,0);
CPen penBlack(PS_SOLID, 1, RGB(0, 0, 0));
CPen* ppenOld = pDC->SelectObject(&penBlack);
for(long i=0; i<4; i++){
pDC->MoveTo( rcButton.left + 4 + i, rcButton.top + rcButton.Height()/2 - 2 + i);
pDC->LineTo( rcButton.left + 4 + 7 - i, rcButton.top + rcButton.Height()/2 - 2 + i);
}
pDC->SelectObject(ppenOld);
m_edit.Invalidate();
}
void CTreeComboBox::ShowDropDown()
{
if (m_pActiveCombo!=NULL)
{
HideDropDown();
//m_edit.SelectText(m_multiline);
m_edit.SetFocus();
return;
}
CRect rc;
GetWindowRect(&rc);
m_tree.SetWindowPos(&wndTopMost,rc.left, rc.bottom, rc.Width(), 220,SWP_SHOWWINDOW);
CWnd* pTopParent = GetParent()->GetParentOwner();
if (pTopParent != NULL)
{
pTopParent->SendMessage( WM_NCACTIVATE, TRUE );
pTopParent->SetRedraw( TRUE );
}
m_pActiveCombo = this;
}
void CTreeComboBox::HideDropDown()
{
if (m_pActiveCombo!=NULL)
{
m_pActiveCombo->GetTree()->ShowWindow( SW_HIDE );
m_pActiveCombo = NULL;
}
}
LRESULT CALLBACK CTreeComboBox::ParentWindowProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
// CHECK Message
if (nMsg==WM_COMMAND ||
nMsg==WM_SYSCOMMAND ||
nMsg==WM_SYSKEYDOWN ||
nMsg==WM_LBUTTONDOWN ||
nMsg==WM_NCLBUTTONDOWN)
{
// FILTER Messages
if (!IsMsgOK(hWnd, nMsg, lParam))
m_pActiveCombo->HideDropDown();
}
// CALL Parent
if (!m_parentWndProc)
return NULL;
return CallWindowProc( m_parentWndProc, hWnd, nMsg, wParam, lParam );
}
BOOL CTreeComboBox::IsMsgOK(HWND hWnd, UINT nMsg, /*WPARAM wParam,*/ LPARAM lParam)
{
// ASSERT
if (!hWnd)
return FALSE;
if (nMsg != WM_COMMAND)
return FALSE;
if (!m_pActiveCombo)
return FALSE;
if ((HWND)lParam != m_pActiveCombo->GetSafeHwnd())
return FALSE;
//check if mouse pos is in drop down rect
CRect rc;
m_pActiveCombo->GetWindowRect(rc);
CPoint pt;
GetCursorPos(&pt);
if (!rc.PtInRect(pt))
return FALSE;
return TRUE;
}
void CTreeComboBox::OnKillFocus(CWnd* pNewWnd)
{
// CALL Parent
CButton::OnKillFocus(pNewWnd);
// HIDE Active DropDown
if (pNewWnd != &m_edit)
HideDropDown();
}
void CTreeComboBox::OnSetFocus(CWnd* pOldWnd)
{
CButton::OnSetFocus(pOldWnd);
if (!m_pressed)
m_edit.SetFocus();
}
void CTreeComboBox::LoadXmlSubTree(CXmlElement *pElement, HTREEITEM hItem)
{
CXmlElement *pChild = m_xmlDocument.GetFirstChild(pElement);
while (pChild != NULL)
{
CString name = pChild->GetValue("name");
if (name=="")
name = pChild->m_strData;
if (name=="")
name = pChild->m_strName;
int image = (pChild->m_ChildElements.GetCount()!=0)?0:2;
HTREEITEM hChildItem = m_tree.InsertItem(name, image, image, hItem);
// save data
m_tree.SetItemData(hChildItem, (DWORD)pChild);
LoadXmlSubTree(pChild, hChildItem);
pChild = m_xmlDocument.GetNextSibling(pElement);
}
}
void CTreeComboBox::LoadXml(CString filename, int bmp)
{
//m_imagelist.Create(bmp,16,1,RGB(255,0,0));
m_imagelist.Create(bmp,16,1,RGB(255,0,0));
m_tree.SetImageList(&m_imagelist,TVSIL_NORMAL);
m_xmlDocument.DeleteContents();
if (m_xmlDocument.Load(filename))
{
m_tree.DeleteAllItems();
LoadXmlSubTree(m_xmlDocument.GetRootElement(), TVI_ROOT);
}
}
void CTreeComboBox::LoadString(CString info, int bmp)
{
if (!m_imagelist)
{
m_imagelist.Create(bmp,16,1,RGB(255,255,255));
m_tree.SetImageList(&m_imagelist,TVSIL_NORMAL);
}
m_xmlDocument.DeleteContents();
if (m_xmlDocument.LoadString(info))
{
m_tree.DeleteAllItems();
LoadXmlSubTree(m_xmlDocument.GetRootElement(), TVI_ROOT);
}
}
void CTreeComboBox::OnLButtonUp(UINT nFlags, CPoint point)
{
m_pressed = FALSE;
if (m_pActiveCombo)
Invalidate();
CButton::OnLButtonUp(nFlags, point);
}
void CTreeComboBox::OnLButtonDblClk(UINT nFlags, CPoint point)
{
OnLButtonDown(nFlags, point);
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -