methoden aus c-dll in .net projekt nutzen
-
hi forum,
vorab:
ich habe den grundsätzlich spannenden thread von wesley67 gelesen:
http://www.c-plusplus.net/forum/viewtopic-var-t-is-192725.htmldesweiteren habe ich dieses problem bereits in den microsoft-foren, wie auch
in c#-foren besprochen und keiner konnte mir wirklich helfen.ich schliesse also daraus, dass dies wohl eher ein ungewöhnliches vorgehen ist.
seltsamerweise aber, habe ich unzählige leute angetroffen welche mit dem selben
problem konfrontiert waren und keine lösung gefunden haben.also probiere ich es gerne hier noch einma und hoffe auf hilfe : )
aufgabe:
ich benötige ein meiner c#-anwendung die messages bzw. das wm_paint-"event" und
zwar systemweit. (bzw. alles was auf dem monitor sichtbar ist)meine idee:
ich weiss, dass ich mit dem framework nicht an diese hooks herankomme und das
vorhaben mit einer c-dll lösen könnte.
in einem c-tutorial habe ich mir dann die c-dll geschnappt, welche mir diese
möglichkeit bietet. (tut für mousehooks)
leider bin ich auch nach x versuchen nicht in der lage diese messages aufzufangen.meine bitte:
helft mir bitte zu verstehen, wo genau mein problem liegt bzw. was ich nicht
richtig verstanden habe.
(eventuell gibts ja auch bereits ein demo-programm, welches genau das aufzeigt)übrigens: es gibt keine fehler beim starten der applikation, ich weiss nur nicht
wie ich an meine lieben daten komme : (meine c-dll: (HEADER)
#ifndef _DLL_H_ #define _DLL_H_ #include #if BUILDING_DLL # define DLLIMPORT __declspec (dllexport) #else /* Not BUILDING_DLL */ # define DLLIMPORT __declspec (dllimport) #endif /* Not BUILDING_DLL */ // zur Deklaration von Variablen innerhalb eines "shared data segment" #define SHARED __attribute__((section(".shr"), shared)) DLLIMPORT BOOL InstallHook(); DLLIMPORT BOOL UninstallHook(); LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam); #endif /* _DLL_H_ */
meine c-dll:
/* Replace "dll.h" with the name of your header */ #include "dll.h" // Globale Variablen HHOOK g_hMouseHook SHARED = NULL; // Handle unseres Hooks (als "shared" Deklariert) HINSTANCE g_hInst SHARED = NULL; // Handle der DLL selbst BOOL APIENTRY DllMain (HINSTANCE hInst /* Library instance handle. */ , DWORD reason /* Reason this function is being called. */ , LPVOID reserved /* Not used. */ ) { g_hInst = hInst; return TRUE; } DLLIMPORT BOOL InstallHook() { if(g_hMouseHook != NULL) return TRUE; g_hMouseHook = SetWindowsHookEx(WH_MOUSE, MouseProc, g_hInst, 0); if(g_hMouseHook == NULL) return FALSE; return TRUE; } DLLIMPORT BOOL UninstallHook() { if(g_hMouseHook != NULL) { UnhookWindowsHookEx(g_hMouseHook); g_hMouseHook = NULL; } return TRUE; } LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam) { if (nCode < 0) return CallNextHookEx(g_hMouseHook, nCode, wParam, lParam); if(nCode == HC_ACTION) { if ( (wParam == WM_LBUTTONDOWN)||(wParam == WM_NCLBUTTONDOWN) ) { MOUSEHOOKSTRUCT *mhs = (MOUSEHOOKSTRUCT*)lParam; HWND caller = FindWindow("Pipette", NULL); if(caller != NULL) PostMessage(caller, WM_USER+123, 0, MAKELPARAM(mhs->pt.x, mhs->pt.y)); } } return CallNextHookEx(g_hMouseHook, nCode, wParam, lParam); }
mein c#-code gesäubert:
using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; using System.Runtime.InteropServices; namespace Pipette { static class Program { [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); // MouseProc abonnieren und mit receiveData verarbeiten (?) MouseProc myCallback = new MouseProc(receiveData); // Methode in der dll aufrufen InstallHook(); // GUI starten Application.Run(new Pipette()); } public static void receiveData(int nCode, IntPtr WPARAM, IntPtr LPARAM) { MessageBox.Show("Empfange Daten : )"); } public delegate void MouseProc(int nCode, IntPtr WPARAM, IntPtr LPARAM); [DllImport("mousehook.dll")] public static extern bool InstallHook(); [DllImport("mousehook.dll")] public static extern bool UninstallHook(); } }
ich weiss, dass diese dll nicht alles kann, was ich schlussendlich benötige,
jedoch habe ich momentan nix anderes und möchte einfach nur den ablauf so verstehen, dass ich mein beispiel zum laufen bringe.die app bringt keine exceptions, jedoch aber passiert auch sonst nichts.
bitte helft mir.
nullpunkt
-
Bis wo kommst Du denn?
Ich meine, werden die C- Funktionen Aufgerufen? (Könnte man mit Traces o.ä. herausfinden.)
Simon
-
hi simon.gysi,
mit sicherheit kann ich sagen, dass die methode erkannt werden, denn
wenn ich eine unbekannte funktion im aufruf angebe, dann erhalte ich
den fehler, dass der einstiegspunkt in der dll nicht gefunden wurde.ich denk also das müsste schonmal passen. bzw. ich glaube, dass der
eigentliche hook installiert wird.mfg nullpunkt
-
ch denk also das müsste schonmal passen. bzw. ich glaube, dass der
eigentliche hook installiert wird.Überprüfe es doch.
Du erzeugst einen MouseProc Delegaten, der aber nicht verwendet wird.
Irgendwo muss noch die Weiterleitung gemacht werde: Unmanaged -> Managed.
Bei dir sieht es aus als mischt Du zwei Ansätze: Messages (WM_USER+123) und Callbacks.Teste Doch mal of deine unmanaged (C) MouseProc Funktion aufgerufen wird.
Simon
-
hi simon.gysi,
besten dank, irgendwie waren da tatsächlich ansätze vermischt. ich hab das
ganze nochmals neu aufgerollt und durchdacht, nun erhalte ich die benötigten
messages : )dazu möchte ich aber gleich eine frage anhängen, da sie das thema eigentlich
auch betrifft:das einzige was ich von der message eigentlich möchte, ist das neu zu
zeichnende rectangle sowie die koordinaten dazu.ich habe in der msdn ein bisschen etwas über das thema gefunden, jedoch sind
die meisten beispiele in c gehalten.könnte mir evt jemand den nötigen wink geben?
mfg nullpunkt
-
hi,
ich habe es herausgefunden.zuerst musste ich die fehlende funktion importieren:
[DllImport("user32")] public static extern int GetUpdateRect(IntPtr hwnd, ref Rectangle lpRect, int bErase);
und dann habe ich jeweils von der message bzw. vom rectangle nur die location
und size genommen und dann mit graphics vom screen kopiert.Rectangle rect = new Rectangle(); GetUpdateRect(Handle, ref rect, 0); if (rect.Size == new Size(0, 0)) { return; } Bitmap bmp = new Bitmap(rect.Width, rect.Height); Graphics g = Graphics.FromImage(bmp); g.CopyFromScreen(rect.Left, rect.Top, 0, 0, rect.Size);
mfg nullpunkt
-
Hi,
Für Bitmap und Graphics solltest Du noch Dispose() aufrufen, sobald Du diese Resourcen nicht mehr benötigst. In C# geht das sehr elegant mit dem using Statement.Bsp:
using (Bitmap bmp = new Bitmap(rect.Width, rect.Height)) { using (Graphics g = Graphics.FromImage(bmp)) { g.CopyFromScreen(rect.Left, rect.Top, 0, 0, rect.Size); // Noch mehr Dinge anstellen mit bmp und g. // Beim Verlassen des Scopes, wird Dispose automatisch aufgerufen (inkl. try/finally). } }
Simon
-
hi simon,
besten dank, das kannte ich in dieser art noch nicht!mfg nullpunkt