看程序中如下宏语句:
enum
{
Minimal_Quit = wxID_EXIT,
Minimal_About = wxID_ABOUT
};
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(Minimal_Quit, MyFrame::OnQuit)
EVT_MENU(Minimal_About, MyFrame::OnAbout)
END_EVENT_TABLE()
IMPLEMENT_APP(MyApp)
现在展开这些宏来分析内部的运行机制
1. 展开BEGIN_EVENT_TABLE(MyFrame, wxFrame)
2. 展开EVT_MENU(Minimal_Quit, MyFrame::OnQuit)
3. 展开END_EVENT_TABLE()
1. 在wxWidgets-2.6.2\include\wx\event.h文件中宏BEGIN_EVENT_TABLE被定义如下:
#define BEGIN_EVENT_TABLE(theClass, baseClass) const wxEventTable theClass::sm_eventTable = { &baseClass::sm_eventTable, &theClass::sm_eventTableEntries[0] }; const wxEventTable *theClass::GetEventTable() const { return &theClass::sm_eventTable; } wxEventHashTable theClass::sm_eventHashTable(theClass::sm_eventTable); wxEventHashTable &theClass::GetEventHashTable() const { return theClass::sm_eventHashTable; } const wxEventTableEntry theClass::sm_eventTableEntries[] = {
经过预编译处理后程序如下:
const wxEventTable MyFrame::sm_eventTable = { &wxFrame::sm_eventTable, &MyFrame::sm_eventTableEntries[0] };
const wxEventTable *MyFrame::GetEventTable() const { return &MyFrame::sm_eventTable; }
wxEventHashTable MyFrame::sm_eventHashTable(MyFrame::sm_eventTable);
wxEventHashTable &MyFrame::GetEventHashTable() const { return MyFrame::sm_eventHashTable; }
const wxEventTableEntry MyFrame::sm_eventTableEntries[] = {
2. 在wxWidgets-2.6.2\include\wx\event.h文件中宏EVT_MENU被定义如下:
#define EVT_MENU(winid, func) wx__DECLARE_EVT1(wxEVT_COMMAND_MENU_SELECTED, winid, wxCommandEventHandler(func))
#define wx__DECLARE_EVT1(evt, id, fn) wx__DECLARE_EVT2(evt, id, wxID_ANY, fn)
#define wx__DECLARE_EVT2(evt, id1, id2, fn) DECLARE_EVENT_TABLE_ENTRY(evt, id1, id2, fn, NULL),
#define DECLARE_EVENT_TABLE_ENTRY(type, winid, idLast, fn, obj) wxEventTableEntry(type, winid, idLast, fn, obj)
当中wxCommandEventHandler(func)进行静态强制类型转化,把指定的函数(func)指针类型转化为事件处理函数类型
#define wxCommandEventHandler(func) (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxCommandEventFunction, &func)
注: typedef void (wxObject::*wxObjectEventFunction)(wxEvent&);
typedef void (wxEvtHandler::*wxEventFunction)(wxEvent&);
typedef void (wxEvtHandler::*wxCommandEventFunction)(wxCommandEvent&);
#define wxStaticCastEvent(type, val) wx_static_cast(type, val)
#define wx_static_cast(t, x) ((t)(x)) //进行强制类型转化
EVT_MENU(Minimal_Quit, MyFrame::OnQuit)经过预编译处理后程序如下:
wxEventTableEntry(wxEVT_COMMAND_MENU_SELECTED, Minimal_Quit, wxID_ANY, MyFrame::OnQuit, NULL)
3. 在wxWidgets-2.6.2\include\wx\event.h文件中宏BEGIN_EVENT_TABLE被定义如下:
#define END_EVENT_TABLE() DECLARE_EVENT_TABLE_ENTRY( wxEVT_NULL, 0, 0, 0, 0 ) };
再展开DECLARE_EVENT_TABLE_ENTRY:
#define DECLARE_EVENT_TABLE_ENTRY(type, winid, idLast, fn, obj) wxEventTableEntry(type, winid, idLast, fn, obj)
经过预编译处理后程序如下:
wxEventTableEntry(wxEVT_NULL, 0, 0, 0, 0)};
综合上面所述,
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(Minimal_Quit, MyFrame::OnQuit)
EVT_MENU(Minimal_About, MyFrame::OnAbout)
END_EVENT_TABLE()
最终展开的效果为:
const wxEventTable MyFrame::sm_eventTable = { &wxFrame::sm_eventTable, &MyFrame::sm_eventTableEntries[0] };
const wxEventTable *MyFrame::GetEventTable() const { return &MyFrame::sm_eventTable; }
wxEventHashTable MyFrame::sm_eventHashTable(MyFrame::sm_eventTable);
wxEventHashTable &MyFrame::GetEventHashTable() const { return MyFrame::sm_eventHashTable; }
const wxEventTableEntry MyFrame::sm_eventTableEntries[] = {
wxEventTableEntry(wxEVT_COMMAND_MENU_SELECTED, Minimal_Quit, wxID_ANY, MyFrame::OnQuit, NULL),
wxEventTableEntry(wxEVT_COMMAND_MENU_SELECTED, Minimal_About, wxID_ANY, MyFrame::OnAbout, NULL),
wxEventTableEntry(wxEVT_NULL, 0, 0, 0, 0)
};
wxWidgets通过宏的方式在预编译时静态设置好了事件映射表, 把指定的一个唯一的命令ID和MyFrame的指定函数静态绑定。实际上也可以进行动态绑定,这里先不描述。
IMPLEMENT_APP(MyApp)宏展开如下:
IMPLEMENT_APP(appname)
l IMPLEMENT_APP_NO_THEMES(appname)
n IMPLEMENT_APP_NO_MAIN(appname)
wxAppConsole *wxCreateApp() { wxAppConsole::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE, "your program"); return new appname; } wxAppInitializer wxTheAppInitializer((wxAppInitializerFunction) wxCreateApp); appname& wxGetApp() { return *(appname *)wxTheApp; }
n IMPLEMENT_WXWIN_MAIN
extern "C" int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, \ wxCmdLineArgType lpCmdLine, int nCmdShow) { return wxEntry(hInstance, hPrevInstance, lpCmdLine, nCmdShow); }
l IMPLEMENT_WX_THEME_SUPPORT
最终的结果为:
wxAppConsole *wxCreateApp()
{
wxAppConsole::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE,
"your program");
return new MyApp;
}
wxAppInitializer
wxTheAppInitializer((wxAppInitializerFunction) wxCreateApp);
MyApp& wxGetApp() { return *( MyApp*)wxTheApp; }
extern "C" int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance, wxCmdLineArgType lpCmdLine,
int nCmdShow)
{
return wxEntry(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}
可以看出这个就是win32应用程序主程序了。它通过wxEntry函数实现整个主函数的功能,该函数与平台相关,可以自己调用本函数实现wxWidgets默认的入口函数(参考manual)。该函数的实现在wxWidgets-2.6.2\src\msw\main.cpp。
程序继续执行,在函数int wxEntryReal(int& argc, wxChar **argv)内部主要完成三个事情:
1: 调用wxApp::Initialize初始化应用程序,初始化时候调用wxApp::RegisterWindowClasses()注册一个窗口类,注册窗口类后, wxWidgets-2.6.2\src\msw\window.cpp文件下的LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)成为窗口事件处理主函数,负责窗口事件处理。后面创建MyFrame时候最终会调用CreateWindow创建函数主窗口。
2: 调用wxAppConsole::CallOnInit(),该函数最后调用bool MyApp::OnInit()虚拟函数初始化应用程序,因此经过wxWidgets封装后,呈现给用户的最终的主程序入口就是用户自己重载的OnInit()虚拟函数。在MyFrame构造函数调用wxTopLevelWindow::Create()完成窗口创建。
3: 最后调用wxAppBase::OnRun()进行消息循环接收发送, 把属于窗口的消息发送给wxWndProc进行处理。