[C#/.NET] pointer/interface/struct

Pagina: 1
Acties:

  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 16-05 11:22
Ik wil het gebruik van de functie CallNextHook beetje generiek opzetten, en heb daarvoor het volgende bedacht:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public enum WPARAM : int
{
    WM_KEYDOWN  = 256
}

public interface LPARAM
{
}

public struct KBDLLHOOKSTRUCT : LPARAM
{ 
    public int vkCode; 
    public int scanCode; 
    public int flags; 
    public int time; 
    public int dwExtraInfo; 
} 
     
public struct MSLLHOOKSTRUCT : LPARAM
{ 
    public POINT pt; 
    public int mouseData; 
    public int flags; 
    public int time; 
    public int dwExtraInfo; 
} 

public delegate int HOOKPROC (int nCode, WPARAM wParam, LPARAM * lParam); 

[DllImport("user32")]         
public static extern int CallNextHookEx(int hHook, int nCode, WPARAM wParam, LPARAM * lParam);

//---

private int LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM * lParam)
{
    return CallNextHookEx(hHook, nCode, wParam, lParam);
}

HOOKPROC hHook = new HOOKPROC(LowLevelKeyboardProc);


Dit werkt niet, omdat ik geen pointers van managed types (LPARAM) door kan geven in C#. Het lParam wat binnenkomt in LowLevelKeyboardProc is bevat het adres naar de structure. Hoe kan ik ervoor zorgen dat ik in mijn functie dit adres kan gebruiken als de struct (zonder eerst een Marshal.PtrToStructure te hoeven doen), en expliciet gebruik blijven maken van de LPARAM (waar de beschikbare structs van zijn afgeleid) ivm de leesbaarheid?

De precieze foutmelding is trouwens:
Regel 31 en 35: Cannot take address or size of variable of a managed type ("User32.LPARAM")

[ Voor 8% gewijzigd door riezebosch op 03-11-2004 23:50 ]

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 16-05 11:22
Heb het toch maar als volgt opgelost:

C++:
1
2
3
4
5
6
7
8
private int LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam)
{
    WPARAM p = (WPARAM) wParam.ToInt32();

    KBDLLHOOKSTRUCT l = (KBDLLHOOKSTRUCT) Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT));

    return Hooks.CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
}


Waarbij wParam en lParam dus allebei een IntPtr geworden zijn. Als iemand een andere oplossing weet (niet dat deze niet netjes genoeg is, ik wil alleen graag weten of het ook anders kan; casten adhv geheugenadres in .NET).

[ Voor 50% gewijzigd door riezebosch op 03-11-2004 13:08 ]

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 16-05 11:22
Nu heb ik het ook weer anders. Als ik de lParam van het type KBDLLHOOKSTRUCT laat zijn geeft het ook geen problemen.

C++:
1
2
[DllImport("user32")]         
public static extern int CallNextHookEx(int hHook, HOOKCODE nCode, WPARAM wParam, ref KBDLLHOOKSTRUCT lParam);


Maar ik wil dit juist van de interface LPARAM laten zijn, zodat ik bij implemenatie van de delegate pas op hoef te geven welk type struct ik mee wil geven. Hoe kan ik dit nou realiseren in C#? Want als ik ipv ref KBDLLHOOKSTRUCT lParam een ref LPARAM lParam doe compileert ie wel, gaat het ook goed als ik de hook set, maar loopt m'n programma vast zogauw ik een toest indruk.

Ik kan natuurlijk twee functies opnemen, voor beide mogelijkheden één, maar het gaat me erom dat ik die ene functie mooi generiek kan maken...

Edit:
Ik geloof dat ik 'm aardig begin te begrijpen. Het is me gelukt om de CallNextHookEx wel van een ref LPARAM lParam mee te geven, alleen moet de delegate dan wel een ref KBDLLHOOKSTRUCT hebben (waarmee ik 'm in de LowLevelKeyboardProc wel ff moet casten bij het doorgeven). Dit zal zijn omdat bij het zetten van de hook de grootte van de callbackfunctie en de parameters bekend moet zijn. Niet dan? Dat kan ie aan LPARAM natuurlijk niet uitlezen, want dat is alleen een lege interface...

[ Voor 37% gewijzigd door riezebosch op 03-11-2004 23:57 ]

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


  • EfBe
  • Registratie: Januari 2000
  • Niet online
Je moet ook iets doen met de struct layout, maar de specifieke statements zijn me ontgaan. De C# DirectX sdk biedt wellicht uitkomst.

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 16-05 11:22
EfBe, had niet zo'n zin die complete SDK te downloaden (+/- 250MB0 maar iig bedankt voor je reactie :) Ik heb het nu zelf opgelost adhv voorbeelden voor een union in C#. Ik neem beide mogelijkheden (MSLLHOOKSTRUCT en KBDHOOKSTRUCT) op in LPARAM, en laat ze met behulp van de FieldOffsetAttribute overlappen.

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[StructLayout(LayoutKind.Explicit)]
public struct LPARAM
{
    [FieldOffset(0)] public KBDLLHOOKSTRUCT k;
    [FieldOffset(0)] public MSLLHOOKSTRUCT m;
}

public struct KBDLLHOOKSTRUCT
{ 
    public int vkCode; 
    public int scanCode; 
    public int flags; 
    public int time; 
    public int dwExtraInfo; 
} 
        
public struct MSLLHOOKSTRUCT
{ 
    public POINT pt; 
    public int mouseData; 
    public int flags; 
    public int time; 
    public int dwExtraInfo; 
}


De functie wordt dan:
C++:
1
2
[DllImport("user32")]         
public static extern int CallNextHookEx(int hHook, HOOKCODE nCode, WPARAM wParam, ref LPARAM lParam);


En als ik dan de lParam moet gebruiken in mijn callbackproc kan ik gewoon lParam.k doen voor de keyboardhookstruct en lParam.m voor de mousehookstruct.

Ik weet niet of iemand hier iets aan heeft, gezien het gebrek aan reacties, maar misschien dat het anderen nog op ideeën brengt B)

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack