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

时间:2012-11-13 22:38:37

标签: windows-8 64-bit winapi fox-toolkit

对于64位应用程序,在Windows 8(64位)上调用CreateWindowExA是否存在已知问题?

背景:我正在使用FOX Toolkit(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

3 个答案:

答案 0 :(得分:2)

我发现源问题:FOX错误地将窗口过程的函数签名定义为

long CALLBACK wndproc(FXID hwnd,unsigned iMsg,unsigned int wParam,long lParam);

FXID typedef为void*),因此在64位Windows上,wParamlParam只有32位宽,而它们应该是64位。正确的函数签名(使用FOX类型)是:

FXival CALLBACK wndproc(FXID hwnd,unsigned int iMsg,FXuval wParam,FXival lParam); 

那么为什么它可以在64位Windows中运行到Windows 7?正如MSDN says

  

lParam的{​​{1}}包含指向CREATESTRUCT的指针   包含有关正在创建的窗口的信息的结构。   CREATESTRUCT的成员与the的参数相同   CreateWindowEx函数。

在Windows 7(64位)及以下版本中,该结构总是在4GB以下的内存中分配,即使指针值被截断为32位,它仍指向正确的位置。从Windows 8开始,该结构被分配在64位内存范围内的任何位置,截断它可能会产生不正确的指针。

我只有一点不确定:WM_NCCREATECALLBACK,参数从右到左被压入堆栈。因此,鉴于__stdcall的声明不正确,它是否仍在检索正确的windprociMsg参数?

答案 1 :(得分:1)

我有同样的问题。然后我使用没有“A”的CreateWindowEx(..)函数解决了它。这可能对应该使用此功能的其他人有益

答案 2 :(得分:0)

确认:64位Windows 8.1不会调用WM_CREATE(32位,而是一位,如同32位和64位Windows 7)。 当消息循环不相关时,在CreateWindows *()下会发生这些麻烦。

32位地址的注释是公平的。 在以下代码中     SetWindowLongPtr(m_hWnd,GWLP_USERDATA,(LONG_PTR)this) LONG_PTR可能被错误地替换为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也会消失,它也会继续工作。