[英]CreateWindowExA failing on Windows 8 (Pro 64-bit)
在Windows 8(64位)上为64位应用程序调用CreateWindowExA是否存在已知问题?
背景:我正在使用FOX工具包 (FOX STABLE 1.6.46)。 在编译和运行最简单的Hello World示例(“hello”)时,文件FXWindow.cpp:1345中对CreateWindowExA
的调用返回零HWND句柄(但GetLastError()
不报告错误)。 这仅在一个特定配置中发生:
OS | OS Platform | App compiled for | CreateWindowExA succeeds? |
Windows 7 | 32-bit | 32-bit | YES |
Windows 7 | 64-bit | 32-bit | YES |
Windows 7 | 64-bit | 64-bit | YES |
Windows 8 | 64-bit | 32-bit | YES |
Windows 8 | 64-bit | 64-bit | NO! (returns NULL) |
使用最后一个配置, CreateWindowExA
有什么不同吗? 请注意,窗口过程在所有情况下都是相同的,并且它接收的消息按以下顺序排列如下:
WM_GETMINMAXINFO
(转发给DefWindowProc
) WM_NCCREATE
(转发给DefWindowProc
) 在最后一个配置中,它继续WM_NCDESTROY
,然后CreateWindowExA
返回NULL。
在所有其他配置中,发送WM_NCCALCSIZE
,最后发送WM_CREATE
。
我发现了源问题:FOX错误地将窗口过程的函数签名定义为
long CALLBACK wndproc(FXID hwnd,unsigned iMsg,unsigned int wParam,long lParam);
( FXID
void*
),所以在64位Windows上, wParam
和lParam
只有32位宽,而它们应该是64位。 正确的函数签名(使用FOX类型)是:
FXival CALLBACK wndproc(FXID hwnd,unsigned int iMsg,FXuval wParam,FXival lParam);
那么为什么它在64位Windows中运行到Windows 7呢? 正如MSDN所说 :
WM_NCCREATE
的lParam
包含一个指向CREATESTRUCT结构的指针,该结构包含有关正在创建的窗口的信息。 CREATESTRUCT的成员与CreateWindowEx函数的参数相同。
碰巧在Windows 7(64位)及以下版本中,该结构总是在4GB以下的内存中分配,即使指针值被截断为32位,它仍然指向正确的位置。 从Windows 8开始,该结构被分配到64位内存范围内的任何位置,截断它可能会产生不正确的指针。
我不确定有一件事: CALLBACK
是__stdcall
,参数从右到左被压入堆栈。 那么,鉴于windproc
声明不正确,它是否仍然检索正确的iMsg
和hwnd
参数?
我有同样的问题。 然后我使用没有“A”的CreateWindowEx(..)函数解决了它。 这对于应该使用此功能的其他人可能是有益的
确认:64位Windows 8.1不调用WM_CREATE(32位,但是一次调用,如同32位和64位Windows 7)。 当消息循环不相关时,在CreateWindows *()下会发生这些麻烦。
32位地址的注释是公平的。 在下面的代码SetWindowLongPtr(m_hWnd,GWLP_USERDATA,(LONG_PTR)this)中,LONG_PTR可能会被LONG错误地替换为Windows 7原谅而LONG,但Windows 8却没有。
幸运的是,WM_NCCREATE仍然被发送。
在拦截WM_CREATE / WM_NCCREATE之后,必须“返回DefWindowProc()”,而不是“返回0”。
我使用这个机制将一个指针(CreateWindow()的最后一个参数)传递给我的WndProc,后者又将这个指针与hwnd相关联。 希望将所有与窗口相关的数据和函数打包到一个类中,并使代码更好地构造。 这个想法看起来很健壮,但最终我拒绝了。 原因是GetWindowLongPtr()的成本在每次WndProc调用时都会被调用。 它是32位上的约100条指令和64位版本上的~70条。 另一种方法是指向动态对象的静态指针(如果WndProc服务于多个对象实例,则可能是哈希表)。 可能不是很好,但它工作得更快,即使WM_NCCREATE也会消失,它仍会继续工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.