1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/fdrepdlg.cpp
3 // Purpose: wxFindReplaceDialog class
4 // Author: Markus Greither
5 // Modified by: 31.07.01: VZ: integrated into wxWindows
8 // Copyright: (c) Markus Greither
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
21 #pragma implementation "fdrepdlg.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
38 #include "wx/msw/private.h"
40 #if !defined(__WIN32__) || defined(__SALFORDC__) || defined(__WXWINE__)
44 #include "wx/fdrepdlg.h"
46 // ----------------------------------------------------------------------------
47 // functions prototypes
48 // ----------------------------------------------------------------------------
50 LRESULT APIENTRY
wxFindReplaceWindowProc(HWND hwnd
, WXUINT nMsg
,
51 WPARAM wParam
, LPARAM lParam
);
53 UINT CALLBACK
wxFindReplaceDialogHookProc(HWND hwnd
,
58 // ----------------------------------------------------------------------------
60 // ----------------------------------------------------------------------------
62 IMPLEMENT_DYNAMIC_CLASS(wxFindReplaceDialog
, wxDialog
)
64 IMPLEMENT_DYNAMIC_CLASS(wxFindDialogEvent
, wxCommandEvent
)
66 DEFINE_EVENT_TYPE(wxEVT_COMMAND_FIND
)
67 DEFINE_EVENT_TYPE(wxEVT_COMMAND_FIND_NEXT
)
68 DEFINE_EVENT_TYPE(wxEVT_COMMAND_FIND_REPLACE
)
69 DEFINE_EVENT_TYPE(wxEVT_COMMAND_FIND_REPLACE_ALL
)
70 DEFINE_EVENT_TYPE(wxEVT_COMMAND_FIND_CLOSE
)
72 // ----------------------------------------------------------------------------
73 // wxFindReplaceDialogImpl: the internals of wxFindReplaceDialog
74 // ----------------------------------------------------------------------------
76 class WXDLLEXPORT wxFindReplaceDialogImpl
79 wxFindReplaceDialogImpl(wxFindReplaceDialog
*dialog
, int flagsWX
);
80 ~wxFindReplaceDialogImpl();
82 void InitFindWhat(const wxString
& str
);
83 void InitReplaceWith(const wxString
& str
);
85 void SubclassDialog(HWND hwnd
);
87 static UINT
GetFindDialogMessage() { return ms_msgFindDialog
; }
89 // only for passing to ::FindText or ::ReplaceText
90 FINDREPLACE
*GetPtrFindReplace() { return &m_findReplace
; }
93 void InitString(const wxString
& str
, LPTSTR
*ppStr
, WORD
*pLen
);
95 // the owner of the dialog
98 // the previous window proc of our owner
99 WNDPROC m_oldParentWndProc
;
101 // the find replace data used by the dialog
102 FINDREPLACE m_findReplace
;
104 // registered Message for Dialog
105 static UINT ms_msgFindDialog
;
108 UINT
wxFindReplaceDialogImpl::ms_msgFindDialog
= 0;
110 // ============================================================================
112 // ============================================================================
114 // ----------------------------------------------------------------------------
115 // wxFindReplaceDialogImpl
116 // ----------------------------------------------------------------------------
118 wxFindReplaceDialogImpl::wxFindReplaceDialogImpl(wxFindReplaceDialog
*dialog
,
121 // get the identifier for the find dialog message if we don't have it yet
122 if ( !ms_msgFindDialog
)
124 ms_msgFindDialog
= ::RegisterWindowMessage(FINDMSGSTRING
);
126 if ( !ms_msgFindDialog
)
128 wxLogLastError(_T("RegisterWindowMessage(FINDMSGSTRING)"));
133 m_oldParentWndProc
= NULL
;
135 wxZeroMemory(m_findReplace
);
137 // translate the flags: first the dialog creation flags
139 // always set this to be able to set the title
140 int flags
= FR_ENABLEHOOK
;
142 int flagsDialog
= dialog
->GetWindowStyle();
143 if ( flagsDialog
& wxFR_NOMATCHCASE
)
144 flags
|= FR_NOMATCHCASE
;
145 if ( flagsDialog
& wxFR_NOWHOLEWORD
)
146 flags
|= FR_NOWHOLEWORD
;
147 if ( flagsDialog
& wxFR_NOUPDOWN
)
148 flags
|= FR_NOUPDOWN
;
150 // and now the flags governing the initial values of the dialogs controls
151 if ( flagsWX
& wxFR_DOWN
)
153 if ( flagsWX
& wxFR_MATCHCASE
)
154 flags
|= FR_MATCHCASE
;
155 if ( flagsWX
& wxFR_WHOLEWORD
)
156 flags
|= FR_WHOLEWORD
;
158 m_findReplace
.lStructSize
= sizeof(FINDREPLACE
);
159 m_findReplace
.hwndOwner
= GetHwndOf(dialog
->GetParent());
160 m_findReplace
.Flags
= flags
;
162 m_findReplace
.lCustData
= (LPARAM
)dialog
;
163 m_findReplace
.lpfnHook
= wxFindReplaceDialogHookProc
;
166 void wxFindReplaceDialogImpl::InitString(const wxString
& str
,
167 LPTSTR
*ppStr
, WORD
*pLen
)
169 size_t len
= str
.length() + 1;
172 // MSDN docs say that the buffer must be at least 80 chars
176 *ppStr
= new wxChar
[len
];
177 wxStrcpy(*ppStr
, str
);
181 void wxFindReplaceDialogImpl::InitFindWhat(const wxString
& str
)
183 InitString(str
, &m_findReplace
.lpstrFindWhat
, &m_findReplace
.wFindWhatLen
);
186 void wxFindReplaceDialogImpl::InitReplaceWith(const wxString
& str
)
189 &m_findReplace
.lpstrReplaceWith
,
190 &m_findReplace
.wReplaceWithLen
);
193 void wxFindReplaceDialogImpl::SubclassDialog(HWND hwnd
)
197 // check that we don't subclass the parent twice: this would be a bad idea
198 // as then we'd have infinite recursion in wxFindReplaceWindowProc
199 WNDPROC oldParentWndProc
= (WNDPROC
)::GetWindowLong(hwnd
, GWL_WNDPROC
);
201 if ( oldParentWndProc
!= wxFindReplaceWindowProc
)
203 // save old wnd proc elsewhere to access it from
204 // wxFindReplaceWindowProc
205 m_oldParentWndProc
= oldParentWndProc
;
206 (void)::SetWindowLong(hwnd
, GWL_USERDATA
, (LONG
)oldParentWndProc
);
208 // and set the new one
209 (void)::SetWindowLong(hwnd
, GWL_WNDPROC
, (LONG
)wxFindReplaceWindowProc
);
213 wxFindReplaceDialogImpl::~wxFindReplaceDialogImpl()
215 delete [] m_findReplace
.lpstrFindWhat
;
216 delete [] m_findReplace
.lpstrReplaceWith
;
220 ::SetWindowLong(m_hwndOwner
, GWL_WNDPROC
, (LONG
)m_oldParentWndProc
);
224 // ----------------------------------------------------------------------------
225 // Window Proc for handling RegisterWindowMessage(FINDMSGSTRING)
226 // ----------------------------------------------------------------------------
228 LRESULT APIENTRY
wxFindReplaceWindowProc(HWND hwnd
, WXUINT nMsg
,
229 WPARAM wParam
, LPARAM lParam
)
231 if ( nMsg
== wxFindReplaceDialogImpl::GetFindDialogMessage() )
233 FINDREPLACE
*pFR
= (FINDREPLACE
*)lParam
;
234 wxFindReplaceDialog
*dialog
= (wxFindReplaceDialog
*)pFR
->lCustData
;
236 // map flags from Windows
239 bool replace
= FALSE
;
240 if ( pFR
->Flags
& FR_DIALOGTERM
)
242 evtType
= wxEVT_COMMAND_FIND_CLOSE
;
244 else if ( pFR
->Flags
& FR_FINDNEXT
)
246 evtType
= wxEVT_COMMAND_FIND_NEXT
;
248 else if ( pFR
->Flags
& FR_REPLACE
)
250 evtType
= wxEVT_COMMAND_FIND_REPLACE
;
254 else if ( pFR
->Flags
& FR_REPLACEALL
)
256 evtType
= wxEVT_COMMAND_FIND_REPLACE_ALL
;
262 wxFAIL_MSG( _T("unknown find dialog event") );
268 if ( pFR
->Flags
& FR_DOWN
)
270 if ( pFR
->Flags
& FR_WHOLEWORD
)
271 flags
|= wxFR_WHOLEWORD
;
272 if ( pFR
->Flags
& FR_MATCHCASE
)
273 flags
|= wxFR_MATCHCASE
;
275 wxFindDialogEvent
event(evtType
, dialog
->GetId());
276 event
.SetEventObject(dialog
);
277 event
.SetFlags(flags
);
278 event
.SetFindString(pFR
->lpstrFindWhat
);
281 event
.SetReplaceString(pFR
->lpstrReplaceWith
);
284 // TODO: should we copy the strings to dialog->GetData() as well?
286 if ( !dialog
->GetEventHandler()->ProcessEvent(event
) )
288 // the event is not propagated upwards to the parent automatically
289 // because the dialog is a top level window, so do it manually as
290 // in 9 cases of 10 the message must be processed by the dialog
291 // owner and not the dialog itself
292 (void)dialog
->GetParent()->GetEventHandler()->ProcessEvent(event
);
296 WNDPROC wndProc
= (WNDPROC
)::GetWindowLong(hwnd
, GWL_USERDATA
);
299 wxASSERT_MSG( wndProc
!= wxFindReplaceWindowProc
,
300 _T("infinite recursion detected") );
302 return ::CallWindowProc(wndProc
, hwnd
, nMsg
, wParam
, lParam
);
305 // ----------------------------------------------------------------------------
306 // Find/replace dialog hook proc
307 // ----------------------------------------------------------------------------
309 UINT CALLBACK
wxFindReplaceDialogHookProc(HWND hwnd
,
311 WPARAM
WXUNUSED(wParam
),
314 if ( uiMsg
== WM_INITDIALOG
)
316 FINDREPLACE
*pFR
= (FINDREPLACE
*)lParam
;
317 wxFindReplaceDialog
*dialog
= (wxFindReplaceDialog
*)pFR
->lCustData
;
319 ::SetWindowText(hwnd
, dialog
->GetTitle());
321 // don't return FALSE from here or the dialog won't be shown
328 // ----------------------------------------------------------------------------
330 // ----------------------------------------------------------------------------
332 void wxFindReplaceData::Init()
337 // ============================================================================
338 // wxFindReplaceDialog implementation
339 // ============================================================================
341 // ----------------------------------------------------------------------------
342 // wxFindReplaceDialog ctors/dtor
343 // ----------------------------------------------------------------------------
345 void wxFindReplaceDialog::Init()
348 m_FindReplaceData
= NULL
;
350 // as we're created in the hidden state, bring the internal flag in sync
354 wxFindReplaceDialog::wxFindReplaceDialog(wxWindow
*parent
,
355 wxFindReplaceData
*data
,
356 const wxString
&title
,
358 : m_FindReplaceData(data
)
362 (void)Create(parent
, data
, title
, flags
);
365 wxFindReplaceDialog::~wxFindReplaceDialog()
367 // unsubclass the parent
370 // prevent the base class dtor from trying to hide us!
373 // and from destroying our window
377 bool wxFindReplaceDialog::Create(wxWindow
*parent
,
378 wxFindReplaceData
*data
,
379 const wxString
&title
,
382 m_windowStyle
= flags
;
383 m_FindReplaceData
= data
;
388 // we must have a parent as it will get the messages from us
389 return parent
!= NULL
;
392 // ----------------------------------------------------------------------------
393 // wxFindReplaceDialog data access
394 // ----------------------------------------------------------------------------
396 void wxFindReplaceDialog::SetData(wxFindReplaceData
*data
)
398 delete m_FindReplaceData
;
399 m_FindReplaceData
= data
;
402 // ----------------------------------------------------------------------------
403 // wxFindReplaceData show/hide
404 // ----------------------------------------------------------------------------
406 bool wxFindReplaceDialog::Show(bool show
)
408 if ( !wxWindowBase::Show(show
) )
410 // visibility status didn't change
414 // do we already have the dialog window?
418 (void)::ShowWindow(GetHwnd(), show
? SW_SHOW
: SW_HIDE
);
425 // well, it doesn't exist which is as good as being hidden
429 wxCHECK_MSG( m_FindReplaceData
, FALSE
, _T("call Create() first!") );
431 wxASSERT_MSG( !m_impl
, _T("why don't we have the window then?") );
433 m_impl
= new wxFindReplaceDialogImpl(this, m_FindReplaceData
->GetFlags());
435 m_impl
->InitFindWhat(m_FindReplaceData
->GetFindString());
437 bool replace
= HasFlag(wxFR_REPLACEDIALOG
);
440 m_impl
->InitReplaceWith(m_FindReplaceData
->GetReplaceString());
443 // call the right function to show the dialog which does what we want
444 FINDREPLACE
*pFR
= m_impl
->GetPtrFindReplace();
447 hwnd
= ::ReplaceText(pFR
);
449 hwnd
= ::FindText(pFR
);
453 wxLogError(_("Failed to create the standard find/replace dialog (error code %d)"),
454 ::CommDlgExtendedError());
462 // subclass parent window in order to get FINDMSGSTRING message
463 m_impl
->SubclassDialog(GetHwndOf(m_parent
));
465 if ( !::ShowWindow(hwnd
, SW_SHOW
) )
467 wxLogLastError(_T("ShowWindow(find dialog)"));
470 m_hWnd
= (WXHWND
)hwnd
;
475 // ----------------------------------------------------------------------------
476 // wxFindReplaceDialog title handling
477 // ----------------------------------------------------------------------------
479 // we set the title of this dialog in our jook proc but for now don't crash in
480 // the base class version because of m_hWnd == 0
482 void wxFindReplaceDialog::SetTitle( const wxString
& title
)
487 wxString
wxFindReplaceDialog::GetTitle() const
492 // ----------------------------------------------------------------------------
493 // wxFindReplaceDialog position/size
494 // ----------------------------------------------------------------------------
496 void wxFindReplaceDialog::DoSetSize(int WXUNUSED(x
), int WXUNUSED(y
),
497 int WXUNUSED(width
), int WXUNUSED(height
),
498 int WXUNUSED(sizeFlags
))
500 // ignore - we can't change the size of this standard dialog
504 // NB: of course, both of these functions are completely bogus, but it's better
506 void wxFindReplaceDialog::DoGetSize(int *width
, int *height
) const
508 // the standard dialog size
515 void wxFindReplaceDialog::DoGetClientSize(int *width
, int *height
) const
517 // the standard dialog size
524 #endif // wxUSE_FINDREPLDLG