GetWindowLongPtr将错误设置为"类已存在"

chr*_*ris 1 c++ winapi wrapper

在我的Windows API包装器中,我可以选择在出现错误时出现一个消息框.我有一个我不能真正确定的.

这是我的主要功能:

int main()
{
    Window win; //create default window with default class (name changes each new instance)

    return messageLoop(); //the familiar GetMessage() while loop, returns msg.wParam
}
Run Code Online (Sandbox Code Playgroud)

这一切都很好,但当我关闭我的窗口(刚通过X按钮测试)时,我得到以下消息(这是我复制消息框时得到的):

---------------------------
Error
---------------------------
File: "G:\programming\v2\wwbasewindow.h"
Function: _fakeWndProc
Line: 61
Error Code: 1410
Error: Class already exists.


---------------------------
OK   
---------------------------
Run Code Online (Sandbox Code Playgroud)

现在很清楚这个错误来自哪里,但不完全是为什么.这是_fakeWndProc功能.调用该函数后的整个wrap (function, args)语法检查GetLastError().这就是您没有看到错误检查的原因.

LRESULT CALLBACK BaseWindow::_fakeWndProc (msgfillparams) //trick procedure (taken from someone's gui wrapper guide)
{
    BaseWindow * destinationWindowPtr = 0; //for which window message goes to

    //PROBLEM IN THE FOLLOWING LINE (gets a pointer to the window, set when it's created)
    destinationWindowPtr = (BaseWindow *)wrap (GetWindowLongPtr, hwnd, GWLP_USERDATA);

    if (msg == WM_COMMAND && lParam != 0) //if control message, set destination to that window
        destinationWindowPtr = (BaseWindow *)wrap (GetWindowLongPtr, (hwin)lParam, GWLP_USERDATA);

    if (destinationWindowPtr) //check if pointer is valid
        return destinationWindowPtr->_WndProc (hwnd, msg, wParam, lParam); //call window's procedure
    else
        return wrap (DefWindowProc, hwnd, msg, wParam, lParam); //call default procedure
}
Run Code Online (Sandbox Code Playgroud)

我只是想知道为什么这个调用是(试图创建一个类?)除此之外,我尝试从WM_CLOSE消息出现时检查错误代码.我在行之前和之后输出代码.这是出现的:

Before: 0
After: 0
--->Before: 0
--->Before: 1410
After: 1410
Before: 1410
After: 1410
...
Run Code Online (Sandbox Code Playgroud)

这让我感到困惑,因为这意味着函数会调用SendMessage内部的某个地方.但为什么不为其他人做同样的事呢?

错误本身并没有太大的区别,因为程序结束后,但我不希望它闲逛.我怎么处理它?

注:我只是想不打电话PostQuitMessage (0);的时候WM_DESTROY来了,并创造了2个窗口.关闭时他们都给出了同样的错误,所以不一定是程序的结束.

此外,每个人都给出了错误1400(无效的窗口句柄),但只有当我没有打电话时PostQuitMessage.此错误源于对DefWindowProc这些窗口各自窗口过程的调用.关于那个的任何想法吗?

编辑:

根据要求,以下代码为wrap:

// pass along useful error information (useless constants within error function)
#define wrap(...) Wrap (__FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)

// cstr == char *
// con == const
// sdword == int (signed dword)

// version if return value of API function is not void
template<typename TRet, typename... TArgs>
typename std::enable_if<!std::is_void<TRet>::value, TRet>::type
Wrap(con cstr file, const char * const func, con sdword line, TRet(*WINAPI api)(TArgs...), TArgs... args)
{
    TRet result = api(std::forward<TArgs>(args)...); //call API function
    if (GetLastError()) __wwError.set (GetLastError(), file, func, line); //set variables and create message box
    return result; // pass back return value
}

// version if return value is void
template<typename... TArgs>
void Wrap(con cstr file, const char * const func, con sdword line, void(*WINAPI api)(TArgs...), TArgs... args)
{
    api(std::forward<TArgs>(args)...);
    if (GetLastError()) __wwError.set (GetLastError(), file, func, line);
}
Run Code Online (Sandbox Code Playgroud)

我100%肯定这一点并且__wwError.set()工作.用此包装的所有其他函数都会给出相应的消息框.

Dav*_*nan 7

您对GetLastError的调用完全不正确.你不能不加区分地调用GetLastError.您应该只在API调用文档说它有效时才调用它.通常情况下,如果API调用报告失败.

对DefWindowProc的调用很好地说明了这可能会出错.DefWindowProc的文档没有提到函数报告失败的方法.它没有提到调用GetLastError.因此,不应该对GetLastError进行调用,并且返回未定义的,无意义的值.

由于是一个Win32函数来报告故障没有一个共同的机制,你的企图包装所有的Win32 API与一个常见的错误处理程序是注定要失败的调用.

您需要做的是根据自己的优点处理每个API调用,并编写适合该API调用的错误检查.由于您使用的是C++,我建议您在此处使用例外.写一个函数,ThrowLastWin32Error说,只要API函数报告失败就会调用.ThrowLastWin32Error的实现将调用GetLastError,然后在抛出适当的描述性异常之前调用FormatMessage以获取文本描述.你会像这样使用它:

if (!CallSomeWin32Function())
    ThrowLastWin32Error();
Run Code Online (Sandbox Code Playgroud)

但重点是您需要逐个检查函数是否成功,因为不同的Win32函数会以不同的方式报告失败.