ShowWindow如何报告失败?

时间:2017-03-04 19:03:24

标签: windows winapi

阅读文档看起来ShowWindow函数没有失败的概念。这让我感到惊讶,因为看起来几乎任何非平凡的代码都会失败。

窗口句柄可能无效。显然,这是调用者违反的联系方式,但这种情况只是“未定义”或“不关心”,那么呢?

我想知道是否支持SetLastError

3 个答案:

答案 0 :(得分:1)

ShowWindowAsync虽然本质上是异步的,但它会告诉您操作是否成功启动。根据您的工作情况,它可能是一种可用的替代方案。

答案 1 :(得分:1)

虽然ShowWindow()确实没有错误概念,但我们可以使用SetWindowPos()作为备选文件,以支持GetLastError()

在下文中,我提供了一个示例,演示如何将SetWindowPos()包装到函数中,以通过抛出和处理异常来弥合C样式错误报告与C ++方法之间的差距。

示例:

#include <windows.h>
#include <iostream>
#include <sstream>
#include <system_error>

// Show or hide the given window by calling SetWindowPos().
//
// \exception Reports any error by throwing std::sytem_error exception.

void MyShowWindow( HWND hwnd, bool show ) {
    DWORD flags = SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER;
    if( show )
        flags |= SWP_SHOWWINDOW;
    else
        flags |= SWP_HIDEWINDOW;

    if( !::SetWindowPos( hwnd, nullptr, 0, 0, 0, 0, flags ) ) {
        // NOTE: Call GetLastError() IMMEDIATELY when a function's return value indicates 
        // failure and it is documented that said function supports GetLastError().
        // ANY other code (be it your own or library code) before the next line must be 
        // avoided as it may invalidate the last error value.
        DWORD err = ::GetLastError();
        std::ostringstream msg;
        msg << "Could not change visibility of window (HWND 0x" << hwnd << ")";
        throw std::system_error( static_cast<int>( err ), std::system_category(), msg.str() );
    }
}

<强>用法:

使用包装函数MyShowWindow()时,必须确保捕获它抛出的异常。以下示例说明了如何执行此操作。

int main(){
    try{
        // Passing an invalid handle to MyShowWindow() will throw
        // std::system_error exception. There may be other reasons for the
        // function to fail, for instance if you pass the window handle of  
        // another process to which you don't have access as an argument
        // to the function.
        HWND anInvalidHandle = 0;
        MyShowWindow( anInvalidHandle, true );
    }
    catch( std::system_error& e ){
        // Catch the exception thrown by MyShowWindow() and report all
        // available error details.
        // e.code() outputs the error code retrieved via GetLastError().
        std::cout << "Error: " << e.what() << std::endl
                  << "Error code: " << e.code() << std::endl;
    }

    return 0;
}

<强>输出:

Error: Could not change visibility of window (HWND 0x00000000): Ung³ltiges Fensterhandle
Error code: system:1400

消息显示“窗口句柄无效”,错误代码对应ERROR_INVALID_WINDOW_HANDLE。

注意:

虽然提供的MyShowWindow()函数仅支持SW_HIDE的{​​{1}}和SW_SHOW功能,但可以通过使用其他ShowWindow标记来提供剩余的功能(例如SetWindowPos映射到SW_SHOWNA)或调用提供此功能的其他Windows API函数,并记录为支持SWP_SHOWWINDOW | SWP_NOACTIVATE

答案 2 :(得分:-2)

ShowWindow没有任何错误感知。如果提供的窗口不存在(或者不可访问),则只返回false。

事实上,ShowWindow除了向目标窗口发送WM_SHOW消息之外没有什么作用。由于Windows消息队列的性质,ShowWindow不知道它的完成状态。虽然正如评论中指出的那样,WM_SHOW是同步处理的,但消息队列本身没有内置的错误报告机制,除了将错误消息发送回发送方。

[编辑] 在尝试访问不存在的窗口时,GetLastError似乎报告了无效的窗口句柄。对我来说,这是一种未知行为,因为通常返回值应指示是否使用GetLastError。但是,通过事先手动测试窗口可以很容易地避免这种情况(参见:IsWindow)