📄 mainfrm.cpp
字号:
/*
* Copyright (C) 2001-2005 Jacek Sieka, arnetheduck on gmail point com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "stdafx.h"
#include "../client/DCPlusPlus.h"
#include "Resource.h"
#include "MainFrm.h"
#include "AboutDlg.h"
#include "HubFrame.h"
#include "SearchFrm.h"
#include "PublicHubsFrm.h"
#include "PropertiesDlg.h"
#include "UsersFrame.h"
#include "DirectoryListingFrm.h"
#include "FavoritesFrm.h"
#include "NotepadFrame.h"
#include "QueueFrame.h"
#include "SpyFrame.h"
#include "FinishedFrame.h"
#include "ADLSearchFrame.h"
#include "FinishedULFrame.h"
#include "TextFrame.h"
#include "StatsFrame.h"
#include "LineDlg.h"
#include "HashProgressDlg.h"
#include "UPnP.h"
#include "../client/ConnectionManager.h"
#include "../client/DownloadManager.h"
#include "../client/UploadManager.h"
#include "../client/StringTokenizer.h"
#include "../client/SimpleXML.h"
#include "../client/ShareManager.h"
#include "../client/version.h"
MainFrame::MainFrame() : trayMessage(0), trayIcon(false), maximized(false), lastUpload(-1), lastUpdate(0),
lastUp(0), lastDown(0), oldshutdown(false), stopperThread(NULL), c(new HttpConnection()),
closing(false), missedAutoConnect(false)
{
memset(statusSizes, 0, sizeof(statusSizes));
links.homepage = _T("http://dcplusplus.sourceforge.net/");
links.downloads = links.homepage + _T("download/");
links.translations = _T("http://sourceforge.net/tracker/?atid=460289&group_id=40287");
links.faq = links.homepage + _T("faq/faq.php?list=all&prog=1&lang=en");
links.help = links.homepage + _T("forum/");
links.discuss = links.homepage + _T("forum/");
links.features = links.homepage + _T("bugs/");
links.bugs = links.homepage + _T("bugs/");
};
MainFrame::~MainFrame() {
m_CmdBar.m_hImageList = NULL;
images.Destroy();
largeImages.Destroy();
largeImagesHot.Destroy();
WinUtil::uninit();
}
DWORD WINAPI MainFrame::stopper(void* p) {
MainFrame* mf = (MainFrame*)p;
HWND wnd, wnd2 = NULL;
while( (wnd=::GetWindow(mf->m_hWndMDIClient, GW_CHILD)) != NULL) {
if(wnd == wnd2)
Sleep(100);
else {
::PostMessage(wnd, WM_CLOSE, 0, 0);
wnd2 = wnd;
}
}
shutdown();
mf->PostMessage(WM_CLOSE);
return 0;
}
LRESULT MainFrame::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) {
TimerManager::getInstance()->addListener(this);
QueueManager::getInstance()->addListener(this);
LogManager::getInstance()->addListener(this);
WinUtil::init(m_hWnd);
// Register server socket message
WSAAsyncSelect(ConnectionManager::getInstance()->getServerSocket().getSocket(),
m_hWnd, SERVER_SOCKET_MESSAGE, FD_ACCEPT);
trayMessage = RegisterWindowMessage(_T("TaskbarCreated"));
TimerManager::getInstance()->start();
// Set window name
SetWindowText(_T(APPNAME) _T(" ") _T(VERSIONSTRING));
// Load images
// create command bar window
HWND hWndCmdBar = m_CmdBar.Create(m_hWnd, rcDefault, NULL, ATL_SIMPLE_CMDBAR_PANE_STYLE);
m_hMenu = WinUtil::mainMenu;
// attach menu
m_CmdBar.AttachMenu(m_hMenu);
// load command bar images
images.CreateFromImage(IDB_TOOLBAR, 16, 15, CLR_DEFAULT, IMAGE_BITMAP, LR_CREATEDIBSECTION | LR_SHARED);
m_CmdBar.m_hImageList = images;
m_CmdBar.m_arrCommand.Add(ID_FILE_CONNECT);
m_CmdBar.m_arrCommand.Add(ID_FILE_RECONNECT);
m_CmdBar.m_arrCommand.Add(IDC_FOLLOW);
m_CmdBar.m_arrCommand.Add(IDC_FAVORITES);
m_CmdBar.m_arrCommand.Add(IDC_FAVUSERS);
m_CmdBar.m_arrCommand.Add(IDC_QUEUE);
m_CmdBar.m_arrCommand.Add(IDC_FINISHED);
m_CmdBar.m_arrCommand.Add(IDC_FINISHED_UL);
m_CmdBar.m_arrCommand.Add(ID_FILE_SEARCH);
m_CmdBar.m_arrCommand.Add(IDC_FILE_ADL_SEARCH);
m_CmdBar.m_arrCommand.Add(IDC_SEARCH_SPY);
m_CmdBar.m_arrCommand.Add(IDC_OPEN_FILE_LIST);
m_CmdBar.m_arrCommand.Add(ID_FILE_SETTINGS);
m_CmdBar.m_arrCommand.Add(IDC_NOTEPAD);
m_CmdBar.m_arrCommand.Add(IDC_NET_STATS);
m_CmdBar.m_arrCommand.Add(ID_WINDOW_CASCADE);
m_CmdBar.m_arrCommand.Add(ID_WINDOW_TILE_HORZ);
m_CmdBar.m_arrCommand.Add(ID_WINDOW_TILE_VERT);
m_CmdBar.m_arrCommand.Add(ID_WINDOW_MINIMIZE_ALL);
m_CmdBar.m_arrCommand.Add(ID_WINDOW_RESTORE_ALL);
// remove old menu
SetMenu(NULL);
HWND hWndToolBar = createToolbar();
CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);
AddSimpleReBarBand(hWndCmdBar);
AddSimpleReBarBand(hWndToolBar, NULL, TRUE);
CreateSimpleStatusBar();
ctrlStatus.Attach(m_hWndStatusBar);
ctrlStatus.SetSimple(FALSE);
int w[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
ctrlStatus.SetParts(8, w);
statusSizes[0] = WinUtil::getTextWidth(TSTRING(AWAY), ::GetDC(ctrlStatus.m_hWnd)); // for "AWAY" segment
CToolInfo ti(TTF_SUBCLASS, ctrlStatus.m_hWnd);
ctrlLastLines.Create(ctrlStatus.m_hWnd, rcDefault, NULL, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP, WS_EX_TOPMOST);
ctrlLastLines.AddTool(&ti);
CreateMDIClient();
m_CmdBar.SetMDIClient(m_hWndMDIClient);
WinUtil::mdiClient = m_hWndMDIClient;
ctrlTab.Create(m_hWnd, rcDefault);
WinUtil::tabCtrl = &ctrlTab;
transferView.Create(m_hWnd);
SetSplitterPanes(m_hWndMDIClient, transferView.m_hWnd);
SetSplitterExtendedStyle(SPLIT_PROPORTIONAL);
m_nProportionalPos = 8000;
UIAddToolBar(hWndToolBar);
UISetCheck(ID_VIEW_TOOLBAR, 1);
UISetCheck(ID_VIEW_STATUS_BAR, 1);
UISetCheck(ID_VIEW_TRANSFER_VIEW, 1);
// register object for message filtering and idle updates
CMessageLoop* pLoop = _Module.GetMessageLoop();
ATLASSERT(pLoop != NULL);
pLoop->AddMessageFilter(this);
pLoop->AddIdleHandler(this);
c->addListener(this);
c->downloadFile("http://dcplusplus.sourceforge.net/version.xml");
if(BOOLSETTING(OPEN_PUBLIC)) PostMessage(WM_COMMAND, ID_FILE_CONNECT);
if(BOOLSETTING(OPEN_FAVORITE_HUBS)) PostMessage(WM_COMMAND, IDC_FAVORITES);
if(BOOLSETTING(OPEN_FAVORITE_HUBS)) PostMessage(WM_COMMAND, IDC_FAVUSERS);
if(BOOLSETTING(OPEN_QUEUE)) PostMessage(WM_COMMAND, IDC_QUEUE);
if(BOOLSETTING(OPEN_FINISHED_DOWNLOADS)) PostMessage(WM_COMMAND, IDC_FINISHED);
if(BOOLSETTING(OPEN_FINISHED_DOWNLOADS)) PostMessage(WM_COMMAND, IDC_FINISHED_UL);
if(BOOLSETTING(OPEN_SEARCH_SPY)) PostMessage(WM_COMMAND, IDC_SEARCH_SPY);
if(BOOLSETTING(OPEN_NOTEPAD)) PostMessage(WM_COMMAND, IDC_NOTEPAD);
if(!BOOLSETTING(SHOW_STATUSBAR))
PostMessage(WM_COMMAND, ID_VIEW_STATUS_BAR);
if(!BOOLSETTING(SHOW_TOOLBAR))
PostMessage(WM_COMMAND, ID_VIEW_TOOLBAR);
if(!BOOLSETTING(SHOW_TRANSFERVIEW))
PostMessage(WM_COMMAND, ID_VIEW_TRANSFER_VIEW);
if(!(GetAsyncKeyState(VK_SHIFT) & 0x8000))
PostMessage(WM_SPEAKER, AUTO_CONNECT);
PostMessage(WM_SPEAKER, PARSE_COMMAND_LINE);
File::ensureDirectory(SETTING(LOG_DIRECTORY));
startSocket();
// we should have decided what ports we are using by now
// so if we are using UPnP lets open the ports.
// Initialize (no more need for all these elses)
UPnP_TCPConnection = UPnP_UDPConnection = NULL;
if( BOOLSETTING( SETTINGS_USE_UPNP ) )
{
if (
( WinUtil::getOsMajor() >= 5 && WinUtil::getOsMinor() >= 1 ) //WinXP & WinSvr2003
|| WinUtil::getOsMajor() >= 6 ) //Longhorn
{
UPnP_TCPConnection = new UPnP( Util::getLocalIp(), "TCP", APPNAME " Download Port (" + Util::toString(ConnectionManager::getInstance()->getPort()) + " TCP)", ConnectionManager::getInstance()->getPort() );
UPnP_UDPConnection = new UPnP( Util::getLocalIp(), "UDP", APPNAME " Search Port (" + Util::toString(SearchManager::getInstance()->getPort()) + " UDP)", SearchManager::getInstance()->getPort() );
if ( FAILED(UPnP_UDPConnection->OpenPorts()) || FAILED(UPnP_TCPConnection->OpenPorts()) )
{
LogManager::getInstance()->message(STRING(UPNP_FAILED_TO_CREATE_MAPPINGS));
MessageBox(CTSTRING(UPNP_FAILED_TO_CREATE_MAPPINGS), _T(APPNAME) _T(" ") _T(VERSIONSTRING), MB_OK | MB_ICONWARNING);
// fall-back to passive mode
SettingsManager::getInstance()->set(SettingsManager::CONNECTION_TYPE, SettingsManager::CONNECTION_PASSIVE);
// We failed! thus reset the objects
delete UPnP_TCPConnection;
delete UPnP_UDPConnection;
UPnP_TCPConnection = UPnP_UDPConnection = NULL;
}
else
{
// now lets configure the external IP (connect to me) address
string ExternalIP = UPnP_TCPConnection->GetExternalIP();
if ( ExternalIP.empty() == false )
{
// woohoo, we got the external IP from the UPnP framework
SettingsManager::getInstance()->set(SettingsManager::SERVER, ExternalIP );
SettingsManager::getInstance()->set(SettingsManager::CONNECTION_TYPE, SettingsManager::CONNECTION_ACTIVE);
}
else
{
//:-( Looks like we have to rely on the user setting the external IP manually
// no need to do cleanup here because the mappings work
LogManager::getInstance()->message(STRING(UPNP_FAILED_TO_GET_EXTERNAL_IP));
MessageBox(CTSTRING(UPNP_FAILED_TO_GET_EXTERNAL_IP), _T(APPNAME) _T(" ") _T(VERSIONSTRING), MB_OK | MB_ICONWARNING);
}
}
}
else
{
LogManager::getInstance()->message(STRING(OPERATING_SYSTEM_NOT_COMPATIBLE));
}
}
if(SETTING(NICK).empty()) {
PostMessage(WM_COMMAND, IDC_HELP_README);
PostMessage(WM_COMMAND, ID_FILE_SETTINGS);
}
// We want to pass this one on to the splitter...hope it get's there...
bHandled = FALSE;
return 0;
}
/**
* @todo Fix this, it's dead ugly...
*/
void MainFrame::startSocket() {
SearchManager::getInstance()->disconnect();
ConnectionManager::getInstance()->disconnect();
if(SETTING(CONNECTION_TYPE) == SettingsManager::CONNECTION_ACTIVE) {
short lastPort = (short)SETTING(IN_PORT);
short firstPort = lastPort;
while(true) {
try {
ConnectionManager::getInstance()->setPort(lastPort);
WSAAsyncSelect(ConnectionManager::getInstance()->getServerSocket().getSocket(), m_hWnd, SERVER_SOCKET_MESSAGE, FD_ACCEPT);
break;
} catch(const Exception& e) {
dcdebug("MainFrame::OnCreate caught %s\n", e.getError().c_str());
short newPort = (short)((lastPort == 32000) ? 1025 : lastPort + 1);
SettingsManager::getInstance()->setDefault(SettingsManager::IN_PORT, newPort);
if(SETTING(IN_PORT) == lastPort || (firstPort == newPort)) {
// Changing default didn't change port, a fixed port must be in use...(or we
// tried all ports
AutoArray<TCHAR> buf(STRING(PORT_IS_BUSY).size() + 8);
_stprintf(buf, CTSTRING(PORT_IS_BUSY), SETTING(IN_PORT));
MessageBox(buf, _T(APPNAME) _T(" ") _T(VERSIONSTRING), MB_ICONSTOP | MB_OK);
break;
}
lastPort = newPort;
}
}
lastPort = (short)SETTING(UDP_PORT);
firstPort = lastPort;
while(true) {
try {
SearchManager::getInstance()->setPort(lastPort);
break;
} catch(const Exception& e) {
dcdebug("MainFrame::OnCreate caught %s\n", e.getError().c_str());
short newPort = (short)((lastPort == 32000) ? 1025 : lastPort + 1);
SettingsManager::getInstance()->setDefault(SettingsManager::UDP_PORT, newPort);
if(SETTING(UDP_PORT) == lastPort || (firstPort == newPort)) {
// Changing default didn't change port, a fixed port must be in use...(or we
// tried all ports
AutoArray<TCHAR> buf(STRING(PORT_IS_BUSY).size() + 8);
_stprintf(buf, CTSTRING(PORT_IS_BUSY), SETTING(UDP_PORT));
MessageBox(buf, _T(APPNAME) _T(" ") _T(VERSIONSTRING), MB_ICONSTOP | MB_OK);
break;
}
lastPort = newPort;
}
}
}
}
HWND MainFrame::createToolbar() {
CToolBarCtrl ctrlToolbar;
largeImages.CreateFromImage(IDB_TOOLBAR20, 20, 15, CLR_DEFAULT, IMAGE_BITMAP, LR_CREATEDIBSECTION | LR_SHARED);
largeImagesHot.CreateFromImage(IDB_TOOLBAR20_HOT, 20, 15, CLR_DEFAULT, IMAGE_BITMAP, LR_CREATEDIBSECTION | LR_SHARED);
ctrlToolbar.Create(m_hWnd, NULL, NULL, ATL_SIMPLE_CMDBAR_PANE_STYLE | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS, 0, ATL_IDW_TOOLBAR);
ctrlToolbar.SetImageList(largeImages);
ctrlToolbar.SetHotImageList(largeImagesHot);
const int numButtons = 21;
TBBUTTON tb[numButtons];
memset(tb, 0, sizeof(tb));
int n = 0, bitmap = 0;
tb[n].iBitmap = bitmap++;
tb[n].idCommand = ID_FILE_CONNECT;
tb[n].fsState = TBSTATE_ENABLED;
tb[n].fsStyle = TBSTYLE_BUTTON | TBSTYLE_AUTOSIZE;
n++;
tb[n].fsStyle = TBSTYLE_SEP;
n++;
tb[n].iBitmap = bitmap++;
tb[n].idCommand = ID_FILE_RECONNECT;
tb[n].fsState = TBSTATE_ENABLED;
tb[n].fsStyle = TBSTYLE_BUTTON | TBSTYLE_AUTOSIZE;
n++;
tb[n].iBitmap = bitmap++;
tb[n].idCommand = IDC_FOLLOW;
tb[n].fsState = TBSTATE_ENABLED;
tb[n].fsStyle = TBSTYLE_BUTTON | TBSTYLE_AUTOSIZE;
n++;
tb[n].fsStyle = TBSTYLE_SEP;
n++;
tb[n].iBitmap = bitmap++;
tb[n].idCommand = IDC_FAVORITES;
tb[n].fsState = TBSTATE_ENABLED;
tb[n].fsStyle = TBSTYLE_BUTTON | TBSTYLE_AUTOSIZE;
n++;
tb[n].iBitmap = bitmap++;
tb[n].idCommand = IDC_FAVUSERS;
tb[n].fsState = TBSTATE_ENABLED;
tb[n].fsStyle = TBSTYLE_BUTTON | TBSTYLE_AUTOSIZE;
n++;
tb[n].fsStyle = TBSTYLE_SEP;
n++;
tb[n].iBitmap = bitmap++;
tb[n].idCommand = IDC_QUEUE;
tb[n].fsState = TBSTATE_ENABLED;
tb[n].fsStyle = TBSTYLE_BUTTON | TBSTYLE_AUTOSIZE;
n++;
tb[n].iBitmap = bitmap++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -