Wstring в LPARAM и WPARAM

Мне нужно заполнить элементы структуры:

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); 

Но я понятия не имею, поможет ли это мне.

Спасибо за любой вклад или помощь!!

Строковые указатели lParam и wParam действительны только до тех пор, пока действителен wsBookmark; вам нужно проверить, оправдано ли это.

J.R. 08.04.2019 02:32

Да, я это проверил. wsBookmark действителен.

tmighty 08.04.2019 02:44

Это не обязательно должны быть строковые данные или указатели. См. SPEI_TTS_BOOKMARK отсюда для документации docs.microsoft.com/en-us/previous-versions/windows/desktop/… Дополнительные документы: docs.microsoft.com/en-us/previous-versions/windows/desktop/…

Richard Critten 08.04.2019 03:05
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
664
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Структура SPEVENT — это задокументировано в MSDN.

В вашем случае документация для флага SPET_LPARAM_IS_STRING гласит:

SPET_LPARAM_IS_STRING
The SPEVENT.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 the lParam type is SPET_LPARAM_IS_STRING. The user must call CoTaskMemFree on the lParam 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 be SPET_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 нужно просто переключить. Тогда это работает фантастически. Спасибо большое, сам бы до этого не додумался!

tmighty 08.04.2019 03:12

@tmighty Я исправил ошибку в своем ответе. И да, выделенную память нужно освободить, но в этом случае CSpEvent деструктор сделает это за вас.

Remy Lebeau 08.04.2019 08:13

Другие вопросы по теме