Windows 8 CreateWindowExA在Windows 8上失败(Pro 64位)
在Windows 8(64位)上为64位应用程序调用CreateWindowExA是否存在已知问题 上下文:我正在使用(FOX STABLE 1.6.46)。在编译和运行最简单的Hello World示例(“Hello”)时,对文件FXWindow.cpp:1345中的Windows 8 CreateWindowExA在Windows 8上失败(Pro 64位),windows-8,64-bit,winapi,fox-toolkit,Windows 8,64 Bit,Winapi,Fox Toolkit,在Windows 8(64位)上为64位应用程序调用CreateWindowExA是否存在已知问题 上下文:我正在使用(FOX STABLE 1.6.46)。在编译和运行最简单的Hello World示例(“Hello”)时,对文件FXWindow.cpp:1345中的CreateWindowExA的调用返回零HWND句柄(但GetLastError()不报告错误)。这仅在一种特定配置中发生: OS | OS Platform | App compiled for | Create
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\u NCCREATE
)DefWindowProc
WM\u NCDESTROY
,然后CreateWindowExA
返回NULL
在所有其他配置中,
WM\u NCCALCSIZE
被发送,最后WM\u CREATE
我发现了源问题:福克斯错误地将窗口过程的函数签名定义为
long CALLBACK wndproc(FXID hwnd,unsigned iMsg,unsigned int wParam,long lParam);
(使用FXID
typedef'd到void*
),因此在64位窗口上,wParam
和lParam
只有32位宽,而它们应该是64位的。正确的函数签名(使用FOX类型)是:
那么为什么它能在64位Windows到Windows7之间工作呢?作为:
WM\u NCCREATE
的lParam
包含指向CREATESTRUCT的指针
结构,其中包含有关正在创建的窗口的信息。
CREATESTRUCT的成员与
CreateWindowEx函数
在Windows7(64位)及以下版本上,该结构总是在4GB以下的内存中分配,即使指针值被截断为32位,它仍然指向正确的位置。从Windows 8开始,该结构被分配到64位内存范围内的任何位置,截断它可能会产生错误的指针
只有一件事我不确定:
CALLBACK
作为\uu stdcall
,参数从右到左被推到堆栈上。因此,鉴于windproc的声明不正确,它是否仍在检索正确的iMsg
和hwnd
参数?我也遇到了同样的问题。然后我用CreateWindowEx(..)函数解决了这个问题,没有“A”。这可能对其他应该使用此功能的人有益确认: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不能原谅LONG
幸运的是,WM_NCCREATE仍然被发送
截取WM_CREATE/WM_NCCREATE后,必须“返回DefWindowProc()”,而不是“返回0”
我使用这种机制将指针(CreateWindow()的最后一个参数)传递给我的WndProc,WndProc又将该指针与hwnd关联起来。
其目的是将所有与窗口相关的数据和函数打包到一个类中,并使代码具有更好的结构。
这个想法看起来很有说服力,但我最终还是拒绝了。
原因是每次WndProc调用都会调用GetWindowLongPtr()的开销。
在32位版本上是~100条指令,在64位版本上是~70条指令。
另一种方法是指向动态对象的静态指针(如果WndProc服务于多个对象实例,则可能是哈希表)。
也许不是很好,但它工作得更快,即使WM\u nCreate也会消失,它也会继续工作。是
DefWindowProc()
在处理WM\u nCreate
时返回FALSE
?@RemyLebeau:是-返回FALSE
。返回类型也错误。在x64上,前4个参数通过寄存器传递。正确-也修复了这一问题。现在一切都清楚了。
FXival CALLBACK wndproc(FXID hwnd,unsigned int iMsg,FXuval wParam,FXival lParam);