1

我正在阅读 MSDN 中的 NOTIFYICONDATA 文档。

它说NOTIFYICONDATA结构有一个cbSize成员应该设置为结构的大小,但NOTIFYICONDATA结构的大小在每个Shell32.dll中都有不同的大小,所以你应该在设置cbSize之前获得Shell32.dll版本。

以下引用来自 MSDN:


如果是 5.0 或更高版本,请按如下方式初始化 cbSize 成员。

nid.cbSize = sizeof(NOTIFYICONDATA);

将 cbSize 设置为该值会启用所有 5.0 和 6.0 版本的增强功能。对于早期版本,6.0 之前的结构的大小由 NOTIFYICONDATA_V2_SIZE 常量给出,5.0 之前的结构由 NOTIFYICONDATA_V1_SIZE 常量给出。如下初始化 cbSize 成员。nid.cbSize = NOTIFYICONDATA_V2_SIZE;

将此值用于 cbSize 将允许您的应用程序将 NOTIFYICONDATA 与早期的 Shell32.dll 版本一起使用,尽管没有 6.0 版增强功能。


我发现它有点模糊,因为 'sizeof(NOTIFYICONDATA)' 在 Win98(使用 Shell32.dll 4.x 版)、Win2K(5.0 版)和 WinXP(6.0 版)中具有不同的值。它怎么能“启用所有版本 5.0 和 6.0 的增强功能”?

于是我找了NOTIFYICONDATA_V1_SIZE的定义(源代码如下),我看到了:

NOTIFYICONDATA_V1_SIZE 适用于 Win 2K(不包括 2K)

NOTIFYICONDATA_V2_SIZE 适用于 Win XP

NOTIFYICONDATA_V3_SIZE 适用于 Vista

(不确定我是否正确)

和 MSDN 说的完全不一样?Win2K没有?

所以,我现在完全糊涂了。如何根据 Shell32.dll 版本设置 cbSize 成员?

//= = = = = = = = ShellAPI.h = = = = = = = =

typedef struct _NOTIFYICONDATAA {
    DWORD cbSize;
    HWND hWnd;
    UINT uID;
    UINT uFlags;
    UINT uCallbackMessage;
    HICON hIcon;
#if (NTDDI_VERSION < NTDDI_WIN2K)
    CHAR   szTip[64];
#endif
#if (NTDDI_VERSION >= NTDDI_WIN2K)
    CHAR   szTip[128];
    DWORD dwState;
    DWORD dwStateMask;
    CHAR   szInfo[256];
    union {
        UINT  uTimeout;
        UINT  uVersion;  // used with NIM_SETVERSION, values 0, 3 and 4
    } DUMMYUNIONNAME;
    CHAR   szInfoTitle[64];
    DWORD dwInfoFlags;
#endif
#if (NTDDI_VERSION >= NTDDI_WINXP)
    GUID guidItem;
#endif
#if (NTDDI_VERSION >= NTDDI_VISTA)
    HICON hBalloonIcon;
#endif
} NOTIFYICONDATAA, *PNOTIFYICONDATAA;


typedef struct _NOTIFYICONDATAW {
    DWORD cbSize;
    HWND hWnd;
    UINT uID;
    UINT uFlags;
    UINT uCallbackMessage;
    HICON hIcon;
#if (NTDDI_VERSION < NTDDI_WIN2K)
    WCHAR  szTip[64];
#endif
#if (NTDDI_VERSION >= NTDDI_WIN2K)
    WCHAR  szTip[128];
    DWORD dwState;
    DWORD dwStateMask;
    WCHAR  szInfo[256];
    union {
        UINT  uTimeout;
        UINT  uVersion;  // used with NIM_SETVERSION, values 0, 3 and 4
    } DUMMYUNIONNAME;
    WCHAR  szInfoTitle[64];
    DWORD dwInfoFlags;
#endif
#if (NTDDI_VERSION >= NTDDI_WINXP)
    GUID guidItem;
#endif
#if (NTDDI_VERSION >= NTDDI_VISTA)
    HICON hBalloonIcon;
#endif
} NOTIFYICONDATAW, *PNOTIFYICONDATAW;


#define NOTIFYICONDATAA_V1_SIZE     FIELD_OFFSET(NOTIFYICONDATAA, szTip[64])
#define NOTIFYICONDATAW_V1_SIZE     FIELD_OFFSET(NOTIFYICONDATAW, szTip[64])
#ifdef UNICODE
#define NOTIFYICONDATA_V1_SIZE      NOTIFYICONDATAW_V1_SIZE
#else
#define NOTIFYICONDATA_V1_SIZE      NOTIFYICONDATAA_V1_SIZE
#endif


#define NOTIFYICONDATAA_V2_SIZE     FIELD_OFFSET(NOTIFYICONDATAA, guidItem)
#define NOTIFYICONDATAW_V2_SIZE     FIELD_OFFSET(NOTIFYICONDATAW, guidItem)
#ifdef UNICODE
#define NOTIFYICONDATA_V2_SIZE      NOTIFYICONDATAW_V2_SIZE
#else
#define NOTIFYICONDATA_V2_SIZE      NOTIFYICONDATAA_V2_SIZE
#endif


#define NOTIFYICONDATAA_V3_SIZE     FIELD_OFFSET(NOTIFYICONDATAA, hBalloonIcon)
#define NOTIFYICONDATAW_V3_SIZE     FIELD_OFFSET(NOTIFYICONDATAW, hBalloonIcon)
#ifdef UNICODE
#define NOTIFYICONDATA_V3_SIZE      NOTIFYICONDATAW_V3_SIZE
#else
#define NOTIFYICONDATA_V3_SIZE      NOTIFYICONDATAA_V3_SIZE
#endif

(好像代码在网站上看起来不太好,但它来自ShellAPI.h,都一样)

4

3 回答 3

4

这取决于您编译的最低 Windows 版本。您不会动态设置大小。根据您支持的最低版本的 Windows 设置大小。

于 2009-04-13T12:26:39.343 回答
4

通过平台 sdk 标头可以使用哪些功能由 控制_WIN32_WINNT,应将其定义为您所针对的操作系统的较低版本。

http://msdn.microsoft.com/en-us/library/6sehtctf.aspx正确的值是:

0x0500 用于 Windows 2000 操作系统,0x0501 用于 Windows XP,0x0502 用于 Windows Server 2003,0x0600 用于 Windows Vista。

所以NOTIFYICONDATA_V1_SIZE参考任何低于 2K 的版本,参考NOTIFYICONDATA_V2_SIZE2K,参考NOTIFYICONDATA_V3_SIZEXP 而没有参考 Vista(在这种情况下,您可以使用 sizeof(NOTIFYICONDATA))。

如果您编译项目并_WIN32_WINNT设置为最新版本,并检测您在运行时运行的 shell.dll 版本,您可以将 .cbSize 设置为正确的大小,其余字段将被忽略。

像这样的东西应该工作:

NOTIFYICONDATA notify;
ZeroMemory(&notify, sizeof(notify)); 
if(version >= VISTA) {
  notify.cbSize = sizeof(NOTIFYICONDATA);
}
else if(version >= XP) {
  notify.cbSize = NOTIFYICONDATA_V3_SIZE;
}
else if(version >= 2K) {
  notify.cbSize = NOTIFYICONDATA_V2_SIZE;
}
else {
  notify.cbSize = NOTIFYICONDATA_V1_SIZE;
}
于 2009-04-13T16:25:16.073 回答
0

“这取决于您编译的最低 Windows 版本。您不会动态设置大小。您根据您支持的最低 Windows 版本设置大小。”

其实并不是。只需尝试针对 VISTA 构建并在 XP 下运行。您将在 64+ 字节的消息大小上获得一个空的工具提示字符串。安全的解决方案是构建(_WIN32_WINNT >= 0x0600)和设置cbSize = NOTIFYICONDATA_V3_SIZE

正确的解决方案是在运行时检查shell32.dll版本。6.0.6000 - Vista+, 6.0.0 - XP,5.0.0 - W2K

于 2014-04-04T13:16:35.613 回答