Res.DesignExt.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Windows.Forms;
  4. using System.Drawing;
  5. using System.Reflection;
  6. using System.IO;
  7. #if !MONO
  8. using FastReport.DevComponents.DotNetBar;
  9. #endif
  10. namespace FastReport.Utils
  11. {
  12. partial class Res
  13. {
  14. private class ImageInfo
  15. {
  16. private int dpi;
  17. private List<Bitmap> images;
  18. private ImageList imageList;
  19. private bool imagesLoaded = false;
  20. public List<Bitmap> Images
  21. {
  22. get
  23. {
  24. if (!imagesLoaded)
  25. LoadImages();
  26. return images;
  27. }
  28. }
  29. private Bitmap AddImage(Bitmap srcImage, int x, int y, int srcImageSize)
  30. {
  31. int destImageSize = (int)Math.Round(16 * dpi / 96f);
  32. Bitmap image = new Bitmap(destImageSize, destImageSize);
  33. // Upscaling images contained in buttons.png produces artifacts.
  34. // Copy the portion of image to slice then upscale it.
  35. Bitmap slice = null;
  36. if (srcImage.Width > srcImageSize)
  37. {
  38. slice = new Bitmap(srcImageSize, srcImageSize);
  39. using (Graphics g = Graphics.FromImage(slice))
  40. {
  41. g.DrawImage(srcImage, new Rectangle(0, 0, srcImageSize, srcImageSize), x, y, srcImageSize, srcImageSize, GraphicsUnit.Pixel);
  42. }
  43. x = 0;
  44. y = 0;
  45. srcImage = slice;
  46. }
  47. using (Graphics g = Graphics.FromImage(image))
  48. {
  49. g.DrawImage(srcImage, new Rectangle(0, 0, destImageSize, destImageSize), x, y, srcImageSize, srcImageSize, GraphicsUnit.Pixel);
  50. }
  51. images.Add(image);
  52. if (slice != null)
  53. slice.Dispose();
  54. return image;
  55. }
  56. private void LoadImages()
  57. {
  58. imagesLoaded = true;
  59. images = new List<Bitmap>();
  60. const string resName = "buttons.png"; // the image must contain 10 icons in a row
  61. using (Bitmap allImages = LoadResourceImage(resName, dpi))
  62. {
  63. int srcImageSize = allImages.Width / 10;
  64. int x = 0;
  65. int y = 0;
  66. bool done = false;
  67. do
  68. {
  69. AddImage(allImages, x, y, srcImageSize);
  70. x += srcImageSize;
  71. if (x >= allImages.Width)
  72. {
  73. x = 0;
  74. y += srcImageSize;
  75. }
  76. done = y > allImages.Height;
  77. }
  78. while (!done);
  79. }
  80. }
  81. private void CreateImageList()
  82. {
  83. imageList = new ImageList();
  84. int imageSize = images[0].Width;
  85. imageList.ImageSize = new Size(imageSize, imageSize);
  86. imageList.ColorDepth = ColorDepth.Depth32Bit;
  87. foreach (Bitmap bmp in images)
  88. {
  89. imageList.Images.Add(bmp);
  90. }
  91. }
  92. public ImageList GetImages()
  93. {
  94. if (!imagesLoaded)
  95. LoadImages();
  96. if (imageList == null)
  97. CreateImageList();
  98. return imageList;
  99. }
  100. public Bitmap GetImage(int index)
  101. {
  102. if (index < 0)
  103. return null;
  104. if (!imagesLoaded)
  105. LoadImages();
  106. return images[index];
  107. }
  108. // for images added by user
  109. public int AddImage(Bitmap img)
  110. {
  111. // ensure everything is loaded
  112. GetImages();
  113. Bitmap image = AddImage(img, 0, 0, img.Width);
  114. imageList.Images.Add(image);
  115. return images.Count - 1;
  116. }
  117. public ImageInfo(int dpi)
  118. {
  119. this.dpi = dpi;
  120. }
  121. }
  122. private readonly static Dictionary<int, ImageInfo> dpiAwareImages = new Dictionary<int, ImageInfo>();
  123. private static Bitmap LoadResourceImage(string name, int dpi, bool scaleToTargetSize = false)
  124. {
  125. // loads appropriate image for given dpi and current icon pack
  126. // - original name: "name.png"
  127. // - high dpi: "name-hi.png"
  128. // - other image pack: "name-1.png", "name-1-hi.png"
  129. //
  130. // Notes:
  131. // - the image with original name (for 96dpi) must exist. It will be used to determine the target size.
  132. // - a note to previous note :) - if a classic-pack image does not exist (it is the case with ribbon icons), use an image from the next (#1) pack with "-1" suffix
  133. // - if no image pack or hi-version of image exists, the original image is used. Scaling is performed if needed.
  134. string originalName = name;
  135. Bitmap originalImage = ResourceLoader.GetBitmap(originalName);
  136. if (originalImage == null)
  137. {
  138. // no original image? It may happen if a classic icon pack does not have an image. Use an image from the next pack
  139. originalImage = ResourceLoader.GetBitmap(
  140. Path.GetFileNameWithoutExtension(originalName) + "-1" + Path.GetExtension(originalName));
  141. }
  142. Bitmap srcImage = null;
  143. Size destImageSize = new Size((int)Math.Round(originalImage.Width * dpi / 96f), (int)Math.Round(originalImage.Height * dpi / 96f));
  144. int iconPack = Config.IconPack;
  145. if (iconPack != 0)
  146. name = Path.GetFileNameWithoutExtension(originalName) + "-" + iconPack.ToString() + Path.GetExtension(originalName);
  147. // high dpi images
  148. if (dpi >= 144)
  149. name = Path.GetFileNameWithoutExtension(name) + "-hi" + Path.GetExtension(originalName);
  150. srcImage = ResourceLoader.GetBitmap(name);
  151. if (srcImage == null)
  152. {
  153. // no image exist, use the original one
  154. srcImage = originalImage;
  155. }
  156. // scale to target size
  157. if (scaleToTargetSize)
  158. {
  159. Bitmap destImage = new Bitmap(destImageSize.Width, destImageSize.Height);
  160. using (Graphics g = Graphics.FromImage(destImage))
  161. {
  162. g.DrawImage(srcImage, new Rectangle(0, 0, destImageSize.Width, destImageSize.Height));
  163. }
  164. return destImage;
  165. }
  166. return srcImage;
  167. }
  168. private static int CheckDpi(int dpi)
  169. {
  170. if (!dpiAwareImages.ContainsKey(dpi))
  171. dpiAwareImages.Add(dpi, new ImageInfo(dpi));
  172. return dpi;
  173. }
  174. private static int CheckUserImages(int dpi)
  175. {
  176. if (dpi != 96)
  177. {
  178. // if image list has less images than 96-dpi image list, add user images to image list
  179. List<Bitmap> images96 = dpiAwareImages[CheckDpi(96)].Images;
  180. List<Bitmap> images = dpiAwareImages[CheckDpi(dpi)].Images;
  181. for (int i = images.Count; i < images96.Count; i++)
  182. dpiAwareImages[dpi].AddImage(images96[i]);
  183. }
  184. return dpi;
  185. }
  186. /// <summary>
  187. /// Adds user image to 96 dpi images.
  188. /// </summary>
  189. /// <param name="img">User image (16x16 pixels).</param>
  190. /// <returns>Image index in the image list.</returns>
  191. internal static int AddImage(Bitmap img)
  192. {
  193. return dpiAwareImages[CheckDpi(96)].AddImage(img);
  194. }
  195. /// <summary>
  196. /// Gets the standard images used in FastReport as an <b>ImageList</b>.
  197. /// </summary>
  198. /// <returns><b>ImageList</b> object that contains standard images.</returns>
  199. /// <remarks>
  200. /// FastReport contains about 240 truecolor images of 16x16 size that are stored in one
  201. /// big image side-by-side. This image can be found in FastReport resources (the "buttons.png" resource).
  202. /// </remarks>
  203. public static ImageList GetImages(int dpi)
  204. {
  205. return dpiAwareImages[CheckUserImages(CheckDpi(dpi))].GetImages();
  206. }
  207. /// <summary>
  208. /// Gets an image with specified index.
  209. /// </summary>
  210. /// <param name="index">Image index (zero-based).</param>
  211. /// <param name="dpi">Dpi value (96 for base dpi).</param>
  212. /// <returns>The image with specified index.</returns>
  213. /// <remarks>
  214. /// FastReport contains about 240 truecolor images of 16x16 size that are stored in one
  215. /// big image side-by-side. This image can be found in FastReport resources (the "buttons.png" resource).
  216. /// </remarks>
  217. public static Bitmap GetImage(int index, int dpi)
  218. {
  219. return dpiAwareImages[CheckUserImages(CheckDpi(dpi))].GetImage(index);
  220. }
  221. /// <summary>
  222. /// Gets an image with specified name from resources.
  223. /// </summary>
  224. /// <param name="name">The name of image resource.</param>
  225. /// <param name="dpi">Dpi value (96 for base dpi).</param>
  226. /// <returns>The image.</returns>
  227. public static Bitmap GetImage(string name, int dpi)
  228. {
  229. return LoadResourceImage(name, dpi, true);
  230. }
  231. /// <summary>
  232. /// Gets an image with specified index and converts it to <b>Icon</b>.
  233. /// </summary>
  234. /// <param name="index">Image index (zero-based).</param>
  235. /// <param name="dpi">Dpi value (96 for base dpi).</param>
  236. /// <returns>The <b>Icon</b> object.</returns>
  237. public static Icon GetIcon(int index, int dpi)
  238. {
  239. #if AVALONIA
  240. return GetImage(index, dpi) as Icon;
  241. #else
  242. return Icon.FromHandle(GetImage(index, dpi).GetHicon());
  243. #endif
  244. }
  245. #if !MONO
  246. static partial void ResDesignExt()
  247. {
  248. // for using FastReport.dll without FastReport.Bars.dll if the designer is not shown
  249. foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
  250. {
  251. if (a.ManifestModule.Name == "FastReport.Bars.dll")
  252. {
  253. RegisterLocalizeStringEventHandler();
  254. break;
  255. }
  256. }
  257. }
  258. private static void RegisterLocalizeStringEventHandler()
  259. {
  260. LocalizationKeys.LocalizeString += new DotNetBarManager.LocalizeStringEventHandler(LocalizationKeys_LocalizeString);
  261. }
  262. private static void LocalizationKeys_LocalizeString(object sender, LocalizeEventArgs e)
  263. {
  264. switch (e.Key)
  265. {
  266. case "barsys_autohide_tooltip":
  267. e.LocalizedValue = Res.Get("Designer,ToolWindow,AutoHide");
  268. e.Handled = true;
  269. break;
  270. case "barsys_close_tooltip":
  271. e.LocalizedValue = Res.Get("Designer,ToolWindow,Close");
  272. e.Handled = true;
  273. break;
  274. case "cust_mnu_addremove":
  275. e.LocalizedValue = Res.Get("Designer,Toolbar,AddOrRemove");
  276. e.Handled = true;
  277. break;
  278. case "sys_morebuttons":
  279. e.LocalizedValue = Res.Get("Designer,Toolbar,MoreButtons");
  280. e.Handled = true;
  281. break;
  282. }
  283. }
  284. #endif
  285. }
  286. }