为什么PrivateFontCollection AddFontFile引发访问冲突异常? 尝试使用以下代码将自定义字体添加到C++ MFC应用程序: void CMFCApplication1View::OnInitialUpdate() { CFormView::OnInitialUpdate(); // ... // dynamic path std::string test = std::string("Oswald.ttf"); std::string path = this->ExePath() + test; std::wstring widestr = std::wstring(path.begin(), path.end()); const wchar_t* widecstr = widestr.c_str(); // hardcoded path std::string s = R"(D:\DEV\C\CTests\MFCApplication1\Debug\Oswald.ttf)"; std::wstring r = std::wstring(s.begin(), s.end()); const wchar_t* t = r.c_str(); Gdiplus::PrivateFontCollection m_fontcollection; Gdiplus::Status nResults = m_fontcollection.AddFontFile(t); // access violation exception thrown here // ... } std::string CMFCApplication1View::ExePath() { char buffer[MAX_PATH]; GetModuleFileNameA(NULL, buffer, MAX_PATH); std::string::size_type pos = std::string(buffer).find_last_of("\\/"); return std::string(buffer).substr(0, pos + 1); } 我是C++的新手(来自C语言)。调用AddFontFile时,代码会引发访问冲突异常,包括硬编码版本和动态版本,但路径的值是正确的
我错过了什么明显的东西吗为什么PrivateFontCollection AddFontFile引发访问冲突异常? 尝试使用以下代码将自定义字体添加到C++ MFC应用程序: void CMFCApplication1View::OnInitialUpdate() { CFormView::OnInitialUpdate(); // ... // dynamic path std::string test = std::string("Oswald.ttf"); std::string path = this->ExePath() + test; std::wstring widestr = std::wstring(path.begin(), path.end()); const wchar_t* widecstr = widestr.c_str(); // hardcoded path std::string s = R"(D:\DEV\C\CTests\MFCApplication1\Debug\Oswald.ttf)"; std::wstring r = std::wstring(s.begin(), s.end()); const wchar_t* t = r.c_str(); Gdiplus::PrivateFontCollection m_fontcollection; Gdiplus::Status nResults = m_fontcollection.AddFontFile(t); // access violation exception thrown here // ... } std::string CMFCApplication1View::ExePath() { char buffer[MAX_PATH]; GetModuleFileNameA(NULL, buffer, MAX_PATH); std::string::size_type pos = std::string(buffer).find_last_of("\\/"); return std::string(buffer).substr(0, pos + 1); } 我是C++的新手(来自C语言)。调用AddFontFile时,代码会引发访问冲突异常,包括硬编码版本和动态版本,但路径的值是正确的,c++,mfc,gdi+,C++,Mfc,Gdi+,我错过了什么明显的东西吗 更新 根据我的评论,这就是我现在所做的。这似乎是工作,并没有更多的转换的东西,但正如我所说,这将需要一段时间,直到我确信我这样做是正确的 void CMFCApplication1View::OnInitialUpdate() { CFormView::OnInitialUpdate(); // ... // font path // const wchar_t* path = (this->ExePath() + std:
更新 根据我的评论,这就是我现在所做的。这似乎是工作,并没有更多的转换的东西,但正如我所说,这将需要一段时间,直到我确信我这样做是正确的
void CMFCApplication1View::OnInitialUpdate()
{
CFormView::OnInitialUpdate();
// ...
// font path
// const wchar_t* path = (this->ExePath() + std::wstring(L"Oswald.ttf")).c_str();
const wchar_t* path = &(this->ExePath() + std::wstring(L"Oswald.ttf"))[0];
// Gdiplus init
ULONG_PTR gdiplusToken;
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
// Gdiplus font
Gdiplus::PrivateFontCollection m_fontcollection;
Gdiplus::Status nResults = m_fontcollection.AddFontFile(path);
// ...
}
std::wstring CMFCApplication1View::ExePath() {
wchar_t buffer[MAX_PATH];
GetModuleFileNameW(NULL, buffer, MAX_PATH);
std::wstring::size_type pos = (std::wstring(buffer)).find_last_of(L"\\/");
return std::wstring(buffer).substr(0, pos + 1);
}
上面使用c_str()或赋值&wstring[0]的转换基于以下答案:
您是否初始化了GDI+?正如Michael Chourdakis所说,我们看不到您在哪里初始化了GDI+。比如:
Gdiplus::GdiplusStartupInput GdiplusStartupInput;ULONG_PTR gdiplusToken;Gdiplus::GdiplusStartup(&gdiplusToken,&gdiplusStartupInput,NULL)
可能不相关,但是隐式的char
towchar\t
强制转换很奇怪。为什么不直接编写std::wstring r=LR“(D:\DEV\C\CTests\mfcapapplication1\Debug\Oswald.ttf)”代码>例如?类似地,在ExePath()
中,您应该调用getModuleFileName
并返回std::wstring
。一致地使用wchar\u t
和wstring
,而不是随机地混淆std::string
和std::wstring
。操作系统在内部只使用Unicode,因此您强制它使用遗留代码在ANSI和Unicode之间进行转换(这可能根本不会成功)!MichaelChourdakis:就是这样。卡斯托里克斯:成功了,谢谢!我不知道这是必需的。如果你们中有人想发布一个带有初始化代码的答案,我会接受的。zett42:因为在我掌握cpp中的字符串/字符操作之前,我需要吸收大量的东西。会尽力做到你说的,谢谢你的评论widestr.c_str()
返回一个不属于自己的指针。确保您了解对象生命周期的后果。尝试将窄字符串转换为宽字符串(std::wstring(s.begin(),s.end())
)时无法转换。它随机丢弃数据。如果您的路径包含非ASCII字符,则看起来很有效,但完全没有乐趣。你将调试这个数小时。要么在整个过程中使用宽字符串,要么执行适当的转换(例如,通过使用MFC/ATL转换宏)。您是否初始化了GDI+?正如Michael Chourdakis所说,我们看不到您在哪里初始化了GDI+。比如:Gdiplus::GdiplusStartupInput GdiplusStartupInput;ULONG_PTR gdiplusToken;Gdiplus::GdiplusStartup(&gdiplusToken,&gdiplusStartupInput,NULL)
可能不相关,但是隐式的char
towchar\t
强制转换很奇怪。为什么不直接编写std::wstring r=LR“(D:\DEV\C\CTests\mfcapapplication1\Debug\Oswald.ttf)”代码>例如?类似地,在ExePath()
中,您应该调用getModuleFileName
并返回std::wstring
。一致地使用wchar\u t
和wstring
,而不是随机地混淆std::string
和std::wstring
。操作系统在内部只使用Unicode,因此您强制它使用遗留代码在ANSI和Unicode之间进行转换(这可能根本不会成功)!MichaelChourdakis:就是这样。卡斯托里克斯:成功了,谢谢!我不知道这是必需的。如果你们中有人想发布一个带有初始化代码的答案,我会接受的。zett42:因为在我掌握cpp中的字符串/字符操作之前,我需要吸收大量的东西。会尽力做到你说的,谢谢你的评论widestr.c_str()
返回一个不属于自己的指针。确保您了解对象生命周期的后果。尝试将窄字符串转换为宽字符串(std::wstring(s.begin(),s.end())
)时无法转换。它随机丢弃数据。如果您的路径包含非ASCII字符,则看起来很有效,但完全没有乐趣。你将调试这个数小时。在整个过程中使用宽字符串,或执行适当的转换(例如,通过使用MFC/ATL转换宏)。