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()工作.用此包装的所有其他函数都会给出相应的消息框.
您对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函数会以不同的方式报告失败.
| 归档时间: |
|
| 查看次数: |
459 次 |
| 最近记录: |