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