核心类分析
wxApp继承关系
wxFrame继承关系
wxPanel的继承关系
类图还是有点复杂的,超出预期。那我们从关系的视角入手分析吧。
消息是怎么分发的
OnPaint 打个断点断下来
从栈底部往上看,WinMain
到 wxEntryReal
之前是有分析的。
wxEntryReal
的最后 return wxTheApp->OnRun();
启动了消息循环
int wxAppBase::OnRun()
{
……
return wxAppConsole::OnRun();
}
int wxAppConsoleBase::OnRun()
{
return MainLoop();
}
int wxAppConsoleBase::MainLoop()
{
wxEventLoopBaseTiedPtr mainLoop(&m_mainLoop, CreateMainLoop());
if (wxTheApp)
wxTheApp->OnLaunched();
return m_mainLoop ? m_mainLoop->Run() : -1;
}
实质上调到了wxAppConsoleBase::MainLoop()
很明显是 wxEventLoopBaseTiedPtr mainLoop(&m_mainLoop, CreateMainLoop());
这一句创建了消息循环。mainLoop 是个指针,m_mainLoop 是负责消息循环的对象。打个断点调一下试试。
wxEventLoopBase *wxAppConsoleBase::CreateMainLoop()
{
return GetTraits()->CreateEventLoop();
}
wxEventLoopBase* wxGUIAppTraits::CreateEventLoop()
{
return new wxEventLoop;
}
看上去像是这里在这里创建的。其实 wxEventLoop
在Windows平台被定义为了 wxGUIEventLoop
wxGUIEventLoop
继承自 wxMSWEventLoopBase
继承自 wxEventLoopManual
继承自 wxEventLoopBase
这里启动消息循环 return m_mainLoop ? m_mainLoop->Run() : -1;
int wxEventLoopManual::DoRun()
{
……
// this is the event loop itself
for ( ;; )
{
while ( !m_shouldExit
&& !Pending()
&& !(wxTheApp && wxTheApp->HasPendingEvents())
&& ProcessIdle() );
if ( m_shouldExit )
break;
if ( !ProcessEvents() || m_shouldExit )
break;
}
return m_exitcode;
}
bool wxMSWEventLoopBase::Pending() const
{
MSG msg;
return ::PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE) != 0;
}
这里就是我们熟悉的PeekMessage了。消息经过系统处理以后,发回给我们注册的 WndProc 函数
实际上是 注册的是 ……\wxWidgets\src\msw\window.cpp 中的 wxWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
函数,注册过程我们后续分析。
LRESULT WXDLLEXPORT APIENTRY
wxWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
……
wxWindowMSW *wnd = wxFindWinFromHandle(hWnd);
LRESULT rc;
wxSEH_TRY
{
if ( wnd && wxGUIEventLoop::AllowProcessing(wnd) )
rc = wnd->MSWWindowProc(message, wParam, lParam);
else
rc = ::DefWindowProc(hWnd, message, wParam, lParam);
}
wxSEH_HANDLE(0)
return rc;
}
找到消息对应的 wxWindowMSW
对象,然后调用 MSWWindowProc
WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
{
WXLRESULT result;
if ( !MSWHandleMessage(&result, message, wParam, lParam) )
{
#if wxDEBUG_LEVEL >= 2
wxLogTrace("winmsg", wxT("Forwarding %s to DefWindowProc."),
wxGetMessageName(message));
#endif // wxDEBUG_LEVEL >= 2
result = MSWDefWindowProc(message, wParam, lParam);
}
return result;
}
bool
wxWindowMSW::MSWHandleMessage(WXLRESULT *result,
WXUINT message,
WXWPARAM wParam,
WXLPARAM lParam)
{
// did we process the message?
bool processed = false;
// the return value
union
{
bool allow;
WXLRESULT result;
WXHBRUSH hBrush;
} rc;
// for most messages we should return 0 when we do process the message
rc.result = 0;
switch ( message )
{
case WM_PAINT:
{
processed = HandlePaint();
}
break;
default:
// try a custom message handler
}
if ( !processed )
return false;
*result = rc.result;
return true;
}
bool wxWindowMSW::HandlePaint()
{
wxPaintEvent event(this);
bool processed = HandleWindowEvent(event);
return createdPaintDC;
}
这里构造出了 wxPaintEvent
事件对象
bool wxWindowBase::HandleWindowEvent(wxEvent& event) const
{
// SafelyProcessEvent() will handle exceptions nicely
return GetEventHandler()->SafelyProcessEvent(event);
}
这里进入了 wxEvtHandler
的分发逻辑,一路调用到
bool wxEvtHandler::TryHereOnly(wxEvent& event)
{
// Then static per-class event tables
if ( GetEventHashTable().HandleEvent(event, this) )
return true;
在 GetEventHashTable()
继续分发
bool wxEventHashTable::HandleEvent(wxEvent &event, wxEvtHandler *self)
{
// Find all entries for the given event type.
wxEventType eventType = event.GetEventType();
const EventTypeTablePointer eTTnode = m_eventTypeTable[eventType % m_size];
if (eTTnode && eTTnode->eventType == eventType)
{
// Now start the search for an event handler
// that can handle an event with the given ID.
const wxEventTableEntryPointerArray&
eventEntryTable = eTTnode->eventEntryTable;
const size_t count = eventEntryTable.GetCount();
for (size_t n = 0; n < count; n++)
{
const wxEventTableEntry& entry = *eventEntryTable[n];
if ( wxEvtHandler::ProcessEventIfMatchesId(entry, self, event) )
return true;
}
}
return false;
}
这里遍历 wxEventTableEntry
bool wxEvtHandler::ProcessEventIfMatchesId(const wxEventTableEntryBase& entry,
wxEvtHandler *handler,
wxEvent& event)
{
int tableId1 = entry.m_id,
tableId2 = entry.m_lastId;
if ((tableId1 == wxID_ANY) ||
(tableId2 == wxID_ANY && tableId1 == event.GetId()) ||
(tableId2 != wxID_ANY &&
(event.GetId() >= tableId1 && event.GetId() <= tableId2)))
{
event.Skip(false);
event.m_callbackUserData = entry.m_callbackUserData;
wxTheApp->CallEventHandler(handler, *entry.m_fn, event);
}
return false;
}
这里匹配到entry
也就找到了处理函数,又经过曲折的几部,最终调到了
BombCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
消息机制总结
窗口创建过程
消息分发过程
待补充
其他待整理的信息
RTTI 实现
wxIMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler);
展开如下
wxClassInfo wxApp::ms_classInfo(L"wxApp", &wxEvtHandler::ms_classInfo, 0, (int)sizeof(wxApp), wxApp::wxCreateObject);
wxClassInfo* wxApp::GetClassInfo() const { return &wxApp::ms_classInfo; }
wxObject* wxApp::wxCreateObject() { return new wxApp; };
生成一个 wxClassInfo
静态成员变量
event机制
const wxEventTable wxApp::sm_eventTable = { &wxEvtHandler::sm_eventTable, &wxApp::sm_eventTableEntries[0] };
const wxEventTable* wxApp::GetEventTable() const { return &wxApp::sm_eventTable; }
wxEventHashTable wxApp::sm_eventHashTable(wxApp::sm_eventTable);
wxEventHashTable& wxApp::GetEventHashTable() const { return wxApp::sm_eventHashTable; }
const wxEventTableEntry wxApp::sm_eventTableEntries[] = {
wxEventTableEntry(wxEVT_IDLE, wxID_ANY, wxID_ANY, wxNewEventTableFunctor(wxEVT_IDLE, wxEventFunctionCast(static_cast<wxIdleEventFunction>(&wxApp::OnIdle))), 0),
wxEventTableEntry(wxEVT_END_SESSION, wxID_ANY, wxID_ANY, wxNewEventTableFunctor(wxEVT_END_SESSION, wxEventFunctionCast(static_cast<wxCloseEventFunction>(&wxApp::OnEndSession))), 0),
wxEventTableEntry(wxEVT_QUERY_END_SESSION, wxID_ANY, wxID_ANY, wxNewEventTableFunctor(wxEVT_QUERY_END_SESSION, wxEventFunctionCast(static_cast<wxCloseEventFunction>(&wxApp::OnQueryEndSession))), 0),
wxEventTableEntry(wxEVT_NULL, 0, 0, 0, 0) };
struct WXDLLIMPEXP_BASE wxEventTable
{
const wxEventTable *baseTable; // base event table (next in chain)
const wxEventTableEntry *entries; // bottom of entry array
};
const wxEventTable wxApp::sm_eventTable = { &wxEvtHandler::sm_eventTable, &wxApp::sm_eventTableEntries[0] };
一个wxEventTable
静态常量成员,wxApp::sm_eventTable
。
wxApp::sm_eventTable.baseTable
指向自己 wxEvtHandler::sm_eventTable
基类同名成员
wxApp::sm_eventTable.entries
指向自己 wxApp::sm_eventTableEntries[0]
一个wxEventHashTable
静态成员 wxApp::sm_eventHashTable
。
一个 wxEventTableEntry
静态常量数组 wxApp::sm_eventTableEntries[]
保存ID和成员函数的对应关系