P/Invoke 使用的“APPCOMMAND”变量是啥?

Posted

技术标签:

【中文标题】P/Invoke 使用的“APPCOMMAND”变量是啥?【英文标题】:What are "APPCOMMAND" variables used with P/Invoke?P/Invoke 使用的“APPCOMMAND”变量是什么? 【发布时间】:2014-06-04 20:39:39 【问题描述】:

我在 *** 上搜索并找到了Mute Volume in C# 的答案。我不明白答案是怎么回事。我从未深入了解编组或 P/Invoke。我以前用过它们,但不明白我在做什么。

这就是我感到困惑的地方:

private const int APPCOMMAND_VOLUME_MUTE = 0x80000;
private const int WM_APPCOMMAND = 0x319;

在声明这些时,它们的名称是否重要,或者它们只是被视为任何整数而不管它们被称为什么?

0x800000x319 的值从何而来?

【问题讨论】:

常量名称无关紧要,但最好保持名称为标准名称。使用其他名称可能会使熟悉 API 的任何人感到困惑。这些值基本上是由使用 PInvoke 调用的 API 定义的幻数。 WinAPI 充满了神奇的数字,您可以从 MSDN 获得这些数字。为什么是魔术数字?因为微软员工是魔术师。 【参考方案1】:

这些值在Winuser.h 中定义,它包含在更常见的Windows.h 中。

WM_APPCOMMAND 的 Winuser 常量记录在 this MSDN page 上。

与任何变量一样,如何在代码中命名这些变量在技术上取决于您。但是,通常的做法是保持命名与您正在调用的库(在本例中为 Winuser.h)所使用的名称一致。我认为没有理由为它们命名。

【讨论】:

感谢您提供的文档,例如,如果我想粘贴一些东西并且命令代码是 38。我会像这样:private const int APPCOMMAND_PASTE = 0x38000;SendMessage(this.Handle, WM_APPCOMMAND, IntPtr.Zero, (IntPtr)APPCOMMAND_PASTE); 假设您已经导入了 user32.dll 并且当然声明了 SendMessage。 @Frank Close。正如 kobigurk 指出的那样,这些值是 LPARAM 并且需要放置在高位,因此您应该将其定义为 APPCOMMAND_PASTE = 0x380000; (用 四个 零填充右侧)。完整的 8 位值实际上是 0x00380000(静音是 0x00080000),我们只是去掉前导零,就像你写 int a = 1; 而不是 int a = 00000001; 一样。【参考方案2】:

这些名称是为了方便起见,但取自 WinAPI 文档/头文件。其中许多常量都有一个助记符前缀,作为它们使用位置的提示,例如WM_ => Windows 消息、SPI_ => SystemParametersInfo 等

最好不要更改它们,只要您可以在必要时在文档中查找它们。

除了 Microsoft 文档之外,pinvoke.net 是一个社区维护的 wiki,它记录了 WinAPI。如果需要,您可以在那里查找常量值。归根结底,它们之所以如此,是因为它们在 WinAPI 中是这样定义的。

【讨论】:

【参考方案3】:

命名约定无关紧要,它只包含一个 int 值。通常使用这些名称,但您可以使用任何名称。

这些值由 SendMessage e.q. 使用

[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);

SendMessage(this.Handle, WM_APPCOMMAND, IntPtr.Zero, (IntPtr)APPCOMMAND_VOLUME_MUTE);

SendMessage(this.Handle, WM_APPCOMMAND, IntPtr.Zero, (IntPtr)APPCOMMAND_VOLUME_UP);

http://www.blackwasp.co.uk/BasicVolumeControl.aspx

【讨论】:

【参考方案4】:

名称无关紧要,正如您所料 - 这些是整数值,它们取自 MSDN。

请记住,其中的值是 LPARAM,这意味着它们是高位。 WPARAM 将是低位。两者都是 32 位(4 字节),在这种情况下它们为零 - 这就是“0x8”变为“0x80000”的原因。

【讨论】:

以上是关于P/Invoke 使用的“APPCOMMAND”变量是啥?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 WM_APPCOMMAND LPARAM 必须乘以 65536

使用 P/Invoke 会导致系统 AccessViolationException [重复]

使用 P/Invoke 时设置 StringBuilder.Capacity 的正确方法是啥?

使用 P/Invoke 调用 dll 时,为啥 LoadLibrary 在某些机器上会失败?

使用 P/Invoke 时为非托管代码存储数据

使用 P/Invoke 在托管和非托管回调链上引发异常