手抄报 安全手抄报 手抄报内容 手抄报图片 英语手抄报 清明节手抄报 节约用水手抄报

sqlyog代码框架分析

时间:2024-10-12 06:49:29

1、 从网上下载SQLyog源代码, 并编译这份源代码, 具体过程见本人的另外一篇经验"sqlyog源代码下载编译教程", 可以在我的经验文章中找到这篇文章, 具体如下图所示:

sqlyog代码框架分析

2、 使用vs2017(假定已经安装支持了MFC)打开SQLyog项目, 在sqlyog-community源代码目录下面有一个build目录, 其中有项目工程文件SQLyogCommunity.sln, 双击可以打开项目, 具体如下图所示:

sqlyog代码框架分析
sqlyog代码框架分析

3、 点击"生成解决方案", 无错误, 输出提示"全部重新生成: 成功 1 个,失败 0 个,跳过 0 个", 表明成功编译生成了SQLyog客户端程序, 在"..\sqlyog-community\bin\win32\debug"目录下面生成了一个可执行exe文件SQLyogCommunity.exe, 具体如下图所示:

sqlyog代码框架分析
sqlyog代码框架分析

4、 点击"本地Win...调试器", 启动运行程序, 并让其断点到winmain函数的入口处, 程序启动以后, 首先断点在WinMain函数中, 具体如下图所示:

sqlyog代码框架分析

5、 可以看到在sqlyog项目代码中有WinMain函数, 而Winmain是windows平台下应用程序的入口函数, 具体点说WinMain()函数是Win32程序开始的入口点, 也就表明sqlyog项目是使用Win32 SDK来编码开发实现的。

6、 WinMain函数原型:int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, LPSTR lpCmdLine, int nCmdShow ); hInstance ---> 当前实例的句柄 hPrevInstance ---> 前一个实例的句柄 lpCmdLine ---> 命令行参数 nCmdShow ---> 窗体显示形式(最大化、最小化)

7、 在windows下, win32 sdk编写应用程序的一般步骤是: (1).实现函数WinMain, 也就是根据其原型在源代码中定义它; (2).创建一个窗口; (3).进行消息的循环; (4).编写窗口过程函数。 了解了win32 sdk编程步骤, 下面结合sqlyog项目代码来一步步分析下。

8、 sqlyog项目代码中有一个名为WinMain.cpp的文件, 在这个文件里面实现了函数WinMain, 代码如下:// Function :// The main function of the application.// The start of the software.wyInt32 WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance, PSTR cmdline, wyInt32 icmdshow){ ....... return msg.wParam;} 具体如下图:

sqlyog代码框架分析

9、 WinMain函数开始是一系列的变量声明, 定义配置与相关的初始化, 具体如下面代码:HINSTANCE hrich, hsci; #ifdef BLACKBOX HINSTANCE hblackbox;#endif FrameWindow *mainwin; MSG msg; wyBool isVistaAnd32BitSQLyog = wyFalse; pGlobals = new GLOBALS; _ASSERT(pGlobals != NULL); //DEBUG_ENTER("WinMain"); //call mysql_library_init to avoid crash if (mysql_library_init(0, NULL, NULL)) { DisplayErrorText(1, _("could not initialize MySQL library")); return 0; } // First clear every stuff in the pglobals variable. InitGlobals(pGlobals); InitWinSock(); ///*Checks whether commandline argument as got explicit path for .ini, and other logfiles. //also filename whose contents as to be displayed in Sqlyog Editor //Otion can be any of one //i. SQLyogEnt.exe -dir "E:\path" -f "D:\test.sql" //ii. SQLyogEnt.exe -dir "E:\path" "D:\test.sql" //iii. SQLyogEnt.exe -f "D:\test.sql" -dir "E:\path" -f //-dir stands for explicit path for .ini, tags, logs, favourites , etc //-f stands for file to be oponed in editor //*/ //Gets the Attributes passed through command line(-f, -dir) if(pGlobals->m_configdirpath.GetLength())//unsigned long len=0;// if(len=pGlobals->m_configdirpath.GetLength()) pGlobals->m_configdirpath.Clear(); if(GetConfigDetails(cmdline) == wyFalse) return 0; CreateInitFile();#ifndef _WIN64 OSVERSIONINFOEX osvi; osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); //get the OS version and set the display style accordingly if (GetVersionEx((OSVERSIONINFO*)&osvi)) { if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0 && osvi.wProductType == VER_NT_WORKSTATION) isVistaAnd32BitSQLyog = wyTrue; }#endif#ifdef _DEBUG HANDLE hlogfile = NULL; hlogfile = CreateFile(L"SQLyog_debug_log.txt", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);#else //Initialize the Path for .INI & .dmp files CreateInitFile(); if (isVistaAnd32BitSQLyog == wyFalse) { MiniDump dumpcrash; if (IsCrashDumpSupported() == wyTrue) dumpcrash.InitDumpDetails(pGlobals->m_configdirpath.GetString()); } #endif _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_WNDW); _CrtSetReportFile(_CRT_WARN, hlogfile); _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_WNDW); _CrtSetReportFile(_CRT_ERROR, hlogfile); _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_WNDW); _CrtSetReportFile(_CRT_ASSERT, hlogfile); _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE ); _CrtSetReportFile(_CRT_WARN, hlogfile); _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE ); _CrtSetReportFile(_CRT_ERROR, hlogfile); _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE ); _CrtSetReportFile(_CRT_ASSERT, hlogfile); _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); VERIFY(hsci = ::LoadLibrary(L"SciLexer.dll")); if(!hsci) { DisplayErrorText(GetLastError(), _("Error loading SciLexer.dll")); VERIFY(FreeLibrary(hsci)); return 0; } pGlobals->m_statusbarsections = STATUS_BAR_SECTIONS; /* register scintilla */ //Scintilla_RegisterClasses(NULL);#ifndef VC6 /* startup gdiplus...this is required to display image in BLOB window */ ULONG_PTR gditoken; Gdiplus::GdiplusStartupInput startupinput; Gdiplus::GdiplusStartup(&gditoken, &startupinput, NULL);#endif pGlobals->m_hinstance = hinstance; VERIFY(hrich = ::LoadLibrary(L"Riched20.dll"));#ifdef BLACKBOX VERIFY(hblackbox = ::LoadLibrary(L"BlackBox.dll"));#endif /* check for library problems */ if(!hrich) { DisplayErrorText(GetLastError(), _("Error loading riched20.dll")); VERIFY(FreeLibrary(hsci)); return 0; } 为整个sqlyog项目的运行做初始化准备工作。

10、 初始化准备工作完成以后, 使用以下代码来创建sqlyog软件相关的窗口:pGlobals->m_f足毂忍珩indreplace = wyFalse; CreateCustomTabIconList(); // Initialize the common controls. InitCustomControls(); CollectCurrentWindowsVersion(); pGlobals->m_modulenamelength = GetModuleNameLength(); wyTheme::SubclassControls(); if(!pGlobals->m_modulenamelength) { DisplayErrorText(GetLastError(), _("GetModuleFileName length failed!")); return 0; } SetLanguage(NULL, wyTrue); wyTheme::Init(); // Create the mainwindow. mainwin = new FrameWindow(pGlobals->m_hinstance); 类FrameWindow是sqlyog客户端的主界面窗口对应的类函数, 也就是整个应用程序的主窗口, 定义实现的文件在FrameWindow.h和FrameWindow.cpp, 这样子就有了程序的主框架窗口了, ui界面层的最大部分我们已经知道是如何生成的了。

11、 sqlyog客户端主界面确立以后, 接下来我们就需要事先消息循谪藁钴碳环了, 整个循环主要是来处理消息的,代码如下所示:// The main loop for messages. while(G髫潋啜缅etMessage(&msg, NULL, 0, 0)) { if(pGlobals->m_pcmainwin->m_finddlg) { if((pGlobals->m_pcmainwin->m_finddlg && IsWindowVisible(pGlobals->m_pcmainwin->m_finddlg)&& IsDialogMessage(pGlobals->m_pcmainwin->m_finddlg, &msg))) { pGlobals->m_findreplace = wyTrue; continue; } } if(!TranslateMDISysAccel(pGlobals->m_hwndclient, &msg)) { if(!(TranslateAccelerator(mainwin->GetHwnd(), g_accel, &msg))) { /// code to catch Accel(short-cuts for Save & Revert) key-press on Create/Alter table tabbed interface if(pGlobals->m_pcmainwin->m_htabinterface && IsDialogMessage(pGlobals->m_pcmainwin->m_htabinterface, &msg)) { continue; } if(pGlobals->m_pcmainwin->m_hwndtooltip && msg.message == WM_LBUTTONDOWN) { FrameWindow::ShowQueryExecToolTip(wyFalse); } pGlobals->m_findreplace = wyFalse; TranslateMessage(&msg); DispatchMessage(&msg); } } } 上面代码开启了消息循环。 Windows操作系统为每一个正在运行的应用程序保持有一个消息队列。 当有事件发生后, Windows并不是将这个激发事件直接送给应用程序,而是先将其翻译成一个Windows消息,然后再把这个消息加入到这个应用程序的消息队列中去。应用程序需要通过消息循环来接收这些消息。 即Windows 中有一个系统消息队列, 对于每一个正在执行的Windows应用程序, 系统为其建立一个"消息队列", 即应用程序队列,用来存放该程序可能创建的各种窗口的消息。 应用程序中含有一段称作"消息循环"的代码,用来从消息队列中检索这些消息并把它们分发到相应的窗口函数中。 Windows是以消息驱动的操作系统, Windows 消息提供了应用程序与Windows系统之间进行通讯的手段。 Windows应用程序是基于消息的程序设计模式, 使用事件驱动编程模型,分为消息概述、消息结构、消息类型。 消息循环代码是应用程序中主函数WinMain ( )中类似如下的程序段:while(GetMessage(&msg,NULL,0,0)){ TranslateMessage(&msg); //从消息队列中取得消息 DispatchMessage(&msg); //检索并生成字符消息WM_CHAR //将消息发送给相应的窗口函数} 由此可见, 所谓"消息循环", 实际是程序循环。可以看到sqlyog客户端应用程序的消息循环就是在WinMain.cpp中实现的。

12、 由于Windows 应用程序创建的每个窗口都在系统核心注册一个相应的窗口函数, 窗口函数程序代码形式上是一个巨大的switch 语句, 吹涡皋陕用以处理由消息循环发送到该窗口的消息, 窗口函数由Windows 采用消息驱动的形式直接调用,而不是由应用程序显示调用的, 窗口函数处理完消息后又将控制权返回给Windows。 也就是说sqlyog客户端应用程序中的每个窗口都会注册一个相应的窗口函数, 而每个窗口都对应有一个头文件和一个cpp文件, 举例如"Connect to MySQL Host"这个窗口(File--->New Connection...), 可以看到整个过程的调用代码堆栈图下图所示, 可以看到最顶层的是FrameWindow::WndProc()函数,// The window procedure for MainWindow.// It creates all its child window in WM_CREATE message.LRESULT CALLBACK FrameWindow::WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam){ ........}整个函数窗口过程函数在WM_CREATE消息响应时候创建了所有子窗口, case WM_CREATE: pcmainwin->OnCreate(); return 0;函数代码如下:void FrameWindow::OnCreate(){ // CreateToolBarWindow(); CreateStatusBarWindow(); CreateMDIWindow(); m_findmsg = RegisterWindowMessage(FINDMSGSTRING); CheckForAutoKeywords(); ConvertIniFileToUtf8(); MigrateFiles(); //MigratePersonalFolderToFavorites(); return;} 在这里创建了主界面窗口的子窗口, 每个子窗口都有一个窗口过程函数来处理各自的消息, 到此sqlyog客户端整个主体框架分析完毕。

sqlyog代码框架分析
© 手抄报圈