einfache 2D Objekte per Direct2D, ohne Verweis oder NuGet-Pakete, zeichnen

    • VB.NET
    • .NET (FX) 4.5–4.8

    Es gibt 19 Antworten in diesem Thema. Der letzte Beitrag () ist von simpelSoft.

      einfache 2D Objekte per Direct2D, ohne Verweis oder NuGet-Pakete, zeichnen

      Hi@all

      Es gab vor kurzem einen Thread mit der Frage nach alternativen zu GDI+ zum zeichnen einfacher 2D Objekte. Der Threadersteller hat zwar eine Lösung für seine Frage gefunden, dennoch möchte ich Euch eine Möglichkeit per Direct2D nicht vorenthalten, weil ich dieses Projekt extra dafür angefangen hatte. Für dieses einfache Direct2D Beispiel werden keine Verweise oder Downloads zu irgendwelchen NuGet-Paketen benötigt. Man baut halt nur das an Funktionen ein, was man auch wirklich benötigt.

      Dieses Direct2D Beispiel ist relativ einfach gehalten (nicht vollständig, nur ein paar Funktionen zum testen) um einfache 2D Objekte zu zeichnen und nutzt nur Pointer auf die entsprechende Interfaces, Funktionen, Delegates und die Funktionsnummer aus der VTable der Interfaces. Dieses Beispiel ist speziell für Multithreading ausgelegt und soll nur zeigen wie man COM-Interfaces, bzw. nur einzelne Funktionen eines Interfaces nutzen kann, ohne die Interfaces komplett im Code einzubauen.
      Bilder
      • Direct2D_Sample.png

        914,5 kB, 1.011×473, 102 mal angesehen
      Dateien
      Mfg -Franky-
      Hab etwas rumgefuhrwerkt und es dann nach kopieren von Daten aus einem anderen Projekt zum Laufen gebracht. Nuja …
      Aber schau mer mal, ist doch unter der Haupt ziemlich komplex.

      ##########

      Mir kam das komisch vor, dass in der Sub D2D1Draw random immer wieder neu instanziiert wird und hatte ihn mal da rausgezogen und somit klassenweit gemacht. Dann ist aber nach 4-5 Redraws Dusterbusch angesagt. 8| Ich sehe, dass ich den Code noch weniger verstehe als gedacht.
      Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

      Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VaporiZed“ ()

      Hi

      Sorry wenn ich da zuviel aus dem Projektordner gelöscht habe. Ich werde den Upload zeitnah erneuern bzw. die fehlenden Dateien nachreichen.

      @VaporiZed: Komplex ist ja relativ. Wenn man das Prinzip verstanden hat, ist es ganz einfach.

      Ganz grob funktioniert das so: Hole mir den Funtionspointer einer bestimmten Funktion aus der VTable von einem COM-Interface Pointer und führe diese Funktion mit den entsprechenden Parametern der Funktion aus.
      Mfg -Franky-

      VaporiZed schrieb:

      ist doch unter der Haupt ziemlich komplex

      Geht mir auch so. Ich saß an dem IMFMediaEngine(Ex) Player eine halbe Ewigkeit um den ans laufen zu bekommen. Diese COM-Interfaces sind absolut nichts für mich. Aber an dem Code sieht man ja, dass -Franky- noch von der ganz alten Schule ist, damals hatte man es eben noch richtig drauf. Heutzutage denkt doch jeder der ein bisschen JavaScript kann das er Experte sei.
      Hi@all

      Hab das ganze hier noch einmal Hochgeladen. Jetzt sollten alle Dateien vorhanden sein.

      @Bluespide
      Das ich mich viel mit COM-Interfaces beschäftige liegt einfach daran das mir das .NET-Framework einfach nicht alles bietet, nicht vorhanden oder veraltet ist, um bestimmte Dinge programmieren zu können. Das ganze entstand aber noch unter VB6 und liegt schon länger zurück. Auch da verwende ich so entsprechende COM-Interfaces. Das ganze hat auch einen einfachen Grund. Entweder gibt es keine Verweise/DLLs/TLBs die man nutzen kann oder man muss sich für .NET ein passendes NuGet Paket installieren. Nun brauch ich aber vllt nur 4 oder 5 Funktionen von ein paar COM-Interfaces. Dazu extra ein riesen NuGet Paket herunterladen mit Sachen die ich nicht benötige? Was liegt da näher selbst entsprechende COM-Interfaces, die ich benötige, im Code einzubauen und zu nutzen. So wie mit der IMFMediaEngine. Da ist das ja noch recht überschaubar an Funktionen. Was aber machen wenn man z.B. die Funktion CreateSvgDocument vom Interface ID2D1DeviceContext5 nutzen möchte? 8 komplette Interfaces einbauen um nur eine Funktion aus diesem Interface zu nutzen? Neeeeee. Da rufe ich einfach die 115. Funktion des Interfaces ID2D1DeviceContext5 auf. So wie in diesem Direct2D Beispiel.
      Dateien
      Mfg -Franky-
      Ok, das Vorgehen vom Prinzip her ist mir jetzt klar. Aber der Weg dorthin ist mir neu. Und die Doku, wo was zu finden ist, allein Private Const IID_ID2D1Factory1 As String = "bb12d362-daee-4b9a-aa1d-14ba401cfa1f", ist für mich erstmal komplett unklar. Kannst Du da etwas Licht ins Dunkel bringen?
      Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

      Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
      Hi VaporiZed

      Deine Frage ist schnell beantwortet. Alles was Du benötigst sind die Header-Dateien aus dem SDK. Für Deine Frage die Datei d2d1_1.h. In welcher Header-Datei Du was findest, steht in der MSDN wenn Du nach diesem Interface suchst. In der d2d1_1.h findest Du die IIDs zu den enthaltenen Interfaces, das Interface selber und die entsprechenden Funktionen des Interfaces.
      Mfg -Franky-
      Versuch es mal mit dem. Habe ich übersetzen lassen.
      Kleinere Anpassungen sind wahrscheinlich trotzdem noch notwendig.

      Freundliche Grüsse

      exc-jdbi


      Spoiler anzeigen

      Quellcode

      1. using System.Runtime.InteropServices;
      2. internal static partial class modDirect2D
      3. {
      4. #region Const
      5. public const int S_OK = 0;
      6. public const int D3D_FEATURE_LEVEL_9_1 = 37120;
      7. public const int D3D_FEATURE_LEVEL_10_0 = 40960;
      8. private const string IID_ID2D1Factory1 = "bb12d362-daee-4b9a-aa1d-14ba401cfa1f";
      9. #endregion
      10. #region Enum
      11. // Interface function numbers
      12. // Function numbers according to the VTable for the corresponding interface.
      13. private enum VTable_Interfaces : int
      14. {
      15. // ----==== IUnknown ====----
      16. // QueryInterface = 0
      17. // AddRef = 1
      18. // Release = 2
      19. // ----==== ID2D1Factory ====----
      20. CreateHwndRenderTarget = 14,
      21. // ----==== ID2D1RenderTarget ====----
      22. CreateSolidColorBrush = 8,
      23. DrawLine = 15,
      24. DrawRectangle = 16,
      25. FillRectangle = 17,
      26. DrawRoundedRectangle = 18,
      27. FillRoundedRectangle = 19,
      28. Clear = 47,
      29. BeginDraw = 48,
      30. EndDraw = 49,
      31. // ----==== ID2D1HwndRenderTarget ====----
      32. Resize = 58,
      33. // ----==== ID2D1SolidColorBrush ====----
      34. SetColor = 8
      35. }
      36. public enum D2D1_FACTORY_TYPE : int
      37. {
      38. D2D1_FACTORY_TYPE_SINGLE_THREADEDField = 0,
      39. D2D1_FACTORY_TYPE_MULTI_THREADEDField = 1
      40. }
      41. public enum D2D1_DEBUG_LEVEL : int
      42. {
      43. D2D1_DEBUG_LEVEL_NONEField = 0,
      44. D2D1_DEBUG_LEVEL_ERRORField = 1,
      45. D2D1_DEBUG_LEVEL_WARNINGField = 2,
      46. D2D1_DEBUG_LEVEL_INFORMATIONField = 3
      47. }
      48. public enum DXGI_FORMAT : int
      49. {
      50. DXGI_FORMAT_UNKNOWNField = 0,
      51. DXGI_FORMAT_R32G32B32A32_TYPELESSField = 1,
      52. DXGI_FORMAT_R32G32B32A32_FLOATField = 2,
      53. DXGI_FORMAT_R32G32B32A32_UINTField = 3,
      54. DXGI_FORMAT_R32G32B32A32_SINTField = 4,
      55. DXGI_FORMAT_R32G32B32_TYPELESSField = 5,
      56. DXGI_FORMAT_R32G32B32_FLOATField = 6,
      57. DXGI_FORMAT_R32G32B32_UINTField = 7,
      58. DXGI_FORMAT_R32G32B32_SINTField = 8,
      59. DXGI_FORMAT_R16G16B16A16_TYPELESSField = 9,
      60. DXGI_FORMAT_R16G16B16A16_FLOATField = 10,
      61. DXGI_FORMAT_R16G16B16A16_UNORMField = 11,
      62. DXGI_FORMAT_R16G16B16A16_UINTField = 12,
      63. DXGI_FORMAT_R16G16B16A16_SNORMField = 13,
      64. DXGI_FORMAT_R16G16B16A16_SINTField = 14,
      65. DXGI_FORMAT_R32G32_TYPELESSField = 15,
      66. DXGI_FORMAT_R32G32_FLOATField = 16,
      67. DXGI_FORMAT_R32G32_UINTField = 17,
      68. DXGI_FORMAT_R32G32_SINTField = 18,
      69. DXGI_FORMAT_R32G8X24_TYPELESSField = 19,
      70. DXGI_FORMAT_D32_FLOAT_S8X24_UINTField = 20,
      71. DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESSField = 21,
      72. DXGI_FORMAT_X32_TYPELESS_G8X24_UINTField = 22,
      73. DXGI_FORMAT_R10G10B10A2_TYPELESSField = 23,
      74. DXGI_FORMAT_R10G10B10A2_UNORMField = 24,
      75. DXGI_FORMAT_R10G10B10A2_UINTField = 25,
      76. DXGI_FORMAT_R11G11B10_FLOATField = 26,
      77. DXGI_FORMAT_R8G8B8A8_TYPELESSField = 27,
      78. DXGI_FORMAT_R8G8B8A8_UNORMField = 28,
      79. DXGI_FORMAT_R8G8B8A8_UNORM_SRGBField = 29,
      80. DXGI_FORMAT_R8G8B8A8_UINTField = 30,
      81. DXGI_FORMAT_R8G8B8A8_SNORMField = 31,
      82. DXGI_FORMAT_R8G8B8A8_SINTField = 32,
      83. DXGI_FORMAT_R16G16_TYPELESSField = 33,
      84. DXGI_FORMAT_R16G16_FLOATField = 34,
      85. DXGI_FORMAT_R16G16_UNORMField = 35,
      86. DXGI_FORMAT_R16G16_UINTField = 36,
      87. DXGI_FORMAT_R16G16_SNORMField = 37,
      88. DXGI_FORMAT_R16G16_SINTField = 38,
      89. DXGI_FORMAT_R32_TYPELESSField = 39,
      90. DXGI_FORMAT_D32_FLOATField = 40,
      91. DXGI_FORMAT_R32_FLOATField = 41,
      92. DXGI_FORMAT_R32_UINTField = 42,
      93. DXGI_FORMAT_R32_SINTField = 43,
      94. DXGI_FORMAT_R24G8_TYPELESSField = 44,
      95. DXGI_FORMAT_D24_UNORM_S8_UINTField = 45,
      96. DXGI_FORMAT_R24_UNORM_X8_TYPELESSField = 46,
      97. DXGI_FORMAT_X24_TYPELESS_G8_UINTField = 47,
      98. DXGI_FORMAT_R8G8_TYPELESSField = 48,
      99. DXGI_FORMAT_R8G8_UNORMField = 49,
      100. DXGI_FORMAT_R8G8_UINTField = 50,
      101. DXGI_FORMAT_R8G8_SNORMField = 51,
      102. DXGI_FORMAT_R8G8_SINTField = 52,
      103. DXGI_FORMAT_R16_TYPELESSField = 53,
      104. DXGI_FORMAT_R16_FLOATField = 54,
      105. DXGI_FORMAT_D16_UNORMField = 55,
      106. DXGI_FORMAT_R16_UNORMField = 56,
      107. DXGI_FORMAT_R16_UINTField = 57,
      108. DXGI_FORMAT_R16_SNORMField = 58,
      109. DXGI_FORMAT_R16_SINTField = 59,
      110. DXGI_FORMAT_R8_TYPELESSField = 60,
      111. DXGI_FORMAT_R8_UNORMField = 61,
      112. DXGI_FORMAT_R8_UINTField = 62,
      113. DXGI_FORMAT_R8_SNORMField = 63,
      114. DXGI_FORMAT_R8_SINTField = 64,
      115. DXGI_FORMAT_A8_UNORMField = 65,
      116. DXGI_FORMAT_R1_UNORMField = 66,
      117. DXGI_FORMAT_R9G9B9E5_SHAREDEXPField = 67,
      118. DXGI_FORMAT_R8G8_B8G8_UNORMField = 68,
      119. DXGI_FORMAT_G8R8_G8B8_UNORMField = 69,
      120. DXGI_FORMAT_BC1_TYPELESSField = 70,
      121. DXGI_FORMAT_BC1_UNORMField = 71,
      122. DXGI_FORMAT_BC1_UNORM_SRGBField = 72,
      123. DXGI_FORMAT_BC2_TYPELESSField = 73,
      124. DXGI_FORMAT_BC2_UNORMField = 74,
      125. DXGI_FORMAT_BC2_UNORM_SRGBField = 75,
      126. DXGI_FORMAT_BC3_TYPELESSField = 76,
      127. DXGI_FORMAT_BC3_UNORMField = 77,
      128. DXGI_FORMAT_BC3_UNORM_SRGBField = 78,
      129. DXGI_FORMAT_BC4_TYPELESSField = 79,
      130. DXGI_FORMAT_BC4_UNORMField = 80,
      131. DXGI_FORMAT_BC4_SNORMField = 81,
      132. DXGI_FORMAT_BC5_TYPELESSField = 82,
      133. DXGI_FORMAT_BC5_UNORMField = 83,
      134. DXGI_FORMAT_BC5_SNORMField = 84,
      135. DXGI_FORMAT_B5G6R5_UNORMField = 85,
      136. DXGI_FORMAT_B5G5R5A1_UNORMField = 86,
      137. DXGI_FORMAT_B8G8R8A8_UNORMField = 87,
      138. DXGI_FORMAT_B8G8R8X8_UNORMField = 88,
      139. DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORMField = 89,
      140. DXGI_FORMAT_B8G8R8A8_TYPELESSField = 90,
      141. DXGI_FORMAT_B8G8R8A8_UNORM_SRGBField = 91,
      142. DXGI_FORMAT_B8G8R8X8_TYPELESSField = 92,
      143. DXGI_FORMAT_B8G8R8X8_UNORM_SRGBField = 93,
      144. DXGI_FORMAT_BC6H_TYPELESSField = 94,
      145. DXGI_FORMAT_BC6H_UF16Field = 95,
      146. DXGI_FORMAT_BC6H_SF16Field = 96,
      147. DXGI_FORMAT_BC7_TYPELESSField = 97,
      148. DXGI_FORMAT_BC7_UNORMField = 98,
      149. DXGI_FORMAT_BC7_UNORM_SRGBField = 99,
      150. DXGI_FORMAT_AYUVField = 100,
      151. DXGI_FORMAT_Y410Field = 101,
      152. DXGI_FORMAT_Y416Field = 102,
      153. DXGI_FORMAT_NV12Field = 103,
      154. DXGI_FORMAT_P010Field = 104,
      155. DXGI_FORMAT_P016Field = 105,
      156. DXGI_FORMAT_420_OPAQUEField = 106,
      157. DXGI_FORMAT_YUY2Field = 107,
      158. DXGI_FORMAT_Y210Field = 108,
      159. DXGI_FORMAT_Y216Field = 109,
      160. DXGI_FORMAT_NV11Field = 110,
      161. DXGI_FORMAT_AI44Field = 111,
      162. DXGI_FORMAT_IA44Field = 112,
      163. DXGI_FORMAT_P8Field = 113,
      164. DXGI_FORMAT_A8P8Field = 114,
      165. DXGI_FORMAT_B4G4R4A4_UNORMField = 115,
      166. DXGI_FORMAT_P208Field = 130,
      167. DXGI_FORMAT_V208Field = 131,
      168. DXGI_FORMAT_V408Field = 132
      169. }
      170. public enum D2D1_ALPHA_MODE : int
      171. {
      172. D2D1_ALPHA_MODE_UNKNOWNField = 0,
      173. D2D1_ALPHA_MODE_PREMULTIPLIEDField = 1,
      174. D2D1_ALPHA_MODE_STRAIGHTField = 2,
      175. D2D1_ALPHA_MODE_IGNOREField = 3
      176. }
      177. public enum D2D1_RENDER_TARGET_TYPE : int
      178. {
      179. D2D1_RENDER_TARGET_TYPE_DEFAULTField = 0,
      180. D2D1_RENDER_TARGET_TYPE_SOFTWAREField = 1,
      181. D2D1_RENDER_TARGET_TYPE_HARDWAREField = 2
      182. }
      183. public enum D2D1_RENDER_TARGET_USAGE : int
      184. {
      185. D2D1_RENDER_TARGET_USAGE_NONEField = 0,
      186. D2D1_RENDER_TARGET_USAGE_FORCE_BITMAP_REMOTINGField = 1,
      187. D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLEField = 2
      188. }
      189. public enum D2D1_FEATURE_LEVEL : int
      190. {
      191. D2D1_FEATURE_LEVEL_DEFAULTField = 0,
      192. D2D1_FEATURE_LEVEL_9Field = D3D_FEATURE_LEVEL_9_1,
      193. D2D1_FEATURE_LEVEL_10Field = D3D_FEATURE_LEVEL_10_0
      194. }
      195. public enum D2D1_PRESENT_OPTIONS : int
      196. {
      197. D2D1_PRESENT_OPTIONS_NONEField = 0,
      198. D2D1_PRESENT_OPTIONS_RETAIN_CONTENTSField = 1,
      199. D2D1_PRESENT_OPTIONS_IMMEDIATELYField = 2
      200. }
      201. #endregion
      202. #region Structure
      203. public partial struct D2D1_PIXEL_FORMAT
      204. {
      205. public DXGI_FORMAT dFormat;
      206. public D2D1_ALPHA_MODE AlphaMode;
      207. public D2D1_PIXEL_FORMAT(D2D1_ALPHA_MODE eAlphaMode)
      208. {
      209. AlphaMode = eAlphaMode;
      210. }
      211. }
      212. public partial struct D2D1_RENDER_TARGET_PROPERTIES
      213. {
      214. public D2D1_RENDER_TARGET_TYPE etype;
      215. public D2D1_PIXEL_FORMAT PixelFormat;
      216. public float DpiX;
      217. public float DpiY;
      218. public D2D1_RENDER_TARGET_USAGE Usage;
      219. public D2D1_FEATURE_LEVEL minLevel;
      220. public D2D1_RENDER_TARGET_PROPERTIES(D2D1_PIXEL_FORMAT tPixelFormat)
      221. {
      222. PixelFormat = tPixelFormat;
      223. }
      224. }
      225. public partial struct D2D1_SIZE_U
      226. {
      227. public int Width;
      228. public int Height;
      229. public D2D1_SIZE_U(int intWidth, int intHeight)
      230. {
      231. Width = intWidth;
      232. Height = intHeight;
      233. }
      234. }
      235. public partial struct D2D1_HWND_RENDER_TARGET_PROPERTIES
      236. {
      237. public IntPtr hwnd;
      238. public D2D1_SIZE_U pixelSize;
      239. public D2D1_PRESENT_OPTIONS presentOptions;
      240. public D2D1_HWND_RENDER_TARGET_PROPERTIES(IntPtr pHwnd)
      241. {
      242. hwnd = pHwnd;
      243. }
      244. }
      245. public partial struct D2D1_FACTORY_OPTIONS
      246. {
      247. public D2D1_DEBUG_LEVEL debugLevel;
      248. public D2D1_FACTORY_OPTIONS(D2D1_DEBUG_LEVEL eDebugLevel = D2D1_DEBUG_LEVEL.D2D1_DEBUG_LEVEL_NONE)
      249. {
      250. debugLevel = eDebugLevel;
      251. }
      252. }
      253. public partial struct D2D1_COLOR_F
      254. {
      255. public float r;
      256. public float g;
      257. public float b;
      258. public float a;
      259. public D2D1_COLOR_F(float sngA = 1f, float sngR = 0f, float sngG = 0f, float sngB = 0f)
      260. {
      261. r = sngR;
      262. g = sngG;
      263. b = sngB;
      264. a = sngA;
      265. }
      266. }
      267. public partial struct D2D1_MATRIX_3X2_F
      268. {
      269. public float m_11;
      270. public float m_12;
      271. public float m_21;
      272. public float m_22;
      273. public float m_31;
      274. public float m_32;
      275. }
      276. public partial struct D2D1_BRUSH_PROPERTIES
      277. {
      278. public float opacity;
      279. public D2D1_MATRIX_3X2_F transform;
      280. public D2D1_BRUSH_PROPERTIES(float sngOpacity)
      281. {
      282. opacity = sngOpacity;
      283. }
      284. }
      285. public partial struct D2D1_TAG
      286. {
      287. public ulong value;
      288. }
      289. public partial struct D2D1_POINT_2F
      290. {
      291. public float x;
      292. public float y;
      293. public D2D1_POINT_2F(float sngX, float sngY)
      294. {
      295. x = sngX;
      296. y = sngY;
      297. }
      298. }
      299. public partial struct D2D1_RECT_F
      300. {
      301. public float left;
      302. public float top;
      303. public float right;
      304. public float bottom;
      305. public D2D1_RECT_F(float sngLeft, float sngTop, float sngRight, float sngBottom)
      306. {
      307. left = sngLeft;
      308. top = sngTop;
      309. right = sngRight;
      310. bottom = sngBottom;
      311. }
      312. }
      313. public partial struct D2D1_ROUNDED_RECT
      314. {
      315. public D2D1_RECT_F rect;
      316. public float radiusX;
      317. public float radiusY;
      318. public D2D1_ROUNDED_RECT(D2D1_RECT_F tRect, float sngRadiusX, float sngRadiusY)
      319. {
      320. rect = tRect;
      321. radiusX = sngRadiusX;
      322. radiusY = sngRadiusY;
      323. }
      324. }
      325. #endregion
      326. #region API
      327. [DllImport("D2d1.dll", EntryPoint = "D2D1CreateFactory")]
      328. [PreserveSig]
      329. private static extern int D2D1CreateFactory([In] D2D1_FACTORY_TYPE factoryType, [In] ref Guid riid, [In] ref D2D1_FACTORY_OPTIONS pFactoryOptions, out IntPtr ppIFactory);
      330. #endregion
      331. #region Delegates
      332. // ----==== ID2D1Factory ====----
      333. private delegate int ID2D1Factory_CreateHwndRenderTarget([In] IntPtr @this, [In] ref D2D1_RENDER_TARGET_PROPERTIES renderTargetProperties, [In] ref D2D1_HWND_RENDER_TARGET_PROPERTIES hwndRenderTargetProperties, out IntPtr ppID2D1HwndRenderTarget);
      334. // ----==== ID2D1RenderTarget ====----
      335. private delegate int ID2D1RenderTarget_CreateSolidColorBrush([In] IntPtr @this, [In] ref D2D1_COLOR_F color, [In] ref D2D1_BRUSH_PROPERTIES brushProperties, out IntPtr ppID2D1SolidColorBrush);
      336. private delegate void ID2D1RenderTarget_DrawLine([In] IntPtr @this, [In] D2D1_POINT_2F point0, [In] D2D1_POINT_2F point1, [In] IntPtr brush, [In] float strokeWidth, [In] IntPtr strokeStyle);
      337. private delegate void ID2D1RenderTarget_DrawRectangle([In] IntPtr @this, [In] ref D2D1_RECT_F rect, [In] IntPtr brush, [In] float strokeWidth, [In] IntPtr strokeStyle);
      338. private delegate void ID2D1RenderTarget_FillRectangle([In] IntPtr @this, [In] ref D2D1_RECT_F rect, [In] IntPtr brush);
      339. private delegate void ID2D1RenderTarget_DrawRoundedRectangle([In] IntPtr @this, [In] ref D2D1_ROUNDED_RECT roundedRect, [In] IntPtr brush, [In] float strokeWidth, [In] IntPtr strokeStyle);
      340. private delegate void ID2D1RenderTarget_FillRoundedRectangle([In] IntPtr @this, [In] ref D2D1_ROUNDED_RECT roundedRect, [In] IntPtr brush);
      341. private delegate void ID2D1RenderTarget_Clear([In] IntPtr @this, [In] ref D2D1_COLOR_F color);
      342. private delegate void ID2D1RenderTarget_BeginDraw([In] IntPtr @this);
      343. private delegate int ID2D1RenderTarget_EndDraw([In] IntPtr @this, out D2D1_TAG tag1, out D2D1_TAG tag2);
      344. // ----==== ID2D1HwndRenderTarget ====----
      345. private delegate int ID2D1HwndRenderTarget_Resize([In] IntPtr @this, [In] ref D2D1_SIZE_U pixelSize);
      346. // ----==== ID2D1SolidColorBrush ====----
      347. private delegate void ID2D1SolidColorBrush_SetColor([In] IntPtr @this, [In] ref D2D1_COLOR_F color);
      348. #endregion
      349. #region Functions
      350. // ----==== Creates the ID2D1Factory1 interface ====----
      351. public static IntPtr CreateID2D1Factory1(D2D1_FACTORY_OPTIONS tD2D1FactoryOptions, D2D1_FACTORY_TYPE eFactoryType = D2D1_FACTORY_TYPE.D2D1_FACTORY_TYPE_SINGLE_THREADED)
      352. {
      353. var pRet = IntPtr.Zero;
      354. var pID2D1Factory1 = IntPtr.Zero;
      355. if (D2D1CreateFactory(eFactoryType, new Guid(IID_ID2D1Factory1), tD2D1FactoryOptions, pID2D1Factory1) == S_OK)
      356. {
      357. pRet = pID2D1Factory1;
      358. }
      359. return pRet;
      360. }
      361. // ----==== ID2D1Factory Functions ====----
      362. public static IntPtr CreateHwndRenderTarget(IntPtr pID2D1Factory, D2D1_RENDER_TARGET_PROPERTIES renderTargetProperties, D2D1_HWND_RENDER_TARGET_PROPERTIES hwndRenderTargetProperties)
      363. {
      364. var pRet = IntPtr.Zero;
      365. var pVTablePtr = IntPtr.Zero;
      366. var pID2D1HwndRenderTarget = IntPtr.Zero;
      367. if (pID2D1Factory != IntPtr.Zero)
      368. {
      369. if (GetVTablePtr(pID2D1Factory, VTable_Interfaces.CreateHwndRenderTarget, ref pVTablePtr))
      370. {
      371. ID2D1Factory_CreateHwndRenderTarget Method = (ID2D1Factory_CreateHwndRenderTarget)Marshal.GetDelegateForFunctionPointer(pVTablePtr, typeof(ID2D1Factory_CreateHwndRenderTarget));
      372. if (Method.Invoke(pID2D1Factory, renderTargetProperties, hwndRenderTargetProperties, pID2D1HwndRenderTarget) == S_OK)
      373. {
      374. pRet = pID2D1HwndRenderTarget;
      375. }
      376. }
      377. }
      378. return pRet;
      379. }
      380. // ----==== ID2D1RenderTarget Functions ====----
      381. public static void RenderTarget_DrawLine(IntPtr pID2D1RenderTarget, D2D1_POINT_2F point0, D2D1_POINT_2F point1, IntPtr brush, float strokeWidth = 1f, IntPtr strokeStyle = default)
      382. {
      383. var pVTablePtr = IntPtr.Zero;
      384. if (pID2D1RenderTarget != IntPtr.Zero)
      385. {
      386. if (GetVTablePtr(pID2D1RenderTarget, VTable_Interfaces.DrawLine, ref pVTablePtr))
      387. {
      388. ID2D1RenderTarget_DrawLine Method = (ID2D1RenderTarget_DrawLine)Marshal.GetDelegateForFunctionPointer(pVTablePtr, typeof(ID2D1RenderTarget_DrawLine));
      389. Method.Invoke(pID2D1RenderTarget, point0, point1, brush, strokeWidth, strokeStyle);
      390. }
      391. }
      392. }
      393. public static void RenderTarget_DrawRectangle(IntPtr pID2D1RenderTarget, D2D1_RECT_F rect, IntPtr brush, float strokeWidth = 1f, IntPtr strokeStyle = default)
      394. {
      395. var pVTablePtr = IntPtr.Zero;
      396. if (pID2D1RenderTarget != IntPtr.Zero)
      397. {
      398. if (GetVTablePtr(pID2D1RenderTarget, VTable_Interfaces.DrawRectangle, ref pVTablePtr))
      399. {
      400. ID2D1RenderTarget_DrawRectangle Method = (ID2D1RenderTarget_DrawRectangle)Marshal.GetDelegateForFunctionPointer(pVTablePtr, typeof(ID2D1RenderTarget_DrawRectangle));
      401. Method.Invoke(pID2D1RenderTarget, rect, brush, strokeWidth, strokeStyle);
      402. }
      403. }
      404. }
      405. public static void RenderTarget_FillRectangle(IntPtr pID2D1RenderTarget, D2D1_RECT_F rect, IntPtr brush)
      406. {
      407. var pVTablePtr = IntPtr.Zero;
      408. if (pID2D1RenderTarget != IntPtr.Zero)
      409. {
      410. if (GetVTablePtr(pID2D1RenderTarget, VTable_Interfaces.FillRectangle, ref pVTablePtr))
      411. {
      412. ID2D1RenderTarget_FillRectangle Method = (ID2D1RenderTarget_FillRectangle)Marshal.GetDelegateForFunctionPointer(pVTablePtr, typeof(ID2D1RenderTarget_FillRectangle));
      413. Method.Invoke(pID2D1RenderTarget, rect, brush);
      414. }
      415. }
      416. }
      417. public static void RenderTarget_DrawRoundedRectangle(IntPtr pID2D1RenderTarget, D2D1_ROUNDED_RECT roundedRect, IntPtr brush, float strokeWidth = 1f, IntPtr strokeStyle = default)
      418. {
      419. var pVTablePtr = IntPtr.Zero;
      420. if (GetVTablePtr(pID2D1RenderTarget, VTable_Interfaces.DrawRoundedRectangle, ref pVTablePtr))
      421. {
      422. if (pVTablePtr != IntPtr.Zero)
      423. {
      424. ID2D1RenderTarget_DrawRoundedRectangle Method = (ID2D1RenderTarget_DrawRoundedRectangle)Marshal.GetDelegateForFunctionPointer(pVTablePtr, typeof(ID2D1RenderTarget_DrawRoundedRectangle));
      425. Method.Invoke(pID2D1RenderTarget, roundedRect, brush, strokeWidth, strokeStyle);
      426. }
      427. }
      428. }
      429. public static void RenderTarget_FillRoundedRectangle(IntPtr pID2D1RenderTarget, D2D1_ROUNDED_RECT roundedRect, IntPtr brush)
      430. {
      431. var pVTablePtr = IntPtr.Zero;
      432. if (pID2D1RenderTarget != IntPtr.Zero)
      433. {
      434. if (GetVTablePtr(pID2D1RenderTarget, VTable_Interfaces.FillRoundedRectangle, ref pVTablePtr))
      435. {
      436. ID2D1RenderTarget_FillRoundedRectangle Method = (ID2D1RenderTarget_FillRoundedRectangle)Marshal.GetDelegateForFunctionPointer(pVTablePtr, typeof(ID2D1RenderTarget_FillRoundedRectangle));
      437. Method.Invoke(pID2D1RenderTarget, roundedRect, brush);
      438. }
      439. }
      440. }
      441. public static void RenderTarget_Clear(IntPtr pID2D1RenderTarget, D2D1_COLOR_F? color = default)
      442. {
      443. D2D1_COLOR_F tColor;
      444. var pVTablePtr = IntPtr.Zero;
      445. if (pID2D1RenderTarget != IntPtr.Zero)
      446. {
      447. if (GetVTablePtr(pID2D1RenderTarget, VTable_Interfaces.Clear, ref pVTablePtr))
      448. {
      449. ID2D1RenderTarget_Clear Method = (ID2D1RenderTarget_Clear)Marshal.GetDelegateForFunctionPointer(pVTablePtr, typeof(ID2D1RenderTarget_Clear));
      450. if (color.HasValue)
      451. {
      452. tColor = (D2D1_COLOR_F)color;
      453. }
      454. else
      455. {
      456. tColor = new D2D1_COLOR_F(1, 0, 0, 0);
      457. }
      458. Method.Invoke(pID2D1RenderTarget, tColor);
      459. }
      460. }
      461. }
      462. public static void RenderTarget_BeginDraw(IntPtr pID2D1RenderTarget)
      463. {
      464. var pVTablePtr = IntPtr.Zero;
      465. if (pID2D1RenderTarget != IntPtr.Zero)
      466. {
      467. if (GetVTablePtr(pID2D1RenderTarget, VTable_Interfaces.BeginDraw, ref pVTablePtr))
      468. {
      469. ID2D1RenderTarget_BeginDraw Method = (ID2D1RenderTarget_BeginDraw)Marshal.GetDelegateForFunctionPointer(pVTablePtr, typeof(ID2D1RenderTarget_BeginDraw));
      470. Method.Invoke(pID2D1RenderTarget);
      471. }
      472. }
      473. }
      474. public static bool RenderTarget_EndDraw(IntPtr pID2D1RenderTarget, [Optional, DefaultParameterValue(default)] ref D2D1_TAG tag1, [Optional, DefaultParameterValue(default)] ref D2D1_TAG tag2)
      475. {
      476. bool bolRet = false;
      477. var pVTablePtr = IntPtr.Zero;
      478. if (pID2D1RenderTarget != IntPtr.Zero)
      479. {
      480. if (GetVTablePtr(pID2D1RenderTarget, VTable_Interfaces.EndDraw, ref pVTablePtr))
      481. {
      482. ID2D1RenderTarget_EndDraw Method = (ID2D1RenderTarget_EndDraw)Marshal.GetDelegateForFunctionPointer(pVTablePtr, typeof(ID2D1RenderTarget_EndDraw));
      483. if (Method.Invoke(pID2D1RenderTarget, tag1, tag2) == S_OK)
      484. {
      485. bolRet = true;
      486. }
      487. }
      488. }
      489. return bolRet;
      490. }
      491. public static IntPtr CreateSolidColorBrush(IntPtr pID2D1RenderTarget, D2D1_COLOR_F color, D2D1_BRUSH_PROPERTIES? brushProperties = default)
      492. {
      493. var pRet = IntPtr.Zero;
      494. var pVTablePtr = IntPtr.Zero;
      495. D2D1_BRUSH_PROPERTIES tD2D1BP;
      496. var pID2D1SolidColorBrush = IntPtr.Zero;
      497. if (pID2D1RenderTarget != IntPtr.Zero)
      498. {
      499. if (GetVTablePtr(pID2D1RenderTarget, VTable_Interfaces.CreateSolidColorBrush, ref pVTablePtr))
      500. {
      501. ID2D1RenderTarget_CreateSolidColorBrush Method = (ID2D1RenderTarget_CreateSolidColorBrush)Marshal.GetDelegateForFunctionPointer(pVTablePtr, typeof(ID2D1RenderTarget_CreateSolidColorBrush));
      502. if (brushProperties.HasValue)
      503. {
      504. tD2D1BP = (D2D1_BRUSH_PROPERTIES)brushProperties;
      505. }
      506. else
      507. {
      508. tD2D1BP = new D2D1_BRUSH_PROPERTIES(1);
      509. }
      510. if (Method.Invoke(pID2D1RenderTarget, color, tD2D1BP, pID2D1SolidColorBrush) == S_OK)
      511. {
      512. pRet = pID2D1SolidColorBrush;
      513. }
      514. }
      515. }
      516. return pRet;
      517. }
      518. // ----==== ID2D1HwndRenderTarget Functions ====----
      519. public static bool HwndRenderTarget_Resize(IntPtr pID2D1HwndRenderTarget, D2D1_SIZE_U pixelSize)
      520. {
      521. bool bolRet = false;
      522. var pVTablePtr = IntPtr.Zero;
      523. if (pID2D1HwndRenderTarget != IntPtr.Zero)
      524. {
      525. if (GetVTablePtr(pID2D1HwndRenderTarget, VTable_Interfaces.Resize, ref pVTablePtr))
      526. {
      527. ID2D1HwndRenderTarget_Resize Method = (ID2D1HwndRenderTarget_Resize)Marshal.GetDelegateForFunctionPointer(pVTablePtr, typeof(ID2D1HwndRenderTarget_Resize));
      528. if (Method.Invoke(pID2D1HwndRenderTarget, pixelSize) == S_OK)
      529. {
      530. bolRet = true;
      531. }
      532. }
      533. }
      534. return bolRet;
      535. }
      536. // ----==== ID2D1SolidColorBrush Functions ====----
      537. public static void SolidColorBrush_SetColor(IntPtr pID2D1SolidColorBrush, D2D1_COLOR_F? color = default)
      538. {
      539. D2D1_COLOR_F tColor;
      540. var pVTablePtr = IntPtr.Zero;
      541. if (pID2D1SolidColorBrush != IntPtr.Zero)
      542. {
      543. if (GetVTablePtr(pID2D1SolidColorBrush, VTable_Interfaces.SetColor, ref pVTablePtr))
      544. {
      545. ID2D1SolidColorBrush_SetColor Method = (ID2D1SolidColorBrush_SetColor)Marshal.GetDelegateForFunctionPointer(pVTablePtr, typeof(ID2D1SolidColorBrush_SetColor));
      546. if (color.HasValue)
      547. {
      548. tColor = (D2D1_COLOR_F)color;
      549. }
      550. else
      551. {
      552. tColor = new D2D1_COLOR_F(1, 0, 0, 0);
      553. }
      554. Method.Invoke(pID2D1SolidColorBrush, tColor);
      555. }
      556. }
      557. }
      558. // ----==== Release Interface ====----
      559. public static void Release(ref IntPtr pInterface)
      560. {
      561. if (pInterface != IntPtr.Zero)
      562. {
      563. if (Marshal.Release(pInterface) == 0)
      564. {
      565. pInterface = IntPtr.Zero;
      566. }
      567. }
      568. }
      569. // ----==== Get the VTable pointer from the interface function number ====----
      570. private static bool GetVTablePtr(IntPtr pInterface, int intMethodNumber, ref IntPtr pVTablePtr)
      571. {
      572. bool bolRet = false;
      573. if (pInterface != IntPtr.Zero)
      574. {
      575. if (intMethodNumber >= 0)
      576. {
      577. var pVTablePtrs = new IntPtr[1];
      578. Marshal.Copy(IntPtr.Add(Marshal.ReadIntPtr(pInterface), IntPtr.Size * intMethodNumber), pVTablePtrs, 0, 1);
      579. pVTablePtr = pVTablePtrs[0];
      580. bolRet = true;
      581. }
      582. }
      583. return bolRet;
      584. }
      585. #endregion
      586. }
      Sind die ganzen sich wiederholenden Aufrufe mit Absicht, um quasi Typsicherheit zu erreichen? Denn ein Teil ließe sich ja auch zur Übersichtlichkeit kürzen:
      Spoiler anzeigen

      VB.NET-Quellcode

      1. Public Sub RenderTarget_DrawLine(pID2D1RenderTarget As IntPtr,
      2. point0 As D2D1_POINT_2F,
      3. point1 As D2D1_POINT_2F,
      4. brush As IntPtr,
      5. Optional strokeWidth As Single = 1,
      6. Optional strokeStyle As IntPtr = Nothing)
      7. GenericMethodCall(Of ID2D1RenderTarget_DrawLine)(pID2D1RenderTarget, VTable_Interfaces.DrawLine, point0, point1, brush, strokeWidth, strokeStyle)
      8. End Sub
      9. Public Sub RenderTarget_DrawRectangle(pID2D1RenderTarget As IntPtr,
      10. rect As D2D1_RECT_F,
      11. brush As IntPtr,
      12. Optional strokeWidth As Single = 1,
      13. Optional strokeStyle As IntPtr = Nothing)
      14. GenericMethodCall(Of ID2D1RenderTarget_DrawRectangle)(pID2D1RenderTarget, VTable_Interfaces.DrawRectangle, rect, brush, strokeWidth, strokeStyle)
      15. End Sub
      16. Public Sub RenderTarget_FillRectangle(pID2D1RenderTarget As IntPtr, rect As D2D1_RECT_F, brush As IntPtr)
      17. GenericMethodCall(Of ID2D1RenderTarget_FillRectangle)(pID2D1RenderTarget, VTable_Interfaces.FillRectangle, rect, brush)
      18. End Sub
      19. Public Sub RenderTarget_DrawRoundedRectangle(pID2D1RenderTarget As IntPtr,
      20. roundedRect As D2D1_ROUNDED_RECT,
      21. brush As IntPtr,
      22. Optional strokeWidth As Single = 1,
      23. Optional strokeStyle As IntPtr = Nothing)
      24. GenericMethodCall(Of ID2D1RenderTarget_DrawRoundedRectangle)(pID2D1RenderTarget, VTable_Interfaces.DrawRoundedRectangle, roundedRect, brush, strokeWidth, strokeStyle)
      25. End Sub
      26. Public Sub RenderTarget_FillRoundedRectangle(pID2D1RenderTarget As IntPtr, roundedRect As D2D1_ROUNDED_RECT, brush As IntPtr)
      27. GenericMethodCall(Of ID2D1RenderTarget_FillRoundedRectangle)(pID2D1RenderTarget, VTable_Interfaces.FillRoundedRectangle, roundedRect, brush)
      28. End Sub
      29. Public Sub RenderTarget_Clear(pID2D1RenderTarget As IntPtr, Optional color As D2D1_COLOR_F? = Nothing)
      30. Dim tColor = If(color.HasValue, CType(color, D2D1_COLOR_F), New D2D1_COLOR_F(1, 0, 0, 0))
      31. GenericMethodCall(Of ID2D1RenderTarget_Clear)(pID2D1RenderTarget, VTable_Interfaces.Clear, tColor)
      32. End Sub
      33. Public Sub RenderTarget_BeginDraw(pID2D1RenderTarget As IntPtr)
      34. GenericMethodCall(Of ID2D1RenderTarget_BeginDraw)(pID2D1RenderTarget, VTable_Interfaces.BeginDraw)
      35. End Sub
      36. Private Sub GenericMethodCall(Of T)(pRenderTarget As IntPtr, VTable_Interface As VTable_Interfaces, ParamArray Parameters As Object())
      37. Dim pVTablePtr = IntPtr.Zero
      38. If pRenderTarget = IntPtr.Zero OrElse Not GetVTablePtr(pRenderTarget, VTable_Interface, pVTablePtr) Then Return
      39. Dim ParameterList As New List(Of Object)
      40. ParameterList.Add(pRenderTarget)
      41. ParameterList.AddRange(Parameters)
      42. Marshal.GetDelegateForFunctionPointer(pVTablePtr, GetType(T)).DynamicInvoke(ParameterList.ToArray)
      43. End Sub


      bzw: Habe die Nullable(Of Foo) gegen Foo? ersetzt.
      Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

      Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
      @VaporiZed
      Mit Absicht ist das nicht. Ich wollte es erst einmal einfach halten. Im Grunde mach ich das so, wie Du mit GenericMethodCall, in VB6 auch. Eine Funktion in der ich den Pointer auf das Interface, die Funktionsnummer und die Parameter als ParamArray übergebe. Ok, VB6 ist nicht vergleichbar mit .Net, aber im Grunde ist es das gleiche.

      @simpelSoft
      Ich kann zwar C# lesen, aber kein C# schreiben.
      Mfg -Franky-
      @simpelSoftnull
      Ich wäre interessiert.

      Du könntest doch mal Anfangen mit einer C#-Version (eventuell neuer Thread eröffnen), und wir werden dich unterstützen und besprechen hier so weit es geht, bin mir nämlich sicher, dass es in C# so seine tucken gibt in der Umsetzung.


      @-Franky-
      Wenn ich ein paar mal über den Button darüber hovere, dann gibt es in deiner Version plötzlich einen Abbruch, und es werden keine Linien mehr gezeichnet. Frage mich gerade ob es Objekte gibt die nicht korrekt zurückgesetzt werden? Oder woher kommt das?

      EDIT: Ich glaube ich hab den Fehler gefunden. in der Structure D2D1_COLOR_F (Instanzierung in der Methode D2D1Draw) werden plötzlich keine Zufalls-Single-Werte übergeben, sondern nur noch der Wert 0 (Null) über alle 4 Parameter sngA, sngR, sngG, sngB im Kontruktor.

      Ich habe die Random-Instanzierung auch klassenweit genommen. Sobald die Random-Instanzierung in der Methode D2D1Draw wie es bei dir von Anfang ist, läuft alles korrekt. Die klassenweite Random ist für die Parallelzustände intern nicht geeignet.

      Freundliche Grüsse

      exc-jdbi


      Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „exc-jdbi“ ()

      -Franky- schrieb:

      8 komplette Interfaces einbauen um nur eine Funktion aus diesem Interface zu nutzen? Neeeeee.

      Stimmt, dazu habe ich auch schon einfach ​void _VtblGap1_17(); Funktionen in das Interface gesetzt um z.B. 17 Funktionen zu überspringen, aber mit den Pointern selber holen geht natürlich auch.

      exc-jdbi schrieb:

      Wenn ich ein paar mal über den Button darüber hovere, dann gibt es in deiner Version plötzlich einen Abbruch, und es werden keine Linien mehr gezeichnet.
      Jup, das hatte ich wohl etwas verschwurbelt weiter oben schon angemerkt.

      VaporiZed schrieb:

      Mir kam das komisch vor, dass in der Sub D2D1Draw random immer wieder neu instanziiert wird und hatte ihn mal da rausgezogen und somit klassenweit gemacht. Dann ist aber nach 4-5 Redraws Dusterbusch angesagt.
      Mal sehen, ob dazu was in der Doku zu finden ist.

      ###########

      VB.NET-Quellcode

      1. Dim Counter = 0
      2. Parallel.For(0, 999, Sub(y)
      3. Dim a = Random.Next(0, 255)
      4. Dim b = Random.Next(0, 255)
      5. Dim c = Random.Next(0, 255)
      6. Dim d = Random.Next(0, 255)
      7. If {a, b, c, d}.All(Function(x) x = 0) Then Counter += 1
      8. End Sub)
      9. If Counter > 900 Then Stop


      Auch dieser Code wird bei mir nach ca. 10x zum 0er-Problem.

      ##########

      Die Anzahl der Random.Next-Aufrufe ist es nicht, das geht bei mir von 3000-240000.

      ##########

      stackoverflow schrieb:


      Random is not thread-safe - you shouldn't be using the same instance from multiple threads. It can get much worse than just returning the same data - by using it from multiple threads, you can get it "stuck" in a state where it will always return 0, IIRC.

      Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

      Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

      Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „VaporiZed“ ()

      @VaporiZed
      Manchmal hat man ja kein Bock sich extra die Header-Dateien rauszusuchen um zB die IIDs, CLSIDs, Enums, Const in Erfahrung zu bringen. Ich nutze dann die Seite magnumdb.com/search dafür. Das schöne an dieser Seite: Man kann auch Platzhalter verwenden wie zB IID_ID2D1Factory*. Dann werden halt alle IIDs von IID_ID2D1Factory bis IID_ID2D1Factory7 aufgelistet. Structures finden geht mit der Seite allerdings nicht.
      Mfg -Franky-