Недавно я пытался создать класс окна, используя Windows API в C ++. Однако всякий раз, когда я пытаюсь вызвать ShowWindow, функция устанавливает последнюю ошибку в 1400 (ERROR_INVALID_WINDOW_HANDLE). Попробовав некоторое время, я наткнулся на следующий пример:
http://blogs.msdn.com/b/oldnewthing/archive/2005/04/22/410773.aspx#comments
Даже создав новый проект (я использую 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;
}
(Полный код можно найти по ссылке выше)
Если у кого-то есть идеи о том, как использовать дескриптор окна в качестве переменной-члена класса без получения ошибки 1400 в ShowWindow, я был бы очень признателен за помощь.
ShowWindow(prw->GetHWND(), nShowCmd);
int error = GetLastError();
Это не правильный код. Единственный раз, когда допустимо вызывать GetLastError (), это когда функция winapi не удалось. Если вы используете GetLastError (), когда они не в противном случае вы получите совершенно случайное число. ShowWindow () немного отличается тем, что вообще не генерирует код ошибки, поэтому использование GetLastError () никогда правильный.
Общий шаблон примерно:
if (!SomeWinapiFunction(...)) {
int error = GetLastError();
CrashAndBurn(error);
}
Но проверьте документацию MSDN, чтобы увидеть, какое возвращаемое значение указывает на ошибку и подходит ли GetLastError (). Например, это не относится к функциям GDI. Обязательно исправьте это и в других частях вашего кода. Правильная обработка ошибок очень важно, когда вы используете сырой API. В частности, обратите внимание, что ваш метод RootWindow :: Create () не имеет хорошего способа указать на неудачу при создании окна. Это должно быть исправлено. Исключения, конечно, очень хороший способ сделать это.
У меня такая же проблема. Решение было двигаться DefWindowProc () от дефолт до конца WndProc ().
До:
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;
}
После:
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);;
}