Windows 8 CreateWindowExA在Windows 8上失败(Pro 64位)

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

在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 | 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);