]> git.saurik.com Git - wxWidgets.git/blob - src/msw/fdrepdlg.cpp
wxWindowBase remembers title/label now
[wxWidgets.git] / src / msw / fdrepdlg.cpp
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
6 // Created: 23/03/2001
7 // RCS-ID:
8 // Copyright: (c) Markus Greither
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation "fdrepdlg.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #if wxUSE_FINDREPLDLG
32
33 #ifndef WX_PRECOMP
34 #include "wx/intl.h"
35 #include "wx/log.h"
36 #endif
37
38 #include "wx/msw/private.h"
39
40 #if !defined(__WIN32__) || defined(__SALFORDC__) || defined(__WXWINE__)
41 #include <commdlg.h>
42 #endif
43
44 #include "wx/fdrepdlg.h"
45
46 // ----------------------------------------------------------------------------
47 // functions prototypes
48 // ----------------------------------------------------------------------------
49
50 LRESULT APIENTRY FindReplaceWindowProc(HWND hwnd, WXUINT nMsg,
51 WPARAM wParam, LPARAM lParam);
52
53 UINT CALLBACK wxFindReplaceDialogHookProc(HWND hwnd,
54 UINT uiMsg,
55 WPARAM wParam,
56 LPARAM lParam);
57
58 // ----------------------------------------------------------------------------
59 // wxWin macros
60 // ----------------------------------------------------------------------------
61
62 IMPLEMENT_DYNAMIC_CLASS(wxFindReplaceDialog, wxDialog)
63
64 IMPLEMENT_DYNAMIC_CLASS(wxFindDialogEvent, wxCommandEvent)
65
66 // ----------------------------------------------------------------------------
67 // wxFindReplaceDialogImpl: the internals of wxFindReplaceDialog
68 // ----------------------------------------------------------------------------
69
70 class WXDLLEXPORT wxFindReplaceDialogImpl
71 {
72 public:
73 wxFindReplaceDialogImpl(wxFindReplaceDialog *dialog, int flagsWX);
74 ~wxFindReplaceDialogImpl();
75
76 void InitFindWhat(const wxString& str);
77 void InitReplaceWith(const wxString& str);
78
79 void SubclassDialog(HWND hwnd);
80
81 static UINT GetFindDialogMessage() { return ms_msgFindDialog; }
82
83 // only for passing to ::FindText or ::ReplaceText
84 FINDREPLACE *GetPtrFindReplace() { return &m_findReplace; }
85
86 private:
87 void InitString(const wxString& str, LPTSTR *ppStr, WORD *pLen);
88
89 // the owner of the dialog
90 HWND m_hwndOwner;
91
92 // the previous window proc of our owner
93 WNDPROC m_oldParentWndProc;
94
95 // the find replace data used by the dialog
96 FINDREPLACE m_findReplace;
97
98 // registered Message for Dialog
99 static UINT ms_msgFindDialog;
100 };
101
102 UINT wxFindReplaceDialogImpl::ms_msgFindDialog = 0;
103
104 // ============================================================================
105 // implementation
106 // ============================================================================
107
108 // ----------------------------------------------------------------------------
109 // wxFindReplaceDialogImpl
110 // ----------------------------------------------------------------------------
111
112 wxFindReplaceDialogImpl::wxFindReplaceDialogImpl(wxFindReplaceDialog *dialog,
113 int flagsWX)
114 {
115 // get the identifier for the find dialog message if we don't have it yet
116 if ( !ms_msgFindDialog )
117 {
118 ms_msgFindDialog = ::RegisterWindowMessage(FINDMSGSTRING);
119
120 if ( !ms_msgFindDialog )
121 {
122 wxLogLastError(_T("RegisterWindowMessage(FINDMSGSTRING)"));
123 }
124 }
125
126 m_hwndOwner = NULL;
127 m_oldParentWndProc = NULL;
128
129 wxZeroMemory(m_findReplace);
130
131 // translate the flags
132
133 // always set this to be able to set the title
134 int flags = FR_ENABLEHOOK;
135
136 if ( flagsWX & wxFR_NOMATCHCASE)
137 flags |= FR_NOMATCHCASE;
138 if ( flagsWX & wxFR_NOWHOLEWORD)
139 flags |= FR_NOWHOLEWORD;
140 if ( flagsWX & wxFR_NOUPDOWN)
141 flags |= FR_NOUPDOWN;
142 if ( flagsWX & wxFR_DOWN)
143 flags |= FR_DOWN;
144
145 m_findReplace.lStructSize = sizeof(FINDREPLACE);
146 m_findReplace.hwndOwner = GetHwndOf(dialog->GetParent());
147 m_findReplace.Flags = flags;
148
149 m_findReplace.lCustData = (LPARAM)dialog;
150 m_findReplace.lpfnHook = wxFindReplaceDialogHookProc;
151 }
152
153 void wxFindReplaceDialogImpl::InitString(const wxString& str,
154 LPTSTR *ppStr, WORD *pLen)
155 {
156 size_t len = str.length() + 1;
157 if ( len < 80 )
158 {
159 // MSDN docs say that the buffer must be at least 80 chars
160 len = 80;
161 }
162
163 *ppStr = new wxChar[len];
164 wxStrcpy(*ppStr, str);
165 *pLen = len;
166 }
167
168 void wxFindReplaceDialogImpl::InitFindWhat(const wxString& str)
169 {
170 InitString(str, &m_findReplace.lpstrFindWhat, &m_findReplace.wFindWhatLen);
171 }
172
173 void wxFindReplaceDialogImpl::InitReplaceWith(const wxString& str)
174 {
175 InitString(str,
176 &m_findReplace.lpstrReplaceWith,
177 &m_findReplace.wReplaceWithLen);
178 }
179
180 void wxFindReplaceDialogImpl::SubclassDialog(HWND hwnd)
181 {
182 m_hwndOwner = hwnd;
183 m_oldParentWndProc = (WNDPROC)::SetWindowLong
184 (
185 hwnd,
186 GWL_WNDPROC,
187 (LONG)FindReplaceWindowProc
188 );
189
190 // save it elsewhere to access it from FindReplaceWindowProc()
191 (void)::SetWindowLong(hwnd, GWL_USERDATA, (LONG)m_oldParentWndProc);
192 }
193
194 wxFindReplaceDialogImpl::~wxFindReplaceDialogImpl()
195 {
196 delete [] m_findReplace.lpstrFindWhat;
197 delete [] m_findReplace.lpstrReplaceWith;
198
199 if ( m_hwndOwner )
200 {
201 ::SetWindowLong(m_hwndOwner, GWL_WNDPROC, (LONG)m_oldParentWndProc);
202 }
203 }
204
205 // ----------------------------------------------------------------------------
206 // Window Proc for handling RegisterWindowMessage(FINDMSGSTRING)
207 // ----------------------------------------------------------------------------
208
209 LRESULT APIENTRY FindReplaceWindowProc(HWND hwnd, WXUINT nMsg,
210 WPARAM wParam, LPARAM lParam)
211 {
212 if ( nMsg == wxFindReplaceDialogImpl::GetFindDialogMessage() )
213 {
214 FINDREPLACE *pFR = (FINDREPLACE *)lParam;
215 wxFindReplaceDialog *dialog = (wxFindReplaceDialog *)pFR->lCustData;
216
217 // map flags from Windows
218 wxEventType evtType;
219
220 bool replace = FALSE;
221 if ( pFR->Flags & FR_DIALOGTERM )
222 {
223 evtType = wxEVT_COMMAND_FIND_CLOSE;
224 }
225 else if ( pFR->Flags & FR_FINDNEXT )
226 {
227 evtType = wxEVT_COMMAND_FIND_NEXT;
228 }
229 else if ( pFR->Flags & FR_REPLACE )
230 {
231 evtType = wxEVT_COMMAND_REPLACE;
232
233 replace = TRUE;
234 }
235 else if ( pFR->Flags & FR_REPLACEALL )
236 {
237 evtType = wxEVT_COMMAND_REPLACE_ALL;
238
239 replace = TRUE;
240 }
241 else
242 {
243 wxFAIL_MSG( _T("unknown find dialog event") );
244
245 return 0;
246 }
247
248 wxUint32 flags = 0;
249 if ( pFR->Flags & FR_DOWN )
250 flags |= wxFR_DOWN;
251 if ( pFR->Flags & FR_WHOLEWORD )
252 flags |= wxFR_WHOLEWORD;
253 if ( pFR->Flags & FR_MATCHCASE )
254 flags |= wxFR_MATCHCASE;
255
256 wxFindDialogEvent event(evtType, dialog->GetId());
257 event.SetFlags(flags);
258 event.SetFindString(pFR->lpstrFindWhat);
259 if ( replace )
260 {
261 event.SetReplaceString(pFR->lpstrReplaceWith);
262 }
263
264 (void)dialog->GetEventHandler()->ProcessEvent(event);
265 }
266
267 WNDPROC wndProc = (WNDPROC)::GetWindowLong(hwnd, GWL_USERDATA);
268
269 return ::CallWindowProc(wndProc, hwnd, nMsg, wParam, lParam);
270 };
271
272 // ----------------------------------------------------------------------------
273 // Find/replace dialog hook proc
274 // ----------------------------------------------------------------------------
275
276 UINT CALLBACK wxFindReplaceDialogHookProc(HWND hwnd,
277 UINT uiMsg,
278 WPARAM WXUNUSED(wParam),
279 LPARAM lParam)
280 {
281 if ( uiMsg == WM_INITDIALOG )
282 {
283 FINDREPLACE *pFR = (FINDREPLACE *)lParam;
284 wxFindReplaceDialog *dialog = (wxFindReplaceDialog *)pFR->lCustData;
285
286 ::SetWindowText(hwnd, dialog->GetTitle());
287
288 // don't return FALSE from here or the dialog won't be shown
289 return TRUE;
290 }
291
292 return 0;
293 }
294
295 // ============================================================================
296 // wxFindReplaceDialog implementation
297 // ============================================================================
298
299 // ----------------------------------------------------------------------------
300 // wxFindReplaceDialog ctors/dtor
301 // ----------------------------------------------------------------------------
302
303 void wxFindReplaceDialog::Init()
304 {
305 m_impl = NULL;
306 m_FindReplaceData = NULL;
307
308 // as we're created in the hidden state, bring the internal flag in sync
309 m_isShown = FALSE;
310 }
311
312 wxFindReplaceDialog::wxFindReplaceDialog(wxWindow *parent,
313 wxFindReplaceData *data,
314 const wxString &title)
315 : m_FindReplaceData(data)
316 {
317 Init();
318
319 (void)Create(parent, data, title);
320 }
321
322 wxFindReplaceDialog::~wxFindReplaceDialog()
323 {
324 delete m_impl;
325 }
326
327 bool wxFindReplaceDialog::Create(wxWindow *parent,
328 wxFindReplaceData *data,
329 const wxString &title)
330 {
331 m_FindReplaceData = data;
332 m_parent = parent;
333
334 SetTitle(title);
335
336 // we must have a parent as it will get the messages from us
337 return parent != NULL;
338 }
339
340 // ----------------------------------------------------------------------------
341 // wxFindReplaceDialog data access
342 // ----------------------------------------------------------------------------
343
344 void wxFindReplaceDialog::SetData(wxFindReplaceData *data)
345 {
346 delete m_FindReplaceData;
347 m_FindReplaceData = data;
348 }
349
350 // ----------------------------------------------------------------------------
351 // wxFindReplaceData show/hide
352 // ----------------------------------------------------------------------------
353
354 bool wxFindReplaceDialog::Show(bool show)
355 {
356 if ( !wxWindowBase::Show(show) )
357 {
358 // visibility status didn't change
359 return FALSE;
360 }
361
362 // do we already have the dialog window?
363 if ( m_hWnd )
364 {
365 // yes, just use it
366 return ::ShowWindow(GetHwnd(), show ? SW_SHOW : SW_HIDE);
367 }
368
369 if ( !show )
370 {
371 // well, it doesn't exist which is as good as being hidden
372 return TRUE;
373 }
374
375 wxCHECK_MSG( m_FindReplaceData, FALSE, _T("call Create() first!") );
376
377 wxASSERT_MSG( !m_impl, _T("why don't we have the window then?") );
378
379 int flagsWX = m_FindReplaceData->GetFlags();
380
381 m_impl = new wxFindReplaceDialogImpl(this, flagsWX);
382
383 m_impl->InitFindWhat(m_FindReplaceData->GetFindString());
384
385 if ( flagsWX & wxFR_REPLACEDIALOG)
386 {
387 m_impl->InitFindWhat(m_FindReplaceData->GetReplaceString());
388 }
389
390 // call the right function to show the dialog which does what we want
391 HWND (*pfn)(FINDREPLACE *) = flagsWX & wxFR_REPLACEDIALOG ? ::ReplaceText
392 : ::FindText;
393 m_hWnd = (WXHWND)(*pfn)(m_impl->GetPtrFindReplace());
394 if ( !m_hWnd )
395 {
396 wxLogError(_("Failed to create the standard find/replace dialog (error code %d)"),
397 ::CommDlgExtendedError());
398
399 delete m_impl;
400 m_impl = NULL;
401
402 return FALSE;
403 }
404
405 // subclass parent window in order to get FINDMSGSTRING message
406 m_impl->SubclassDialog(GetHwndOf(m_parent));
407
408 if ( !::ShowWindow((HWND)m_hWnd, SW_SHOW) )
409 {
410 wxLogLastError(_T("ShowWindow(find dialog)"));
411 }
412
413 return TRUE;
414 }
415
416 // ----------------------------------------------------------------------------
417 // wxFindReplaceDialog title handling
418 // ----------------------------------------------------------------------------
419
420 // we set the title of this dialog in our jook proc but for now don't crash in
421 // the base class version because of m_hWnd == 0
422
423 void wxFindReplaceDialog::SetTitle( const wxString& title)
424 {
425 m_title = title;
426 }
427
428 wxString wxFindReplaceDialog::GetTitle() const
429 {
430 return m_title;
431 }
432
433 // ----------------------------------------------------------------------------
434 // wxFindReplaceDialog position/size
435 // ----------------------------------------------------------------------------
436
437 void wxFindReplaceDialog::DoSetSize(int WXUNUSED(x), int WXUNUSED(y),
438 int WXUNUSED(width), int WXUNUSED(height),
439 int WXUNUSED(sizeFlags))
440 {
441 // ignore - we can't change the size of this standard dialog
442 return;
443 }
444
445 // NB: of course, both of these functions are completely bogus, but it's better
446 // than nothing
447 void wxFindReplaceDialog::DoGetSize(int *width, int *height) const
448 {
449 // the standard dialog size
450 if ( width )
451 *width = 225;
452 if ( height )
453 *height = 324;
454 }
455
456 void wxFindReplaceDialog::DoGetClientSize(int *width, int *height) const
457 {
458 // the standard dialog size
459 if ( width )
460 *width = 219;
461 if ( height )
462 *height = 299;
463 }
464
465 #endif // wxUSE_FINDREPLDLG
466