X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/8db37e069996bf60cbc152eb8d93b199e7c80842..b50e6e416e2b4cdc849ea6f24181094c0957d904:/src/msw/fdrepdlg.cpp diff --git a/src/msw/fdrepdlg.cpp b/src/msw/fdrepdlg.cpp index aac3a07202..78b7f27dc2 100644 --- a/src/msw/fdrepdlg.cpp +++ b/src/msw/fdrepdlg.cpp @@ -4,7 +4,7 @@ // 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 "mswfdrepdlg.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -31,29 +27,23 @@ #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" +#include "wx/msw/mslu.h" + // ---------------------------------------------------------------------------- // functions prototypes // ---------------------------------------------------------------------------- -LRESULT APIENTRY 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 @@ -74,27 +64,34 @@ public: void InitFindWhat(const wxString& str); void InitReplaceWith(const wxString& str); - void SubclassDialog(HWND hwnd); - - static UINT GetFindDialogMessage() { return ms_msgFindDialog; } - // 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); + // called from window procedure for ms_msgFindDialog + static bool FindMessageHandler(wxWindow *win, + WXUINT nMsg, + WPARAM wParam, + LPARAM lParam); - // the owner of the dialog - HWND m_hwndOwner; + // copy string str contents to ppStr and fill pLen with its length + void InitString(const wxString& str, LPTSTR *ppStr, WORD *pLen); - // the previous window proc of our owner - WNDPROC m_oldParentWndProc; // 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; + + wxDECLARE_NO_COPY_CLASS(wxFindReplaceDialogImpl); }; UINT wxFindReplaceDialogImpl::ms_msgFindDialog = 0; @@ -117,12 +114,17 @@ wxFindReplaceDialogImpl::wxFindReplaceDialogImpl(wxFindReplaceDialog *dialog, if ( !ms_msgFindDialog ) { - wxLogLastError(_T("RegisterWindowMessage(FINDMSGSTRING)")); + wxLogLastError(wxT("RegisterWindowMessage(FINDMSGSTRING)")); } + + wxWindow::MSWRegisterMessageHandler + ( + ms_msgFindDialog, + &wxFindReplaceDialogImpl::FindMessageHandler + ); } - m_hwndOwner = NULL; - m_oldParentWndProc = NULL; + m_wasClosedByUser = false; wxZeroMemory(m_findReplace); @@ -167,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) @@ -182,124 +184,133 @@ void wxFindReplaceDialogImpl::InitReplaceWith(const wxString& str) &m_findReplace.wReplaceWithLen); } -void wxFindReplaceDialogImpl::SubclassDialog(HWND hwnd) -{ - m_hwndOwner = hwnd; - - // check that we don't subclass the parent twice: this would be a bad idea - // as then we'd have infinite recursion in wxFindReplaceWindowProc - WNDPROC oldParentWndProc = (WNDPROC)::GetWindowLong(hwnd, GWL_WNDPROC); - - if ( oldParentWndProc != wxFindReplaceWindowProc ) - { - // save old wnd proc elsewhere to access it from - // wxFindReplaceWindowProc - m_oldParentWndProc = oldParentWndProc; - (void)::SetWindowLong(hwnd, GWL_USERDATA, (LONG)oldParentWndProc); - - // and set the new one - (void)::SetWindowLong(hwnd, GWL_WNDPROC, (LONG)wxFindReplaceWindowProc); - } -} - wxFindReplaceDialogImpl::~wxFindReplaceDialogImpl() { delete [] m_findReplace.lpstrFindWhat; delete [] m_findReplace.lpstrReplaceWith; - - if ( m_hwndOwner ) - { - ::SetWindowLong(m_hwndOwner, GWL_WNDPROC, (LONG)m_oldParentWndProc); - } } // ---------------------------------------------------------------------------- -// Window Proc for handling RegisterWindowMessage(FINDMSGSTRING) +// handler for FINDMSGSTRING message // ---------------------------------------------------------------------------- -LRESULT APIENTRY wxFindReplaceWindowProc(HWND hwnd, WXUINT nMsg, - WPARAM wParam, LPARAM lParam) +bool +wxFindReplaceDialogImpl::FindMessageHandler(wxWindow * WXUNUSED(win), + WXUINT WXUNUSED_UNLESS_DEBUG(nMsg), + WPARAM WXUNUSED(wParam), + LPARAM lParam) { - if ( nMsg == wxFindReplaceDialogImpl::GetFindDialogMessage() ) +#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 + + wxASSERT_MSG( nMsg == ms_msgFindDialog, wxT("unexpected message received") ); + + 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 ) { - FINDREPLACE *pFR = (FINDREPLACE *)lParam; - wxFindReplaceDialog *dialog = (wxFindReplaceDialog *)pFR->lCustData; + s_lastMsgFlags = 0; + return 0; + } + s_lastMsgFlags = pFR->Flags; +#endif // wxUSE_UNICODE_MSLU - // map flags from Windows - wxEventType evtType; + wxFindReplaceDialog *dialog = (wxFindReplaceDialog *)pFR->lCustData; - bool replace = FALSE; - if ( pFR->Flags & FR_DIALOGTERM ) - { - evtType = wxEVT_COMMAND_FIND_CLOSE; - } - else if ( pFR->Flags & FR_FINDNEXT ) - { - evtType = wxEVT_COMMAND_FIND_NEXT; - } - else if ( pFR->Flags & FR_REPLACE ) - { - evtType = wxEVT_COMMAND_FIND_REPLACE; + // map flags from Windows + wxEventType evtType; - replace = TRUE; - } - else if ( pFR->Flags & FR_REPLACEALL ) - { - evtType = wxEVT_COMMAND_FIND_REPLACE_ALL; + 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(); - replace = TRUE; - } - else - { - wxFAIL_MSG( _T("unknown find dialog event") ); + evtType = wxEVT_COMMAND_FIND_CLOSE; + } + else if ( pFR->Flags & FR_FINDNEXT ) + { + evtType = wxEVT_COMMAND_FIND_NEXT; + } + else if ( pFR->Flags & FR_REPLACE ) + { + evtType = wxEVT_COMMAND_FIND_REPLACE; - return 0; - } + replace = true; + } + else if ( pFR->Flags & FR_REPLACEALL ) + { + evtType = wxEVT_COMMAND_FIND_REPLACE_ALL; - wxUint32 flags = 0; - if ( pFR->Flags & FR_DOWN ) - flags |= wxFR_DOWN; - if ( pFR->Flags & FR_WHOLEWORD ) - flags |= wxFR_WHOLEWORD; - if ( pFR->Flags & FR_MATCHCASE ) - flags |= wxFR_MATCHCASE; - - wxFindDialogEvent event(evtType, dialog->GetId()); - event.SetEventObject(dialog); - event.SetFlags(flags); - event.SetFindString(pFR->lpstrFindWhat); - if ( replace ) - { - event.SetReplaceString(pFR->lpstrReplaceWith); - } + replace = true; + } + else + { + wxFAIL_MSG( wxT("unknown find dialog event") ); - dialog->Send(event); + return 0; + } + + wxUint32 flags = 0; + if ( pFR->Flags & FR_DOWN ) + flags |= wxFR_DOWN; + if ( pFR->Flags & FR_WHOLEWORD ) + flags |= wxFR_WHOLEWORD; + if ( pFR->Flags & FR_MATCHCASE ) + flags |= wxFR_MATCHCASE; + + wxFindDialogEvent event(evtType, dialog->GetId()); + event.SetEventObject(dialog); + event.SetFlags(flags); + event.SetFindString(pFR->lpstrFindWhat); + if ( replace ) + { + event.SetReplaceString(pFR->lpstrReplaceWith); } - WNDPROC wndProc = (WNDPROC)::GetWindowLong(hwnd, GWL_USERDATA); +#if wxUSE_UNICODE_MSLU + s_blockMsg = true; +#endif // wxUSE_UNICODE_MSLU - // sanity check - wxASSERT_MSG( wndProc != wxFindReplaceWindowProc, - _T("infinite recursion detected") ); + dialog->Send(event); - return ::CallWindowProc(wndProc, hwnd, nMsg, wParam, lParam); +#if wxUSE_UNICODE_MSLU + s_blockMsg = false; +#endif // wxUSE_UNICODE_MSLU + + return true; } // ---------------------------------------------------------------------------- // 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 ) { FINDREPLACE *pFR = (FINDREPLACE *)lParam; wxFindReplaceDialog *dialog = (wxFindReplaceDialog *)pFR->lCustData; - ::SetWindowText(hwnd, dialog->GetTitle()); + ::SetWindowText(hwnd, dialog->GetTitle().wx_str()); // don't return FALSE from here or the dialog won't be shown return TRUE; @@ -322,14 +333,14 @@ 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, int flags) - : m_FindReplaceData(data) + : wxFindReplaceDialogBase(parent, data, title, flags) { Init(); @@ -338,14 +349,29 @@ wxFindReplaceDialog::wxFindReplaceDialog(wxWindow *parent, wxFindReplaceDialog::~wxFindReplaceDialog() { - // unsubclass the parent - delete m_impl; + if ( m_impl ) + { + // 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 flag must have been set + if ( !m_impl->WasClosedByUser() ) + { + // if it wasn't, delete the dialog ourselves + if ( !::DestroyWindow(GetHwnd()) ) + { + wxLogLastError(wxT("DestroyWindow(find dialog)")); + } + } + + // unsubclass the parent + delete m_impl; + } // prevent the base class dtor from trying to hide us! - m_isShown = FALSE; + m_isShown = false; - // and from destroying our window - m_hWnd = NULL; + // and from destroying our window [again] + m_hWnd = (WXHWND)NULL; } bool wxFindReplaceDialog::Create(wxWindow *parent, @@ -363,16 +389,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 // ---------------------------------------------------------------------------- @@ -382,7 +398,7 @@ 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? @@ -391,18 +407,18 @@ bool wxFindReplaceDialog::Show(bool show) // yes, just use it (void)::ShowWindow(GetHwnd(), show ? SW_SHOW : SW_HIDE); - return TRUE; + 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, wxT("call Create() first!") ); - wxASSERT_MSG( !m_impl, _T("why don't we have the window then?") ); + wxASSERT_MSG( !m_impl, wxT("why don't we have the window then?") ); m_impl = new wxFindReplaceDialogImpl(this, m_FindReplaceData->GetFlags()); @@ -430,20 +446,17 @@ 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, SW_SHOW) ) { - wxLogLastError(_T("ShowWindow(find dialog)")); + wxLogLastError(wxT("ShowWindow(find dialog)")); } m_hWnd = (WXHWND)hwnd; - return TRUE; + return true; } // ---------------------------------------------------------------------------- @@ -496,4 +509,3 @@ void wxFindReplaceDialog::DoGetClientSize(int *width, int *height) const } #endif // wxUSE_FINDREPLDLG -