Exemplo n.º 1
0
int HitTest(HWND hwnd, struct ClcData *dat, int testx, int testy, ClcContact **contact, ClcGroup **group, DWORD *flags)
{
	ClcContact *hitcontact = NULL;
	ClcGroup *hitgroup = NULL;
	int indent, width, i;
	int checkboxWidth;
	SIZE textSize;
	RECT clRect;
	HFONT hFont;
	DWORD style = GetWindowLongPtr(hwnd, GWL_STYLE);
	BYTE mirror_mode = cfg::dat.bUseDCMirroring;

	if (flags)
		*flags = 0;
	GetClientRect(hwnd, &clRect);
	if (testx < 0 || testy < 0 || testy >= clRect.bottom || testx >= clRect.right) {
		if (flags) {
			if (testx < 0)
				*flags |= CLCHT_TOLEFT;
			else if (testx >= clRect.right)
				*flags |= CLCHT_TORIGHT;
			if (testy < 0)
				*flags |= CLCHT_ABOVE;
			else if (testy >= clRect.bottom)
				*flags |= CLCHT_BELOW;
		}
		return -1;
	}
	if (testx < dat->leftMargin) {
		if (flags)
			*flags |= CLCHT_INLEFTMARGIN | CLCHT_NOWHERE;
		return -1;
	}
	int hit = RowHeight::hitTest(dat, dat->yScroll + testy);
	if (hit != -1)
		hit = pcli->pfnGetRowByIndex(dat, hit, &hitcontact, &hitgroup);

	if (hit == -1) {
		if (flags)
			*flags |= CLCHT_NOWHERE | CLCHT_BELOWITEMS;
		return -1;
	}
	if (contact)
		*contact = hitcontact;
	if (group)
		*group = hitgroup;

	for (indent = 0; hitgroup->parent; indent++, hitgroup = hitgroup->parent)
		;

	if (!dat->bisEmbedded) {
		if (hitcontact->type == CLCIT_CONTACT) {
			if (mirror_mode == 1 || (mirror_mode == 2 && hitcontact->pExtra->dwCFlags & ECF_RTLNICK))
				return RTL_HitTest(hwnd, dat, testx, hitcontact, flags, indent, hit);
		}
		else if (hitcontact->type == CLCIT_GROUP) {
			if (cfg::dat.bGroupAlign == CLC_GROUPALIGN_RIGHT || (hitcontact->isRtl && cfg::dat.bGroupAlign == CLC_GROUPALIGN_AUTO))
				return RTL_HitTest(hwnd, dat, testx, hitcontact, flags, indent, hit);
		}
	}

	// avatar check
	if (hitcontact->type == CLCIT_CONTACT && cfg::dat.dwFlags & CLUI_FRAME_AVATARS && hitcontact->ace != NULL && hitcontact->avatarLeft != -1) {
		if (testx > hitcontact->avatarLeft && testx < hitcontact->avatarLeft + cfg::dat.avatarSize) {
			if (flags)
				*flags |= CLCHT_ONAVATAR;
		}
	}
	if (testx < dat->leftMargin + indent * dat->groupIndent) {
		if (flags)
			*flags |= CLCHT_ONITEMINDENT;
		return hit;
	}
	checkboxWidth = 0;
	if (style & CLS_CHECKBOXES && hitcontact->type == CLCIT_CONTACT)
		checkboxWidth = dat->checkboxSize + 2;
	if (style & CLS_GROUPCHECKBOXES && hitcontact->type == CLCIT_GROUP)
		checkboxWidth = dat->checkboxSize + 2;
	if (hitcontact->type == CLCIT_INFO && hitcontact->flags & CLCIIF_CHECKBOX)
		checkboxWidth = dat->checkboxSize + 2;
	if (testx < dat->leftMargin + indent * dat->groupIndent + checkboxWidth) {
		if (flags)
			*flags |= CLCHT_ONITEMCHECK;
		return hit;
	}
	if (testx < dat->leftMargin + indent * dat->groupIndent + checkboxWidth + dat->iconXSpace) {
		if (flags)
			*flags |= CLCHT_ONITEMICON;
		return hit;
	}

	int rightOffset = hitcontact->extraIconRightBegin;
	if (rightOffset) {
		for (i = dat->extraColumnsCount - 1; i >= 0; i--) {
			if (hitcontact->iExtraImage[i] == EMPTY_EXTRA_ICON)
				continue;

			rightOffset -= dat->extraColumnSpacing;
			if (testx > rightOffset && testx < rightOffset + dat->extraColumnSpacing) {
				if (flags)
					*flags |= (CLCHT_ONITEMEXTRA | (i << 24));
				return hit;
			}
		}
	}

	HDC hdc = GetDC(hwnd);
	if (hitcontact->type == CLCIT_GROUP)
		hFont = reinterpret_cast<HFONT>(SelectObject(hdc, dat->fontInfo[FONTID_GROUPS].hFont));
	else
		hFont = reinterpret_cast<HFONT>(SelectObject(hdc, dat->fontInfo[FONTID_CONTACTS].hFont));
	GetTextExtentPoint32(hdc, hitcontact->szText, (int)mir_tstrlen(hitcontact->szText), &textSize);
	width = textSize.cx;
	if (hitcontact->type == CLCIT_GROUP) {
		TCHAR *szCounts;
		szCounts = pcli->pfnGetGroupCountsText(dat, hitcontact);
		if (szCounts[0]) {
			GetTextExtentPoint32(hdc, _T(" "), 1, &textSize);
			width += textSize.cx;
			SelectObject(hdc, dat->fontInfo[FONTID_GROUPCOUNTS].hFont);
			GetTextExtentPoint32(hdc, szCounts, (int)mir_tstrlen(szCounts), &textSize);
			width += textSize.cx;
		}
	}
	SelectObject(hdc, hFont);
	ReleaseDC(hwnd, hdc);
	if (cfg::dat.dwFlags & CLUI_FULLROWSELECT && !(GetKeyState(VK_SHIFT) & 0x8000) && testx > dat->leftMargin + indent * dat->groupIndent + checkboxWidth + dat->iconXSpace + width + 4 + (cfg::dat.dwFlags & CLUI_FRAME_AVATARS ? cfg::dat.avatarSize : 0)) {
		if (flags)
			*flags |= CLCHT_ONITEMSPACE;
		return hit;
	}
	if (testx < dat->leftMargin + indent * dat->groupIndent + checkboxWidth + dat->iconXSpace + width + 4 + (cfg::dat.dwFlags & CLUI_FRAME_AVATARS ? cfg::dat.avatarSize : 0)) {
		if (flags)
			*flags |= CLCHT_ONITEMLABEL;
		return hit;
	}
	if (flags)
		*flags |= CLCHT_NOWHERE;
	return -1;
}
Exemplo n.º 2
0
int HitTest(HWND hwnd, struct ClcData *dat, int testx, int testy, struct ClcContact **contact, struct ClcGroup **group, DWORD *flags)
{
    struct ClcContact *hitcontact;
    struct ClcGroup *hitgroup;
    int hit, indent, width, i, cxSmIcon;
    int checkboxWidth;
    SIZE textSize;
    HDC hdc;
    RECT clRect;
    HFONT hFont;
    DWORD style = GetWindowLong(hwnd, GWL_STYLE);
	BYTE mirror_mode = cfg::dat.bUseDCMirroring;

    if (flags)
        *flags = 0;
    GetClientRect(hwnd, &clRect);
    if (testx < 0 || testy < 0 || testy >= clRect.bottom || testx >= clRect.right) {
        if (flags) {
            if (testx < 0)
                *flags |= CLCHT_TOLEFT;
            else if (testx >= clRect.right)
                *flags |= CLCHT_TORIGHT;
            if (testy < 0)
                *flags |= CLCHT_ABOVE;
            else if (testy >= clRect.bottom)
                *flags |= CLCHT_BELOW;
        }
        return -1;
    }
    if (testx< dat->leftMargin) {
        if (flags)
            *flags |= CLCHT_INLEFTMARGIN | CLCHT_NOWHERE;
        return -1;
    }
   	hit = RowHeight::hitTest(dat, dat->yScroll + testy);
	if (hit != -1)
		hit = pcli->pfnGetRowByIndex(dat, hit, &hitcontact, &hitgroup);

    if (hit == -1) {
        if (flags)
            *flags |= CLCHT_NOWHERE | CLCHT_BELOWITEMS;
        return -1;
    }
    if (contact)
        *contact = hitcontact;
    if (group)
        *group = hitgroup;

    for (indent = 0; hitgroup->parent; indent++,hitgroup = hitgroup->parent) {
        ;
    }

    if(!dat->bisEmbedded) {
        if(hitcontact->type == CLCIT_CONTACT) {
            if(mirror_mode == 1 || (mirror_mode == 2 && cfg::eCache[hitcontact->extraCacheEntry].dwCFlags & ECF_RTLNICK))
                return RTL_HitTest(hwnd, dat, testx, testy, hitcontact, flags, indent, hit);
        }
        else if(hitcontact->type == CLCIT_GROUP) {
            if(cfg::dat.bGroupAlign == CLC_GROUPALIGN_RIGHT || (hitcontact->isRtl && cfg::dat.bGroupAlign == CLC_GROUPALIGN_AUTO))
                return RTL_HitTest(hwnd, dat, testx, testy, hitcontact, flags, indent, hit);
        }
    }

    // avatar check
    if(hitcontact->type == CLCIT_CONTACT && cfg::dat.dwFlags & CLUI_FRAME_AVATARS && hitcontact->ace != NULL && hitcontact->avatarLeft != -1) {
        if(testx >hitcontact->avatarLeft && testx < hitcontact->avatarLeft + cfg::dat.avatarSize) {
            if(flags)
                *flags |= CLCHT_ONAVATAR;
        }
    }
    if (testx< dat->leftMargin + indent * dat->groupIndent) {
        if (flags)
            *flags |= CLCHT_ONITEMINDENT;
        return hit;
    }
    checkboxWidth = 0;
    if (style & CLS_CHECKBOXES && hitcontact->type == CLCIT_CONTACT)
        checkboxWidth = dat->checkboxSize + 2;
    if (style & CLS_GROUPCHECKBOXES && hitcontact->type == CLCIT_GROUP)
        checkboxWidth = dat->checkboxSize + 2;
    if (hitcontact->type == CLCIT_INFO && hitcontact->flags & CLCIIF_CHECKBOX)
        checkboxWidth = dat->checkboxSize + 2;
    if (testx< dat->leftMargin + indent * dat->groupIndent + checkboxWidth) {
        if (flags)
            *flags |= CLCHT_ONITEMCHECK;
        return hit;
    }
    if (testx< dat->leftMargin + indent * dat->groupIndent + checkboxWidth + dat->iconXSpace) {
        if (flags)
            *flags |= CLCHT_ONITEMICON;
        return hit;
    }
    cxSmIcon = GetSystemMetrics(SM_CXSMICON);
    for (i = 0; i< dat->extraColumnsCount; i++) {
        if (hitcontact->iExtraImage[i] == 0xFF)
            continue;
        if (testx >= clRect.right - dat->extraColumnSpacing * (dat->extraColumnsCount - i) && testx< clRect.right - dat->extraColumnSpacing * (dat->extraColumnsCount - i) + cxSmIcon) {
            if (flags)
                *flags |= CLCHT_ONITEMEXTRA | (i << 24);
            return hit;
        }
    }
    if(hitcontact->extraCacheEntry >= 0 && hitcontact->extraCacheEntry < cfg::nextCacheEntry && cfg::eCache[hitcontact->extraCacheEntry].iExtraValid) {
        //int rightOffset = clRect.right;
        int rightOffset = hitcontact->extraIconRightBegin;
        int images_present = 0;

        for (i = 5; i >= 0; i--) {
            if (cfg::eCache[hitcontact->extraCacheEntry].iExtraImage[i] == 0xFF)
                continue;
            if(!((1 << i) & cfg::eCache[hitcontact->extraCacheEntry].dwXMask))
                continue;
            images_present++;
            if (testx > (rightOffset - (cfg::dat.exIconScale + 2) * images_present) && testx < (rightOffset - (cfg::dat.exIconScale + 2) * images_present + (cfg::dat.exIconScale))) {
                if (flags)
                    *flags |= (CLCHT_ONITEMEXTRAEX | ((i + 1) << 24));
                return hit;
            }
        }
    }
    hdc = GetDC(hwnd);
    if (hitcontact->type == CLCIT_GROUP)
        hFont = reinterpret_cast<HFONT>(SelectObject(hdc, dat->fontInfo[FONTID_GROUPS].hFont));
    else
        hFont = reinterpret_cast<HFONT>(SelectObject(hdc, dat->fontInfo[FONTID_CONTACTS].hFont));
    GetTextExtentPoint32(hdc, hitcontact->szText, lstrlen(hitcontact->szText), &textSize);
    width = textSize.cx;
    if (hitcontact->type == CLCIT_GROUP) {
        char *szCounts;
        szCounts = pcli->pfnGetGroupCountsText(dat, hitcontact);
        if (szCounts[0]) {
            GetTextExtentPoint32A(hdc, " ", 1, &textSize);
            width += textSize.cx;
            SelectObject(hdc, dat->fontInfo[FONTID_GROUPCOUNTS].hFont);
            GetTextExtentPoint32A(hdc, szCounts, lstrlenA(szCounts), &textSize);
            width += textSize.cx;
        }
    }
    SelectObject(hdc, hFont);
    ReleaseDC(hwnd, hdc);
    if (cfg::dat.dwFlags & CLUI_FULLROWSELECT && !(GetKeyState(VK_SHIFT) & 0x8000) && testx > dat->leftMargin + indent * dat->groupIndent + checkboxWidth + dat->iconXSpace + width + 4 + (cfg::dat.dwFlags & CLUI_FRAME_AVATARS ? cfg::dat.avatarSize : 0)) {
        if (flags)
            *flags |= CLCHT_ONITEMSPACE;
        return hit;
    }
    if (testx< dat->leftMargin + indent * dat->groupIndent + checkboxWidth + dat->iconXSpace + width + 4 + (cfg::dat.dwFlags & CLUI_FRAME_AVATARS ? cfg::dat.avatarSize : 0)) {
        if (flags)
            *flags |= CLCHT_ONITEMLABEL;
        return hit;
    }
    if (flags)
        *flags |= CLCHT_NOWHERE;
    return -1;
}