繁体   English   中英

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

[英]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上, wParamlParam只有32位宽,而它们应该是64位。 正确的函数签名(使用FOX类型)是:

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

那么为什么它在64位Windows中运行到Windows 7呢? 正如MSDN所说

WM_NCCREATElParam包含一个指向CREATESTRUCT结构的指针,该结构包含有关正在创建的窗口的信息。 CREATESTRUCT的成员与CreateWindowEx函数的参数相同。

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

我不确定有一件事: CALLBACK__stdcall ,参数从右到左被压入堆栈。 那么,鉴于windproc声明不正确,它是否仍然检索正确的iMsghwnd参数?

我有同样的问题。 然后我使用没有“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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM