Передача событий в wxView

Это русская секция форума wxWidjets. В этой секции вы можете обсуждать любые вопросы, связанные с wxWidgets на вашем родном языке.
Post Reply
mzet82
In need of some credit
In need of some credit
Posts: 8
Joined: Thu Dec 29, 2011 8:23 am

Передача событий в wxView

Post by mzet82 »

Привет. Проблема в следующем. Есть приложение на базе архитектуры документ-вид. видов у документа два. Так вот событие от кнопки, скажем, последовательно проходит через класс документа, через класс вида (первого) и так далеее. А во второй вид это событие не приходит, как сделать, чтоб событие можно было отловить и во втором виде?
mzet82
In need of some credit
In need of some credit
Posts: 8
Joined: Thu Dec 29, 2011 8:23 am

Re: Передача событий в wxView

Post by mzet82 »

Я тут вроде нашел ответ. Вот код. Посмотрите правильно я сделал?

Code: Select all

#include <wx/wx.h>
#include <wx/docview.h>
#include <wx/progdlg.h>

// ----------------------------------------------------------------------------
// CDocument
// ----------------------------------------------------------------------------
// Это класс документа. Тут храняться данные, и методы обработки тоже тут находяться
// Здесь происходит загрузка и сохранение и/в файл, изменение данных и так далее
// Для примера возьмем текстовую строку - m_Text - это будут наши данные.

class CDocument : public wxDocument
{
	CDocument();
	virtual bool OnCreate(const wxString& path, long flags);
	bool AddNewView( wxClassInfo* pClassInfo, long flags );

	// это здесь и далее нужно для RTTI,
	// так как создание объектов делается через RTTI
	DECLARE_DYNAMIC_CLASS(CDocument)

public:

	DECLARE_EVENT_TABLE()
};

// ----------------------------------------------------------------------------
// CTextViewCtrl
// ----------------------------------------------------------------------------
// Это клас редактора. Команды меню направляются в активный вид View, так как у
// нас их два, то нужно отслеживать фокус редактора и устанавливать активным
// соответсвующимй вид.

class CTextViewCtrl : public wxTextCtrl
{
public:
	CTextViewCtrl(wxWindow *parent, wxWindowID id = wxID_ANY);
	void SetView(wxView *v)
	{
		m_view = v;
	}

private:
	wxView *m_view;
	void OnSetFocus(wxFocusEvent& event);
	DECLARE_EVENT_TABLE()
};

// ----------------------------------------------------------------------------
// CFrame
// ----------------------------------------------------------------------------
// Класс фрейма - тоже должно быть знакомо
// собственно самое главное окошко )
// в качестве родителя используется специальный класс wxDocParentFrame
// в нем реализован некоторый функционал по обработке предопределеннных меню
// (wxID_NEW, wxID_OPEN и т.д.)

class CFrame : public wxDocParentFrame
{
public:
	CFrame(wxDocManager *manager, wxFrame *parent);
	CTextViewCtrl *m_leftText;
	CTextViewCtrl *m_rightText;


	void OnProgressDialog(wxCommandEvent& event);
	void OnAbout(wxCommandEvent& event)	{ wxMessageBox("Sample for 2 View"); }
	void OnUpdateFileDisable(wxUpdateUIEvent& event) { event.Enable(false);	}
	DECLARE_EVENT_TABLE()
};

// ----------------------------------------------------------------------------
// CApp
// ----------------------------------------------------------------------------
// Класс приложения, должен быть знаком )

class CApp : public wxApp
{
	// менеджер документов
	// он хранит список созданных документов (в случае MDI приложения) или один
	// документ в случае SDI
	wxDocManager *m_docManager;

public:
	virtual bool OnInit();
	CFrame *GetMainFrame();
};

// Объявляет глобальный объект CApp,
// теперь к классу приложения можно обращаться
// с помощью глобальной функции wxGetApp().метод_класса_CApp
DECLARE_APP(CApp)



// ----------------------------------------------------------------------------
// CViewTextLeft
// ----------------------------------------------------------------------------
// Собственно вид, создается документом
// и отображает данные из документа,
// чтоб получить доступ к документу используется метод wxDocument *GetDocument();
// его нужно приводить к нашему типу документа, обычно пишут так
// CDocument *pDoc = wxDynamicCast(GetDocument(), CDocument);
// или по старому
// CDocument *pDoc = (CDocument *)GetDocument();

class CViewTextLeft : public wxView
{
	CViewTextLeft();
	virtual bool OnCreate(wxDocument *WXUNUSED(doc), long WXUNUSED(flags));
	bool OnClose(bool bDelWindow);
	void OnUpdate(wxView* sender, wxObject* hint);
	virtual void OnDraw(wxDC *dc);

	CTextViewCtrl *m_leftText;

	void OnFile(wxCommandEvent& event);
	void OnUpdateFile(wxUpdateUIEvent& event);

	DECLARE_EVENT_TABLE()
	DECLARE_DYNAMIC_CLASS(CViewTextLeft)
};

// ----------------------------------------------------------------------------
// CViewTextRight
// ----------------------------------------------------------------------------
// Собственно вид, создается документом
// и отображает данные из документа,
// чтоб получить доступ к документу используется метод wxDocument *GetDocument();
// его нужно приводить к нашему типу документа, обычно пишут так
// CDocument *pDoc = wxDynamicCast(GetDocument(), CDocument);
// или по старому
// CDocument *pDoc = (CDocument *)GetDocument();

class CViewTextRight : public wxView
{
	CViewTextRight();
	virtual bool OnCreate(wxDocument *WXUNUSED(doc), long WXUNUSED(flags));
	bool OnClose(bool bDelWindow);
	void OnUpdate(wxView* sender, wxObject* hint);
	virtual void OnDraw(wxDC *dc);

	CTextViewCtrl *m_rightText;

	void OnFile(wxCommandEvent& event);
	void OnUpdateFile(wxUpdateUIEvent& event);

	DECLARE_EVENT_TABLE()
	DECLARE_DYNAMIC_CLASS(CViewTextRight)
};

// ----------------------------------------------------------------------------
// I M P L E M E N T A T I O N
// ----------------------------------------------------------------------------

IMPLEMENT_APP(CApp)

IMPLEMENT_DYNAMIC_CLASS(CDocument, wxDocument)
IMPLEMENT_DYNAMIC_CLASS(CViewTextLeft, wxView)
IMPLEMENT_DYNAMIC_CLASS(CViewTextRight, wxView)

BEGIN_EVENT_TABLE(CDocument, wxDocument)
END_EVENT_TABLE()

BEGIN_EVENT_TABLE(CTextViewCtrl, wxTextCtrl)
	EVT_SET_FOCUS(CTextViewCtrl::OnSetFocus)
END_EVENT_TABLE()

BEGIN_EVENT_TABLE(CViewTextLeft, wxView)
	EVT_MENU(wxID_FILE1, CViewTextLeft::OnFile)
	EVT_UPDATE_UI(wxID_FILE1, CViewTextLeft::OnUpdateFile)
END_EVENT_TABLE()

BEGIN_EVENT_TABLE(CViewTextRight, wxView)
	EVT_MENU(wxID_FILE2, CViewTextRight::OnFile)
	EVT_UPDATE_UI(wxID_FILE2, CViewTextRight::OnUpdateFile)
END_EVENT_TABLE()

BEGIN_EVENT_TABLE(CFrame, wxDocParentFrame)
	EVT_MENU(wxID_ABOUT, CFrame::OnAbout)
	EVT_MENU(wxID_ADD, CFrame::OnProgressDialog)
	EVT_UPDATE_UI(wxID_FILE2, CFrame::OnUpdateFileDisable)
	EVT_UPDATE_UI(wxID_FILE2, CFrame::OnUpdateFileDisable)
END_EVENT_TABLE()

// ----------------------------------------------------------------------------
// CTextViewCtrl
// ----------------------------------------------------------------------------

CTextViewCtrl::CTextViewCtrl(wxWindow *parent, wxWindowID id)
	: wxTextCtrl(parent, id, "", wxDefaultPosition, wxSize(200, 200), wxTE_MULTILINE)
	, m_view(NULL)
{
}

void CTextViewCtrl::OnSetFocus(wxFocusEvent& event)
{
	if (m_view)
	{
		// при получении фокуса элементом управления
		// делаем соответсвующий (содержащий данный элемент управления)
		// вид активным
		m_view->Activate(true);
	}
	event.Skip();	// что бы курсор отображался
}

// ----------------------------------------------------------------------------
// CDocument
// ----------------------------------------------------------------------------

CDocument::CDocument()
{
}

// Добавление видов
bool CDocument::OnCreate(const wxString& path, long flags)
{
	wxLogDebug("CDocument::OnCreate");

	if ( !AddNewView( CLASSINFO( CViewTextLeft ), flags ) )
	{
		return false;
	}

	if ( !AddNewView( CLASSINFO( CViewTextRight ), flags ) )
	{
		return false;
	}

	return true;
}

// вспомогательная функция создания видов через RTTI
// код подсмотрен в исходниках wxWidgets
bool CDocument::AddNewView( wxClassInfo* pClassInfo, long flags )
{
	if( !pClassInfo )
	{
		return false;
	}

	wxView* pView = (wxView *)pClassInfo->CreateObject();

	if( pView )
	{
		pView->SetDocument( this );
		if ( !pView->OnCreate( this, flags ) )
		{
			delete pView;
		}
		else
		{
			AddView( pView );
			return true;
		}
	}

	return false;
}


// ----------------------------------------------------------------------------
// CApp
// ----------------------------------------------------------------------------

bool CApp::OnInit()
{
	// для SDI - 1 документ
	// для MDI - без ограничений
	// устанавливает число одновременно открытых документов
	m_docManager = new wxDocManager;
	m_docManager->SetMaxDocsOpen(1);
	new wxDocTemplate(	m_docManager,
						_T(""),	// тут парамтеры всякие, можно помотреть в документации
						_T(""),
						_T(""),
						_T(""),
						_T(""),
						_T(""),
						CLASSINFO(CDocument),// Это документ
						NULL				// А здесь обычно вид, если один
						// а если несколько как у нас, то создаем вручную
						// CDocument::OnCreate() (смотри выше)
					 );

	CFrame *frame = new CFrame(m_docManager, NULL);
	SetTopWindow(frame);
	frame->Center();
	frame->Show();
	return true;
}

CFrame *CApp::GetMainFrame()
{
	return (CFrame *)GetTopWindow();
}


// ----------------------------------------------------------------------------
// CFrame
// ----------------------------------------------------------------------------

CFrame::CFrame(wxDocManager *manager, wxFrame *parent)
	: wxDocParentFrame(	manager, parent, wxID_ANY, _("Document View 2 SDI"))
{
	wxMenu *menuFile = new wxMenu();
	menuFile->Append(wxID_NEW, _("&New\tCtrl+N"));
	menuFile->Append(wxID_CLOSE, _("&Close"));
	menuFile->AppendSeparator();
	menuFile->Append(wxID_EXIT, _("E&xit"));

	wxMenu *menuEdit = new wxMenu();
	menuEdit->Append(wxID_FILE1, _("&Menu of Left Text Ctrl"));
	menuEdit->Append(wxID_FILE2, _("&Menu of Right Text Ctrl"));
	menuEdit->Append(wxID_ADD, _("&Show Progress Dialog"));

	wxMenu *menuHelp = new wxMenu();
	menuHelp->Append(wxID_ABOUT, _("&About\tCtrl+A"));

	wxMenuBar *menuBar = new wxMenuBar();
	menuBar->Append(menuFile, _("&File"));
	menuBar->Append(menuEdit, _("&Edit"));
	menuBar->Append(menuHelp, _("&Help"));
	SetMenuBar(menuBar);

	SetMinSize(GetSize());
	wxPanel *panel = new wxPanel(this);
	m_leftText = new CTextViewCtrl(panel);
	m_rightText = new CTextViewCtrl(panel);

	wxBoxSizer *sizer = new wxBoxSizer(wxHORIZONTAL);
	sizer->Add(m_leftText, 1, wxEXPAND|wxRIGHT, 2);
	sizer->Add(m_rightText, 1, wxEXPAND|wxRIGHT, 2);
	panel->SetSizer(sizer);
	sizer->SetSizeHints(this);
	CreateStatusBar(2);
}

void CFrame::OnProgressDialog(wxCommandEvent& event)
{
	wxProgressDialog dlg("Progress", "Wait while working...", 100, this, wxPD_AUTO_HIDE);
	for (int i = 0; i <= 100; i++)
	{
		dlg.Update(i);
		wxMilliSleep(100);
	}
}

// ----------------------------------------------------------------------------
// CViewTextLeft
// ----------------------------------------------------------------------------

CViewTextLeft::CViewTextLeft()
{
}

bool CViewTextLeft::OnCreate(wxDocument *WXUNUSED(doc), long WXUNUSED(flags))
{
	m_leftText = wxGetApp().GetMainFrame()->m_leftText;
	m_leftText->SetFocus();
	m_leftText->SetView(this);
	Activate(true);
	return true;
}

bool CViewTextLeft::OnClose(bool bDelWindow)
{
	m_leftText->Clear();
	m_leftText->SetView(NULL);
	m_leftText = NULL;
	Activate(false);
	if ( bDelWindow )
	{
	}
	return true;
}

// вызывается когда документ обновляет виды с помощью UpdateAllViews()
void CViewTextLeft::OnUpdate(wxView* sender, wxObject* hint)
{
}

// вызывается CCanvas для рисования
void CViewTextLeft::OnDraw(wxDC *dc)
{
}

void CViewTextLeft::OnFile(wxCommandEvent& event)
{
	m_leftText->AppendText("Select menu to left View\n");
}

void CViewTextLeft::OnUpdateFile(wxUpdateUIEvent& event)
{
	event.Enable(true);
}

// ----------------------------------------------------------------------------
// CViewTextRight
// ----------------------------------------------------------------------------

CViewTextRight::CViewTextRight()
{
}

bool CViewTextRight::OnCreate(wxDocument *WXUNUSED(doc), long WXUNUSED(flags))
{
	m_rightText = wxGetApp().GetMainFrame()->m_rightText;
	m_rightText->SetView(this);
	return true;
}

bool CViewTextRight::OnClose(bool bDelWindow)
{
	m_rightText->Clear();
	m_rightText->SetView(NULL);
	m_rightText = NULL;
	Activate(false);
	if ( bDelWindow )
	{
	}
	return true;
}

// вызывается когда документ обновляет виды с помощью UpdateAllViews()
void CViewTextRight::OnUpdate(wxView* sender, wxObject* hint)
{
}

// вызывается CCanvas для рисования
void CViewTextRight::OnDraw(wxDC *dc)
{
}

void CViewTextRight::OnFile(wxCommandEvent& event)
{
	m_rightText->AppendText("Select menu to right View\n");
}

void CViewTextRight::OnUpdateFile(wxUpdateUIEvent& event)
{
	event.Enable(true);
}

Post Reply