1 /* 2 KeePass Password Safe - The Open-Source Password Manager 3 Copyright (C) 2003-2021 Dominik Reichl <dominik.reichl@t-online.de> 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 20 using System; 21 using System.Collections.Generic; 22 using System.Diagnostics; 23 using System.Drawing; 24 using System.Text; 25 using System.Windows.Forms; 26 27 using KeePass.Resources; 28 29 using KeePassLib; 30 using KeePassLib.Native; 31 using KeePassLib.Utility; 32 33 namespace KeePass.UI.ToolStripRendering 34 { 35 internal sealed class ProExtTsrFactory : TsrFactory 36 { 37 private PwUuid m_uuid = new PwUuid(new byte[] { 38 0x21, 0xED, 0x54, 0x1A, 0xE2, 0xEB, 0xCB, 0x0C, 39 0x57, 0x18, 0x41, 0x32, 0x70, 0xD8, 0xE0, 0xE9 40 }); 41 42 public override PwUuid Uuid 43 { 44 get { return m_uuid; } 45 } 46 47 public override string Name 48 { 49 get { return (".NET/Office - " + KPRes.Professional); } 50 } 51 CreateInstance()52 public override ToolStripRenderer CreateInstance() 53 { 54 return new ProExtTsr(); 55 } 56 } 57 58 public class ProExtTsr : ToolStripProfessionalRenderer 59 { 60 private bool m_bCustomColorTable = false; 61 62 protected bool IsDarkStyle 63 { 64 get 65 { 66 ProfessionalColorTable ct = this.ColorTable; 67 if(ct == null) { Debug.Assert(false); return false; } 68 69 return UIUtil.IsDarkColor(ct.ToolStripDropDownBackground); 70 } 71 } 72 73 protected virtual bool EnsureTextContrast 74 { 75 get { return true; } 76 } 77 ProExtTsr()78 public ProExtTsr() : base() 79 { 80 } 81 ProExtTsr(ProfessionalColorTable ct)82 public ProExtTsr(ProfessionalColorTable ct) : base(ct) 83 { 84 m_bCustomColorTable = true; 85 } 86 OnRenderButtonBackground(ToolStripItemRenderEventArgs e)87 protected override void OnRenderButtonBackground(ToolStripItemRenderEventArgs e) 88 { 89 base.OnRenderButtonBackground(e); 90 91 // .NET incorrectly draws the border using 92 // this.ColorTable.ButtonSelectedBorder even when the button 93 // is pressed; thus in this case we draw it again using the 94 // correct color 95 ToolStripItem tsi = ((e != null) ? e.Item : null); 96 if((tsi != null) && tsi.Pressed && !NativeLib.IsUnix()) 97 { 98 using(Pen p = new Pen(this.ColorTable.ButtonPressedBorder)) 99 { 100 e.Graphics.DrawRectangle(p, 0, 0, tsi.Width - 1, tsi.Height - 1); 101 } 102 } 103 } 104 OnRenderItemCheck(ToolStripItemImageRenderEventArgs e)105 protected override void OnRenderItemCheck(ToolStripItemImageRenderEventArgs e) 106 { 107 if(MonoWorkarounds.IsRequired()) 108 { 109 base.OnRenderItemCheck(e); 110 return; 111 } 112 113 Image imgToDispose = null; 114 try 115 { 116 Graphics g = e.Graphics; 117 Image imgOrg = e.Image; 118 Rectangle rOrg = e.ImageRectangle; 119 ToolStripItem tsi = e.Item; 120 121 Image img = imgOrg; 122 Rectangle r = rOrg; 123 Debug.Assert(r.Width == r.Height); 124 Debug.Assert(DpiUtil.ScalingRequired || (r.Size == 125 ((img != null) ? img.Size : new Size(3, 5)))); 126 127 // Override the .NET checkmark bitmap 128 ToolStripMenuItem tsmi = (tsi as ToolStripMenuItem); 129 if((tsmi != null) && tsmi.Checked && (tsmi.Image == null)) 130 img = Properties.Resources.B16x16_MenuCheck; 131 132 if(tsi != null) 133 { 134 Rectangle rContent = tsi.ContentRectangle; 135 Debug.Assert(rContent.Contains(r) || DpiUtil.ScalingRequired); 136 r.Intersect(rContent); 137 if(r.Height < r.Width) r.Width = r.Height; 138 } 139 else { Debug.Assert(false); } 140 141 if((img != null) && (r.Size != img.Size)) 142 { 143 img = GfxUtil.ScaleImage(img, r.Width, r.Height, 144 ScaleTransformFlags.UIIcon); 145 imgToDispose = img; 146 } 147 148 if((img != imgOrg) || (r != rOrg)) 149 { 150 ToolStripItemImageRenderEventArgs eNew = 151 new ToolStripItemImageRenderEventArgs(g, tsi, img, r); 152 base.OnRenderItemCheck(eNew); 153 return; 154 } 155 156 /* ToolStripMenuItem tsmi = (tsi as ToolStripMenuItem); 157 if((tsmi != null) && tsmi.Checked && (r.Width > 0) && 158 (r.Height > 0) && (img != null) && 159 ((img.Width != r.Width) || (img.Height != r.Height))) 160 { 161 Rectangle rContent = tsmi.ContentRectangle; 162 r.Intersect(rContent); 163 if(r.Height < r.Width) 164 r.Width = r.Height; 165 166 ProfessionalColorTable ct = this.ColorTable; 167 168 Color clrBorder = ct.ButtonSelectedBorder; 169 170 Color clrBG = ct.CheckBackground; 171 if(tsmi.Selected) clrBG = ct.CheckSelectedBackground; 172 if(tsmi.Pressed) clrBG = ct.CheckPressedBackground; 173 174 Color clrFG = ((UIUtil.ColorToGrayscale(clrBG).R >= 128) ? 175 Color.Black : Color.White); 176 177 using(SolidBrush sb = new SolidBrush(clrBG)) 178 { 179 g.FillRectangle(sb, r); 180 } 181 using(Pen p = new Pen(clrBorder)) 182 { 183 g.DrawRectangle(p, r.X, r.Y, r.Width - 1, r.Height - 1); 184 } 185 186 ControlPaint.DrawMenuGlyph(g, r, MenuGlyph.Checkmark, 187 clrFG, Color.Transparent); 188 189 // if((img.Width == r.Width) && (img.Height == r.Height)) 190 // g.DrawImage(img, r); 191 // else 192 // { 193 // Image imgScaled = GfxUtil.ScaleImage(img, 194 // r.Width, r.Height, ScaleTransformFlags.UIIcon); 195 // g.DrawImage(imgScaled, r); 196 // imgScaled.Dispose(); 197 // } 198 199 return; 200 } */ 201 202 /* if((img != null) && (r.Width > 0) && (r.Height > 0) && 203 ((img.Width != r.Width) || (img.Height != r.Height)) && 204 (tsi != null)) 205 { 206 // This should only happen on high DPI 207 Debug.Assert(DpiUtil.ScalingRequired); 208 209 Image imgScaled = GfxUtil.ScaleImage(img, 210 r.Width, r.Height, ScaleTransformFlags.UIIcon); 211 // Image imgScaled = new Bitmap(r.Width, r.Height, 212 // PixelFormat.Format32bppArgb); 213 // using(Graphics gScaled = Graphics.FromImage(imgScaled)) 214 // { 215 // gScaled.Clear(Color.Transparent); 216 217 // Color clrFG = ((UIUtil.ColorToGrayscale( 218 // this.ColorTable.CheckBackground).R >= 128) ? 219 // Color.FromArgb(18, 24, 163) : Color.White); 220 221 // Rectangle rGlyph = new Rectangle(0, 0, r.Width, r.Height); 222 // // rGlyph.Inflate(-r.Width / 12, -r.Height / 12); 223 224 // ControlPaint.DrawMenuGlyph(gScaled, rGlyph, 225 // MenuGlyph.Bullet, clrFG, Color.Transparent); 226 // } 227 228 ToolStripItemImageRenderEventArgs eMod = 229 new ToolStripItemImageRenderEventArgs(g, e.Item, 230 imgScaled, r); 231 base.OnRenderItemCheck(eMod); 232 233 imgScaled.Dispose(); 234 return; 235 } */ 236 } 237 catch(Exception) { Debug.Assert(false); } 238 finally 239 { 240 if(imgToDispose != null) imgToDispose.Dispose(); 241 } 242 243 base.OnRenderItemCheck(e); // Not in 'finally', see 'eNew' 244 } 245 OnRenderItemText(ToolStripItemTextRenderEventArgs e)246 protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e) 247 { 248 if(e != null) 249 { 250 ToolStripItem tsi = e.Item; 251 252 // In high contrast mode, various colors of the default 253 // color table are incorrect, thus check m_bCustomColorTable 254 if((tsi != null) && this.EnsureTextContrast && m_bCustomColorTable) 255 { 256 bool bDarkBack = this.IsDarkStyle; 257 if(tsi.Selected || tsi.Pressed) 258 { 259 if((tsi.Owner is ContextMenuStrip) || (tsi.OwnerItem != null)) 260 bDarkBack = UIUtil.IsDarkColor(this.ColorTable.MenuItemSelected); 261 else // Top menu item 262 { 263 if(tsi.Pressed) 264 bDarkBack = UIUtil.IsDarkColor( 265 this.ColorTable.MenuItemPressedGradientMiddle); 266 else 267 bDarkBack = UIUtil.IsDarkColor(UIUtil.ColorMiddle( 268 this.ColorTable.MenuItemSelectedGradientBegin, 269 this.ColorTable.MenuItemSelectedGradientEnd)); 270 } 271 } 272 273 // e.TextColor might be incorrect, thus use tsi.ForeColor 274 bool bDarkText = UIUtil.IsDarkColor(tsi.ForeColor); 275 276 if(bDarkBack && bDarkText) 277 { 278 Debug.Assert(false); 279 e.TextColor = Color.White; 280 } 281 else if(!bDarkBack && !bDarkText) 282 { 283 Debug.Assert(false); 284 e.TextColor = Color.Black; 285 } 286 } 287 } 288 else { Debug.Assert(false); } 289 290 base.OnRenderItemText(e); 291 } 292 } 293 } 294