Poignée de fenêtre non valide ShowWindow

J’ai essayé récemment de créer une classe de fenêtre en utilisant l’API Windows en C ++. Cependant, chaque fois que j’essaie d’appeler ShowWindow, la fonction définit la dernière erreur sur 1400 (ERROR_INVALID_WINDOW_HANDLE). Après avoir essayé pendant un certain temps, je suis tombé sur l’exemple suivant: http://blogs.msdn.com/b/oldnewthing/archive/2005/04/22/410773.aspx#comments

Même en créant un nouveau projet (j’utilise MSVC Express 2008) et en copiant exactement le code (ce que je déteste faire), j’ai découvert que, bien que le code crée une fenêtre, la fonction ShowWindow signalait toujours l’erreur 1400. Voici un extrait de le code trouvé sur le lien ci-dessus:

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; } 

(Le code complet peut être trouvé sur le lien ci-dessus)

Si quelqu’un a des idées sur l’utilisation du handle de fenêtre en tant que variable membre d’une classe sans recevoir l’erreur 1400 sur ShowWindow, j’apprécierais grandement de l’aide.

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

Ce n’est pas le code correct. La seule fois où il est possible d’appeler GetLastError (), c’est quand une fonction winapi a échoué . Si vous utilisez GetLastError () alors qu’elles n’ont pas échoué, vous obtiendrez un nombre totalement aléatoire. ShowWindow () est un peu spécial en ce sens qu’il ne produit aucun code d’erreur. L’utilisation de GetLastError () n’est donc jamais correcte.

Le schéma générique est grosso modo:

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

Mais vérifiez la documentation MSDN pour voir quelle valeur de retour indique une erreur et si GetLastError () est approprié. Ce n’est généralement pas sur les fonctions GDI par exemple. Assurez-vous de corriger cela également dans d’autres parties de votre code. Obtenir une gestion correcte des erreurs est très important lorsque vous utilisez l’api brut. Notez en particulier que votre méthode RootWindow :: Create () n’a pas de moyen efficace pour indiquer l’échec de la création de la fenêtre. Cela doit être corrigé. Les exceptions sont bien sûr un très bon moyen de le faire.

J’ai eu le même problème. La solution consistait à déplacer DefWindowProc () par défaut à la fin de WndProc () .

Avant:

 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; } 

Après:

 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);; }