#c #winapi
#c #winapi
Вопрос:
Я относительно новичок в C и пробую Windows Notification с использованием Win32 API.
Это метод, который у меня есть:
BOOL Notification::ShowNotification(std::string title, std::string info) {
NOTIFYICONDATA nid = {
sizeof(nid)
};
nid.uFlags = NIF_INFO | NIF_GUID;
nid.guidItem = __uuidof(AppIcon);
nid.dwInfoFlags = NIIF_USER | NIIF_LARGE_ICON;
std::wstring wtitle = std::wstring(title.begin(), title.end());
const wchar_t * wchar_title = (STRSAFE_LPCWSTR) wtitle.c_str();
StringCchCopy(nid.szInfoTitle, sizeof(nid.szInfoTitle), wchar_title);
std::wstring wInfo = std::wstring(info.begin(), info.end());
const wchar_t * wchar_Info = (STRSAFE_LPCWSTR) wInfo.c_str();
StringCchCopy(nid.szInfo, sizeof(nid.szInfo), wchar_Info);
LoadIconMetric(g_hInst, MAKEINTRESOURCE(IDI_NOTIFICATIONICON), LIM_LARGE, amp; nid.hBalloonIcon);
return Shell_NotifyIcon(NIM_MODIFY, amp; nid);
}
Как вы можете видеть, существует дублирующий код для преобразования string
типа в STRSAFE_LPCWSTR
для переменных title
и info
. Я думал о небольшом служебном методе, который заменил бы дублирующийся код.
Что-то вроде этого:
void Notification::ConvertToLPCWSTR(std::string input, STRSAFE_LPCWSTR amp;result)
{
std::wstring wide_string = std::wstring(input.begin(), input.end());
result = (STRSAFE_LPCWSTR)wide_string.c_str();
}
А затем использовать его из ShowNotification
метода, подобного этому, где wchar_title
передается по ссылке:
STRSAFE_LPCWSTR wchar_title;
ConvertToLPCWSTR(title, wchar_title);
Но это приводит к сбою, потому что wide_string
переменная выделяется стеком и выходит из области видимости, когда ConvertToLPCWSTR
выполнение завершено, из-за чего wchar_title
указывает на освобожденную память.
Кто-нибудь знает хороший способ исправить это?
Комментарии:
1. Почему понижающий голос?
2. Вам не нужны никакие преобразования. Просто исправьте свои интерфейсы, чтобы они принимали правильные строки в кодировке UTF-16 (иначе
std::wstring
с любым заданным компилятором Windows).3.
std::wstring(info.begin(), info.end())
это неправильный способ преобразованияstd::string
вstd::wstring
. Это будет работать только для строк ASCII. В противном случае вам необходимо преобразовать данные, используяMultiByteToWideChar()
,std::wstring_convert
или эквивалент.
Ответ №1:
Вам нужно переместить все три строки повторяющегося кода в небольшую служебную функцию.
static void Notification::ConvertToLPCWSTR(const std::stringamp; input, LPWSTR result, size_t result_max_size) {
std::wstring wInfo = std::wstring(input.begin(), input.end());
const wchar_t * wchar_Info = (STRSAFE_LPCWSTR) wInfo.c_str();
StringCchCopy(result, result_max_size, wchar_Info);
}
И вызвать, как
ConvertToLPCWSTR(info, nid.szInfo, sizeof(nid.szInfo));
Комментарии:
1. Спасибо S.M. Итак, идея заключается в том, чтобы заполнить цель, прежде чем переменная стека выйдет за пределы области видимости, передав саму цель в метод. Я привык в основном работать на C #, где я мог бы просто вернуть преобразованное значение из служебного метода, которое затем будет использоваться вызываемым пользователем.
2.
std::wstring wInfo = std::wstring(input.begin(), input.end())
не делает ничего значимого для любой кодировки символов. За исключением ASCII. И да, это выражение настолько неверно, что требует голосования «против».3. Это преобразование типов данных (
char
вwchar_t
), а не преобразование кодировки.