private extern static int GetCharacterPlacement( IntPtr hdc, string lpString, int nCount, int nMaxExtent, ref GCP_RESULTS lpResults, int dwFlags);
public Rectangle[] MeasureCharacterRanges( Graphics graphics, string text, RectangleF layoutRect, GraphicsUnit pageUnit) { Rectangle bounds = Rectangle.Empty; if (layoutRect.IsEmpty) { bounds = new Rectangle(0, 0, 1000, 1000); } else { bounds = Rectangle.Round(layoutRect); } IntPtr hdc = graphics.GetHdc(); try { IntPtr oldFont = SelectObject(hdc, this.Handle); GCP_RESULTS gcpResults = new GCP_RESULTS(); gcpResults.lStructSize = Marshal.SizeOf(typeof(GCP_RESULTS)); gcpResults.lpOutString = IntPtr.Zero; gcpResults.lpOrder = IntPtr.Zero; gcpResults.lpDx = IntPtr.Zero; gcpResults.lpCaretPos = Marshal.AllocCoTaskMem(sizeof(int) * text.Length); gcpResults.lpClass = IntPtr.Zero; gcpResults.lpGlyphs = IntPtr.Zero; gcpResults.nGlyphs = text.Length; GetCharacterPlacement( hdc, text, text.Length, 0, ref gcpResults, GcpFlags.GCP_USEKERNING | GcpFlags.GCP_LIGATE); int count = text.Length; Rectangle[] result = new Rectangle[count]; int prevPos = Marshal.ReadInt32(gcpResults.lpCaretPos, 0); for (int i = 0; i < count - 1; i++) { int nextPos = Marshal.ReadInt32(gcpResults.lpCaretPos, (i + 1) * sizeof(int)); result[i] = new Rectangle(bounds.X + prevPos, bounds.Y, nextPos - prevPos, bounds.Height); prevPos = nextPos; } if (count > 0) { result[count - 1] = new Rectangle(bounds.X + prevPos, bounds.Y, bounds.Width - prevPos, bounds.Height); } Marshal.FreeCoTaskMem(gcpResults.lpCaretPos); SelectObject(hdc, oldFont); return(result); } finally { graphics.ReleaseHdc(hdc); } }
public static void GetCharacterPlacement(DeviceContextSafeHandle hdc, string text, GCPFlags flags, out GcpResults gcpResults) { int len = text.Length; gcpResults = new GcpResults { Order = new int[len], Dx = new int[len], CaretPos = new int[len], Class = new byte[len], Glyphs = new short[len], }; GCHandle ordHnd = GCHandle.Alloc(gcpResults.Order, GCHandleType.Pinned); GCHandle dxHnd = GCHandle.Alloc(gcpResults.Dx, GCHandleType.Pinned); GCHandle carHnd = GCHandle.Alloc(gcpResults.CaretPos, GCHandleType.Pinned); GCHandle clsHnd = GCHandle.Alloc(gcpResults.Class, GCHandleType.Pinned); GCHandle glyHnd = GCHandle.Alloc(gcpResults.Glyphs, GCHandleType.Pinned); try { GCP_RESULTS rs = new GCP_RESULTS { StructSize = Marshal.SizeOf(typeof(GCP_RESULTS)), OutString = new String('\0', len + 2), Order = ordHnd.AddrOfPinnedObject(), Dx = dxHnd.AddrOfPinnedObject(), CaretPos = carHnd.AddrOfPinnedObject(), Class = clsHnd.AddrOfPinnedObject(), Glyphs = glyHnd.AddrOfPinnedObject(), GlyphCount = len, MaxFit = 0 }; uint r = GetCharacterPlacement(hdc, text, len, 0, ref rs, (uint)flags); if (r == 0 && Marshal.GetLastWin32Error() != 0) { throw new Win32Exception(); } gcpResults.OutString = rs.OutString; gcpResults.MaxFit = rs.MaxFit; return; } finally { ordHnd.Free(); dxHnd.Free(); carHnd.Free(); clsHnd.Free(); glyHnd.Free(); } }
[DllImport("gdi32.dll", EntryPoint="GetCharacterPlacementW")] public static extern uint GetCharacterPlacementW( IntPtr hdc, [MarshalAs(UnmanagedType.LPWStr)] string lpString, int nCount, int nMaxExtent, ref GCP_RESULTS lpResults, uint dwFlags );
static extern int GetCharacterPlacement( IntPtr hdc, string lpString, int nCount, int nMaxExtent, ref GCP_RESULTS lpResults, uint dwFlags );
[DllImport("gdi32.dll", EntryPoint = "GetCharacterPlacementW")] public static extern uint GetCharacterPlacementW(IntPtr hdc, [MarshalAs(UnmanagedType.LPWStr)] string lpString, int nCount, int nMaxExtent, ref GCP_RESULTS lpResults, uint dwFlags);
public static extern uint GetCharacterPlacementW(IntPtr hdc, [MarshalAs(UnmanagedType.LPWStr)] string lpString, int nCount, int nMaxExtent, ref GCP_RESULTS lpResults, GCPFlags dwFlags);
static extern uint GetCharacterPlacement(DeviceContextSafeHandle hdc, [MarshalAs(UnmanagedType.LPWStr)] string lpString, int nCount, int nMaxExtent, ref GCP_RESULTS lpResults, uint dwFlags);