【问题标题】:Getting Desktop Resolution in MFC C++在 MFC C++ 中获取桌面分辨率
【发布时间】:2015-04-28 17:30:16
【问题描述】:

我继承了一些用 MFC C++ 编写的部分开发了 10 年的代码。我的任务是更新和完成应用程序。

在 CDialogChild 类中,它在 .h 文件中如下所示:

private:
static const int m_iDefaultDesktopSizeX = 1024;

static const int m_iDefaultDesktopSizeY = 740;

我仍在尝试找出代码及其背后的逻辑,但我决定动态获取解决方案。我从 .h 中删除了“静态”关键字以及幻数,然后尝试在构造函数的初始化列表中定义它们:

CDialogChild::CDialogChild(CWnd* pParent /*=NULL*/)
: CDialog(CDialogChild::IDD, pParent) , //more variables,
m_iDefaultDesktopSizeX(GetSystemMetrics(SM_CXSCREEN)), m_iDefaultDesktopSizeY(GetSystemMetrics(SM_CYSCREEN))
{
//...
}

我的分辨率是 1366x768,我在 Visual Studio 2013 调试器中得到的数字各不相同,从“无法访问内存”到数百万的数字。

然后我决定尝试在构造函数中初始化它们,而不是在初始化列表中。我从两个变量中删除了标题中的“const”关键字,然后想我会打印到调试输出它们的值。这是我的代码(我知道它不是那么优雅,但仍在搞清楚 MFC 约定):

#ifdef UNICODE
typedef std::wstringstream tstringstream;
#else
typedef std::stringstream tstringstream;
#endif

m_iDefaultDesktopSizeX = GetSystemMetrics(SM_CXSCREEN);
m_iDefaultDesktopSizeY = GetSystemMetrics(SM_CYSCREEN);    

#ifdef OUTPUT_DEBUG_STRING
    tstringstream ss1;
    tstringstream ss2;

    ss1 << m_iDefaultDesktopSizeX;
    //stream >> sizeX;

    ss2 << m_iDefaultDesktopSizeY;

    LPTSTR dest = _T("m_iDefaultDesktopSizeX = ");
    LPTSTR src1 = _T("");
    LPTSTR src2 = _T("");

    ss1 >> src1;
    ss2 >> src2;

    // 1000 is a magic number
    StringCchCat(dest, 1000, src1);
    StringCchCat(dest, 1000, _T(" and m_iDefaultDesktopSizeY = "));
    StringCchCat(dest, 1000, src2);
    OutputDebugString(dest);
#endif

当我运行它时,在“ss2 >> src2”上抛出一个异常,说访问冲突写入[十六进制地址]

那么,发生了什么事,我应该提供哪些更多信息?我遇到的问题是在对另一个问题进行故障排除时,因此可以提供其中一个或两个方面的帮助会很棒!

编辑

感谢 Mark 的评论,我将所有 LPTSTR 变量的初始化更改为“new TCHAR()”,从而解决了该特定问题。我能够在调试输出中运行字符串,它显示了正确的分辨率(即使它在 VS 调试器本身中是错误的),非常感谢!即使我将变量放回构造函数初始化列表并再次将它们设为“const”,这仍然有效:)

但是,我现在收到一个新错误。虽然这最终不是在这个#ifdef 块中发生的问题,但我现在得到的错误可能会在我编写的其他代码中弹出。

代码:

tstringstream ss1;
tstringstream ss2;

ss1 << m_iDefaultDesktopSizeX;
//stream >> sizeX;

ss2 << m_iDefaultDesktopSizeY;

LPTSTR dest = new TCHAR();
StringCchCat(dest, 300, _T("\nm_iDefaultDesktopSizeX = "));
LPTSTR src1 = new TCHAR();
LPTSTR src2 = new TCHAR();

ss1 >> src1;
ss2 >> src2;


StringCchCat(dest, 300, src1);
StringCchCat(dest, 300, _T(" and m_iDefaultDesktopSizeY = "));
StringCchCat(dest, 300, src2);
OutputDebugString(dest);

//error happens on the line below this one!!!!
delete dest;
dest = 0;
delete  src1;
src1 = 0;
delete  src2;
src2 = 0;

运行时到达删除命令时发生错误,并且.exe​​文件已触发断点。

【问题讨论】:

  • 您的ss2 &gt;&gt; src2 正在尝试写入零长度的只读字符串文字;您需要一个字符缓冲区。而且您可能正在运行发布版本,因此调试器会为您提供虚假值。附言我会改用SystemParametersInfoSPI_GETWORKAREA
  • 非常感谢。我将 src1、src2 和 dest 变量的初始化更改为使用“new TCHAR()”,它确实修复了访问冲突错误。我正在运行调试版本,该产品从未发布(它被搁置)。感谢您提及,我检查了。我会调查 SystemParametersInfo,谢谢马克!
  • 您的第一个解决方案对我来说似乎没问题,并且在这里完美运行。问题出在您的调试代码中。
  • 迈克尔,你能详细说明一下吗?
  • 我做了更多的搜索。原来,它处于发布模式!我通过配置管理器将其切换回调试模式,现在调试器像老板一样工作。非常感谢!

标签: c++ mfc stringstream getsystemmetrics


【解决方案1】:

该错误很可能是由代码中的缓冲区溢出引起的,例如:

LPTSTR dest = new TCHAR();
StringCchCat(dest, 300, _T("\nm_iDefaultDesktopSizeX = "));

第一行分配一个字符,然后在第二行写大约 20-30 个字符。

不要使用原始字符串指针,只需使用 CString 或 std::wstring:

tstringstream ss1;
tstringstream ss2;

ss1 << m_iDefaultDesktopSizeX;
ss2 << m_iDefaultDesktopSizeY;

CString dest = _T("\nm_iDefaultDesktopSizeX = ");
dest += ss1.str().c_str();
dest += _T(" and m_iDefaultDesktopSizeY = ");
dest += ss2.str().c_str();

OutputDebugString(dest);

【讨论】:

  • 这听起来很有希望。如前所述,虽然我熟悉常规 C++,但我对 MFC 不太熟悉。 MFC 是否无缝地将 CString 隐式转换为 LPTSTR(例如 OutputDebugString() 需要 LPCTSTR)?
  • 谢谢!而且您需要将其从 std::string 更改为 c_string,因为 MFC 无法将其转换为 TCHAR* 或 CString?
  • 我不确定你所说的 c_string 是什么意思。你是说CString?您可以在大多数地方使用 CString 或 std::wstring (尽管最好不要使用 std::string ,因为它适用于 ANSI 字符串),尽管使用 std::wstring 您需要调用 std::wstring::c_str 方法转换为LPCTSTR。
  • 对不起,我应该更清楚。我的意思是 c_str() 方法感谢您的快速响应!
  • 您的解决方案完美运行!谢谢,进一步的开发应该没有那么痛苦。真的很感激:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多