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

@@ -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);
}

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);
}
@@ -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);

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);

File diff suppressed because it is too large Load Diff

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

@@ -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);

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