1. small fix in wxDirDialog: SHBrowseForFolder() doesn't like '/'s

2. streamlined DDE code (better error handling, range checking)
3. hack in wxExecute to allow launching DDE servers
4. changed wxTreeCtrl::m_filename scope from private to protected
5. corrected creating wxBitmaps from XBMs
6. wxListCtrl no longer sends bogus ACTIVATED events


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@5488 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2000-01-18 01:22:56 +00:00
parent 052e12db71
commit 5bd3a2da95
11 changed files with 944 additions and 583 deletions

View File

@@ -155,7 +155,7 @@ public:
bool Modified() const { return IsModified(); } bool Modified() const { return IsModified(); }
#endif #endif
private: protected:
// the name of the last file loaded with LoadFile() which will be used by // the name of the last file loaded with LoadFile() which will be used by
// SaveFile() by default // SaveFile() by default
wxString m_filename; wxString m_filename;

View File

@@ -758,13 +758,15 @@ wxString wxFileTypeImpl::GetCommand(const wxChar *verb) const
return wxEmptyString; return wxEmptyString;
} }
strKey << wxT("\\shell\\") << verb << wxT("\\command"); strKey << wxT("\\shell\\") << verb;
wxRegKey key(wxRegKey::HKCR, strKey); wxRegKey key(wxRegKey::HKCR, strKey + _T("\\command"));
wxString command; wxString command;
if ( key.Open() ) { if ( key.Open() ) {
// it's the default value of the key // it's the default value of the key
if ( key.QueryValue(wxT(""), command) ) { if ( key.QueryValue(wxT(""), command) ) {
// transform it from '%1' to '%s' style format string // transform it from '%1' to '%s' style format string (now also
// test for %L - apparently MS started using it as well for the
// same purpose)
// NB: we don't make any attempt to verify that the string is valid, // NB: we don't make any attempt to verify that the string is valid,
// i.e. doesn't contain %2, or second %1 or .... But we do make // i.e. doesn't contain %2, or second %1 or .... But we do make
@@ -773,7 +775,9 @@ wxString wxFileTypeImpl::GetCommand(const wxChar *verb) const
size_t len = command.Len(); size_t len = command.Len();
for ( size_t n = 0; (n < len) && !foundFilename; n++ ) { for ( size_t n = 0; (n < len) && !foundFilename; n++ ) {
if ( command[n] == wxT('%') && if ( command[n] == wxT('%') &&
(n + 1 < len) && command[n + 1] == wxT('1') ) { (n + 1 < len) &&
(command[n + 1] == wxT('1') ||
command[n + 1] == wxT('L')) ) {
// replace it with '%s' // replace it with '%s'
command[n + 1] = wxT('s'); command[n + 1] = wxT('s');
@@ -781,8 +785,33 @@ wxString wxFileTypeImpl::GetCommand(const wxChar *verb) const
} }
} }
if ( !foundFilename ) { // look whether we must issue some DDE requests to the application
// we didn't find any '%1'! // (and not just launch it)
strKey += _T("\\DDEExec");
wxRegKey keyDDE(wxRegKey::HKCR, strKey);
if ( keyDDE.Open() ) {
wxString ddeCommand, ddeServer, ddeTopic;
keyDDE.QueryValue(_T(""), ddeCommand);
ddeCommand.Replace(_T("%1"), _T("%s"));
wxRegKey(wxRegKey::HKCR, strKey + _T("\\Application")).
QueryValue(_T(""), ddeServer);
wxRegKey(wxRegKey::HKCR, strKey + _T("\\Topic")).
QueryValue(_T(""), ddeTopic);
// HACK: we use a special feature of wxExecute which exists
// just because we need it here: it will establish DDE
// conversation with the program it just launched
command.Prepend(_T("WX_DDE#"));
command << _T('#') << ddeServer
<< _T('#') << ddeTopic
<< _T('#') << ddeCommand;
}
else if ( !foundFilename ) {
// we didn't find any '%1' - the application doesn't know which
// file to open (note that we only do it if there is no DDEExec
// subkey)
//
// HACK: append the filename at the end, hope that it will do // HACK: append the filename at the end, hope that it will do
command << wxT(" %s"); command << wxT(" %s");
} }
@@ -1779,7 +1808,8 @@ wxMimeTypesManagerImpl::wxMimeTypesManagerImpl()
}; };
// first read the system wide file(s) // first read the system wide file(s)
for ( size_t n = 0; n < WXSIZEOF(aStandardLocations); n++ ) { size_t n;
for ( n = 0; n < WXSIZEOF(aStandardLocations); n++ ) {
wxString dir = aStandardLocations[n]; wxString dir = aStandardLocations[n];
wxString file = dir + wxT("/mailcap"); wxString file = dir + wxT("/mailcap");
@@ -1810,7 +1840,7 @@ wxMimeTypesManagerImpl::wxMimeTypesManagerImpl()
// read KDE/GNOME tables // read KDE/GNOME tables
ArrayIconHandlers& handlers = GetIconHandlers(); ArrayIconHandlers& handlers = GetIconHandlers();
size_t count = handlers.GetCount(); size_t count = handlers.GetCount();
for ( size_t n = 0; n < count; n++ ) for ( n = 0; n < count; n++ )
handlers[n]->GetMimeInfoRecords(this); handlers[n]->GetMimeInfoRecords(this);
} }

View File

@@ -1627,7 +1627,7 @@ static void gtk_window_hscroll_change_callback( GtkWidget *WXUNUSED(widget), wxW
static gint gtk_scrollbar_button_press_callback( GtkRange *WXUNUSED(widget), static gint gtk_scrollbar_button_press_callback( GtkRange *WXUNUSED(widget),
GdkEventButton *WXUNUSED(gdk_event), GdkEventButton *WXUNUSED(gdk_event),
wxWindow *win ) wxWindow *WXUNUSED(win))
{ {
DEBUG_MAIN_THREAD DEBUG_MAIN_THREAD
@@ -1650,7 +1650,7 @@ static gint gtk_scrollbar_button_press_callback( GtkRange *WXUNUSED(widget),
static gint gtk_scrollbar_button_release_callback( GtkRange *WXUNUSED(widget), static gint gtk_scrollbar_button_release_callback( GtkRange *WXUNUSED(widget),
GdkEventButton *WXUNUSED(gdk_event), GdkEventButton *WXUNUSED(gdk_event),
wxWindow *win ) wxWindow *WXUNUSED(win))
{ {
DEBUG_MAIN_THREAD DEBUG_MAIN_THREAD

View File

@@ -1627,7 +1627,7 @@ static void gtk_window_hscroll_change_callback( GtkWidget *WXUNUSED(widget), wxW
static gint gtk_scrollbar_button_press_callback( GtkRange *WXUNUSED(widget), static gint gtk_scrollbar_button_press_callback( GtkRange *WXUNUSED(widget),
GdkEventButton *WXUNUSED(gdk_event), GdkEventButton *WXUNUSED(gdk_event),
wxWindow *win ) wxWindow *WXUNUSED(win))
{ {
DEBUG_MAIN_THREAD DEBUG_MAIN_THREAD
@@ -1650,7 +1650,7 @@ static gint gtk_scrollbar_button_press_callback( GtkRange *WXUNUSED(widget),
static gint gtk_scrollbar_button_release_callback( GtkRange *WXUNUSED(widget), static gint gtk_scrollbar_button_release_callback( GtkRange *WXUNUSED(widget),
GdkEventButton *WXUNUSED(gdk_event), GdkEventButton *WXUNUSED(gdk_event),
wxWindow *win ) wxWindow *WXUNUSED(win))
{ {
DEBUG_MAIN_THREAD DEBUG_MAIN_THREAD

View File

@@ -227,25 +227,63 @@ wxBitmap::~wxBitmap()
wxTheBitmapList->DeleteObject(this); wxTheBitmapList->DeleteObject(this);
} }
wxBitmap::wxBitmap(const char bits[], int the_width, int the_height, int no_bits) wxBitmap::wxBitmap(const char bits[], int width, int height, int depth)
{ {
Init(); Init();
wxBitmapRefData *refData = new wxBitmapRefData; wxBitmapRefData *refData = new wxBitmapRefData;
m_refData = refData; m_refData = refData;
refData->m_width = the_width; refData->m_width = width;
refData->m_height = the_height; refData->m_height = height;
refData->m_depth = no_bits; refData->m_depth = depth;
refData->m_numColors = 0; refData->m_numColors = 0;
refData->m_selectedInto = NULL; refData->m_selectedInto = NULL;
HBITMAP hbmp = ::CreateBitmap(the_width, the_height, 1, no_bits, bits); char *data;
if ( depth == 1 )
{
// we assume that it is in XBM format which is not quite the same as
// the format CreateBitmap() wants because the order of bytes in the
// line is inversed!
static const size_t bytesPerLine = (width + 7) / 8;
static const size_t padding = bytesPerLine % 2;
static const size_t len = height * ( padding + bytesPerLine );
data = (char *)malloc(len);
const char *src = bits;
char *dst = data;
for ( int rows = 0; rows < height; rows++ )
{
// note that offset cannot be size_t due to >= 0 test!
for ( int offset = bytesPerLine - 1; offset >= 0; offset-- )
{
*dst++ = *(src + offset);
}
if ( padding )
*dst++ = 0;
src += bytesPerLine;
}
}
else
{
// bits should already be in Windows standard format
data = (char *)bits; // const_cast is harmless
}
HBITMAP hbmp = ::CreateBitmap(width, height, 1, depth, data);
if ( !hbmp ) if ( !hbmp )
{ {
wxLogLastError("CreateBitmap"); wxLogLastError("CreateBitmap");
} }
if ( data != bits )
{
free(data);
}
SetHBITMAP((WXHBITMAP)hbmp); SetHBITMAP((WXHBITMAP)hbmp);
} }

View File

@@ -204,10 +204,9 @@ bool wxControl::MSWOnNotify(int idCtrl,
void wxControl::OnEraseBackground(wxEraseEvent& event) void wxControl::OnEraseBackground(wxEraseEvent& event)
{ {
// In general, you don't want to erase the background of a control, // notice that this 'dumb' implementation may cause flicker for some of the
// or you'll get a flicker. // controls in which case they should intercept wxEraseEvent and process it
// TODO: move this 'null' function into each control that // themselves somehow
// might flicker.
RECT rect; RECT rect;
::GetClientRect(GetHwnd(), &rect); ::GetClientRect(GetHwnd(), &rect);

View File

@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// Name: dde.cpp // Name: msw/dde.cpp
// Purpose: DDE classes // Purpose: DDE classes
// Author: Julian Smart // Author: Julian Smart
// Modified by: // Modified by:
@@ -9,6 +9,14 @@
// Licence: wxWindows licence // Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#ifdef __GNUG__ #ifdef __GNUG__
#pragma implementation "dde.h" #pragma implementation "dde.h"
#endif #endif
@@ -20,10 +28,6 @@
#pragma hdrstop #pragma hdrstop
#endif #endif
#ifndef WX_PRECOMP
#include "wx/defs.h"
#endif
#if wxUSE_IPC #if wxUSE_IPC
#ifndef WX_PRECOMP #ifndef WX_PRECOMP
@@ -35,35 +39,45 @@
#include "wx/dde.h" #include "wx/dde.h"
#include "wx/msw/private.h" #include "wx/msw/private.h"
#include <string.h>
#include <windows.h> #include <windows.h>
#include <ddeml.h> #include <ddeml.h>
#ifndef __TWIN32__ #if defined(__TWIN32__) || defined(__GNUWIN32_OLD__)
#if !wxUSE_NORLANDER_HEADERS
#ifdef __GNUWIN32__
#include "wx/msw/gnuwin32/extra.h" #include "wx/msw/gnuwin32/extra.h"
#endif #endif
#endif
#endif
#include <string.h> // ----------------------------------------------------------------------------
// macros and constants
// ----------------------------------------------------------------------------
#ifdef __WIN32__ #ifdef __WIN32__
#define _EXPORT /**/ #define _EXPORT
#else #else
#define _EXPORT _export #define _EXPORT _export
#endif #endif
IMPLEMENT_DYNAMIC_CLASS(wxDDEServer, wxServerBase) #if wxUSE_UNICODE
IMPLEMENT_DYNAMIC_CLASS(wxDDEClient, wxClientBase) #define DDE_CP CP_WINUNICODE
IMPLEMENT_CLASS(wxDDEConnection, wxConnectionBase) #else
#define DDE_CP CP_WINANSI
#endif
#define GetHConv() ((HCONV)m_hConv)
// default timeout for DDE operations (5sec)
#define DDE_TIMEOUT 5000
// ----------------------------------------------------------------------------
// private functions
// ----------------------------------------------------------------------------
static wxDDEConnection *DDEFindConnection(HCONV hConv); static wxDDEConnection *DDEFindConnection(HCONV hConv);
static void DDEDeleteConnection(HCONV hConv); static void DDEDeleteConnection(HCONV hConv);
static wxDDEServer *DDEFindServer(const wxString& s); static wxDDEServer *DDEFindServer(const wxString& s);
extern "C" HDDEDATA EXPENTRY _EXPORT _DDECallback( extern "C" HDDEDATA EXPENTRY _EXPORT _DDECallback(WORD wType,
WORD wType,
WORD wFmt, WORD wFmt,
HCONV hConv, HCONV hConv,
HSZ hsz1, HSZ hsz1,
@@ -75,7 +89,18 @@ DWORD lData2);
// Add topic name to atom table before using in conversations // Add topic name to atom table before using in conversations
static HSZ DDEAddAtom(const wxString& string); static HSZ DDEAddAtom(const wxString& string);
static HSZ DDEGetAtom(const wxString& string); static HSZ DDEGetAtom(const wxString& string);
static void DDEPrintError(void);
// string handles
static HSZ DDEAtomFromString(const wxString& s);
static wxString DDEStringFromAtom(HSZ hsz);
// error handling
static wxString DDEGetErrorMsg(UINT error);
static void DDELogError(const wxString& s, UINT error = DMLERR_NO_ERROR);
// ----------------------------------------------------------------------------
// global variables
// ----------------------------------------------------------------------------
static DWORD DDEIdInst = 0L; static DWORD DDEIdInst = 0L;
static wxDDEConnection *DDECurrentlyConnecting = NULL; static wxDDEConnection *DDECurrentlyConnecting = NULL;
@@ -86,30 +111,61 @@ static wxList wxDDEServerObjects;
char *DDEDefaultIPCBuffer = NULL; char *DDEDefaultIPCBuffer = NULL;
int DDEDefaultIPCBufferSize = 0; int DDEDefaultIPCBufferSize = 0;
/*
* Initialization
*
*/
static bool DDEInitialized = FALSE; static bool DDEInitialized = FALSE;
void wxDDEInitialize() // ----------------------------------------------------------------------------
// private classes
// ----------------------------------------------------------------------------
// A module to allow DDE cleanup without calling these functions
// from app.cpp or from the user's application.
class wxDDEModule : public wxModule
{ {
if (DDEInitialized) public:
return; wxDDEModule() {}
DDEInitialized = TRUE; bool OnInit() { return TRUE; }
void OnExit() { wxDDECleanUp(); }
private:
DECLARE_DYNAMIC_CLASS(wxDDEModule)
};
// ----------------------------------------------------------------------------
// wxWin macros
// ----------------------------------------------------------------------------
IMPLEMENT_DYNAMIC_CLASS(wxDDEServer, wxServerBase)
IMPLEMENT_DYNAMIC_CLASS(wxDDEClient, wxClientBase)
IMPLEMENT_CLASS(wxDDEConnection, wxConnectionBase)
IMPLEMENT_DYNAMIC_CLASS(wxDDEModule, wxModule)
// ============================================================================
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// initialization and cleanup
// ----------------------------------------------------------------------------
extern void wxDDEInitialize()
{
if ( !DDEInitialized )
{
// Should insert filter flags // Should insert filter flags
DdeInitialize(&DDEIdInst, (PFNCALLBACK)MakeProcInstance( PFNCALLBACK callback = (PFNCALLBACK)
(FARPROC)_DDECallback, wxGetInstance()), MakeProcInstance((FARPROC)_DDECallback, wxGetInstance());
APPCLASS_STANDARD, UINT rc = DdeInitialize(&DDEIdInst, callback, APPCLASS_STANDARD, 0L);
0L); if ( rc != DMLERR_NO_ERROR )
{
DDELogError(_T("Failed to initialize DDE"), rc);
}
else
{
DDEInitialized = TRUE;
}
}
} }
/*
* CleanUp
*/
void wxDDECleanUp() void wxDDECleanUp()
{ {
@@ -118,24 +174,13 @@ void wxDDECleanUp()
DdeUninitialize(DDEIdInst); DdeUninitialize(DDEIdInst);
DDEIdInst = 0; DDEIdInst = 0;
} }
if (DDEDefaultIPCBuffer)
delete [] DDEDefaultIPCBuffer; delete [] DDEDefaultIPCBuffer;
} }
// A module to allow DDE initialization/cleanup // ----------------------------------------------------------------------------
// without calling these functions from app.cpp or from // functions working with the global connection list(s)
// the user's application. // ----------------------------------------------------------------------------
class wxDDEModule: public wxModule
{
DECLARE_DYNAMIC_CLASS(wxDDEModule)
public:
wxDDEModule() {}
bool OnInit() { wxDDEInitialize(); return TRUE; };
void OnExit() { wxDDECleanUp(); };
};
IMPLEMENT_DYNAMIC_CLASS(wxDDEModule, wxModule)
// Global find connection // Global find connection
static wxDDEConnection *DDEFindConnection(HCONV hConv) static wxDDEConnection *DDEFindConnection(HCONV hConv)
@@ -200,40 +245,44 @@ static wxDDEServer *DDEFindServer(const wxString& s)
return found; return found;
} }
/* // ----------------------------------------------------------------------------
* Server // wxDDEServer
* // ----------------------------------------------------------------------------
*/
wxDDEServer::wxDDEServer(void) wxDDEServer::wxDDEServer()
{ {
m_serviceName = ""; wxDDEInitialize();
wxDDEServerObjects.Append(this); wxDDEServerObjects.Append(this);
} }
bool wxDDEServer::Create(const wxString& server_name) bool wxDDEServer::Create(const wxString& server)
{ {
m_serviceName = server_name; m_serviceName = server;
HSZ serviceName = DdeCreateStringHandle(DDEIdInst, WXSTRINGCAST server_name, CP_WINANSI);
if (DdeNameService(DDEIdInst, serviceName, (HSZ) NULL, DNS_REGISTER) == 0) if ( !DdeNameService(DDEIdInst, DDEAtomFromString(server), (HSZ)NULL, DNS_REGISTER) )
{ {
DDEPrintError(); DDELogError(wxString::Format(_("Failed to register DDE server '%s'"),
server.c_str()));
return FALSE; return FALSE;
} }
return TRUE; return TRUE;
} }
wxDDEServer::~wxDDEServer(void) wxDDEServer::~wxDDEServer()
{ {
if (m_serviceName != wxT("")) if ( !!m_serviceName )
{ {
HSZ serviceName = DdeCreateStringHandle(DDEIdInst, WXSTRINGCAST m_serviceName, CP_WINANSI); if ( !DdeNameService(DDEIdInst, DDEAtomFromString(m_serviceName),
if (DdeNameService(DDEIdInst, serviceName, NULL, DNS_UNREGISTER) == 0) (HSZ)NULL, DNS_UNREGISTER) )
{ {
DDEPrintError(); DDELogError(wxString::Format(_("Failed to unregister DDE server '%s'"),
m_serviceName.c_str()));
} }
} }
wxDDEServerObjects.DeleteObject(this); wxDDEServerObjects.DeleteObject(this);
wxNode *node = m_connections.First(); wxNode *node = m_connections.First();
@@ -293,19 +342,18 @@ bool wxDDEServer::DeleteConnection(WXHCONV conv)
return found; return found;
} }
// ----------------------------------------------------------------------------
// wxDDEClient
// ----------------------------------------------------------------------------
/* wxDDEClient::wxDDEClient()
* Client
*
*/
wxDDEClient::wxDDEClient(void)
{ {
wxDDEInitialize();
wxDDEClientObjects.Append(this); wxDDEClientObjects.Append(this);
} }
wxDDEClient::~wxDDEClient(void) wxDDEClient::~wxDDEClient()
{ {
wxDDEClientObjects.DeleteObject(this); wxDDEClientObjects.DeleteObject(this);
wxNode *node = m_connections.First(); wxNode *node = m_connections.First();
@@ -322,14 +370,18 @@ bool wxDDEClient::ValidHost(const wxString& /* host */)
return TRUE; return TRUE;
} }
wxConnectionBase *wxDDEClient::MakeConnection(const wxString& /* host */, const wxString& server_name, const wxString& topic) wxConnectionBase *wxDDEClient::MakeConnection(const wxString& WXUNUSED(host),
const wxString& server,
const wxString& topic)
{ {
HSZ serviceName = DdeCreateStringHandle(DDEIdInst, WXSTRINGCAST server_name, CP_WINANSI); HCONV hConv = DdeConnect(DDEIdInst, DDEAtomFromString(server), DDEAtomFromString(topic),
HSZ topic_atom = DdeCreateStringHandle(DDEIdInst, WXSTRINGCAST topic, CP_WINANSI); (PCONVCONTEXT)NULL);
if ( !hConv )
HCONV hConv = DdeConnect(DDEIdInst, serviceName, topic_atom, (PCONVCONTEXT)NULL); {
if (hConv == (HCONV) NULL) DDELogError(wxString::Format(_("Failed to create connection to "
return (wxConnectionBase*) NULL; "server '%s' on topic '%s'"),
server.c_str(), topic.c_str()));
}
else else
{ {
wxDDEConnection *connection = (wxDDEConnection*) OnMakeConnection(); wxDDEConnection *connection = (wxDDEConnection*) OnMakeConnection();
@@ -341,11 +393,12 @@ wxConnectionBase *wxDDEClient::MakeConnection(const wxString& /* host */, const
m_connections.Append(connection); m_connections.Append(connection);
return connection; return connection;
} }
else return (wxConnectionBase*) NULL;
}
} }
wxConnectionBase *wxDDEClient::OnMakeConnection(void) return (wxConnectionBase*) NULL;
}
wxConnectionBase *wxDDEClient::OnMakeConnection()
{ {
return new wxDDEConnection; return new wxDDEConnection;
} }
@@ -382,9 +435,9 @@ bool wxDDEClient::DeleteConnection(WXHCONV conv)
return found; return found;
} }
/* // ----------------------------------------------------------------------------
* Connection // wxDDEConnection
*/ // ----------------------------------------------------------------------------
wxDDEConnection::wxDDEConnection(char *buffer, int size) wxDDEConnection::wxDDEConnection(char *buffer, int size)
{ {
@@ -401,8 +454,6 @@ wxDDEConnection::wxDDEConnection(char *buffer, int size)
m_bufSize = size; m_bufSize = size;
} }
m_topicName = "";
m_client = NULL; m_client = NULL;
m_server = NULL; m_server = NULL;
@@ -410,7 +461,7 @@ wxDDEConnection::wxDDEConnection(char *buffer, int size)
m_sendingData = NULL; m_sendingData = NULL;
} }
wxDDEConnection::wxDDEConnection(void) wxDDEConnection::wxDDEConnection()
{ {
m_hConv = 0; m_hConv = 0;
m_sendingData = NULL; m_sendingData = NULL;
@@ -421,10 +472,9 @@ wxDDEConnection::wxDDEConnection(void)
m_bufPtr = DDEDefaultIPCBuffer; m_bufPtr = DDEDefaultIPCBuffer;
m_bufSize = DDEDefaultIPCBufferSize; m_bufSize = DDEDefaultIPCBufferSize;
m_topicName = "";
} }
wxDDEConnection::~wxDDEConnection(void) wxDDEConnection::~wxDDEConnection()
{ {
if (m_server) if (m_server)
m_server->GetConnections().DeleteObject(this); m_server->GetConnections().DeleteObject(this);
@@ -433,22 +483,40 @@ wxDDEConnection::~wxDDEConnection(void)
} }
// Calls that CLIENT can make // Calls that CLIENT can make
bool wxDDEConnection::Disconnect(void) bool wxDDEConnection::Disconnect()
{ {
DDEDeleteConnection((HCONV) m_hConv); DDEDeleteConnection(GetHConv());
return (DdeDisconnect((HCONV) m_hConv) != 0);
bool ok = DdeDisconnect(GetHConv()) != 0;
if ( !ok )
{
DDELogError(_T("Failed to disconnect from DDE server gracefully"));
}
return ok;
} }
bool wxDDEConnection::Execute(const wxChar *data, int size, wxIPCFormat format) bool wxDDEConnection::Execute(const wxChar *data, int size, wxIPCFormat format)
{ {
DWORD result; DWORD result;
if (size < 0) if (size < 0)
size = wxStrlen(data); {
size = wxStrlen(data) + 1;
}
size ++; bool ok = DdeClientTransaction((LPBYTE)data, size,
GetHConv(),
NULL,
format,
XTYP_EXECUTE,
DDE_TIMEOUT,
&result) != 0;
if ( !ok )
{
DDELogError(_T("DDE execute request failed"));
}
return (DdeClientTransaction((LPBYTE)data, size, (HCONV) m_hConv, return ok;
NULL, format, XTYP_EXECUTE, 5000, &result) ? TRUE : FALSE);
} }
char *wxDDEConnection::Request(const wxString& item, int *size, wxIPCFormat format) char *wxDDEConnection::Request(const wxString& item, int *size, wxIPCFormat format)
@@ -456,32 +524,50 @@ char *wxDDEConnection::Request(const wxString& item, int *size, wxIPCFormat form
DWORD result; DWORD result;
HSZ atom = DDEGetAtom(item); HSZ atom = DDEGetAtom(item);
HDDEDATA returned_data = DdeClientTransaction(NULL, 0, (HCONV) m_hConv, HDDEDATA returned_data = DdeClientTransaction(NULL, 0,
atom, format, XTYP_REQUEST, 5000, &result); GetHConv(),
atom, format,
XTYP_REQUEST,
DDE_TIMEOUT,
&result);
if ( !returned_data )
{
DDELogError(_T("DDE data request failed"));
DWORD len = DdeGetData(returned_data, (LPBYTE)(m_bufPtr), m_bufSize, 0); return NULL;
}
DWORD len = DdeGetData(returned_data, (LPBYTE)m_bufPtr, m_bufSize, 0);
DdeFreeDataHandle(returned_data); DdeFreeDataHandle(returned_data);
if (size) *size = (int)len; if (size)
if (len > 0) *size = (int)len;
{
return m_bufPtr; return m_bufPtr;
} }
else return NULL;
}
bool wxDDEConnection::Poke(const wxString& item, wxChar *data, int size, wxIPCFormat format) bool wxDDEConnection::Poke(const wxString& item, wxChar *data, int size, wxIPCFormat format)
{ {
DWORD result; DWORD result;
if (size < 0) if (size < 0)
size = wxStrlen(data); {
size = wxStrlen(data) + 1;
size ++; }
HSZ item_atom = DDEGetAtom(item); HSZ item_atom = DDEGetAtom(item);
return (DdeClientTransaction((LPBYTE)data, size, (HCONV) m_hConv, bool ok = DdeClientTransaction((LPBYTE)data, size,
item_atom, format, XTYP_POKE, 5000, &result) ? TRUE : FALSE); GetHConv(),
item_atom, format,
XTYP_POKE,
DDE_TIMEOUT,
&result) != 0;
if ( !ok )
{
DDELogError(_("DDE poke request failed"));
}
return ok;
} }
bool wxDDEConnection::StartAdvise(const wxString& item) bool wxDDEConnection::StartAdvise(const wxString& item)
@@ -489,8 +575,18 @@ bool wxDDEConnection::StartAdvise(const wxString& item)
DWORD result; DWORD result;
HSZ atom = DDEGetAtom(item); HSZ atom = DDEGetAtom(item);
return (DdeClientTransaction(NULL, 0, (HCONV) m_hConv, bool ok = DdeClientTransaction(NULL, 0,
atom, CF_TEXT, XTYP_ADVSTART, 5000, &result) ? TRUE : FALSE); GetHConv(),
atom, CF_TEXT,
XTYP_ADVSTART,
DDE_TIMEOUT,
&result) != 0;
if ( !ok )
{
DDELogError(_("Failed to establish an advise loop with DDE server"));
}
return ok;
} }
bool wxDDEConnection::StopAdvise(const wxString& item) bool wxDDEConnection::StopAdvise(const wxString& item)
@@ -498,71 +594,89 @@ bool wxDDEConnection::StopAdvise(const wxString& item)
DWORD result; DWORD result;
HSZ atom = DDEGetAtom(item); HSZ atom = DDEGetAtom(item);
return (DdeClientTransaction(NULL, 0, (HCONV) m_hConv, bool ok = DdeClientTransaction(NULL, 0,
atom, CF_TEXT, XTYP_ADVSTOP, 5000, &result) ? TRUE : FALSE); GetHConv(),
atom, CF_TEXT,
XTYP_ADVSTOP,
DDE_TIMEOUT,
&result) != 0;
if ( !ok )
{
DDELogError(_("Failed to terminate the advise loop with DDE server"));
}
return ok;
} }
// Calls that SERVER can make // Calls that SERVER can make
bool wxDDEConnection::Advise(const wxString& item, wxChar *data, int size, wxIPCFormat format) bool wxDDEConnection::Advise(const wxString& item,
wxChar *data,
int size,
wxIPCFormat format)
{ {
if (size < 0) if (size < 0)
size = wxStrlen(data); {
size = wxStrlen(data) + 1;
size ++; }
HSZ item_atom = DDEGetAtom(item); HSZ item_atom = DDEGetAtom(item);
HSZ topic_atom = DDEGetAtom(m_topicName); HSZ topic_atom = DDEGetAtom(m_topicName);
m_sendingData = data; m_sendingData = data;
m_dataSize = size; m_dataSize = size;
m_dataType = format; m_dataType = format;
return (DdePostAdvise(DDEIdInst, topic_atom, item_atom) != 0);
bool ok = DdePostAdvise(DDEIdInst, topic_atom, item_atom) != 0;
if ( !ok )
{
DDELogError(_("Failed to send DDE advise notification"));
} }
bool wxDDEConnection::OnDisconnect(void) return ok;
}
bool wxDDEConnection::OnDisconnect()
{ {
delete this; delete this;
return TRUE; return TRUE;
} }
// ----------------------------------------------------------------------------
// _DDECallback
// ----------------------------------------------------------------------------
#define DDERETURN HDDEDATA #define DDERETURN HDDEDATA
HDDEDATA EXPENTRY _EXPORT _DDECallback( HDDEDATA EXPENTRY _EXPORT
WORD wType, _DDECallback(WORD wType,
WORD wFmt, WORD wFmt,
HCONV hConv, HCONV hConv,
HSZ hsz1, HSZ hsz1,
HSZ hsz2, HSZ hsz2,
HDDEDATA hData, HDDEDATA hData,
DWORD /* lData1 */, DWORD WXUNUSED(lData1),
DWORD /* lData2 */) DWORD WXUNUSED(lData2))
{ {
switch (wType) switch (wType)
{ {
case XTYP_CONNECT: case XTYP_CONNECT:
{ {
wxChar topic_buf[100]; wxString topic = DDEStringFromAtom(hsz1),
wxChar server_buf[100]; srv = DDEStringFromAtom(hsz2);
DdeQueryString(DDEIdInst, hsz1, (LPTSTR)topic_buf, WXSIZEOF(topic_buf), wxDDEServer *server = DDEFindServer(srv);
CP_WINANSI);
DdeQueryString(DDEIdInst, hsz2, (LPTSTR)server_buf, WXSIZEOF(topic_buf),
CP_WINANSI);
wxDDEServer *server = DDEFindServer(server_buf);
if (server) if (server)
{ {
wxDDEConnection *connection = wxDDEConnection *connection =
(wxDDEConnection*) server->OnAcceptConnection(wxString(topic_buf)); (wxDDEConnection*) server->OnAcceptConnection(topic);
if (connection) if (connection)
{ {
connection->m_server = server; connection->m_server = server;
server->GetConnections().Append(connection); server->GetConnections().Append(connection);
connection->m_hConv = 0; connection->m_hConv = 0;
connection->m_topicName = topic_buf; connection->m_topicName = topic;
DDECurrentlyConnecting = connection; DDECurrentlyConnecting = connection;
return (DDERETURN)(DWORD)TRUE; return (DDERETURN)(DWORD)TRUE;
} }
} }
else return (DDERETURN)0;
break; break;
} }
@@ -574,7 +688,6 @@ DWORD /* lData2 */)
DDECurrentlyConnecting = NULL; DDECurrentlyConnecting = NULL;
return (DDERETURN)(DWORD)TRUE; return (DDERETURN)(DWORD)TRUE;
} }
else return 0;
break; break;
} }
@@ -586,7 +699,6 @@ DWORD /* lData2 */)
DDEDeleteConnection(hConv); // Delete mapping: hConv => connection DDEDeleteConnection(hConv); // Delete mapping: hConv => connection
return (DDERETURN)(DWORD)TRUE; return (DDERETURN)(DWORD)TRUE;
} }
else return (DDERETURN)0;
break; break;
} }
@@ -596,14 +708,21 @@ DWORD /* lData2 */)
if (connection) if (connection)
{ {
DWORD len = DdeGetData(hData, (LPBYTE)(connection->m_bufPtr), connection->m_bufSize, 0); DWORD len = DdeGetData(hData,
(LPBYTE)connection->m_bufPtr,
connection->m_bufSize,
0);
DdeFreeDataHandle(hData); DdeFreeDataHandle(hData);
if (connection->OnExecute(connection->m_topicName, connection->m_bufPtr, (int)len, (wxIPCFormat) wFmt)) if ( connection->OnExecute(connection->m_topicName,
connection->m_bufPtr,
(int)len,
(wxIPCFormat) wFmt) )
{
return (DDERETURN)(DWORD)DDE_FACK; return (DDERETURN)(DWORD)DDE_FACK;
else }
}
return (DDERETURN)DDE_FNOTPROCESSED; return (DDERETURN)DDE_FNOTPROCESSED;
} else return (DDERETURN)DDE_FNOTPROCESSED;
break;
} }
case XTYP_REQUEST: case XTYP_REQUEST:
@@ -612,21 +731,28 @@ DWORD /* lData2 */)
if (connection) if (connection)
{ {
wxChar item_name[200]; wxString item_name = DDEStringFromAtom(hsz2);
DdeQueryString(DDEIdInst, hsz2, (LPTSTR)item_name, WXSIZEOF(item_name),
CP_WINANSI);
int user_size = -1; int user_size = -1;
char *data = connection->OnRequest(connection->m_topicName, wxString(item_name), &user_size, (wxIPCFormat) wFmt); char *data = connection->OnRequest(connection->m_topicName,
item_name,
&user_size,
(wxIPCFormat) wFmt);
if (data) if (data)
{ {
if (user_size < 0) user_size = strlen(data); if (user_size < 0)
user_size = wxStrlen(data) + 1;
HDDEDATA handle = DdeCreateDataHandle(DDEIdInst, HDDEDATA handle = DdeCreateDataHandle(DDEIdInst,
(LPBYTE)data, user_size + 1, 0, hsz2, wFmt, 0); (LPBYTE)data,
user_size,
0,
hsz2,
wFmt,
0);
return (DDERETURN)handle; return (DDERETURN)handle;
} else return (DDERETURN)0; }
} else return (DDERETURN)0; }
break; break;
} }
@@ -636,15 +762,26 @@ DWORD /* lData2 */)
if (connection) if (connection)
{ {
wxChar item_name[200]; wxString item_name = DDEStringFromAtom(hsz2);
DdeQueryString(DDEIdInst, hsz2, (LPTSTR)item_name, WXSIZEOF(item_name),
CP_WINANSI); DWORD len = DdeGetData(hData,
DWORD len = DdeGetData(hData, (LPBYTE)(connection->m_bufPtr), connection->m_bufSize, 0); (LPBYTE)connection->m_bufPtr,
connection->m_bufSize,
0);
DdeFreeDataHandle(hData); DdeFreeDataHandle(hData);
connection->OnPoke(connection->m_topicName, wxString(item_name), connection->m_bufPtr, (int)len, (wxIPCFormat) wFmt);
return (DDERETURN)(DWORD)DDE_FACK; connection->OnPoke(connection->m_topicName,
} else return (DDERETURN)DDE_FNOTPROCESSED; item_name,
break; connection->m_bufPtr,
(int)len,
(wxIPCFormat) wFmt);
return (DDERETURN)DDE_FACK;
}
else
{
return (DDERETURN)DDE_FNOTPROCESSED;
}
} }
case XTYP_ADVSTART: case XTYP_ADVSTART:
@@ -653,12 +790,12 @@ DWORD /* lData2 */)
if (connection) if (connection)
{ {
wxChar item_name[200]; wxString item_name = DDEStringFromAtom(hsz2);
DdeQueryString(DDEIdInst, hsz2, (LPTSTR)item_name, WXSIZEOF(item_name),
CP_WINANSI); return (DDERETURN)connection->
OnStartAdvise(connection->m_topicName, item_name);
}
return (DDERETURN)(DWORD)connection->OnStartAdvise(connection->m_topicName, wxString(item_name));
} else return (DDERETURN)0;
break; break;
} }
@@ -668,11 +805,12 @@ DWORD /* lData2 */)
if (connection) if (connection)
{ {
wxChar item_name[200]; wxString item_name = DDEStringFromAtom(hsz2);
DdeQueryString(DDEIdInst, hsz2, (LPTSTR)item_name, WXSIZEOF(item_name),
CP_WINANSI); return (DDERETURN)connection->
return (DDERETURN)(DWORD)connection->OnStopAdvise(connection->m_topicName, wxString(item_name)); OnStopAdvise(connection->m_topicName, item_name);
} else return (DDERETURN)0; }
break; break;
} }
@@ -682,12 +820,22 @@ DWORD /* lData2 */)
if (connection && connection->m_sendingData) if (connection && connection->m_sendingData)
{ {
HDDEDATA data = DdeCreateDataHandle(DDEIdInst, HDDEDATA data = DdeCreateDataHandle
(
DDEIdInst,
(LPBYTE)connection->m_sendingData, (LPBYTE)connection->m_sendingData,
connection->m_dataSize, 0, hsz2, connection->m_dataType, 0); connection->m_dataSize,
0,
hsz2,
connection->m_dataType,
0
);
connection->m_sendingData = NULL; connection->m_sendingData = NULL;
return (DDERETURN)data; return (DDERETURN)data;
} else return (DDERETURN)NULL; }
break; break;
} }
@@ -697,27 +845,38 @@ DWORD /* lData2 */)
if (connection) if (connection)
{ {
wxChar item_name[200]; wxString item_name = DDEStringFromAtom(hsz2);
DdeQueryString(DDEIdInst, hsz2, (LPTSTR)item_name, WXSIZEOF(item_name),
CP_WINANSI);
DWORD len = DdeGetData(hData, (LPBYTE)(connection->m_bufPtr), connection->m_bufSize, 0); DWORD len = DdeGetData(hData,
(LPBYTE)connection->m_bufPtr,
connection->m_bufSize,
0);
DdeFreeDataHandle(hData); DdeFreeDataHandle(hData);
if (connection->OnAdvise(connection->m_topicName, wxString(item_name), connection->m_bufPtr, (int)len, (wxIPCFormat) wFmt)) if ( connection->OnAdvise(connection->m_topicName,
item_name,
connection->m_bufPtr,
(int)len,
(wxIPCFormat) wFmt) )
{
return (DDERETURN)(DWORD)DDE_FACK; return (DDERETURN)(DWORD)DDE_FACK;
else }
}
return (DDERETURN)DDE_FNOTPROCESSED; return (DDERETURN)DDE_FNOTPROCESSED;
} else return (DDERETURN)DDE_FNOTPROCESSED;
break;
} }
} }
return 0;
return (DDERETURN)0;
} }
// ----------------------------------------------------------------------------
// DDE strings and atoms
// ----------------------------------------------------------------------------
// Atom table stuff // Atom table stuff
static HSZ DDEAddAtom(const wxString& string) static HSZ DDEAddAtom(const wxString& string)
{ {
HSZ atom = DdeCreateStringHandle(DDEIdInst, WXSTRINGCAST string, CP_WINANSI); HSZ atom = DDEAtomFromString(string);
wxAtomTable.Append(string, (wxObject *)atom); wxAtomTable.Append(string, (wxObject *)atom);
return atom; return atom;
} }
@@ -734,70 +893,114 @@ static HSZ DDEGetAtom(const wxString& string)
} }
} }
void DDEPrintError(void) // atom <-> strings
static HSZ DDEAtomFromString(const wxString& s)
{ {
wxChar *err = NULL; wxASSERT_MSG( DDEIdInst, _T("DDE not initialized") );
switch (DdeGetLastError(DDEIdInst))
HSZ hsz = DdeCreateStringHandle(DDEIdInst, s, DDE_CP);
if ( !hsz )
{ {
DDELogError(_("Failed to create DDE string"));
}
return hsz;
}
static wxString DDEStringFromAtom(HSZ hsz)
{
// all DDE strings are normally limited to 255 bytes
static const size_t len = 256;
wxString s;
(void)DdeQueryString(DDEIdInst, hsz, s.GetWriteBuf(len), len, DDE_CP);
s.UngetWriteBuf();
return s;
}
// ----------------------------------------------------------------------------
// error handling
// ----------------------------------------------------------------------------
static void DDELogError(const wxString& s, UINT error)
{
if ( !error )
{
error = DdeGetLastError(DDEIdInst);
}
wxLogError(s + _T(": ") + DDEGetErrorMsg(error));
}
static wxString DDEGetErrorMsg(UINT error)
{
wxString err;
switch ( error )
{
case DMLERR_NO_ERROR:
err = _("no DDE error.");
break;
case DMLERR_ADVACKTIMEOUT: case DMLERR_ADVACKTIMEOUT:
err = wxT("A request for a synchronous advise transaction has timed out."); err = _("a request for a synchronous advise transaction has timed out.");
break; break;
case DMLERR_BUSY: case DMLERR_BUSY:
err = wxT("The response to the transaction caused the DDE_FBUSY bit to be set."); err = _("the response to the transaction caused the DDE_FBUSY bit to be set.");
break; break;
case DMLERR_DATAACKTIMEOUT: case DMLERR_DATAACKTIMEOUT:
err = wxT("A request for a synchronous data transaction has timed out."); err = _("a request for a synchronous data transaction has timed out.");
break; break;
case DMLERR_DLL_NOT_INITIALIZED: case DMLERR_DLL_NOT_INITIALIZED:
err = wxT("A DDEML function was called without first calling the DdeInitialize function,\n\ror an invalid instance identifier\n\rwas passed to a DDEML function."); err = _("a DDEML function was called without first calling the DdeInitialize function,\n\ror an invalid instance identifier\n\rwas passed to a DDEML function.");
break; break;
case DMLERR_DLL_USAGE: case DMLERR_DLL_USAGE:
err = wxT("An application initialized as APPCLASS_MONITOR has\n\rattempted to perform a DDE transaction,\n\ror an application initialized as APPCMD_CLIENTONLY has \n\rattempted to perform server transactions."); err = _("an application initialized as APPCLASS_MONITOR has\n\rattempted to perform a DDE transaction,\n\ror an application initialized as APPCMD_CLIENTONLY has \n\rattempted to perform server transactions.");
break; break;
case DMLERR_EXECACKTIMEOUT: case DMLERR_EXECACKTIMEOUT:
err = wxT("A request for a synchronous execute transaction has timed out."); err = _("a request for a synchronous execute transaction has timed out.");
break; break;
case DMLERR_INVALIDPARAMETER: case DMLERR_INVALIDPARAMETER:
err = wxT("A parameter failed to be validated by the DDEML."); err = _("a parameter failed to be validated by the DDEML.");
break; break;
case DMLERR_LOW_MEMORY: case DMLERR_LOW_MEMORY:
err = wxT("A DDEML application has created a prolonged race condition."); err = _("a DDEML application has created a prolonged race condition.");
break; break;
case DMLERR_MEMORY_ERROR: case DMLERR_MEMORY_ERROR:
err = wxT("A memory allocation failed."); err = _("a memory allocation failed.");
break; break;
case DMLERR_NO_CONV_ESTABLISHED: case DMLERR_NO_CONV_ESTABLISHED:
err = wxT("A client's attempt to establish a conversation has failed."); err = _("a client's attempt to establish a conversation has failed.");
break; break;
case DMLERR_NOTPROCESSED: case DMLERR_NOTPROCESSED:
err = wxT("A transaction failed."); err = _("a transaction failed.");
break; break;
case DMLERR_POKEACKTIMEOUT: case DMLERR_POKEACKTIMEOUT:
err = wxT("A request for a synchronous poke transaction has timed out."); err = _("a request for a synchronous poke transaction has timed out.");
break; break;
case DMLERR_POSTMSG_FAILED: case DMLERR_POSTMSG_FAILED:
err = wxT("An internal call to the PostMessage function has failed. "); err = _("an internal call to the PostMessage function has failed. ");
break; break;
case DMLERR_REENTRANCY: case DMLERR_REENTRANCY:
err = wxT("Reentrancy problem."); err = _("reentrancy problem.");
break; break;
case DMLERR_SERVER_DIED: case DMLERR_SERVER_DIED:
err = wxT("A server-side transaction was attempted on a conversation\n\rthat was terminated by the client, or the server\n\rterminated before completing a transaction."); err = _("a server-side transaction was attempted on a conversation\n\rthat was terminated by the client, or the server\n\rterminated before completing a transaction.");
break; break;
case DMLERR_SYS_ERROR: case DMLERR_SYS_ERROR:
err = wxT("An internal error has occurred in the DDEML."); err = _("an internal error has occurred in the DDEML.");
break; break;
case DMLERR_UNADVACKTIMEOUT: case DMLERR_UNADVACKTIMEOUT:
err = wxT("A request to end an advise transaction has timed out."); err = _("a request to end an advise transaction has timed out.");
break; break;
case DMLERR_UNFOUND_QUEUE_ID: case DMLERR_UNFOUND_QUEUE_ID:
err = wxT("An invalid transaction identifier was passed to a DDEML function.\n\rOnce the application has returned from an XTYP_XACT_COMPLETE callback,\n\rthe transaction identifier for that callback is no longer valid."); err = _("an invalid transaction identifier was passed to a DDEML function.\n\rOnce the application has returned from an XTYP_XACT_COMPLETE callback,\n\rthe transaction identifier for that callback is no longer valid.");
break; break;
default: default:
err = wxT("Unrecognised error type."); err.Printf(_("Unknown DDE error %08x"), error);
break;
} }
MessageBox((HWND) NULL, (LPCTSTR)err, wxT("DDE Error"), MB_OK | MB_ICONINFORMATION);
return err;
} }
#endif #endif

View File

@@ -88,6 +88,7 @@ wxDirDialog::wxDirDialog(wxWindow *parent,
m_message = message; m_message = message;
m_parent = parent; m_parent = parent;
m_path = defaultPath; m_path = defaultPath;
m_path.Replace(_T("/"), _T("\\")); // SHBrowseForFolder doesn't like '/'s
} }
int wxDirDialog::ShowModal() int wxDirDialog::ShowModal()

View File

@@ -1420,9 +1420,16 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
} }
// else translate it into wxEVT_COMMAND_LIST_ITEM_ACTIVATED event // else translate it into wxEVT_COMMAND_LIST_ITEM_ACTIVATED event
// if it happened on an item (and not on empty place)
{ {
eventType = wxEVT_COMMAND_LIST_ITEM_ACTIVATED;
NM_LISTVIEW* hdr = (NM_LISTVIEW*)lParam; NM_LISTVIEW* hdr = (NM_LISTVIEW*)lParam;
if ( hdr->iItem == -1 )
{
// not on item
return FALSE;
}
eventType = wxEVT_COMMAND_LIST_ITEM_ACTIVATED;
event.m_itemIndex = hdr->iItem; event.m_itemIndex = hdr->iItem;
} }
break; break;

View File

@@ -102,8 +102,6 @@ long wxStaticBox::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
} }
break; break;
// VZ: I will remove (or change) this soon... (15.11.99)
#if 0
case WM_ERASEBKGND: case WM_ERASEBKGND:
// prevent wxControl from processing this message because it will // prevent wxControl from processing this message because it will
// erase the background incorrectly and there is no way for us to // erase the background incorrectly and there is no way for us to
@@ -112,7 +110,6 @@ long wxStaticBox::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
// without painting over other controls - and if we don't, // without painting over other controls - and if we don't,
// wxControl still gets it) // wxControl still gets it)
return MSWDefWindowProc(nMsg, wParam, lParam); return MSWDefWindowProc(nMsg, wParam, lParam);
#endif
} }
return wxControl::MSWWindowProc(nMsg, wParam, lParam); return wxControl::MSWWindowProc(nMsg, wParam, lParam);

View File

@@ -74,6 +74,8 @@
#endif #endif
#include <stdarg.h> #include <stdarg.h>
#include "wx/dde.h" // for WX_DDE hack in wxExecute
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// constants // constants
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -177,9 +179,78 @@ LRESULT APIENTRY _EXPORT wxExecuteWindowCbk(HWND hWnd, UINT message,
} }
#endif #endif
long wxExecute(const wxString& command, bool sync, wxProcess *handler) long wxExecute(const wxString& cmd, bool sync, wxProcess *handler)
{ {
wxCHECK_MSG( !!command, 0, wxT("empty command in wxExecute") ); wxCHECK_MSG( !!cmd, 0, wxT("empty command in wxExecute") );
// DDE hack: this is really not pretty, but we need to allow this for
// transparent handling of DDE servers in wxMimeTypesManager. Usually it
// returns the command which should be run to view/open/... a file of the
// given type. Sometimes, however, this command just launches the server
// and an additional DDE request must be made to really open the file. To
// keep all this well hidden from the application, we allow a special form
// of command: WX_DDE:<command>:DDE_SERVER:DDE_TOPIC:DDE_COMMAND in which
// case we execute just <command> and process the rest below
wxString command, ddeServer, ddeTopic, ddeCommand;
static const size_t lenDdePrefix = 7; // strlen("WX_DDE:")
if ( cmd.Left(lenDdePrefix) == _T("WX_DDE#") )
{
const wxChar *p = cmd.c_str() + 7;
while ( *p && *p != _T('#') )
{
command += *p++;
}
if ( *p )
{
// skip '#'
p++;
}
else
{
wxFAIL_MSG(_T("invalid WX_DDE command in wxExecute"));
}
while ( *p && *p != _T('#') )
{
ddeServer += *p++;
}
if ( *p )
{
// skip '#'
p++;
}
else
{
wxFAIL_MSG(_T("invalid WX_DDE command in wxExecute"));
}
while ( *p && *p != _T('#') )
{
ddeTopic += *p++;
}
if ( *p )
{
// skip '#'
p++;
}
else
{
wxFAIL_MSG(_T("invalid WX_DDE command in wxExecute"));
}
while ( *p )
{
ddeCommand += *p++;
}
}
else
{
// no DDE
command = cmd;
}
#if defined(__WIN32__) && !defined(__TWIN32__) #if defined(__WIN32__) && !defined(__TWIN32__)
// the old code is disabled because we really need a process handle // the old code is disabled because we really need a process handle
@@ -237,6 +308,7 @@ long wxExecute(const wxString& command, bool sync, wxProcess *handler)
return result; return result;
#else // 1 #else // 1
// create the process // create the process
STARTUPINFO si; STARTUPINFO si;
wxZeroMemory(si); wxZeroMemory(si);
@@ -338,6 +410,20 @@ long wxExecute(const wxString& command, bool sync, wxProcess *handler)
return pi.dwProcessId; return pi.dwProcessId;
} }
// second part of DDE hack: now establish the DDE conversation with the
// just launched process
if ( !!ddeServer )
{
wxDDEClient client;
wxConnectionBase *conn = client.MakeConnection(_T(""),
ddeServer,
ddeTopic);
if ( !conn || !conn->Execute(ddeCommand) )
{
wxLogError(_("Couldn't launch DDE server '%s'."), command.c_str());
}
}
if ( !sync ) if ( !sync )
{ {
// clean up will be done when the process terminates // clean up will be done when the process terminates