簡體   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