A有一个C#类,简化了全局热键的处理。 该类使用Win32-API函数 RegisterHotKey()来注册热键。

根据MSDN,此函数需要ID值在0x0000到0xBFFF范围内 从应用程序调用时,ID值在0xC000到0xFFFF范围内 从共享DLL调用。 GlobalAddAtom()可用于在运行时获取ID 在DLL中。

要隐藏与类用户的区别,类本身应该决定哪个 注册热键时使用ID范围。好吧,要做到这一点,班级必须 能够检测其代码是在应用程序内还是在应用程序内运行 共享DLL。

但是怎么做?什么是最好的C#/ .NET方式呢?

有帮助吗?

解决方案

试试这个:

bool isDll = this.GetType().Assembly.EntryPoint == null;

MSDN:

Assembly.EntryPoint Property

  

"属性值MethodInfo对象   这代表了入口点   这个集会。如果没有入口点   发现(例如,组件是一个   DLL),一个空引用(Nothing in   返回Visual Basic)。 "

其他提示

你的类 - 你知道你把它放在哪里。

如果您没有共享它,那么只需选择一个低于0xBFFF的ID并完成它。

如果您的类属于可以由多个应用程序共享的DLL ...或者可以简单地由您无法控制的代码共享,因此无法为...分类ID,然后使用 GlobalAddAtom() 获取ID(并记住你之后打电话给 GlobalDeleteAtom() 取消注册热键)。


解释

考虑为什么存在两个不同的ID范围,以及为什么API文档建议使用 GlobalAddAtom()来获取共享DLL的后一范围内的ID,这可能值得花一点时间。让我们从 RegisterHotKey()的参数文档开始:

  

ID 结果        [in]指定热键的标识符。如果hWnd参数为NULL,则热键与当前线程关联,而不是与特定窗口关联。如果已存在具有相同hWnd和id参数的热键,请参阅所执行操作的备注。

由此我们可以推测,热键由两个可能的信息对中的一个唯一标识:线程或窗口句柄,以及任意16位数字。如果指定窗口句柄( HWND ),则消息被发送到该窗口;否则,它被发送到线程。

所以......如果你只为给定的窗口注册一个热键,那么这个ID并不重要 1 ;没有其他人可以为该窗口注册热键,其他窗口的热键事件将发布到这些窗口。同样,如果您只为给定的线程注册一个无窗口热键,您将只获取该热键的消息。 如果您控制应用程序的所有代码,您可以使用您想要分配它们的任何技术来选择您想要的热键ID ;没有其他人会踩到他们,因为你拥有能够的所有代码来踩他们!

但是如果你正在编写一个可以被其他代码调用的通用例程呢?您无法可靠地选择常量ID,因为调用者可能已经使用该ID,如果他们也使用相同的窗口或线程,您最终将重新定义其热键。或者,如果(在您的情况下)您不知道在运行时将注册多少热键?

您需要一种方法来确保您在运行时选择的ID将是其他人无法使用的ID。这是 GlobalAddAtom()发挥作用的地方:你传递一个字符串,它给你一个保证与该字符串相对应的ID而不是其他字符串;这对系统来说实际上是唯一的,除非其他人传递相同的字符串 - 你可能会想出一个独特的字符串;只需使用您的公司名称或社会安全号码,以及为您需要的每个新原子增加的前缀。或者,如果你真的是偏执狂,请使用GUID。

真相背后的真相

有了这个,让我试着澄清一些混乱:Windows实际上并不关心调用 RegisterHotKey()的代码是否在DLL中。它不能。请考虑以下例程:

void RegisterSuperHappyFunHotKey(HWND hWnd, int id, 
                                 unsigned int fsModifiers, unsigned int vk)
{
   RegisterHotKey(hWnd, id, fsModifiers, vk);
}

此例程 nothing 但将其参数转发到WinAPI函数,其中没有一个标识调用

完成菲利普回答:

您需要获取调用函数的程序集的引用,因此代码应如下所示:

Assembly assembly = Assembly.GetCallingAssembly();
Boolean isDll = assembly.EntryPoint == null;

希望这有帮助。

Ricardo Lacerda Castelo Branco

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top