찾기(Find)을 구현하기 위해서는 문자열 비교 및 검색 기능을 구현해야되는데.

 wxWidgets에서는 기본적으로 제공해준다.

 여기서 wxFindReplaceDialog라는 창을 제공해주는데.

 이걸 사용하기 위해선 'fdrepdlg.h' 라는 헤더 파일을 포함해줘야한다.

 

wxMain.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 
// Find Dialog
#include <wx/fdrepdlg.h>
 
class MyFrame : public wxFrame
{
public:
    ...
private:
    // 메모장 기능해주는 장치.
    wxTextCtrl* m_textControl;
 
    // 찾기 기능을 처리하기 위한 창.
    wxFindReplaceDialog* m_findDialog;
    wxFindReplaceData m_findData; // 찾기 및 바꾸기 데이터.
 
    ...
};
cs

 

이렇게 하면, wxFindReplaceDialog의 창을 불러와서 특정 문자열을 찾아서 제공하도록 할 수 있다.

 

이제, Edit의 하위 메뉴인 Find를 처리해주는 이벤트 핸들러와 Dialog로 데이터를 제공 받는 이벤트 핸들러들을 만든다.

Find를 처리해주는 이벤트 핸들러를 OnFind라고 하고,

FindReplace의 이벤트 핸들러는 OnFindClose, OnFindNext로 한다.

 

wxMain.h

1
2
3
4
    void OnFind(wxCommandEvent& event);
    // FindDialog 이벤트를 받는 핸들러
    void OnFindClose(wxFindDialogEvent& event); // FindDialog가 닫혔을시.
    void OnFindNext(wxFindDialogEvent& event); // FindDialog로 다음 문자을 검색할시.
cs

 

이제, 하위 메뉴를 추가 및 이벤트 핸들러를 연결한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
    m_menuEdit = new wxMenu;
    m_menuEdit->Append(wxID_UNDO, "&Undo\tCtrl+Z""Undo the last action");
    m_menuEdit->Append(wxID_REDO, "&Redo\tCtrl+Y""Redo the last undone action");
    m_menuFile->AppendSeparator();
    m_menuEdit->Append(wxID_CUT, "Cu&t\tCtrl+X""Cut the selected text to the clipboard");
    m_menuEdit->Append(wxID_COPY, "&Copy\tCtrl+C""Copy the selected text to the clipboard");
    m_menuEdit->Append(wxID_PASTE, "&Paste\tCtrl+V""Paste text from the clipboard");
    m_menuFile->AppendSeparator();
    m_menuEdit->Append(wxID_FIND, "&Findl\tCtrl+F""Find text");
    m_menuFile->AppendSeparator();
    m_menuEdit->Append(ID_SELECT_ALL, "&Select All\tCtrl+A""Select all text");
    m_menuFile->AppendSeparator();
    m_menuEdit->AppendCheckItem(ID_DATETIME, "&DateTime\tF5""DateTime");
 
    // 메뉴 Edit에 관련된 이벤트 핸들러
    Bind(wxEVT_MENU, &MyFrame::OnUndo, this, wxID_UNDO);
    Bind(wxEVT_MENU, &MyFrame::OnRedo, this, wxID_REDO);
    Bind(wxEVT_MENU, &MyFrame::OnCut, this, wxID_CUT);
    Bind(wxEVT_MENU, &MyFrame::OnCopy, this, wxID_COPY);
    Bind(wxEVT_MENU, &MyFrame::OnPaste, this, wxID_PASTE);
 
    Bind(wxEVT_MENU, &MyFrame::OnFind, this, wxID_FIND);
 
    Bind(wxEVT_MENU, &MyFrame::OnSelectAll, this, ID_DATETIME);
    Bind(wxEVT_MENU, &MyFrame::OnInsertDateTime, this, ID_DATETIME);
 
 
    // FindDialog 이벤트 핸들러 적용.
    Bind(wxEVT_FIND_CLOSE, &MyFrame::OnFindClose, this);
    Bind(wxEVT_FIND, &MyFrame::OnFindNext, this);
cs

 

이제, 이벤트 핸들러를 구현한다.

먼저 Find 메뉴를 처리하는 이벤트 핸들러의 구현은 다음과 같이 한다.

1
2
3
4
5
6
void MyFrame::OnFind(wxCommandEvent& event) {
    if (!m_findDialog) {
        m_findDialog = new wxFindReplaceDialog(this&m_findData, "Find");
        m_findDialog->Show(true);
    }
}
cs

 

이후에 FindReplaceDialog를 처리하기 위한 이벤트 핸들러는 다음과 같이 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// FindDialog를 닫았을때 처리하는 이벤트
void MyFrame::OnFindClose(wxFindDialogEvent& event) {
    m_findDialog->Destroy();
    m_findDialog = nullptr;
}
 
// FindDialog를 다음 문자을 검색했을때 처리하는 이벤트
void MyFrame::OnFindNext(wxFindDialogEvent& event){
    wxString searchString = event.GetFindString();
    int flags = event.GetFlags();
 
    // 검색 시작 위치를 결정합니다.
    long startPos = m_textControl->GetInsertionPoint();
    long textLength = m_textControl->GetValue().length();
 
    // 대소문자 구분 여부를 확인합니다.
    wxString textToSearch = m_textControl->GetValue();
    if (!(flags & wxFR_MATCHCASE))
    {
        textToSearch.MakeLower();
        searchString.MakeLower();
    }
 
    // 검색을 시작합니다.
    long foundPos = -1;
    if (flags & wxFR_DOWN) // "다음 찾기"인 경우
    {
        foundPos = textToSearch.find(searchString, startPos);
        // 검색된 위치가 현재 커서 위치보다 앞인 경우 다음 위치부터 다시 검색
        if (foundPos == startPos) {
            foundPos = textToSearch.find(searchString, startPos + 1);
        };
    }
    else // "이전 찾기"인 경우 (옵션에 따라)
    {
        wxString textToStartPos = textToSearch.Mid(0, startPos);
        foundPos = textToStartPos.rfind(searchString);
    }
 
    if (foundPos != wxString::npos)
    {
        m_textControl->ShowPosition(foundPos);
    }
    else
    {
        wxMessageBox("Search string not found.""Find", wxOK | wxICON_INFORMATION);
    }
}
cs

 

여기서, OnFindClose는 FindReplaceDialog가 종료되면, 반환하도록 만들어서 창을 제거하도록 만든다.

OnFindNext는 FindReplaceDialog의 상태를 보고 거기에 맞춰 검색하도록 하는 장치이다.

단어를 선택하지 않고, 현재 위치로 이동하여 자동으로 스크롤로 이동하도록 만든다.

Posted by JunkMam
,