2013-03-01 2 views
3

Я недавно пытался создать класс окна с помощью Windows API на C++. Однако всякий раз, когда я пытаюсь вызвать ShowWindow, функция устанавливает последнюю ошибку в 1400 (ERROR_INVALID_WINDOW_HANDLE). Попробовав на некоторое время, я наткнулся на следующий пример: http://blogs.msdn.com/b/oldnewthing/archive/2005/04/22/410773.aspx#commentsShowWindow Неверный дескриптор окна

Даже создавая новый проект (я использую MSVC 2008 Express) и скопировать код в точности (который я ненавижу делать), я обнаружил, что, в то время как код успешно создали окно, функция 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, я был бы очень признателен за помощь.

+0

Это может показаться тривиальным, но вы * проверили * возвращаемое значение GetHWND(), чтобы убедиться, что он установлен на действительный дескриптор окна? Т.е. 'if (! :: IsWindow (prw-> GetHWND()) {panic}'? Код, который вы связали (который был честно устарел, когда он был написан, а время не принесло никаких пользы) полагается на обработку WM_NCCREATE, чтобы установите дескриптор окна элемента. Если это не сделано правильно или возникло условие ошибки на вашем пути, ваш дескриптор окна не будет действителен. – WhozCraig

+0

Я попытался добавить код, как было предложено, но IsWindow вернул 1, указав, что дескриптор окна идентифицирует существующее окно [см. функцию microsoft.com: IsWindow()] (http://msdn.microsoft.com/en-us/library/windows/desktop/ms633528%28v=vs.85%29.aspx). – Mmarss

ответ

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

Неправильный код. Единственный раз, когда вы можете позвонить GetLastError(), это когда функция winapi не удалась. Если вы используете GetLastError(), когда они не сделали, то вы получите абсолютно случайное число. ShowWindow() немного отличается тем, что он вообще не создает код ошибки, поэтому использование GetLastError() равно never правильно.

Общий шаблон примерно:

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

Но проверить документацию MSDN, чтобы увидеть, что возвращаемое значение указывает на ошибку и будет ли GetLastError() является целесообразным. Например, это не относится к функциям GDI. Обязательно исправьте это и в других частях вашего кода. Правило правильной обработки ошибок - очень важно, когда вы используете raw api. В частности, обратите внимание на то, как ваш метод RootWindow :: Create() не имеет никакого хорошего способа указывать на неспособность создать окно. Это необходимо исправить. Исключения, конечно, очень хороший способ сделать это.

+0

+1 Очень приятно поймать, Ханс. Я ошибочно предположил, что он уже вывел API, провалился. Никогда не приходил мне в голову, что его «проблема» заключалась в том, что проблем не было. – WhozCraig

+0

Большое спасибо, но знаете ли вы, почему функция, которая завершено успешно сообщит, что ошибка произошла через GetLastError? – Mmarss

+0

Снова, это ** не ** сообщило о какой-либо ошибке. Он вернул TRUE. Вызов GetLastError() при отсутствии ошибки дает произвольное число. Однако это не криптографически безопасное случайное число. –

Смежные вопросы