fdrepdlg.cpp

来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 547 行 · 第 1/2 页

CPP
547
字号
/////////////////////////////////////////////////////////////////////////////
// Name:        src/msw/fdrepdlg.cpp
// Purpose:     wxFindReplaceDialog class
// Author:      Markus Greither and Vadim Zeitlin
// Modified by:
// Created:     23/03/2001
// RCS-ID:
// Copyright:   (c) Markus Greither
// Licence:     wxWindows licence
/////////////////////////////////////////////////////////////////////////////

// ============================================================================
// declarations
// ============================================================================

// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------

#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
    #pragma implementation "mswfdrepdlg.h"
#endif

// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
    #pragma hdrstop
#endif

#if wxUSE_FINDREPLDLG

#ifndef WX_PRECOMP
    #include "wx/intl.h"
    #include "wx/log.h"
#endif

#include "wx/msw/wrapcdlg.h"
#include "wx/fdrepdlg.h"

// ----------------------------------------------------------------------------
// functions prototypes
// ----------------------------------------------------------------------------

LRESULT APIENTRY wxFindReplaceWindowProc(HWND hwnd, WXUINT nMsg,
                                       WPARAM wParam, LPARAM lParam);

UINT_PTR CALLBACK wxFindReplaceDialogHookProc(HWND hwnd,
                                              UINT uiMsg,
                                              WPARAM wParam,
                                              LPARAM lParam);

// ----------------------------------------------------------------------------
// wxWin macros
// ----------------------------------------------------------------------------

IMPLEMENT_DYNAMIC_CLASS(wxFindReplaceDialog, wxDialog)

// ----------------------------------------------------------------------------
// wxFindReplaceDialogImpl: the internals of wxFindReplaceDialog
// ----------------------------------------------------------------------------

class WXDLLEXPORT wxFindReplaceDialogImpl
{
public:
    wxFindReplaceDialogImpl(wxFindReplaceDialog *dialog, int flagsWX);
    ~wxFindReplaceDialogImpl();

    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);

    // the owner of the dialog
    HWND m_hwndOwner;

    // 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;

    DECLARE_NO_COPY_CLASS(wxFindReplaceDialogImpl)
};

UINT wxFindReplaceDialogImpl::ms_msgFindDialog = 0;

// ============================================================================
// implementation
// ============================================================================

// ----------------------------------------------------------------------------
// wxFindReplaceDialogImpl
// ----------------------------------------------------------------------------

wxFindReplaceDialogImpl::wxFindReplaceDialogImpl(wxFindReplaceDialog *dialog,
                                                 int flagsWX)
{
    // get the identifier for the find dialog message if we don't have it yet
    if ( !ms_msgFindDialog )
    {
        ms_msgFindDialog = ::RegisterWindowMessage(FINDMSGSTRING);

        if ( !ms_msgFindDialog )
        {
            wxLogLastError(_T("RegisterWindowMessage(FINDMSGSTRING)"));
        }
    }

    m_hwndOwner = NULL;
    m_oldParentWndProc = NULL;

    m_wasClosedByUser = false;

    wxZeroMemory(m_findReplace);

    // translate the flags: first the dialog creation flags

    // always set this to be able to set the title
    int flags = FR_ENABLEHOOK;

    int flagsDialog = dialog->GetWindowStyle();
    if ( flagsDialog & wxFR_NOMATCHCASE)
        flags |= FR_NOMATCHCASE;
    if ( flagsDialog & wxFR_NOWHOLEWORD)
        flags |= FR_NOWHOLEWORD;
    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());
    m_findReplace.Flags = flags;

    m_findReplace.lCustData = (LPARAM)dialog;
    m_findReplace.lpfnHook = wxFindReplaceDialogHookProc;
}

void wxFindReplaceDialogImpl::InitString(const wxString& str,
                                         LPTSTR *ppStr, WORD *pLen)
{
    size_t len = str.length() + 1;
    if ( len < 80 )
    {
        // MSDN docs say that the buffer must be at least 80 chars
        len = 80;
    }

    *ppStr = new wxChar[len];
    wxStrcpy(*ppStr, str);
    *pLen = (WORD)len;
}

void wxFindReplaceDialogImpl::InitFindWhat(const wxString& str)
{
    InitString(str, &m_findReplace.lpstrFindWhat, &m_findReplace.wFindWhatLen);
}

void wxFindReplaceDialogImpl::InitReplaceWith(const wxString& str)
{
    InitString(str,
               &m_findReplace.lpstrReplaceWith,
               &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
    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()
{
    delete [] m_findReplace.lpstrFindWhat;
    delete [] m_findReplace.lpstrReplaceWith;

    if ( m_hwndOwner )
    {
        // undo subclassing
        wxSetWindowProc(m_hwndOwner, m_oldParentWndProc);
    }
}

// ----------------------------------------------------------------------------
// Window Proc for handling RegisterWindowMessage(FINDMSGSTRING)
// ----------------------------------------------------------------------------

LRESULT APIENTRY 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;
        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 )
        {
            evtType = wxEVT_COMMAND_FIND_NEXT;
        }
        else if ( pFR->Flags & FR_REPLACE )
        {
            evtType = wxEVT_COMMAND_FIND_REPLACE;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?