Fix passing Unicode strings via wxIPC when using DDE

wxIPC API doesn't map well onto DDE, as we don't have wxIPCFormat
parameter in StartAdvise() but do allow specifying the format when
calling Advise() itself, whereas DDE requires specifying the format when
establishing the advise loop and the data always must use this format
later.

Because of this, we have to pass the actual format with the data itself
instead of relying on DDE formats support. This has the advantage of
allowing wxIPC_UTF8TEXT to work, while previously it didn't and
couldn't, as DDE only supports the standard (or custom, but registered)
clipboard formats and it wasn't one of them. Of course, this also has a
disadvantage of having to make another copy of the data, but this seems
unavoidable.

This change allow Advise() overload taking wxString to work, including
for non-ASCII strings, as shown by the update to the IPC sample. It also
makes wxDDEConnection::m_dataType unnecessary, as we must always use the
format passed to DDE callback anyhow when handling XTYP_ADVREQ.

Closes #17900.
This commit is contained in:
Vadim Zeitlin
2018-12-24 01:42:12 +01:00
parent b891fe1974
commit c657fd3d61
4 changed files with 31 additions and 12 deletions

View File

@@ -124,6 +124,10 @@ All (GUI):
- Allow changing tooltip text for button allowing to enter a new string
in wxPGArrayEditorDialog.
wxMSW:
- Fix passing Unicode strings via wxIPC when using DDE.
3.1.2: (released 2018-12-10)
----------------------------

View File

@@ -70,7 +70,6 @@ public:
WXHCONV m_hConv;
const void* m_sendingData;
int m_dataSize;
wxIPCFormat m_dataType;
wxDECLARE_NO_COPY_CLASS(wxDDEConnection);
wxDECLARE_DYNAMIC_CLASS(wxDDEConnection);

View File

@@ -268,7 +268,11 @@ void MyServer::Advise()
{
const wxDateTime now = wxDateTime::Now();
m_connection->Advise(m_connection->m_advise, now.Format());
m_connection->Advise
(
m_connection->m_advise,
wxString::FromUTF8("\xd0\x9f\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82")
);
const wxString s = now.FormatTime() + " " + now.FormatDate();
m_connection->Advise(m_connection->m_advise, s.mb_str(), wxNO_LEN);

View File

@@ -748,12 +748,20 @@ bool wxDDEConnection::DoAdvise(const wxString& item,
size_t size,
wxIPCFormat format)
{
// Unfortunately we currently always use the same CF_TEXT in StartAdvise()
// but allow calling Advise() with different formats. This doesn't map well
// to the DDE API, so the price to pay for it is that we need to send the
// actual format used as part of the data, even if this means making
// another copy of it.
wxCharBuffer buf;
buf.extend(size + 1);
*buf.data() = format;
memcpy(buf.data() + 1, data, size);
HSZ item_atom = DDEGetAtom(item);
HSZ topic_atom = DDEGetAtom(m_topicName);
m_sendingData = data; // mrf: potential for scope problems here?
m_dataSize = size;
// wxIPC_PRIVATE does not succeed, so use text instead
m_dataType = format == wxIPC_PRIVATE ? wxIPC_TEXT : format;
m_sendingData = buf.data();
m_dataSize = size + 1;
bool ok = DdePostAdvise(DDEIdInst, topic_atom, item_atom) != 0;
if ( !ok )
@@ -986,11 +994,12 @@ _DDECallback(UINT wType,
connection->m_dataSize,
0,
hsz2,
connection->m_dataType,
wFmt,
0
);
connection->m_sendingData = NULL;
connection->m_dataSize = 0;
return (DDERETURN)data;
}
@@ -1008,18 +1017,21 @@ _DDECallback(UINT wType,
DWORD len = DdeGetData(hData, NULL, 0, 0);
void *data = connection->GetBufferAtLeast(len);
BYTE* const data = static_cast<BYTE*>(connection->GetBufferAtLeast(len));
wxASSERT_MSG(data != NULL,
wxT("Buffer too small in _DDECallback (XTYP_ADVDATA)") );
DdeGetData(hData, (LPBYTE)data, len, 0);
DdeGetData(hData, data, len, 0);
DdeFreeDataHandle(hData);
// Our code in DoAdvise() prepends the actual format of the
// data as the first byte, extract it back now.
if ( connection->OnAdvise(connection->m_topicName,
item_name,
data,
(int)len,
(wxIPCFormat) wFmt) )
data + 1,
(int)len - 1,
(wxIPCFormat)*data) )
{
return (DDERETURN)(DWORD)DDE_FACK;
}