2015-04-02 111 views
-2

首先,我是完全的,对于任何类型的编程都是100%新的,所以我很抱歉如果这是一个非常明显的错误,但我找不到任何东西。试图保持代表活着

我想实现我的程序的全局热键,我需要保持这种委托活着防止CallbackOnCollectedDelegate错误,但我的代码给了我两下生成错误:

无效令牌 '(' 类,结构或接口成员声明

无效标记 ')' 在类,结构或接口成员声明

public delegate int keyboardHookProc(int code, int wParam, ref keyboardHookStruct lParam); 
    GC.KeepAlive(keyboardHookProc); 

    public struct keyboardHookStruct { 
     public int vkCode; 
     public int scanCode; 
     public int flags; 
     public int time; 
     public int dwExtraInfo; 
    } 

    const int WH_KEYBOARD_LL = 13; 
    const int WM_KEYDOWN = 0x100; 
    const int WM_KEYUP = 0x101; 
    const int WM_SYSKEYDOWN = 0x104; 
    const int WM_SYSKEYUP = 0x105; 

任何帮助表示赞赏,谢谢!

+0

委托是一种类型,你不能在方法体内声明它。 – Dusan 2015-04-02 12:29:01

+0

令牌错误是由于您的代码组合造成的 – 2015-04-02 12:30:13

+0

您是否可以发布完整的代码?在哪里声明它? – Rohit 2015-04-02 12:30:35

回答

0

您不能保留代表声明还活着。也不要为此使用GC.KeepAlive();尽管它是针对“托管引用到非托管代码”的情况,但只有在相同方法中设置和清除钩子时,才是有用的(有关更多信息,请参阅this link)。

这些钩子的问题是非托管代码具有委托的地址,但该参考位于垃圾收集器的雷达下方。所以过了一段时间垃圾收集器开始清理,非托管代码调用一个现在无效的地址。

如果您的应用程序保持键盘在其整个生命周期挂钩,一个简单的解决方案是将其分配给一个静态成员:

static keyboardHookProc myKeyboardDelegate; 

void SetHook() 
{ 
    myKeyboardDelegate = new keyboardHookProc(MyHandler); 
    UnmanagedMethod(myKeyboardDelegate); 
} 

int MyHandler(int code, int wParam, ref keyboardHookStruct lParam) 
{ 
    ... 
} 

有更好的方法,虽然,你可以在一个类包装这和隐藏从您的应用程序的其余部分委托。只要确保您保留对您提供给非托管代码的委托的引用,直到挂钩被移除。