// Calculates tab's elements, based on its width and height. // Generates a GraphicsPath, which is used for painting the tab, etc. bool Reshape(int dx, int dy) { dx--; if (width == dx && height == dy) return false; width = dx; height = dy; GraphicsPath shape; // define tab's body shape.AddRectangle(Rect(0, 0, width, height)); shape.SetMarker(); // define "x"'s circle int c = int((float)height * 0.78f + 0.5f); // size of bounding square for the circle int maxC = DpiScaleX(hwnd, 17); if (height > maxC) { c = DpiScaleX(hwnd, 17); } Point p(width - c - DpiScaleX(hwnd, 3), (height - c) / 2); // circle's position shape.AddEllipse(p.X, p.Y, c, c); shape.SetMarker(); // define "x" int o = int((float)c * 0.286f + 0.5f); // "x"'s offset shape.AddLine(p.X + o, p.Y + o, p.X + c - o, p.Y + c - o); shape.StartFigure(); shape.AddLine(p.X + c - o, p.Y + o, p.X + o, p.Y + c - o); shape.SetMarker(); delete data; data = new PathData(); shape.GetPathData(data); return true; }
static void CalcCloseButtonPos(LabelWithCloseWnd *w, int dx, int dy) { int btnDx = DpiScaleX(w->hwnd, CLOSE_BTN_DX); int btnDy = DpiScaleY(w->hwnd, CLOSE_BTN_DY); int x = dx - btnDx - DpiScaleX(w->hwnd, w->padX); int y = 0; if (dy > btnDy) { y = (dy - btnDy) / 2; } w->closeBtnPos = RectI(x, y, btnDx, btnDy); }
SizeI GetIdealSize(LabelWithCloseWnd *w) { WCHAR *s = win::GetText(w->hwnd); SizeI size = TextSizeInHwnd(w->hwnd, s); free(s); int btnDx = DpiScaleX(w->hwnd, CLOSE_BTN_DX); int btnDy = DpiScaleY(w->hwnd, CLOSE_BTN_DY); size.dx += btnDx; size.dx += DpiScaleX(w->hwnd, LABEL_BUTTON_SPACE_DX); size.dx += 2 * DpiScaleX(w->hwnd, w->padX); if (size.dy < btnDy) { size.dy = btnDy; } size.dy += 2 * DpiScaleY(w->hwnd, w->padY); return size; }
static void PaintHDC(LabelWithCloseWnd *w, HDC hdc, const PAINTSTRUCT &ps) { HBRUSH br = CreateSolidBrush(w->bgCol); FillRect(hdc, &ps.rcPaint, br); ClientRect cr(w->hwnd); int x = DpiScaleX(w->hwnd, w->padX); int y = DpiScaleY(w->hwnd, w->padY); UINT opts = ETO_OPAQUE; if (IsRtl(w->hwnd)) { opts = opts | ETO_RTLREADING; } HGDIOBJ prevFont = nullptr; if (w->font) { prevFont = SelectObject(hdc, w->font); } SetTextColor(hdc, w->txtCol); SetBkColor(hdc, w->bgCol); WCHAR *s = win::GetText(w->hwnd); ExtTextOut(hdc, x, y, opts, nullptr, s, (UINT)str::Len(s), nullptr); free(s); // Text might be too long and invade close button area. We just re-paint // the background, which is not the pretties but works. // A better way would be to intelligently truncate text or shrink the font // size (within reason) x = w->closeBtnPos.x - DpiScaleX(w->hwnd, LABEL_BUTTON_SPACE_DX); RectI ri(x, 0, cr.dx - x, cr.dy); RECT r = ri.ToRECT(); FillRect(hdc, &r, br); DrawCloseButton(hdc, w); DeleteObject(br); if (w->font) { SelectObject(hdc, prevFont); } }
/* ツールバー作成 @date @@@ 2002.01.03 YAZAKI m_tbMyButtonなどをCShareDataからCMenuDrawerへ移動したことによる修正。 @date 2005.08.29 aroka ツールバーの折り返し @date 2006.06.17 ryoji ビジュアルスタイルが有効の場合はツールバーを Rebar に入れてサイズ変更時のちらつきを無くす */ void CMainToolBar::CreateToolBar( void ) { if( m_hwndToolBar )return; REBARINFO rbi; REBARBANDINFO rbBand; int nFlag; TBBUTTON tbb; int i; int nIdx; LONG_PTR lToolType; nFlag = 0; // 2006.06.17 ryoji // Rebar ウィンドウの作成 if( IsVisualStyle() ){ // ビジュアルスタイル有効 m_hwndReBar = ::CreateWindowEx( WS_EX_TOOLWINDOW, REBARCLASSNAME, //レバーコントロール NULL, WS_CHILD/* | WS_VISIBLE*/ | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | // 2007.03.08 ryoji WS_VISIBLE 除去 RBS_BANDBORDERS | CCS_NODIVIDER, 0, 0, 0, 0, m_pOwner->GetHwnd(), NULL, CEditApp::getInstance()->GetAppInstance(), NULL ); if( NULL == m_hwndReBar ){ TopWarningMessage( m_pOwner->GetHwnd(), LS(STR_ERR_DLGEDITWND04) ); return; } if( GetDllShareData().m_Common.m_sToolBar.m_bToolBarIsFlat ){ /* フラットツールバーにする/しない */ PreventVisualStyle( m_hwndReBar ); // ビジュアルスタイル非適用のフラットな Rebar にする } ::ZeroMemory(&rbi, sizeof(rbi)); rbi.cbSize = sizeof(rbi); Rebar_SetbarInfo(m_hwndReBar, &rbi); nFlag = CCS_NORESIZE | CCS_NODIVIDER | CCS_NOPARENTALIGN | TBSTYLE_FLAT; // ツールバーへの追加スタイル } /* ツールバーウィンドウの作成 */ m_hwndToolBar = ::CreateWindowEx( 0, TOOLBARCLASSNAME, NULL, WS_CHILD/* | WS_VISIBLE*/ | WS_CLIPCHILDREN | /*WS_BORDER | */ // 2006.06.17 ryoji WS_CLIPCHILDREN 追加 // 2007.03.08 ryoji WS_VISIBLE 除去 /* WS_EX_WINDOWEDGE| */ TBSTYLE_TOOLTIPS | // TBSTYLE_WRAPABLE | // TBSTYLE_ALTDRAG | // CCS_ADJUSTABLE | nFlag, 0, 0, 0, 0, m_pOwner->GetHwnd(), (HMENU)ID_TOOLBAR, CEditApp::getInstance()->GetAppInstance(), NULL ); if( NULL == m_hwndToolBar ){ if( GetDllShareData().m_Common.m_sToolBar.m_bToolBarIsFlat ){ /* フラットツールバーにする/しない */ GetDllShareData().m_Common.m_sToolBar.m_bToolBarIsFlat = FALSE; } TopWarningMessage( m_pOwner->GetHwnd(), LS(STR_ERR_DLGEDITWND05) ); DestroyToolBar(); // 2006.06.17 ryoji } else{ // 2006.09.06 ryoji ツールバーをサブクラス化する g_pOldToolBarWndProc = (WNDPROC)::SetWindowLongPtr( m_hwndToolBar, GWLP_WNDPROC, (LONG_PTR)ToolBarWndProc ); Toolbar_SetButtonSize( m_hwndToolBar, DpiScaleX(22), DpiScaleY(22) ); // 2009.10.01 ryoji 高DPI対応スケーリング Toolbar_ButtonStructSize( m_hwndToolBar, sizeof(TBBUTTON) ); // Oct. 12, 2000 genta // 既に用意されているImage Listをアイコンとして登録 m_pcIcons->SetToolBarImages( m_hwndToolBar ); /* ツールバーにボタンを追加 */ int count = 0; //@@@ 2002.06.15 MIK int nToolBarButtonNum = 0;// 2005/8/29 aroka // From Here 2005.08.29 aroka // はじめにツールバー構造体の配列を作っておく TBBUTTON *pTbbArr = new TBBUTTON[GetDllShareData().m_Common.m_sToolBar.m_nToolBarButtonNum]; for( i = 0; i < GetDllShareData().m_Common.m_sToolBar.m_nToolBarButtonNum; ++i ){ nIdx = GetDllShareData().m_Common.m_sToolBar.m_nToolBarButtonIdxArr[i]; pTbbArr[nToolBarButtonNum] = m_pOwner->GetMenuDrawer().getButton(nIdx); // セパレータが続くときはひとつにまとめる // 折り返しボタンもTBSTYLE_SEP属性を持っているので // 折り返しの前のセパレータは全て削除される. if( (pTbbArr[nToolBarButtonNum].fsStyle & TBSTYLE_SEP) && (nToolBarButtonNum!=0)){ if( (pTbbArr[nToolBarButtonNum-1].fsStyle & TBSTYLE_SEP) ){ pTbbArr[nToolBarButtonNum-1] = pTbbArr[nToolBarButtonNum]; nToolBarButtonNum--; } } // 仮想折返しボタンがきたら直前のボタンに折返し属性を付ける if( pTbbArr[nToolBarButtonNum].fsState & TBSTATE_WRAP ){ if( nToolBarButtonNum!=0 ){ pTbbArr[nToolBarButtonNum-1].fsState |= TBSTATE_WRAP; } continue; } nToolBarButtonNum++; } // To Here 2005.08.29 aroka for( i = 0; i < nToolBarButtonNum; ++i ){ tbb = pTbbArr[i]; //@@@ 2002.06.15 MIK start switch( tbb.fsStyle ) { case TBSTYLE_DROPDOWN: //ドロップダウン //拡張スタイルに設定 Toolbar_SetExtendedStyle( m_hwndToolBar, TBSTYLE_EX_DRAWDDARROWS ); Toolbar_AddButtons( m_hwndToolBar, 1, &tbb ); count++; break; case TBSTYLE_COMBOBOX: //コンボボックス { RECT rc; TBBUTTONINFO tbi; TBBUTTON my_tbb; LOGFONT lf; switch( tbb.idCommand ) { case F_SEARCH_BOX: if( m_hwndSearchBox ) { break; } //セパレータ作る memset_raw( &my_tbb, 0, sizeof(my_tbb) ); my_tbb.fsStyle = TBSTYLE_BUTTON; //ボタンにしないと描画が乱れる 2005/8/29 aroka my_tbb.idCommand = tbb.idCommand; //同じIDにしておく if( tbb.fsState & TBSTATE_WRAP ){ //折り返し 2005/8/29 aroka my_tbb.fsState |= TBSTATE_WRAP; } Toolbar_AddButtons( m_hwndToolBar, 1, &my_tbb ); count++; //サイズを設定する tbi.cbSize = sizeof(tbi); tbi.dwMask = TBIF_SIZE; tbi.cx = (WORD)DpiScaleX(160); //ボックスの幅 // 2009.10.01 ryoji 高DPI対応スケーリング Toolbar_SetButtonInfo( m_hwndToolBar, tbb.idCommand, &tbi ); //位置とサイズを取得する rc.right = rc.left = rc.top = rc.bottom = 0; Toolbar_GetItemRect( m_hwndToolBar, count-1, &rc ); //コンボボックスを作る // Mar. 8, 2003 genta 検索ボックスを1ドット下にずらした m_hwndSearchBox = CreateWindow( _T("COMBOBOX"), _T("Combo"), WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | CBS_DROPDOWN /*| CBS_SORT*/ | CBS_AUTOHSCROLL /*| CBS_DISABLENOSCROLL*/, rc.left, rc.top + 1, rc.right - rc.left, (rc.bottom - rc.top) * 10, m_hwndToolBar, (HMENU)(INT_PTR)tbb.idCommand, CEditApp::getInstance()->GetAppInstance(), NULL ); if( m_hwndSearchBox ) { m_pOwner->SetCurrentFocus(0); lf = m_pOwner->GetLogfont(); //memset_raw( &lf, 0, sizeof(lf) ); lf.lfHeight = DpiPointsToPixels(-9); // Jan. 14, 2003 genta ダイアログにあわせてちょっと小さく // 2009.10.01 ryoji 高DPI対応(ポイント数から算出) lf.lfWidth = 0; lf.lfEscapement = 0; lf.lfOrientation = 0; lf.lfWeight = FW_NORMAL; lf.lfItalic = FALSE; lf.lfUnderline = FALSE; lf.lfStrikeOut = FALSE; //lf.lfCharSet = GetDllShareData().m_Common.m_sView.m_lf.lfCharSet; lf.lfOutPrecision = OUT_TT_ONLY_PRECIS; // Raster Font を使わないように //lf.lfClipPrecision = GetDllShareData().m_Common.m_sView.m_lf.lfClipPrecision; //lf.lfQuality = GetDllShareData().m_Common.m_sView.m_lf.lfQuality; //lf.lfPitchAndFamily = GetDllShareData().m_Common.m_sView.m_lf.lfPitchAndFamily; //_tcsncpy( lf.lfFaceName, GetDllShareData().m_Common.m_sView.m_lf.lfFaceName, _countof(lf.lfFaceName)); // 画面のフォントに設定 2012/11/27 Uchi m_hFontSearchBox = ::CreateFontIndirect( &lf ); if( m_hFontSearchBox ) { ::SendMessage( m_hwndSearchBox, WM_SETFONT, (WPARAM)m_hFontSearchBox, MAKELONG (TRUE, 0) ); } // //入力長制限 // Combo_LimitText( m_hwndSearchBox, (WPARAM)_MAX_PATH - 1 ); //検索ボックスを更新 // 関数化 2010/6/6 Uchi AcceptSharedSearchKey(); m_comboDel = SComboBoxItemDeleter(); // 再表示用の初期化 m_comboDel.pRecent = &m_cRecentSearch; CDialog::SetComboBoxDeleter(m_hwndSearchBox, &m_comboDel); } break; default: break; } } break; case TBSTYLE_BUTTON: //ボタン case TBSTYLE_SEP: //セパレータ default: Toolbar_AddButtons( m_hwndToolBar, 1, &tbb ); count++; break; } //@@@ 2002.06.15 MIK end } if( GetDllShareData().m_Common.m_sToolBar.m_bToolBarIsFlat ){ /* フラットツールバーにする/しない */ lToolType = ::GetWindowLongPtr(m_hwndToolBar, GWL_STYLE); lToolType |= (TBSTYLE_FLAT); ::SetWindowLongPtr(m_hwndToolBar, GWL_STYLE, lToolType); ::InvalidateRect(m_hwndToolBar, NULL, TRUE); } delete []pTbbArr;// 2005/8/29 aroka } // 2006.06.17 ryoji // ツールバーを Rebar に入れる if( m_hwndReBar && m_hwndToolBar ){ // ツールバーの高さを取得する DWORD dwBtnSize = Toolbar_GetButtonSize( m_hwndToolBar ); DWORD dwRows = Toolbar_GetRows( m_hwndToolBar ); // バンド情報を設定する // 以前のプラットフォームに _WIN32_WINNT >= 0x0600 で定義される構造体のフルサイズを渡すと失敗する // 2007.12.21 ryoji rbBand.cbSize = CCSIZEOF_STRUCT( REBARBANDINFO, wID ); rbBand.fMask = RBBIM_STYLE | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE; rbBand.fStyle = RBBS_CHILDEDGE; rbBand.hwndChild = m_hwndToolBar; // ツールバー rbBand.cxMinChild = 0; rbBand.cyMinChild = HIWORD(dwBtnSize) * dwRows; rbBand.cx = 250; // バンドを追加する Rebar_InsertBand( m_hwndReBar, -1, &rbBand ); ::ShowWindow( m_hwndToolBar, SW_SHOW ); } return; }
/*! 独自拡張プロパティシートのウィンドウプロシージャ @author ryoji @date 2007.05.25 新規 */ static LRESULT CALLBACK PropSheetWndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { switch( uMsg ){ case WM_SHOWWINDOW: // 追加ボタンの位置を調整する if( wParam ){ HWND hwndBtn; RECT rcOk; RECT rcTab; POINT pt; hwndBtn = ::GetDlgItem( hwnd, 0x02000 ); ::GetWindowRect( ::GetDlgItem( hwnd, IDOK ), &rcOk ); ::GetWindowRect( PropSheet_GetTabControl( hwnd ), &rcTab ); pt.x = rcTab.left; pt.y = rcOk.top; ::ScreenToClient( hwnd, &pt ); ::MoveWindow( hwndBtn, pt.x, pt.y, DpiScaleX(140), rcOk.bottom - rcOk.top, FALSE ); } break; case WM_COMMAND: // 追加ボタンが押された時はその処理を行う if( HIWORD( wParam ) == BN_CLICKED && LOWORD( wParam ) == 0x02000 ){ HWND hwndBtn = ::GetDlgItem( hwnd, 0x2000 ); RECT rc; POINT pt; // メニューを表示する ::GetWindowRect( hwndBtn, &rc ); pt.x = rc.left; pt.y = rc.bottom; GetMonitorWorkRect( pt, &rc ); // モニタのワークエリア HMENU hMenu = ::CreatePopupMenu(); ::InsertMenu( hMenu, 0, MF_BYPOSITION | MF_STRING, 100, LS(STR_SHELL_MENU_OPEN) ); ::InsertMenu( hMenu, 1, MF_BYPOSITION | MF_STRING, 101, LS(STR_SHELL_MENU_IMPEXP) ); int nId = ::TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_LEFTBUTTON | TPM_RETURNCMD, ( pt.x > rc.left )? pt.x: rc.left, ( pt.y < rc.bottom )? pt.y: rc.bottom, 0, hwnd, NULL ); ::DestroyMenu( hMenu ); // 選択されたメニューの処理 switch( nId ){ case 100: // 設定フォルダを開く TCHAR szPath[_MAX_PATH]; GetInidir( szPath ); // フォルダの ITEMIDLIST を取得して ShellExecuteEx() で開く // Note. MSDN の ShellExecute() の解説にある方法でフォルダを開こうとした場合、 // フォルダと同じ場所に <フォルダ名>.exe があるとうまく動かない。 // verbが"open"やNULLではexeのほうが実行され"explore"では失敗する // (フォルダ名の末尾に'\\'を付加してもWindows 2000では付加しないのと同じ動作になってしまう) LPSHELLFOLDER pDesktopFolder; if( SUCCEEDED(::SHGetDesktopFolder(&pDesktopFolder)) ){ LPMALLOC pMalloc; if( SUCCEEDED(::SHGetMalloc(&pMalloc)) ){ LPITEMIDLIST pIDL; WCHAR pwszDisplayName[_MAX_PATH]; _tcstowcs(pwszDisplayName, szPath, _countof(pwszDisplayName)); //#ifdef _UNICODE // pwszDisplayName = szPath; //#else // WCHAR wszPath[_MAX_PATH]; // ::MultiByteToWideChar( CP_ACP, 0, szPath, -1, wszPath, _MAX_PATH ); // pwszDisplayName = wszPath; //#endif if( SUCCEEDED(pDesktopFolder->ParseDisplayName(NULL, NULL, pwszDisplayName, NULL, &pIDL, NULL)) ){ SHELLEXECUTEINFO si; ::ZeroMemory( &si, sizeof(si) ); si.cbSize = sizeof(si); si.fMask = SEE_MASK_IDLIST; si.lpVerb = _T("open"); si.lpIDList = pIDL; si.nShow = SW_SHOWNORMAL; ::ShellExecuteEx( &si ); // フォルダを開く pMalloc->Free( (void*)pIDL ); } pMalloc->Release(); } pDesktopFolder->Release(); } break; case 101: // インポート/エクスポートの起点リセット(起点を設定フォルダにする) int nMsgResult = MYMESSAGEBOX( hwnd, MB_OKCANCEL | MB_ICONINFORMATION, GSTR_APPNAME, LS(STR_SHELL_IMPEXPDIR) ); if( IDOK == nMsgResult ) { DLLSHAREDATA *pShareData = &GetDllShareData(); GetInidir( pShareData->m_sHistory.m_szIMPORTFOLDER ); AddLastChar( pShareData->m_sHistory.m_szIMPORTFOLDER, _countof2(pShareData->m_sHistory.m_szIMPORTFOLDER), _T('\\') ); } break; } } break; case WM_DESTROY: ::SetWindowLongPtr( hwnd, GWLP_WNDPROC, (LONG_PTR)s_pOldPropSheetWndProc ); break; } return ::CallWindowProc( s_pOldPropSheetWndProc, hwnd, uMsg, wParam, lParam ); }
static inline SizeI GetTabSize(HWND hwnd) { int dx = DpiScaleX(hwnd, std::max(gGlobalPrefs->prereleaseSettings.tabWidth, MIN_TAB_WIDTH)); int dy = DpiScaleY(hwnd, TABBAR_HEIGHT); return SizeI(dx, dy); }
// 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(); } }
/* ツールバーボタンリストのアイテム描画 @date 2003.08.27 Moca システムカラーのブラシはCreateSolidBrushをやめGetSysColorBrushに @date 2005.08.09 aroka CPropCommon.cpp から移動 @date 2007.11.02 ryoji ボタンとセパレータとで処理を分ける */ void CPropToolbar::DrawToolBarItemList( DRAWITEMSTRUCT* pDis ) { TBBUTTON tbb; HBRUSH hBrush; RECT rc; RECT rc0; RECT rc1; RECT rc2; // hBrush = ::CreateSolidBrush( ::GetSysColor( COLOR_WINDOW ) ); hBrush = ::GetSysColorBrush( COLOR_WINDOW ); ::FillRect( pDis->hDC, &pDis->rcItem, hBrush ); // ::DeleteObject( hBrush ); rc = pDis->rcItem; rc0 = pDis->rcItem; rc0.left += GetSystemMetrics(SM_CXSMICON) + DpiScaleX(2); rc1 = rc0; rc2 = rc0; if( (int)pDis->itemID < 0 ){ }else{ //@@@ 2002.01.03 YAZAKI m_tbMyButtonなどをCShareDataからCMenuDrawerへ移動したことによる修正。 // tbb = m_cShareData.m_tbMyButton[pDis->itemData]; // tbb = m_pcMenuDrawer->m_tbMyButton[pDis->itemData]; tbb = m_pcMenuDrawer->getButton(pDis->itemData); // ボタンとセパレータとで処理を分ける 2007.11.02 ryoji WCHAR szLabel[256]; if( tbb.fsStyle & TBSTYLE_SEP ){ // テキストだけ表示する if( tbb.idCommand == F_SEPARATOR ){ auto_strncpy( szLabel, LSW(STR_PROPCOMTOOL_ITEM1), _countof(szLabel) - 1 ); // nLength 未使用 2003/01/09 Moca szLabel[_countof(szLabel) - 1] = L'\0'; }else if( tbb.idCommand == F_MENU_NOT_USED_FIRST ){ // ツールバー折返 auto_strncpy( szLabel, LSW(STR_PROPCOMTOOL_ITEM2), _countof(szLabel) - 1 ); szLabel[_countof(szLabel) - 1] = L'\0'; }else{ auto_strncpy( szLabel, LSW(STR_PROPCOMTOOL_ITEM3), _countof(szLabel) - 1 ); szLabel[_countof(szLabel) - 1] = L'\0'; } // From Here Oct. 15, 2001 genta }else{ // アイコンとテキストを表示する m_pcIcons->Draw( tbb.iBitmap, pDis->hDC, rc.left + 2, rc.top + 2, ILD_NORMAL ); m_cLookup.Funccode2Name( tbb.idCommand, szLabel, _countof( szLabel ) ); } // To Here Oct. 15, 2001 genta /* アイテムが選択されている */ if( pDis->itemState & ODS_SELECTED ){ // hBrush = ::CreateSolidBrush( ::GetSysColor( COLOR_HIGHLIGHT ) ); hBrush = ::GetSysColorBrush( COLOR_HIGHLIGHT ); ::SetTextColor( pDis->hDC, ::GetSysColor( COLOR_HIGHLIGHTTEXT ) ); }else{ // hBrush = ::CreateSolidBrush( ::GetSysColor( COLOR_WINDOW ) ); hBrush = ::GetSysColorBrush( COLOR_WINDOW ); ::SetTextColor( pDis->hDC, ::GetSysColor( COLOR_WINDOWTEXT ) ); } rc1.left++; rc1.top++; rc1.right--; rc1.bottom--; ::FillRect( pDis->hDC, &rc1, hBrush ); // ::DeleteObject( hBrush ); ::SetBkMode( pDis->hDC, TRANSPARENT ); // 2014.11.25 topマージンが2固定だとフォントが大きい時に見切れるので変数に変更 TextOutW_AnyBuild( pDis->hDC, rc1.left + 4, rc1.top + nToolBarListBoxTopMargin, szLabel, wcslen( szLabel ) ); } /* アイテムにフォーカスがある */ if( pDis->itemState & ODS_FOCUS ){ ::DrawFocusRect( pDis->hDC, &rc2 ); } return; }