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; }
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; }