PageRenderTime 51ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/branches/2.x/Dorian/Gorgon/Gorgon.Graphics/Native/Win32API.cs

http://gorgonlib.googlecode.com/
C# | 256 lines | 120 code | 35 blank | 101 comment | 27 complexity | ad486cc9406d16a87c7784f807f2fa54 MD5 | raw file
Possible License(s): LGPL-2.0
  1. #region MIT.
  2. //
  3. // Gorgon.
  4. // Copyright (C) 2011 Michael Winsor
  5. //
  6. // Permission is hereby granted, free of charge, to any person obtaining a copy
  7. // of this software and associated documentation files (the "Software"), to deal
  8. // in the Software without restriction, including without limitation the rights
  9. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. // copies of the Software, and to permit persons to whom the Software is
  11. // furnished to do so, subject to the following conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be included in
  14. // all copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. // Created: Sunday, July 24, 2011 10:15:39 PM
  24. //
  25. #endregion
  26. using System;
  27. using System.Collections.Generic;
  28. using System.Linq;
  29. using System.Text;
  30. using System.Diagnostics;
  31. using System.Windows.Forms;
  32. using System.Runtime.InteropServices;
  33. using Drawing = System.Drawing;
  34. namespace GorgonLibrary.Native
  35. {
  36. /// <summary>
  37. /// Win 32 API function calls.
  38. /// </summary>
  39. [System.Security.SuppressUnmanagedCodeSecurity()]
  40. unsafe static class Win32API
  41. {
  42. #region Variables.
  43. private static IntPtr _lasthObj = IntPtr.Zero; // Last active object handle.
  44. private static IntPtr _hdc = IntPtr.Zero; // Current device context.
  45. private static IntPtr _hFont = IntPtr.Zero; // Font handle.
  46. private static Drawing.Graphics _lastGraphics = null; // Last used graphics interface.
  47. private static Drawing.Font _tempFont = null; // Temporary font.
  48. #endregion
  49. #region Win32 Methods.
  50. /// <summary>
  51. /// The SelectObject function selects an object into the specified device context (DC). The new object replaces the previous object of the same type.
  52. /// </summary>
  53. /// <param name="hDC">A handle to the DC.</param>
  54. /// <param name="hObj">A handle to the object to be selected.</param>
  55. /// <returns>If the selected object is not a region and the function succeeds, the return value is a handle to the object being replaced</returns>
  56. [DllImport("gdi32.dll", ExactSpelling = true)]
  57. private static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObj);
  58. /// <summary>
  59. /// The DeleteDC function deletes the specified device context (DC).
  60. /// </summary>
  61. /// <param name="hObj">A handle to the device context.</param>
  62. /// <returns>If the function succeeds, the return value is nonzero. If the function fails, the return value is zero.</returns>
  63. [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
  64. private static extern int DeleteObject(IntPtr hObj);
  65. /// <summary>
  66. /// The GetCharABCWidths function retrieves the widths, in logical units, of consecutive characters in a specified range from the current TrueType font. This function succeeds only with TrueType fonts.
  67. /// </summary>
  68. /// <param name="HDC">A handle to the device context.</param>
  69. /// <param name="uFirstChar">The first character in the group of consecutive characters from the current font.</param>
  70. /// <param name="uLastChar">The last character in the group of consecutive characters from the current font.</param>
  71. /// <param name="lpABC">A pointer to an array of ABC structures that receives the character widths, in logical units. This array must contain at least as many ABC structures as there are characters in the range specified by the uFirstChar and uLastChar parameters.</param>
  72. /// <returns>TRUE if successful, FALSE if not.</returns>
  73. [DllImport("gdi32.dll", EntryPoint = "GetCharABCWidthsW", CharSet = CharSet.Unicode)]
  74. private static extern bool GetCharABCWidthsW(IntPtr HDC, uint uFirstChar, uint uLastChar, ABC* lpABC);
  75. /// <summary>
  76. /// The GetKerningPairs function retrieves the character-kerning pairs for the currently selected font for the specified device context.
  77. /// </summary>
  78. /// <param name="HDC">A handle to the device context.</param>
  79. /// <param name="numberOfPairs">The number of pairs in the keyPairs array. If the font has more than nNumPairs kerning pairs, the function returns an error.</param>
  80. /// <param name="kernPairs">A pointer to an array of KERNINGPAIR structures that receives the kerning pairs. The array must contain at least as many structures as specified by the nNumPairs parameter. If this parameter is NULL, the function returns the total number of kerning pairs for the font.</param>
  81. /// <returns>If the function succeeds, the return value is the number of kerning pairs returned. If the function fails, the return value is zero.</returns>
  82. [DllImport("gdi32.dll", EntryPoint = "GetKerningPairsW", CharSet = CharSet.Unicode)]
  83. private static extern uint GetKerningPairsW(IntPtr HDC, uint numberOfPairs, KERNINGPAIR* kernPairs);
  84. /// <summary>
  85. /// The SetMapMode function sets the mapping mode of the specified device context. The mapping mode defines the unit of measure used to transform page-space units into device-space units, and also defines the orientation of the device's x and y axes.
  86. /// </summary>
  87. /// <param name="HDC">A handle to the device context.</param>
  88. /// <param name="fnMapMode">The new mapping mode.</param>
  89. /// <returns>If the function succeeds, the return value identifies the previous mapping mode. If the function fails, the return value is zero.</returns>
  90. [DllImport("gdi32.dll", EntryPoint = "SetMapMode", CharSet = CharSet.Auto)]
  91. private static extern MapModes SetMapMode(IntPtr HDC, MapModes fnMapMode);
  92. /// <summary>
  93. /// Function to retrieve the nearest monitor to the window.
  94. /// </summary>
  95. /// <param name="hwnd">Handle to the window.</param>
  96. /// <param name="flags">Flags to pass in.</param>
  97. /// <returns></returns>
  98. [DllImport("user32.dll", CharSet=CharSet.Auto)]
  99. private static extern IntPtr MonitorFromWindow(IntPtr hwnd, MonitorFlags flags);
  100. /// <summary>
  101. /// Function to enable or disable desktop composition.
  102. /// </summary>
  103. /// <param name="uCompositionAction">Composition action.</param>
  104. /// <returns></returns>
  105. [DllImport("Dwmapi.dll")]
  106. public static extern int DwmEnableComposition(int uCompositionAction);
  107. /// <summary>
  108. /// Function to determine if desktop composition is enabled or not.
  109. /// </summary>
  110. /// <param name="pfEnabled"></param>
  111. /// <returns></returns>
  112. [DllImport("dwmapi.dll")]
  113. public static extern int DwmIsCompositionEnabled(out bool pfEnabled);
  114. #endregion
  115. #region Methods.
  116. /// <summary>
  117. /// Function to retrieve the monitor with the largest portion of the window inside of it.
  118. /// </summary>
  119. /// <param name="window">Window to locate.</param>
  120. /// <returns>The handle to the monitor.</returns>
  121. public static IntPtr GetMonitor(Control window)
  122. {
  123. return MonitorFromWindow(window.Handle, MonitorFlags.MONITOR_DEFAULTTOPRIMARY);
  124. }
  125. /// <summary>
  126. /// Function to set the active font.
  127. /// </summary>
  128. /// <param name="graphics">Graphics interface to use.</param>
  129. /// <param name="font">Font to set.</param>
  130. public static void SetActiveFont(Drawing.Graphics graphics, Drawing.Font font)
  131. {
  132. if ((_lasthObj != IntPtr.Zero) || (_hdc != IntPtr.Zero) || (_hFont != IntPtr.Zero))
  133. return;
  134. try
  135. {
  136. _lastGraphics = graphics;
  137. _tempFont = (Drawing.Font)font.Clone();
  138. _hdc = graphics.GetHdc();
  139. _hFont = _tempFont.ToHfont();
  140. _lasthObj = SelectObject(_hdc, _hFont);
  141. }
  142. catch
  143. {
  144. // Restore everything in case of an exception.
  145. RestoreActiveObject();
  146. throw;
  147. }
  148. }
  149. /// <summary>
  150. /// Function to restore the last known active object.
  151. /// </summary>
  152. public static void RestoreActiveObject()
  153. {
  154. if (_lasthObj != IntPtr.Zero)
  155. SelectObject(_hdc, _lasthObj);
  156. if ((_hdc != IntPtr.Zero) && (_lastGraphics != null))
  157. _lastGraphics.ReleaseHdc();
  158. if (_hFont != IntPtr.Zero)
  159. DeleteObject(_hFont);
  160. if (_tempFont != null)
  161. _tempFont.Dispose();
  162. _tempFont = null;
  163. _hFont = IntPtr.Zero;
  164. _lasthObj = IntPtr.Zero;
  165. _hdc = IntPtr.Zero;
  166. _lastGraphics = null;
  167. }
  168. /// <summary>
  169. /// Function to get the kerning pairs for a font.
  170. /// </summary>
  171. /// <returns>A list of kerning pair values for the active font.</returns>
  172. public static IList<KERNINGPAIR> GetKerningPairs()
  173. {
  174. int size = 0;
  175. KERNINGPAIR[] pairs = null;
  176. MapModes lastMapMode = MapModes.MM_TEXT;
  177. #if DEBUG
  178. if (_hdc == IntPtr.Zero)
  179. throw new GorgonException(GorgonResult.CannotEnumerate, "Cannot retrieve kerning pairs. No device context.");
  180. #endif
  181. lastMapMode = SetMapMode(_hdc, MapModes.MM_TEXT);
  182. // Get the number of pairs.
  183. size = (int)GetKerningPairsW(_hdc, 0, null);
  184. // If we have no pairs, then leave here.
  185. if (size == 0)
  186. return new KERNINGPAIR[0];
  187. pairs = new KERNINGPAIR[size];
  188. KERNINGPAIR* pairPtr = stackalloc KERNINGPAIR[size];
  189. if (GetKerningPairsW(_hdc, (uint)size, pairPtr) == 0)
  190. throw new InvalidOperationException("Could not retrieve character kerning pairs.");
  191. for(int i = 0; i < size; i++)
  192. pairs[i] = pairPtr[i];
  193. return pairs;
  194. }
  195. /// <summary>
  196. /// Function to get the ABC kerning widths for the active font object.
  197. /// </summary>
  198. /// <param name="firstCharacter">First character to return.</param>
  199. /// <param name="lastCharacter">Last character to return.</param>
  200. /// <returns>A list of font ABC values.</returns>
  201. public static IDictionary<char, ABC> GetCharABCWidths(char firstCharacter, char lastCharacter)
  202. {
  203. uint firstCharIndex = Convert.ToUInt32(firstCharacter);
  204. uint lastCharIndex = Convert.ToUInt32(lastCharacter);
  205. int size = (int)(lastCharIndex - firstCharIndex) + 1;
  206. SortedDictionary<char, ABC> result = new SortedDictionary<char, ABC>();
  207. #if DEBUG
  208. if (_hdc == IntPtr.Zero)
  209. throw new GorgonException(GorgonResult.CannotEnumerate, "Cannot retrieve ABC widths. No device context.");
  210. #endif
  211. ABC* abcData = stackalloc ABC[size];
  212. if (!GetCharABCWidthsW(_hdc, firstCharIndex, lastCharIndex, abcData))
  213. throw new InvalidOperationException("Could not retrieve character widths for the specified characters.");
  214. // Copy to our result.
  215. for (int i = 0; i < size; i++)
  216. result.Add(Convert.ToChar(i + Convert.ToInt32(firstCharacter)), abcData[i]);
  217. return result;
  218. }
  219. #endregion
  220. }
  221. }