#include "stdafx.h"
#include "teamtalk.h"
#include "UI/MainDialog.h"
#include "GlobalConfig.h"
#include "versioninfo.h"
#include "google/protobuf/stubs/common.h"
#include "utility/utilCommonAPI.h"
#include "utility/Multilingual.h"
#include "utility/utilStrCodingAPI.h"
#include "Modules/IHttpPoolModule.h"
#include "Modules/ILoginModule.h"
#include "Modules/IMiscModule.h" //一些比较杂的公用的接口函数
#include "Modules/ISysConfigModule.h"
#include "Modules/ITcpClientModule.h"
#include "Modules/UIEventManager.h"
#include "network/OperationManager.h"
#include "network/ImCore.h" //IM核心类:线程、TcpSockets的操作之类的
/*
* 指定重启管理器的风格
* 重启管理器可以支持多种风格,例如,有的风格(AFX_RESTART_MANAGER_SUPPORT_RESTART)只是将崩溃的应用程序重新启动,
* 而有的风格(AFX_RESTART_MANAGER_SUPPORT_ALL_ASPECTS)不仅将应用程序重新启动,还可以打开原来自动保存的文档,恢复应用程序到崩溃前的状态。
* 我们可以在应用程序类的构造函数中,通过指定CWinAppEx的dwRestartManagerSupportFlags成员变量来指定重启管理器的风格。
*/
CteamtalkApp::CteamtalkApp()
:m_pMainDialog(0)
{
m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART;
}
CteamtalkApp theApp; //MFC类实例
/*
* 应用程序入口
*/
BOOL CteamtalkApp::InitInstance()
{
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
InitCtrls.dwICC = ICC_WIN95_CLASSES; //用来注册InitCommonControls函数所注册的所有类。
InitCommonControlsEx(&InitCtrls);
//如果一个运行在 Windows XP 上的应用程序清单指定要使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,则需要 InitCommonControlsEx();否则,将无法创建窗口。
//YAOLOG 初始化
_InitLog();
//验证GOOGLE_PROTOBUF版本兼容性
// Verify that the version of the library that we linked against is
// compatible with the version of the headers we compiled against.
GOOGLE_PROTOBUF_VERIFY_VERSION;
//输出一行日志
LOG__(APP, _T("===================VersionNO:%d======BulidTime:%s--%s==========================")
, TEAMTALK_VERSION, util::utf8ToCString(__DATE__), util::utf8ToCString(__TIME__));
if (!__super::InitInstance()) //__super关键字:本类的基类CWinApp
{
LOG__(ERR, _T("__super::InitInstance failed."));
return FALSE;
}
//调用在应用程序对象的 InitInstance 函数中对此函数启用 OLE 控件包容的支持。
AfxEnableControlContainer();
//应用程序是否已经启动
if (_IsHaveInstance())
{
LOG__(ERR, _T("Had one instance,this will exit"));
HWND hwndMain = FindWindow(_T("TeamTalkMainDialog"), NULL); //寻找标题为TeamTalkMainDialog的进程
if (hwndMain)
{
::SendMessage(hwndMain, WM_START_MOGUTALKINSTANCE, NULL, NULL);
//该函数将指定的消息发送到一个或多个窗口。此函数为指定的窗口调用窗口程序,直到窗口程序处理完消息再返回。
//而和函数PostMessage不同,PostMessage是将一个消息寄送到一个线程的消息队列后就立即返回。
}
return FALSE;
}
//启动蓝狐大神写的IM核心类(线程启动,互斥锁。。。有兴趣可以深入去了解ImCore)
//start imcore lib
if (!imcore::IMLibCoreRunEvent())
{
LOG__(ERR, _T("start imcore lib failed!"));
}
LOG__(APP, _T("start imcore lib done"));
//start ui event
if (module::getEventManager()->startup() != imcore::IMCORE_OK)
{
LOG__(ERR, _T("start ui event failed"));
}
LOG__(APP, _T("start ui event done"));
//create user folders
_CreateUsersFolder();
//duilib初始化
CPaintManagerUI::SetInstance(AfxGetInstanceHandle()); //将程序实例与皮肤绘制管理器挂钩
//获取可执行程序的所在路径,指的是.exe文件路径
CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath() + _T("..\\gui\\"));//track这个设置了路径,会导致base里设置的无效。
//COM在OLE32.DLL和 OLE32.LIB定义了一些常用的函数。在使用这些函数前要先调用CoInitialize来初始化COM库
::CoInitialize(NULL);
//OleInitialize是初始化Ole的运行环境,Ole是在Com的基础上作的扩展,是ActiveX运行的基础,OleInitialize肯定会调用CoInitialize。
::OleInitialize(NULL);
//无需配置server(这里是初始化)
module::TTConfig* pCfg = module::getSysConfigModule()->getSystemConfig();
if (pCfg && pCfg->loginServIP.IsEmpty())
{
if (!module::getSysConfigModule()->showServerConfigDialog(NULL))
{
LOG__(APP, _T("server config canceled"));
return FALSE;
}
}
//创建登陆窗口,并启动它
if (!module::getLoginModule()->showLoginDialog())
{
LOG__(ERR, _T("login canceled"));
return FALSE;
}
LOG__(APP,_T("login success"));
//创建主窗口,只是初始化,这里不会ShowModal显示处理
if (!_CreateMainDialog())
{
LOG__(ERR, _T("Create MianDialog failed"));
return FALSE;
}
LOG__(APP, _T("Create MianDialog done"));
CPaintManagerUI::MessageLoop(); //DuiLib之消息循环。
CPaintManagerUI::Term(); //关闭压缩包
return TRUE;
}
//销毁主窗口
BOOL CteamtalkApp::_DestroyMainDialog()
{
delete m_pMainDialog;
m_pMainDialog = 0;
return TRUE;
}
//创建主窗口
BOOL CteamtalkApp::_CreateMainDialog()
{
m_pMainDialog = new MainDialog(); //新建主窗体类对象
PTR_FALSE(m_pMainDialog); //assert 该值为FALSE时中断当前操作
CString csTitle = util::getMultilingual()->getStringById(_T("STRID_GLOBAL_CAPTION_NAME")); //从bin\teamtalk\chinese.ini 配置文件中获取窗体标题
//创建主窗口(600宽,800高)
if (!m_pMainDialog->Create(NULL, csTitle
, UI_CLASSSTYLE_DIALOG, WS_EX_STATICEDGE /*| WS_EX_APPWINDOW*/ | WS_EX_TOOLWINDOW, 0, 0, 600, 800))
return FALSE;
m_pMainDialog->BringToTop(); //主窗体置于所有窗体上面
return TRUE;
}
//退出应用程序
BOOL CteamtalkApp::ExitInstance()
{
LOG__(APP, _T("Exit Instance"));
//close httppool
module::getHttpPoolModule()->shutdown();
LOG__(APP, _T("close http pool done"));
//close network socket io
module::getTcpClientModule()->shutdown();
LOG__(APP, _T("close tcpclient socket done"));
//stop imcore lib
imcore::IMLibCoreStopEvent();
LOG__(APP, _T("stop imcore lib done"));
//stop ui event
module::getEventManager()->shutdown();
LOG__(APP, _T("stop ui event done"));
//销毁主窗口
_DestroyMainDialog();
LOG__(APP,_T("MainDialog Destory done"));
//终止Winsock 2 DLL (Ws2_32.dll) 的使用.
WSACleanup();
// Optional: Delete all global objects allocated by libprotobuf.
google::protobuf::ShutdownProtobufLibrary();
LOG__(APP, _T("Exit OK"));
YAOLOG_EXIT;
return __super::ExitInstance(); ///__super关键字:本类的基类CWinApp
}
//创建用户目录
BOOL CteamtalkApp::_CreateUsersFolder()
{
module::IMiscModule* pModule = module::getMiscModule(); //定义一些比较杂的公用的接口函数的类实例
//users目录
if (!util::createAllDirectories(pModule->getUsersDir()))
{
LOG__(ERR, _T("_CreateUsersFolder users direcotry failed!"));
return FALSE;
}
//下载目录
if (!util::createAllDirectories(pModule->getDownloadDir()))
{
LOG__(ERR, _T("_CreateUsersFolder download direcotry failed!"));
return FALSE;
}
return TRUE;
}
//应用程序的HANDLE标识号
#ifdef _DEBUG
#define AppSingletonMutex _T("{7A666640-EDB3-44CC-954B-0C43F35A2E17}")
#else
#define AppSingletonMutex _T("{5676532A-6F70-460D-A1F0-81D6E68F046A}")
#endif
BOOL CteamtalkApp::_IsHaveInstance()
{
// 单实例运行
HANDLE hMutex = ::CreateMutex(NULL, TRUE, AppSingletonMutex);
if (hMutex != NULL && GetLastError() == ERROR_ALREADY_EXISTS)
{
MessageBox(0, _T("上次程序运行还没完全退出,请稍后再启动!"), _T("TeamTalk"), MB_OK);
return TRUE;
}
return FALSE;
}
//初始化YAOLOG日志
void CteamtalkApp::_InitLog()
{
std::string logConfig = util::cStringToString(util::getAppPath()) + "\\ttlogconfig.ini";
YAOLOG_INIT;
YAOLOG_CREATE(APP, true, YaoUtil::LOG_TYPE_TEXT);
YAOLOG_CREATE(NET, true, YaoUtil::LOG_TYPE_TEXT);
YAOLOG_CREATE(DEBG, true, YaoUtil::LOG_TYPE_TEXT);
YAOLOG_CREATE(ERR, true, YaoUtil::LOG_TYPE_TEXT);
YAOLOG_CREATE(SOCK, true, YaoUtil::LOG_TYPE_FORMATTED_BIN);
YAOLOG_SET_ATTR_FROM_CONFIG_FILE(APP, logConfig.c_str());
YAOLOG_SET_ATTR_FROM_CONFIG_FILE(NET, logConfig.c_str());
YAOLOG_SET_ATTR_FROM_CONFIG_FILE(DEBG, logConfig.c_str());
YAOLOG_SET_ATTR_FROM_CONFIG_FILE(ERR, logConfig.c_str());
YAOLOG_SET_ATTR_FROM_CONFIG_FILE(SOCK, logConfig.c_str());
}