Co znaczy błąd Incompatible types: 'regular procedure and method pointer'

0

Wywala mi taki, i nie wiem co robię źle.
Incompatible types: 'regular procedure and method pointer'

0

To może daj kod. Szklane kule nam się popsuły.

0
var 
  Hook : Integer;
begin
  Hook := SetWindowsHookEx(wh_journalrecord, Play, HInstance, 0);
end;

Chyba wiecie co robi funkcja Play...

0

Poczytaj http://delphi.about.com/cs/adptips2003/a/bltip1003_5.htm
a ta linia kodu co dałeś nic nie mówi...

0

W parametrze dajesz niezgodny typ.
Funkcja SetWindowsHookEx przyjmuje parametry typów : (kolejno)

  • int
  • HOOKPROC
  • HINSTANCE
  • DWORD

Wszystkie parametry sa tylko wejsciowe.
Cala funkcja zwraca wartosc typu HHOOK.
przykład:

HOOKPROC hkprcSysMsg;
static HINSTANCE hinstDLL; 
static HHOOK hhookSysMsg; 
 
hinstDLL = LoadLibrary(TEXT("c:\\myapp\\sysmsg.dll")); 
hkprcSysMsg = (HOOKPROC)GetProcAddress(hinstDLL, "SysMessageProc"); 

hhookSysMsg = SetWindowsHookEx( 
                    WH_SYSMSGFILTER,
                    hkprcSysMsg,
                    hinstDLL,
                    0); 
0
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }

  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  Hook: HHOOK;

implementation

{$R *.dfm}
function Play(Code: integer; wParam, lParam: Longint): Longint; stdcall;
begin
  //tu mozna by cos cobic ale na sztuke wywolam:
  Result := CallNextHookEx(Hook, Code, wParam, lParam);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Hook:=SetWindowsHookEx(wh_journalrecord, play, HInstance, 0);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  UnhookWindowsHookEx(Hook);
end;

end.
0
unit SystemSpy;

interface

uses
  SysUtils, Classes, Windows, Messages;

type
  TKomponent = class(TComponent)
  private
    fHa  : Boolean;
    fHook : HHook;
    MessageBuffer : TEventMsg;
    function Play(Code: Integer; wParam, lParam: Longint): Longint; stdcall;
  protected
    { Protected declarations }
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property HookActive      : Boolean read fHA     write fHa;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Standard', [TKomponent]);
end;

function TKomponent.Play(Code: Integer; wParam, lParam: Longint): Longint; stdcall;
var C : Char;
    S : String;
begin
  case Code of
    HC_ACTION:
      begin
        MessageBuffer := PEventMsg(lParam)^;
        if MessageBuffer.Message = WM_KeyDown then
          begin
                 //'nie wazne';
          end  
      else
        Result := CallNextHookEx(fHook, Code, wParam, lParam)
  end;
end;

constructor TKomponent.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  fHook := SetWindowsHookEx(wh_journalrecord, Play, HInstance, 0);
end;

destructor TKomponent.Destroy;
begin
 UnHookWindowsHookEx(fHook);
 inherited
end;

end.
0

Tyle odpowiedzi i każda błędna.
Pytanie to: "Co znaczy błąd incompatible types: 'regular procedure and method pointer'".
Odpowiedź: błąd ten oznacza niezgodność typów - regularna procedura (?) i wskaźnik na metodę (?)
:D

0

Może popsuję wszystkim zabawę :D, ale czy nie trzeba podać adresu procedury zamiast samej procedury? Czyli @Play. Delphi to nie to samo co C++...

0

@up:
Wtedy "Variable required"...

Znalazłem błąd:
Nie może być
Function TForm1.Play(Code: integer; wParam, lParam: Longint): Longint; stdcall;
Tylko
Function Play(Code: integer; wParam, lParam: Longint): Longint; stdcall;
Itp.

0

Przecież podałem Tobie TomRiddle rozwiązanie w komentarzu, dostałeś w miarę krótko link do źródel z przykładem użycia Hook'a, ktory działa, bo jak mi wspominałeś nie radzisz sobie ze zrozumieniem jak za dużo tekstu masz do przeczytania. Po prostu - o ile się orientuję - funkcja obsługi Hook'a nie może być elementem klasy. Chcesz się odwoływać do jakiejś klasy to podstawiaj sobie w konstruktorze do zmiennej globalnej ten tworzony obiekt i operuj na with ... do begin ... end; Ewentualnie tak jak masz pokazane poniżej. Po co mnożysz sobie problemy i generujesz je tam gdzie ich nie ma lub nie powinno być.

//...
var
  MainForm : TMainForm;

const
  WH_KEYBOARD_LL = $000D;

type
  tagKBDLLHOOKSTRUCT = packed record
    vkCode : DWord;
    ScanCode : DWord;
    Flags : DWord;
    Time : DWord;
    dwExtraInfo : integer;
  end;
  KBDLLHOOKSTRUCT = tagKBDLLHOOKSTRUCT;
  PKBDLLHOOKSTRUCT = ^KBDLLHOOKSTRUCT;

var
  HKHook : HHook;

implementation

{$R *.dfm}

function LowLevelKeyboardProc(nCode : Integer; wParam : Integer; lParam : Integer) : Integer; stdcall; export;
var
  Hook : PKBDLLHOOKSTRUCT;
begin
  Hook := Pointer(lParam);
  case nCode of
    HC_ACTION :
      begin
        with MainForm do
        begin
          TestMemo.Lines.Add(Format('vkCode: %d ScanCode: %d Flags: %d Time: %d ExtraInfo: %d',
            [Hook.vkCode, Hook.ScanCode, Hook.Flags, Hook.Time, Hook.dwExtraInfo]));
        end;
      end;
  end;
  Result := CallNextHookEx(HKHook, nCode, wParam, lParam);
end;

procedure HookIt;
begin
  HKHook := SetWindowsHookEx(WH_KEYBOARD_LL, @LowLevelKeyboardProc, hInstance, 0);
end;

procedure UnHookIt;
begin
  UnHookWindowsHookEx(HKHook);
end;
0

Może być w klasie ale to większa zabawa. W Google znalazłem taki moduł:

unit HookInst;
//------------------------------------------------------------------------------
 //                        HOOK METHOD INSTANCE
 //
 // These few lines of code implement for windows hooks what MakeObjectInstance
 // and FreeObjectInstance do for windows message functions.  They allow a method
 // to be written and passed into the SetWindowsHookEx API function rather than a
 // stand alone function which cannot directly access variables or methods.
 //
 // An example of use is in the IDE Peek expert.
 //
 // The code is based entirely on the MakeObjectInstance and FreeObjectInstance
 // in the Delphi Forms unit.  In fact my only input has been to change a few
 // names and make it work for Hook calls rather than Message calls.  So I don't
 // claim a lot.  Borland's ownership of this code is recognised and I hope
 // noone there minds my borrowing it and bodging it for this purpose!
 //
 // This way of writing a hook function is a bit wasteful of memory for what you
 // are doing (but hell, what's 4KB nowadays!, this isn't a Z80 and CPM).
 //
 // Only tested under Delphi 3.02
 //
 // Version 1.00 5-2-98 Grahame Marsh
 //
 // Freeware - you get it for free, I take nothing, I make no promises!
 //
 // Please feel free to contact me: [email protected]
 //------------------------------------------------------------------------------


 interface

 uses
   Windows;

 type
   THookCall = packed record
     Code   : integer;
     WParam : WPARAM;
     LParam : LPARAM;
     Result : LResult
   end;

   THookMethod = procedure (var HookCall: THookCall) of object;

 function  MakeHookInstance (Method: THookMethod): pointer;
 procedure FreeHookInstance (ObjectInstance: pointer);

 implementation

 const
   InstanceCount = 313;  // set so that sizeof (TInstanceBlock) < PageSize

 type
   PObjectInstance = ^TObjectInstance;
   TObjectInstance = packed record
     Code: Byte;
     Offset: Integer;
     case Integer of
       0: (Next: PObjectInstance);
       1: (Method: THookMethod);
   end;

 type
   PInstanceBlock = ^TInstanceBlock;
   TInstanceBlock = packed record
     Next: PInstanceBlock;
     Code: array[1..2] of Byte;
     WndProcPtr: Pointer;
     Instances: array[0..InstanceCount] of TObjectInstance;
   end;

 var
   InstBlockList : PInstanceBlock  = nil;
   InstFreeList  : PObjectInstance = nil;

 function StdHookProc (Code, WParam: WPARAM; LParam: LPARAM): LResult; stdcall; assembler;
 asm
         XOR     EAX,EAX
         PUSH    EAX
         PUSH    LParam
         PUSH    WParam
         PUSH    Code
         MOV     EDX,ESP
         MOV     EAX,[ECX].Longint[4]
         CALL    [ECX].Pointer
         ADD     ESP,12
         POP     EAX
 end;

 { Allocate a hook method instance }

 function CalcJmpOffset(Src, Dest: Pointer): Longint;
 begin
   Result := Longint(Dest) - (Longint(Src) + 5);
 end;

 function MakeHookInstance(Method: THookMethod): Pointer;
 const
   BlockCode: array [1..2] of Byte = ($59, $E9);
   PageSize = 4096;
 var
   Block: PInstanceBlock;
   Instance: PObjectInstance;
 begin
   if InstFreeList = nil then
   begin
     Block := VirtualAlloc (nil, PageSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
     Block^.Next := InstBlockList;
     Move(BlockCode, Block^.Code, SizeOf(BlockCode));
     Block^.WndProcPtr := Pointer(CalcJmpOffset(@Block^.Code[2], @StdHookProc));
     Instance := @Block^.Instances;
     repeat
       Instance^.Code := $E8;
       Instance^.Offset := CalcJmpOffset(Instance, @Block^.Code);
       Instance^.Next := InstFreeList;
       InstFreeList := Instance;
       Inc(Longint(Instance), SizeOf(TObjectInstance));
     until Longint(Instance) - Longint(Block) >= SizeOf(TInstanceBlock);
     InstBlockList := Block
   end;
   Result := InstFreeList;
   Instance := InstFreeList;
   InstFreeList := Instance^.Next;
   Instance^.Method := Method
 end;

 { Free a hook method instance }

 procedure FreeHookInstance (ObjectInstance: Pointer);
 begin
   if ObjectInstance <> nil then
   begin
     PObjectInstance(ObjectInstance)^.Next := InstFreeList;
     InstFreeList := ObjectInstance
   end
 end;

 end.

a tu przykład użycia:

unit KeybHock;

interface
 
uses
  SysUtils, Classes, Windows, Messages, HookInst;

const
  WH_KEYBOARD_LL = $000D;

type
  tagKBDLLHOOKSTRUCT = packed record
    vkCode : DWord;
    ScanCode : DWord;
    Flags : DWord;
    Time : DWord;
    dwExtraInfo : integer;
  end;
  KBDLLHOOKSTRUCT = tagKBDLLHOOKSTRUCT;
  PKBDLLHOOKSTRUCT = ^KBDLLHOOKSTRUCT;


  TKeybHock = class(TComponent)
  private
    fHa  : Boolean;
    fHook : HHook;
    fHookProc: Pointer;
    MessageBuffer : TEventMsg;
    procedure Play(var HookCall: THookCall);

    procedure SetHookActive(Value: Boolean);
  protected
    { Protected declarations }
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property HookActive: Boolean read fHA  write SetHookActive default False;
  end;


procedure Register;
 
implementation
 
procedure Register;
begin
  RegisterComponents('Standard', [TKeybHock]);
end;

procedure TKeybHock.Play(var HookCall: THookCall);
var
  Hook: PKBDLLHOOKSTRUCT;
begin
  case HookCall.Code of
    HC_ACTION:
    begin
      Hook:= Pointer(HookCall.lParam);
      //tu sie bawisz
    end
    else
      HookCall.Result:= CallNextHookEx(fHook, HookCall.Code, HookCall.wParam, HookCall.lParam);
  end;
end;

procedure TKeybHock.SetHookActive(Value: Boolean);
begin
  if fHA = Value then exit;
  if Value = True then
  begin
    fHookProc:= MakeHookInstance(Play);
    fHook := SetWindowsHookEx(WH_KEYBOARD_LL, fHookProc, HInstance, 0);
    fHA:= (fHook > 0);
  end
  else
  begin
    UnHookWindowsHookEx(fHook);
    FreeHookInstance(fHookProc);
    fHA:= False;
  end;
end;

constructor TKeybHock.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  fHA:= False;
end;

destructor TKeybHock.Destroy;
begin
  SetHookActive(False);
  inherited;
end;
 
end.
0

Mówię to już 4 czy 5 raz. To nie jest kod bezpośrednio na formie. Tworzę komponent (nazwa klasy TKomponent), i to wtedy (w kodzie komponentu, jak chce go zainstalować) błąd się pojawia. Na formie działa świetnie.

0

Incompatible types: 'regular procedure and method pointer'

Nie można używać wskaźnika na metodę (procedurę lub funkcję będącą członkiem klasy) tam, gdzie potrzebny jest wskaźnik na procedurę lub funkcję globalną — ani odwrotnie.

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