void CreateToc(WindowInfo *win) { win->hwndTocBox = CreateWindow(WC_STATIC, L"", WS_CHILD|WS_CLIPCHILDREN, 0, 0, gGlobalPrefs->sidebarDx, 0, win->hwndFrame, (HMENU)0, GetModuleHandle(nullptr), nullptr); LabelWithCloseWnd *l = CreateLabelWithCloseWnd(win->hwndTocBox, IDC_TOC_LABEL_WITH_CLOSE); win->tocLabelWithClose = l; SetPaddingXY(l, 2, 2); SetFont(l, GetDefaultGuiFont()); // label is set in UpdateToolbarSidebarText() win->hwndTocTree = CreateWindowEx(WS_EX_STATICEDGE, WC_TREEVIEW, L"TOC", TVS_HASBUTTONS|TVS_HASLINES|TVS_LINESATROOT|TVS_SHOWSELALWAYS| TVS_TRACKSELECT|TVS_DISABLEDRAGDROP|TVS_NOHSCROLL|TVS_INFOTIP| WS_TABSTOP|WS_VISIBLE|WS_CHILD, 0, 0, 0, 0, win->hwndTocBox, (HMENU)IDC_TOC_TREE, GetModuleHandle(nullptr), nullptr); TreeView_SetUnicodeFormat(win->hwndTocTree, true); if (nullptr == DefWndProcTocTree) DefWndProcTocTree = (WNDPROC)GetWindowLongPtr(win->hwndTocTree, GWLP_WNDPROC); SetWindowLongPtr(win->hwndTocTree, GWLP_WNDPROC, (LONG_PTR)WndProcTocTree); if (nullptr == DefWndProcTocBox) DefWndProcTocBox = (WNDPROC)GetWindowLongPtr(win->hwndTocBox, GWLP_WNDPROC); SetWindowLongPtr(win->hwndTocBox, GWLP_WNDPROC, (LONG_PTR)WndProcTocBox); }
void CreateFavorites(WindowInfo* win) { HMODULE h = GetModuleHandleW(nullptr); int dx = gGlobalPrefs->sidebarDx; DWORD dwStyle = WS_CHILD | WS_CLIPCHILDREN; win->hwndFavBox = CreateWindowW(WC_STATIC, L"", dwStyle, 0, 0, dx, 0, win->hwndFrame, (HMENU)0, h, nullptr); LabelWithCloseWnd* l = CreateLabelWithCloseWnd(win->hwndFavBox, IDC_FAV_LABEL_WITH_CLOSE); win->favLabelWithClose = l; SetPaddingXY(l, 2, 2); SetFont(l, GetDefaultGuiFont()); // label is set in UpdateToolbarSidebarText() dwStyle = TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | TVS_SHOWSELALWAYS | TVS_TRACKSELECT | TVS_DISABLEDRAGDROP | TVS_NOHSCROLL | TVS_INFOTIP | WS_TABSTOP | WS_VISIBLE | WS_CHILD; win->hwndFavTree = CreateWindowExW(WS_EX_STATICEDGE, WC_TREEVIEW, L"Fav", dwStyle, 0, 0, 0, 0, win->hwndFavBox, (HMENU)IDC_FAV_TREE, h, nullptr); TreeView_SetUnicodeFormat(win->hwndFavTree, true); if (nullptr == DefWndProcFavTree) { DefWndProcFavTree = (WNDPROC)GetWindowLongPtr(win->hwndFavTree, GWLP_WNDPROC); } SetWindowLongPtr(win->hwndFavTree, GWLP_WNDPROC, (LONG_PTR)WndProcFavTree); if (nullptr == DefWndProcFavBox) { DefWndProcFavBox = (WNDPROC)GetWindowLongPtr(win->hwndFavBox, GWLP_WNDPROC); } SetWindowLongPtr(win->hwndFavBox, GWLP_WNDPROC, (LONG_PTR)WndProcFavBox); }
bool CreateEditCtrl(EditCtrl *w) { // Note: has to remember this here because when I GetWindowStyle() later on, // WS_BORDER is not set, which is a mystery, because it is being drawn. // also, WS_BORDER seems to be painted in client areay w->hasBorder = bit::IsMaskSet<DWORD>(w->dwStyle, WS_BORDER); RECT rc = w->initialPos; w->hwnd = CreateWindowExW(w->dwExStyle, WC_EDIT, L"", w->dwStyle, rc.left, rc.top, RectDx(rc), RectDy(rc), w->parent, nullptr, GetModuleHandleW(nullptr), nullptr); if (!w->hwnd) { return false; } SetFont(w, GetDefaultGuiFont()); SetWindowSubclass(w->hwnd, EditProc, 0, (DWORD_PTR)w); SetWindowSubclass(GetParent(w->hwnd), EditParentProc, 0, (DWORD_PTR)w); return true; }
bool TreeCtrl::Create(const WCHAR* title) { if (!title) { title = L""; } RECT rc = this->initialPos; HMODULE hmod = GetModuleHandleW(nullptr); this->hwnd = CreateWindowExW(this->dwExStyle, WC_TREEVIEWW, title, this->dwStyle, rc.left, rc.top, RectDx(rc), RectDy(rc), this->parent, this->menu, hmod, nullptr); if (!this->hwnd) { return false; } TreeView_SetUnicodeFormat(this->hwnd, true); this->SetFont(GetDefaultGuiFont()); Subclass(this); return true; }
void CreateTabbar(WindowInfo* win) { DWORD dwStyle = WS_CHILD | WS_CLIPSIBLINGS /*| WS_VISIBLE*/ | TCS_FOCUSNEVER | TCS_FIXEDWIDTH | TCS_FORCELABELLEFT; DWORD dwStyleEx = 0; auto h = GetModuleHandleW(nullptr); HWND hwndTabBar = CreateWindowExW(dwStyleEx, WC_TABCONTROL, L"", dwStyle, 0, 0, 0, 0, win->hwndFrame, (HMENU)IDC_TABBAR, h, nullptr); SetWindowSubclass(hwndTabBar, TabBarProc, 0, (DWORD_PTR)win); SetWindowSubclass(GetParent(hwndTabBar), TabBarParentProc, 0, (DWORD_PTR)win); SizeI tabSize = GetTabSize(win->hwndFrame); TabPainter* tp = new TabPainter(hwndTabBar, tabSize); SetWindowLongPtr(hwndTabBar, GWLP_USERDATA, (LONG_PTR)tp); SetWindowFont(hwndTabBar, GetDefaultGuiFont(), FALSE); TabCtrl_SetItemSize(hwndTabBar, tabSize.dx, tabSize.dy); win->hwndTabBar = hwndTabBar; win->tabSelectionHistory = new Vec<TabInfo*>(); }
bool CreateFrameRateWnd(FrameRateWnd *w) { // WS_POPUP removes all decorations DWORD dwStyle = WS_POPUP | WS_VISIBLE | WS_DISABLED; RECT r = GetClientRect(w->hwndAssociatedWith); // since this is WS_POPUP window, providing w->hwndAssocatedWith doesn't establish // parent-child relationship but ownership relationship (as long as hwndAssociatedWith // is WS_OVERLAPEPED or WS_POPUP). Owned window always shows up on top of owner in z-order // http://msdn.microsoft.com/en-us/library/ms632599%28v=VS.85%29.aspx#owned_windows HWND hwnd = CreateWindowEx(WS_EX_LAYERED, FRAME_RATE_CLASS_NAME, NULL, dwStyle, 0, 0, 0, 0, w->hwndAssociatedWith, NULL, GetModuleHandle(NULL), w); CrashIf(hwnd != w->hwnd); if (!hwnd) { return false; } w->font = GetDefaultGuiFont(); SetWindowSubclass(w->hwndAssociatedWith, WndProcFrameRateAssociated, 0, (DWORD_PTR) w); SetLayeredWindowAttributes(hwnd, 0, 0x7f, LWA_ALPHA); ShowFrameRate(w, 0); return true; }
void CreateTabbar(WindowInfo *win) { HWND hwndTabBar = CreateWindow(WC_TABCONTROL, L"", WS_CHILD | WS_CLIPSIBLINGS /*| WS_VISIBLE*/ | TCS_FOCUSNEVER | TCS_FIXEDWIDTH | TCS_FORCELABELLEFT, 0, 0, 0, 0, win->hwndFrame, (HMENU)IDC_TABBAR, GetModuleHandle(nullptr), nullptr); if (!DefWndProcTabBar) DefWndProcTabBar = (WNDPROC)GetWindowLongPtr(hwndTabBar, GWLP_WNDPROC); SetWindowLongPtr(hwndTabBar, GWLP_WNDPROC, (LONG_PTR)WndProcTabBar); SizeI tabSize = GetTabSize(win->hwndFrame); TabPainter *tp = new TabPainter(hwndTabBar, tabSize); SetWindowLongPtr(hwndTabBar, GWLP_USERDATA, (LONG_PTR)tp); SetWindowFont(hwndTabBar, GetDefaultGuiFont(), FALSE); TabCtrl_SetItemSize(hwndTabBar, tabSize.dx, tabSize.dy); win->hwndTabBar = hwndTabBar; win->tabSelectionHistory = new Vec<TabInfo *>(); }
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { int retCode = 1; // by default it's error #ifdef DEBUG // Memory leak detection (only enable _CRTDBG_LEAK_CHECK_DF for // regular termination so that leaks aren't checked on exceptions, // aborts, etc. where some clean-up might not take place) _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF); //_CrtSetBreakAlloc(421); TryLoadMemTrace(); #endif DisableDataExecution(); // ensure that C functions behave consistently under all OS locales // (use Win32 functions where localized input or output is desired) setlocale(LC_ALL, "C"); // don't show system-provided dialog boxes when accessing files on drives // that are not mounted (e.g. a: drive without floppy or cd rom drive // without a cd). SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS); #if defined(DEBUG) || defined(SVN_PRE_RELEASE_VER) if (str::StartsWith(lpCmdLine, "/tester")) { extern int TesterMain(); // in Tester.cpp return TesterMain(); } if (str::StartsWith(lpCmdLine, "/regress")) { extern int RegressMain(); // in Regress.cpp return RegressMain(); } #endif #ifdef SUPPORTS_AUTO_UPDATE if (str::StartsWith(lpCmdLine, "-autoupdate")) { bool quit = AutoUpdateMain(); if (quit) return 0; } #endif srand((unsigned int)time(NULL)); // load uiautomationcore.dll before installing crash handler (i.e. initializing // dbghelp.dll), so that we get function names/offsets in GetCallstack() uia::Initialize(); #ifdef DEBUG dbghelp::RememberCallstackLogs(); #endif SetupCrashHandler(); ScopedOle ole; InitAllCommonControls(); ScopedGdiPlus gdiPlus(true); mui::Initialize(); uitask::Initialize(); prefs::Load(); CommandLineInfo i(GetCommandLine()); SetCurrentLang(i.lang ? i.lang : gGlobalPrefs->uiLanguage); // This allows ad-hoc comparison of gdi, gdi+ and gdi+ quick when used // in layout #if 0 RedirectIOToConsole(); BenchEbookLayout(L"C:\\kjk\\downloads\\pg12.mobi"); system("pause"); goto Exit; #endif if (i.showConsole) { RedirectIOToConsole(); RedirectDllIOToConsole(); } if (i.makeDefault) AssociateExeWithPdfExtension(); if (i.pathsToBenchmark.Count() > 0) { BenchFileOrDir(i.pathsToBenchmark); if (i.showConsole) system("pause"); } if (i.exitImmediately) goto Exit; gCrashOnOpen = i.crashOnOpen; gPolicyRestrictions = GetPolicies(i.restrictedUse); GetFixedPageUiColors(gRenderCache.textColor, gRenderCache.backgroundColor); DebugGdiPlusDevice(gUseGdiRenderer); if (!RegisterWinClass()) goto Exit; CrashIf(hInstance != GetModuleHandle(NULL)); if (!InstanceInit(nCmdShow)) goto Exit; if (i.hwndPluginParent) { if (!SetupPluginMode(i)) goto Exit; } if (i.printerName) { // note: this prints all PDF files. Another option would be to // print only the first one for (size_t n = 0; n < i.fileNames.Count(); n++) { bool ok = PrintFile(i.fileNames.At(n), i.printerName, !i.silent, i.printSettings); if (!ok) retCode++; } --retCode; // was 1 if no print failures, turn 1 into 0 goto Exit; } bool showStartPage = i.fileNames.Count() == 0 && gGlobalPrefs->rememberOpenedFiles && gGlobalPrefs->showStartPage; if (showStartPage) { // make the shell prepare the image list, so that it's ready when the first window's loaded SHFILEINFO sfi; SHGetFileInfo(L".pdf", 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_USEFILEATTRIBUTES); } if (gGlobalPrefs->reopenOnce) { WStrVec moreFileNames; ParseCmdLine(gGlobalPrefs->reopenOnce, moreFileNames); moreFileNames.Reverse(); for (WCHAR **fileName = moreFileNames.IterStart(); fileName; fileName = moreFileNames.IterNext()) { i.fileNames.Append(*fileName); } moreFileNames.RemoveAt(0, moreFileNames.Count()); str::ReplacePtr(&gGlobalPrefs->reopenOnce, NULL); } HANDLE hMutex = NULL; HWND hPrevWnd = NULL; if (i.printDialog || i.stressTestPath || gPluginMode) { // TODO: pass print request through to previous instance? } else if (i.reuseDdeInstance) { hPrevWnd = FindWindow(FRAME_CLASS_NAME, NULL); } else if (gGlobalPrefs->reuseInstance || gGlobalPrefs->useTabs) { hPrevWnd = FindPrevInstWindow(&hMutex); } if (hPrevWnd) { for (size_t n = 0; n < i.fileNames.Count(); n++) { OpenUsingDde(hPrevWnd, i.fileNames.At(n), i, 0 == n); } goto Exit; } WindowInfo *win = NULL; for (size_t n = 0; n < i.fileNames.Count(); n++) { win = LoadOnStartup(i.fileNames.At(n), i, !win); if (!win) { retCode++; continue; } if (i.printDialog) OnMenuPrint(win, i.exitWhenDone); } if (i.fileNames.Count() > 0 && !win) { // failed to create any window, even though there // were files to load (or show a failure message for) goto Exit; } if (i.printDialog && i.exitWhenDone) goto Exit; if (!win) { win = CreateAndShowWindowInfo(); if (!win) goto Exit; } UpdateUITextForLanguage(); // needed for RTL languages if (win->IsAboutWindow()) { // TODO: shouldn't CreateAndShowWindowInfo take care of this? UpdateToolbarAndScrollbarState(*win); } // Make sure that we're still registered as default, // if the user has explicitly told us to be if (gGlobalPrefs->associatedExtensions) RegisterForPdfExtentions(win->hwndFrame); if (i.stressTestPath) { // don't save file history and preference changes gPolicyRestrictions = (gPolicyRestrictions | Perm_RestrictedUse) & ~Perm_SavePreferences; RebuildMenuBarForWindow(win); StartStressTest(&i, win, &gRenderCache); } if (gGlobalPrefs->checkForUpdates) UpdateCheckAsync(win, true); // only hide newly missing files when showing the start page on startup if (showStartPage && gFileHistory.Get(0)) { gFileExistenceChecker = new FileExistenceChecker(); gFileExistenceChecker->Start(); } // call this once it's clear whether Perm_SavePreferences has been granted prefs::RegisterForFileChanges(); retCode = RunMessageLoop(); SafeCloseHandle(&hMutex); CleanUpThumbnailCache(gFileHistory); Exit: prefs::UnregisterForFileChanges(); while (gWindows.Count() > 0) { DeleteWindowInfo(gWindows.At(0)); } #ifndef DEBUG // leave all the remaining clean-up to the OS // (as recommended for a quick exit) ExitProcess(retCode); #else DeleteObject(GetDefaultGuiFont()); DeleteBitmap(gBitmapReloadingCue); DeleteSplitterBrush(); // wait for FileExistenceChecker to terminate // (which should be necessary only very rarely) while (gFileExistenceChecker) { Sleep(10); uitask::DrainQueue(); } mui::Destroy(); uitask::Destroy(); trans::Destroy(); SaveCallstackLogs(); dbghelp::FreeCallstackLogs(); // must be after uitask::Destroy() because we might have queued prefs::Reload() // which crashes if gGlobalPrefs is freed gFileHistory.UpdateStatesSource(NULL); DeleteGlobalPrefs(gGlobalPrefs); // it's still possible to crash after this (destructors of static classes, // atexit() code etc.) point, but it's very unlikely UninstallCrashHandler(); // output leaks after all destructors of static objects have run _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); return retCode; #endif }
// Paints the tabs that intersect the window's update rectangle. void Paint(HDC hdc, RECT &rc) { IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom); // paint the background bool isTranslucentMode = inTitlebar && dwm::IsCompositionEnabled(); if (isTranslucentMode) PaintParentBackground(hwnd, hdc); else { HBRUSH brush = CreateSolidBrush(color.bar); FillRect(hdc, &rc, brush); DeleteObject(brush); } // TODO: GDI+ doesn't seem to cope well with SetWorldTransform XFORM ctm = { 1.0, 0, 0, 1.0, 0, 0 }; SetWorldTransform(hdc, &ctm); Graphics graphics(hdc); graphics.SetCompositingMode(CompositingModeSourceCopy); graphics.SetCompositingQuality(CompositingQualityHighQuality); graphics.SetSmoothingMode(SmoothingModeHighQuality); graphics.SetTextRenderingHint(TextRenderingHintClearTypeGridFit); graphics.SetPageUnit(UnitPixel); GraphicsPath shapes(data->Points, data->Types, data->Count); GraphicsPath shape; GraphicsPathIterator iterator(&shapes); SolidBrush br(Color(0, 0, 0)); Pen pen(&br, 2.0f); Font f(hdc, GetDefaultGuiFont()); // TODO: adjust these constant values for DPI? RectF layout((REAL)DpiScaleX(hwnd,3), 1.0f, REAL(width - DpiScaleX(hwnd,20)), (REAL)height); StringFormat sf(StringFormat::GenericDefault()); sf.SetFormatFlags(StringFormatFlagsNoWrap); sf.SetLineAlignment(StringAlignmentCenter); sf.SetTrimming(StringTrimmingEllipsisCharacter); REAL yPosTab = inTitlebar ? 0.0f : REAL(ClientRect(hwnd).dy - height - 1); for (int i = 0; i < Count(); i++) { graphics.ResetTransform(); graphics.TranslateTransform(1.f + (REAL)(width + 1) * i - (REAL)rc.left, yPosTab - (REAL)rc.top); if (!graphics.IsVisible(0, 0, width + 1, height + 1)) continue; // in firefox style we only paint current and highlighed tabs // all other tabs only show bool onlyText = g_FirefoxStyle && !((current == i) || (highlighted == i)); if (onlyText) { #if 0 // we need to first paint the background with the same color as caption, // otherwise the text looks funny (because is transparent?) // TODO: what is the damn bg color of caption? bar is too light, outline is too dark Color bgColTmp; bgColTmp.SetFromCOLORREF(color.bar); { SolidBrush bgBr(bgColTmp); graphics.FillRectangle(&bgBr, layout); } bgColTmp.SetFromCOLORREF(color.outline); { SolidBrush bgBr(bgColTmp); graphics.FillRectangle(&bgBr, layout); } #endif // TODO: this is a hack. If I use no background and cleartype, the // text looks funny (is bold). // CompositingModeSourceCopy doesn't work with clear type // another option is to draw background before drawing text, but // I can't figure out what is the actual color of caption graphics.SetTextRenderingHint(TextRenderingHintAntiAliasGridFit); graphics.SetCompositingMode(CompositingModeSourceCopy); //graphics.SetCompositingMode(CompositingModeSourceOver); br.SetColor(ToColor(color.text)); graphics.DrawString(text.At(i), -1, &f, layout, &sf, &br); graphics.SetTextRenderingHint(TextRenderingHintClearTypeGridFit); continue; } COLORREF bgCol = color.background;; if (current == i) { bgCol = color.current; } else if (highlighted == i) { bgCol = color.highlight; } // ensure contrast between text and background color // TODO: adjust threshold (and try adjusting both current/background tabs) COLORREF textCol = color.text; float bgLight = GetLightness(bgCol), textLight = GetLightness(textCol); if (textLight < bgLight ? bgLight < 0x70 : bgLight > 0x90) textCol = textLight ? AdjustLightness(textCol, 255.0f / textLight - 1.0f) : RGB(255, 255, 255); if (fabs(textLight - bgLight) < 0x40) textCol = bgLight < 0x80 ? RGB(255, 255, 255) : RGB(0, 0, 0); // paint tab's body graphics.SetCompositingMode(CompositingModeSourceCopy); iterator.NextMarker(&shape); br.SetColor(ToColor(bgCol)); graphics.FillPath(&br, &shape); // draw tab's text graphics.SetCompositingMode(CompositingModeSourceOver); br.SetColor(ToColor(textCol)); graphics.DrawString(text.At(i), -1, &f, layout, &sf, &br); // paint "x"'s circle iterator.NextMarker(&shape); if (xClicked == i || xHighlighted == i) { br.SetColor(ToColor(i == xClicked ? color.x_click : color.x_highlight)); graphics.FillPath(&br, &shape); } // paint "x" iterator.NextMarker(&shape); if (xClicked == i || xHighlighted == i) pen.SetColor(ToColor(color.x_line)); else pen.SetColor(ToColor(color.outline)); graphics.DrawPath(&pen, &shape); iterator.Rewind(); } }
// Paints the tabs that intersect the window's update rectangle. void Paint(HDC hdc, RECT& rc) { IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom); // paint the background #if 0 bool isTranslucentMode = inTitlebar && dwm::IsCompositionEnabled(); if (isTranslucentMode) { PaintParentBackground(hwnd, hdc); } else { // note: not sure what color should be used here and painting // background works fine /*HBRUSH brush = CreateSolidBrush(colors.bar); FillRect(hdc, &rc, brush); DeleteObject(brush);*/ } #else PaintParentBackground(hwnd, hdc); #endif // TODO: GDI+ doesn't seem to cope well with SetWorldTransform XFORM ctm = {1.0, 0, 0, 1.0, 0, 0}; SetWorldTransform(hdc, &ctm); Graphics gfx(hdc); gfx.SetCompositingMode(CompositingModeSourceCopy); gfx.SetCompositingQuality(CompositingQualityHighQuality); gfx.SetSmoothingMode(SmoothingModeHighQuality); gfx.SetTextRenderingHint(TextRenderingHintClearTypeGridFit); gfx.SetPageUnit(UnitPixel); GraphicsPath shapes(data->Points, data->Types, data->Count); GraphicsPath shape; GraphicsPathIterator iterator(&shapes); SolidBrush br(Color(0, 0, 0)); Pen pen(&br, 2.0f); Font f(hdc, GetDefaultGuiFont()); // TODO: adjust these constant values for DPI? RectF layout((REAL)DpiScaleX(hwnd, 3), 1.0f, REAL(width - DpiScaleX(hwnd, 20)), (REAL)height); StringFormat sf(StringFormat::GenericDefault()); sf.SetFormatFlags(StringFormatFlagsNoWrap); sf.SetLineAlignment(StringAlignmentCenter); sf.SetTrimming(StringTrimmingEllipsisCharacter); REAL yPosTab = inTitlebar ? 0.0f : REAL(ClientRect(hwnd).dy - height - 1); for (int i = 0; i < Count(); i++) { gfx.ResetTransform(); gfx.TranslateTransform(1.f + (REAL)(width + 1) * i - (REAL)rc.left, yPosTab - (REAL)rc.top); if (!gfx.IsVisible(0, 0, width + 1, height + 1)) continue; // Get the correct colors based on the state and the current theme COLORREF bgCol = GetAppColor(AppColor::TabBackgroundBg); COLORREF textCol = GetAppColor(AppColor::TabBackgroundText); COLORREF xColor = GetAppColor(AppColor::TabBackgroundCloseX); COLORREF circleColor = GetAppColor(AppColor::TabBackgroundCloseCircle); if (selectedTabIdx == i) { bgCol = GetAppColor(AppColor::TabSelectedBg); textCol = GetAppColor(AppColor::TabSelectedText); xColor = GetAppColor(AppColor::TabSelectedCloseX); circleColor = GetAppColor(AppColor::TabSelectedCloseCircle); } else if (highlighted == i) { bgCol = GetAppColor(AppColor::TabHighlightedBg); textCol = GetAppColor(AppColor::TabHighlightedText); xColor = GetAppColor(AppColor::TabHighlightedCloseX); circleColor = GetAppColor(AppColor::TabHighlightedCloseCircle); } if (xHighlighted == i) { xColor = GetAppColor(AppColor::TabHoveredCloseX); circleColor = GetAppColor(AppColor::TabHoveredCloseCircle); } if (xClicked == i) { xColor = GetAppColor(AppColor::TabClickedCloseX); circleColor = GetAppColor(AppColor::TabClickedCloseCircle); } // paint tab's body gfx.SetCompositingMode(CompositingModeSourceCopy); iterator.NextMarker(&shape); br.SetColor(ToColor(bgCol)); Point points[4]; shape.GetPathPoints(points, 4); Rect body(points[0].X, points[0].Y, points[2].X - points[0].X, points[2].Y - points[0].Y); body.Inflate(0, 0); gfx.SetClip(body); body.Inflate(5, 5); gfx.FillRectangle(&br, body); gfx.ResetClip(); // draw tab's text gfx.SetCompositingMode(CompositingModeSourceOver); br.SetColor(ToColor(textCol)); gfx.DrawString(text.at(i), -1, &f, layout, &sf, &br); // paint "x"'s circle iterator.NextMarker(&shape); bool closeCircleEnabled = true; if ((xClicked == i || xHighlighted == i) && closeCircleEnabled) { br.SetColor(ToColor(circleColor)); gfx.FillPath(&br, &shape); } // paint "x" iterator.NextMarker(&shape); pen.SetColor(ToColor(xColor)); gfx.DrawPath(&pen, &shape); iterator.Rewind(); } }