1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/fdrepdlg.cpp
3 // Purpose: wxFindReplaceDialog class
4 // Author: Markus Greither and Vadim Zeitlin
8 // Copyright: (c) Markus Greither
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
30 #include "wx/msw/wrapcdlg.h"
35 #include "wx/fdrepdlg.h"
37 #include "wx/msw/mslu.h"
39 // ----------------------------------------------------------------------------
40 // functions prototypes
41 // ----------------------------------------------------------------------------
43 UINT_PTR CALLBACK
wxFindReplaceDialogHookProc(HWND hwnd
,
48 // ----------------------------------------------------------------------------
50 // ----------------------------------------------------------------------------
52 IMPLEMENT_DYNAMIC_CLASS(wxFindReplaceDialog
, wxDialog
)
54 // ----------------------------------------------------------------------------
55 // wxFindReplaceDialogImpl: the internals of wxFindReplaceDialog
56 // ----------------------------------------------------------------------------
58 class WXDLLEXPORT wxFindReplaceDialogImpl
61 wxFindReplaceDialogImpl(wxFindReplaceDialog
*dialog
, int flagsWX
);
62 ~wxFindReplaceDialogImpl();
64 void InitFindWhat(const wxString
& str
);
65 void InitReplaceWith(const wxString
& str
);
67 // only for passing to ::FindText or ::ReplaceText
68 FINDREPLACE
*GetPtrFindReplace() { return &m_findReplace
; }
70 // set/query the "closed by user" flag
71 void SetClosedByUser() { m_wasClosedByUser
= true; }
72 bool WasClosedByUser() const { return m_wasClosedByUser
; }
75 // called from window procedure for ms_msgFindDialog
76 static bool FindMessageHandler(wxWindow
*win
,
81 // copy string str contents to ppStr and fill pLen with its length
82 void InitString(const wxString
& str
, LPTSTR
*ppStr
, WORD
*pLen
);
85 // the find replace data used by the dialog
86 FINDREPLACE m_findReplace
;
88 // true if the user closed us, false otherwise
89 bool m_wasClosedByUser
;
91 // registered Message for Dialog
92 static UINT ms_msgFindDialog
;
94 wxDECLARE_NO_COPY_CLASS(wxFindReplaceDialogImpl
);
97 UINT
wxFindReplaceDialogImpl::ms_msgFindDialog
= 0;
99 // ============================================================================
101 // ============================================================================
103 // ----------------------------------------------------------------------------
104 // wxFindReplaceDialogImpl
105 // ----------------------------------------------------------------------------
107 wxFindReplaceDialogImpl::wxFindReplaceDialogImpl(wxFindReplaceDialog
*dialog
,
110 // get the identifier for the find dialog message if we don't have it yet
111 if ( !ms_msgFindDialog
)
113 ms_msgFindDialog
= ::RegisterWindowMessage(FINDMSGSTRING
);
115 if ( !ms_msgFindDialog
)
117 wxLogLastError(wxT("RegisterWindowMessage(FINDMSGSTRING)"));
120 wxWindow::MSWRegisterMessageHandler
123 &wxFindReplaceDialogImpl::FindMessageHandler
127 m_wasClosedByUser
= false;
129 wxZeroMemory(m_findReplace
);
131 // translate the flags: first the dialog creation flags
133 // always set this to be able to set the title
134 int flags
= FR_ENABLEHOOK
;
136 int flagsDialog
= dialog
->GetWindowStyle();
137 if ( flagsDialog
& wxFR_NOMATCHCASE
)
138 flags
|= FR_NOMATCHCASE
;
139 if ( flagsDialog
& wxFR_NOWHOLEWORD
)
140 flags
|= FR_NOWHOLEWORD
;
141 if ( flagsDialog
& wxFR_NOUPDOWN
)
142 flags
|= FR_NOUPDOWN
;
144 // and now the flags governing the initial values of the dialogs controls
145 if ( flagsWX
& wxFR_DOWN
)
147 if ( flagsWX
& wxFR_MATCHCASE
)
148 flags
|= FR_MATCHCASE
;
149 if ( flagsWX
& wxFR_WHOLEWORD
)
150 flags
|= FR_WHOLEWORD
;
152 m_findReplace
.lStructSize
= sizeof(FINDREPLACE
);
153 m_findReplace
.hwndOwner
= GetHwndOf(dialog
->GetParent());
154 m_findReplace
.Flags
= flags
;
156 m_findReplace
.lCustData
= (LPARAM
)dialog
;
157 m_findReplace
.lpfnHook
= wxFindReplaceDialogHookProc
;
160 void wxFindReplaceDialogImpl::InitString(const wxString
& str
,
161 LPTSTR
*ppStr
, WORD
*pLen
)
163 size_t len
= str
.length() + 1;
166 // MSDN docs say that the buffer must be at least 80 chars
170 *ppStr
= new wxChar
[len
];
171 wxStrcpy(*ppStr
, str
);
175 void wxFindReplaceDialogImpl::InitFindWhat(const wxString
& str
)
177 InitString(str
, &m_findReplace
.lpstrFindWhat
, &m_findReplace
.wFindWhatLen
);
180 void wxFindReplaceDialogImpl::InitReplaceWith(const wxString
& str
)
183 &m_findReplace
.lpstrReplaceWith
,
184 &m_findReplace
.wReplaceWithLen
);
187 wxFindReplaceDialogImpl::~wxFindReplaceDialogImpl()
189 delete [] m_findReplace
.lpstrFindWhat
;
190 delete [] m_findReplace
.lpstrReplaceWith
;
193 // ----------------------------------------------------------------------------
194 // handler for FINDMSGSTRING message
195 // ----------------------------------------------------------------------------
198 wxFindReplaceDialogImpl::FindMessageHandler(wxWindow
* WXUNUSED(win
),
199 WXUINT
WXUNUSED_UNLESS_DEBUG(nMsg
),
200 WPARAM
WXUNUSED(wParam
),
203 #if wxUSE_UNICODE_MSLU
204 static unsigned long s_lastMsgFlags
= 0;
206 // This flag helps us to identify the bogus ANSI message
207 // sent by UNICOWS.DLL (see below)
208 // while we're sending our message to the dialog
209 // we ignore possible messages sent in between
210 static bool s_blockMsg
= false;
211 #endif // wxUSE_UNICODE_MSLU
213 wxASSERT_MSG( nMsg
== ms_msgFindDialog
, wxT("unexpected message received") );
215 FINDREPLACE
*pFR
= (FINDREPLACE
*)lParam
;
217 #if wxUSE_UNICODE_MSLU
218 // This is a hack for a MSLU problem: Versions up to 1.0.4011
219 // of UNICOWS.DLL send the correct UNICODE item after button press
220 // and a bogus ANSI mode item right after this, so lets ignore
221 // the second bogus message
222 if ( wxUsingUnicowsDll() && s_lastMsgFlags
== pFR
->Flags
)
227 s_lastMsgFlags
= pFR
->Flags
;
228 #endif // wxUSE_UNICODE_MSLU
230 wxFindReplaceDialog
*dialog
= (wxFindReplaceDialog
*)pFR
->lCustData
;
232 // map flags from Windows
235 bool replace
= false;
236 if ( pFR
->Flags
& FR_DIALOGTERM
)
238 // we have to notify the dialog that it's being closed by user and
239 // not deleted programmatically as it behaves differently in these
241 dialog
->GetImpl()->SetClosedByUser();
243 evtType
= wxEVT_COMMAND_FIND_CLOSE
;
245 else if ( pFR
->Flags
& FR_FINDNEXT
)
247 evtType
= wxEVT_COMMAND_FIND_NEXT
;
249 else if ( pFR
->Flags
& FR_REPLACE
)
251 evtType
= wxEVT_COMMAND_FIND_REPLACE
;
255 else if ( pFR
->Flags
& FR_REPLACEALL
)
257 evtType
= wxEVT_COMMAND_FIND_REPLACE_ALL
;
263 wxFAIL_MSG( wxT("unknown find dialog event") );
269 if ( pFR
->Flags
& FR_DOWN
)
271 if ( pFR
->Flags
& FR_WHOLEWORD
)
272 flags
|= wxFR_WHOLEWORD
;
273 if ( pFR
->Flags
& FR_MATCHCASE
)
274 flags
|= wxFR_MATCHCASE
;
276 wxFindDialogEvent
event(evtType
, dialog
->GetId());
277 event
.SetEventObject(dialog
);
278 event
.SetFlags(flags
);
279 event
.SetFindString(pFR
->lpstrFindWhat
);
282 event
.SetReplaceString(pFR
->lpstrReplaceWith
);
285 #if wxUSE_UNICODE_MSLU
287 #endif // wxUSE_UNICODE_MSLU
291 #if wxUSE_UNICODE_MSLU
293 #endif // wxUSE_UNICODE_MSLU
298 // ----------------------------------------------------------------------------
299 // Find/replace dialog hook proc
300 // ----------------------------------------------------------------------------
303 wxFindReplaceDialogHookProc(HWND hwnd
,
305 WPARAM
WXUNUSED(wParam
),
308 if ( uiMsg
== WM_INITDIALOG
)
310 FINDREPLACE
*pFR
= (FINDREPLACE
*)lParam
;
311 wxFindReplaceDialog
*dialog
= (wxFindReplaceDialog
*)pFR
->lCustData
;
313 ::SetWindowText(hwnd
, dialog
->GetTitle().wx_str());
315 // don't return FALSE from here or the dialog won't be shown
322 // ============================================================================
323 // wxFindReplaceDialog implementation
324 // ============================================================================
326 // ----------------------------------------------------------------------------
327 // wxFindReplaceDialog ctors/dtor
328 // ----------------------------------------------------------------------------
330 void wxFindReplaceDialog::Init()
333 m_FindReplaceData
= NULL
;
335 // as we're created in the hidden state, bring the internal flag in sync
339 wxFindReplaceDialog::wxFindReplaceDialog(wxWindow
*parent
,
340 wxFindReplaceData
*data
,
341 const wxString
&title
,
343 : wxFindReplaceDialogBase(parent
, data
, title
, flags
)
347 (void)Create(parent
, data
, title
, flags
);
350 wxFindReplaceDialog::~wxFindReplaceDialog()
354 // the dialog might have been already deleted if the user closed it
355 // manually but in this case we should have got a notification about it
356 // and the flag must have been set
357 if ( !m_impl
->WasClosedByUser() )
359 // if it wasn't, delete the dialog ourselves
360 if ( !::DestroyWindow(GetHwnd()) )
362 wxLogLastError(wxT("DestroyWindow(find dialog)"));
366 // unsubclass the parent
370 // prevent the base class dtor from trying to hide us!
373 // and from destroying our window [again]
374 m_hWnd
= (WXHWND
)NULL
;
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 // wxFindReplaceData show/hide
394 // ----------------------------------------------------------------------------
396 bool wxFindReplaceDialog::Show(bool show
)
398 if ( !wxWindowBase::Show(show
) )
400 // visibility status didn't change
404 // do we already have the dialog window?
408 (void)::ShowWindow(GetHwnd(), show
? SW_SHOW
: SW_HIDE
);
415 // well, it doesn't exist which is as good as being hidden
419 wxCHECK_MSG( m_FindReplaceData
, false, wxT("call Create() first!") );
421 wxASSERT_MSG( !m_impl
, wxT("why don't we have the window then?") );
423 m_impl
= new wxFindReplaceDialogImpl(this, m_FindReplaceData
->GetFlags());
425 m_impl
->InitFindWhat(m_FindReplaceData
->GetFindString());
427 bool replace
= HasFlag(wxFR_REPLACEDIALOG
);
430 m_impl
->InitReplaceWith(m_FindReplaceData
->GetReplaceString());
433 // call the right function to show the dialog which does what we want
434 FINDREPLACE
*pFR
= m_impl
->GetPtrFindReplace();
437 hwnd
= ::ReplaceText(pFR
);
439 hwnd
= ::FindText(pFR
);
443 wxLogError(_("Failed to create the standard find/replace dialog (error code %d)"),
444 ::CommDlgExtendedError());
451 if ( !::ShowWindow(hwnd
, SW_SHOW
) )
453 wxLogLastError(wxT("ShowWindow(find dialog)"));
456 m_hWnd
= (WXHWND
)hwnd
;
461 // ----------------------------------------------------------------------------
462 // wxFindReplaceDialog title handling
463 // ----------------------------------------------------------------------------
465 // we set the title of this dialog in our jook proc but for now don't crash in
466 // the base class version because of m_hWnd == 0
468 void wxFindReplaceDialog::SetTitle( const wxString
& title
)
473 wxString
wxFindReplaceDialog::GetTitle() const
478 // ----------------------------------------------------------------------------
479 // wxFindReplaceDialog position/size
480 // ----------------------------------------------------------------------------
482 void wxFindReplaceDialog::DoSetSize(int WXUNUSED(x
), int WXUNUSED(y
),
483 int WXUNUSED(width
), int WXUNUSED(height
),
484 int WXUNUSED(sizeFlags
))
486 // ignore - we can't change the size of this standard dialog
490 // NB: of course, both of these functions are completely bogus, but it's better
492 void wxFindReplaceDialog::DoGetSize(int *width
, int *height
) const
494 // the standard dialog size
501 void wxFindReplaceDialog::DoGetClientSize(int *width
, int *height
) const
503 // the standard dialog size
510 #endif // wxUSE_FINDREPLDLG