public static extern uint GetCharacterPlacementW(IntPtr hdc, [MarshalAs(UnmanagedType.LPWStr)] string lpString, int nCount, int nMaxExtent, ref GCP_RESULTS lpResults, GCPFlags dwFlags);
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(); } }