Witam, mogę dostać link do artykułu jak wyeksportować zmienne z DLL na zewątrz, mam hook na mysz, zapisałem tam x,y kliknięć w zmiennych xpos, ypos i chciałbym ich użyć w aplikacji która korzysta z tej DLL, ponieważ finalnie będę rysował mapę aktywności.
Pozdrawiam, Marcin.
Po 1: o ile wiem z dllki możesz eksportować funkcje lub procedury. Także to co masz w dll po słowie kluczowym exports
. Także albo zwracasz jakieś zmienne przez rezultat funkcji albo przez zmienną po słowie kluczowym var
jako parametr funkcji. Dllka raczej w bezpośredni sposób nie przekaże Tobie zmiennych, o ile dobrze rozumiem co chcesz osiągnąć.
Po 2: Do założenia Hooka na myszkę, nieważne czy globalnego czy lokalnego nie potrzeba w ogóle korzystać z dllki. A pozycję kursora możesz wtedy bez problemów określać na bieżąco. Jak coś to WH_MOUSE_LL = $0E
, a położenie myszki określa pole Pt
rekordu typu PMOUSEHOOKSTRUCT
, który przekazywany jest przez zmienną w parametrze LParam
funkcji obsługi takiego Hooka.
Więcej opisów na MSDNie pod hasłem Hooks overview
oraz licznych stronach do wygooglowania.
Zmienne można tak samo eksportować jak funkcje.
Przez "tak samo" mam na myśli tak samo.
function HookProc(Code: integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var
CurrWND: THandle;
begin
if Code < 0 then
begin
Result := CallNextHookEx(GlobalData^.HookHandle, Code, wParam, lParam);
exit;
end; // if
if (wParam = WM_LBUTTONDBLCLK) then
begin
MessageBox(0, 'Kliknąles 2x!' , '' , MB_OK);
xPos := LOWORD(lParam);
yPos := HIWORD(lParam);
end; // if
Result := CallNextHookEx(GlobalData^.HookHandle, Code, wParam, lParam);
end;
eksportuję procedurę do głównego programu, ale nadal nie wiem jak wydobyć zmienne xPos,yPos. Może mnie ktoś naprowadzić? Rozumiem, że dla niektórych to może banalne no ale... dla mnie jeszcze nie. :)
Jaki to Hook? Jak WH_MOUSE_LL to http://msdn.microsoft.com/en-us/library/windows/desktop/ms644986%28v=vs.85%29.aspx i zobacz co masz lParam
Jak WH_MOUSE http://msdn.microsoft.com/en-us/library/windows/desktop/ms644988%28v=vs.85%29.aspx i zobacz co masz lParam
OK, już rozumiem.
X := PMouseHookStruct(lParam).pt.X;
Y := PMouseHookStruct(lParam).pt.Y;
Mam problem, ponieważ program nie wyświetla kordów w ogóle i nie wiem dlaczego.
function HookProc(Code: integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var
CurrWND: THandle;
x,y: integer;
begin
if Code < 0 then
begin
Result := CallNextHookEx(GlobalData^.HookHandle, Code, wParam, lParam);
exit;
end; // if
if (wParam = WM_LBUTTONDBLCLK) then
begin
x:=PMouseHookStruct(lParam).pt.X;
y:=PMouseHookStruct(lParam).pt.Y;
Form1.Edit1.Text:=InttoStr(x);
Form1.Edit2.Text:=InttoStr(y);
end; // if
Result := CallNextHookEx(GlobalData^.HookHandle, Code, wParam, lParam);
end;
procedure RunHook; stdcall;
begin
GlobalData^.HookHandle:= SetWindowsHookEx(WH_MOUSE, @HookProc, HInstance, 0);
if GlobalData^.HookHandle = INVALID_HANDLE_VALUE then
begin
MessageBox(0, 'Error :)' , '' , MB_OK);
Exit;
end;
end;
eksportuje RunHook, tak wygląda główny program:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Edit1: TEdit;
Edit2: TEdit;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
procedure RunHook; stdcall; external 'hook_na_mysz.dll' name 'RunHook';
procedure KillHook; stdcall; external 'hook_na_mysz.dll' name 'KillHook';
var
Form1: TForm1;
pom,xc,yc:integer;
s: string;
pom2: string;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
RunHook;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
KillHook;
end;
end.
Unit1 dodałem w modułach do Dllki i nie mam zielonego pojęcia czemu nie zmienia wartości editow.
A nie przypadkiem:
x:=PMouseHookStruct(lParam)^.pt.X;
y:=PMouseHookStruct(lParam)^.pt.Y;
A tak w ogóle jak się odwojujesz formy z DLL? To jakaś forma w DLL?
w DLL w sekcji uses Unit1 in 'Unit1.pas' {Form1};
Ech, to są wedle mnie podstawy bardziej zaawanoswanych rzeczy jak Hooki. Wszystko jest elegancko opisane na MSDN. Jak również na mnóstwie stron do wygooglowania. Raczej tego Hooka powinieneś obsłużyć wedlug mnie tak, jak pokazałem w przykładowym kodzie załączniku.
Jest tam również dołaczony exek. Kompilowane pod Delphi 7, ale pod nowszymi środowiskami, według mnie również to powinno działać prawidłowo. I w ogóle @zalespl: czy jesteś w stanie wytłumaczyć po co Tobie dllka? Do tego Hooka niepotrzebna jest, jak sam widzisz dllka. Chociaż na google są niestety przykładowe wpisy z kodem, które mogłyby to sugerować. To nie globalny hook na funkcje API. Nie trzeba tak bardzo kombinować.
A jeżeli się już upierasz na dllce to zrób sobie funkcje, która zwraca TPoint
, a w jej definicji ustawiaj Result
tej funkcji na HookStruct
, który to będzie zmienną globalną. Oczywiście funkcje zwracającą te koordynaty sobie wyekportuj po słowie kluczowym exports
- na końcu kodu Twojej dllki. Przynajmniej w taki sposób ja bym kombinował. Ale o wiele łatwiej obslużyć tego Hooka w kodzie swojej właściwej aplikacji. Bo widze, że przez swój "upór na dllkę" tylko sobie komplikujesz sprawę. A dołaczony kod był pisany na próbę po jednym z pytan na forum i mam nadzieję, że publikujac go nie narazimy się na mnóstwo kolejnych pytań go dotyczących.
kombinuję z Dll'ką przez te przykłady właśnie. Dzięki za sugestie, przeanalizuję ten kod który zalinkowałeś. Uczę się tego dalej więc trochę biję głową w ścianę aż mi coś się uda, a dla początkującego może i przejrzyście opisano na MSDN'ie ale czasem nie wiem jak z tego skorzystać. Jeżeli chodzi o wskaźniki itd to spróbuję na surowo się tym pobawić bo jeszcze tego nie robiłem.
może mi ktoś powiedzieć czemu nie otrzymuję komunikatów o hooku WM_LBUTTONDBLCLK, lbuttondown i up, tak samo jak mousemove przychodzą, a dblclk nie.
czytałem coś o ustawieniu flagi CS_DBLCLKS, ale w przykładach robiono to przy tworzeniu okien, a nie dla hooków.
Niestety aby otrzymać komunikat WM_LBUTTONDBLCLK
według MSDN, okno musi mieć styl klasy CS_DBLCLKS
. Jednak mimo to nie otrzymuje w funkcji Hooka innych komunikatów w hex (większych od $200) niż 201 i 202. Oczekiwany 203 w moim Memo się nie pojawia. Poniżej kod funkcji globalnego Hooka:
//...
type
PMouseLLHookStruct = ^MouseLLHookStruct;
MouseLLHookStruct = record
pt : TPoint;
mouseData : cardinal;
flags : cardinal;
time : cardinal;
dwExtraInfo : cardinal;
end;
function LocalMouseHookProc(Code : integer; WParam : WPARAM; LParam : LPARAM) : LRESULT; stdcall;
var
HookStruct : PMouseLLHookStruct;
begin
HookStruct := Pointer(LParam);
if Code = HC_ACTION then
begin
if WParam > $200 then
begin
MainForm.Memo1.Lines.Add(IntToHex(WParam, 1));
end;
end;
Result := CallNextHookEx(MouseHookHandle, Code, WParam, LParam);
end;
//...
A tutaj kod na szybko przeklejony z dema WinAPI w kompendium na 4p. Mimo że mój dodany MessageBox
się pojawia, To taki komunikat nie jest "wyłapywany". Może jeszcze @kAzek albo ktoś inny coś tutaj doradzi. Bo nie ma chyba prostej metody na to aby to złapać tak jak chcesz.
program Project2;
uses
Windows,
Messages;
var
Edit : HWND;
function WndProc(Wnd : HWND; uMsg : UINT; wPar : WPARAM; lPar : LPARAM) : LRESULT; stdcall;
var
Buffer : array[0..128] of char;
begin
{ na początek zwracamy wartość 0 - meldunek jest przetwarzany }
Result := 0;
case uMsg of
WM_CREATE :
begin
Edit := CreateWindow('EDIT', '', WS_CHILD or WS_VISIBLE or WS_BORDER, 10, 10, 100, 25,
Wnd, 0, hInstance, nil);
CreateWindow('BUTTON', 'OK', WS_CHILD or WS_VISIBLE, 150, 10, 120, 25, Wnd, 101, hInstance, nil);
end;
WM_LBUTTONDBLCLK :
begin
MessageBox(Wnd, 'Kliknąłeś dwa razy lewym klawiszem!', 'Boom!', MB_OK);
end;
WM_COMMAND :
if wPar = 101 then
begin
GetWindowText(Edit, Buffer, SizeOf(Buffer)); // pobierz tekst z edita
MessageBox(Wnd, Buffer, 'EDIT', MB_OK); // wyświetl w okienku
SendMessage(Wnd, WM_SETTEXT, 0, Longint(@Buffer)); // ustaw nową wartość Caption
end;
WM_DESTROY : PostQuitMessage(0);
else
Result := DefWindowProc(Wnd, uMsg, wPar, lPar);
end;
end;
var
Wnd : TWndClass; // klasa okna
Msg : TMsg;
begin
with Wnd do
begin
style := CS_DBLCLKS;
lpfnWndProc := @WndProc; // funkcja okienkowa
hInstance := hInstance; // uchwyt do zasobów
lpszClassName := 'My1stApp'; // klasa
hbrBackground := COLOR_WINDOW; // kolor tła
end;
RegisterClass(Wnd); // zarejestruj nowa klasę
// stwórz formę...
CreateWindow('My1stApp', 'Server App',
WS_VISIBLE or WS_TILEDWINDOW,
300, 300, 300, 70,
0, 0, hInstance, nil);
while GetMessage(msg, 0, 0, 0) do
begin
TranslateMessage(msg);
DispatchMessage(msg);
end;
end.
Wydaje mi się (nie mam żadnej pewności jeżeli się mylę to proszę mnie poprawić) że "to nie jest komunikat myszki" i hooki na mychę tu nie pomogą, bo fizycznie nie istnieje coś takiego jak podwójne kliknięcie to system wysyła taki komunikat WM_LBUTTONDBLCLK do oka pod warunkiem że ma ono styl CS_DBLCLKS i naciśnięcia lewego przycisku myszy (komunikaty WM_LBUTTONDOWN) nastąpiły w odpowiednim odstępie czasowym.
@kAzek masz za pewne racje. A Ty @zalespl możesz osiągnąc swój cel chyba tylko hookiem na WH_GETMESSAGE
. A żeby on działal globalnie, z tego co widzę to potrzebna jest niestety/stety dllka.
Przy okazji okazało się, że ze mnie oczywiście totalna lama. Nie wiedzieć dlaczego, gdy robiłem w dllce wyeksportowaną funkcję zwracającą zawartośc zmiennej globalnej tej dllki i chciałem to "odebrać" w aplikacji ładującej dllke przez wywołanie tej funkcji. To zawsze otrzymywałem zero. Może ktoś poda przykład jak to ogarnąc. Dodanie ShareMem
w sekcji uses
nic nie pomogło. Na google jest przykład jak można eksportowac zmienną globalną o nazwie global
typu integer. Ale robiąc to statycznie. Może ktoś bardziej ogarnięty z dllkami, podpowie jak dostać od dllki jakąs wartość obojętnego typu, która tam w dllce się zmieniać może co chwilę. Jak na przykład otrzymywany komunikat z hooku. Myślałem, że takie rzeczy robi się bezproblemowo, ale jednak teraz nie dziwię się Tobie @zalespl, że miałeś problemy, bo sam się motam. Ale to może za mało snu albo jakieś zaćmienie. Także wyjasnijcie mi proszę.
A póki co sklecony na szybko, przykładowy kod, w dołaczonym do tego posta archiwum. Zaś aplikacja, na której można testować hook na komunikat jest w podkatalogu EXAMPLE_APP
. Wszystko skompilowane pod Delphi 7. Potrzebne kody źródłowe, biblioteka i exeki - dołączone. Przeanalizuj sobie @zalespl zawartość dołączonego archiwum.