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:
@@ -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;
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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);
|
||||||
|
617
src/msw/dde.cpp
617
src/msw/dde.cpp
@@ -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
|
||||||
|
@@ -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()
|
||||||
|
@@ -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;
|
||||||
|
@@ -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);
|
||||||
|
@@ -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
|
||||||
|
Reference in New Issue
Block a user