GetWindowLongA 函数 (winuser.h) - Win32 apps | Microsoft Learn
GetWindowLongA 函数 (winuser.h)
GetWindowLongPtrA 函数 (winuser.h)
GetWindowLongPtrW 函数 (winuser.h)
GetWindowLongW 函数 (winuser.h)
函数间的区别是什么?
1.后缀 A 和 W 的含义:
- A 后缀:ANSI 版本,使用 ANSI 字符集(单字节字符)
- W 后缀:Unicode 版本,使用 Unicode 字符集(宽字符,UTF-16)
2.函数区别
- GetWindowLongA:32位 ANSI 版本
- GetWindowLongW:32位 Unicode 版本
- GetWindowLongPtrA:64位 ANSI 版本
- GetWindowLongPtrW:64位 Unicode 版本
3.32位和64位的区别:
- GetWindowLong:用于32位系统,返回32位值
- GetWindowLongPtr:用于64位系统,返回64位值(在64位系统上可以处理指针)
[DllImport("user32.dll", EntryPoint = "GetWindowLong")]
private static extern IntPtr GetWindowLong32(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", EntryPoint = "GetWindowLongPtr")]
private static extern IntPtr GetWindowLong64(IntPtr hWnd, int nIndex);
在引用时为什么不需要带后面的A或W?
- C#的P/Invoke(Platform Invocation Services)系统会自动处理字符集映射
- 当在C#中使用 [DllImport] 时,可以通过 CharSet 参数来控制使用哪个版本,如:
// 自动选择(默认)
[DllImport("user32.dll", EntryPoint = "GetWindowLong")]
// 明确指定ANSI
[DllImport("user32.dll", CharSet = CharSet.Ansi)]
// 明确指定Unicode
[DllImport("user32.dll", CharSet = CharSet.Unicode)]- 不指定 CharSet,默认会使用 CharSet.Auto,这会根据操作系统自动选择合适的版本
- 在现代Windows系统中(NT系列),默认会使用Unicode版本(W)
实践建议:
- 在现代Windows开发中,推荐使用Unicode版本(W),因为它支持所有字符集
- 在64位兼容性方面,推荐使用Ptr版本的函数
- 在C#中,最好使用 CharSet.Auto 或 CharSet.Unicode,让系统自动选择合适的版本
- 如果需要同时支持32位和64位系统,可以像你的代码示例那样分别声明两个版本,然后根据运行时的系统架构选择合适的版本
这种设计是Windows API的历史遗留问题,主要是为了向后兼容性。在现代开发中,我们通常不需要关心这些细节,因为框架(如.NET)会帮我们处理这些差异。
ANSI 版本和Unicode 版本区别
1.ANSI 版本(A后缀):
- ANSI(American National Standards Institute)是早期Windows使用的字符编码标准
- 特点:
- 使用单字节字符(1个字节 = 8位)表示一个字符
- 在英语环境下工作良好(因为ASCII字符集只需要7位就能表示)
- 不同语言环境使用不同的代码页(Code Page)
- 例如:
- 英语使用代码页 1252
- 简体中文使用代码页 936
- 日语使用代码页 932
- 局限性:
- 一个字节最多只能表示256个不同的字符
- 不同语言之间的文本无法在同一程序中正确显示
- 需要切换代码页来支持不同语言
2.Unicode 版本(W后缀):
- Unicode是一个国际标准,目标是包含世界上所有字符
- 特点:
- 使用宽字符(2个字节 = 16位)表示一个字符(在Windows中使用UTF-16编码)
- 可以表示超过65,536个不同的字符
- 支持多语言文本在同一程序中混合使用
- 不需要切换代码页
- 可以处理所有语言的字符
3.为什么会有这两个版本:
- 历史原因:
- Windows最初(Windows 3.1之前)只支持ANSI
- Windows NT引入了Unicode支持
- 为了保持向后兼容性,保留了ANSI版本的API
- 兼容性考虑:
- 旧的应用程序仍在使用ANSI版本
- 一些遗留系统可能只支持ANSI
- 某些特定场景下ANSI版本可能更节省内存
ANSI 和ASCII区别
1.ASCII(American Standard Code for Information Interchange):
- 是最基本的字符编码标准
- 使用7位二进制数(0-127)表示字符
- 只能表示128个字符:
- 0-31:控制字符(如换行、回车等)
- 32-126:可打印字符(英文字母、数字、标点符号等)
- 127:DEL(删除)
- 优点:简单,适用于英文
- 缺点:无法表示其他语言字符
2.ANSI(American National Standards Institute):
- 实际上是对ASCII的扩展
- 使用8位(一个字节)表示字符(0-255)
- 结构:
- 0-127位置:与ASCII完全相同
- 128-255位置:根据不同的代码页(Code Page)定义不同的字符
- 代码页系统:
- Windows-1252(CP1252):西欧语言
- CP936(GBK):简体中文
- CP932:日语
- CP949:韩语