Przekazywanie zmiennych na zewnątrz z DLL

0

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.

0

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.

0

Zmienne można tak samo eksportować jak funkcje.
Przez "tak samo" mam na myśli tak samo.

0
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. :)

0

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.

0

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?

0

w DLL w sekcji uses Unit1 in 'Unit1.pas' {Form1};

1

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.

0

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.

0

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.

0

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.
0

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.

0

@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.

1 użytkowników online, w tym zalogowanych: 0, gości: 1