X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/c41b00c9f51e5b06420b8522dc4de38e83bb1488..50679f941ec64c417c39582b276068fef8ca59cb:/src/msw/fdrepdlg.cpp diff --git a/src/msw/fdrepdlg.cpp b/src/msw/fdrepdlg.cpp index cb74cb9596..fbfd80833d 100644 --- a/src/msw/fdrepdlg.cpp +++ b/src/msw/fdrepdlg.cpp @@ -1,10 +1,10 @@ ///////////////////////////////////////////////////////////////////////////// // Name: src/msw/fdrepdlg.cpp // Purpose: wxFindReplaceDialog class -// Author: Markus Greither -// Modified by: 31.07.01: VZ: integrated into wxWindows +// Author: Markus Greither and Vadim Zeitlin +// Modified by: // Created: 23/03/2001 -// RCS-ID: +// RCS-ID: $Id$ // Copyright: (c) Markus Greither // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -17,10 +17,6 @@ // headers // ---------------------------------------------------------------------------- -#ifdef __GNUG__ - #pragma implementation "fdrepdlg.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -31,29 +27,24 @@ #if wxUSE_FINDREPLDLG #ifndef WX_PRECOMP + #include "wx/msw/wrapcdlg.h" #include "wx/intl.h" #include "wx/log.h" #endif -#include "wx/msw/private.h" - -#if !defined(__WIN32__) || defined(__SALFORDC__) || defined(__WXWINE__) - #include -#endif - #include "wx/fdrepdlg.h" // ---------------------------------------------------------------------------- // functions prototypes // ---------------------------------------------------------------------------- -LRESULT APIENTRY FindReplaceWindowProc(HWND hwnd, WXUINT nMsg, - WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK wxFindReplaceWindowProc(HWND hwnd, WXUINT nMsg, + WPARAM wParam, LPARAM lParam); -UINT CALLBACK wxFindReplaceDialogHookProc(HWND hwnd, - UINT uiMsg, - WPARAM wParam, - LPARAM lParam); +UINT_PTR CALLBACK wxFindReplaceDialogHookProc(HWND hwnd, + UINT uiMsg, + WPARAM wParam, + LPARAM lParam); // ---------------------------------------------------------------------------- // wxWin macros @@ -61,8 +52,6 @@ UINT CALLBACK wxFindReplaceDialogHookProc(HWND hwnd, IMPLEMENT_DYNAMIC_CLASS(wxFindReplaceDialog, wxDialog) -IMPLEMENT_DYNAMIC_CLASS(wxFindDialogEvent, wxCommandEvent) - // ---------------------------------------------------------------------------- // wxFindReplaceDialogImpl: the internals of wxFindReplaceDialog // ---------------------------------------------------------------------------- @@ -83,6 +72,10 @@ public: // only for passing to ::FindText or ::ReplaceText FINDREPLACE *GetPtrFindReplace() { return &m_findReplace; } + // set/query the "closed by user" flag + void SetClosedByUser() { m_wasClosedByUser = true; } + bool WasClosedByUser() const { return m_wasClosedByUser; } + private: void InitString(const wxString& str, LPTSTR *ppStr, WORD *pLen); @@ -95,8 +88,13 @@ private: // the find replace data used by the dialog FINDREPLACE m_findReplace; + // true if the user closed us, false otherwise + bool m_wasClosedByUser; + // registered Message for Dialog static UINT ms_msgFindDialog; + + DECLARE_NO_COPY_CLASS(wxFindReplaceDialogImpl) }; UINT wxFindReplaceDialogImpl::ms_msgFindDialog = 0; @@ -126,21 +124,30 @@ wxFindReplaceDialogImpl::wxFindReplaceDialogImpl(wxFindReplaceDialog *dialog, m_hwndOwner = NULL; m_oldParentWndProc = NULL; + m_wasClosedByUser = false; + wxZeroMemory(m_findReplace); - // translate the flags + // translate the flags: first the dialog creation flags // always set this to be able to set the title int flags = FR_ENABLEHOOK; - if ( flagsWX & wxFR_NOMATCHCASE) + int flagsDialog = dialog->GetWindowStyle(); + if ( flagsDialog & wxFR_NOMATCHCASE) flags |= FR_NOMATCHCASE; - if ( flagsWX & wxFR_NOWHOLEWORD) + if ( flagsDialog & wxFR_NOWHOLEWORD) flags |= FR_NOWHOLEWORD; - if ( flagsWX & wxFR_NOUPDOWN) + if ( flagsDialog & wxFR_NOUPDOWN) flags |= FR_NOUPDOWN; + + // and now the flags governing the initial values of the dialogs controls if ( flagsWX & wxFR_DOWN) flags |= FR_DOWN; + if ( flagsWX & wxFR_MATCHCASE) + flags |= FR_MATCHCASE; + if ( flagsWX & wxFR_WHOLEWORD ) + flags |= FR_WHOLEWORD; m_findReplace.lStructSize = sizeof(FINDREPLACE); m_findReplace.hwndOwner = GetHwndOf(dialog->GetParent()); @@ -162,7 +169,7 @@ void wxFindReplaceDialogImpl::InitString(const wxString& str, *ppStr = new wxChar[len]; wxStrcpy(*ppStr, str); - *pLen = len; + *pLen = (WORD)len; } void wxFindReplaceDialogImpl::InitFindWhat(const wxString& str) @@ -180,15 +187,17 @@ void wxFindReplaceDialogImpl::InitReplaceWith(const wxString& str) void wxFindReplaceDialogImpl::SubclassDialog(HWND hwnd) { m_hwndOwner = hwnd; - m_oldParentWndProc = (WNDPROC)::SetWindowLong - ( - hwnd, - GWL_WNDPROC, - (LONG)FindReplaceWindowProc - ); - - // save it elsewhere to access it from FindReplaceWindowProc() - (void)::SetWindowLong(hwnd, GWL_USERDATA, (LONG)m_oldParentWndProc); + + // check that we don't subclass the parent twice: this would be a bad idea + // as then we'd have infinite recursion in wxFindReplaceWindowProc + wxCHECK_RET( wxGetWindowProc(hwnd) != &wxFindReplaceWindowProc, + _T("can't have more than one find dialog currently") ); + + // set the new one and save the old as user data to allow access to it + // from wxFindReplaceWindowProc + m_oldParentWndProc = wxSetWindowProc(hwnd, wxFindReplaceWindowProc); + + wxSetWindowUserData(hwnd, (void *)m_oldParentWndProc); } wxFindReplaceDialogImpl::~wxFindReplaceDialogImpl() @@ -198,7 +207,8 @@ wxFindReplaceDialogImpl::~wxFindReplaceDialogImpl() if ( m_hwndOwner ) { - ::SetWindowLong(m_hwndOwner, GWL_WNDPROC, (LONG)m_oldParentWndProc); + // undo subclassing + wxSetWindowProc(m_hwndOwner, m_oldParentWndProc); } } @@ -206,20 +216,49 @@ wxFindReplaceDialogImpl::~wxFindReplaceDialogImpl() // Window Proc for handling RegisterWindowMessage(FINDMSGSTRING) // ---------------------------------------------------------------------------- -LRESULT APIENTRY FindReplaceWindowProc(HWND hwnd, WXUINT nMsg, - WPARAM wParam, LPARAM lParam) +LRESULT CALLBACK wxFindReplaceWindowProc(HWND hwnd, WXUINT nMsg, + WPARAM wParam, LPARAM lParam) { +#if wxUSE_UNICODE_MSLU + static unsigned long s_lastMsgFlags = 0; + + // This flag helps us to identify the bogus ANSI message + // sent by UNICOWS.DLL (see below) + // while we're sending our message to the dialog + // we ignore possible messages sent in between + static bool s_blockMsg = false; +#endif // wxUSE_UNICODE_MSLU + if ( nMsg == wxFindReplaceDialogImpl::GetFindDialogMessage() ) { FINDREPLACE *pFR = (FINDREPLACE *)lParam; + +#if wxUSE_UNICODE_MSLU + // This is a hack for a MSLU problem: Versions up to 1.0.4011 + // of UNICOWS.DLL send the correct UNICODE item after button press + // and a bogus ANSI mode item right after this, so lets ignore + // the second bogus message + if ( wxUsingUnicowsDll() && s_lastMsgFlags == pFR->Flags ) + { + s_lastMsgFlags = 0; + return 0; + } + s_lastMsgFlags = pFR->Flags; +#endif // wxUSE_UNICODE_MSLU + wxFindReplaceDialog *dialog = (wxFindReplaceDialog *)pFR->lCustData; // map flags from Windows wxEventType evtType; - bool replace = FALSE; + bool replace = false; if ( pFR->Flags & FR_DIALOGTERM ) { + // we have to notify the dialog that it's being closed by user and + // not deleted programmatically as it behaves differently in these + // 2 cases + dialog->GetImpl()->SetClosedByUser(); + evtType = wxEVT_COMMAND_FIND_CLOSE; } else if ( pFR->Flags & FR_FINDNEXT ) @@ -228,15 +267,15 @@ LRESULT APIENTRY FindReplaceWindowProc(HWND hwnd, WXUINT nMsg, } else if ( pFR->Flags & FR_REPLACE ) { - evtType = wxEVT_COMMAND_REPLACE; + evtType = wxEVT_COMMAND_FIND_REPLACE; - replace = TRUE; + replace = true; } else if ( pFR->Flags & FR_REPLACEALL ) { - evtType = wxEVT_COMMAND_REPLACE_ALL; + evtType = wxEVT_COMMAND_FIND_REPLACE_ALL; - replace = TRUE; + replace = true; } else { @@ -254,6 +293,7 @@ LRESULT APIENTRY FindReplaceWindowProc(HWND hwnd, WXUINT nMsg, flags |= wxFR_MATCHCASE; wxFindDialogEvent event(evtType, dialog->GetId()); + event.SetEventObject(dialog); event.SetFlags(flags); event.SetFindString(pFR->lpstrFindWhat); if ( replace ) @@ -261,22 +301,39 @@ LRESULT APIENTRY FindReplaceWindowProc(HWND hwnd, WXUINT nMsg, event.SetReplaceString(pFR->lpstrReplaceWith); } - (void)dialog->GetEventHandler()->ProcessEvent(event); +#if wxUSE_UNICODE_MSLU + s_blockMsg = true; +#endif // wxUSE_UNICODE_MSLU + + dialog->Send(event); + +#if wxUSE_UNICODE_MSLU + s_blockMsg = false; +#endif // wxUSE_UNICODE_MSLU } +#if wxUSE_UNICODE_MSLU + else if ( !s_blockMsg ) + s_lastMsgFlags = 0; +#endif // wxUSE_UNICODE_MSLU + + WNDPROC wndProc = (WNDPROC)wxGetWindowUserData(hwnd); - WNDPROC wndProc = (WNDPROC)::GetWindowLong(hwnd, GWL_USERDATA); + // sanity check + wxASSERT_MSG( wndProc != wxFindReplaceWindowProc, + _T("infinite recursion detected") ); return ::CallWindowProc(wndProc, hwnd, nMsg, wParam, lParam); -}; +} // ---------------------------------------------------------------------------- // Find/replace dialog hook proc // ---------------------------------------------------------------------------- -UINT CALLBACK wxFindReplaceDialogHookProc(HWND hwnd, - UINT uiMsg, - WPARAM WXUNUSED(wParam), - LPARAM lParam) +UINT_PTR CALLBACK +wxFindReplaceDialogHookProc(HWND hwnd, + UINT uiMsg, + WPARAM WXUNUSED(wParam), + LPARAM lParam) { if ( uiMsg == WM_INITDIALOG ) { @@ -306,28 +363,50 @@ void wxFindReplaceDialog::Init() m_FindReplaceData = NULL; // as we're created in the hidden state, bring the internal flag in sync - m_isShown = FALSE; + m_isShown = false; } wxFindReplaceDialog::wxFindReplaceDialog(wxWindow *parent, wxFindReplaceData *data, - const wxString &title) - : m_FindReplaceData(data) + const wxString &title, + int flags) + : wxFindReplaceDialogBase(parent, data, title, flags) { Init(); - (void)Create(parent, data, title); + (void)Create(parent, data, title, flags); } wxFindReplaceDialog::~wxFindReplaceDialog() { + // the dialog might have been already deleted if the user closed it + // manually but in this case we should have got a notification about it and + // the flagmust have been set + if ( !m_impl->WasClosedByUser() ) + { + // if it wasn't, delete the dialog ourselves + if ( !::DestroyWindow(GetHwnd()) ) + { + wxLogLastError(_T("DestroyWindow(find dialog)")); + } + } + + // unsubclass the parent delete m_impl; + + // prevent the base class dtor from trying to hide us! + m_isShown = false; + + // and from destroying our window [again] + m_hWnd = (WXHWND)NULL; } bool wxFindReplaceDialog::Create(wxWindow *parent, wxFindReplaceData *data, - const wxString &title) + const wxString &title, + int flags) { + m_windowStyle = flags; m_FindReplaceData = data; m_parent = parent; @@ -337,16 +416,6 @@ bool wxFindReplaceDialog::Create(wxWindow *parent, return parent != NULL; } -// ---------------------------------------------------------------------------- -// wxFindReplaceDialog data access -// ---------------------------------------------------------------------------- - -void wxFindReplaceDialog::SetData(wxFindReplaceData *data) -{ - delete m_FindReplaceData; - m_FindReplaceData = data; -} - // ---------------------------------------------------------------------------- // wxFindReplaceData show/hide // ---------------------------------------------------------------------------- @@ -356,42 +425,47 @@ bool wxFindReplaceDialog::Show(bool show) if ( !wxWindowBase::Show(show) ) { // visibility status didn't change - return FALSE; + return false; } // do we already have the dialog window? if ( m_hWnd ) { // yes, just use it - return ::ShowWindow(GetHwnd(), show ? SW_SHOW : SW_HIDE); + (void)::ShowWindow(GetHwnd(), show ? SW_SHOW : SW_HIDE); + + return true; } if ( !show ) { // well, it doesn't exist which is as good as being hidden - return TRUE; + return true; } - wxCHECK_MSG( m_FindReplaceData, FALSE, _T("call Create() first!") ); + wxCHECK_MSG( m_FindReplaceData, false, _T("call Create() first!") ); wxASSERT_MSG( !m_impl, _T("why don't we have the window then?") ); - int flagsWX = m_FindReplaceData->GetFlags(); - - m_impl = new wxFindReplaceDialogImpl(this, flagsWX); + m_impl = new wxFindReplaceDialogImpl(this, m_FindReplaceData->GetFlags()); m_impl->InitFindWhat(m_FindReplaceData->GetFindString()); - if ( flagsWX & wxFR_REPLACEDIALOG) + bool replace = HasFlag(wxFR_REPLACEDIALOG); + if ( replace ) { - m_impl->InitFindWhat(m_FindReplaceData->GetReplaceString()); + m_impl->InitReplaceWith(m_FindReplaceData->GetReplaceString()); } // call the right function to show the dialog which does what we want - HWND (*pfn)(FINDREPLACE *) = flagsWX & wxFR_REPLACEDIALOG ? ::ReplaceText - : ::FindText; - m_hWnd = (WXHWND)(*pfn)(m_impl->GetPtrFindReplace()); - if ( !m_hWnd ) + FINDREPLACE *pFR = m_impl->GetPtrFindReplace(); + HWND hwnd; + if ( replace ) + hwnd = ::ReplaceText(pFR); + else + hwnd = ::FindText(pFR); + + if ( !hwnd ) { wxLogError(_("Failed to create the standard find/replace dialog (error code %d)"), ::CommDlgExtendedError()); @@ -399,18 +473,20 @@ bool wxFindReplaceDialog::Show(bool show) delete m_impl; m_impl = NULL; - return FALSE; + return false; } // subclass parent window in order to get FINDMSGSTRING message m_impl->SubclassDialog(GetHwndOf(m_parent)); - if ( !::ShowWindow((HWND)m_hWnd, SW_SHOW) ) + if ( !::ShowWindow(hwnd, SW_SHOW) ) { wxLogLastError(_T("ShowWindow(find dialog)")); } - return TRUE; + m_hWnd = (WXHWND)hwnd; + + return true; } // ---------------------------------------------------------------------------- @@ -463,4 +539,3 @@ void wxFindReplaceDialog::DoGetClientSize(int *width, int *height) const } #endif // wxUSE_FINDREPLDLG -