08. april 2006 - 18:42Der er
13 kommentarer og 1 løsning
Pointers (ArrayList to IntPtr and back)
Hejsa
Jeg sidder og roder med pointers i forbindelse med bl.a. EnumChildWindows, og jeg vil gerne sende en ArrayList videre som lParam.
Er der nogen der kort kan forklare hvordan man konverterer til og fra IntPtr, og hvordan man bruger dem fornuftigt i forhold til Win32 API? Der er også noget med at man ikke bruge bool og int som return types, eller bare i det hele taget, mht. 64 bit systemer. Hvad går det ud på?
Det kan du opnå ved at lade din ArrayList være et felt på klassen og blot tilføje til denne når callback funktionen kører.
Er det alligevel nødvendigt, skal du bruge et GCHandle (Garbage-Collector Handle), som dels gør at objektet ikke bliver garbage collected og dels at det ikke bliver flyttet fra dens memory plads. Endelig er der en metode, som muliggør at du kan få fat på GCHandle objektet ud fra en IntPtr til det, uden selv at skulle caste. Husk altid at Free() et GCHandle når du er færdig med det.
using System; using System.Collections.Generic; using System.Runtime.InteropServices;
namespace EnumChildrenTest { class Program { static void Main(string[] args) { Console.WriteLine("Children to desktop window:"); List<IntPtr> list = WindowEnumerator.GetChildren(WindowEnumerator.GetDesktopWindow()); foreach (IntPtr ptr in list) { Console.WriteLine(ptr); } } }
public class WindowEnumerator { /// <summary> /// Gets the children. /// </summary> /// <param name="hwndParent">The HWND parent.</param> /// <returns></returns> public static List<IntPtr> GetChildren(IntPtr hwndParent) { List<IntPtr> list = new List<IntPtr>(); GCHandle handle = GCHandle.Alloc(list); try { EnumChildWindows(hwndParent, new EnumWindowProc(EnumWindowCallback), GCHandle.ToIntPtr(handle)); } finally { if (handle.IsAllocated) handle.Free(); } return list; }
private static bool EnumWindowCallback(IntPtr hwndChild, IntPtr lParam) { GCHandle handle = GCHandle.FromIntPtr(lParam); List<IntPtr> list = handle.Target as List<IntPtr>; if (list != null) list.Add(hwndChild); else throw new InvalidCastException("lParam did not point to a List of IntPtr"); return true; }
Jeg havde ikke lige lagt mærke til at FromIntPtr var 2.0 specifikt; men fint at du fandt en løsning alligevel.
"List" er en af de nye klasser i .NET Framework 2.0. < > er notationen for generics, som er en ny feature i C# 2.0. Populært sagt kan du med generics skrive samme kode der kan arbejde på flere forskellige typer. I eksemplet betyder List<IntPtr>: " en liste der arbejder på IntPtr", og Add metoden tager derfor IntPtr som argument, og indexeren returnerer IntPtr (i stedet for object, som på en arraylist). Dvs. du sparer nogle casts, og listen er typesikker, dvs. du kan være 100% sikker på at listen kun indeholder IntPtr's.
Collections som f.eks. List, er en af de helt oplagte steder at bruge Generics, men det kan også bruges til mange andre formål.
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.