1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/fdrepdlg.cpp
3 // Purpose: wxFindReplaceDialog class
4 // Author: Markus Greither and Vadim Zeitlin
7 // Copyright: (c) Markus Greither
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
15 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
29 #include "wx/msw/wrapcdlg.h"
34 #include "wx/fdrepdlg.h"
36 #include "wx/msw/mslu.h"
38 // ----------------------------------------------------------------------------
39 // functions prototypes
40 // ----------------------------------------------------------------------------
42 UINT_PTR CALLBACK
wxFindReplaceDialogHookProc(HWND hwnd
,
47 // ----------------------------------------------------------------------------
49 // ----------------------------------------------------------------------------
51 IMPLEMENT_DYNAMIC_CLASS(wxFindReplaceDialog
, wxDialog
)
53 // ----------------------------------------------------------------------------
54 // wxFindReplaceDialogImpl: the internals of wxFindReplaceDialog
55 // ----------------------------------------------------------------------------
57 class WXDLLEXPORT wxFindReplaceDialogImpl
60 wxFindReplaceDialogImpl(wxFindReplaceDialog
*dialog
, int flagsWX
);
61 ~wxFindReplaceDialogImpl();
63 void InitFindWhat(const wxString
& str
);
64 void InitReplaceWith(const wxString
& str
);
66 // only for passing to ::FindText or ::ReplaceText
67 FINDREPLACE
*GetPtrFindReplace() { return &m_findReplace
; }
69 // set/query the "closed by user" flag
70 void SetClosedByUser() { m_wasClosedByUser
= true; }
71 bool WasClosedByUser() const { return m_wasClosedByUser
; }
74 // called from window procedure for ms_msgFindDialog
75 static bool FindMessageHandler(wxWindow
*win
,
80 // copy string str contents to ppStr and fill pLen with its length
81 void InitString(const wxString
& str
, LPTSTR
*ppStr
, WORD
*pLen
);
84 // the find replace data used by the dialog
85 FINDREPLACE m_findReplace
;
87 // true if the user closed us, false otherwise
88 bool m_wasClosedByUser
;
90 // registered Message for Dialog
91 static UINT ms_msgFindDialog
;
93 wxDECLARE_NO_COPY_CLASS(wxFindReplaceDialogImpl
);
96 UINT
wxFindReplaceDialogImpl::ms_msgFindDialog
= 0;
98 // ============================================================================
100 // ============================================================================
102 // ----------------------------------------------------------------------------
103 // wxFindReplaceDialogImpl
104 // ----------------------------------------------------------------------------
106 wxFindReplaceDialogImpl::wxFindReplaceDialogImpl(wxFindReplaceDialog
*dialog
,
109 // get the identifier for the find dialog message if we don't have it yet
110 if ( !ms_msgFindDialog
)
112 ms_msgFindDialog
= ::RegisterWindowMessage(FINDMSGSTRING
);
114 if ( !ms_msgFindDialog
)
116 wxLogLastError(wxT("RegisterWindowMessage(FINDMSGSTRING)"));
119 wxWindow::MSWRegisterMessageHandler
122 &wxFindReplaceDialogImpl::FindMessageHandler
126 m_wasClosedByUser
= false;
128 wxZeroMemory(m_findReplace
);
130 // translate the flags: first the dialog creation flags
132 // always set this to be able to set the title
133 int flags
= FR_ENABLEHOOK
;
135 int flagsDialog
= dialog
->GetWindowStyle();
136 if ( flagsDialog
& wxFR_NOMATCHCASE
)
137 flags
|= FR_NOMATCHCASE
;
138 if ( flagsDialog
& wxFR_NOWHOLEWORD
)
139 flags
|= FR_NOWHOLEWORD
;
140 if ( flagsDialog
& wxFR_NOUPDOWN
)
141 flags
|= FR_NOUPDOWN
;
143 // and now the flags governing the initial values of the dialogs controls
144 if ( flagsWX
& wxFR_DOWN
)
146 if ( flagsWX
& wxFR_MATCHCASE
)
147 flags
|= FR_MATCHCASE
;
148 if ( flagsWX
& wxFR_WHOLEWORD
)
149 flags
|= FR_WHOLEWORD
;
151 m_findReplace
.lStructSize
= sizeof(FINDREPLACE
);
152 m_findReplace
.hwndOwner
= GetHwndOf(dialog
->GetParent());
153 m_findReplace
.Flags
= flags
;
155 m_findReplace
.lCustData
= (LPARAM
)dialog
;
156 m_findReplace
.lpfnHook
= wxFindReplaceDialogHookProc
;
159 void wxFindReplaceDialogImpl::InitString(const wxString
& str
,
160 LPTSTR
*ppStr
, WORD
*pLen
)
162 size_t len
= str
.length() + 1;
165 // MSDN docs say that the buffer must be at least 80 chars
169 *ppStr
= new wxChar
[len
];
170 wxStrcpy(*ppStr
, str
);
174 void wxFindReplaceDialogImpl::InitFindWhat(const wxString
& str
)
176 InitString(str
, &m_findReplace
.lpstrFindWhat
, &m_findReplace
.wFindWhatLen
);
179 void wxFindReplaceDialogImpl::InitReplaceWith(const wxString
& str
)
182 &m_findReplace
.lpstrReplaceWith
,
183 &m_findReplace
.wReplaceWithLen
);
186 wxFindReplaceDialogImpl::~wxFindReplaceDialogImpl()
188 delete [] m_findReplace
.lpstrFindWhat
;
189 delete [] m_findReplace
.lpstrReplaceWith
;
192 // ----------------------------------------------------------------------------
193 // handler for FINDMSGSTRING message
194 // ----------------------------------------------------------------------------
197 wxFindReplaceDialogImpl::FindMessageHandler(wxWindow
* WXUNUSED(win
),
198 WXUINT
WXUNUSED_UNLESS_DEBUG(nMsg
),
199 WPARAM
WXUNUSED(wParam
),
202 #if wxUSE_UNICODE_MSLU
203 static unsigned long s_lastMsgFlags
= 0;
205 // This flag helps us to identify the bogus ANSI message
206 // sent by UNICOWS.DLL (see below)
207 // while we're sending our message to the dialog
208 // we ignore possible messages sent in between
209 static bool s_blockMsg
= false;
210 #endif // wxUSE_UNICODE_MSLU
212 wxASSERT_MSG( nMsg
== ms_msgFindDialog
, wxT("unexpected message received") );
214 FINDREPLACE
*pFR
= (FINDREPLACE
*)lParam
;
216 #if wxUSE_UNICODE_MSLU
217 // This is a hack for a MSLU problem: Versions up to 1.0.4011
218 // of UNICOWS.DLL send the correct UNICODE item after button press
219 // and a bogus ANSI mode item right after this, so let's ignore
220 // the second bogus message
221 if ( wxUsingUnicowsDll() && s_lastMsgFlags
== pFR
->Flags
)
226 s_lastMsgFlags
= pFR
->Flags
;
227 #endif // wxUSE_UNICODE_MSLU
229 wxFindReplaceDialog
*dialog
= (wxFindReplaceDialog
*)pFR
->lCustData
;
231 // map flags from Windows
234 bool replace
= false;
235 if ( pFR
->Flags
& FR_DIALOGTERM
)
237 // we have to notify the dialog that it's being closed by user and
238 // not deleted programmatically as it behaves differently in these
240 dialog
->GetImpl()->SetClosedByUser();
242 evtType
= wxEVT_FIND_CLOSE
;
244 else if ( pFR
->Flags
& FR_FINDNEXT
)
246 evtType
= wxEVT_FIND_NEXT
;
248 else if ( pFR
->Flags
& FR_REPLACE
)
250 evtType
= wxEVT_FIND_REPLACE
;
254 else if ( pFR
->Flags
& FR_REPLACEALL
)
256 evtType
= wxEVT_FIND_REPLACE_ALL
;
262 wxFAIL_MSG( wxT("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 #if wxUSE_UNICODE_MSLU
286 #endif // wxUSE_UNICODE_MSLU
290 #if wxUSE_UNICODE_MSLU
292 #endif // wxUSE_UNICODE_MSLU
297 // ----------------------------------------------------------------------------
298 // Find/replace dialog hook proc
299 // ----------------------------------------------------------------------------
302 wxFindReplaceDialogHookProc(HWND hwnd
,
304 WPARAM
WXUNUSED(wParam
),
307 if ( uiMsg
== WM_INITDIALOG
)
309 FINDREPLACE
*pFR
= (FINDREPLACE
*)lParam
;
310 wxFindReplaceDialog
*dialog
= (wxFindReplaceDialog
*)pFR
->lCustData
;
312 ::SetWindowText(hwnd
, dialog
->GetTitle().t_str());
314 // don't return FALSE from here or the dialog won't be shown
321 // ============================================================================
322 // wxFindReplaceDialog implementation
323 // ============================================================================
325 // ----------------------------------------------------------------------------
326 // wxFindReplaceDialog ctors/dtor
327 // ----------------------------------------------------------------------------
329 void wxFindReplaceDialog::Init()
332 m_FindReplaceData
= NULL
;
334 // as we're created in the hidden state, bring the internal flag in sync
338 wxFindReplaceDialog::wxFindReplaceDialog(wxWindow
*parent
,
339 wxFindReplaceData
*data
,
340 const wxString
&title
,
342 : wxFindReplaceDialogBase(parent
, data
, title
, flags
)
346 (void)Create(parent
, data
, title
, flags
);
349 wxFindReplaceDialog::~wxFindReplaceDialog()
353 // the dialog might have been already deleted if the user closed it
354 // manually but in this case we should have got a notification about it
355 // and the flag must have been set
356 if ( !m_impl
->WasClosedByUser() )
358 // if it wasn't, delete the dialog ourselves
359 if ( !::DestroyWindow(GetHwnd()) )
361 wxLogLastError(wxT("DestroyWindow(find dialog)"));
365 // unsubclass the parent
369 // prevent the base class dtor from trying to hide us!
372 // and from destroying our window [again]
373 m_hWnd
= (WXHWND
)NULL
;
376 bool wxFindReplaceDialog::Create(wxWindow
*parent
,
377 wxFindReplaceData
*data
,
378 const wxString
&title
,
381 m_windowStyle
= flags
;
382 m_FindReplaceData
= data
;
387 // we must have a parent as it will get the messages from us
388 return parent
!= NULL
;
391 // ----------------------------------------------------------------------------
392 // wxFindReplaceData show/hide
393 // ----------------------------------------------------------------------------
395 bool wxFindReplaceDialog::Show(bool show
)
397 if ( !wxWindowBase::Show(show
) )
399 // visibility status didn't change
403 // do we already have the dialog window?
407 (void)::ShowWindow(GetHwnd(), show
? SW_SHOW
: SW_HIDE
);
414 // well, it doesn't exist which is as good as being hidden
418 wxCHECK_MSG( m_FindReplaceData
, false, wxT("call Create() first!") );
420 wxASSERT_MSG( !m_impl
, wxT("why don't we have the window then?") );
422 m_impl
= new wxFindReplaceDialogImpl(this, m_FindReplaceData
->GetFlags());
424 m_impl
->InitFindWhat(m_FindReplaceData
->GetFindString());
426 bool replace
= HasFlag(wxFR_REPLACEDIALOG
);
429 m_impl
->InitReplaceWith(m_FindReplaceData
->GetReplaceString());
432 // call the right function to show the dialog which does what we want
433 FINDREPLACE
*pFR
= m_impl
->GetPtrFindReplace();
436 hwnd
= ::ReplaceText(pFR
);
438 hwnd
= ::FindText(pFR
);
442 wxLogError(_("Failed to create the standard find/replace dialog (error code %d)"),
443 ::CommDlgExtendedError());
450 if ( !::ShowWindow(hwnd
, SW_SHOW
) )
452 wxLogLastError(wxT("ShowWindow(find dialog)"));
455 m_hWnd
= (WXHWND
)hwnd
;
460 // ----------------------------------------------------------------------------
461 // wxFindReplaceDialog title handling
462 // ----------------------------------------------------------------------------
464 // we set the title of this dialog in our jook proc but for now don't crash in
465 // the base class version because of m_hWnd == 0
467 void wxFindReplaceDialog::SetTitle( const wxString
& title
)
472 wxString
wxFindReplaceDialog::GetTitle() const
477 // ----------------------------------------------------------------------------
478 // wxFindReplaceDialog position/size
479 // ----------------------------------------------------------------------------
481 void wxFindReplaceDialog::DoSetSize(int WXUNUSED(x
), int WXUNUSED(y
),
482 int WXUNUSED(width
), int WXUNUSED(height
),
483 int WXUNUSED(sizeFlags
))
485 // ignore - we can't change the size of this standard dialog
489 // NB: of course, both of these functions are completely bogus, but it's better
491 void wxFindReplaceDialog::DoGetSize(int *width
, int *height
) const
493 // the standard dialog size
500 void wxFindReplaceDialog::DoGetClientSize(int *width
, int *height
) const
502 // the standard dialog size
509 #endif // wxUSE_FINDREPLDLG