class WXDLLEXPORT wxFindReplaceData : public wxObject
{
public:
- wxFindReplaceData() { }
- wxFindReplaceData(wxUint32 flags) { SetFlags(flags); }
+ wxFindReplaceData() { Init(); }
+ wxFindReplaceData(wxUint32 flags) { Init(); SetFlags(flags); }
// accessors
const wxString& GetFindString() { return m_FindWhat; }
void SetFindString(const wxString& str) { m_FindWhat = str; }
void SetReplaceString(const wxString& str) { m_ReplaceWith = str; }
+protected:
+ void Init();
+
private:
wxUint32 m_Flags;
wxString m_FindWhat,
wxFindReplaceDialog() { Init(); }
wxFindReplaceDialog(wxWindow *parent,
wxFindReplaceData *data,
- const wxString &title);
+ const wxString &title,
+ int style = 0);
bool Create(wxWindow *parent,
wxFindReplaceData *data,
- const wxString &title);
+ const wxString &title,
+ int style = 0);
virtual ~wxFindReplaceDialog();
wxFindReplaceDialogImpl *GetImpl() const { return m_impl; }
// override some base class virtuals
- virtual bool Show(bool show);
+ virtual bool Show(bool show = TRUE);
virtual void SetTitle( const wxString& title);
virtual wxString GetTitle() const;
wxString GetFindString() const { return GetString(); }
const wxString& GetReplaceString() const { return m_strReplace; }
+ wxFindReplaceDialog *GetDialog() const
+ { return wxStaticCast(GetEventObject(), wxFindReplaceDialog); }
+
// implementation only
void SetFlags(int flags) { SetInt(flags); }
void SetFindString(const wxString& str) { SetString(str); }
};
BEGIN_DECLARE_EVENT_TYPES()
- DECLARE_EVENT_TYPE(wxEVT_COMMAND_FIND_NEXT, 510)
- DECLARE_EVENT_TYPE(wxEVT_COMMAND_REPLACE, 511)
- DECLARE_EVENT_TYPE(wxEVT_COMMAND_REPLACE_ALL, 512)
- DECLARE_EVENT_TYPE(wxEVT_COMMAND_FIND_CLOSE, 513)
+ DECLARE_EVENT_TYPE(wxEVT_COMMAND_FIND, 510)
+ DECLARE_EVENT_TYPE(wxEVT_COMMAND_FIND_NEXT, 511)
+ DECLARE_EVENT_TYPE(wxEVT_COMMAND_FIND_REPLACE, 512)
+ DECLARE_EVENT_TYPE(wxEVT_COMMAND_FIND_REPLACE_ALL, 513)
+ DECLARE_EVENT_TYPE(wxEVT_COMMAND_FIND_CLOSE, 514)
END_DECLARE_EVENT_TYPES()
typedef void (wxEvtHandler::*wxFindDialogEventFunction)(wxFindDialogEvent&);
+#define EVT_FIND(id, fn) \
+ DECLARE_EVENT_TABLE_ENTRY( \
+ wxEVT_COMMAND_FIND, id, -1, \
+ (wxObjectEventFunction)(wxEventFunction)(wxFindDialogEventFunction) \
+ & fn, \
+ (wxObject *) NULL \
+ ),
+
#define EVT_FIND_NEXT(id, fn) \
DECLARE_EVENT_TABLE_ENTRY( \
wxEVT_COMMAND_FIND_NEXT, id, -1, \
(wxObject *) NULL \
),
-#define EVT_REPLACE(id, fn) \
+#define EVT_FIND_REPLACE(id, fn) \
DECLARE_EVENT_TABLE_ENTRY( \
- wxEVT_COMMAND_REPLACE, id, -1, \
+ wxEVT_COMMAND_FIND_REPLACE, id, -1, \
(wxObjectEventFunction)(wxEventFunction)(wxFindDialogEventFunction) \
& fn, \
(wxObject *) NULL \
#define EVT_FIND_REPLACE_ALL(id, fn) \
DECLARE_EVENT_TABLE_ENTRY( \
- wxEVT_COMMAND_REPLACE_ALL, id, -1, \
+ wxEVT_COMMAND_FIND_REPLACE_ALL, id, -1, \
(wxObjectEventFunction)(wxEventFunction)(wxFindDialogEventFunction) \
& fn, \
(wxObject *) NULL \
),
-#define EVT_FIND_FIND_CLOSE(id, fn) \
+#define EVT_FIND_CLOSE(id, fn) \
DECLARE_EVENT_TABLE_ENTRY( \
wxEVT_COMMAND_FIND_CLOSE, id, -1, \
(wxObjectEventFunction)(wxEventFunction)(wxFindDialogEventFunction) \
#include "wx/choicdlg.h"
#include "wx/tipdlg.h"
#include "wx/progdlg.h"
+#include "wx/fdrepdlg.h"
#define wxTEST_GENERIC_DIALOGS_IN_MSW 0
#endif
#if wxUSE_PROGRESSDLG
EVT_MENU(DIALOGS_PROGRESS, MyFrame::ShowProgress)
-#endif
+#endif // wxUSE_PROGRESSDLG
+#if wxUSE_FINDREPLDLG
+ EVT_MENU(DIALOGS_FIND, MyFrame::ShowFindDialog)
+ EVT_MENU(DIALOGS_REPLACE, MyFrame::ShowReplaceDialog)
+
+ EVT_FIND(-1, MyFrame::OnFindDialog)
+ EVT_FIND_NEXT(-1, MyFrame::OnFindDialog)
+ EVT_FIND_REPLACE(-1, MyFrame::OnFindDialog)
+ EVT_FIND_REPLACE_ALL(-1, MyFrame::OnFindDialog)
+ EVT_FIND_CLOSE(-1, MyFrame::OnFindDialog)
+#endif // wxUSE_FINDREPLDLG
EVT_MENU(wxID_EXIT, MyFrame::OnExit)
EVT_BUTTON(DIALOGS_MODELESS_BTN, MyFrame::OnButton)
#if wxUSE_PROGRESSDLG
file_menu->Append(DIALOGS_PROGRESS, "Pro&gress dialog\tCtrl-G");
#endif // wxUSE_PROGRESSDLG
+#if wxUSE_FINDREPLDLG
+ file_menu->Append(DIALOGS_FIND, "&Find dialog\tCtrl-F");
+ file_menu->Append(DIALOGS_REPLACE, "Find and &replace dialog\tShift-Ctrl-F");
+#endif // wxUSE_FINDREPLDLG
file_menu->AppendSeparator();
- file_menu->Append(DIALOGS_MODAL, "Mo&dal dialog\tCtrl-F");
+ file_menu->Append(DIALOGS_MODAL, "Mo&dal dialog\tCtrl-D");
file_menu->Append(DIALOGS_MODELESS, "Modeless &dialog\tCtrl-Z", "", TRUE);
file_menu->AppendSeparator();
file_menu->Append(wxID_EXIT, "E&xit\tAlt-X");
#endif // wxUSE_PROGRESSDLG
+#if wxUSE_FINDREPLDLG
+
+void MyFrame::ShowReplaceDialog( wxCommandEvent& WXUNUSED(event) )
+{
+ wxFindReplaceDialog *dialog = new wxFindReplaceDialog
+ (
+ this,
+ &m_findData,
+ "Find and replace dialog",
+ wxFR_REPLACEDIALOG
+ );
+ dialog->Show();
+}
+
+void MyFrame::ShowFindDialog( wxCommandEvent& WXUNUSED(event) )
+{
+ wxFindReplaceDialog *dialog = new wxFindReplaceDialog
+ (
+ this,
+ &m_findData,
+ "Find dialog",
+ // just for testing
+ wxFR_NOWHOLEWORD
+ );
+ dialog->Show();
+}
+
+static wxString DecodeFindDialogEventFlags(int flags)
+{
+ wxString str;
+ str << (flags & wxFR_DOWN ? "down" : "up") << ", "
+ << (flags & wxFR_WHOLEWORD ? "whole words only, " : "")
+ << (flags & wxFR_MATCHCASE ? "" : "not ")
+ << "case sensitive";
+
+ return str;
+}
+
+void MyFrame::OnFindDialog(wxFindDialogEvent& event)
+{
+ wxEventType type = event.GetEventType();
+
+ if ( type == wxEVT_COMMAND_FIND || type == wxEVT_COMMAND_FIND_NEXT )
+ {
+ wxLogMessage("Find %s'%s' (flags: %s)",
+ type == wxEVT_COMMAND_FIND_NEXT ? "next " : "",
+ event.GetFindString().c_str(),
+ DecodeFindDialogEventFlags(event.GetFlags()).c_str());
+ }
+ else if ( type == wxEVT_COMMAND_FIND_REPLACE ||
+ type == wxEVT_COMMAND_FIND_REPLACE_ALL )
+ {
+ wxLogMessage("Replace %s'%s' with '%s' (flags: %s)",
+ type == wxEVT_COMMAND_FIND_REPLACE_ALL ? "all " : "",
+ event.GetFindString().c_str(),
+ event.GetReplaceString().c_str(),
+ DecodeFindDialogEventFlags(event.GetFlags()).c_str());
+ }
+ else if ( type == wxEVT_COMMAND_FIND_CLOSE )
+ {
+ wxLogMessage("Find dialog is being closed.");
+
+ event.GetDialog()->Destroy();
+ }
+ else
+ {
+ wxLogError("Unknown find dialog event!");
+ }
+}
+
+#endif // wxUSE_FINDREPLDLG
+
// ----------------------------------------------------------------------------
// MyCanvas
// ----------------------------------------------------------------------------
void ShowTip(wxCommandEvent& event);
void ModalDlg(wxCommandEvent& event);
void ModelessDlg(wxCommandEvent& event);
+#if wxUSE_PROGRESSDLG
void ShowProgress(wxCommandEvent& event);
+#endif // wxUSE_PROGRESSDLG
+#if wxUSE_FINDREPLDLG
+ void ShowFindDialog(wxCommandEvent& event);
+ void ShowReplaceDialog(wxCommandEvent& event);
+
+ void OnFindDialog(wxFindDialogEvent& event);
+#endif // wxUSE_FINDREPLDLG
#if !defined(__WXMSW__) || wxTEST_GENERIC_DIALOGS_IN_MSW
void ChooseColourGeneric(wxCommandEvent& event);
private:
MyModelessDialog *m_dialog;
+#if wxUSE_FINDREPLDLG
+ wxFindReplaceData m_findData;
+#endif // wxUSE_FINDREPLDLG
+
DECLARE_EVENT_TABLE()
};
DIALOGS_MODAL,
DIALOGS_MODELESS,
DIALOGS_MODELESS_BTN,
- DIALOGS_PROGRESS
+ DIALOGS_PROGRESS,
+ DIALOGS_FIND,
+ DIALOGS_REPLACE
};
#endif
HWND hWnd = msg->hwnd;
wxWindow *wndThis = wxGetWindowFromHWND((WXHWND)hWnd);
+ // this may happen if the event occured in a standard modeless dialog (the
+ // only example of which I know of is the find/replace dialog) - then call
+ // IsDialogMessage() to make TAB navigation in it work
+ if ( !wndThis )
+ {
+ return ::IsDialogMessage(hWnd, msg) != 0;
+ }
+
#if wxUSE_TOOLTIPS
// we must relay WM_MOUSEMOVE events to the tooltip ctrl if we want it to
// popup the tooltip bubbles
- if ( wndThis && (msg->message == WM_MOUSEMOVE) )
+ if ( (msg->message == WM_MOUSEMOVE) )
{
wxToolTip *tt = wndThis->GetToolTip();
if ( tt )
// functions prototypes
// ----------------------------------------------------------------------------
-LRESULT APIENTRY FindReplaceWindowProc(HWND hwnd, WXUINT nMsg,
+LRESULT APIENTRY wxFindReplaceWindowProc(HWND hwnd, WXUINT nMsg,
WPARAM wParam, LPARAM lParam);
UINT CALLBACK wxFindReplaceDialogHookProc(HWND hwnd,
IMPLEMENT_DYNAMIC_CLASS(wxFindDialogEvent, wxCommandEvent)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_FIND)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_FIND_NEXT)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_FIND_REPLACE)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_FIND_REPLACE_ALL)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_FIND_CLOSE)
+
// ----------------------------------------------------------------------------
// wxFindReplaceDialogImpl: the internals of wxFindReplaceDialog
// ----------------------------------------------------------------------------
wxZeroMemory(m_findReplace);
- // translate the flags
+ // translate the flags: first the dialog creation flags
// always set this to be able to set the title
int flags = FR_ENABLEHOOK;
- if ( flagsWX & wxFR_NOMATCHCASE)
+ int flagsDialog = dialog->GetWindowStyle();
+ if ( flagsDialog & wxFR_NOMATCHCASE)
flags |= FR_NOMATCHCASE;
- if ( flagsWX & wxFR_NOWHOLEWORD)
+ if ( flagsDialog & wxFR_NOWHOLEWORD)
flags |= FR_NOWHOLEWORD;
- if ( flagsWX & wxFR_NOUPDOWN)
+ if ( flagsDialog & wxFR_NOUPDOWN)
flags |= FR_NOUPDOWN;
+
+ // and now the flags governing the initial values of the dialogs controls
if ( flagsWX & wxFR_DOWN)
flags |= FR_DOWN;
+ if ( flagsWX & wxFR_MATCHCASE)
+ flags |= FR_MATCHCASE;
+ if ( flagsWX & wxFR_WHOLEWORD )
+ flags |= FR_WHOLEWORD;
m_findReplace.lStructSize = sizeof(FINDREPLACE);
m_findReplace.hwndOwner = GetHwndOf(dialog->GetParent());
void wxFindReplaceDialogImpl::SubclassDialog(HWND hwnd)
{
m_hwndOwner = hwnd;
- m_oldParentWndProc = (WNDPROC)::SetWindowLong
- (
- hwnd,
- GWL_WNDPROC,
- (LONG)FindReplaceWindowProc
- );
-
- // save it elsewhere to access it from FindReplaceWindowProc()
- (void)::SetWindowLong(hwnd, GWL_USERDATA, (LONG)m_oldParentWndProc);
+
+ // check that we don't subclass the parent twice: this would be a bad idea
+ // as then we'd have infinite recursion in wxFindReplaceWindowProc
+ WNDPROC oldParentWndProc = (WNDPROC)::GetWindowLong(hwnd, GWL_WNDPROC);
+
+ if ( oldParentWndProc != wxFindReplaceWindowProc )
+ {
+ // save old wnd proc elsewhere to access it from
+ // wxFindReplaceWindowProc
+ m_oldParentWndProc = oldParentWndProc;
+ (void)::SetWindowLong(hwnd, GWL_USERDATA, (LONG)oldParentWndProc);
+
+ // and set the new one
+ (void)::SetWindowLong(hwnd, GWL_WNDPROC, (LONG)wxFindReplaceWindowProc);
+ }
}
wxFindReplaceDialogImpl::~wxFindReplaceDialogImpl()
// Window Proc for handling RegisterWindowMessage(FINDMSGSTRING)
// ----------------------------------------------------------------------------
-LRESULT APIENTRY FindReplaceWindowProc(HWND hwnd, WXUINT nMsg,
- WPARAM wParam, LPARAM lParam)
+LRESULT APIENTRY wxFindReplaceWindowProc(HWND hwnd, WXUINT nMsg,
+ WPARAM wParam, LPARAM lParam)
{
if ( nMsg == wxFindReplaceDialogImpl::GetFindDialogMessage() )
{
}
else if ( pFR->Flags & FR_REPLACE )
{
- evtType = wxEVT_COMMAND_REPLACE;
+ evtType = wxEVT_COMMAND_FIND_REPLACE;
replace = TRUE;
}
else if ( pFR->Flags & FR_REPLACEALL )
{
- evtType = wxEVT_COMMAND_REPLACE_ALL;
+ evtType = wxEVT_COMMAND_FIND_REPLACE_ALL;
replace = TRUE;
}
flags |= wxFR_MATCHCASE;
wxFindDialogEvent event(evtType, dialog->GetId());
+ event.SetEventObject(dialog);
event.SetFlags(flags);
event.SetFindString(pFR->lpstrFindWhat);
if ( replace )
event.SetReplaceString(pFR->lpstrReplaceWith);
}
- (void)dialog->GetEventHandler()->ProcessEvent(event);
+ // TODO: should we copy the strings to dialog->GetData() as well?
+
+ if ( !dialog->GetEventHandler()->ProcessEvent(event) )
+ {
+ // the event is not propagated upwards to the parent automatically
+ // because the dialog is a top level window, so do it manually as
+ // in 9 cases of 10 the message must be processed by the dialog
+ // owner and not the dialog itself
+ (void)dialog->GetParent()->GetEventHandler()->ProcessEvent(event);
+ }
}
WNDPROC wndProc = (WNDPROC)::GetWindowLong(hwnd, GWL_USERDATA);
+ // sanity check
+ wxASSERT_MSG( wndProc != wxFindReplaceWindowProc,
+ _T("infinite recursion detected") );
+
return ::CallWindowProc(wndProc, hwnd, nMsg, wParam, lParam);
-};
+}
// ----------------------------------------------------------------------------
// Find/replace dialog hook proc
return 0;
}
+// ----------------------------------------------------------------------------
+// wxFindReplaceData
+// ----------------------------------------------------------------------------
+
+void wxFindReplaceData::Init()
+{
+ m_Flags = 0;
+}
+
// ============================================================================
// wxFindReplaceDialog implementation
// ============================================================================
wxFindReplaceDialog::wxFindReplaceDialog(wxWindow *parent,
wxFindReplaceData *data,
- const wxString &title)
+ const wxString &title,
+ int flags)
: m_FindReplaceData(data)
{
Init();
- (void)Create(parent, data, title);
+ (void)Create(parent, data, title, flags);
}
wxFindReplaceDialog::~wxFindReplaceDialog()
{
+ // unsubclass the parent
delete m_impl;
+
+ // prevent the base class dtor from trying to hide us!
+ m_isShown = FALSE;
+
+ // and from destroying our window
+ m_hWnd = NULL;
}
bool wxFindReplaceDialog::Create(wxWindow *parent,
wxFindReplaceData *data,
- const wxString &title)
+ const wxString &title,
+ int flags)
{
+ m_windowStyle = flags;
m_FindReplaceData = data;
m_parent = parent;
if ( m_hWnd )
{
// yes, just use it
- return ::ShowWindow(GetHwnd(), show ? SW_SHOW : SW_HIDE);
+ (void)::ShowWindow(GetHwnd(), show ? SW_SHOW : SW_HIDE);
+
+ return TRUE;
}
if ( !show )
wxASSERT_MSG( !m_impl, _T("why don't we have the window then?") );
- int flagsWX = m_FindReplaceData->GetFlags();
-
- m_impl = new wxFindReplaceDialogImpl(this, flagsWX);
+ m_impl = new wxFindReplaceDialogImpl(this, m_FindReplaceData->GetFlags());
m_impl->InitFindWhat(m_FindReplaceData->GetFindString());
- if ( flagsWX & wxFR_REPLACEDIALOG)
+ bool replace = HasFlag(wxFR_REPLACEDIALOG);
+ if ( replace )
{
- m_impl->InitFindWhat(m_FindReplaceData->GetReplaceString());
+ m_impl->InitReplaceWith(m_FindReplaceData->GetReplaceString());
}
// call the right function to show the dialog which does what we want
- HWND (*pfn)(FINDREPLACE *) = flagsWX & wxFR_REPLACEDIALOG ? ::ReplaceText
- : ::FindText;
- m_hWnd = (WXHWND)(*pfn)(m_impl->GetPtrFindReplace());
- if ( !m_hWnd )
+ FINDREPLACE *pFR = m_impl->GetPtrFindReplace();
+ HWND hwnd;
+ if ( replace )
+ hwnd = ::ReplaceText(pFR);
+ else
+ hwnd = ::FindText(pFR);
+
+ if ( !hwnd )
{
wxLogError(_("Failed to create the standard find/replace dialog (error code %d)"),
::CommDlgExtendedError());
// subclass parent window in order to get FINDMSGSTRING message
m_impl->SubclassDialog(GetHwndOf(m_parent));
- if ( !::ShowWindow((HWND)m_hWnd, SW_SHOW) )
+ if ( !::ShowWindow(hwnd, SW_SHOW) )
{
wxLogLastError(_T("ShowWindow(find dialog)"));
}
+ m_hWnd = (WXHWND)hwnd;
+
return TRUE;
}
// ----------------------------------------------------------------------------
extern wxWindowList wxModelessWindows;
-extern wxList WXDLLEXPORT wxPendingDelete;
extern const wxChar *wxFrameClassName;
#if wxUSE_MENUS_NATIVE
wxMenu *wxCurrentPopupMenu = NULL;
#endif // wxUSE_MENUS_NATIVE
-extern wxList WXDLLEXPORT wxPendingDelete;
extern const wxChar *wxCanvasClassName;
// ---------------------------------------------------------------------------
#endif // wxUSE_SPINCTRL
#endif // Win32
-
- if ( !win )
- {
- // hwnd is not a wxWindow, try its parent next below
- hwnd = ::GetParent(hwnd);
- }
}
}
while ( hwnd && !win )
{
- win = wxFindWinFromHandle((WXHWND)hwnd);
+ // this is a really ugly hack needed to avoid mistakenly returning the
+ // parent frame wxWindow for the find/replace modeless dialog HWND -
+ // this, in turn, is needed to call IsDialogMessage() from
+ // wxApp::ProcessMessage() as for this we must return NULL from here
+ //
+ // FIXME: this is clearly not the best way to do it but I think we'll
+ // need to change HWND <-> wxWindow code more heavily than I can
+ // do it now to fix it
+ if ( ::GetWindow(hwnd, GW_OWNER) )
+ {
+ // it's a dialog box, don't go upwards
+ break;
+ }
+
hwnd = ::GetParent(hwnd);
+ win = wxFindWinFromHandle((WXHWND)hwnd);
}
return win;