drag and drop in dll

Status
Niet open voor verdere reacties.

sander the man

Gebruiker
Lid geworden
7 jun 2007
Berichten
94
ik wil een dll maken voor game maker maar dat boeit niet :P

maar het probleem is dat ik wel weet hoe drag and drop weet in een winapi C++ application maar hoe kan je de window messages, wparem en lparam van een anderen handle krijgen?

dit is mijn code voor drag and drop:
Code:
        case WM_DROPFILES:
            TCHAR anewname[256];
            DragQueryFile((HDROP) wParam,0, anewname, 256);//sizeof(anewname));
            MessageBox(hwnd,anewname, "Dropped File:", MB_OK );
            DragFinish((HDROP) wParam);
            break;

dus wat ik me af vraag: hoe kan je de window messages, wparem en lparam van een anderen handle krijgen?
 
Kijk eens naar de functie SetWindowsHookEx() en naar hooks in het algemeen. Daar kun je messages bedoelt voor een andere thread mee vangen.
 
hm.... eerlijk gezegd snap ik er helemaal niks van....

je moet een dll handle invoeren? en nog meer dingen maar niet de handle van het window waarvan je de messages wil... hoe weet hij dan ooit welke messages je wil?
 
Als het een venster in hetzelfde proces is het misschien makkelijker om het venster te "subklassen" met SetWindowLong().

Als je SetWindowsHookEx() gebruikt dan moet je ook een "threadid" meegeven. Deze kan je van de hwnd krijgen met behulp van GetWindowThreadProcessId().
 
Als het een venster in hetzelfde proces is het misschien makkelijker om het venster te "subklassen" met SetWindowLong().

Als je SetWindowsHookEx() gebruikt dan moet je ook een "threadid" meegeven. Deze kan je van de hwnd krijgen met behulp van GetWindowThreadProcessId().
Het is in een ander proces :(

Ik weet niet of het veel werk is ofzo maar kent iemand een example of kan iemand een simpele code maken om de system messages van een bepaald proces te achterhalen?
 
Hopelijk kan je wat met de volgende code en uitleg...
Even snel in elkaar gezet.

De functie die de window messages ontvangt is haakproc() en zit in de dll.
Broncode is in winhook.c. Van winhook.c moet je een dll winhook.dll maken.
Van main.c een gewone .exe.

Het argument lp van haakproc() wijst naar een CWPSTRUCT struct. Hieruit kan je
de hwnd, message, wParam en lParam halen. Je krijgt van ieder venster met
het eerder gevonden draadid (threadid) dus messages.

In dit voorbeeld wordt main.exe gestart kies daarna optie 1 om de messages te onderscheppen of
2 om te stoppen.
Dit programma zoekt naar een venster met de tekst "hello" (de code hiervan zit in de dll zelf. Dit kan natuurlijk ook in de exe).
MessageBeep() wordt aangeroepen bij een WM_SIZE en een WM_RBUTTONDOWN.


winhook.c:
Code:
#define WIN32_MEAN_AND_LEAN
#include <windows.h>

#ifdef __GNUC__
/*met gcc maak je een gedeelde variabele m.b.v. attribute*/
#define GEDEELD  __attribute__(( section(".shared"),shared  ))
#else
/*voor andere compilers is het bij mij niet bekend en GEDEELD doet dus niets*/
#define GEDEELD
#endif

HINSTANCE g_hinstdll = NULL;
HHOOK GEDEELD hhaak  = NULL;

BOOL WINAPI
DllMain(HINSTANCE hinst,DWORD reden,LPVOID reserved)
{
 switch(reden)
 {
  case DLL_PROCESS_ATTACH:
  g_hinstdll = hinst;
  break;
 }//einde switch

 return TRUE;
}


LRESULT CALLBACK
haakproc(int hc,WPARAM wp,LPARAM lp)
{
 int cnh;
 PCWPSTRUCT pcwp;

 pcwp = (PCWPSTRUCT) lp;

 if( hc >=0)
 {
    if(  pcwp->message == WM_RBUTTONDOWN  ) MessageBeep(0);
    if(  pcwp->message == WM_SIZE  ) MessageBeep(0);
 }

 cnh = CallNextHookEx(hhaak,hc,wp,lp);
 return cnh;
}

DWORD
vinddraadid()
{
 DWORD draadid;
 HWND h;
 int i=0;

 h = FindWindow(NULL,"hello");
 if( h )
   draadid = GetWindowThreadProcessId(h,NULL);
 else
 {
   draadid = 0;
   MessageBox(NULL,"kan het venster niet vinden",NULL,0);
 }
 return draadid;
}

BOOL __declspec(dllexport)
InstalleerHaak()
{
 BOOL b=0;
 DWORD draadid;

 if(hhaak);
 else if( draadid=vinddraadid() )
 {
   hhaak = SetWindowsHookEx(WH_CALLWNDPROC,haakproc,g_hinstdll,draadid);
   if (hhaak)
   {
     b=1;
   }
 }
 return b;
}

int __declspec(dllexport)
VerwijderHaak()
{
 return UnhookWindowsHookEx (hhaak);
}


main.c
Code:
#define WIN32_MEAN_AND_LEAN
#include <windows.h>

BOOL InstalleerHaak();
int VerwijderHaak();

int
main()
{
 char s[256];
 HINSTANCE hdll;
 BOOL b;

 do
 {
   printf("1 installeerhaak\n2 verwijderhaak en stoppen\n:");
   gets(s);
   if( s[0] == '1' )
   {
      b = InstalleerHaak();
      if( b ) printf("haak gezet\n");
      else    printf("fout bij het installeren van de haak\n");
   }
   if( s[0] == '2' )VerwijderHaak();
 }
 while( s[0]!='2' );
 return 0;
}
 
Laatst bewerkt:
is het niet mogelijk/makkelijker om het zonder zo een dll te doen? of dacht je dat ik dat bedoelde met m`n topic titel? zo ja dan heb ik dat onduidelijk gezegd en maakt `t gewoon even niet uit.

ik heb even een code in elkaar gepriegeld:
Code:
#define WIN32_MEAN_AND_LEAN
#include <windows.h>
#include <iostream>

#ifdef __GNUC__
/*met gcc maak je een gedeelde variabele m.b.v. attribute*/
#define GEDEELD  __attribute__(( section(".shared"),shared  ))
#else
/*voor andere compilers bij is het mij niet bekend en GEDEELD doet dus niets*/
#define GEDEELD
#endif

HINSTANCE g_hinstdll = NULL;
HHOOK GEDEELD hhaak  = NULL;
 char s[256];
using namespace std;
LRESULT CALLBACK
haakproc(int hc,WPARAM wp,LPARAM lp)
{
 int cnh;
 PCWPSTRUCT pcwp;

 pcwp = (PCWPSTRUCT) lp;

 if( hc >=0)
 {
    if(  pcwp->message == WM_RBUTTONDOWN  ) MessageBeep(0);
    if(  pcwp->message == WM_SIZE  ) MessageBeep(0);
 }

 cnh = CallNextHookEx(hhaak,hc,wp,lp);
 MessageBox(NULL,"1",NULL,0);
 return cnh;
}

DWORD
vinddraadid()
{
 DWORD draadid;
 HWND h;
 int i=0;

 h = FindWindow(NULL,"hello");
 if( h )
   draadid = GetWindowThreadProcessId(h,NULL);
 else
 {
   draadid = 0;
   MessageBox(NULL,"kan het venster niet vinden",NULL,0);
 }
 return draadid;
}
BOOL
InstalleerHaak()
{
 BOOL b=0;
 DWORD draadid;

 if(hhaak);
 else if( draadid=vinddraadid() )
 {
   hhaak = SetWindowsHookEx(WH_CALLWNDPROC,haakproc,g_hinstdll,draadid);
   if (hhaak)
   {
     b=1;
   }
 }
 return b;
}
int
VerwijderHaak()
{
 return UnhookWindowsHookEx (hhaak);
}

int main()
{
BOOL b;

 do
 {
   cout <<"1 installeerhaak\n2 verwijderhaak en stoppen\n:";
   gets(s);
   if( s[0] == '1' )
   {
      b = InstalleerHaak();
      if( b ) cout << "haak gezet\n";
      else    cout << "fout bij het installeren van de haak\n";
   }
   if( s[0] == '2' )VerwijderHaak();
 }
 while( s[0]!='2' );
 return 0;
}

en ik hen een venster gemaakt met hello er in. Alleen ik krijg steeds een error met fout bij het installeren van de haak....

(geen compile error maar die message box)
 
is het niet mogelijk/makkelijker om het zonder zo een dll te doen?
Nee, de dll wordt namelijk geladen in een het andere proces (in dit geval het proces van het venster hallo).
Dit kan niet met een gewone exe. (Het zou misschien werken met een exe die een "relocation table" heeft, maar dat levert mogelijk onvoorspelbaar gedrag en maakt het daarmee moeilijker als het al werkt.)
Volgens Microsoft zou je een dll moeten gebruiken bij gebruik van een callwindowprochook in een ander proces.

Overigens hoeft alleen de functie haakproc() in de dll te zitten de rest kan
ook in de exe, maar dan moet je aardig wat code herschrijven.


(geen compile error maar die message box)
Bedoel je met die message box alleen de regel:
cout << "fout bij het installeren van de haak\n";
dus uitvoer op stdout
of krijg je ook deze:
MessageBox(NULL,"kan het venster niet vinden",NULL,0);
een "gui messagebox"?

Probeer het eens met een dll.
 
Laatst bewerkt:
een gui messagebox.

Maar ik snap dat van winhook.c en main.c nog niet helemaal:
in geen een van beide code zie ik ook maar winhook.dll staan dus hoe kan hij die dll ergens inladen als je hem niet eens vertelt welke dll je moet inladen?

Functies die in winhook.c staan gebruik je in main.c maar als ik van winhook.c een dll maak dan is het geen een losse .dll file. Dus main.c weet toch ook niet wat hij moet doen als je installeerhoek(); uitvoert?

Ik heb nu een aparte dll gemaakt: Winhook.dll simpel door winhook.c te compilen als dynamic link library.

Dan maak ik een nieuw project aan als console application. Ik zet de code van main.c er in en hij geeft allemaal compile errors over functies.

Ik weet dat ik iets fout doe maar ik weet niet wat...
 
Van winhook.c moet je behalve de dll ook nog een "input library" maken. Deze heeft vaak de extensie .lib of .a. Dan heb je dus behalve winhook.dll ook een bestand dat bijv. winhook.lib heet.

Als je dan main.c compileert link je de library winhook.lib mee. Door winhook.lib mee te linken weet main.c dus de definitie van onder meer InstalleerHaak().

Mocht je nog fouten krijgen bij het compileren post deze dan (als het er veel zijn alleen de eerste 4).
 
Laatst bewerkt:
Van winhook.c moet je behalve de dll ook nog een "input library" maken. Deze heeft vaak de extensie .lib of .a. Dan heb je dus behalve winhook.dll ook een bestand dat bijv. winhook.lib heet.

Als je dan main.c compileert link je de library winhook.lib mee. Door winhook.lib mee te linken weet main.c dus de definitie van onder meer InstalleerHaak().

Mocht je nog fouten krijgen bij het compileren post deze dan (als het er veel zijn alleen de eerste 4).

bedankt! ik krijg geen compile erros maar nu krijg ik het berichtje: fout bij het installeren van de haak

terug als ik de haak probeer te installeren... Ik heb ook een venster met hello aangemaakt.

maar ik weet in iedergeval zeker dat ik `t goed gelinkt enz. heb omdat ik het gui message krijg met kan venster niet vinden als ik geen venster met halo aanmaak.

Maar wat kan dan het probleem zijn?
 
Even wat extra uitvoer in InstalleerHaak().
Zet bovenaan winhook.c:
Code:
#include <stdio.h>
en vervang InstalleerHaak() met de volgende uitgebreidere InstalleerHaak()
En post de melding(en) die je krijgt als je het programma draait.
Code:
BOOL __declspec(dllexport)
InstalleerHaak()
{
 BOOL b=0;
 DWORD draadid;

 if(hhaak)printf("Haak is al geinstalleerd\n");
 else if( draadid=vinddraadid() )
 {
   printf("voor SetWindowsHook:\n");
   printf("WH_CALLWNDPROC= %d  haakproc= %u g_hinstdll= %u  draadid=%u \n",
           WH_CALLWNDPROC     ,haakproc,    g_hinstdll,     draadid);
   hhaak = SetWindowsHookEx(WH_CALLWNDPROC,haakproc,g_hinstdll,draadid);
   if (hhaak)
   {
     printf(":) ");
     b=1;
   }
   else
   {
    long f;
    f = GetLastError();
    printf("fout %d bij SetWindowsHook\n",f);
   }
 }
 else printf("Het draadid is niet gevonden\n");
 return b;
}
 
slecht, maar het kan nog goed komen.
g_hinstdll = 0 dit is niet de bedoeling, hij zou een waarde moeten krijgen in DllMain().
Enige kans dat je een C++ project hebt en geen C-project dan wordt DllMain() niet aangeroepen en zou je kunnen proberen extern "C" voor de DllMain() functie te zetten.

Zet ook even
Code:
 DWORD dw=0;
 WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE),"in dllmain\n",11,&dw,(PVOID)0);
voor de switch in DllMain() , dan kan je zien of DllMain echt wordt aangeroepen.
 
Laatst bewerkt:
bedankt!



dat betekent goed toch?

alleen ik krijg geen messagebeep als ik het window met hallo er op resize...

ook als ik de functie messagebeep verander in zo een gui messagebox dan krijg ik die niet...


ik weet niet of het uitmaakt of het hello window in delphi is geschreven?

Edit: ik heb het net geprobeerd met kladblok en daar zegt hij alleen maar resized terwijl ik `m niet resizde...
 
Laatst bewerkt:
Ja het is zo te zien goed, SetWindowsHookEx() is gelukt.

Alleen vreemd dat er geen beep is als je het venster resized. Ik weet niet hoe dat komt.


Edit: ik heb het net geprobeerd met kladblok en daar zegt hij alleen maar resized terwijl ik `m niet resizde...
Wat bedoel je hiermee, hoe zegt hij dat dan?

Je kan proberen MessageBeep() of een andere functie in haakproc() aan te roepen zonder eerst op een message of iets te selecteren zodat je weet of haakproc()
wordt aangeroepen of misschien wel helemaal niet.
I.p.v. if( pcwp->message == WM_RBUTTONDOWN ) MessageBeep(0);
doe je dan bijv. MessageBeep(0);
of MessageBox(NULL,"test","test",0);
(Dat laatste zorgt waarschijnlijk voor oneindige recursie en loopt het programma vast maar dan weet je in ieder geval dat haakproc() wel eens wordt aangeroepen.)
 
Ja het is zo te zien goed, SetWindowsHookEx() is gelukt.

Alleen vreemd dat er geen beep is als je het venster resized. Ik weet niet hoe dat komt.



Wat bedoel je hiermee, hoe zegt hij dat dan?

Je kan proberen MessageBeep() of een andere functie in haakproc() aan te roepen zonder eerst op een message of iets te selecteren zodat je weet of haakproc()
wordt aangeroepen of misschien wel helemaal niet.
I.p.v. if( pcwp->message == WM_RBUTTONDOWN ) MessageBeep(0);
doe je dan bijv. MessageBeep(0);
of MessageBox(NULL,"test","test",0);
(Dat laatste zorgt waarschijnlijk voor oneindige recursie en loopt het programma vast maar dan weet je in ieder geval dat haakproc() wel eens wordt aangeroepen.)

haakproc wordt aan geroepen. Als ik niet zoek voor hello maar voor: Naamloos - Kladblok

en daar `t venster resize krijg ik wel zo een beep maar dan eerder een bijna oneindige beep... hij beept dan als de gek ook al resize ik `m niet meer. En bij dat programma waar ik `m voor wil gebruiken doet hij niks als ik `m resize... maar ik ga nu even wat anderen functies testen en hopelijk werkt een van die wel.

Edit: het lijkt wel of dat game maker window alles blokeerd ofzo... (ik wil het gebruiken voor het programma game maker) want ik krijg geen een WM_ functie ook maar iets terug... en als ik bij DLL_ATTACH zo een gui berichtje maakt komt dat berichtje wel maar met de titel fout en het heeft niet hetzelfde icoontje... (wat wel zo bij paint is)
 
Laatst bewerkt:
en als ik bij DLL_ATTACH zo een gui berichtje maakt komt dat berichtje wel maar met de titel fout en het heeft niet hetzelfde icoontje... (wat wel zo bij paint is)
Ik neem aan dat je dat in DllMain() doet bij DLL_PROCESS_ATTACH (en dus niet bij DLL_ATTACH).
Dit kan wel kloppen, in DllMain() mag je alleen functies van kernel32.dll aanroepen.

Herhaal ik nog even de volgende vraag: Heb je geprobeerd MessageBeep() (of MessageBox()) onvoorwaardelijk aan te roepen in haakproc.
Gebeurt er dan iets, ik neem aan dat dat bij kladblok in ieder geval wel zo is.
Dus even tijdelijk het volgende voor haakproc()
Code:
LRESULT CALLBACK
haakproc(int hc,WPARAM wp,LPARAM lp)
{
 int cnh;

 MessageBeep(0);
 cnh = CallNextHookEx(hhaak,hc,wp,lp);
 return cnh;
}
Ik wil namelijk graag weten of bij programma's anders dan kladblok haakproc() wordt aangeroepen.
 
Laatst bewerkt:
Ik neem aan dat je dat in DllMain() doet bij DLL_PROCESS_ATTACH (en dus niet bij DLL_ATTACH).
Dit kan wel kloppen, in DllMain() mag je alleen functies van kernel32.dll aanroepen.

Herhaal ik nog even de volgende vraag: Heb je geprobeerd MessageBeep() (of MessageBox()) onvoorwaardelijk aan te roepen in haakproc.
Gebeurt er dan iets, ik neem aan dat dat bij kladblok in ieder geval wel zo is.
Dus even tijdelijk het volgende voor haakproc()
Code:
LRESULT CALLBACK
haakproc(int hc,WPARAM wp,LPARAM lp)
{
 int cnh;

 MessageBeep(0);
 cnh = CallNextHookEx(hhaak,hc,wp,lp);
 return cnh;
}
Ik wil namelijk graag weten of bij programma's anders dan kladblok haakproc() wordt aangeroepen.

ja ik bedoelde DLL_PROCESS_ATTACH.

Maar dit is weer wat minder goed nieuws denk ik: ik krijg geen beep of message. Dus dat betekent dat haakproc() niet wordt uitgevoerd toch?

maar ik ben ergens achter gekomen: in dat programma game maker is er een specaile functie voor dll`s omdat het game maker programma een binnenste en buitenste HWND heeft. Dus als je met FindWindow(NULL,"hello"); zoekt dan zie je alleen het buitenste window handle terwijl je de binnenste nodig hebt. Met een functie in dat game maker kan ik achter de binnenste hwnd komen. Ik ga nu even testen of ik met die binnenste handle een berichtje er uit kan krijgen

EDIT:
als ik een los programma maak met deze code:
Code:
#include <windows.h>
#include <iostream>

using namespace std;

int main()
{
    cout << "HWND: ";
    HWND h = (HWND)(int)331052;
    cout << (int)h << endl;
    MessageBox(h,"test in game maker?",NULL,0);
    cout << "2" << endl;
    return 0;
}

Dan krijg ik ook geen bericht van de game maker. En ik weet zeker dat ik doe goede HWND heb...

Maar nu ik even verder denk... Bij game maker laad je toch een dll in. Dus waarom zou je 2 dll`s gebruiken om 1 dll in te laden?
Dus als je het met game maker inlaad heeft de dll ook hetzelfde process. Alleen het `t een anderen thread denk ik.
 
Laatst bewerkt:
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan