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(); }
|
||||
#endif
|
||||
|
||||
private:
|
||||
protected:
|
||||
// the name of the last file loaded with LoadFile() which will be used by
|
||||
// SaveFile() by default
|
||||
wxString m_filename;
|
||||
|
@@ -355,8 +355,8 @@ class wxMimeTypeIconHandler
|
||||
{
|
||||
public:
|
||||
virtual bool GetIcon(const wxString& mimetype, wxIcon *icon) = 0;
|
||||
|
||||
// this function fills manager with MIME types information gathered
|
||||
|
||||
// this function fills manager with MIME types information gathered
|
||||
// (as side effect) when searching for icons. This may be particularly
|
||||
// useful if mime.types is incomplete (e.g. RedHat distributions).
|
||||
virtual void GetMimeInfoRecords(wxMimeTypesManagerImpl *manager) = 0;
|
||||
@@ -370,7 +370,7 @@ class wxGNOMEIconHandler : public wxMimeTypeIconHandler
|
||||
public:
|
||||
virtual bool GetIcon(const wxString& mimetype, wxIcon *icon);
|
||||
virtual void GetMimeInfoRecords(wxMimeTypesManagerImpl *manager) {}
|
||||
|
||||
|
||||
private:
|
||||
void Init();
|
||||
void LoadIconsFromKeyFile(const wxString& filename);
|
||||
@@ -397,7 +397,7 @@ private:
|
||||
void LoadLinksForMimeType(const wxString& dirbase,
|
||||
const wxString& subdir,
|
||||
const wxArrayString& icondirs);
|
||||
void LoadLinkFilesFromDir(const wxString& dirbase,
|
||||
void LoadLinkFilesFromDir(const wxString& dirbase,
|
||||
const wxArrayString& icondirs);
|
||||
void Init();
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
@@ -1445,7 +1474,7 @@ void wxKDEIconHandler::LoadLinksForMimeSubtype(const wxString& dirbase,
|
||||
|
||||
wxString mime_extension, mime_desc;
|
||||
|
||||
pos = wxNOT_FOUND;
|
||||
pos = wxNOT_FOUND;
|
||||
if (wxGetLocale() != NULL)
|
||||
mime_desc = _T("Comment[") + wxGetLocale()->GetName() + _T("]=");
|
||||
if (pos == wxNOT_FOUND) mime_desc = _T("Comment=");
|
||||
@@ -1466,7 +1495,7 @@ void wxKDEIconHandler::LoadLinksForMimeSubtype(const wxString& dirbase,
|
||||
while ( *pc && *pc != _T('\n') ) exts += *pc++;
|
||||
wxStringTokenizer tokenizer(exts, _T(";"));
|
||||
wxString e;
|
||||
|
||||
|
||||
while (tokenizer.HasMoreTokens())
|
||||
{
|
||||
e = tokenizer.GetNextToken();
|
||||
@@ -1476,7 +1505,7 @@ void wxKDEIconHandler::LoadLinksForMimeSubtype(const wxString& dirbase,
|
||||
}
|
||||
mime_extension.RemoveLast();
|
||||
}
|
||||
|
||||
|
||||
ms_infoTypes.Add(mimetype);
|
||||
ms_infoDescriptions.Add(mime_desc);
|
||||
ms_infoExtensions.Add(mime_extension);
|
||||
@@ -1640,7 +1669,7 @@ bool wxKDEIconHandler::GetIcon(const wxString& mimetype, wxIcon *icon)
|
||||
void wxKDEIconHandler::GetMimeInfoRecords(wxMimeTypesManagerImpl *manager)
|
||||
{
|
||||
if ( !m_inited ) Init();
|
||||
|
||||
|
||||
size_t cnt = ms_infoTypes.GetCount();
|
||||
for (unsigned i = 0; i < cnt; i++)
|
||||
manager -> AddMimeTypeInfo(ms_infoTypes[i], ms_infoExtensions[i], ms_infoDescriptions[i]);
|
||||
@@ -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");
|
||||
@@ -1806,11 +1836,11 @@ wxMimeTypesManagerImpl::wxMimeTypesManagerImpl()
|
||||
if ( wxFile::Exists(strUserMimeTypes) ) {
|
||||
ReadMimeTypes(strUserMimeTypes);
|
||||
}
|
||||
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
@@ -253,14 +291,14 @@ wxBitmap::wxBitmap(const char bits[], int the_width, int the_height, int no_bits
|
||||
wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect) const
|
||||
{
|
||||
wxCHECK_MSG( Ok() &&
|
||||
(rect.x >= 0) && (rect.y >= 0) &&
|
||||
(rect.x >= 0) && (rect.y >= 0) &&
|
||||
(rect.x+rect.width <= GetWidth()) &&
|
||||
(rect.y+rect.height <= GetHeight()),
|
||||
wxNullBitmap, wxT("Invalid bitmap or bitmap region") );
|
||||
|
||||
|
||||
wxBitmap ret( rect.width, rect.height, GetDepth() );
|
||||
wxASSERT_MSG( ret.Ok(), wxT("GetSubBitmap error") );
|
||||
|
||||
|
||||
// copy bitmap data
|
||||
HDC dcSrc = ::CreateCompatibleDC(NULL);
|
||||
HDC dcDst = ::CreateCompatibleDC(NULL);
|
||||
|
@@ -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);
|
||||
|
1287
src/msw/dde.cpp
1287
src/msw/dde.cpp
File diff suppressed because it is too large
Load Diff
@@ -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()
|
||||
|
@@ -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;
|
||||
|
@@ -41,7 +41,7 @@
|
||||
// wxWin macros
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxStaticBox, wxControl)
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxStaticBox, wxControl)
|
||||
|
||||
// ============================================================================
|
||||
// implementation
|
||||
@@ -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);
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user