简体   繁体   English

ShowWindow无效的窗口句柄

[英]ShowWindow invalid window handle

I have been trying recently to create a window class using the Windows API in C++. 我最近一直在尝试使用C ++中的Windows API创建一个窗口类。 However, whenever I attempt to call ShowWindow, the function sets the last error to 1400 (ERROR_INVALID_WINDOW_HANDLE). 但是,每当我尝试调用ShowWindow时,该函数都会将最后一个错误设置为1400(ERROR_INVALID_WINDOW_HANDLE)。 After trying for a while, I stumbled across the following example: http://blogs.msdn.com/b/oldnewthing/archive/2005/04/22/410773.aspx#comments 在尝试了一段时间之后,我偶然发现了以下示例: http//blogs.msdn.com/b/oldnewthing/archive/2005/04/22/410773.aspx#comments

Even creating a new project (I use MSVC Express 2008) and copying the code exactly (which I hate to do), I discovered that, while the code successfully created a window, the ShowWindow function still reported error 1400. Here is an excerpt from the code found at the above link: 即使创建一个新项目(我使用MSVC Express 2008)并完全复制代码(我讨厌做),我发现,当代码成功创建一个窗口时,ShowWindow函数仍然报告错误1400.这是摘录自在上面的链接中找到的代码:

int PASCAL
WinMain(HINSTANCE hinst, HINSTANCE, LPSTR, int nShowCmd)
{
 g_hinst = hinst;

 if (SUCCEEDED(CoInitialize(NULL))) {
  InitCommonControls();

  RootWindow *prw = RootWindow::Create();
  if (prw) {
   ShowWindow(prw->GetHWND(), nShowCmd);
   int error = GetLastError(); //Line added by me, error gets set to 1400.
   MSG msg;
       while (GetMessage(&msg, NULL, 0, 0)) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
   }
  }
  CoUninitialize();
 }
 return 0;
}

(The full code can be found at the above link) (完整代码可以在上面的链接中找到)

If anyone has any ideas on how to have the window handle as a member variable of a class without receiving error 1400 on ShowWindow, I would greatly appreciate some help. 如果有人对如何将窗口句柄作为类的成员变量有任何想法而没有在ShowWindow上收到错误1400,我将非常感谢一些帮助。

   ShowWindow(prw->GetHWND(), nShowCmd);
   int error = GetLastError();

This is not correct code. 这不是正确的代码。 The only time it is valid to call GetLastError() is when a winapi function failed . 调用GetLastError()的唯一时间是winapi函数失败 If you use GetLastError() when they didn't fail then you'll get a completely random number. 如果你在没有失败时使用GetLastError(),那么你将获得一个完全随机的数字。 ShowWindow() is a bit special in that it doesn't produce an error code at all so using GetLastError() is never correct. ShowWindow()有点特别之处在于它根本不会产生错误代码,因此使用GetLastError() 永远不会正确。

The generic pattern is roughly: 通用模式大致是:

if (!SomeWinapiFunction(...)) {
    int error = GetLastError();
    CrashAndBurn(error);
}

But do check the MSDN documentation to see what return value indicates an error and whether GetLastError() is appropriate. 但请检查MSDN文档以查看返回值指示错误以及GetLastError()是否合适。 It is generally not on GDI functions for example. 例如,它通常不在GDI函数上。 Be sure to correct this in other parts of your code as well. 请务必在代码的其他部分更正此问题。 Getting error handling right is very important when you use the raw api. 使用原始api时,正确处理错误非常重要。 In particular note how your RootWindow::Create() method has no good way to indicate failure to create the window. 特别注意你的RootWindow :: Create()方法没有很好的方法来指示创建窗口失败。 That needs to be fixed. 这需要修复。 Exceptions are of course a very good way to do so. 例外当然是一种非常好的方法。

I had the same problem. 我有同样的问题。 The solution was to move DefWindowProc() from default to the end of WndProc() . 解决方案是将DefWindowProc()默认值移动到WndProc()的末尾。

Before: 之前:

LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
    static HBITMAP hBitMap;
    static int cxSizeBitMap;
    static int cySizeBitMap;
    static int cxClient;
    static int cyClient;
    HDC hdc;
    BITMAP bitMap;
    PAINTSTRUCT ps;
    HDC hMem;
    HINSTANCE      hInstance ;
    switch( message ) 
    {
        case WM_CREATE:
            hInstance = ((LPCREATESTRUCT) lParam)->hInstance ;
            hBitMap = LoadBitmap( hInstance, MAKEINTRESOURCE( IDB_BRICK ) );
            GetObject( hBitMap, sizeof(BITMAP), &bitMap );
            cxSizeBitMap = bitMap.bmWidth;
            cySizeBitMap = bitMap.bmHeight;
            break;
        case WM_SIZE:
          cxClient = LOWORD (lParam) ;
          cyClient = HIWORD (lParam) ;
            break;
        case WM_PAINT:
            hdc = BeginPaint( hWnd, &ps );
            hMem = CreateCompatibleDC( hdc );
            SelectObject( hMem,  hBitMap );
            for (int y = 0 ; y < cyClient ; y += cySizeBitMap)
            for (int x = 0 ; x < cxClient ; x += cxSizeBitMap)
            {
               BitBlt (hdc, x, y, cxSizeBitMap, cySizeBitMap, hMem, 0, 0, SRCCOPY) ;
            }
            DeleteDC( hMem );
            EndPaint( hWnd, &ps );
            break;
        case WM_DESTROY:
            DeleteObject( hBitMap );
            PostQuitMessage( 0 );
            break;
        default:
            // In this cast ShowWindow() will return 1400.
            DefWindowProc(hWnd, message, wParam, lParam);
    }

    return 0;
}

After: 后:

LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
    static HBITMAP hBitMap;
    static int cxSizeBitMap;
    static int cySizeBitMap;
    static int cxClient;
    static int cyClient;
    HDC hdc;
    BITMAP bitMap;
    PAINTSTRUCT ps;
    HDC hMem;
    HINSTANCE      hInstance ;
    switch( message ) 
    {
        case WM_CREATE:
            hInstance = ((LPCREATESTRUCT) lParam)->hInstance ;
            hBitMap = LoadBitmap( hInstance, MAKEINTRESOURCE( IDB_BRICK ) );
            GetObject( hBitMap, sizeof(BITMAP), &bitMap );
            cxSizeBitMap = bitMap.bmWidth;
            cySizeBitMap = bitMap.bmHeight;
            break;
        case WM_SIZE:
          cxClient = LOWORD (lParam) ;
          cyClient = HIWORD (lParam) ;
            break;

        case WM_PAINT:
            hdc = BeginPaint( hWnd, &ps );
            hMem = CreateCompatibleDC( hdc );

            // Было SelectObject( hdc,  hMem );
            SelectObject( hMem,  hBitMap );
            // Было BitBlt( hdc, 0, 0, cxSize, cySize, hMem, 0, 0, DIB_RGB_COLORS);
            for (int y = 0 ; y < cyClient ; y += cySizeBitMap)
            for (int x = 0 ; x < cxClient ; x += cxSizeBitMap)
            {
               BitBlt (hdc, x, y, cxSizeBitMap, cySizeBitMap, hMem, 0, 0, SRCCOPY) ;
            }


            DeleteDC( hMem );
            EndPaint( hWnd, &ps );
            break;
        case WM_DESTROY:
            DeleteObject( hBitMap );
            PostQuitMessage( 0 );
            break;
    }

    // In this case ShowWindow() will show the window.
    return DefWindowProc(hWnd, message, wParam, lParam);;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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