博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
DirectX11--HR宏关于dxerr库的替代方案
阅读量:4963 次
发布时间:2019-06-12

本文共 4528 字,大约阅读时间需要 15 分钟。

原文:

欢迎加入QQ群: 727623616 可以一起探讨DX11,以及有什么问题也可以在这里汇报。

综述

参考文章:

在龙书11中所使用的HR宏和dxerr库是一个比较实用的错误原因追踪工具。D3D中的某些函数拥有返回值HRESULT,通过dxerr库,可以将错误码转换成错误详细信息的字符串。

在DirectX SDK中,包含了头文件dxerr.h和库文件dxerr.lib,在以往的做法包含了DX SDK后,就可以直接使用dxerr了。但如果是要编写基于Windows SDK的Direct3D程序,在Windows SDK 8.0以上已经没有了dxerr库。

此时此刻,你仍然有两种选择来脱离对DirectX SDK的依赖:

  1. 寻找较新的dxerr.hdxerr.cpp源码来编译出dxerr.lib,或者直接加入你的项目当中;
  2. 直接抛弃dxerr

新的dxerr源码

微软已经将dxerr库开源了,下面的链接可以下载,如果不放心的话,你也可以到上面的参考文章去下载。

在我以往的DirectX11项目中,则是从DXUT中拉过来的dxerr

但要注意的是,由于新的dxerr.h仅提供了DXTrace的Unicode字符集版本,需要将原来的__FILE__替换为__FILEW__,并在项目属性页中将字符集设置为Unicode

1172605-20181222222206381-1198412375.png

抛弃dxerr库

自Windows SDK 8.0起,HRESULT值关于DirectX图形API的错误消息字符串映射已经加入到FormatMessage函数中。我们可以直接脱离对dxerr的依赖,并使用该函数来直接获取错误消息字符串。因此,dxerr库也就没有必要在Windows SDK 8.0以上版本保留了。

FormatMessageW函数--获取格式化消息字符串

鉴于我们只是要获取错误码对应的字符串信息,这里就简单提及一下该函数的部分用法:

DWORD FormatMessageW(  DWORD   dwFlags,          // [In]FORMAT_MESSAGE系列宏  LPCVOID lpSource,         // [In]直接填NULL  DWORD   dwMessageId,      // [In]传入函数异常时返回的HRESULT  DWORD   dwLanguageId,     // [In]语言ID  LPTSTR  lpBuffer,         // [In]用于输出消息字符串的缓冲区  DWORD   nSize,            // [In]WCHAR缓冲区可容纳元素个数  va_list *Arguments        // [In]直接填NULL);

DXTraceW函数

这里我将dxerrDXTraceW函数的实现进行了修改,由于现在错误码信息为中文,为此也顺便把错误窗口和输出也汉化了。只需要包含Windows.hsal.h就可以使用。

函数原型:

// ------------------------------// DXTraceW函数// ------------------------------// 在调试输出窗口中输出格式化错误信息,可选的错误窗口弹出(已汉化)// [In]strFile          当前文件名,通常传递宏__FILEW__// [In]hlslFileName     当前行号,通常传递宏__LINE__// [In]hr               函数执行出现问题时返回的HRESULT值// [In]strMsg           用于帮助调试定位的字符串,通常传递L#x(可能为NULL)// [In]bPopMsgBox       如果为TRUE,则弹出一个消息弹窗告知错误信息// 返回值: 形参hrHRESULT WINAPI DXTraceW(_In_z_ const WCHAR* strFile, _In_ DWORD dwLine, _In_ HRESULT hr, _In_opt_ const WCHAR* strMsg, _In_ bool bPopMsgBox);

函数实现:

HRESULT WINAPI DXTraceW(_In_z_ const WCHAR* strFile, _In_ DWORD dwLine, _In_ HRESULT hr,    _In_opt_ const WCHAR* strMsg, _In_ bool bPopMsgBox){    WCHAR strBufferFile[MAX_PATH];    WCHAR strBufferLine[128];    WCHAR strBufferError[300];    WCHAR strBufferMsg[1024];    WCHAR strBufferHR[40];    WCHAR strBuffer[3000];    swprintf_s(strBufferLine, 128, L"%lu", dwLine);    if (strFile)    {        swprintf_s(strBuffer, 3000, L"%ls(%ls): ", strFile, strBufferLine);        OutputDebugStringW(strBuffer);    }    size_t nMsgLen = (strMsg) ? wcsnlen_s(strMsg, 1024) : 0;    if (nMsgLen > 0)    {        OutputDebugStringW(strMsg);        OutputDebugStringW(L" ");    }    // Windows SDK 8.0起DirectX的错误信息已经集成进错误码中,可以通过FormatMessageW获取错误信息字符串    // 不需要分配字符串内存    FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,        nullptr, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),        strBufferError, 256, nullptr);    WCHAR* errorStr = wcsrchr(strBufferError, L'\r');       if (errorStr)    {        errorStr[0] = L'\0';    // 擦除FormatMessageW带来的换行符(把\r\n的\r置换为\0即可)    }    swprintf_s(strBufferHR, 40, L" (0x%0.8x)", hr);    wcscat_s(strBufferError, strBufferHR);    swprintf_s(strBuffer, 3000, L"错误码含义:%ls", strBufferError);    OutputDebugStringW(strBuffer);    OutputDebugStringW(L"\n");    if (bPopMsgBox)    {        wcscpy_s(strBufferFile, MAX_PATH, L"");        if (strFile)            wcscpy_s(strBufferFile, MAX_PATH, strFile);        wcscpy_s(strBufferMsg, 1024, L"");        if (nMsgLen > 0)            swprintf_s(strBufferMsg, 1024, L"当前调用:%ls\n", strMsg);        swprintf_s(strBuffer, 3000, L"文件名:%ls\n行号:%ls\n错误码含义:%ls\n%ls您需要调试当前应用程序吗?",            strBufferFile, strBufferLine, strBufferError, strBufferMsg);        int nResult = MessageBoxW(GetForegroundWindow(), strBuffer, L"错误", MB_YESNO | MB_ICONERROR);        if (nResult == IDYES)            DebugBreak();    }    return hr;}

HR宏

现在的HR宏变成了这样:

// ------------------------------// HR宏// ------------------------------// Debug模式下的错误提醒与追踪#if defined(DEBUG) | defined(_DEBUG)    #ifndef HR    #define HR(x)                                               \    {                                                           \        HRESULT hr = (x);                                       \        if(FAILED(hr))                                          \        {                                                       \            DXTraceW(__FILEW__, (DWORD)__LINE__, hr, L#x, true);\        }                                                       \    }    #endif#else    #ifndef HR    #define HR(x) (x)    #endif #endif

测试效果如下:

1172605-20181224193702338-831563243.png

在调试输出窗口也可以看到:

1172605-20181224194246433-956466849.png

欢迎加入QQ群: 727623616 可以一起探讨DX11,以及有什么问题也可以在这里汇报。

posted on
2019-05-05 10:02 阅读(
...) 评论(
...)

转载于:https://www.cnblogs.com/lonelyxmas/p/10811425.html

你可能感兴趣的文章
MySQL date_format() 函数
查看>>
mysql 时间处理
查看>>
mysql adddate()函数
查看>>
mysql addtime() 函数
查看>>
mysql 根据日期时间查询数据
查看>>
mysql 创建时间字段
查看>>
mysql 生成随机数rand()
查看>>
mysql e的n次幂exp()
查看>>
mysql sin() 函数
查看>>
mysql upper() 函数
查看>>
mysql 子查询
查看>>
mysql 自联结
查看>>
mysql union 组合查询
查看>>
mysql 引擎类型
查看>>
mysql 字段添加以及删除
查看>>
软件的分类
查看>>
软件测试
查看>>
软件测试的目的
查看>>
阿里短信发送验证码
查看>>
perl读取excel
查看>>