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(); }
#endif
private:
protected:
// the name of the last file loaded with LoadFile() which will be used by
// SaveFile() by default
wxString m_filename;

View File

@@ -758,13 +758,15 @@ wxString wxFileTypeImpl::GetCommand(const wxChar *verb) const
return wxEmptyString;
}
strKey << wxT("\\shell\\") << verb << wxT("\\command");
wxRegKey key(wxRegKey::HKCR, strKey);
strKey << wxT("\\shell\\") << verb;
wxRegKey key(wxRegKey::HKCR, strKey + _T("\\command"));
wxString command;
if ( key.Open() ) {
// it's the default value of the key
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,
// 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();
for ( size_t n = 0; (n < len) && !foundFilename; n++ ) {
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'
command[n + 1] = wxT('s');
@@ -781,8 +785,33 @@ wxString wxFileTypeImpl::GetCommand(const wxChar *verb) const
}
}
if ( !foundFilename ) {
// we didn't find any '%1'!
// look whether we must issue some DDE requests to the application
// (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
command << wxT(" %s");
}
@@ -1779,7 +1808,8 @@ wxMimeTypesManagerImpl::wxMimeTypesManagerImpl()
};
// 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 file = dir + wxT("/mailcap");
@@ -1810,7 +1840,7 @@ wxMimeTypesManagerImpl::wxMimeTypesManagerImpl()
// read KDE/GNOME tables
ArrayIconHandlers& handlers = GetIconHandlers();
size_t count = handlers.GetCount();
for ( size_t n = 0; n < count; n++ )
for ( n = 0; n < count; n++ )
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),
GdkEventButton *WXUNUSED(gdk_event),
wxWindow *win )
wxWindow *WXUNUSED(win))
{
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),
GdkEventButton *WXUNUSED(gdk_event),
wxWindow *win )
wxWindow *WXUNUSED(win))
{
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),
GdkEventButton *WXUNUSED(gdk_event),
wxWindow *win )
wxWindow *WXUNUSED(win))
{
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),
GdkEventButton *WXUNUSED(gdk_event),
wxWindow *win )
wxWindow *WXUNUSED(win))
{
DEBUG_MAIN_THREAD

View File

@@ -227,25 +227,63 @@ wxBitmap::~wxBitmap()
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();
wxBitmapRefData *refData = new wxBitmapRefData;
m_refData = refData;
refData->m_width = the_width;
refData->m_height = the_height;
refData->m_depth = no_bits;
refData->m_width = width;
refData->m_height = height;
refData->m_depth = depth;
refData->m_numColors = 0;
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 )
{
wxLogLastError("CreateBitmap");
}
if ( data != bits )
{
free(data);
}
SetHBITMAP((WXHBITMAP)hbmp);
}

View File

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

View File

@@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////////
// Name: dde.cpp
// Name: msw/dde.cpp
// Purpose: DDE classes
// Author: Julian Smart
// Modified by:
@@ -9,6 +9,14 @@
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#ifdef __GNUG__
#pragma implementation "dde.h"
#endif
@@ -20,10 +28,6 @@
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/defs.h"
#endif
#if wxUSE_IPC
#ifndef WX_PRECOMP
@@ -35,35 +39,45 @@
#include "wx/dde.h"
#include "wx/msw/private.h"
#include <string.h>
#include <windows.h>
#include <ddeml.h>
#ifndef __TWIN32__
#if !wxUSE_NORLANDER_HEADERS
#ifdef __GNUWIN32__
#if defined(__TWIN32__) || defined(__GNUWIN32_OLD__)
#include "wx/msw/gnuwin32/extra.h"
#endif
#endif
#endif
#include <string.h>
// ----------------------------------------------------------------------------
// macros and constants
// ----------------------------------------------------------------------------
#ifdef __WIN32__
#define _EXPORT /**/
#define _EXPORT
#else
#define _EXPORT _export
#endif
IMPLEMENT_DYNAMIC_CLASS(wxDDEServer, wxServerBase)
IMPLEMENT_DYNAMIC_CLASS(wxDDEClient, wxClientBase)
IMPLEMENT_CLASS(wxDDEConnection, wxConnectionBase)
#if wxUSE_UNICODE
#define DDE_CP CP_WINUNICODE
#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 void DDEDeleteConnection(HCONV hConv);
static wxDDEServer *DDEFindServer(const wxString& s);
extern "C" HDDEDATA EXPENTRY _EXPORT _DDECallback(
WORD wType,
extern "C" HDDEDATA EXPENTRY _EXPORT _DDECallback(WORD wType,
WORD wFmt,
HCONV hConv,
HSZ hsz1,
@@ -75,7 +89,18 @@ DWORD lData2);
// Add topic name to atom table before using in conversations
static HSZ DDEAddAtom(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 wxDDEConnection *DDECurrentlyConnecting = NULL;
@@ -86,30 +111,61 @@ static wxList wxDDEServerObjects;
char *DDEDefaultIPCBuffer = NULL;
int DDEDefaultIPCBufferSize = 0;
/*
* Initialization
*
*/
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)
return;
DDEInitialized = TRUE;
public:
wxDDEModule() {}
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
DdeInitialize(&DDEIdInst, (PFNCALLBACK)MakeProcInstance(
(FARPROC)_DDECallback, wxGetInstance()),
APPCLASS_STANDARD,
0L);
PFNCALLBACK callback = (PFNCALLBACK)
MakeProcInstance((FARPROC)_DDECallback, wxGetInstance());
UINT rc = DdeInitialize(&DDEIdInst, callback, APPCLASS_STANDARD, 0L);
if ( rc != DMLERR_NO_ERROR )
{
DDELogError(_T("Failed to initialize DDE"), rc);
}
else
{
DDEInitialized = TRUE;
}
}
}
/*
* CleanUp
*/
void wxDDECleanUp()
{
@@ -118,24 +174,13 @@ void wxDDECleanUp()
DdeUninitialize(DDEIdInst);
DDEIdInst = 0;
}
if (DDEDefaultIPCBuffer)
delete [] DDEDefaultIPCBuffer;
}
// A module to allow DDE initialization/cleanup
// without calling these functions from app.cpp or from
// 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)
// ----------------------------------------------------------------------------
// functions working with the global connection list(s)
// ----------------------------------------------------------------------------
// Global find connection
static wxDDEConnection *DDEFindConnection(HCONV hConv)
@@ -200,40 +245,44 @@ static wxDDEServer *DDEFindServer(const wxString& s)
return found;
}
/*
* Server
*
*/
// ----------------------------------------------------------------------------
// wxDDEServer
// ----------------------------------------------------------------------------
wxDDEServer::wxDDEServer(void)
wxDDEServer::wxDDEServer()
{
m_serviceName = "";
wxDDEInitialize();
wxDDEServerObjects.Append(this);
}
bool wxDDEServer::Create(const wxString& server_name)
bool wxDDEServer::Create(const wxString& server)
{
m_serviceName = server_name;
HSZ serviceName = DdeCreateStringHandle(DDEIdInst, WXSTRINGCAST server_name, CP_WINANSI);
m_serviceName = server;
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 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, serviceName, NULL, DNS_UNREGISTER) == 0)
if ( !DdeNameService(DDEIdInst, DDEAtomFromString(m_serviceName),
(HSZ)NULL, DNS_UNREGISTER) )
{
DDEPrintError();
DDELogError(wxString::Format(_("Failed to unregister DDE server '%s'"),
m_serviceName.c_str()));
}
}
wxDDEServerObjects.DeleteObject(this);
wxNode *node = m_connections.First();
@@ -293,19 +342,18 @@ bool wxDDEServer::DeleteConnection(WXHCONV conv)
return found;
}
// ----------------------------------------------------------------------------
// wxDDEClient
// ----------------------------------------------------------------------------
/*
* Client
*
*/
wxDDEClient::wxDDEClient(void)
wxDDEClient::wxDDEClient()
{
wxDDEInitialize();
wxDDEClientObjects.Append(this);
}
wxDDEClient::~wxDDEClient(void)
wxDDEClient::~wxDDEClient()
{
wxDDEClientObjects.DeleteObject(this);
wxNode *node = m_connections.First();
@@ -322,14 +370,18 @@ bool wxDDEClient::ValidHost(const wxString& /* host */)
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);
HSZ topic_atom = DdeCreateStringHandle(DDEIdInst, WXSTRINGCAST topic, CP_WINANSI);
HCONV hConv = DdeConnect(DDEIdInst, serviceName, topic_atom, (PCONVCONTEXT)NULL);
if (hConv == (HCONV) NULL)
return (wxConnectionBase*) NULL;
HCONV hConv = DdeConnect(DDEIdInst, DDEAtomFromString(server), DDEAtomFromString(topic),
(PCONVCONTEXT)NULL);
if ( !hConv )
{
DDELogError(wxString::Format(_("Failed to create connection to "
"server '%s' on topic '%s'"),
server.c_str(), topic.c_str()));
}
else
{
wxDDEConnection *connection = (wxDDEConnection*) OnMakeConnection();
@@ -341,11 +393,12 @@ wxConnectionBase *wxDDEClient::MakeConnection(const wxString& /* host */, const
m_connections.Append(connection);
return connection;
}
else return (wxConnectionBase*) NULL;
}
}
wxConnectionBase *wxDDEClient::OnMakeConnection(void)
return (wxConnectionBase*) NULL;
}
wxConnectionBase *wxDDEClient::OnMakeConnection()
{
return new wxDDEConnection;
}
@@ -382,9 +435,9 @@ bool wxDDEClient::DeleteConnection(WXHCONV conv)
return found;
}
/*
* Connection
*/
// ----------------------------------------------------------------------------
// wxDDEConnection
// ----------------------------------------------------------------------------
wxDDEConnection::wxDDEConnection(char *buffer, int size)
{
@@ -401,8 +454,6 @@ wxDDEConnection::wxDDEConnection(char *buffer, int size)
m_bufSize = size;
}
m_topicName = "";
m_client = NULL;
m_server = NULL;
@@ -410,7 +461,7 @@ wxDDEConnection::wxDDEConnection(char *buffer, int size)
m_sendingData = NULL;
}
wxDDEConnection::wxDDEConnection(void)
wxDDEConnection::wxDDEConnection()
{
m_hConv = 0;
m_sendingData = NULL;
@@ -421,10 +472,9 @@ wxDDEConnection::wxDDEConnection(void)
m_bufPtr = DDEDefaultIPCBuffer;
m_bufSize = DDEDefaultIPCBufferSize;
m_topicName = "";
}
wxDDEConnection::~wxDDEConnection(void)
wxDDEConnection::~wxDDEConnection()
{
if (m_server)
m_server->GetConnections().DeleteObject(this);
@@ -433,22 +483,40 @@ wxDDEConnection::~wxDDEConnection(void)
}
// Calls that CLIENT can make
bool wxDDEConnection::Disconnect(void)
bool wxDDEConnection::Disconnect()
{
DDEDeleteConnection((HCONV) m_hConv);
return (DdeDisconnect((HCONV) m_hConv) != 0);
DDEDeleteConnection(GetHConv());
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)
{
DWORD result;
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,
NULL, format, XTYP_EXECUTE, 5000, &result) ? TRUE : FALSE);
return ok;
}
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;
HSZ atom = DDEGetAtom(item);
HDDEDATA returned_data = DdeClientTransaction(NULL, 0, (HCONV) m_hConv,
atom, format, XTYP_REQUEST, 5000, &result);
HDDEDATA returned_data = DdeClientTransaction(NULL, 0,
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);
if (size) *size = (int)len;
if (len > 0)
{
if (size)
*size = (int)len;
return m_bufPtr;
}
else return NULL;
}
bool wxDDEConnection::Poke(const wxString& item, wxChar *data, int size, wxIPCFormat format)
{
DWORD result;
if (size < 0)
size = wxStrlen(data);
size ++;
{
size = wxStrlen(data) + 1;
}
HSZ item_atom = DDEGetAtom(item);
return (DdeClientTransaction((LPBYTE)data, size, (HCONV) m_hConv,
item_atom, format, XTYP_POKE, 5000, &result) ? TRUE : FALSE);
bool ok = DdeClientTransaction((LPBYTE)data, size,
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)
@@ -489,8 +575,18 @@ bool wxDDEConnection::StartAdvise(const wxString& item)
DWORD result;
HSZ atom = DDEGetAtom(item);
return (DdeClientTransaction(NULL, 0, (HCONV) m_hConv,
atom, CF_TEXT, XTYP_ADVSTART, 5000, &result) ? TRUE : FALSE);
bool ok = DdeClientTransaction(NULL, 0,
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)
@@ -498,71 +594,89 @@ bool wxDDEConnection::StopAdvise(const wxString& item)
DWORD result;
HSZ atom = DDEGetAtom(item);
return (DdeClientTransaction(NULL, 0, (HCONV) m_hConv,
atom, CF_TEXT, XTYP_ADVSTOP, 5000, &result) ? TRUE : FALSE);
bool ok = DdeClientTransaction(NULL, 0,
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
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)
size = wxStrlen(data);
size ++;
{
size = wxStrlen(data) + 1;
}
HSZ item_atom = DDEGetAtom(item);
HSZ topic_atom = DDEGetAtom(m_topicName);
m_sendingData = data;
m_dataSize = size;
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;
return TRUE;
}
// ----------------------------------------------------------------------------
// _DDECallback
// ----------------------------------------------------------------------------
#define DDERETURN HDDEDATA
HDDEDATA EXPENTRY _EXPORT _DDECallback(
WORD wType,
HDDEDATA EXPENTRY _EXPORT
_DDECallback(WORD wType,
WORD wFmt,
HCONV hConv,
HSZ hsz1,
HSZ hsz2,
HDDEDATA hData,
DWORD /* lData1 */,
DWORD /* lData2 */)
DWORD WXUNUSED(lData1),
DWORD WXUNUSED(lData2))
{
switch (wType)
{
case XTYP_CONNECT:
{
wxChar topic_buf[100];
wxChar server_buf[100];
DdeQueryString(DDEIdInst, hsz1, (LPTSTR)topic_buf, WXSIZEOF(topic_buf),
CP_WINANSI);
DdeQueryString(DDEIdInst, hsz2, (LPTSTR)server_buf, WXSIZEOF(topic_buf),
CP_WINANSI);
wxDDEServer *server = DDEFindServer(server_buf);
wxString topic = DDEStringFromAtom(hsz1),
srv = DDEStringFromAtom(hsz2);
wxDDEServer *server = DDEFindServer(srv);
if (server)
{
wxDDEConnection *connection =
(wxDDEConnection*) server->OnAcceptConnection(wxString(topic_buf));
(wxDDEConnection*) server->OnAcceptConnection(topic);
if (connection)
{
connection->m_server = server;
server->GetConnections().Append(connection);
connection->m_hConv = 0;
connection->m_topicName = topic_buf;
connection->m_topicName = topic;
DDECurrentlyConnecting = connection;
return (DDERETURN)(DWORD)TRUE;
}
}
else return (DDERETURN)0;
break;
}
@@ -574,7 +688,6 @@ DWORD /* lData2 */)
DDECurrentlyConnecting = NULL;
return (DDERETURN)(DWORD)TRUE;
}
else return 0;
break;
}
@@ -586,7 +699,6 @@ DWORD /* lData2 */)
DDEDeleteConnection(hConv); // Delete mapping: hConv => connection
return (DDERETURN)(DWORD)TRUE;
}
else return (DDERETURN)0;
break;
}
@@ -596,14 +708,21 @@ DWORD /* lData2 */)
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);
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;
else
}
}
return (DDERETURN)DDE_FNOTPROCESSED;
} else return (DDERETURN)DDE_FNOTPROCESSED;
break;
}
case XTYP_REQUEST:
@@ -612,21 +731,28 @@ DWORD /* lData2 */)
if (connection)
{
wxChar item_name[200];
DdeQueryString(DDEIdInst, hsz2, (LPTSTR)item_name, WXSIZEOF(item_name),
CP_WINANSI);
wxString item_name = DDEStringFromAtom(hsz2);
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 (user_size < 0) user_size = strlen(data);
if (user_size < 0)
user_size = wxStrlen(data) + 1;
HDDEDATA handle = DdeCreateDataHandle(DDEIdInst,
(LPBYTE)data, user_size + 1, 0, hsz2, wFmt, 0);
(LPBYTE)data,
user_size,
0,
hsz2,
wFmt,
0);
return (DDERETURN)handle;
} else return (DDERETURN)0;
} else return (DDERETURN)0;
}
}
break;
}
@@ -636,15 +762,26 @@ DWORD /* lData2 */)
if (connection)
{
wxChar item_name[200];
DdeQueryString(DDEIdInst, hsz2, (LPTSTR)item_name, WXSIZEOF(item_name),
CP_WINANSI);
DWORD len = DdeGetData(hData, (LPBYTE)(connection->m_bufPtr), connection->m_bufSize, 0);
wxString item_name = DDEStringFromAtom(hsz2);
DWORD len = DdeGetData(hData,
(LPBYTE)connection->m_bufPtr,
connection->m_bufSize,
0);
DdeFreeDataHandle(hData);
connection->OnPoke(connection->m_topicName, wxString(item_name), connection->m_bufPtr, (int)len, (wxIPCFormat) wFmt);
return (DDERETURN)(DWORD)DDE_FACK;
} else return (DDERETURN)DDE_FNOTPROCESSED;
break;
connection->OnPoke(connection->m_topicName,
item_name,
connection->m_bufPtr,
(int)len,
(wxIPCFormat) wFmt);
return (DDERETURN)DDE_FACK;
}
else
{
return (DDERETURN)DDE_FNOTPROCESSED;
}
}
case XTYP_ADVSTART:
@@ -653,12 +790,12 @@ DWORD /* lData2 */)
if (connection)
{
wxChar item_name[200];
DdeQueryString(DDEIdInst, hsz2, (LPTSTR)item_name, WXSIZEOF(item_name),
CP_WINANSI);
wxString item_name = DDEStringFromAtom(hsz2);
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;
}
@@ -668,11 +805,12 @@ DWORD /* lData2 */)
if (connection)
{
wxChar item_name[200];
DdeQueryString(DDEIdInst, hsz2, (LPTSTR)item_name, WXSIZEOF(item_name),
CP_WINANSI);
return (DDERETURN)(DWORD)connection->OnStopAdvise(connection->m_topicName, wxString(item_name));
} else return (DDERETURN)0;
wxString item_name = DDEStringFromAtom(hsz2);
return (DDERETURN)connection->
OnStopAdvise(connection->m_topicName, item_name);
}
break;
}
@@ -682,12 +820,22 @@ DWORD /* lData2 */)
if (connection && connection->m_sendingData)
{
HDDEDATA data = DdeCreateDataHandle(DDEIdInst,
HDDEDATA data = DdeCreateDataHandle
(
DDEIdInst,
(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;
return (DDERETURN)data;
} else return (DDERETURN)NULL;
}
break;
}
@@ -697,27 +845,38 @@ DWORD /* lData2 */)
if (connection)
{
wxChar item_name[200];
DdeQueryString(DDEIdInst, hsz2, (LPTSTR)item_name, WXSIZEOF(item_name),
CP_WINANSI);
wxString item_name = DDEStringFromAtom(hsz2);
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);
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;
else
}
}
return (DDERETURN)DDE_FNOTPROCESSED;
} else return (DDERETURN)DDE_FNOTPROCESSED;
break;
}
}
return 0;
return (DDERETURN)0;
}
// ----------------------------------------------------------------------------
// DDE strings and atoms
// ----------------------------------------------------------------------------
// Atom table stuff
static HSZ DDEAddAtom(const wxString& string)
{
HSZ atom = DdeCreateStringHandle(DDEIdInst, WXSTRINGCAST string, CP_WINANSI);
HSZ atom = DDEAtomFromString(string);
wxAtomTable.Append(string, (wxObject *)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;
switch (DdeGetLastError(DDEIdInst))
wxASSERT_MSG( DDEIdInst, _T("DDE not initialized") );
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:
err = wxT("A request for a synchronous advise transaction has timed out.");
err = _("a request for a synchronous advise transaction has timed out.");
break;
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;
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;
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;
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;
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;
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;
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;
case DMLERR_MEMORY_ERROR:
err = wxT("A memory allocation failed.");
err = _("a memory allocation failed.");
break;
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;
case DMLERR_NOTPROCESSED:
err = wxT("A transaction failed.");
err = _("a transaction failed.");
break;
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;
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;
case DMLERR_REENTRANCY:
err = wxT("Reentrancy problem.");
err = _("reentrancy problem.");
break;
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;
case DMLERR_SYS_ERROR:
err = wxT("An internal error has occurred in the DDEML.");
err = _("an internal error has occurred in the DDEML.");
break;
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;
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;
default:
err = wxT("Unrecognised error type.");
break;
err.Printf(_("Unknown DDE error %08x"), error);
}
MessageBox((HWND) NULL, (LPCTSTR)err, wxT("DDE Error"), MB_OK | MB_ICONINFORMATION);
return err;
}
#endif

View File

@@ -88,6 +88,7 @@ wxDirDialog::wxDirDialog(wxWindow *parent,
m_message = message;
m_parent = parent;
m_path = defaultPath;
m_path.Replace(_T("/"), _T("\\")); // SHBrowseForFolder doesn't like '/'s
}
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
// if it happened on an item (and not on empty place)
{
eventType = wxEVT_COMMAND_LIST_ITEM_ACTIVATED;
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;
}
break;

View File

@@ -102,8 +102,6 @@ long wxStaticBox::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
}
break;
// VZ: I will remove (or change) this soon... (15.11.99)
#if 0
case WM_ERASEBKGND:
// prevent wxControl from processing this message because it will
// 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,
// wxControl still gets it)
return MSWDefWindowProc(nMsg, wParam, lParam);
#endif
}
return wxControl::MSWWindowProc(nMsg, wParam, lParam);

View File

@@ -74,6 +74,8 @@
#endif
#include <stdarg.h>
#include "wx/dde.h" // for WX_DDE hack in wxExecute
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
@@ -177,9 +179,78 @@ LRESULT APIENTRY _EXPORT wxExecuteWindowCbk(HWND hWnd, UINT message,
}
#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__)
// 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;
#else // 1
// create the process
STARTUPINFO si;
wxZeroMemory(si);
@@ -338,6 +410,20 @@ long wxExecute(const wxString& command, bool sync, wxProcess *handler)
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 )
{
// clean up will be done when the process terminates