⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 treeview.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 5 页
字号:
    COLORREF prevColor = infoPtr->clrLine;

    TRACE("\n");
    infoPtr->clrLine = color;
    return (LRESULT)prevColor;
}


static LRESULT
TREEVIEW_GetTextColor(TREEVIEW_INFO *infoPtr)
{
    TRACE("\n");
    return (LRESULT)infoPtr->clrText;
}

static LRESULT
TREEVIEW_SetTextColor(TREEVIEW_INFO *infoPtr, COLORREF color)
{
    COLORREF prevColor = infoPtr->clrText;

    TRACE("\n");
    infoPtr->clrText = color;

    if (infoPtr->clrText != prevColor)
	TREEVIEW_Invalidate(infoPtr, NULL);

    return (LRESULT)prevColor;
}


static LRESULT
TREEVIEW_GetBkColor(TREEVIEW_INFO *infoPtr)
{
    TRACE("\n");
    return (LRESULT)infoPtr->clrBk;
}

static LRESULT
TREEVIEW_SetBkColor(TREEVIEW_INFO *infoPtr, COLORREF newColor)
{
    COLORREF prevColor = infoPtr->clrBk;

    TRACE("\n");
    infoPtr->clrBk = newColor;

    if (newColor != prevColor)
	TREEVIEW_Invalidate(infoPtr, NULL);

    return (LRESULT)prevColor;
}


static LRESULT
TREEVIEW_GetInsertMarkColor(TREEVIEW_INFO *infoPtr)
{
    TRACE("\n");
    return (LRESULT)infoPtr->clrInsertMark;
}

static LRESULT
TREEVIEW_SetInsertMarkColor(TREEVIEW_INFO *infoPtr, COLORREF color)
{
    COLORREF prevColor = infoPtr->clrInsertMark;

    TRACE("%x\n", color);
    infoPtr->clrInsertMark = color;

    return (LRESULT)prevColor;
}


static LRESULT
TREEVIEW_SetInsertMark(TREEVIEW_INFO *infoPtr, BOOL wParam, HTREEITEM item)
{
    TRACE("%d %p\n", wParam, item);

    if (!TREEVIEW_ValidItem(infoPtr, item))
	return 0;

    infoPtr->insertBeforeorAfter = wParam;
    infoPtr->insertMarkItem = item;

    TREEVIEW_Invalidate(infoPtr, NULL);

    return 1;
}


/************************************************************************
 * Some serious braindamage here. lParam is a pointer to both the
 * input HTREEITEM and the output RECT.
 */
static LRESULT
TREEVIEW_GetItemRect(TREEVIEW_INFO *infoPtr, BOOL fTextRect, LPRECT lpRect)
{
    TREEVIEW_ITEM *wineItem;
    const HTREEITEM *pItem = (HTREEITEM *)lpRect;

    TRACE("\n");
    /*
     * validate parameters
     */
    if (pItem == NULL)
	return FALSE;

    wineItem = *pItem;
    if (!TREEVIEW_ValidItem(infoPtr, wineItem) || !ISVISIBLE(wineItem))
	return FALSE;

    /*
     * If wParam is TRUE return the text size otherwise return
     * the whole item size
     */
    if (fTextRect)
    {
	/* Windows does not send TVN_GETDISPINFO here. */

	lpRect->top = wineItem->rect.top;
	lpRect->bottom = wineItem->rect.bottom;

	lpRect->left = wineItem->textOffset;
	lpRect->right = wineItem->textOffset + wineItem->textWidth;
    }
    else
    {
	*lpRect = wineItem->rect;
    }

    TRACE("%s [L:%d R:%d T:%d B:%d]\n", fTextRect ? "text" : "item",
	  lpRect->left, lpRect->right, lpRect->top, lpRect->bottom);

    return TRUE;
}

static inline LRESULT
TREEVIEW_GetVisibleCount(TREEVIEW_INFO *infoPtr)
{
    /* Suprise! This does not take integral height into account. */
    return infoPtr->clientHeight / infoPtr->uItemHeight;
}


static LRESULT
TREEVIEW_GetItemT(TREEVIEW_INFO *infoPtr, LPTVITEMEXW tvItem, BOOL isW)
{
    TREEVIEW_ITEM *wineItem;

    wineItem = tvItem->hItem;
    if (!TREEVIEW_ValidItem(infoPtr, wineItem))
	return FALSE;

    TREEVIEW_UpdateDispInfo(infoPtr, wineItem, tvItem->mask);

    if (tvItem->mask & TVIF_CHILDREN)
    {
        if (wineItem->cChildren==I_CHILDRENCALLBACK)
            FIXME("I_CHILDRENCALLBACK not supported\n");
	tvItem->cChildren = wineItem->cChildren;
    }

    if (tvItem->mask & TVIF_HANDLE)
	tvItem->hItem = wineItem;

    if (tvItem->mask & TVIF_IMAGE)
	tvItem->iImage = wineItem->iImage;

    if (tvItem->mask & TVIF_INTEGRAL)
	tvItem->iIntegral = wineItem->iIntegral;

    /* undocumented: windows ignores TVIF_PARAM and
     * * always sets lParam
     */
    tvItem->lParam = wineItem->lParam;

    if (tvItem->mask & TVIF_SELECTEDIMAGE)
	tvItem->iSelectedImage = wineItem->iSelectedImage;

    if (tvItem->mask & TVIF_STATE)
        /* Careful here - Windows ignores the stateMask when you get the state
 	    That contradicts the documentation, but makes more common sense, masking
	    retrieval in this way seems overkill */
        tvItem->state = wineItem->state;

    if (tvItem->mask & TVIF_TEXT)
    {
        if (isW)
        {
            if (wineItem->pszText == LPSTR_TEXTCALLBACKW)
            {
                tvItem->pszText = LPSTR_TEXTCALLBACKW;
                FIXME(" GetItem called with LPSTR_TEXTCALLBACK\n");
            }
            else
            {
                lstrcpynW(tvItem->pszText, wineItem->pszText, tvItem->cchTextMax);
            }
        }
        else
        {
            if (wineItem->pszText == LPSTR_TEXTCALLBACKW)
            {
                tvItem->pszText = (LPWSTR)LPSTR_TEXTCALLBACKA;
                FIXME(" GetItem called with LPSTR_TEXTCALLBACK\n");
            }
            else
            {
                WideCharToMultiByte(CP_ACP, 0, wineItem->pszText, -1,
                                    (LPSTR)tvItem->pszText, tvItem->cchTextMax, NULL, NULL);
            }
        }
    }
    TRACE("item <%p>, txt %p, img %p, mask %x\n",
	  wineItem, tvItem->pszText, &tvItem->iImage, tvItem->mask);

    return TRUE;
}

/* Beware MSDN Library Visual Studio 6.0. It says -1 on failure, 0 on success,
 * which is wrong. */
static LRESULT
TREEVIEW_SetItemT(TREEVIEW_INFO *infoPtr, LPTVITEMEXW tvItem, BOOL isW)
{
    TREEVIEW_ITEM *wineItem;
    TREEVIEW_ITEM originalItem;

    wineItem = tvItem->hItem;

    TRACE("item %d,mask %x\n", TREEVIEW_GetItemIndex(infoPtr, wineItem),
	  tvItem->mask);

    if (!TREEVIEW_ValidItem(infoPtr, wineItem))
	return FALSE;

    /* store the orignal item values */
    originalItem = *wineItem;

    if (!TREEVIEW_DoSetItemT(infoPtr, wineItem, tvItem, isW))
	return FALSE;

    /* If the text or TVIS_BOLD was changed, and it is visible, recalculate. */
    if ((tvItem->mask & TVIF_TEXT
	 || (tvItem->mask & TVIF_STATE && tvItem->stateMask & TVIS_BOLD))
	&& ISVISIBLE(wineItem))
    {
	TREEVIEW_UpdateDispInfo(infoPtr, wineItem, TVIF_TEXT);
	TREEVIEW_ComputeTextWidth(infoPtr, wineItem, 0);
    }

    if (tvItem->mask != 0 && ISVISIBLE(wineItem))
    {
	/* The refresh updates everything, but we can't wait until then. */
	TREEVIEW_ComputeItemInternalMetrics(infoPtr, wineItem);

        /* if any of the item's values changed and it's not a callback, redraw the item */
        if (item_changed(&originalItem, wineItem, tvItem))
        {
            if (tvItem->mask & TVIF_INTEGRAL)
	    {
	        TREEVIEW_RecalculateVisibleOrder(infoPtr, wineItem);
	        TREEVIEW_UpdateScrollBars(infoPtr);

	        TREEVIEW_Invalidate(infoPtr, NULL);
	    }
	    else
	    {
	        TREEVIEW_UpdateScrollBars(infoPtr);
	        TREEVIEW_Invalidate(infoPtr, wineItem);
	    }
        }
    }

    return TRUE;
}

static LRESULT
TREEVIEW_GetItemState(TREEVIEW_INFO *infoPtr, HTREEITEM wineItem, UINT mask)
{
    TRACE("\n");

    if (!wineItem || !TREEVIEW_ValidItem(infoPtr, wineItem))
	return 0;

    return (wineItem->state & mask);
}

static LRESULT
TREEVIEW_GetNextItem(TREEVIEW_INFO *infoPtr, UINT which, HTREEITEM wineItem)
{
    TREEVIEW_ITEM *retval;

    retval = 0;

    /* handle all the global data here */
    switch (which)
    {
    case TVGN_CHILD:		/* Special case: child of 0 is root */
	if (wineItem)
	    break;
	/* fall through */
    case TVGN_ROOT:
	retval = infoPtr->root->firstChild;
	break;

    case TVGN_CARET:
	retval = infoPtr->selectedItem;
	break;

    case TVGN_FIRSTVISIBLE:
	retval = infoPtr->firstVisible;
	break;

    case TVGN_DROPHILITE:
	retval = infoPtr->dropItem;
	break;

    case TVGN_LASTVISIBLE:
	retval = TREEVIEW_GetLastListItem(infoPtr, infoPtr->root);
	break;
    }

    if (retval)
    {
	TRACE("flags:%x, returns %p\n", which, retval);
	return (LRESULT)retval;
    }

    if (wineItem == TVI_ROOT) wineItem = infoPtr->root;

    if (!TREEVIEW_ValidItem(infoPtr, wineItem))
	return FALSE;

    switch (which)
    {
    case TVGN_NEXT:
	retval = wineItem->nextSibling;
	break;
    case TVGN_PREVIOUS:
	retval = wineItem->prevSibling;
	break;
    case TVGN_PARENT:
	retval = (wineItem->parent != infoPtr->root) ? wineItem->parent : NULL;
	break;
    case TVGN_CHILD:
	retval = wineItem->firstChild;
	break;
    case TVGN_NEXTVISIBLE:
	retval = TREEVIEW_GetNextListItem(infoPtr, wineItem);
	break;
    case TVGN_PREVIOUSVISIBLE:
	retval = TREEVIEW_GetPrevListItem(infoPtr, wineItem);
	break;
    default:
	TRACE("Unknown msg %x,item %p\n", which, wineItem);
	break;
    }

    TRACE("flags:%x, item %p;returns %p\n", which, wineItem, retval);
    return (LRESULT)retval;
}


static LRESULT
TREEVIEW_GetCount(TREEVIEW_INFO *infoPtr)
{
    TRACE(" %d\n", infoPtr->uNumItems);
    return (LRESULT)infoPtr->uNumItems;
}

static VOID
TREEVIEW_ToggleItemState(TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *item)
{
    if (infoPtr->dwStyle & TVS_CHECKBOXES)
    {
	static const unsigned int state_table[] = { 0, 2, 1 };

	unsigned int state;

	state = STATEIMAGEINDEX(item->state);
	TRACE("state:%x\n", state);
	item->state &= ~TVIS_STATEIMAGEMASK;

	if (state < 3)
	    state = state_table[state];

	item->state |= INDEXTOSTATEIMAGEMASK(state);

	TRACE("state:%x\n", state);
	TREEVIEW_Invalidate(infoPtr, item);
    }
}


/* Painting *************************************************************/

/* Draw the lines and expand button for an item. Also draws one section
 * of the line from item's parent to item's parent's next sibling. */
static void
TREEVIEW_DrawItemLines(TREEVIEW_INFO *infoPtr, HDC hdc, TREEVIEW_ITEM *item)
{
    LONG centerx, centery;
    BOOL lar = ((infoPtr->dwStyle
		 & (TVS_LINESATROOT|TVS_HASLINES|TVS_HASBUTTONS))
		> TVS_LINESATROOT);
    HBRUSH hbr, hbrOld;

    if (!lar && item->iLevel == 0)
	return;

    hbr    = CreateSolidBrush(infoPtr->clrBk);
    hbrOld = SelectObject(hdc, hbr);
    
    centerx = (item->linesOffset + item->stateOffset) / 2;
    centery = (item->rect.top + item->rect.bottom) / 2;

    if (infoPtr->dwStyle & TVS_HASLINES)
    {
	HPEN hOldPen, hNewPen;
	HTREEITEM parent;
        LOGBRUSH lb;

	/*
	 * Get a dotted grey pen
	 */
        lb.lbStyle = BS_SOLID;
        lb.lbColor = infoPtr->clrLine;
        hNewPen = ExtCreatePen(PS_COSMETIC|PS_ALTERNATE, 1, &lb, 0, NULL);
	hOldPen = SelectObject(hdc, hNewPen);

	MoveToEx(hdc, item->stateOffset, centery, NULL);
	LineTo(hdc, centerx - 1, centery);

	if (item->prevSibling || item->parent != infoPtr->root)
	{
	    MoveToEx(hdc, centerx, item->rect.top, NULL);
	    LineTo(hdc, centerx, centery);
	}

	if (item->nextSibling)
	{
	    MoveToEx(hdc, centerx, centery, NULL);
	    LineTo(hdc, centerx, item->rect.bottom + 1);
	}

	/* Draw the line from our parent to its next sibling. */
	parent = item->parent;
	while (parent != infoPtr->root)
	{
	    int pcenterx = (parent->linesOffset + parent->stateOffset) / 2;

	    if (parent->nextSibling
		/* skip top-levels unless TVS_LINESATROOT */
		&& parent->stateOffset > parent->linesOffset)
	    {
		MoveToEx(hdc, pcenterx, item->rect.top, NULL);
		LineTo(hdc, pcenterx, item->rect.bottom + 1);
	    }

	    parent = parent->parent;
	}

	SelectObject(hdc, hOldPen);
	DeleteObject(hNewPen);
    }

    /*
     * Display the (+/-) signs
     */

    if (infoPtr->dwStyle & TVS_HASBUTTONS)
    {
	if (item->cChildren)
	{
            HTHEME theme = GetWindowTheme(infoPtr->hwn

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -