static void IsInsidePointA(const HDC DC, int X, int Y, LPCSTR Str, int Count) { SIZE Size; if ((Count > 0) && GetTextExtentPoint32A(DC, Str, Count, &Size)) { DWORD Flags = GetTextAlign(DC); POINT Pt; RECT Rect; if (Flags & TA_UPDATECP) { GetCurrentPositionEx(DC, &Pt); } else { Pt.x = X; Pt.y = Y; } if (Flags & TA_CENTER) { Pt.x-=(Size.cx/2); } else if (Flags & TA_RIGHT) { Pt.x-=Size.cx; } if (Flags & TA_BASELINE) { TEXTMETRIC tm; GetTextMetricsA(DC, &tm); Pt.y-=tm.tmAscent; } else if (Flags & TA_BOTTOM) { Pt.y-=Size.cy; } LPtoDP(DC, &Pt, 1); Rect.left = Pt.x; Rect.right = Pt.x + Size.cx; Rect.top = Pt.y; Rect.bottom = Pt.y + Size.cy; if (((Rect.left <= Rect.right) && (CurParams->Pt.x >= Rect.left) && (CurParams->Pt.x <= Rect.right)) || ((Rect.left > Rect.right) && (CurParams->Pt.x <= Rect.left) && (CurParams->Pt.x >= Rect.right))) { int BegPos; //if (PtInRect(&Rect, CurParams->Pt)) { CurParams->Active = !PtInRect(&Rect, CurParams->Pt); //CurParams->Active = FALSE; BegPos = (int)((abs((CurParams->Pt.x - Rect.left) / (Rect.right - Rect.left)) * (Count - 1)) + 0.5); while ((BegPos < Count - 1) && GetTextExtentPoint32A(DC, Str, BegPos + 1, &Size) && (Size.cx < CurParams->Pt.x - Rect.left)) BegPos++; while ((BegPos >= 0) && GetTextExtentPoint32A(DC, Str, BegPos + 1, &Size) && (Size.cx > CurParams->Pt.x - Rect.left)) BegPos--; if (BegPos < Count - 1) BegPos++; CurParams->BeginPos = BegPos; if (Count > 255) CurParams->WordLen = 255; else CurParams->WordLen = Count; CurParams->Unicode = FALSE; CopyMemory(CurParams->MatchedWordA, Str, CurParams->WordLen); } } }
//----------------------------------------------------------------------------- // Prepares the font by drawing all the characters on the device context. //----------------------------------------------------------------------------- bool Font::PrepareFont( HDC hDC, bool measure ) { SIZE size; char string[2]; // Find the spacing between the characters based on the line height. if( GetTextExtentPoint32A( hDC, string, 1, &size ) == 0 ) return false; m_spacing = (short)ceil( size.cy * 0.1f ); // Set the position to start drawing at. unsigned long x = m_spacing; unsigned long y = 0; // Draw each character on the DC and move to the next position. for( char c = 32; c < 127; c++ ) { string[0] = c; if( GetTextExtentPoint32A( hDC, string, 1, &size ) == 0 ) return false; if( (unsigned long)( x + size.cx + m_spacing ) > m_textureWidth ) { x = m_spacing; y += size.cy + 1; } // Ensure there is enough room to draw the character. if( y + size.cy > m_textureHeight ) return false; // Draw the character if not measuring. if( !measure ) { if( ExtTextOutA( hDC, x + 0, y + 0, ETO_OPAQUE, NULL, string, 1, NULL ) == 0 ) return false; m_textureCoords[c - 32][0] = (float)( x - m_spacing ) / m_textureWidth; m_textureCoords[c - 32][1] = (float)( y ) / m_textureHeight; m_textureCoords[c - 32][2] = (float)( x + size.cx + m_spacing ) / m_textureWidth; m_textureCoords[c - 32][3] = (float)( y + size.cy ) / m_textureHeight; } x += size.cx + ( 2 * m_spacing ); } return true; }
static int create_item(HDC hdc, const SANE_Option_Descriptor *opt, INT id, LPDLGITEMTEMPLATEW *template_out, int y, int *cx, int* count) { LPDLGITEMTEMPLATEW tpl = NULL,rc = NULL; WORD class = 0xffff; DWORD styles = WS_VISIBLE; LPBYTE ptr = NULL; LPDLGITEMTEMPLATEW lead_static = NULL; LPDLGITEMTEMPLATEW trail_edit = NULL; DWORD leading_len = 0; DWORD trail_len = 0; DWORD local_len = 0; LPCSTR title = NULL; CHAR buffer[255]; int padding = 0; int padding2 = 0; int base_x = 0; LONG base; int ctl_cx = 0; SIZE size; GetTextExtentPoint32A(hdc,"X",1,&size); base = GetDialogBaseUnits(); base_x = MulDiv(size.cx,4,LOWORD(base)); if (opt->type == SANE_TYPE_BOOL) { class = 0x0080; /* Button */ styles |= BS_AUTOCHECKBOX; local_len += MultiByteToWideChar(CP_ACP,0,opt->title,-1,NULL,0); local_len *= sizeof(WCHAR); title = opt->title; } else if (opt->type == SANE_TYPE_INT)
//============================================================================================================= bool CStatic::Initialize(HWND parent) { SIZE s; HDC hdc = GetDC(parent); GetTextExtentPoint32A(hdc, Text.c_str(), Text.length(), &s); hwnd = CreateWindowA( "STATIC", Text.c_str(), WS_VISIBLE|WS_CHILD|Align, Location.x, Location.y, s.cx, s.cy, parent, 0, (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL); Size.x = s.cx; Size.y = s.cy; HFONT font = (HFONT)GetStockObject(DEFAULT_GUI_FONT); SendMessage(hwnd, WM_SETFONT, (WPARAM)font, MAKELPARAM(TRUE, 0)); return (hwnd != NULL); }
void LoadCLCFonts(HWND hwnd, ClcData *dat) { RegisterCLUIFonts(); HDC hdc = GetDC(hwnd); HFONT holdfont = (HFONT)GetCurrentObject(hdc, OBJ_FONT); for (int i = 0; i <= FONTID_MODERN_MAX; i++) { if (!dat->fontModernInfo[i].changed && dat->fontModernInfo[i].hFont) { DeleteObject(dat->fontModernInfo[i].hFont); } LOGFONT lf; // Issue 40: Do not reload font colors for embedded clists // Parent window is responsible to re-set fonts colors if needed GetFontSetting(i, &lf, dat->force_in_dialog ? NULL : &dat->fontModernInfo[i].colour, &dat->fontModernInfo[i].effect, &dat->fontModernInfo[i].effectColour1, &dat->fontModernInfo[i].effectColour2); dat->fontModernInfo[i].hFont = CreateFontIndirect(&lf); dat->fontModernInfo[i].changed = 0; SelectObject(hdc, dat->fontModernInfo[i].hFont); SIZE fontSize; GetTextExtentPoint32A(hdc, "x", 1, &fontSize); dat->fontModernInfo[i].fontHeight = fontSize.cy; } SelectObject(hdc, holdfont); ReleaseDC(hwnd, hdc); }
void UpdateHorizontalScrollLen(HWND list, const char* string) { SIZE s= {0}; HDC hdc=GetDC(list); SelectObject(hdc, (HFONT)SendMessageA(list, WM_GETFONT, 0, 0)); GetTextExtentPoint32A(hdc, string, strlen(string), &s); SendMessageA(list, LB_SETHORIZONTALEXTENT, s.cx+5, 0); }
int GetTextWidth(HDC hdc, const std::string& text) { SIZE sz; if (!GetTextExtentPoint32A(hdc, text.c_str(), text.length(), &sz)) ThrowLastError("GetTextExtentPoint32A"); return sz.cx; }
static int create_trailing_edit(HDC hdc, LPDLGITEMTEMPLATEW* template_out, int id, int y, LPCSTR text,BOOL is_int) { LPDLGITEMTEMPLATEW tpl = NULL; INT len; LPBYTE ptr; SIZE size; LONG base; static const char int_base[] = "0000 xxx"; static const char float_base[] = "0000.0000 xxx"; base = GetDialogBaseUnits(); len = MultiByteToWideChar(CP_ACP,0,text,-1,NULL,0); len *= sizeof(WCHAR); len += sizeof(DLGITEMTEMPLATE); len += 3*sizeof(WORD); tpl = HeapAlloc(GetProcessHeap(),0,len); tpl->style=WS_VISIBLE|ES_READONLY|WS_BORDER; tpl->dwExtendedStyle = 0; tpl->x = 1; tpl->y = y; tpl->id = id; if (is_int) GetTextExtentPoint32A(hdc,int_base,lstrlenA(int_base),&size); else GetTextExtentPoint32A(hdc,float_base,lstrlenA(float_base),&size); tpl->cx = MulDiv(size.cx*2,4,LOWORD(base)); tpl->cy = MulDiv(size.cy,8,HIWORD(base)) * 2; ptr = (LPBYTE)tpl + sizeof(DLGITEMTEMPLATE); *(LPWORD)ptr = 0xffff; ptr += sizeof(WORD); *(LPWORD)ptr = 0x0081; ptr += sizeof(WORD); ptr += MultiByteToWideChar(CP_ACP,0,text,-1,(LPWSTR)ptr,len) * sizeof(WCHAR); *(LPWORD)ptr = 0x0000; *template_out = tpl; return len; }
static int string_width(const CHAR *s) { SIZE sz; HDC hdc; hdc = CreateCompatibleDC(NULL); GetTextExtentPoint32A(hdc, s, strlen(s), &sz); DeleteDC(hdc); return sz.cx; }
BOOL GetTextExtentPoint32W_AnyBuild( HDC hdc, LPCWSTR lpString, int cbString, LPSIZE lpSize ) { vector<char> buf; wcstombs_vector(lpString,cbString,&buf); return GetTextExtentPoint32A( hdc, &buf[0], buf.size()-1, lpSize ); }
static int create_leading_static(HDC hdc, LPCSTR text, LPDLGITEMTEMPLATEW* template_out, int y, int id) { LPDLGITEMTEMPLATEW tpl = NULL; INT len; SIZE size; LPBYTE ptr; LONG base; *template_out = NULL; if (!text) return 0; base = GetDialogBaseUnits(); len = MultiByteToWideChar(CP_ACP,0,text,-1,NULL,0); len *= sizeof(WCHAR); len += sizeof(DLGITEMTEMPLATE); len += 3*sizeof(WORD); tpl = HeapAlloc(GetProcessHeap(),0,len); tpl->style=WS_VISIBLE; tpl->dwExtendedStyle = 0; tpl->x = 4; tpl->y = y; tpl->id = ID_BASE; GetTextExtentPoint32A(hdc,text,lstrlenA(text),&size); tpl->cx = MulDiv(size.cx,4,LOWORD(base)); tpl->cy = MulDiv(size.cy,8,HIWORD(base)) * 2; ptr = (LPBYTE)tpl + sizeof(DLGITEMTEMPLATE); *(LPWORD)ptr = 0xffff; ptr += sizeof(WORD); *(LPWORD)ptr = 0x0082; ptr += sizeof(WORD); ptr += MultiByteToWideChar(CP_ACP,0,text,-1,(LPWSTR)ptr,len) * sizeof(WCHAR); *(LPWORD)ptr = 0x0000; *template_out = tpl; return len; }
EXPORT BOOL CALLBACK EdrCenterTextA(HDC hdc, PRECT prc, PCSTR pString) { int iLength; SIZE size; iLength = lstrlenA(pString); GetTextExtentPoint32A(hdc, pString, iLength, &size); return TextOutA(hdc, (prc->right - prc->left - size.cx) / 2, (prc->bottom - prc->top - size.cy) / 2, pString, iLength); }
void EditControl::ExpandToText() { HDC hDC = GetDC(getHandle()); char* text; if ( hDC != NULL && GetEditText(text) ) { SIZE strSize = { }; RECT textRect = { }; if ( GetTextExtentPoint32A(hDC, text, GetTextLength(), &strSize) == TRUE && GetClientRect(getHandle(), &textRect) == TRUE && strSize.cx > (textRect.right-textRect.left) ) { textRect.right = textRect.left + strSize.cx; if ( AdjustWindowRect(&textRect, GetWindowStyle(getHandle()), FALSE) != 0 ) SetWidth(textRect.right-textRect.left); } delete[] text; ReleaseDC(hDC); } }
bool StringGuideWindow::CreateThis(HWND hParent) { if ( ClassWindow::RegisterWindowClass(0, NULL, NULL, CreateSolidBrush(RGB(0, 0, 0)), NULL, "StringGuide", NULL, false) && ClassWindow::CreateClassWindow(0, NULL, WS_OVERLAPPED|WS_CHILD|WS_VISIBLE, 463, 7, 125, 365, hParent, NULL) ) { HWND hStringGuide = getHandle(); HDC hDC = GetDC(hStringGuide); SelectObject(hDC, defaultFont); SIZE strSize = { }; for (size_t i = 0; i < strColors.size(); i++) { auto Color = strColors.at(i); GetTextExtentPoint32A(hDC, std::get<2>(Color).c_str(), std::get<2>(Color).length(), &strSize); colorPrefix[i].CreateThis(hStringGuide, 2, i*13, strSize.cx, 13, std::get<2>(Color).c_str(), 0); color[i].CreateThis(hStringGuide, strSize.cx+3, i*13, 100, 13, std::get<1>(Color).c_str(), TEXT_COLOR_FIRST+i); } ReleaseDC(hDC); return true; } else return false; }
static BOOL IntDrawState(HDC hdc, HBRUSH hbr, DRAWSTATEPROC func, LPARAM lp, WPARAM wp, INT x, INT y, INT cx, INT cy, UINT flags, BOOL unicode) { HBITMAP hbm, hbmsave; HFONT hfsave; HBRUSH hbsave, hbrtmp = 0; HDC memdc; RECT rc; UINT dtflags = DT_NOCLIP; COLORREF fg, bg; UINT opcode = flags & 0xf; INT len = wp; BOOL retval, tmp; if((opcode == DST_TEXT || opcode == DST_PREFIXTEXT) && !len) /* The string is '\0' terminated */ { if(unicode) len = lstrlenW((LPWSTR)lp); else len = lstrlenA((LPSTR)lp); } /* Find out what size the image has if not given by caller */ if(!cx || !cy) { SIZE s; BITMAP bm; switch(opcode) { case DST_TEXT: case DST_PREFIXTEXT: if(unicode) retval = GetTextExtentPoint32W(hdc, (LPWSTR)lp, len, &s); else retval = GetTextExtentPoint32A(hdc, (LPSTR)lp, len, &s); if(!retval) return FALSE; break; case DST_ICON: if(!get_icon_size((HICON)lp, &s)) return FALSE; break; case DST_BITMAP: if(!GetObjectW((HBITMAP)lp, sizeof(bm), &bm)) return FALSE; s.cx = bm.bmWidth; s.cy = bm.bmHeight; break; case DST_COMPLEX: /* cx and cy must be set in this mode */ return FALSE; default: ERR("Invalid opcode: %u\n", opcode); return FALSE; } if(!cx) cx = s.cx; if(!cy) cy = s.cy; } rc.left = x; rc.top = y; rc.right = x + cx; rc.bottom = y + cy; if(flags & DSS_RIGHT) /* This one is not documented in the win32.hlp file */ dtflags |= DT_RIGHT; if(opcode == DST_TEXT) dtflags |= DT_NOPREFIX; else if(opcode == DST_PREFIXTEXT) { if (flags & DSS_HIDEPREFIX) dtflags |= DT_HIDEPREFIX; if (flags & DSS_PREFIXONLY) dtflags |= DT_PREFIXONLY; } /* For DSS_NORMAL we just jam in the image and return */ if((flags & 0x79f0) == DSS_NORMAL) { return PAINTING_DrawStateJam(hdc, opcode, func, lp, len, &rc, dtflags, unicode); } /* For all other states we need to convert the image to B/W in a local bitmap */ /* before it is displayed */ fg = SetTextColor(hdc, RGB(0, 0, 0)); bg = SetBkColor(hdc, RGB(255, 255, 255)); hbm = NULL; hbmsave = NULL; memdc = NULL; hbsave = NULL; retval = FALSE; /* assume failure */ /* From here on we must use "goto cleanup" when something goes wrong */ hbm = CreateBitmap(cx, cy, 1, 1, NULL); if(!hbm) goto cleanup; memdc = CreateCompatibleDC(hdc); if(!memdc) goto cleanup; hbmsave = (HBITMAP)SelectObject(memdc, hbm); if(!hbmsave) goto cleanup; rc.left = rc.top = 0; rc.right = cx; rc.bottom = cy; if(!FillRect(memdc, &rc, (HBRUSH)GetStockObject(WHITE_BRUSH))) goto cleanup; SetBkColor(memdc, RGB(255, 255, 255)); SetTextColor(memdc, RGB(0, 0, 0)); hfsave = (HFONT)SelectObject(memdc, GetCurrentObject(hdc, OBJ_FONT)); /* DST_COMPLEX may draw text as well, * so we must be sure that correct font is selected */ if(!hfsave && (opcode <= DST_PREFIXTEXT)) goto cleanup; tmp = PAINTING_DrawStateJam(memdc, opcode, func, lp, len, &rc, dtflags, unicode); if(hfsave) SelectObject(memdc, hfsave); if(!tmp) goto cleanup; /* This state cause the image to be dithered */ if(flags & DSS_UNION) { hbsave = (HBRUSH)SelectObject(memdc, gpsi->hbrGray); if(!hbsave) goto cleanup; tmp = PatBlt(memdc, 0, 0, cx, cy, 0x00FA0089); SelectObject(memdc, hbsave); if(!tmp) goto cleanup; } if (flags & DSS_DISABLED) hbrtmp = GetSysColorBrush(COLOR_3DHILIGHT); else if (flags & DSS_DEFAULT) hbrtmp = GetSysColorBrush(COLOR_3DSHADOW); /* Draw light or dark shadow */ if (flags & (DSS_DISABLED|DSS_DEFAULT)) { if(!hbrtmp) goto cleanup; hbsave = (HBRUSH)SelectObject(hdc, hbrtmp); if(!hbsave) goto cleanup; if(!BitBlt(hdc, x+1, y+1, cx, cy, memdc, 0, 0, 0x00B8074A)) goto cleanup; SelectObject(hdc, hbsave); } if (flags & DSS_DISABLED) { hbr = hbrtmp = GetSysColorBrush(COLOR_3DSHADOW); if(!hbrtmp) goto cleanup; } else if (!hbr) { hbr = (HBRUSH)GetStockObject(BLACK_BRUSH); } hbsave = (HBRUSH)SelectObject(hdc, hbr); if(!BitBlt(hdc, x, y, cx, cy, memdc, 0, 0, 0x00B8074A)) goto cleanup; retval = TRUE; /* We succeeded */ cleanup: SetTextColor(hdc, fg); SetBkColor(hdc, bg); if(hbsave) SelectObject(hdc, hbsave); if(hbmsave) SelectObject(memdc, hbmsave); if(hbm) DeleteObject(hbm); if(memdc) DeleteDC(memdc); return retval; }
BOOL WINAPI IntGrayString( HDC hDC, HBRUSH hBrush, GRAYSTRINGPROC lpOutputFunc, LPARAM lpData, int nCount, int X, int Y, int nWidth, int nHeight, BOOL unicode) { // AG: Mostly implemented, but probably won't work properly or return // correct error codes. I doubt it grays strings either... Untested! BOOL success = FALSE; HBRUSH hbsave; HDC MemDC = NULL; HBITMAP MemBMP = NULL, OldBMP = NULL; HBRUSH OldBrush = NULL; HFONT OldFont = NULL; RECT r; COLORREF ForeColor, BackColor; ForeColor = SetTextColor(hDC, RGB(0, 0, 0)); BackColor = SetBkColor(hDC, RGB(255, 255, 255)); if (! hBrush) { // The documentation is a little vague on what exactly should happen // here. Something about using the same brush for window text??? hBrush = (HBRUSH) GetCurrentObject(hDC, OBJ_BRUSH); } if ((nCount == -1) && (! lpOutputFunc)) return FALSE; if (! nCount) { // TODO: calculate the length (easy enough) if (unicode) nCount = lstrlenW((WCHAR*)lpData); else nCount = lstrlenA((CHAR*)lpData); } if (! nWidth || ! nHeight) { SIZE s; // TODO: calculate the rect if (unicode) success = GetTextExtentPoint32W(hDC, (WCHAR*) lpData, nCount, &s); else success = GetTextExtentPoint32A(hDC, (CHAR*) lpData, nCount, &s); if (! success) goto cleanup; if (! nWidth) nWidth = s.cx; if (! nHeight) nHeight = s.cy; } SetRect(&r, X, Y, X + nWidth, Y + nHeight); MemDC = CreateCompatibleDC(hDC); if (! MemDC) goto cleanup; MemBMP = CreateBitmap(nWidth, nHeight, 1, 1, NULL); if (! MemBMP) goto cleanup; OldBMP = SelectObject(MemDC, MemBMP); if (! OldBMP) goto cleanup; OldFont = SelectObject(MemDC, GetCurrentObject(hDC, OBJ_FONT)); if (! OldFont) goto cleanup; OldBrush = SelectObject(MemDC, hBrush); if (! OldBrush) goto cleanup; if (! BitBlt(MemDC, 0, 0, nWidth, nHeight, hDC, X, Y, SRCCOPY)) goto cleanup; SetTextColor(MemDC, RGB(255, 255, 255)); SetBkColor(MemDC, RGB(0, 0, 0)); if (lpOutputFunc) { success = lpOutputFunc(MemDC, lpData, nCount); // Set brush etc first? if ((nCount == -1) && (! success)) { // Don't gray (documented behaviour) success = (BOOL) BitBlt(hDC, X, Y, nWidth, nHeight, MemDC, 0, 0, SRCCOPY); goto cleanup; } } else { if (unicode) success = TextOutW(MemDC, 0, 0, (WCHAR*) lpData, nCount); else success = TextOutA(MemDC, 0, 0, (CHAR*) lpData, nCount); if (! success) goto cleanup; hbsave = (HBRUSH)SelectObject(MemDC, gpsi->hbrGray); PatBlt(MemDC, 0, 0, nWidth, nHeight, 0x000A0329); SelectObject(MemDC, hbsave); } if (! BitBlt(hDC, X, Y, nWidth, nHeight, MemDC, 0, 0, SRCCOPY)) goto cleanup; cleanup: SetTextColor(hDC, ForeColor); SetBkColor(hDC, BackColor); if (MemDC) { if (OldFont) SelectObject(MemDC, OldFont); if (OldBrush) SelectObject(MemDC, OldBrush); if (OldBMP) SelectObject(MemDC, OldBMP); if (MemBMP) DeleteObject(MemBMP); DeleteDC(MemDC); } return success; }
int HitTest(HWND hwnd,struct ClcData *dat,int testx,int testy,struct ClcContact **contact,ClcGroup **group,DWORD *flags) { struct ClcContact *hitcontact; ClcGroup *hitgroup; int hit,indent,width,i,cxSmIcon; int checkboxWidth, subident,ic = 0; SIZE textSize; HDC hdc; HFONT oldfont; RECT clRect; DWORD style = GetWindowLongPtr(hwnd,GWL_STYLE); 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 = GetRowByIndex(dat ,(testy+dat->yScroll)/dat->rowHeight,&hitcontact,&hitgroup); if (hit == -1) { if (flags) *flags |= CLCHT_NOWHERE|CLCHT_BELOWITEMS; return -1; } if (contact) *contact = hitcontact; if (group) *group = hitgroup; ///////// if (hitcontact->type == CLCIT_CONTACT && hitcontact->isSubcontact) subident = dat->rowHeight/2; else subident = 0; for (indent = 0;hitgroup->parent;indent++,hitgroup = hitgroup->parent); if (testx<dat->leftMargin+indent*dat->groupIndent+subident) { 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+subident) { if (flags) *flags |= CLCHT_ONITEMCHECK; return hit; } if (testx<dat->leftMargin+indent*dat->groupIndent+checkboxWidth+dat->iconXSpace+subident) { if (flags) *flags |= CLCHT_ONITEMICON; return hit; } hdc = GetDC(hwnd); GetTextExtentPoint32(hdc,hitcontact->szText,lstrlen(hitcontact->szText),&textSize); width = textSize.cx; cxSmIcon = GetSystemMetrics(SM_CXSMICON); for (i=0; i < dat->extraColumnsCount; i++) { int x; if (hitcontact->iExtraImage[i] == EMPTY_EXTRA_ICON) continue; if ((style & CLS_EX_MULTICOLUMNALIGNLEFT)) { x = (dat->leftMargin+indent*dat->groupIndent+checkboxWidth+dat->iconXSpace-2+width); x += 16; x = x+dat->extraColumnSpacing*(ic); if (i == dat->extraColumnsCount-1) {x = clRect.right-18;} } else { int ir; if (dat->MetaIgnoreEmptyExtra) { ir = 0; for (int j = i;j<dat->extraColumnsCount;j++) if (hitcontact->iExtraImage[j] != EMPTY_EXTRA_ICON) ir++; } else ir = dat->extraColumnsCount-i; x = clRect.right-dat->extraColumnSpacing*ir; } ic++; if (testx >= x && testx < x + cxSmIcon) { if (flags) *flags |= CLCHT_ONITEMEXTRA|(i<<24); ReleaseDC(hwnd,hdc); return hit; } } if (hitcontact->type == CLCIT_GROUP) oldfont = (HFONT)SelectObject(hdc,dat->fontInfo[FONTID_GROUPS].hFont); else oldfont = (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 = 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,oldfont); ReleaseDC(hwnd,hdc); if (testx<dat->leftMargin+indent*dat->groupIndent+checkboxWidth+dat->iconXSpace+width+4+subident) { if (flags) *flags |= CLCHT_ONITEMLABEL; return hit; } if (flags) *flags |= CLCHT_NOWHERE; return -1; }
void PaintClc(HWND hwnd, struct ClcData *dat, HDC hdc, RECT * rcPaint) { HDC hdcMem; RECT clRect; int i, y, indent, index, fontHeight; struct ClcGroup *group; HBITMAP hBmpOsb, hOldBitmap; HFONT hOldFont; DWORD style = GetWindowLong(hwnd, GWL_STYLE); int status = GetGeneralisedStatus(); int grey = 0, groupCountsFontTopShift; HBRUSH hBrushAlternateGrey = NULL; // yes I know about GetSysColorBrush() COLORREF tmpbkcolour = style & CLS_CONTACTLIST ? (dat->useWindowsColours ? GetSysColor(COLOR_3DFACE) : dat->bkColour) : dat->bkColour; int minHeight = 16; for (i = 0; i < FONTID_LAST; i++) { if (minHeight < dat->fontInfo[i].fontHeight) { minHeight = dat->fontInfo[i].fontHeight; } } if (dat->rowHeight < minHeight) { dat->rowHeight = minHeight; } if (dat->greyoutFlags & pcli->pfnClcStatusToPf2(status) || style & WS_DISABLED) grey = 1; else if (GetFocus() != hwnd && dat->greyoutFlags & GREYF_UNFOCUS) grey = 1; GetClientRect(hwnd, &clRect); if (rcPaint == NULL) rcPaint = &clRect; if (IsRectEmpty(rcPaint)) return; y = -dat->yScroll; hdcMem = CreateCompatibleDC(hdc); hBmpOsb = CreateBitmap(clRect.right, clRect.bottom, 1, GetDeviceCaps(hdc, BITSPIXEL), NULL); hOldBitmap = SelectObject(hdcMem, hBmpOsb); { TEXTMETRIC tm; hOldFont = SelectObject(hdcMem, dat->fontInfo[FONTID_GROUPS].hFont); GetTextMetrics(hdcMem, &tm); groupCountsFontTopShift = tm.tmAscent; SelectObject(hdcMem, dat->fontInfo[FONTID_GROUPCOUNTS].hFont); GetTextMetrics(hdcMem, &tm); groupCountsFontTopShift -= tm.tmAscent; } if (style & CLS_GREYALTERNATE) hBrushAlternateGrey = CreateSolidBrush(GetNearestColor(hdcMem, RGB(GetRValue(tmpbkcolour) - 10, GetGValue(tmpbkcolour) - 10, GetBValue(tmpbkcolour) - 10))); ChangeToFont(hdcMem, dat, FONTID_CONTACTS, &fontHeight); SetBkMode(hdcMem, TRANSPARENT); { HBRUSH hBrush; hBrush = CreateSolidBrush(tmpbkcolour); FillRect(hdcMem, rcPaint, hBrush); DeleteObject(hBrush); if (dat->hBmpBackground) { BITMAP bmp; HDC hdcBmp; int x, y; int maxx, maxy; int destw, desth; // XXX: Halftone isnt supported on 9x, however the scretch problems dont happen on 98. SetStretchBltMode(hdcMem, HALFTONE); GetObject(dat->hBmpBackground, sizeof(bmp), &bmp); hdcBmp = CreateCompatibleDC(hdcMem); SelectObject(hdcBmp, dat->hBmpBackground); y = dat->backgroundBmpUse & CLBF_SCROLL ? -dat->yScroll : 0; maxx = dat->backgroundBmpUse & CLBF_TILEH ? clRect.right : 1; maxy = dat->backgroundBmpUse & CLBF_TILEV ? maxy = rcPaint->bottom : y + 1; switch (dat->backgroundBmpUse & CLBM_TYPE) { case CLB_STRETCH: if (dat->backgroundBmpUse & CLBF_PROPORTIONAL) { if (clRect.right * bmp.bmHeight < clRect.bottom * bmp.bmWidth) { desth = clRect.bottom; destw = desth * bmp.bmWidth / bmp.bmHeight; } else { destw = clRect.right; desth = destw * bmp.bmHeight / bmp.bmWidth; } } else { destw = clRect.right; desth = clRect.bottom; } break; case CLB_STRETCHH: if (dat->backgroundBmpUse & CLBF_PROPORTIONAL) { destw = clRect.right; desth = destw * bmp.bmHeight / bmp.bmWidth; } else { destw = clRect.right; desth = bmp.bmHeight; } break; case CLB_STRETCHV: if (dat->backgroundBmpUse & CLBF_PROPORTIONAL) { desth = clRect.bottom; destw = desth * bmp.bmWidth / bmp.bmHeight; } else { destw = bmp.bmWidth; desth = clRect.bottom; } break; default: //clb_topleft destw = bmp.bmWidth; desth = bmp.bmHeight; break; } for (; y < maxy; y += desth) { if (y < rcPaint->top - desth) continue; for (x = 0; x < maxx; x += destw) StretchBlt(hdcMem, x, y, destw, desth, hdcBmp, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY); } DeleteDC(hdcBmp); } } group = &dat->list; group->scanIndex = 0; indent = 0; for (index = 0; y < rcPaint->bottom;) { if (group->scanIndex == group->cl.count) { group = group->parent; indent--; if (group == NULL) break; group->scanIndex++; continue; } if (y > rcPaint->top - dat->rowHeight) { int iImage = -1; int selected = index == dat->selection && (dat->showSelAlways || dat->exStyle & CLS_EX_SHOWSELALWAYS || GetFocus() == hwnd) && group->cl.items[group->scanIndex]->type != CLCIT_DIVIDER; int hottrack = dat->exStyle & CLS_EX_TRACKSELECT && group->cl.items[group->scanIndex]->type != CLCIT_DIVIDER && dat->iHotTrack == index; SIZE textSize, countsSize, spaceSize; int width, checkboxWidth; char *szCounts; //alternating grey if (style & CLS_GREYALTERNATE && index & 1) { RECT rc; rc.top = y; rc.bottom = rc.top + dat->rowHeight; rc.left = 0; rc.right = clRect.right; FillRect(hdcMem, &rc, hBrushAlternateGrey); } //setup if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP) ChangeToFont(hdcMem, dat, FONTID_GROUPS, &fontHeight); else if (group->cl.items[group->scanIndex]->type == CLCIT_INFO) { if (group->cl.items[group->scanIndex]->flags & CLCIIF_GROUPFONT) ChangeToFont(hdcMem, dat, FONTID_GROUPS, &fontHeight); else ChangeToFont(hdcMem, dat, FONTID_CONTACTS, &fontHeight); } else if (group->cl.items[group->scanIndex]->type == CLCIT_DIVIDER) ChangeToFont(hdcMem, dat, FONTID_DIVIDERS, &fontHeight); else if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT && group->cl.items[group->scanIndex]->flags & CONTACTF_NOTONLIST) ChangeToFont(hdcMem, dat, FONTID_NOTONLIST, &fontHeight); else if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT && ((group->cl.items[group->scanIndex]->flags & CONTACTF_INVISTO && GetRealStatus(group->cl.items[group->scanIndex], status) != ID_STATUS_INVISIBLE) || (group->cl.items[group->scanIndex]->flags & CONTACTF_VISTO && GetRealStatus(group->cl.items[group->scanIndex], status) == ID_STATUS_INVISIBLE) ) ) { // the contact is in the always visible list and the proto is invisible // the contact is in the always invisible and the proto is in any other mode ChangeToFont(hdcMem, dat, group->cl.items[group->scanIndex]->flags & CONTACTF_ONLINE ? FONTID_INVIS : FONTID_OFFINVIS, &fontHeight); } else if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT && !(group->cl.items[group->scanIndex]->flags & CONTACTF_ONLINE)) ChangeToFont(hdcMem, dat, FONTID_OFFLINE, &fontHeight); else ChangeToFont(hdcMem, dat, FONTID_CONTACTS, &fontHeight); GetTextExtentPoint32(hdcMem, group->cl.items[group->scanIndex]->szText, lstrlen(group->cl.items[group->scanIndex]->szText), &textSize); width = textSize.cx; if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP) { szCounts = pcli->pfnGetGroupCountsText(dat, group->cl.items[group->scanIndex]); if (szCounts[0]) { GetTextExtentPoint32A(hdcMem, " ", 1, &spaceSize); ChangeToFont(hdcMem, dat, FONTID_GROUPCOUNTS, &fontHeight); GetTextExtentPoint32A(hdcMem, szCounts, lstrlenA(szCounts), &countsSize); width += spaceSize.cx + countsSize.cx; } } if ((style & CLS_CHECKBOXES && group->cl.items[group->scanIndex]->type == CLCIT_CONTACT) || (style & CLS_GROUPCHECKBOXES && group->cl.items[group->scanIndex]->type == CLCIT_GROUP) || (group->cl.items[group->scanIndex]->type == CLCIT_INFO && group->cl.items[group->scanIndex]->flags & CLCIIF_CHECKBOX)) checkboxWidth = dat->checkboxSize + 2; else checkboxWidth = 0; //background if (selected) { int x = dat->leftMargin + indent * dat->groupIndent + checkboxWidth + dat->iconXSpace - 2; ImageList_DrawEx(dat->himlHighlight, 0, hdcMem, x, y, min(width + 5, clRect.right - x), dat->rowHeight, CLR_NONE, CLR_NONE, dat->exStyle & CLS_EX_NOTRANSLUCENTSEL ? ILD_NORMAL : ILD_BLEND25); SetTextColor(hdcMem, dat->selTextColour); } else if (hottrack) SetHotTrackColour(hdcMem, dat); //checkboxes if (checkboxWidth) { RECT rc; HANDLE hTheme = NULL; // THEME if (IsWinVerXPPlus()) { if (!themeAPIHandle) { themeAPIHandle = GetModuleHandleA("uxtheme"); if (themeAPIHandle) { MyOpenThemeData = (HANDLE(WINAPI *) (HWND, LPCWSTR)) MGPROC("OpenThemeData"); MyCloseThemeData = (HRESULT(WINAPI *) (HANDLE)) MGPROC("CloseThemeData"); MyDrawThemeBackground = (HRESULT(WINAPI *) (HANDLE, HDC, int, int, const RECT *, const RECT *)) MGPROC("DrawThemeBackground"); } } // Make sure all of these methods are valid (i would hope either all or none work) if (MyOpenThemeData && MyCloseThemeData && MyDrawThemeBackground) { hTheme = MyOpenThemeData(hwnd, L"BUTTON"); } } rc.left = dat->leftMargin + indent * dat->groupIndent; rc.right = rc.left + dat->checkboxSize; rc.top = y + ((dat->rowHeight - dat->checkboxSize) >> 1); rc.bottom = rc.top + dat->checkboxSize; if (hTheme) { MyDrawThemeBackground(hTheme, hdcMem, BP_CHECKBOX, group->cl.items[group->scanIndex]->flags & CONTACTF_CHECKED ? (hottrack ? CBS_CHECKEDHOT : CBS_CHECKEDNORMAL) : (hottrack ? CBS_UNCHECKEDHOT : CBS_UNCHECKEDNORMAL), &rc, &rc); } else DrawFrameControl(hdcMem, &rc, DFC_BUTTON, DFCS_BUTTONCHECK | DFCS_FLAT | (group->cl.items[group->scanIndex]->flags & CONTACTF_CHECKED ? DFCS_CHECKED : 0) | (hottrack ? DFCS_HOT : 0)); if (hTheme && MyCloseThemeData) { MyCloseThemeData(hTheme); hTheme = NULL; } } //icon if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP) iImage = group->cl.items[group->scanIndex]->group->expanded ? IMAGE_GROUPOPEN : IMAGE_GROUPSHUT; else if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT) iImage = group->cl.items[group->scanIndex]->iImage; if (iImage != -1) { /*COLORREF colourFg=dat->selBkColour; int mode=ILD_NORMAL; if(selected) mode=ILD_SELECTED; else if(hottrack) {mode=ILD_FOCUS; colourFg=dat->hotTextColour;} else if(group->cl.items[group->scanIndex]->type==CLCIT_CONTACT && group->cl.items[group->scanIndex]->flags&CONTACTF_NOTONLIST) {colourFg=dat->fontInfo[FONTID_NOTONLIST].colour; mode=ILD_BLEND50;} ImageList_DrawEx(himlCListClc,iImage,hdcMem,dat->leftMargin+indent*dat->groupIndent+checkboxWidth,y+((dat->rowHeight-16)>>1),0,0,CLR_NONE,colourFg,mode); */ // this doesnt use CLS_CONTACTLIST since the colour prolly wont match anyway COLORREF colourFg = dat->selBkColour; int mode = ILD_NORMAL; if (hottrack) { colourFg = dat->hotTextColour; } else if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT && group->cl.items[group->scanIndex]->flags & CONTACTF_NOTONLIST) { colourFg = dat->fontInfo[FONTID_NOTONLIST].colour; mode = ILD_BLEND50; } if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT && dat->showIdle && (group->cl.items[group->scanIndex]->flags & CONTACTF_IDLE) && GetRealStatus(group->cl.items[group->scanIndex], ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE) mode = ILD_SELECTED; ImageList_DrawEx(himlCListClc, iImage, hdcMem, dat->leftMargin + indent * dat->groupIndent + checkboxWidth, y + ((dat->rowHeight - 16) >> 1), 0, 0, CLR_NONE, colourFg, mode); } //text if (group->cl.items[group->scanIndex]->type == CLCIT_DIVIDER) { RECT rc; rc.top = y + (dat->rowHeight >> 1); rc.bottom = rc.top + 2; rc.left = dat->leftMargin + indent * dat->groupIndent; rc.right = rc.left + ((clRect.right - rc.left - textSize.cx) >> 1) - 3; DrawEdge(hdcMem, &rc, BDR_SUNKENOUTER, BF_RECT); TextOut(hdcMem, rc.right + 3, y + ((dat->rowHeight - fontHeight) >> 1), group->cl.items[group->scanIndex]->szText, lstrlen(group->cl.items[group->scanIndex]->szText)); rc.left = rc.right + 6 + textSize.cx; rc.right = clRect.right; DrawEdge(hdcMem, &rc, BDR_SUNKENOUTER, BF_RECT); }
static BOOL CALLBACK DlgProcLogOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { static HBRUSH hBkgColourBrush; switch (msg) { case WM_INITDIALOG: TranslateDialogDefault(hwndDlg); switch (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_LOADHISTORY, SRMSGDEFSET_LOADHISTORY)) { case LOADHISTORY_UNREAD: CheckDlgButton(hwndDlg, IDC_LOADUNREAD, BST_CHECKED); break; case LOADHISTORY_COUNT: CheckDlgButton(hwndDlg, IDC_LOADCOUNT, BST_CHECKED); EnableWindow(GetDlgItem(hwndDlg, IDC_LOADCOUNTN), TRUE); EnableWindow(GetDlgItem(hwndDlg, IDC_LOADCOUNTSPIN), TRUE); break; case LOADHISTORY_TIME: CheckDlgButton(hwndDlg, IDC_LOADTIME, BST_CHECKED); EnableWindow(GetDlgItem(hwndDlg, IDC_LOADTIMEN), TRUE); EnableWindow(GetDlgItem(hwndDlg, IDC_LOADTIMESPIN), TRUE); EnableWindow(GetDlgItem(hwndDlg, IDC_STMINSOLD), TRUE); break; } SendDlgItemMessage(hwndDlg, IDC_LOADCOUNTSPIN, UDM_SETRANGE, 0, MAKELONG(100, 0)); SendDlgItemMessage(hwndDlg, IDC_LOADCOUNTSPIN, UDM_SETPOS, 0, DBGetContactSettingWord(NULL, SRMMMOD, SRMSGSET_LOADCOUNT, SRMSGDEFSET_LOADCOUNT)); SendDlgItemMessage(hwndDlg, IDC_LOADTIMESPIN, UDM_SETRANGE, 0, MAKELONG(12 * 60, 0)); SendDlgItemMessage(hwndDlg, IDC_LOADTIMESPIN, UDM_SETPOS, 0, DBGetContactSettingWord(NULL, SRMMMOD, SRMSGSET_LOADTIME, SRMSGDEFSET_LOADTIME)); CheckDlgButton(hwndDlg, IDC_SHOWLOGICONS, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWLOGICONS, SRMSGDEFSET_SHOWLOGICONS)); CheckDlgButton(hwndDlg, IDC_SHOWNAMES, !DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_HIDENAMES, SRMSGDEFSET_HIDENAMES)); CheckDlgButton(hwndDlg, IDC_SHOWTIMES, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTIME, SRMSGDEFSET_SHOWTIME)); CheckDlgButton(hwndDlg, IDC_SHOWSECONDS, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWSECONDS, SRMSGDEFSET_SHOWSECONDS)); EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWSECONDS), IsDlgButtonChecked(hwndDlg, IDC_SHOWTIMES)); EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWDATES), IsDlgButtonChecked(hwndDlg, IDC_SHOWTIMES)); CheckDlgButton(hwndDlg, IDC_SHOWDATES, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWDATE, SRMSGDEFSET_SHOWDATE)); CheckDlgButton(hwndDlg, IDC_USELONGDATE, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_USELONGDATE, SRMSGDEFSET_USELONGDATE)); CheckDlgButton(hwndDlg, IDC_USERELATIVEDATE, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_USERELATIVEDATE, SRMSGDEFSET_USERELATIVEDATE)); EnableWindow(GetDlgItem(hwndDlg, IDC_USELONGDATE), IsDlgButtonChecked(hwndDlg, IDC_SHOWDATES) && IsDlgButtonChecked(hwndDlg, IDC_SHOWTIMES)); EnableWindow(GetDlgItem(hwndDlg, IDC_USERELATIVEDATE), IsDlgButtonChecked(hwndDlg, IDC_SHOWDATES) && IsDlgButtonChecked(hwndDlg, IDC_SHOWTIMES)); // if (!ServiceExists(MS_IEVIEW_WINDOW)) { // EnableWindow(GetDlgItem(hwndDlg, IDC_USEIEVIEW), FALSE); // } // CheckDlgButton(hwndDlg, IDC_USEIEVIEW, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_USEIEVIEW, SRMSGDEFSET_USEIEVIEW)); CheckDlgButton(hwndDlg, IDC_GROUPMESSAGES, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_GROUPMESSAGES, SRMSGDEFSET_GROUPMESSAGES)); CheckDlgButton(hwndDlg, IDC_MARKFOLLOWUPS, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_MARKFOLLOWUPS, SRMSGDEFSET_MARKFOLLOWUPS)); CheckDlgButton(hwndDlg, IDC_MESSAGEONNEWLINE, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_MESSAGEONNEWLINE, SRMSGDEFSET_MESSAGEONNEWLINE)); CheckDlgButton(hwndDlg, IDC_DRAWLINES, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_DRAWLINES, SRMSGDEFSET_DRAWLINES)); EnableWindow(GetDlgItem(hwndDlg, IDC_LINECOLOUR), IsDlgButtonChecked(hwndDlg, IDC_DRAWLINES)); EnableWindow(GetDlgItem(hwndDlg, IDC_MARKFOLLOWUPS), IsDlgButtonChecked(hwndDlg, IDC_GROUPMESSAGES)); CheckDlgButton(hwndDlg, IDC_SHOWSTATUSCHANGES, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWSTATUSCH, SRMSGDEFSET_SHOWSTATUSCH)); SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_SETCOLOUR, 0, DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_BKGCOLOUR, SRMSGDEFSET_BKGCOLOUR)); SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_SETDEFAULTCOLOUR, 0, SRMSGDEFSET_BKGCOLOUR); SendDlgItemMessage(hwndDlg, IDC_BKGINPUT, CPM_SETCOLOUR, 0, DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_INPUTBKGCOLOUR, SRMSGDEFSET_INPUTBKGCOLOUR)); SendDlgItemMessage(hwndDlg, IDC_BKGINPUT, CPM_SETDEFAULTCOLOUR, 0, SRMSGDEFSET_INPUTBKGCOLOUR); SendDlgItemMessage(hwndDlg, IDC_BKGINCOMING, CPM_SETCOLOUR, 0, DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_INCOMINGBKGCOLOUR, SRMSGDEFSET_INCOMINGBKGCOLOUR)); SendDlgItemMessage(hwndDlg, IDC_BKGINCOMING, CPM_SETDEFAULTCOLOUR, 0, SRMSGDEFSET_INCOMINGBKGCOLOUR); SendDlgItemMessage(hwndDlg, IDC_BKGOUTGOING, CPM_SETCOLOUR, 0, DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_OUTGOINGBKGCOLOUR, SRMSGDEFSET_OUTGOINGBKGCOLOUR)); SendDlgItemMessage(hwndDlg, IDC_BKGOUTGOING, CPM_SETDEFAULTCOLOUR, 0, SRMSGDEFSET_OUTGOINGBKGCOLOUR); SendDlgItemMessage(hwndDlg, IDC_LINECOLOUR, CPM_SETCOLOUR, 0, DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_LINECOLOUR, SRMSGDEFSET_LINECOLOUR)); hBkgColourBrush = CreateSolidBrush(SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_GETCOLOUR, 0, 0)); { int i; LOGFONTA lf; for (i = 0; i < sizeof(fontOptionsList) / sizeof(fontOptionsList[0]); i++) { LoadMsgDlgFont(i, &lf, &fontOptionsList[i].colour); lstrcpyA(fontOptionsList[i].szFace, lf.lfFaceName); fontOptionsList[i].size = (char) lf.lfHeight; fontOptionsList[i].style = (lf.lfWeight >= FW_BOLD ? FONTF_BOLD : 0) | (lf.lfItalic ? FONTF_ITALIC : 0); fontOptionsList[i].charset = lf.lfCharSet; //I *think* some OSs will fail LB_ADDSTRING if lParam==0 SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_ADDSTRING, 0, i + 1); } SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_SETSEL, TRUE, 0); SendDlgItemMessage(hwndDlg, IDC_FONTCOLOUR, CPM_SETCOLOUR, 0, fontOptionsList[0].colour); SendDlgItemMessage(hwndDlg, IDC_FONTCOLOUR, CPM_SETDEFAULTCOLOUR, 0, fontOptionsList[0].defColour); } return TRUE; case WM_CTLCOLORLISTBOX: SetBkColor((HDC) wParam, SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_GETCOLOUR, 0, 0)); return (BOOL) hBkgColourBrush; case WM_MEASUREITEM: { MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *) lParam; HFONT hFont, hoFont; HDC hdc; SIZE fontSize; int iItem = mis->itemData - 1; hFont = CreateFontA(fontOptionsList[iItem].size, 0, 0, 0, fontOptionsList[iItem].style & FONTF_BOLD ? FW_BOLD : FW_NORMAL, fontOptionsList[iItem].style & FONTF_ITALIC ? 1 : 0, 0, 0, fontOptionsList[iItem].charset, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, fontOptionsList[iItem].szFace); hdc = GetDC(GetDlgItem(hwndDlg, mis->CtlID)); hoFont = (HFONT) SelectObject(hdc, hFont); GetTextExtentPoint32A(hdc, fontOptionsList[iItem].szDescr, lstrlenA(fontOptionsList[iItem].szDescr), &fontSize); SelectObject(hdc, hoFont); ReleaseDC(GetDlgItem(hwndDlg, mis->CtlID), hdc); DeleteObject(hFont); mis->itemWidth = fontSize.cx; mis->itemHeight = fontSize.cy; return TRUE; } case WM_DRAWITEM: { DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *) lParam; HFONT hFont, hoFont; HBRUSH hBrush; char *pszText; int iItem = dis->itemData - 1; COLORREF color = (COLORREF) SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_GETCOLOUR, 0, 0); switch (iItem) { case 1: case 5: case 6: case 7: case 9: color = (COLORREF) SendDlgItemMessage(hwndDlg, IDC_BKGINCOMING, CPM_GETCOLOUR, 0, 0); break; case 0: case 2: case 3: case 4: color = (COLORREF) SendDlgItemMessage(hwndDlg, IDC_BKGOUTGOING, CPM_GETCOLOUR, 0, 0); break; case 8: color = (COLORREF) SendDlgItemMessage(hwndDlg, IDC_BKGINPUT, CPM_GETCOLOUR, 0, 0); break; } hBrush = CreateSolidBrush(color); hFont = CreateFontA(fontOptionsList[iItem].size, 0, 0, 0, fontOptionsList[iItem].style & FONTF_BOLD ? FW_BOLD : FW_NORMAL, fontOptionsList[iItem].style & FONTF_ITALIC ? 1 : 0, 0, 0, fontOptionsList[iItem].charset, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, fontOptionsList[iItem].szFace); hoFont = (HFONT) SelectObject(dis->hDC, hFont); SetBkMode(dis->hDC, TRANSPARENT); FillRect(dis->hDC, &dis->rcItem, hBrush); if (dis->itemState & ODS_SELECTED) FrameRect(dis->hDC, &dis->rcItem, GetSysColorBrush(COLOR_HIGHLIGHT)); SetTextColor(dis->hDC, fontOptionsList[iItem].colour); pszText = Translate(fontOptionsList[iItem].szDescr); TextOutA(dis->hDC, dis->rcItem.left, dis->rcItem.top, pszText, lstrlenA(pszText)); SelectObject(dis->hDC, hoFont); DeleteObject(hFont); DeleteObject(hBrush); return TRUE; } case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_LOADUNREAD: case IDC_LOADCOUNT: case IDC_LOADTIME: EnableWindow(GetDlgItem(hwndDlg, IDC_LOADCOUNTN), IsDlgButtonChecked(hwndDlg, IDC_LOADCOUNT)); EnableWindow(GetDlgItem(hwndDlg, IDC_LOADCOUNTSPIN), IsDlgButtonChecked(hwndDlg, IDC_LOADCOUNT)); EnableWindow(GetDlgItem(hwndDlg, IDC_LOADTIMEN), IsDlgButtonChecked(hwndDlg, IDC_LOADTIME)); EnableWindow(GetDlgItem(hwndDlg, IDC_LOADTIMESPIN), IsDlgButtonChecked(hwndDlg, IDC_LOADTIME)); EnableWindow(GetDlgItem(hwndDlg, IDC_STMINSOLD), IsDlgButtonChecked(hwndDlg, IDC_LOADTIME)); break; case IDC_SHOWTIMES: EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWSECONDS), IsDlgButtonChecked(hwndDlg, IDC_SHOWTIMES)); EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWDATES), IsDlgButtonChecked(hwndDlg, IDC_SHOWTIMES)); case IDC_SHOWDATES: EnableWindow(GetDlgItem(hwndDlg, IDC_USELONGDATE), IsDlgButtonChecked(hwndDlg, IDC_SHOWDATES) && IsDlgButtonChecked(hwndDlg, IDC_SHOWTIMES)); EnableWindow(GetDlgItem(hwndDlg, IDC_USERELATIVEDATE), IsDlgButtonChecked(hwndDlg, IDC_SHOWDATES) && IsDlgButtonChecked(hwndDlg, IDC_SHOWTIMES)); break; case IDC_GROUPMESSAGES: EnableWindow(GetDlgItem(hwndDlg, IDC_MARKFOLLOWUPS), IsDlgButtonChecked(hwndDlg, IDC_GROUPMESSAGES)); break; case IDC_DRAWLINES: EnableWindow(GetDlgItem(hwndDlg, IDC_LINECOLOUR), IsDlgButtonChecked(hwndDlg, IDC_DRAWLINES)); break; case IDC_BKGCOLOUR: DeleteObject(hBkgColourBrush); hBkgColourBrush = CreateSolidBrush(SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_GETCOLOUR, 0, 0)); case IDC_BKGINCOMING: case IDC_BKGOUTGOING: case IDC_BKGINPUT: InvalidateRect(GetDlgItem(hwndDlg, IDC_FONTLIST), NULL, TRUE); break; case IDC_FONTLIST: if (HIWORD(wParam) == LBN_SELCHANGE) { if (SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_GETSELCOUNT, 0, 0) > 1) { SendDlgItemMessage(hwndDlg, IDC_FONTCOLOUR, CPM_SETCOLOUR, 0, GetSysColor(COLOR_3DFACE)); SendDlgItemMessage(hwndDlg, IDC_FONTCOLOUR, CPM_SETDEFAULTCOLOUR, 0, GetSysColor(COLOR_WINDOWTEXT)); } else { int i = SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_GETCURSEL, 0, 0), 0) - 1; SendDlgItemMessage(hwndDlg, IDC_FONTCOLOUR, CPM_SETCOLOUR, 0, fontOptionsList[i].colour); SendDlgItemMessage(hwndDlg, IDC_FONTCOLOUR, CPM_SETDEFAULTCOLOUR, 0, fontOptionsList[i].defColour); } } if (HIWORD(wParam) != LBN_DBLCLK) return TRUE; //fall through case IDC_CHOOSEFONT: { CHOOSEFONTA cf = { 0 }; LOGFONTA lf = { 0 }; int i = SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_GETCURSEL, 0, 0), 0) - 1; lf.lfHeight = fontOptionsList[i].size; lf.lfWeight = fontOptionsList[i].style & FONTF_BOLD ? FW_BOLD : FW_NORMAL; lf.lfItalic = fontOptionsList[i].style & FONTF_ITALIC ? 1 : 0; lf.lfCharSet = fontOptionsList[i].charset; lf.lfOutPrecision = OUT_DEFAULT_PRECIS; lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; lf.lfQuality = DEFAULT_QUALITY; lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; lstrcpyA(lf.lfFaceName, fontOptionsList[i].szFace); cf.lStructSize = sizeof(cf); cf.hwndOwner = hwndDlg; cf.lpLogFont = &lf; cf.Flags = CF_FORCEFONTEXIST | CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS; if (ChooseFontA(&cf)) { int selItems[sizeof(fontOptionsList) / sizeof(fontOptionsList[0])]; int sel, selCount; selCount = SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_GETSELITEMS, sizeof(fontOptionsList) / sizeof(fontOptionsList[0]), (LPARAM) selItems); for (sel = 0; sel < selCount; sel++) { i = SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_GETITEMDATA, selItems[sel], 0) - 1; fontOptionsList[i].size = (char) lf.lfHeight; fontOptionsList[i].style = (lf.lfWeight >= FW_BOLD ? FONTF_BOLD : 0) | (lf.lfItalic ? FONTF_ITALIC : 0); fontOptionsList[i].charset = lf.lfCharSet; lstrcpyA(fontOptionsList[i].szFace, lf.lfFaceName); { MEASUREITEMSTRUCT mis = { 0 }; mis.CtlID = IDC_FONTLIST; mis.itemData = i + 1; SendMessage(hwndDlg, WM_MEASUREITEM, 0, (LPARAM) & mis); SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_SETITEMHEIGHT, selItems[sel], mis.itemHeight); } } InvalidateRect(GetDlgItem(hwndDlg, IDC_FONTLIST), NULL, TRUE); break; } return TRUE; } case IDC_FONTCOLOUR: { int selItems[sizeof(fontOptionsList) / sizeof(fontOptionsList[0])]; int sel, selCount, i; selCount = SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_GETSELITEMS, sizeof(fontOptionsList) / sizeof(fontOptionsList[0]), (LPARAM) selItems); for (sel = 0; sel < selCount; sel++) { i = SendDlgItemMessage(hwndDlg, IDC_FONTLIST, LB_GETITEMDATA, selItems[sel], 0) - 1; fontOptionsList[i].colour = SendDlgItemMessage(hwndDlg, IDC_FONTCOLOUR, CPM_GETCOLOUR, 0, 0); } InvalidateRect(GetDlgItem(hwndDlg, IDC_FONTLIST), NULL, FALSE); break; } case IDC_LOADCOUNTN: case IDC_LOADTIMEN: if (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus()) return TRUE; break; } SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); break; case WM_NOTIFY: switch (((LPNMHDR) lParam)->idFrom) { case 0: switch (((LPNMHDR) lParam)->code) { case PSN_APPLY: if (IsDlgButtonChecked(hwndDlg, IDC_LOADCOUNT)) DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_LOADHISTORY, LOADHISTORY_COUNT); else if (IsDlgButtonChecked(hwndDlg, IDC_LOADTIME)) DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_LOADHISTORY, LOADHISTORY_TIME); else DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_LOADHISTORY, LOADHISTORY_UNREAD); DBWriteContactSettingWord(NULL, SRMMMOD, SRMSGSET_LOADCOUNT, (WORD) SendDlgItemMessage(hwndDlg, IDC_LOADCOUNTSPIN, UDM_GETPOS, 0, 0)); DBWriteContactSettingWord(NULL, SRMMMOD, SRMSGSET_LOADTIME, (WORD) SendDlgItemMessage(hwndDlg, IDC_LOADTIMESPIN, UDM_GETPOS, 0, 0)); DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWLOGICONS, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWLOGICONS)); DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_HIDENAMES, (BYTE) ! IsDlgButtonChecked(hwndDlg, IDC_SHOWNAMES)); DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTIME, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWTIMES)); DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWSECONDS, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWSECONDS)); DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWDATE, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWDATES)); DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_USELONGDATE, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_USELONGDATE)); DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_USERELATIVEDATE, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_USERELATIVEDATE)); DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWSTATUSCH, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWSTATUSCHANGES)); DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_GROUPMESSAGES, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_GROUPMESSAGES)); DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_MARKFOLLOWUPS, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_MARKFOLLOWUPS)); DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_MESSAGEONNEWLINE, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_MESSAGEONNEWLINE)); DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_DRAWLINES, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_DRAWLINES)); DBWriteContactSettingDword(NULL, SRMMMOD, SRMSGSET_BKGCOLOUR, SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_GETCOLOUR, 0, 0)); DBWriteContactSettingDword(NULL, SRMMMOD, SRMSGSET_INPUTBKGCOLOUR, SendDlgItemMessage(hwndDlg, IDC_BKGINPUT, CPM_GETCOLOUR, 0, 0)); DBWriteContactSettingDword(NULL, SRMMMOD, SRMSGSET_INCOMINGBKGCOLOUR, SendDlgItemMessage(hwndDlg, IDC_BKGINCOMING, CPM_GETCOLOUR, 0, 0)); DBWriteContactSettingDword(NULL, SRMMMOD, SRMSGSET_OUTGOINGBKGCOLOUR, SendDlgItemMessage(hwndDlg, IDC_BKGOUTGOING, CPM_GETCOLOUR, 0, 0)); DBWriteContactSettingDword(NULL, SRMMMOD, SRMSGSET_LINECOLOUR, SendDlgItemMessage(hwndDlg, IDC_LINECOLOUR, CPM_GETCOLOUR, 0, 0)); // DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_USEIEVIEW, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_USEIEVIEW)); { int i; char str[32]; for (i = 0; i < sizeof(fontOptionsList) / sizeof(fontOptionsList[0]); i++) { wsprintfA(str, "SRMFont%d", i); DBWriteContactSettingString(NULL, SRMMMOD, str, fontOptionsList[i].szFace); wsprintfA(str, "SRMFont%dSize", i); DBWriteContactSettingByte(NULL, SRMMMOD, str, fontOptionsList[i].size); wsprintfA(str, "SRMFont%dSty", i); DBWriteContactSettingByte(NULL, SRMMMOD, str, fontOptionsList[i].style); wsprintfA(str, "SRMFont%dSet", i); DBWriteContactSettingByte(NULL, SRMMMOD, str, fontOptionsList[i].charset); wsprintfA(str, "SRMFont%dCol", i); DBWriteContactSettingDword(NULL, SRMMMOD, str, fontOptionsList[i].colour); } } FreeMsgLogIcons(); LoadMsgLogIcons(); ReloadGlobals(); WindowList_Broadcast(g_dat->hMessageWindowList, DM_OPTIONSAPPLIED, 0, 0); return TRUE; } break; } break; case WM_DESTROY: DeleteObject(hBkgColourBrush); break; } return FALSE; }
HRESULT TShellExt::HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plResult) { LRESULT Dummy; if (plResult == NULL) plResult = &Dummy; SIZE tS; HBRUSH hBr; *plResult = true; if (uMsg == WM_DRAWITEM && wParam == 0) { // either a main sub menu, a group menu or a contact DRAWITEMSTRUCT *dwi = (DRAWITEMSTRUCT*)lParam; TMenuDrawInfo *psd = (TMenuDrawInfo*)dwi->itemData; // don't fill SetBkMode(dwi->hDC, TRANSPARENT); // where to draw the icon? RECT icorc; icorc.left = 0; icorc.top = dwi->rcItem.top + ((dwi->rcItem.bottom - dwi->rcItem.top) / 2) - (16 / 2); icorc.right = icorc.left + 16; icorc.bottom = icorc.top + 16; // draw for groups if (psd->fTypes & (dtGroup | dtEntry)) { hBr = GetSysColorBrush(COLOR_MENU); FillRect(dwi->hDC, &dwi->rcItem, hBr); DeleteObject(hBr); if (dwi->itemState & ODS_SELECTED) { // only do this for entry menu types otherwise a black mask // is drawn under groups hBr = GetSysColorBrush(COLOR_HIGHLIGHT); FillRect(dwi->hDC, &dwi->rcItem, hBr); DeleteObject(hBr); SetTextColor(dwi->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); } // draw icon if (dwi->itemState & ODS_SELECTED) hBr = GetSysColorBrush(COLOR_HIGHLIGHT); else hBr = GetSysColorBrush(COLOR_MENU); DrawIconEx(dwi->hDC, icorc.left + 1, icorc.top, psd->hStatusIcon, 16, 16, 0, hBr, DI_NORMAL); DeleteObject(hBr); // draw the text dwi->rcItem.left += dwi->rcItem.bottom - dwi->rcItem.top - 2; DrawTextA(dwi->hDC, psd->szText, psd->cch, &dwi->rcItem, DT_NOCLIP | DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER); // draw the name of the database text if it's there if (psd->szProfile != NULL) { GetTextExtentPoint32A(dwi->hDC, psd->szText, psd->cch, &tS); dwi->rcItem.left += tS.cx + 8; SetTextColor(dwi->hDC, GetSysColor(COLOR_GRAYTEXT)); DrawTextA(dwi->hDC, psd->szProfile, lstrlenA(psd->szProfile), &dwi->rcItem, DT_NOCLIP | DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER); } } else { // it's a contact! hBr = GetSysColorBrush(COLOR_MENU); FillRect(dwi->hDC, &dwi->rcItem, hBr); DeleteObject(hBr); if (dwi->itemState & ODS_SELECTED) { hBr = GetSysColorBrush(COLOR_HIGHLIGHT); FillRect(dwi->hDC, &dwi->rcItem, hBr); DeleteObject(hBr); SetTextColor(dwi->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); } // draw icon if (dwi->itemState & ODS_SELECTED) hBr = GetSysColorBrush(COLOR_HIGHLIGHT); else hBr = GetSysColorBrush(COLOR_MENU); DrawIconEx(dwi->hDC, icorc.left + 2, icorc.top, psd->hStatusIcon, 16, 16, 0, hBr, DI_NORMAL); DeleteObject(hBr); // draw the text dwi->rcItem.left += dwi->rcItem.bottom - dwi->rcItem.top + 1; DrawTextA(dwi->hDC, psd->szText, psd->cch, &dwi->rcItem, DT_NOCLIP | DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER); } } else if (uMsg == WM_MEASUREITEM) { // don't check if it's really a menu MEASUREITEMSTRUCT *msi = (MEASUREITEMSTRUCT*)lParam; TMenuDrawInfo *psd = (TMenuDrawInfo*)msi->itemData; NONCLIENTMETRICS ncm; ncm.cbSize = (bIsVistaPlus) ? sizeof(ncm) : offsetof(NONCLIENTMETRICS, iPaddedBorderWidth); SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0); // create the font used in menus, this font should be cached somewhere really HFONT hFont = CreateFontIndirect(&ncm.lfMenuFont); // select in the font HFONT hOldFont = (HFONT)SelectObject(hMemDC, hFont); // default to an icon int dx = 16; // get the size 'n' account for the icon GetTextExtentPoint32A(hMemDC, psd->szText, psd->cch, &tS); dx += tS.cx; // main menu item? if (psd->szProfile != NULL) { GetTextExtentPoint32A(hMemDC, psd->szProfile, lstrlenA(psd->szProfile), &tS); dx += tS.cx; } // store it msi->itemWidth = dx + ncm.iMenuWidth; msi->itemHeight = ncm.iMenuHeight + 2; if (tS.cy > (int)msi->itemHeight) msi->itemHeight += tS.cy - msi->itemHeight; // clean up SelectObject(hMemDC, hOldFont); DeleteObject(hFont); } return S_OK; }
int RTL_HitTest(HWND hwnd, struct ClcData *dat, int testx, ClcContact *hitcontact, DWORD *flags, int indent, int hit) { RECT clRect; int right, checkboxWidth, width; DWORD style = GetWindowLongPtr(hwnd, GWL_STYLE); SIZE textSize; HDC hdc; HFONT hFont; GetClientRect(hwnd, &clRect); right = clRect.right; // avatar check if (hitcontact->type == CLCIT_CONTACT && cfg::dat.dwFlags & CLUI_FRAME_AVATARS && hitcontact->ace != NULL && hitcontact->avatarLeft != -1) if (testx < right - hitcontact->avatarLeft && testx > right - hitcontact->avatarLeft - cfg::dat.avatarSize) if (flags) *flags |= CLCHT_ONAVATAR; if (testx > right - (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 > right - (dat->leftMargin + indent * dat->groupIndent + checkboxWidth)) { if (flags) *flags |= CLCHT_ONITEMCHECK; return hit; } if (testx > right - (dat->leftMargin + indent * dat->groupIndent + checkboxWidth + dat->iconXSpace)) { if (flags) *flags |= CLCHT_ONITEMICON; return hit; } int rightOffset = hitcontact->extraIconRightBegin; if (rightOffset) { for (int 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 = 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) { 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, (int)mir_strlen(szCounts), &textSize); width += textSize.cx; } } SelectObject(hdc, hFont); ReleaseDC(hwnd, hdc); if (testx > right - (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 (cfg::dat.dwFlags & CLUI_FULLROWSELECT && !(GetKeyState(VK_SHIFT) & 0x8000) && testx < right - (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 (flags) *flags |= CLCHT_NOWHERE; return -1; }
/** * name: PaintThemeButton * desc: Draws the none themed button * param: ctl - BTNCTRL structure for the button * hdcMem - device context to draw to * rcClient - rectangle of the whole button * return: nothing **/ static void __fastcall PaintButton(BTNCTRL *ctl, HDC hdcMem, LPRECT rcClient) { RECT rcText = { 0, 0, 0, 0 }; TCHAR szText[MAX_PATH] = { 0 }; WORD ccText; // Draw the flat button if (ctl->dwStyle & MBS_FLAT) { HBRUSH hbr = NULL; if (ctl->stateId == PBS_PRESSED || ctl->stateId == PBS_HOT) hbr = GetSysColorBrush(COLOR_3DLIGHT); else { HDC dc; HWND hwndParent; hwndParent = GetParent(ctl->hwnd); if (dc = GetDC(hwndParent)) { hbr = (HBRUSH)SendMessage(hwndParent, WM_CTLCOLORDLG, (WPARAM)dc, (LPARAM)hwndParent); ReleaseDC(hwndParent, dc); } } if (hbr) { FillRect(hdcMem, rcClient, hbr); DeleteObject(hbr); } if (ctl->stateId == PBS_HOT || ctl->bFocus) { if (ctl->pbState) DrawEdge(hdcMem, rcClient, EDGE_ETCHED, BF_RECT | BF_SOFT); else DrawEdge(hdcMem, rcClient, BDR_RAISEDOUTER, BF_RECT | BF_SOFT | BF_FLAT); } else if (ctl->stateId == PBS_PRESSED) DrawEdge(hdcMem, rcClient, BDR_SUNKENOUTER, BF_RECT | BF_SOFT); } else { UINT uState = DFCS_BUTTONPUSH | ((ctl->stateId == PBS_HOT) ? DFCS_HOT : 0) | ((ctl->stateId == PBS_PRESSED) ? DFCS_PUSHED : 0); if (ctl->defbutton&&ctl->stateId == PBS_NORMAL) uState |= DLGC_DEFPUSHBUTTON; DrawFrameControl(hdcMem, rcClient, DFC_BUTTON, uState); // Draw focus rectangle if button has focus if (ctl->bFocus) { RECT focusRect = *rcClient; InflateRect(&focusRect, -3, -3); DrawFocusRect(hdcMem, &focusRect); } } // calculate text rect { SIZE sizeText; HFONT hOldFont; ccText = GetWindowText(ctl->hwnd, szText, _countof(szText)); if (ccText > 0) { hOldFont = (HFONT)SelectObject(hdcMem, ctl->hFont); GetTextExtentPoint32(hdcMem, szText, ccText, &sizeText); if (ctl->cHot) { SIZE sizeHot; GetTextExtentPoint32A(hdcMem, "&", 1, &sizeHot); sizeText.cx -= sizeHot.cx; } SelectObject(hdcMem, hOldFont); rcText.left = (ctl->hIcon) ? 0 : (rcClient->right - rcClient->left - sizeText.cx) / 2; rcText.top = (rcClient->bottom - rcClient->top - sizeText.cy) / 2; rcText.right = rcText.left + sizeText.cx; rcText.bottom = rcText.top + sizeText.cy; if (ctl->stateId == PBS_PRESSED) OffsetRect(&rcText, 1, 1); } } PaintIcon(ctl, hdcMem, &ccText, rcClient, &rcText); // draw text if (ccText > 0) { HFONT hOldFont; hOldFont = (HFONT)SelectObject(hdcMem, ctl->hFont); SetBkMode(hdcMem, TRANSPARENT); SetTextColor(hdcMem, IsWindowEnabled(ctl->hwnd) || !ctl->hThemeButton ? ctl->stateId == PBS_HOT ? GetSysColor(COLOR_HOTLIGHT) : GetSysColor(COLOR_BTNTEXT) : GetSysColor(COLOR_GRAYTEXT)); DrawState(hdcMem, NULL, NULL, (LPARAM)szText, 0, rcText.left, rcText.top, rcText.right - rcText.left, rcText.bottom - rcText.top, IsWindowEnabled(ctl->hwnd) || ctl->hThemeButton ? DST_PREFIXTEXT | DSS_NORMAL : DST_PREFIXTEXT | DSS_DISABLED); SelectObject(hdcMem, hOldFont); } }
void GR_Win32CharWidths::setCharWidthsOfRange(HDC hdc, UT_UCSChar c0, UT_UCSChar c1) { if(m_vRanges.getItemCount() == 0) { _retrieveFontInfo(hdc); } UINT k; int w; #ifdef DEBUG DWORD iErrorCode = 0; #endif // Windows NT and Windows 95 support the Unicode Font file. // All of the Unicode glyphs can be rendered if the glyph is found in // the font file. However, Windows 95 does not support the Unicode // characters other than the characters for which the particular codepage // of the font file is defined. // Reference Microsoft knowledge base: // Q145754 - PRB ExtTextOutW or TextOutW Unicode Text Output Is Blank if (UT_IsWinNT()) { for (k=c0; k<=c1; k++) { if(k == 0x200B || k == 0xFEFF || k == UCS_LIGATURE_PLACEHOLDER) setWidth(k,0); else if(!_doesGlyphExist(k)) { setWidth(k,GR_CW_ABSENT); } else { GetCharWidth32W(hdc,k,k,&w); #ifdef DEBUG ABC abc; int iRes = GetCharABCWidthsW(hdc,k,k,&abc); #endif // handle overstriking chars here UT_uint32 iOver = UT_isOverstrikingChar(k); if(!w || iOver != UT_NOT_OVERSTRIKING) { iOver &= UT_OVERSTRIKING_TYPE; if(iOver == UT_OVERSTRIKING_RIGHT) { w = 0; } else { ABC abc; UT_DebugOnly<int> iRes = GetCharABCWidthsW(hdc,k,k,&abc); UT_ASSERT( iRes ); if(iOver == UT_OVERSTRIKING_LEFT) { UT_ASSERT( abc.abcB < GR_OC_MAX_WIDTH); w = abc.abcB | GR_OC_LEFT_FLUSHED; } else { w = abc.abcB /*+ abc.abcA + abc.abcC*/; w = -w; } } } setWidth(k,w); } } } else { HFONT hFont = (HFONT) GetCurrentObject(hdc, OBJ_FONT); LOGFONTW aLogFont; UT_DebugOnly<int> iRes = GetObjectW(hFont, sizeof(LOGFONTW), &aLogFont); UT_ASSERT(iRes); xxx_UT_DEBUGMSG(("gr_Win32Graphics::getCharWidth: extra interchar. spacing %d\n", GetTextCharacterExtra(hdc))); if(aLogFont.lfCharSet == SYMBOL_CHARSET) { // Symbol character handling for (k=c0; k<=c1; k++) { if(!_doesGlyphExist(k)) { setWidth(k,GR_CW_ABSENT); } else { SIZE Size; char str[sizeof(UT_UCSChar)]; int iConverted = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) &k, 1, str, sizeof(str), NULL, NULL); GetTextExtentPoint32A(hdc, str, iConverted, &Size); setWidth(k, Size.cx); } } } else { // Unicode font and default character sets for (k=c0; k<=c1; k++) { if(k == 0x200B || k == 0xFEFF || k == UCS_LIGATURE_PLACEHOLDER) setWidth(k,0); else if(!_doesGlyphExist(k)) { setWidth(k,GR_CW_ABSENT); } else { SIZE Size; wchar_t sz1[2]; sz1[0] = k; GetTextExtentPoint32W(hdc, sz1, 1, &Size); // handle overstriking chars here UT_uint32 iOver = UT_isOverstrikingChar(k); if(!Size.cx || iOver != UT_NOT_OVERSTRIKING) { iOver &= UT_OVERSTRIKING_TYPE; if(iOver == UT_OVERSTRIKING_RIGHT) { Size.cx = 0; } else { ABC abc; iRes = GetCharABCWidthsW(hdc,k,k,&abc); // I have commented out the assert below, // because when the function above is called for // the first time, it seems to always // return 0, even though it fills the abc // structure with reasonable values, // Tomas, June 22, 2003 // UT_ASSERT( iRes ); #ifdef DEBUG if(!iRes) { iErrorCode = GetLastError(); } #endif if(iOver == UT_OVERSTRIKING_LEFT) { UT_ASSERT( abc.abcB < GR_OC_MAX_WIDTH); Size.cx = abc.abcB | GR_OC_LEFT_FLUSHED; } else { Size.cx = abc.abcB; Size.cx = -Size.cx; } } } #ifdef DEBUG if(iErrorCode) { LPVOID lpMsgBuf; FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, iErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPWSTR) &lpMsgBuf, 0, NULL ); // Process any inserts in lpMsgBuf. // ... // Display the string. //MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION ); UT_DEBUGMSG(("char width error: %s\n", lpMsgBuf)); // Free the buffer. LocalFree( lpMsgBuf ); } #endif setWidth(k,Size.cx); xxx_UT_DEBUGMSG(("gr_Win32Graphics::getCharWidths: 0x%x: Size.cx %d\n", k, Size.cx)); } } } } }
static void TitlePaint(TitleData* data, HWND hWnd, HDC dc) { BITMAP bm; ZeroMemory(&bm, sizeof(bm)); GetObject(data->hBitmap, sizeof(bm), &bm); // If nothing changed since last paint, use the cached bitmap RECT clientRect; GetClientRect(hWnd, &clientRect); int x0 = (RECT_Width(&clientRect) - bm.bmWidth)/2; int y0 = (RECT_Height(&clientRect) - bm.bmHeight)/2; if (!data->bRepaint) { BitBlt(dc,x0,y0,bm.bmWidth,bm.bmHeight,data->hOffScreenDC,0,0,SRCCOPY); return; } // Copy the current image and fill the interior with black // What we essentially want is dest = (screen AND (NOT shape)) // There is no ((NOT src) AND dest) raster operation in Windows, // so what we do is a combination of NOTSRCCOPY (dest = (NOT source)) // and NOTSRCERASE (dest = (NOT src) AND (NOT dest)). NOT is applied // twice to the data we have copied from the screen device context, // restoring the original color. SelectBitmap(data->hOffScreenDC, data->hOffScreenBg); SelectBitmap(data->hBitmapDC, data->hBitmap); BitBlt(data->hOffScreenDC,0,0,bm.bmWidth,bm.bmHeight,dc,x0,y0,NOTSRCCOPY); BitBlt(data->hOffScreenDC,0,0,bm.bmWidth,bm.bmHeight,data->hBitmapDC, 0,0,NOTSRCERASE); // Wipe out the offscreen bitmap with white RECT bitmapRect = {0, 0, bm.bmWidth, bm.bmHeight}; HBRUSH hWhiteBrush = GetStockBrush(WHITE_BRUSH); SelectBitmap(data->hOffScreenDC, data->hOffScreen); FillRect(data->hOffScreenDC, &bitmapRect, hWhiteBrush); // Calculate the size of the product name string const char * prodName = data->productName; if (!prodName) prodName = data->productId; int prodLen = strlen(prodName); SIZE prodNameSize = {0,0}; if (data->hFont) SelectFont(data->hOffScreenDC, data->hFont); GetTextExtentPoint32A(data->hOffScreenDC,prodName,prodLen,&prodNameSize); // Adjust product name rectangle because the cloud is not quite symmetric #ifdef SDK_REGISTRATION int y = 12; int height = (bm.bmHeight - y)/2; #else // !SDK_REGISTRATION int y = 0; int height = bm.bmHeight - 10; #endif // !SDK_REGISTRATION RECT prodNameRect; prodNameRect.left = 0; prodNameRect.right = bm.bmWidth; prodNameRect.top = y + (height - prodNameSize.cy)/2; prodNameRect.bottom = prodNameRect.top + prodNameSize.cy; #ifdef SDK_REGISTRATION // Add more space around the product name InflateRect(&prodNameRect, 0, SCROLL_LINE_SPACE); ScrollTextData* scroll = data->scrollText; if (scroll && scroll->bScrolling) { RECT rc; rc.left = prodNameRect.left; rc.right = prodNameRect.right; BOOL rollover = FALSE; int y1 = prodNameRect.bottom - scroll->offset; if (scroll->hFont) SelectFont(data->hOffScreenDC, scroll->hFont); for (int i=0; y1 < bm.bmHeight; i++) { if (i == scroll->lineCount) { i = 0; y1 += SCROLL_LINE_SPACE; rollover = TRUE; } // Skipping the first line when scrolling for the first time if (!scroll->bFirstLoop || rollover || i > 0) { LPCSTR line = scroll->lines[i]; if (!line) line = " "; rc.top = y1; rc.bottom = y1 + scroll->font.lfHeight + SCROLL_LINE_SPACE; if (rc.bottom >= prodNameRect.bottom) { if (rc.top < bm.bmHeight) { DrawTextA(data->hOffScreenDC, line, strlen(line), &rc, DT_NOCLIP | DT_CENTER | DT_SINGLELINE); } } } y1 += scroll->font.lfHeight + SCROLL_LINE_SPACE; } // Erase the portion of the bitmap that overlaps with the product name int bottom = prodNameRect.bottom + SCROLL_LINE_SPACE; SelectBitmap(data->hBitmapDC, data->hGradientBitmap); BitBlt(data->hOffScreenDC, 0, 0, bm.bmWidth, bottom, data->hBitmapDC, 0, bm.bmHeight - bottom, SRCPAINT); // Restore the product name font if (data->hFont) SelectFont(data->hOffScreenDC, data->hFont); } #endif // SDK_REGISTRATION // Draw the product name DrawTextA(data->hOffScreenDC, prodName, prodLen, &prodNameRect, DT_NOCLIP | DT_CENTER | DT_VCENTER | DT_SINGLELINE); // Fill the exterior with black SelectBitmap(data->hBitmapDC, data->hBitmap); BitBlt(data->hOffScreenDC,0,0,bm.bmWidth,bm.bmHeight, data->hBitmapDC,0,0,SRCAND); // Overlap the two images SelectBitmap(data->hBitmapDC, data->hOffScreenBg); BitBlt(data->hOffScreenDC,0,0,bm.bmWidth,bm.bmHeight, data->hBitmapDC,0,0,SRCPAINT); // Copy the offscreen bitmap to the screen BitBlt(dc,x0,y0,bm.bmWidth,bm.bmHeight,data->hOffScreenDC,0,0,SRCCOPY); data->bRepaint = FALSE; }
extern "C" int main(int argc, wchar_t* argv[]) { TRACED_HOOK_HANDLE hHook = new HOOK_TRACE_INFO(); NTSTATUS NtStatus; ULONG ACLEntries[1] = {0}; UNICODE_STRING* NameBuffer = NULL; ORIG_CreateFontIndirectW = CreateFontIndirectW; FORCE(LhInstallHook( ORIG_CreateFontIndirectW, IMPL_CreateFontIndirectW, (PVOID)0, hHook)); FORCE(LhSetInclusiveACL(ACLEntries, 1, hHook)); CreateFontIndirectW(0); CreateFontW(10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, L"system"); LOGFONTA lf = {}; CreateFontIndirectA(&lf); CreateFontA(12, 0, 0, 0, 400, 0, 0, 0, 2, 0, 0, 0, 0, "MARLETT"); #if 0 ORIG_GetTextExtentPoint32A = GetTextExtentPoint32A; FORCE(LhInstallHook( ORIG_GetTextExtentPoint32A, IMPL_GetTextExtentPoint32A, (PVOID)0, hHook)); HDC hdc = GetDC(NULL); SIZE size; FORCE(LhSetInclusiveACL(ACLEntries, 1, hHook)); GetTextExtentPoint32W(hdc, L"abc", 3, &size); GetTextExtentPointW(hdc, L"abc", 3, &size); GetTextExtentPoint32A(hdc, "abc", 3, &size); GetTextExtentPointA(hdc, "abc", 3, &size); #endif #if 0 ORIG_MessageBeepHook = MessageBeep; /* The following shows how to install and remove local hooks... */ FORCE(LhInstallHook( ORIG_MessageBeepHook, MessageBeepHook, (PVOID)0, hHook)); printf(".\n"); // won't invoke the hook handler because hooks are inactive after installation MessageBeep(123); getch(); BOOL flags = 1; FORCE(LhIsThreadIntercepted(hHook, 0, &flags)); printf("Intercepted %d\n", flags); // activate the hook for the current thread FORCE(LhSetInclusiveACL(ACLEntries, 1, hHook)); FORCE(LhIsThreadIntercepted(hHook, 0, &flags)); printf("Intercepted %d\n", flags); printf(".\n"); // will be redirected into the handler... MessageBeep(123); getch(); FORCE(LhSetGlobalExclusiveACL(ACLEntries, 1)); printf(".\n"); // will be redirected into the handler... MessageBeep(123); getch(); FORCE(LhSetGlobalInclusiveACL(ACLEntries, 1)); printf(".\n"); // will be redirected into the handler... MessageBeep(123); getch(); printf(".\n"); // won't invoke the hook handler because hooks are inactive after installation ORIG_MessageBeepHook(123); getch(); #endif // this will also invalidate "hHook", because it is a traced handle... LhUninstallAllHooks(); // this will do nothing because the hook is already removed... LhUninstallHook(hHook); printf(".\n"); // will be redirected into the handler... MessageBeep(123); getch(); // now we can safely release the traced handle delete hHook; hHook = NULL; // even if the hook is removed, we need to wait for memory release LhWaitForPendingRemovals(); return 0; ERROR_ABORT: if(hHook != NULL) delete hHook; if(NameBuffer != NULL) free(NameBuffer ); printf("\n[Error(0x%p)]: \"%S\" (code: %d {0x%p})\n", (PVOID)NtStatus, RtlGetLastErrorString(), RtlGetLastError(), (PVOID)RtlGetLastError()); _getch(); return NtStatus; }
int ModernDrawStatusBarWorker(HWND hWnd, HDC hDC) { int iconHeight = GetSystemMetrics(SM_CYSMICON)+2; int i; // Count visible protos RECT rc; GetClientRect(hWnd, &rc); if (g_CluiData.fDisableSkinEngine) { if (g_StatusBarData.bkUseWinColors && xpt_IsThemed(g_StatusBarData.hTheme)) xpt_DrawTheme(g_StatusBarData.hTheme, hWnd, hDC, 0, 0, &rc, &rc); else DrawBackGround(hWnd, hDC, g_StatusBarData.hBmpBackground, g_StatusBarData.bkColour, g_StatusBarData.backgroundBmpUse); } else SkinDrawGlyph(hDC, &rc, &rc, "Main,ID=StatusBar"); //TBD g_StatusBarData.nProtosPerLine = db_get_b(NULL, "CLUI", "StatusBarProtosPerLine", SETTING_PROTOSPERLINE_DEFAULT); HFONT hOldFont = g_clcPainter.ChangeToFont(hDC, NULL, FONTID_STATUSBAR_PROTONAME, NULL); SIZE textSize = { 0 }; GetTextExtentPoint32A(hDC, " ", 1, &textSize); int spaceWidth = textSize.cx; int textY = rc.top + ((rc.bottom - rc.top - textSize.cy) >> 1); int iconY = rc.top + ((rc.bottom - rc.top - GetSystemMetrics(SM_CXSMICON)) >> 1); ProtosData.destroy(); int protoCount; PROTOACCOUNT **accs; ProtoEnumAccounts(&protoCount, &accs); if (protoCount == 0) return 0; int iProtoInStatusMenu = 0; for (int j = 0; j < protoCount; j++) { int i = pcli->pfnGetAccountIndexByPos(j); if (i == -1) continue; char *szProto = accs[i]->szModuleName; if (!pcli->pfnGetProtocolVisibility(szProto)) continue; char buf[256]; mir_snprintf(buf, SIZEOF(buf), "SBarAccountIsCustom_%s", szProto); ProtoItemData *p = NULL; if (g_StatusBarData.perProtoConfig && db_get_b(NULL, "CLUI", buf, SETTING_SBARACCOUNTISCUSTOM_DEFAULT)) { mir_snprintf(buf, SIZEOF(buf), "HideAccount_%s", szProto); if (db_get_b(NULL, "CLUI", buf, SETTING_SBARHIDEACCOUNT_DEFAULT)) { iProtoInStatusMenu++; continue; } mir_snprintf(buf, SIZEOF(buf), "SBarShow_%s", szProto); BYTE showOps = db_get_b(NULL, "CLUI", buf, SETTING_SBARSHOW_DEFAULT); p = new ProtoItemData; p->bShowProtoIcon = (showOps & 1) != 0; p->bShowProtoName = (showOps & 2) != 0; p->bShowStatusName = (showOps & 4) != 0; mir_snprintf(buf, SIZEOF(buf), "ShowXStatus_%s", szProto); p->xStatusMode = db_get_b(NULL, "CLUI", buf, SETTING_SBARSHOW_DEFAULT); mir_snprintf(buf, SIZEOF(buf), "UseConnectingIcon_%s", szProto); p->bConnectingIcon = db_get_b(NULL, "CLUI", buf, SETTING_USECONNECTINGICON_DEFAULT) != 0; mir_snprintf(buf, SIZEOF(buf), "ShowUnreadEmails_%s", szProto); p->bShowProtoEmails = db_get_b(NULL, "CLUI", buf, SETTING_SHOWUNREADEMAILS_DEFAULT) != 0; mir_snprintf(buf, SIZEOF(buf), "SBarRightClk_%s", szProto); p->SBarRightClk = db_get_b(NULL, "CLUI", buf, SETTING_SBARRIGHTCLK_DEFAULT) != 0; mir_snprintf(buf, SIZEOF(buf), "PaddingLeft_%s", szProto); p->PaddingLeft = db_get_dw(NULL, "CLUI", buf, SETTING_PADDINGLEFT_DEFAULT); mir_snprintf(buf, SIZEOF(buf), "PaddingRight_%s", szProto); p->PaddingRight = db_get_dw(NULL, "CLUI", buf, SETTING_PADDINGRIGHT_DEFAULT); } else { p = new ProtoItemData; p->bShowProtoIcon = g_StatusBarData.bShowProtoIcon; p->bShowProtoName = g_StatusBarData.bShowProtoName; p->bShowStatusName = g_StatusBarData.bShowStatusName; p->xStatusMode = g_StatusBarData.xStatusMode; p->bConnectingIcon = g_StatusBarData.bConnectingIcon; p->bShowProtoEmails = g_StatusBarData.bShowProtoEmails; p->SBarRightClk = 0; p->PaddingLeft = 0; p->PaddingRight = 0; } p->iProtoStatus = CallProtoService(szProto, PS_GETSTATUS, 0, 0); if (p->iProtoStatus > ID_STATUS_OFFLINE) if (p->bShowProtoEmails == 1 && ProtoServiceExists(szProto, PS_GETUNREADEMAILCOUNT)) { int nEmails = (int)ProtoCallService(szProto, PS_GETUNREADEMAILCOUNT, 0, 0); if (nEmails > 0) { char buf[40]; mir_snprintf(buf, SIZEOF(buf), "[%d]", nEmails); p->szProtoEMailCount = mir_strdup(buf); } } p->tszProtoHumanName = mir_tstrdup(accs[i]->tszAccountName); p->szAccountName = mir_strdup(szProto); p->szProtoName = mir_strdup(accs[i]->szProtoName); p->tszProtoStatusText = mir_tstrdup(pcli->pfnGetStatusModeDescription(p->iProtoStatus, 0)); p->iProtoPos = iProtoInStatusMenu++; p->bIsDimmed = 0; if (g_CluiData.bFilterEffective & CLVM_FILTER_PROTOS) { char szTemp[2048]; mir_snprintf(szTemp, SIZEOF(szTemp), "%s|", p->szAccountName); p->bIsDimmed = strstr(g_CluiData.protoFilter, szTemp) ? 0 : 1; } ProtosData.insert(p); } if (ProtosData.getCount() == 0) return 0; //START MULTILINE HERE int orig_protoCount = protoCount; int orig_visProtoCount = ProtosData.getCount(); int protosperline = 0; if (g_StatusBarData.nProtosPerLine) protosperline = g_StatusBarData.nProtosPerLine; else if (orig_visProtoCount) protosperline = orig_visProtoCount; else if (protoCount) { protosperline = protoCount; orig_visProtoCount = protoCount; } else { protosperline = 1; orig_visProtoCount = 1; } protosperline = min(protosperline, orig_visProtoCount); int linecount = protosperline ? (orig_visProtoCount + (protosperline - 1)) / protosperline : 1; //divide with rounding to up for (int line = 0; line < linecount; line++) { int rowheight = max(textSize.cy + 2, iconHeight); protoCount = min(protosperline, (orig_protoCount - line*protosperline)); int visProtoCount = min(protosperline, (orig_visProtoCount - line*protosperline)); GetClientRect(hWnd, &rc); rc.top += g_StatusBarData.rectBorders.top; rc.bottom -= g_StatusBarData.rectBorders.bottom; int aligndx = 0, maxwidth = 0, xstatus = 0, SumWidth = 0; int height = (rowheight*linecount); if (height > (rc.bottom - rc.top)) { rowheight = (rc.bottom - rc.top) / linecount; height = (rowheight*linecount); } int rowsdy = ((rc.bottom - rc.top) - height) / 2; if (rowheight*(line)+rowsdy < rc.top - rowheight) continue; if (rowheight*(line + 1) + rowsdy>rc.bottom + rowheight) break; if (g_StatusBarData.VAlign == 0) { //top rc.bottom = rc.top + rowheight*(line + 1); rc.top = rc.top + rowheight*line + 1; } else if (g_StatusBarData.VAlign == 1) { //center rc.bottom = rc.top + rowsdy + rowheight*(line + 1); rc.top = rc.top + rowsdy + rowheight*line + 1; } else if (g_StatusBarData.VAlign == 2) { //bottom rc.top = rc.bottom - (rowheight*(linecount - line)); rc.bottom = rc.bottom - (rowheight*(linecount - line - 1) + 1); } textY = rc.top + (((rc.bottom - rc.top) - textSize.cy) / 2); iconY = rc.top + (((rc.bottom - rc.top) - iconHeight) / 2); //Code for each line DWORD sw; int rectwidth = rc.right - rc.left - g_StatusBarData.rectBorders.left - g_StatusBarData.rectBorders.right; if (visProtoCount > 1) sw = (rectwidth - (g_StatusBarData.extraspace*(visProtoCount - 1))) / visProtoCount; else sw = rectwidth; int *ProtoWidth = (int*)mir_alloc(sizeof(int)*visProtoCount); for (i = 0; i < visProtoCount; i++) { ProtoItemData &p = ProtosData[line*protosperline + i]; DWORD w = p.PaddingLeft; w += p.PaddingRight; if (p.bShowProtoIcon) { w += GetSystemMetrics(SM_CXSMICON) + 1; p.extraIcon = NULL; if ((p.xStatusMode & 8) && p.iProtoStatus > ID_STATUS_OFFLINE) { TCHAR str[512]; CUSTOM_STATUS cs = { sizeof(cs) }; cs.flags = CSSF_MASK_NAME | CSSF_TCHAR; cs.ptszName = str; if (CallProtoService(p.szAccountName, PS_GETCUSTOMSTATUSEX, 0, (LPARAM)&cs) == 0) p.tszProtoXStatus = mir_tstrdup(str); } if ((p.xStatusMode & 3)) { if (p.iProtoStatus > ID_STATUS_OFFLINE) { if (ProtoServiceExists(p.szAccountName, PS_GETCUSTOMSTATUSICON)) p.extraIcon = (HICON)ProtoCallService(p.szAccountName, PS_GETCUSTOMSTATUSICON, 0, 0); if (p.extraIcon && (p.xStatusMode & 3) == 3) w += GetSystemMetrics(SM_CXSMICON) + 1; } } } SIZE textSize; if (p.bShowProtoName) { GetTextExtentPoint32(hDC, p.tszProtoHumanName, lstrlen(p.tszProtoHumanName), &textSize); w += textSize.cx + 3 + spaceWidth; } if (p.bShowProtoEmails && p.szProtoEMailCount) { GetTextExtentPoint32A(hDC, p.szProtoEMailCount, lstrlenA(p.szProtoEMailCount), &textSize); w += textSize.cx + 3 + spaceWidth; } if (p.bShowStatusName) { GetTextExtentPoint32(hDC, p.tszProtoStatusText, lstrlen(p.tszProtoStatusText), &textSize); w += textSize.cx + 3 + spaceWidth; } if ((p.xStatusMode & 8) && p.tszProtoXStatus) { GetTextExtentPoint32(hDC, p.tszProtoXStatus, lstrlen(p.tszProtoXStatus), &textSize); w += textSize.cx + 3 + spaceWidth; } if (p.bShowProtoName || (p.bShowProtoEmails && p.szProtoEMailCount) || p.bShowStatusName || ((p.xStatusMode & 8) && p.tszProtoXStatus)) w -= spaceWidth; p.fullWidth = w; if (g_StatusBarData.sameWidth) { ProtoWidth[i] = sw; SumWidth += w; } else { ProtoWidth[i] = w; SumWidth += w; } } // Reposition rects for (i = 0; i < visProtoCount; i++) if (ProtoWidth[i] > maxwidth) maxwidth = ProtoWidth[i]; if (g_StatusBarData.sameWidth) { for (i = 0; i < visProtoCount; i++) ProtoWidth[i] = maxwidth; SumWidth = maxwidth * visProtoCount; } SumWidth += (visProtoCount - 1) * (g_StatusBarData.extraspace + 1); if (SumWidth > rectwidth) { float f = (float)rectwidth / SumWidth; SumWidth = 0; for (i = 0; i < visProtoCount; i++) { ProtoWidth[i] = (int)((float)ProtoWidth[i] * f); SumWidth += ProtoWidth[i]; } SumWidth += (visProtoCount - 1)*(g_StatusBarData.extraspace + 1); } if (g_StatusBarData.Align == 1) //center aligndx = (rectwidth - SumWidth) >> 1; else if (g_StatusBarData.Align == 2) //right aligndx = (rectwidth - SumWidth); // Draw in rects RECT r = rc; r.left += g_StatusBarData.rectBorders.left + aligndx; for (i = 0; i < visProtoCount; i++) { ProtoItemData& p = ProtosData[line*protosperline + i]; HRGN rgn; HICON hIcon = NULL; HICON hxIcon = NULL; BOOL NeedDestroy = FALSE; int x = r.left; x += p.PaddingLeft; r.right = r.left + ProtoWidth[i]; if (p.bShowProtoIcon) { if (p.iProtoStatus > ID_STATUS_OFFLINE && (p.xStatusMode & 3) > 0) { if (ProtoServiceExists(p.szAccountName, PS_GETCUSTOMSTATUSICON)) { hxIcon = p.extraIcon; if (hxIcon) { if ((p.xStatusMode & 3) == 2) { hIcon = GetMainStatusOverlay(p.iProtoStatus); NeedDestroy = TRUE; } else if ((p.xStatusMode & 3) == 1) { hIcon = hxIcon; NeedDestroy = TRUE; hxIcon = NULL; } } } } if (hIcon == NULL && (hxIcon == NULL || ((p.xStatusMode & 3) == 3))) { if ((p.bConnectingIcon == 1) && p.iProtoStatus >= ID_STATUS_CONNECTING && p.iProtoStatus <= ID_STATUS_CONNECTING + MAX_CONNECT_RETRIES) { hIcon = (HICON)CLUI_GetConnectingIconService((WPARAM)p.szAccountName, 0); if (hIcon) NeedDestroy = TRUE; else hIcon = LoadSkinnedProtoIcon(p.szAccountName, p.iProtoStatus); } else hIcon = LoadSkinnedProtoIcon(p.szAccountName, p.iProtoStatus); } rgn = CreateRectRgn(r.left, r.top, r.right, r.bottom); if (g_StatusBarData.sameWidth) { int fw = p.fullWidth; int rw = r.right - r.left; if (g_StatusBarData.Align == 1) x = r.left + ((rw - fw) / 2); else if (g_StatusBarData.Align == 2) x = r.left + ((rw - fw)); else x = r.left; } SelectClipRgn(hDC, rgn); p.bDoubleIcons = false; DWORD dim = p.bIsDimmed ? ((64 << 24) | 0x80) : 0; if ((p.xStatusMode & 3) == 3) { if (hIcon) mod_DrawIconEx_helper(hDC, x, iconY, hIcon, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0, NULL, DI_NORMAL | dim); if (hxIcon) { mod_DrawIconEx_helper(hDC, x + GetSystemMetrics(SM_CXSMICON) + 1, iconY, hxIcon, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0, NULL, DI_NORMAL | dim); x += GetSystemMetrics(SM_CXSMICON) + 1; } p.bDoubleIcons = hIcon && hxIcon; } else { if (hxIcon) mod_DrawIconEx_helper(hDC, x, iconY, hxIcon, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0, NULL, DI_NORMAL | dim); if (hIcon) mod_DrawIconEx_helper(hDC, x, iconY, hIcon, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0, NULL, DI_NORMAL | ((hxIcon && (p.xStatusMode & 4)) ? (192 << 24) : 0) | dim); } if (hxIcon || hIcon) { /* TODO g_StatusBarData.bDrawLockOverlay options to draw locked proto*/ if (db_get_b(NULL, p.szAccountName, "LockMainStatus", 0)) { HICON hLockOverlay = LoadSkinnedIcon(SKINICON_OTHER_STATUS_LOCKED); if (hLockOverlay != NULL) { mod_DrawIconEx_helper(hDC, x, iconY, hLockOverlay, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0, NULL, DI_NORMAL | dim); Skin_ReleaseIcon(hLockOverlay); } } } if (hxIcon) DestroyIcon_protect(hxIcon); if (NeedDestroy) DestroyIcon_protect(hIcon); else Skin_ReleaseIcon(hIcon); x += GetSystemMetrics(SM_CXSMICON) + 1; } if (p.bShowProtoName) { SIZE textSize; RECT rt = r; rt.left = x + (spaceWidth >> 1); rt.top = textY; ske_DrawText(hDC, p.tszProtoHumanName, lstrlen(p.tszProtoHumanName), &rt, 0); if ((p.bShowProtoEmails && p.szProtoEMailCount != NULL) || p.bShowStatusName || ((p.xStatusMode & 8) && p.tszProtoXStatus)) { GetTextExtentPoint32(hDC, p.tszProtoHumanName, lstrlen(p.tszProtoHumanName), &textSize); x += textSize.cx + 3; } } if (p.bShowProtoEmails && p.szProtoEMailCount != NULL) { SIZE textSize; RECT rt = r; rt.left = x + (spaceWidth >> 1); rt.top = textY; ske_DrawTextA(hDC, p.szProtoEMailCount, lstrlenA(p.szProtoEMailCount), &rt, 0); if (p.bShowStatusName || ((p.xStatusMode & 8) && p.tszProtoXStatus)) { GetTextExtentPoint32A(hDC, p.szProtoEMailCount, lstrlenA(p.szProtoEMailCount), &textSize); x += textSize.cx + 3; } }
static void test_tab(INT nMinTabWidth) { HWND hwTab; RECT rTab; HIMAGELIST himl = ImageList_Create(21, 21, ILC_COLOR, 3, 4); SIZE size; HDC hdc; HFONT hOldFont; INT i, dpi; hwTab = create_tabcontrol(TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE); SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth); /* Get System default MinTabWidth */ if (nMinTabWidth < 0) nMinTabWidth = SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth); hdc = GetDC(hwTab); dpi = GetDeviceCaps(hdc, LOGPIXELSX); hOldFont = SelectObject(hdc, (HFONT)SendMessage(hwTab, WM_GETFONT, 0, 0)); GetTextExtentPoint32A(hdc, "Tab 1", strlen("Tab 1"), &size); trace("Tab1 text size: size.cx=%d size.cy=%d\n", size.cx, size.cy); SelectObject(hdc, hOldFont); ReleaseDC(hwTab, hdc); trace (" TCS_FIXEDWIDTH tabs no icon...\n"); CheckSize(hwTab, dpi, -1, "default width"); TabCheckSetSize(hwTab, 50, 20, 50, 20, "set size"); TabCheckSetSize(hwTab, 0, 1, 0, 1, "min size"); SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl); trace (" TCS_FIXEDWIDTH tabs with icon...\n"); TabCheckSetSize(hwTab, 50, 30, 50, 30, "set size > icon"); TabCheckSetSize(hwTab, 20, 20, 25, 20, "set size < icon"); TabCheckSetSize(hwTab, 0, 1, 25, 1, "min size"); DestroyWindow (hwTab); hwTab = create_tabcontrol(TCS_FIXEDWIDTH | TCS_BUTTONS, TCIF_TEXT|TCIF_IMAGE); SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth); hdc = GetDC(hwTab); dpi = GetDeviceCaps(hdc, LOGPIXELSX); ReleaseDC(hwTab, hdc); trace (" TCS_FIXEDWIDTH buttons no icon...\n"); CheckSize(hwTab, dpi, -1, "default width"); TabCheckSetSize(hwTab, 20, 20, 20, 20, "set size 1"); TabCheckSetSize(hwTab, 10, 50, 10, 50, "set size 2"); TabCheckSetSize(hwTab, 0, 1, 0, 1, "min size"); SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl); trace (" TCS_FIXEDWIDTH buttons with icon...\n"); TabCheckSetSize(hwTab, 50, 30, 50, 30, "set size > icon"); TabCheckSetSize(hwTab, 20, 20, 25, 20, "set size < icon"); TabCheckSetSize(hwTab, 0, 1, 25, 1, "min size"); SendMessage(hwTab, TCM_SETPADDING, 0, MAKELPARAM(4,4)); TabCheckSetSize(hwTab, 0, 1, 25, 1, "set padding, min size"); DestroyWindow (hwTab); hwTab = create_tabcontrol(TCS_FIXEDWIDTH | TCS_BOTTOM, TCIF_TEXT|TCIF_IMAGE); SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth); hdc = GetDC(hwTab); dpi = GetDeviceCaps(hdc, LOGPIXELSX); ReleaseDC(hwTab, hdc); trace (" TCS_FIXEDWIDTH | TCS_BOTTOM tabs...\n"); CheckSize(hwTab, dpi, -1, "no icon, default width"); TabCheckSetSize(hwTab, 20, 20, 20, 20, "no icon, set size 1"); TabCheckSetSize(hwTab, 10, 50, 10, 50, "no icon, set size 2"); TabCheckSetSize(hwTab, 0, 1, 0, 1, "no icon, min size"); SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl); TabCheckSetSize(hwTab, 50, 30, 50, 30, "with icon, set size > icon"); TabCheckSetSize(hwTab, 20, 20, 25, 20, "with icon, set size < icon"); TabCheckSetSize(hwTab, 0, 1, 25, 1, "with icon, min size"); SendMessage(hwTab, TCM_SETPADDING, 0, MAKELPARAM(4,4)); TabCheckSetSize(hwTab, 0, 1, 25, 1, "set padding, min size"); DestroyWindow (hwTab); hwTab = create_tabcontrol(0, TCIF_TEXT|TCIF_IMAGE); SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth); trace (" non fixed width, with text...\n"); CheckSize(hwTab, max(size.cx +TAB_PADDING_X*2, (nMinTabWidth < 0) ? DEFAULT_MIN_TAB_WIDTH : nMinTabWidth), -1, "no icon, default width"); for (i=0; i<8; i++) { INT nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(i, 2) : nMinTabWidth; SendMessage(hwTab, TCM_SETIMAGELIST, 0, 0); SendMessage(hwTab, TCM_SETPADDING, 0, MAKELPARAM(i,i)); TabCheckSetSize(hwTab, 50, 20, max(size.cx + i*2, nTabWidth), 20, "no icon, set size"); TabCheckSetSize(hwTab, 0, 1, max(size.cx + i*2, nTabWidth), 1, "no icon, min size"); SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl); nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(i, 3) : nMinTabWidth; TabCheckSetSize(hwTab, 50, 30, max(size.cx + 21 + i*3, nTabWidth), 30, "with icon, set size > icon"); TabCheckSetSize(hwTab, 20, 20, max(size.cx + 21 + i*3, nTabWidth), 20, "with icon, set size < icon"); TabCheckSetSize(hwTab, 0, 1, max(size.cx + 21 + i*3, nTabWidth), 1, "with icon, min size"); } DestroyWindow (hwTab); hwTab = create_tabcontrol(0, TCIF_IMAGE); SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth); trace (" non fixed width, no text...\n"); CheckSize(hwTab, (nMinTabWidth < 0) ? DEFAULT_MIN_TAB_WIDTH : nMinTabWidth, -1, "no icon, default width"); for (i=0; i<8; i++) { INT nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(i, 2) : nMinTabWidth; SendMessage(hwTab, TCM_SETIMAGELIST, 0, 0); SendMessage(hwTab, TCM_SETPADDING, 0, MAKELPARAM(i,i)); TabCheckSetSize(hwTab, 50, 20, nTabWidth, 20, "no icon, set size"); TabCheckSetSize(hwTab, 0, 1, nTabWidth, 1, "no icon, min size"); SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl); if (i > 1 && nMinTabWidth > 0 && nMinTabWidth < DEFAULT_MIN_TAB_WIDTH) nTabWidth += EXTRA_ICON_PADDING *(i-1); TabCheckSetSize(hwTab, 50, 30, nTabWidth, 30, "with icon, set size > icon"); TabCheckSetSize(hwTab, 20, 20, nTabWidth, 20, "with icon, set size < icon"); TabCheckSetSize(hwTab, 0, 1, nTabWidth, 1, "with icon, min size"); } DestroyWindow (hwTab); ImageList_Destroy(himl); DeleteObject(hFont); }
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) { 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, (int)mir_strlen(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; }
void LoadClcOptions(HWND hwnd,struct ClcData *dat) { int i; // dat->rowHeight=DBGetContactSettingByte(NULL,"CLC","RowHeight",CLCDEFAULT_ROWHEIGHT); { LOGFONTA lf; HFONT holdfont; SIZE fontSize; HDC hdc=GetDC(hwnd); for(i=0;i<=FONTID_MAX;i++) { if(!dat->fontInfo[i].changed) DeleteObject(dat->fontInfo[i].hFont); GetFontSetting(i,&lf,&dat->fontInfo[i].colour); { LONG height; HDC hdc=GetDC(NULL); height=lf.lfHeight; lf.lfHeight=-MulDiv(lf.lfHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72); ReleaseDC(NULL,hdc); dat->fontInfo[i].hFont=CreateFontIndirectA(&lf); lf.lfHeight=height; } dat->fontInfo[i].changed=0; holdfont=SelectObject(hdc,dat->fontInfo[i].hFont); GetTextExtentPoint32A(hdc,"x",1,&fontSize); dat->fontInfo[i].fontHeight=fontSize.cy; // if(fontSize.cy>dat->rowHeight && (!DBGetContactSettingByte(NULL,"CLC","DoNotCheckFontSize",0))) dat->rowHeight=fontSize.cy; if(holdfont) SelectObject(hdc,holdfont); } ReleaseDC(hwnd,hdc); } // Row dat->row_min_heigh = DBGetContactSettingWord(NULL,"CList","MinRowHeight",CLCDEFAULT_ROWHEIGHT); dat->row_border = DBGetContactSettingWord(NULL,"CList","RowBorder",2); dat->row_variable_height = DBGetContactSettingByte(NULL,"CList","VariableRowHeight",1); dat->row_align_left_items_to_left = DBGetContactSettingByte(NULL,"CList","AlignLeftItemsToLeft",1); dat->row_hide_group_icon = DBGetContactSettingByte(NULL,"CList","HideGroupsIcon",0); dat->row_align_right_items_to_right = DBGetContactSettingByte(NULL,"CList","AlignRightItemsToRight",1); //TODO: Add to settings dat->row_align_group_mode=DBGetContactSettingByte(NULL,"CList","AlignGroupCaptions",0); for (i = 0 ; i < NUM_ITEM_TYPE ; i++) { char tmp[128]; mir_snprintf(tmp, sizeof(tmp), "RowPos%d", i); dat->row_items[i] = DBGetContactSettingWord(NULL, "CList", tmp, i); } // Avatar if (hwndContactTree == hwnd || hwndContactTree==NULL) { dat->avatars_show = DBGetContactSettingByte(NULL,"CList","AvatarsShow",0); dat->avatars_draw_border = DBGetContactSettingByte(NULL,"CList","AvatarsDrawBorders",0); dat->avatars_border_color = (COLORREF)DBGetContactSettingDword(NULL,"CList","AvatarsBorderColor",0); dat->avatars_round_corners = DBGetContactSettingByte(NULL,"CList","AvatarsRoundCorners",1); dat->avatars_use_custom_corner_size = DBGetContactSettingByte(NULL,"CList","AvatarsUseCustomCornerSize",0); dat->avatars_custom_corner_size = DBGetContactSettingWord(NULL,"CList","AvatarsCustomCornerSize",4); dat->avatars_ignore_size_for_row_height = DBGetContactSettingByte(NULL,"CList","AvatarsIgnoreSizeForRow",0); dat->avatars_draw_overlay = DBGetContactSettingByte(NULL,"CList","AvatarsDrawOverlay",0); dat->avatars_overlay_type = DBGetContactSettingByte(NULL,"CList","AvatarsOverlayType",SETTING_AVATAR_OVERLAY_TYPE_NORMAL); dat->avatars_size = DBGetContactSettingWord(NULL,"CList","AvatarsSize",30); } else { dat->avatars_show = 0; dat->avatars_draw_border = 0; dat->avatars_border_color = 0; dat->avatars_round_corners = 0; dat->avatars_use_custom_corner_size = 0; dat->avatars_custom_corner_size = 4; dat->avatars_ignore_size_for_row_height = 0; dat->avatars_draw_overlay = 0; dat->avatars_overlay_type = SETTING_AVATAR_OVERLAY_TYPE_NORMAL; dat->avatars_size = 30; } // Icon if (hwndContactTree == hwnd|| hwndContactTree==NULL) { dat->icon_hide_on_avatar = DBGetContactSettingByte(NULL,"CList","IconHideOnAvatar",0); dat->icon_draw_on_avatar_space = DBGetContactSettingByte(NULL,"CList","IconDrawOnAvatarSpace",0); dat->icon_ignore_size_for_row_height = DBGetContactSettingByte(NULL,"CList","IconIgnoreSizeForRownHeight",0); } else { dat->icon_hide_on_avatar = 0; dat->icon_draw_on_avatar_space = 0; dat->icon_ignore_size_for_row_height = 0; } // Contact time if (hwndContactTree == hwnd|| hwndContactTree==NULL) { dat->contact_time_show = DBGetContactSettingByte(NULL,"CList","ContactTimeShow",0); dat->contact_time_show_only_if_different = DBGetContactSettingByte(NULL,"CList","ContactTimeShowOnlyIfDifferent",1); } else { dat->contact_time_show = 0; dat->contact_time_show_only_if_different = 0; } { const time_t now = time(NULL); struct tm gmt = *gmtime(&now); time_t gmt_time; //gmt.tm_isdst = -1; gmt_time = mktime(&gmt); dat->local_gmt_diff = (int)difftime(now, gmt_time); gmt = *gmtime(&now); gmt.tm_isdst = -1; gmt_time = mktime(&gmt); dat->local_gmt_diff_dst = (int)difftime(now, gmt_time); } // Text dat->text_rtl = DBGetContactSettingByte(NULL,"CList","TextRTL",0); dat->text_align_right = DBGetContactSettingByte(NULL,"CList","TextAlignToRight",0); dat->text_replace_smileys = DBGetContactSettingByte(NULL,"CList","TextReplaceSmileys",1); dat->text_resize_smileys = DBGetContactSettingByte(NULL,"CList","TextResizeSmileys",1); dat->text_smiley_height = 0; dat->text_use_protocol_smileys = DBGetContactSettingByte(NULL,"CList","TextUseProtocolSmileys",1); if (hwndContactTree == hwnd|| hwndContactTree==NULL) { dat->text_ignore_size_for_row_height = DBGetContactSettingByte(NULL,"CList","TextIgnoreSizeForRownHeight",0); } else { dat->text_ignore_size_for_row_height = 0; } // First line dat->first_line_draw_smileys = DBGetContactSettingByte(NULL,"CList","FirstLineDrawSmileys",1); // Second line if (hwndContactTree == hwnd || hwndContactTree==NULL) { dat->second_line_show = DBGetContactSettingByte(NULL,"CList","SecondLineShow",1); dat->second_line_top_space = DBGetContactSettingWord(NULL,"CList","SecondLineTopSpace",2); dat->second_line_draw_smileys = DBGetContactSettingByte(NULL,"CList","SecondLineDrawSmileys",1); dat->second_line_type = DBGetContactSettingWord(NULL,"CList","SecondLineType",TEXT_STATUS_MESSAGE); { DBVARIANT dbv; if (!DBGetContactSettingTString(NULL, "CList","SecondLineText", &dbv)) { lstrcpyn(dat->second_line_text, dbv.ptszVal, SIZEOF(dat->second_line_text)-1); dat->second_line_text[SIZEOF(dat->second_line_text)-1] = '\0'; DBFreeVariant(&dbv); } else { dat->second_line_text[0] = '\0'; } } dat->second_line_xstatus_has_priority = DBGetContactSettingByte(NULL,"CList","SecondLineXStatusHasPriority",1); dat->second_line_show_status_if_no_away=DBGetContactSettingByte(NULL,"CList","SecondLineShowStatusIfNoAway",0); dat->second_line_use_name_and_message_for_xstatus = DBGetContactSettingByte(NULL,"CList","SecondLineUseNameAndMessageForXStatus",0); } else { dat->second_line_show = 0; dat->second_line_top_space = 0; dat->second_line_draw_smileys = 0; dat->second_line_type = TEXT_STATUS_MESSAGE; dat->second_line_text[0] = '\0'; dat->second_line_xstatus_has_priority = 1; dat->second_line_use_name_and_message_for_xstatus = 0; } // Third line if (hwndContactTree == hwnd || hwndContactTree==NULL) { dat->third_line_show = DBGetContactSettingByte(NULL,"CList","ThirdLineShow",0); dat->third_line_top_space = DBGetContactSettingWord(NULL,"CList","ThirdLineTopSpace",2); dat->third_line_draw_smileys = DBGetContactSettingByte(NULL,"CList","ThirdLineDrawSmileys",0); dat->third_line_type = DBGetContactSettingWord(NULL,"CList","ThirdLineType",TEXT_STATUS); { DBVARIANT dbv; if (!DBGetContactSettingTString(NULL, "CList","ThirdLineText", &dbv)) { lstrcpyn(dat->third_line_text, dbv.ptszVal, SIZEOF(dat->third_line_text)-1); dat->third_line_text[SIZEOF(dat->third_line_text)-1] = '\0'; DBFreeVariant(&dbv); } else { dat->third_line_text[0] = '\0'; } } dat->third_line_xstatus_has_priority = DBGetContactSettingByte(NULL,"CList","ThirdLineXStatusHasPriority",1); dat->third_line_show_status_if_no_away=DBGetContactSettingByte(NULL,"CList","ThirdLineShowStatusIfNoAway",0); dat->third_line_use_name_and_message_for_xstatus = DBGetContactSettingByte(NULL,"CList","ThirdLineUseNameAndMessageForXStatus",0); } else { dat->third_line_show = 0; dat->third_line_top_space = 0; dat->third_line_draw_smileys = 0; dat->third_line_type = TEXT_STATUS_MESSAGE; dat->third_line_text[0] = '\0'; dat->third_line_xstatus_has_priority = 1; dat->third_line_use_name_and_message_for_xstatus = 0; } dat->leftMargin=DBGetContactSettingByte(NULL,"CLC","LeftMargin",CLCDEFAULT_LEFTMARGIN); dat->rightMargin=DBGetContactSettingByte(NULL,"CLC","RightMargin",CLCDEFAULT_RIGHTMARGIN); dat->exStyle=DBGetContactSettingDword(NULL,"CLC","ExStyle",GetDefaultExStyle()); dat->scrollTime=DBGetContactSettingWord(NULL,"CLC","ScrollTime",CLCDEFAULT_SCROLLTIME); dat->force_in_dialog=0; dat->groupIndent=DBGetContactSettingByte(NULL,"CLC","GroupIndent",CLCDEFAULT_GROUPINDENT); dat->subIndent=DBGetContactSettingByte(NULL,"CLC","SubIndent",CLCDEFAULT_GROUPINDENT); dat->gammaCorrection=DBGetContactSettingByte(NULL,"CLC","GammaCorrect",CLCDEFAULT_GAMMACORRECT); dat->showIdle=DBGetContactSettingByte(NULL,"CLC","ShowIdle",CLCDEFAULT_SHOWIDLE); dat->noVScrollbar=DBGetContactSettingByte(NULL,"CLC","NoVScrollBar",0); SendMessage(hwnd,INTM_SCROLLBARCHANGED,0,0); //ShowScrollBar(hwnd,SB_VERT,dat->noVScrollbar==1 ? FALSE : TRUE); if(!dat->bkChanged) { DBVARIANT dbv; dat->bkColour=DBGetContactSettingDword(NULL,"CLC","BkColour",CLCDEFAULT_BKCOLOUR); if(dat->hBmpBackground) {DeleteObject(dat->hBmpBackground); dat->hBmpBackground=NULL;} if(DBGetContactSettingByte(NULL,"CLC","UseBitmap",CLCDEFAULT_USEBITMAP)) { if(!DBGetContactSetting(NULL,"CLC","BkBitmap",&dbv)) { dat->hBmpBackground=(HBITMAP)CallService(MS_UTILS_LOADBITMAP,0,(LPARAM)dbv.pszVal); mir_free(dbv.pszVal); DBFreeVariant(&dbv); } } dat->backgroundBmpUse=DBGetContactSettingWord(NULL,"CLC","BkBmpUse",CLCDEFAULT_BKBMPUSE); dat->MenuBkColor=DBGetContactSettingDword(NULL,"Menu","BkColour",CLCDEFAULT_BKCOLOUR); dat->MenuBkHiColor=DBGetContactSettingDword(NULL,"Menu","SelBkColour",CLCDEFAULT_SELBKCOLOUR); dat->MenuTextColor=DBGetContactSettingDword(NULL,"Menu","TextColour",CLCDEFAULT_TEXTCOLOUR); dat->MenuTextHiColor=DBGetContactSettingDword(NULL,"Menu","SelTextColour",CLCDEFAULT_SELTEXTCOLOUR); if (dat->hMenuBackground) {DeleteObject(dat->hMenuBackground); dat->hMenuBackground=NULL;} if(DBGetContactSettingByte(NULL,"Menu","UseBitmap",CLCDEFAULT_USEBITMAP)) { if(!DBGetContactSetting(NULL,"Menu","BkBitmap",&dbv)) { dat->hMenuBackground=(HBITMAP)CallService(MS_UTILS_LOADBITMAP,0,(LPARAM)dbv.pszVal); mir_free(dbv.pszVal); DBFreeVariant(&dbv); } } dat->MenuBmpUse=DBGetContactSettingWord(NULL,"Menu","BkBmpUse",CLCDEFAULT_BKBMPUSE); } dat->greyoutFlags=DBGetContactSettingDword(NULL,"CLC","GreyoutFlags",CLCDEFAULT_GREYOUTFLAGS); dat->offlineModes=DBGetContactSettingDword(NULL,"CLC","OfflineModes",CLCDEFAULT_OFFLINEMODES); dat->selBkColour=DBGetContactSettingDword(NULL,"CLC","SelBkColour",CLCDEFAULT_SELBKCOLOUR); dat->selTextColour=DBGetContactSettingDword(NULL,"CLC","SelTextColour",CLCDEFAULT_SELTEXTCOLOUR); dat->hotTextColour=DBGetContactSettingDword(NULL,"CLC","HotTextColour",CLCDEFAULT_HOTTEXTCOLOUR); dat->quickSearchColour=DBGetContactSettingDword(NULL,"CLC","QuickSearchColour",CLCDEFAULT_QUICKSEARCHCOLOUR); dat->IsMetaContactsEnabled= DBGetContactSettingByte(NULL,"MetaContacts","Enabled",1) && ServiceExists(MS_MC_GETDEFAULTCONTACT); { dat->MetaIgnoreEmptyExtra=DBGetContactSettingByte(NULL,"CLC","MetaIgnoreEmptyExtra",1); dat->expandMeta=DBGetContactSettingByte(NULL,"CLC","MetaExpanding",1); /* style=GetWindowLong(hwnd,GWL_STYLE); if (dat->MetaIgnoreEmptyExtra) style&=CLS_EX_MULTICOLUMNALIGNLEFT; else style&=!(CLS_EX_MULTICOLUMNALIGNLEFT) */ } { NMHDR hdr; hdr.code=CLN_OPTIONSCHANGED; hdr.hwndFrom=hwnd; hdr.idFrom=GetDlgCtrlID(hwnd); SendMessage(GetParent(hwnd),WM_NOTIFY,0,(LPARAM)&hdr); } SendMessage(hwnd,WM_SIZE,0,0); }
HRESULT cFont::InitDeviceObjects(LPDIRECT3DDEVICE9 pDevice) { HRESULT hr; this->m_pDevice= pDevice; m_fTextScale = 1.0f; if (dwFontHeight > 40)dwWidth = dwHeight = 1024; else if (dwFontHeight > 20)dwWidth = dwHeight = 512; else dwWidth = dwHeight = 256; D3DCAPS9 d3dCaps; pDevice->GetDeviceCaps(&d3dCaps); if (dwWidth > d3dCaps.MaxTextureWidth) { m_fTextScale = (FLOAT)d3dCaps.MaxTextureWidth / (FLOAT)dwWidth; dwWidth =dwHeight = d3dCaps.MaxTextureWidth; } hr = pDevice->CreateTexture(dwWidth, dwHeight, 1,0, D3DFMT_A4R4G4B4,D3DPOOL_MANAGED, &m_pTexture, 0); if (FAILED(hr))return hr; DWORD* pBitmapBits; BITMAPINFO bmi; ZeroMemory(&bmi.bmiHeader, sizeof(BITMAPINFOHEADER)); bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biWidth = (int)dwWidth; bmi.bmiHeader.biHeight = -(int)dwHeight; bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biCompression = BI_RGB; bmi.bmiHeader.biBitCount = 32; HDC hDC = CreateCompatibleDC(NULL); HBITMAP hbmBitmap = CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, (void**)&pBitmapBits, NULL, 0); SetMapMode(hDC, MM_TEXT); INT nHeight = -MulDiv(dwFontHeight, (INT)(GetDeviceCaps(hDC, LOGPIXELSY) * m_fTextScale), 72); DWORD dwBold = (dwFontFlags & D3DFONT_BOLD) ? FW_EXTRABOLD : FW_NORMAL; DWORD dwItalic = (dwFontFlags & D3DFONT_ITALIC) ? TRUE : FALSE; HFONT hFont = CreateFont(nHeight, 0, 0, 0, dwBold, dwItalic, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, VARIABLE_PITCH, strFontName); if (NULL == hFont) return E_FAIL; HGDIOBJ hPrevBitmap = SelectObject(hDC, hbmBitmap); HGDIOBJ hPrevFont = SelectObject(hDC, hFont); SetTextColor(hDC, RGB(255, 255, 255)); SetBkColor(hDC, 0x00000000); SetTextAlign(hDC, TA_TOP); DWORD x = 0; DWORD y = 0; char str[2] = "x"; SIZE size; for (int c = 32; c <= MAX_CHAR_INDEX; c++) { str[0] = c; GetTextExtentPoint32A(hDC, str, 1, &size); if ((DWORD)(x + size.cx + 1) > dwWidth) { x = 0; y += size.cy + 1; } ExtTextOutA(hDC, x + 0, y + 0, ETO_OPAQUE, NULL, str, 1, NULL); m_fTexCoords[c - 32][0] = ((FLOAT)(x + 0)) / dwWidth; m_fTexCoords[c - 32][1] = ((FLOAT)(y + 0)) / dwWidth; m_fTexCoords[c - 32][2] = ((FLOAT)(x + 0 + size.cx)) / dwWidth; m_fTexCoords[c - 32][3] = ((FLOAT)(y + 0 + size.cy)) / dwWidth; x += size.cx + 1; } D3DLOCKED_RECT d3dlr; m_pTexture->LockRect(0, &d3dlr, 0, 0); BYTE* pDstRow = (BYTE*)d3dlr.pBits; WORD* pDst16; BYTE bAlpha; for (y = 0; y < dwHeight; y++) { pDst16 = (WORD*)pDstRow; for (x = 0; x < dwWidth; x++) { bAlpha = (BYTE)((pBitmapBits[dwWidth*y + x] & 0xff) >> 4); if (bAlpha > 0) { *pDst16++ = (bAlpha << 12) | 0x0fff; } else { *pDst16++ = 0x0000; } } pDstRow += d3dlr.Pitch; } m_pTexture->UnlockRect(0); SelectObject(hDC, hPrevBitmap); SelectObject(hDC, hPrevFont); DeleteObject(hbmBitmap); DeleteDC(hDC); DeleteObject(hFont); return S_OK; }