📄 osdtreeview.c
字号:
p = pParent->child;
while (p->next != NULL)
p = p->next;
p->next = pChild;
}
pData->nItemCount++; /*总数加一*/
pData->nVisItemCount++;
deep = getItemdeep (pData, pChild);
hdc = GetDC (hwnd);
GetTextExtentPoint(hdc, pChild->text, -1, &pChild->text_ext);
h = pData->nItemHeight;
w = TVBoxGap + h + TVBoxGap + pChild->text_ext.cx + deep * h;
if (pData->dwStyle & TVS_WITHICON)
w += h + TVICONGAP;
pData->nWidth = MAX (w, pData->nWidth);
ReleaseDC (hwnd, hdc);
}
/*****************************************************************************
up-,down-
*****************************************************************************/
static void tvDrawItem (HDC hdc, PTVDATA pData, int centerX, int centerY,PTVITEM p, int up, int down)
{
HWND hwnd=WindowFromDC(hdc);
int h = pData->nItemHeight;
SIZE size;
centerX-=hwnd->ScrollLeft;
centerY-=hwnd->ScrollTop;
SetPenColor (hdc, 0x000000);
// draw box.
if (p->child != NULL) /*有子节点*/
{
Rectangle (hdc, centerX - TVBoxHalfHeight, centerY - TVBoxHalfHeight,centerX + TVBoxHalfHeight, centerY + TVBoxHalfHeight);
MoveToEx (hdc, centerX - TVBoxHalfHeight + 2, centerY,NULL);
LineTo (hdc, centerX + TVBoxHalfHeight - 1, centerY);
if (p->dwFlags & TVIF_FOLD) /*本节点折叠 画"+ "*/
{
MoveToEx(hdc, centerX, centerY - TVBoxHalfHeight + 2,NULL); /*画 | */
LineTo (hdc, centerX, centerY + TVBoxHalfHeight - 2);
MoveToEx(hdc, centerX, centerY - (h>>1) - h * up,NULL);
LineTo (hdc, centerX, centerY - TVBoxHalfHeight);
}else{ /*本节点展开画"--" */
MoveToEx(hdc, centerX, centerY - (h>>1) - h * up,NULL);
LineTo (hdc, centerX, centerY - TVBoxHalfHeight);
}
MoveToEx(hdc, centerX + TVBoxHalfHeight, centerY,NULL); /*画-- */
LineTo (hdc, centerX + (h>>1) + TVBoxGap, centerY);
if (p->next != NULL) /*有同级的下一节点*/
{
MoveToEx(hdc, centerX, centerY + TVBoxHalfHeight,NULL); /*画 | */
LineTo (hdc, centerX, centerY + (h>>1) + h * down);
}
}else{//==================================================
MoveToEx(hdc, centerX, centerY - (h>>1) - h * up,NULL);
LineTo (hdc, centerX, centerY);
LineTo (hdc, centerX + (h>>1) + TVBoxGap, centerY);
if (p->next != NULL){
MoveToEx(hdc, centerX, centerY,NULL);
LineTo (hdc, centerX, centerY + (h>>1) + h * down);
}
}
centerX += (h>>1) + TVBoxGap;
//==================================================
//画节点的图标
if (pData->dwStyle & TVS_WITHICON)
{
if (!(pData->dwStyle & TVS_ICONFORSELECT) && (!p->child || (p->dwFlags & TVIF_FOLD)))
{
//if((p->IconFold)DrawIcon(hdc,centerX,centerY-(h>>1),(HICON) p->IconFold);
}else if ((pData->dwStyle & TVS_ICONFORSELECT) && p->dwFlags & TVIF_SELECTED)
{
//if ((p->IconFold))DrawIcon(hdc,centerX,centerY-(h>>1),(HICON) p->IconFold);
}else{
// if((p->IconUnfold))DrawIcon(hdc,centerX,centerY-(h>>1),(HICON)p->IconUnfold);
}
centerX += h + TVICONGAP;
}
//==================================================
// draw text.
GetTextExtentPoint (hdc, p->text, strlen(p->text),&size);
if (p->dwFlags & TVIF_SELECTED) /*选中项*/
{
SetBkColor (hdc, GetSysColor( COLOR_BTNTEXT));
SetTextColor (hdc, GetSysColor( COLOR_HIGHLIGHTTEXT));
FillBox(hdc, centerX, centerY - (h>>1),size.cx,h, RGB(0,0,255));
TextOut (hdc, centerX, centerY - (h>>1), p->text,-1);
}else{ /*普通项*/
SetBkColor (hdc, GetWindowBackColor(WindowFromDC(hdc)));
FillBox(hdc, centerX, centerY - (h>>1),size.cx,h,GetWindowBackColor(WindowFromDC(hdc)));
SetTextColor (hdc, GetWindowForeColor(WindowFromDC(hdc)));
TextOut (hdc, centerX, centerY - (h>>1), p->text,-1);
}
}
/*****************************************************************************
draw all items.
input: p -开始节点
*****************************************************************************/
static void doAll (HDC hdc, PTVDATA pData, PTVITEM p, int cenX, int cenY, int c, int d)
{
static int deep, count;
int up, down, h = pData->nItemHeight;
PTVITEM t;
deep = d;
count = c;
up = getItemsWithPrev (pData, p);
down = getItemsWithNext (pData, p);
if (count >= pData->nItemTop)
tvDrawItem (hdc, pData, cenX + deep * pData->nItemHeight, cenY + (count - pData->nItemTop) * pData->nItemHeight, p, up, down);
count++;
if (!(p->dwFlags & TVIF_FOLD)) /*该节点项展开*/
{
t = p->child;
deep++;
while (t)
{
doAll (hdc, pData, t, cenX, cenY, count, deep);
//if (count > pData->nItemTop + pData->nVisCount) return; /*超出显示范围*/
t = t->next;
}
deep--;
}
}
/*****************************************************************************
*****************************************************************************/
static void tvSetVScrollInfo (HWND hwnd, PTVDATA pData, BOOL fRedraw)
{
SCROLLINFO si;
RECT rc;
GetClientRect(hwnd, &rc);
if (pData->nVisCount >= pData->nVisItemCount)
{
SetScrollPos (hwnd, SB_VERT, 0,FALSE);
EnableScrollBar (hwnd, SB_VERT, FALSE);
ShowScrollBar (hwnd, SB_VERT, FALSE);
return;
}
si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
si.nMax = getVisItemCount (pData) * pData->nItemHeight;
si.nMin = 0;
si.nPage =RECTH(&rc);
si.nPos = hwnd->ScrollTop;
SetScrollInfo (hwnd, SB_VERT, &si, fRedraw);
EnableScrollBar (hwnd, SB_VERT, TRUE);
ShowScrollBar (hwnd, SB_VERT, TRUE);
}
/*****************************************************************************
*****************************************************************************/
static void tvSetHScrollInfo (HWND hwnd, PTVDATA pData, BOOL fRedraw)
{
SCROLLINFO si;
RECT rc;
GetClientRect(hwnd, &rc);
if (pData->nVisWidth >= pData->nWidth)
{
SetScrollPos (hwnd, SB_HORZ, 0,FALSE);
ShowScrollBar (hwnd, SB_HORZ, FALSE);
EnableScrollBar (hwnd, SB_HORZ, FALSE);
return;
}
si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
si.nMax = pData->nWidth - 1;
si.nMin = 0;
si.nPage = RECTW(&rc);
si.nPos = hwnd->ScrollLeft;
SetScrollInfo (hwnd,SB_HORZ,&si,fRedraw);
ShowScrollBar (hwnd,SB_HORZ,TRUE);
EnableScrollBar (hwnd,SB_HORZ,TRUE);
}
/*****************************************************************************
*****************************************************************************/
static void tvRecalcWidthsHelper (HDC hdc, PTVITEM p)
{
while (p)
{
GetTextExtentPoint(hdc, p->text, -1, &p->text_ext);
if (p->child)
tvRecalcWidthsHelper (hdc, p->child);
p = p->next;
}
}
/*****************************************************************************
*****************************************************************************/
static void tvRecalcWidths (HWND hwnd, PTVDATA pData)
{
HDC hdc = GetDC(hwnd);
tvRecalcWidthsHelper (hdc, pData->root);
ReleaseDC (hwnd, hdc);
pData->nWidth = getTVWidth (pData);
pData->nVisItemCount = getVisItemCount (pData);
InvalidateRect (hwnd, NULL, FALSE);
tvSetVScrollInfo (hwnd, pData, TRUE);
tvSetHScrollInfo (hwnd, pData, TRUE);
}
/*****************************************************************************
画出整个控件
*****************************************************************************/
static void tvOnDraw (HWND hwnd, HDC hdc, PTVDATA pData)
{
RECT rcClient;
int centerX, centerY;
GetClientRect (hwnd, &rcClient);
FillRectangle(hdc, &rcClient,GetWindowBackColor(hwnd));
centerX = rcClient.left + TVBoxGap + (pData->nItemHeight>>1);
centerY = rcClient.top + (pData->nItemHeight>>1);
doAll(hdc, pData, pData->root, centerX, centerY, 0, 0);
}
/*****************************************************************************
取出
input: count-
*****************************************************************************/
static PTVITEM ItemFromCount (PTVITEM p, int count, int c)
{
PTVITEM q, t = NULL;
static int cnt;
cnt = c;
cnt++;
if (cnt == count)
return p;
else if (p->child != NULL && !(p->dwFlags & TVIF_FOLD)) /*本节点已展开*/
{
q = p->child;
while (q != NULL && !(t = ItemFromCount (q, count, cnt)))
q = q->next;
}
else
return NULL;
return t;
}
/*****************************************************************************
根据在第几行row 取出节点
*****************************************************************************/
static PTVITEM getItemFromRow (PTVDATA pData, int nRow)
{
if (pData->root == NULL)
return NULL;
return ItemFromCount (pData->root, nRow, 0);
}
/*****************************************************************************
从p 到ptgt共有多少可视行
*****************************************************************************/
static int CountFromItem (PTVITEM p, PTVITEM pTgt, int c)
{
static int count;
int t = 0;
PTVITEM q;
count = c;
count++;
if (p == pTgt)
return count;
else if (p->child != NULL && !(p->dwFlags & TVIF_FOLD))
{
q = p->child;
while (q != NULL && !(t = CountFromItem (q, pTgt, count)))
q = q->next;
}
else
return 0;
return t;
}
/*****************************************************************************
从根节点到指定节点共有多少可视行
*****************************************************************************/
static int getCountFromItem (PTVDATA pData, PTVITEM pNode)
{
if (pNode == NULL) return 0;
return CountFromItem (pData->root, pNode, 0);
}
/*****************************************************************************
*****************************************************************************/
static UINT TreeViewCtrlProc (HWND hwnd, int message, WPARAM wParam, LPARAM lParam)
{
//PAINTSTRUCT ps;
PTVDATA pData=(PTVDATA)GetWinData(hwnd);
DWORD dwStyle;
switch (message)
{
case WM_CREATE:
dwStyle = GetWindowStyle (hwnd);
if (!(pData =(TVDATA*)PrMalloc(sizeof(TVDATA)))) return -1;
SetWindowLong(hwnd, 0, (LONG) pData);
if (!tvInitTVData (hwnd, pData, dwStyle))
{
mwOsFreeMemory (pData);
return -1;
}
if (pData->dwStyle & TVS_WITHICON)
{
SetIconKind(ICON_SMALL);
pData->root->IconFold =LoadIconFromFile("tools/icon/w95mbx03.ico");// (DWORD)GetSystemIcon(1);// ICON_FOLD;
pData->root->IconUnfold =LoadIconFromFile("tools/icon/w95mbx03.ico");// (DWORD) GetSystemIcon(2);// CON_UNFOLD;
}
//houzh SetWindowBackColor(hwnd, COLOR_WHITE);
break;
//=====================================================================
case WM_SIZING:
{
RECT rc;
GetClientRect(hwnd, &rc);
pData->nVisCount =(RECTH(&rc)) / pData->nItemHeight;
pData->nVisWidth =RECTW (&rc);
}
break;
//=====================================================================
case WM_DESTROY:
RemoveTree (hwnd, pData, pData->root);
PrFree(pData);
break;
case WM_GETTEXTLENGTH:
case WM_GETTEXT:
case WM_SETTEXT:
return -1;
//=====================================================================
case WM_PAINT:
if (hwnd->bRedraw==TRUE){
HDC hdc;
PAINTSTRUCT ps;
hdc = BeginPaint(hwnd,&ps);
tvOnDraw (hwnd, hdc, pData);
EndPaint (hwnd,&ps);
}break;
//=====================================================================
case TVM_GETROOT:return (DWORD) pData->root;
break;
//=====================================================================
case TVM_FINDITEM:
{
char *buffer;
PTVITEM p, q;
buffer = (char *) lParam;
if (buffer == NULL) return -1;
p = find (pData, buffer);
if (p == NULL) return -1;
pData->pItemSelected->dwFlags &= ~TVIF_SELECTED;
p->dwFlags |= TVIF_SELECTED;
pData->pItemSelected = p;
q = getParent (pData, p);
while (q){
q->dwFlags &= ~TVIF_FOLD;
q = getParent (pData, q);
}
pData->nVisItemCount = getVisItemCount (pData);
pData->nWidth = getTVWidth (pData);
InvalidateRect (hwnd, NULL, FALSE);
tvSetVScrollInfo (hwnd, pData, TRUE);
tvSetHScrollInfo (hwnd, pData, TRUE);
if (wParam != 0)
*(PTVITEM *) wParam = p;
return 0;
}
//=====================================================================
case TVM_GETSELITEM:
if (wParam != 0)
*(PTVITEM *) wParam = pData->pItemSelected;
return 0;
//=====================================================================
case TVM_CHANGESELTEXT:
{
char *buffer;
PTVITEM p;
int id = LOWORD (wParam);
buffer = (char *) lParam;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -