I have been trying recently to create a window class using the Windows API in C++. However, whenever I attempt to call ShowWindow, the function sets the last error to 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

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:

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(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. If you use GetLastError() when they didn't fail then you'll get a completely random number. ShowWindow() is a bit special in that it doesn't produce an error code at all so using GetLastError() is never correct.

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. It is generally not on GDI functions for example. 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. In particular note how your RootWindow::Create() method has no good way to indicate failure to create the window. 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().

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归因
不隶属于 StackOverflow
scroll top