2014-10-10 75 views
9

我和一位程序員進行了一次小小的辯論。他用下面的語句在他的代碼:對`INVALID_HANDLE_VALUE`檢查`HWND`是否錯誤?

HWND hWnd = SomeFunctionWhichReturnsAWindow(); 
if(hWnd != NULL && hWnd != INVALID_HANDLE_VALUE) 
{ 
    // All good 
} 
else 
{ 
    // Error 
} 

我告訴他,在我看來這是一種錯誤的做法,因爲HWND類型無關,與INVALID_HANDLE_VALUE定義,但他肯定這是好的代碼,因爲有效的句柄永遠不可能等於INVALID_HANDLE_VALUE,並且它處於「比安全感更安全」的情緒中。

那麼,這是一個可接受的和正確的習慣用法嗎?

+1

錯誤是一個大詞。但是,當然,窗口句柄永遠不會有這個值,它只用於kernel32句柄。 – 2014-10-10 15:58:23

+2

@HansPassant在實踐中,是的,但不是它只是一個實現細節? – Paul 2014-10-10 16:01:25

+0

如果你看看返回HANDLE的各種函數,你會發現它們中的一些返回NULL(如CreateThread),其中一些返回INVALID_HANDLE_VALUE(如CreateFile)。您必須檢查文檔以查看每個特定函數在失敗時返回的內容。由於歷史原因,返回值非常不一致。這些值被選擇爲與16位Windows兼容。 16位功能的OpenFile,_lopen和_lcreat返回-1上發生故障,使32位CreateFile函數,以便於從Win16的移植代碼返回INVALID_HANDLE_VALUE。 – Marichyasana 2014-10-11 06:59:40

回答

12

HWNDINVALID_HANDLE_VALUE進行比較是錯誤的。雖然在實踐中這不會是一個會傷害你的錯誤。

CreateWindowEx保留爲無效的唯一HWND值爲NULL。現在,它恰好是INVALID_HANDLE_VALUE永遠無法成爲有效的HWND的實現細節,但這只是實現細節。產生窗口句柄的函數CreateWindowEx使用NULL來指示失敗。這就是你需要知道的一切。

如果您希望與您的同事贏得您的意見,我建議您查看SomeFunctionWhichReturnsAWindow並找出調用哪個Win32 API來生成HWND。然後查閱文檔。這會告訴你NULL是保留的無效值。

爲了清楚起見,您絕對應該更改代碼以僅針對NULL進行測試。

8

INVALID_HANDLE_VALUE被定義爲-1。一個無效的HWND被定義爲0.沒有API會在失敗時返回HWND(-1),因此檢查INVALID_HANDLE_VALUE是沒有意義的,它永遠不會發生。

但是,也有一些API接受保留非零HWND值作爲輸入,並且因此不能被用作有效HWND返回值,或者:

PeekMessage()GetMessage()

如果的hWnd (Peek/Get)消息檢索屬於當前線程的任何窗口的消息,以及當前線程的消息隊列中其hwnd值爲NULL(請參閱MSG結構)的任何消息。因此,如果hWnd爲NULL,則會處理窗口消息和線程消息。

如果hWnd爲-1,(PEEK/GET)消息檢索對當前線程的消息隊列,其HWND值爲NULL僅消息,即,螺紋的消息張貼由PostMessage的(當hWnd參數是NULL)或PostThreadMessage。

因此,HWND(0)HWND(-1)之間存在邏輯差異。事實上,由於這種差異,有效的HWND永遠不會是-1,因爲消息循環永遠無法爲其檢索消息。

另外SetWindowPos()有一些保留值,以及:

hWndInsertAfter [在,可選]
類型:HWND

的句柄窗口先於在Z順序定位窗口。該參數必須是窗口句柄或以下值之一。

HWND_BOTTOM
(HWND)1
地方在Z次序的底部的窗口。如果hWnd參數標識最上面的窗口,則窗口失去其最高層狀態,並放置在所有其他窗口的底部。

HWND_NOTOPMOST
(HWND)-2
地方以上所有非最頂層窗口窗口(即,所有最頂層窗口後面)。如果窗口已經是非最高窗口,則此標誌無效。

HWND_TOP
(HWND)0
地方在Z次序的頂部的窗口。

HWND_TOPMOST
(HWND)-1-
地方以上所有非最頂層窗口的窗口。窗口保持最高位置,即使它被禁用。

+1

我還發現'SetWindowPos'收到'(HWND)1'和'(HWND)-2',所以這些文件也不能是有效的'HWND'。這不是檢查驗證的理由,但:) – Paul 2014-10-10 17:35:30

1

CreateWindowEx和返回HWND的類似函數清楚地表明無效的HWND是0.任何其他可能是有效的。

因此,檢查INVALID_HANDLE_VALUE是100%錯誤的,無論你可能會認爲什麼。

製作假設,如「這將可能永遠不會傷害」是非常危險的,此時雖然有效,將來你可以用來假設都不是無辜的類似的功能。