tmighty
tmighty

Reputation: 11399

wstring to LPARAM and WPARAM

I need to populate the members of a struct:

typedef struct SPEVENT
{
    SPEVENTENUM        eEventId : 16;
    SPEVENTLPARAMTYPE  elParamType : 16;
    ULONG       ulStreamNum;
    ULONGLONG   ullAudioStreamOffset;
    WPARAM      wParam;
    LPARAM      lParam;
} SPEVENT;

The information on how to use this is sparse. The only examples for populating it are from other users, but nothing official.

The app receiving this event should get the string. With my approach, it doesn't work: The string is "".

Can anybody tell me if he spots anything obvious wrong in my attempt?

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

As I have explained, there doesn't seem to be any official guide on how to populate these members.

What I found so far are these user codes:

https://github.com/m-toman/SALB/blob/master/sapi/htstts.cpp In this link I see this:

CHECKASSERTId(( !wcscmp( (WCHAR*)Event.lParam, szwBMarkStr ) ), tpr, IDS_STRING9); 

But I have no idea if that would help me.

Thank you for any input or help!!

Upvotes: 0

Views: 1298

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 597051

The SPEVENT struct is documented on MSDN.

In your case, the documentation for the SPET_LPARAM_IS_STRING flag says:

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.

Which means the memory pointed to by the lParam MUST by allocated with CoTaskMemAlloc() (or related function), which std::wstring is not, so you cannot just pass the std::wstring::c_str() pointer in the lParam, you must make a copy to a CoTask-allocated memory block.

Also, the SPEI_TTS_BOOKMARK says:

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.

So, with that said, try this instead:

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;

Upvotes: 1

Related Questions