Forum: PC-Programmierung C# : Referenz auf Klasse einer statischen Funktion übergeben


von Ing. ET (Gast)


Lesenswert?

Hallo,
folgendes Problem:
Ich benutze die Win32-API und moechte alle Windows ueberpruefen.
Meine Code schaut so aus:
1
public delegate bool CallBack(int hwnd, int lparam);
2
3
[DllImport("user32.dll")]
4
public static extern int EnumWindows(CallBack callback, int param);
5
6
7
EnumWindows(cbWinName, 0);
8
CallBack cbWinName = new CallBack(fnWinName);
9
10
private static bool fnWinName(int hWnd, int lParam)
11
{
12
//Hier moechte auf Klassenelemente zugreifen
13
}

in der callback Funktion fnWinName moechte ich auf nicht-statische 
Klassen-Elemente zugreifen. Dieser Funktion wird lParam uebergeben, 
welcher im obigen Beispiel in der Funktion EnumWindows mit 0 festgelegt 
wird.

Mit C wuerde ich einfach eine Struktur auf (int) casten, dann kann ich 
in fnWinName darauf zugreifen
1
struct Sdata {...};
2
struct Sdata data;
3
EnumWindows(fnWinName, (int) &data);
4
5
int fnWinName(int hWnd, int lParam)
6
{
7
struct Sdata *p= (struct Sdata *)lParam;
8
9
}

Wie kann ich in C# sowas machen, d.h. in dem int-Argument eine Referenz 
auf einen Datenbereich, bzw. Klasse uebergeben?

Gruss, Juergen

von Sam .. (sam1994)


Lesenswert?

Referenzen macht man in c# in Methoden normalerweise mit dem 
Schlüsselwort ref. Das ist aber glaub ich auch das einzigste.

von Arc N. (arc)


Lesenswert?

Oder man nimmt das Beispiel von
http://pinvoke.net/default.aspx/user32.EnumWindows
als Vorlage...

von Ing. ET (Gast)


Lesenswert?

>http://pinvoke.net/default.aspx/user32.EnumWindows

Danke fuer den Link.
Ich finde sehr interessant, dass man so einfach die Signatur von 
DLL-Funktionen abaendern kann. Ein 'int' und ein 'ref' haben zwar die 
gleiche Datengroesse (4 Bytes), aber trotzdem cool, dass es so einfach 
geht.


Die Deklaration in user32.dll:
1
WINUSERAPI BOOL WINAPI EnumWindows(WNDENUMPROC,LPARAM);
2
typedef BOOL(CALLBACK *WNDENUMPROC)(HWND,LPARAM);

abgeaendert in
1
private delegate bool EnumWindowsProc(IntPtr hWnd, ref SearchData data);

von Peter (Gast)


Lesenswert?

Ing. ET schrieb:
> Ich finde sehr interessant, dass man so einfach die Signatur von
> DLL-Funktionen abaendern kann.
da ist das Problem mit DLLs, die signatur steht dort überhaupt nicht 
drin, du kannst hinschreiben was du willst.

private delegate bool EnumWindowsProc(byte a, int b, string c);

das merkt auch erstmal niemand, bis zum starten der Funktion...

von Ing. ET (Gast)


Lesenswert?

>da ist das Problem mit DLLs, die signatur steht dort überhaupt nicht
>drin, du kannst hinschreiben was du willst.

Da will ich auf einen Fehler in C# hinweisen.
Wenn man folgenden Code ausfuehrt:
1
[DllImport("user32.dll")]
2
public static extern bool GetWindowRect(int hWnd, ref Rectangle rc);
3
4
5
...
6
7
Rectangle rc = new Rectangle();
8
GetWindowRect(hwnd, ref rc);
9
10
x=rc.Width;
11
y=rc.Height;

dann kann man Verwirrung ernten:
In rc.Width und rc.Height stehen nicht die Weite/Hoehe, sondern die x/y 
Position der rechten unteren Ecke.
Vermutlich stimmt System.Drawing.Rectangle nicht mit der DLL-Struktur 
ueberein.
Ich habe das Problem geloest, indem ich die Weite mit rc.Width-rc.X 
errechne. Ob das bei Visual C# 2010 auch so ist, weiss ich nicht, ich 
verwende C# 2008 Express.

von Peter (Gast)


Lesenswert?

Ing. ET schrieb:
> public static extern bool GetWindowRect(int hWnd, ref Rectangle rc);

das sollte man auf keine Fall so machen!!!! Denn in C# sind die 
strukturen/Klassen nicht dafür gedacht das sie von einer DLL verwendet 
werden. Wenn du z.b. ein 64bit system hast kann es schon sein das das 
alles nicht mehr passt. Du musst dafür die extra eine stuktur so 
anlegen:

[StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            public int Left;        // x position of upper-left corner
            public int Top;         // y position of upper-left corner
            public int Right;       // x position of lower-right corner
            public int Bottom;      // y position of lower-right corner
        }


alles andere wird irgendwann schief gehen!

von Arc N. (arc)


Lesenswert?

Ing. ET schrieb:
>>da ist das Problem mit DLLs, die signatur steht dort überhaupt nicht
>>drin, du kannst hinschreiben was du willst.
>
> Da will ich auf einen Fehler in C# hinweisen.
> Wenn man folgenden Code ausfuehrt:
>
>
1
> [DllImport("user32.dll")]
2
> public static extern bool GetWindowRect(int hWnd, ref Rectangle rc);
3
> 
4
> 
5
> ...
6
> 
7
> Rectangle rc = new Rectangle();
8
> GetWindowRect(hwnd, ref rc);
9
> 
10
> x=rc.Width;
11
> y=rc.Height;
12
>
>
> dann kann man Verwirrung ernten:
> In rc.Width und rc.Height stehen nicht die Weite/Hoehe, sondern die x/y
> Position der rechten unteren Ecke.
> Vermutlich stimmt System.Drawing.Rectangle nicht mit der DLL-Struktur
> ueberein.

Nicht nur vermutlich, die Struktur ist unterschiedlich...
http://www.pinvoke.net/default.aspx/user32.getwindowrect
http://msdn.microsoft.com/en-us/library/dd162897(v=VS.85).aspx
http://msdn.microsoft.com/en-us/library/ms633519(VS.85).aspx

von Ing. ET (Gast)


Lesenswert?

>das sollte man auf keine Fall so machen!!!! Denn in C# sind die
>strukturen/Klassen nicht dafür gedacht das sie von einer DLL verwendet

Das habe ich mir schon gedacht, aber ich bin neu in C# eingestiegen und 
lerne die Sprache mit tutorials und google.
Der obige Code ist von einem Tutorial abgekupfert und er hat ja 
funktioniert, solange ich nur die .X/.Y members benutzt habe.

Also KEIN Fehler in C#, sondern im Tutorial.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.