Autor Beitrag
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Do 13.09.18 07:30 
- Nachträglich durch die Entwickler-Ecke gelöscht -
OlafSt
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 470
Erhaltene Danke: 94

Win7, Win81, Win10
Tokyo, VS2017
BeitragVerfasst: Do 13.09.18 07:42 
Ein Generic geht nicht ?

_________________
Lies, was da steht. Denk dann drüber nach. Dann erst fragen.
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4246
Erhaltene Danke: 901

Win10
C#, C++ (VS 2015/17)
BeitragVerfasst: Do 13.09.18 08:07 
Und diese Generic-Methode könntest du dann mittels where T : struct passend einschränken (s.a. Einschränkungen für Typparameter).
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Do 13.09.18 08:45 
- Nachträglich durch die Entwickler-Ecke gelöscht -
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4246
Erhaltene Danke: 901

Win10
C#, C++ (VS 2015/17)
BeitragVerfasst: Do 13.09.18 09:16 
Nein, die Klasse muß nicht zwangsläufig generisch sein.

Was meinst du aber jetzt mit "untypisierter Zeiger (void*)"? Zeige mal am besten ein Beispiel.
OlafSt
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 470
Erhaltene Danke: 94

Win7, Win81, Win10
Tokyo, VS2017
BeitragVerfasst: Do 13.09.18 09:26 
Eine generische Klasse braucht es nicht. Eine List<T>, später als List<integer> instanziiert, hat auch keinen generischen Integer ;)

_________________
Lies, was da steht. Denk dann drüber nach. Dann erst fragen.
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Do 13.09.18 13:36 
- Nachträglich durch die Entwickler-Ecke gelöscht -
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4246
Erhaltene Danke: 901

Win10
C#, C++ (VS 2015/17)
BeitragVerfasst: Do 13.09.18 14:48 
Einfach so:
ausblenden C#-Quelltext
1:
2:
[DllImport("User32.dll", EntryPoint = "SendMessage")]
private static extern bool SendMsgB<T>(IntPtr hWnd, int Msg, int wParam, ref T lParam) where T : struct;

Und der Aufruf dazu:
ausblenden C#-Quelltext
1:
2:
3:
4:
public static bool capDriverGetCaps(IntPtr hwnd, ref CAPDRIVERCAPS psCaps, int wSize)
{
  return SendMsgB(hwnd, WM_CAP_DRIVER_GET_CAPS, wSize, ref psCaps);
}

s.a. Ideone-Code (wobei dabei DllImportAttribute sowie CAPDRIVERCAPS nur Fakes sind).
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Fr 14.09.18 00:10 
- Nachträglich durch die Entwickler-Ecke gelöscht -
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4246
Erhaltene Danke: 901

Win10
C#, C++ (VS 2015/17)
BeitragVerfasst: Fr 14.09.18 08:17 
Puh, da scheint wohl P/Invoke nicht mit generischen Methoden umgehen zu können.

Dann bleibt wohl nur (ohne unsafe zu benutzen):
ausblenden C#-Quelltext
1:
2:
[DllImport("User32.dll", EntryPoint = "SendMessage")]
private static extern bool SendMsgB(IntPtr hWnd, int Msg, int wParam, IntPtr lParam);

Und dann eine generische Methode erstellen, welche mittels Marshal.AllocHGlobal diesen IntPtr erstellt und nach dem Aufruf von SendMsgB dann Marshal.PtrToStructure aufruft (s.a. die Beispiele)

PS: Laß dich nicht verwirren von "This API is now obsolete.": dies bezieht sich nur auf die Methoden-Überladung mittels object (je nachdem also welche Framework-Version du nutzt, wird die passende Methode verwendet).

PPS: Die Größe der Struktur würde ich direkt in capDriverGetCaps vornehmen (und nicht wie du es bisher machst, jedesmal als Parameter übergeben).
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Fr 14.09.18 20:38 
- Nachträglich durch die Entwickler-Ecke gelöscht -
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4246
Erhaltene Danke: 901

Win10
C#, C++ (VS 2015/17)
BeitragVerfasst: Sa 15.09.18 07:53 
Ja stimmt, zumindestens wenn es auch ein Input-Parameter sein soll. Bei capDriverGetCaps bin ich jedoch von einem reinen Output(out)-Parameter ausgegangen.
Aber als generelle Methode sicherlich empfehlenswert.

Du könntest aber jetzt einfach 2 verschiedene generische Methoden anbieten, einmal mit ref und einmal mit out:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
public static bool SendMsgRef<T>(IntPtr hwnd, int msg, ref T param) where T : struct
{
    int wSize = Marshal.SizeOf(param);
    IntPtr hMem = Marshal.AllocHGlobal(wSize);
    // ZeroMemory(hMem, wSize); // sehe ich nicht als notwendig hier an (wegen anschließendem StructureToPtr)

    Marshal.StructureToPtr(param, hMem, true);
    bool result = SendMsgB(hwnd, msg, wSize, hMem);
    param = (T)Marshal.PtrToStructure(hMem, typeof(T));

    Marshal.FreeHGlobal(hMem);

    return result;
}

public static bool SendMsgOut<T>(IntPtr hwnd, int msg, out T param) where T : struct
{
  // wie oben, nur ohne StructureToPtr
}
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Sa 15.09.18 21:11 
- Nachträglich durch die Entwickler-Ecke gelöscht -