检查`HWND`对`INVALID_HANDLE_VALUE`是错误的吗?

Pau*_*aul 12 c windows winapi

我与一位程序员进行了一次小小的辩论.他在代码中使用了以下习语:

HWND hWnd = SomeFunctionWhichReturnsAWindow();
if(hWnd != NULL && hWnd != INVALID_HANDLE_VALUE)
{
    // All good
}
else
{
    // Error
}
Run Code Online (Sandbox Code Playgroud)

我告诉他,在我看来,这是一种错误的方法,因为HWND类型与INVALID_HANDLE_VALUE定义无关,但他确信这是一个好的代码,因为有效的句柄永远不会相等INVALID_HANDLE_VALUE,而且它的情绪是"比抱歉更安全".

那么,这是一个可以接受和正确的成语吗?

Dav*_*nan 16

比较HWND反对是错误的INVALID_HANDLE_VALUE.虽然,在实践中,这不是一个会伤害你的错误.

HWNDCreateWindowEx无效保留的唯一值是NULL.现在,它恰好是一个INVALID_HANDLE_VALUE不能有效的HWND实现细节,但这只是实现细节.能产生窗口句柄功能,CreateWindowEx,使用NULL以指示失败.这就是你需要知道的全部.

如果您希望与您的同事赢得您的论点,我建议您查看内部SomeFunctionWhichReturnsAWindow并找出调用哪个Win32 API来生成HWND.然后查阅文档.这将显示您NULL保留的无效值.

为了清楚起见,您绝对应该更改代码以NULL单独测试.


Rem*_*eau 11

INVALID_HANDLE_VALUE定义为-1.无效HWND定义为0.没有API会HWND(-1)在失败时返回,因此检查INVALID_HANDLE_VALUE是没有意义的,它永远不会发生.

但是,有些API接受保留的非零HWND值作为输入,因此不能用作有效的HWND返回值:

PeekMessage()并且GetMessage():

如果hWnd为NULL,则(Peek/Get)Message检索属于当前线程的任何窗口的消息,以及当前线程的消息队列中hwnd值为NULL的任何消息(请参阅MSG结构).因此,如果hWnd为NULL,则处理窗口消息和线程消息.

如果hWnd为-1,则(Peek/Get)消息仅检索当前线程的hwnd值为NULL的消息队列上的消息,即PostMessage发布的线程消息(当hWnd参数为NULL时)或PostThreadMessage.

所以HWND(0)和之间存在逻辑差异HWND(-1).事实上,由于存在这种差异,有效HWND将永远不会为-1,因为消息循环永远无法为其检索消息.

还有SetWindowPos()一些保留值:

hWndInsertAfter [in,optional]
类型:HWND

窗口的句柄,位于Z顺序中定位窗口之前.此参数必须是窗口句柄或以下值之一.

HWND_BOTTOM
(HWND)1
将窗口置于Z顺序的底部.如果hWnd参数标识最顶层窗口,则窗口将失去其最顶层状态,并放置在所有其他窗口的底部.

HWND_NOTOPMOST
(HWND)-2
将窗口置于所有非最顶层窗口(即所有最顶层窗口后面)的上方.如果窗口已经是非最顶层窗口,则此标志无效.

HWND_TOP
(HWND)0
将窗口置于Z顺序的顶部.

HWND_TOPMOST
(HWND)-1
将窗口置于所有非最顶层窗口的上方.即使停用窗口,窗口也会保持最高位置.