Мне нужно заполнить элементы структуры:
typedef struct SPEVENT
{
SPEVENTENUM eEventId : 16;
SPEVENTLPARAMTYPE elParamType : 16;
ULONG ulStreamNum;
ULONGLONG ullAudioStreamOffset;
WPARAM wParam;
LPARAM lParam;
} SPEVENT;
Информация о том, как это использовать, скудна. Единственные примеры для его заполнения — от других пользователей, но ничего официального.
Приложение, получающее это событие, должно получить строку. С моим подходом это не работает: строка "".
Может ли кто-нибудь сказать мне, замечает ли он что-то очевидное неправильное в моей попытке?
wstring wsBookmark = L"MyBookmark";
CSpEvent nBookmarkEvent;
nBookmarkEvent.eEventId = SPEI_TTS_BOOKMARK;
nBookmarkEvent.elParamType = SPET_LPARAM_IS_STRING;
nBookmarkEvent.ullAudioStreamOffset = 0;
nBookmarkEvent.lParam = _wtol(wsBookmark.c_str());
nBookmarkEvent.wParam = (LPARAM)wsBookmark.c_str();
Как я уже объяснял, похоже, не существует официального руководства по заполнению этих членов.
То, что я нашел до сих пор, это эти коды пользователей:
https://github.com/m-toman/SALB/blob/master/sapi/htstts.cpp По этой ссылке я вижу это:
CHECKASSERTId(( !wcscmp( (WCHAR*)Event.lParam, szwBMarkStr ) ), tpr, IDS_STRING9);
Но я понятия не имею, поможет ли это мне.
Спасибо за любой вклад или помощь!!
Да, я это проверил. wsBookmark действителен.
Это не обязательно должны быть строковые данные или указатели. См. SPEI_TTS_BOOKMARK отсюда для документации docs.microsoft.com/en-us/previous-versions/windows/desktop/… Дополнительные документы: docs.microsoft.com/en-us/previous-versions/windows/desktop/…
Структура SPEVENT
— это задокументировано в MSDN.
В вашем случае документация для флага SPET_LPARAM_IS_STRING
гласит:
SPET_LPARAM_IS_STRING
TheSPEVENT.lParam
value represents a pointer to a string. For example, the TTS bookmark event (i.e.,SPEI_TTS_BOOKMARK
) includes a pointer the bookmark name, so thelParam
type isSPET_LPARAM_IS_STRING
. The user must callCoTaskMemFree
on thelParam
member (as pointer) to release the associated memory.
Это означает, что память, на которую указывает lParam
, ДОЛЖНА быть выделена с помощью CoTaskMemAlloc()
(или связанной с ней функции), чего std::wstring
нет, поэтому вы не можете просто передать указатель std::wstring::c_str()
в lParam
, вы должны сделать копию в блок памяти, выделенный CoTask.
Кроме того, SPEI_TTS_BOOKMARK
говорит:
SPEI_TTS_BOOKMARK
The bookmark element is used to insert a bookmark into the output stream. If an application specifies interest in bookmark events, it will receive the bookmark events during synthesis.wParam
is the current bookmark name (in base 10) converted to a long integer. If name of current bookmark is not an integer,wParam
will be zero.lParam
is the bookmark string.elParamType
has to beSPET_LPARAM_IS_STRING
.
Итак, с учетом сказанного, попробуйте это вместо этого:
wstring wsBookmark = L"MyBookmark";
UINT size = (wsBookmark.size() + 1) * sizeof(wchar_t);
wchar_t *ptr = (wchar_t*) CoTaskMemAlloc(size);
CopyMemory(ptr, wsBookmark.c_str(), size);
CSpEvent nBookmarkEvent;
nBookmarkEvent.eEventId = SPEI_TTS_BOOKMARK;
nBookmarkEvent.elParamType = SPET_LPARAM_IS_STRING;
nBookmarkEvent.ullAudioStreamOffset = 0;
nBookmarkEvent.wParam = 0;
nBookmarkEvent.lParam = (LPARAM) ptr;
Большое спасибо! Вы поместили (LPARAM)ptr в wParam, в то время как он должен быть в lParam, поэтому 2 нужно просто переключить. Тогда это работает фантастически. Спасибо большое, сам бы до этого не додумался!
Строковые указатели
lParam
иwParam
действительны только до тех пор, пока действителенwsBookmark
; вам нужно проверить, оправдано ли это.