📄 privateframe.cpp
字号:
/*
* Copyright (C) 2001-2006 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 "PrivateFrame.h"
#include "SearchFrm.h"
#include "WinUtil.h"
#include "../client/Client.h"
#include "../client/ClientManager.h"
#include "../client/Util.h"
#include "../client/LogManager.h"
#include "../client/UploadManager.h"
#include "../client/ShareManager.h"
#include "../client/FavoriteManager.h"
#include "../client/QueueManager.h"
#include "../client/StringTokenizer.h"
PrivateFrame::FrameMap PrivateFrame::frames;
LRESULT PrivateFrame::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
CreateSimpleStatusBar(ATL_IDS_IDLEMESSAGE, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP);
ctrlStatus.Attach(m_hWndStatusBar);
ctrlClient.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
WS_VSCROLL | ES_AUTOVSCROLL | ES_MULTILINE | ES_NOHIDESEL | ES_READONLY, WS_EX_CLIENTEDGE);
ctrlClient.FmtLines(TRUE);
ctrlClient.LimitText(0);
ctrlClient.SetFont(WinUtil::font);
ctrlMessage.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
ES_AUTOHSCROLL | ES_MULTILINE | ES_AUTOVSCROLL, WS_EX_CLIENTEDGE);
ctrlMessageContainer.SubclassWindow(ctrlMessage.m_hWnd);
ctrlClientContainer.SubclassWindow(ctrlClient.m_hWnd);
ctrlMessage.SetFont(WinUtil::font);
tabMenu.CreatePopupMenu();
tabMenu.AppendMenu(MF_STRING, IDC_GETLIST, CTSTRING(GET_FILE_LIST));
tabMenu.AppendMenu(MF_STRING, IDC_MATCH_QUEUE, CTSTRING(MATCH_QUEUE));
tabMenu.AppendMenu(MF_STRING, IDC_GRANTSLOT, CTSTRING(GRANT_EXTRA_SLOT));
tabMenu.AppendMenu(MF_STRING, IDC_ADD_TO_FAVORITES, CTSTRING(ADD_TO_FAVORITES));
PostMessage(WM_SPEAKER, USER_UPDATED);
created = true;
ClientManager::getInstance()->addListener(this);
bHandled = FALSE;
return 1;
}
void PrivateFrame::gotMessage(const User::Ptr& from, const User::Ptr& to, const User::Ptr& replyTo, const tstring& aMessage) {
PrivateFrame* p = NULL;
const User::Ptr& user = (replyTo == ClientManager::getInstance()->getMe()) ? to : replyTo;
FrameIter i = frames.find(user);
if(i == frames.end()) {
p = new PrivateFrame(user);
frames[user] = p;
p->readLog();
p->addLine(aMessage);
if(Util::getAway()) {
if(!(BOOLSETTING(NO_AWAYMSG_TO_BOTS) && user->isSet(User::BOT)))
p->sendMessage(Text::toT(Util::getAwayMessage()));
}
if(BOOLSETTING(PRIVATE_MESSAGE_BEEP) || BOOLSETTING(PRIVATE_MESSAGE_BEEP_OPEN)) {
MessageBeep(MB_OK);
}
} else {
if(BOOLSETTING(PRIVATE_MESSAGE_BEEP)) {
MessageBeep(MB_OK);
}
i->second->addLine(aMessage);
}
}
void PrivateFrame::openWindow(const User::Ptr& replyTo, const tstring& msg) {
PrivateFrame* p = NULL;
FrameIter i = frames.find(replyTo);
if(i == frames.end()) {
p = new PrivateFrame(replyTo);
frames[replyTo] = p;
p->CreateEx(WinUtil::mdiClient);
p->readLog();
} else {
p = i->second;
if(::IsIconic(p->m_hWnd))
::ShowWindow(p->m_hWnd, SW_RESTORE);
p->MDIActivate(p->m_hWnd);
}
if(!msg.empty())
p->sendMessage(msg);
}
LRESULT PrivateFrame::onChar(UINT uMsg, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled) {
switch(wParam) {
case VK_RETURN:
if( WinUtil::isShift() || WinUtil::isCtrl() || WinUtil::isAlt() ) {
bHandled = FALSE;
} else {
if(uMsg == WM_KEYDOWN) {
onEnter();
}
}
break;
default:
bHandled = FALSE;
}
return 0;
}
void PrivateFrame::onEnter()
{
bool resetText = true;
if(ctrlMessage.GetWindowTextLength() > 0) {
AutoArray<TCHAR> msg(ctrlMessage.GetWindowTextLength()+1);
ctrlMessage.GetWindowText(msg, ctrlMessage.GetWindowTextLength()+1);
tstring s(msg, ctrlMessage.GetWindowTextLength());
// Process special commands
if(s[0] == '/') {
tstring param;
tstring message;
tstring status;
if(WinUtil::checkCommand(s, param, message, status)) {
if(!message.empty()) {
sendMessage(message);
}
if(!status.empty()) {
addClientLine(status);
}
} else if(Util::stricmp(s.c_str(), _T("clear")) == 0) {
ctrlClient.SetWindowText(_T(""));
} else if(Util::stricmp(s.c_str(), _T("grant")) == 0) {
UploadManager::getInstance()->reserveSlot(getUser());
addClientLine(TSTRING(SLOT_GRANTED));
} else if(Util::stricmp(s.c_str(), _T("close")) == 0) {
PostMessage(WM_CLOSE);
} else if((Util::stricmp(s.c_str(), _T("favorite")) == 0) || (Util::stricmp(s.c_str(), _T("fav")) == 0)) {
FavoriteManager::getInstance()->addFavoriteUser(getUser());
addStatus(TSTRING(FAVORITE_USER_ADDED));
} else if(Util::stricmp(s.c_str(), _T("getlist")) == 0) {
BOOL bTmp;
onGetList(0,0,0,bTmp);
} else if(Util::stricmp(s.c_str(), _T("log")) == 0) {
StringMap params;
params["hubNI"] = Util::toString(ClientManager::getInstance()->getHubNames(replyTo->getCID()));
params["hubURL"] = Util::toString(ClientManager::getInstance()->getHubs(replyTo->getCID()));
params["userCID"] = replyTo->getCID().toBase32();
params["userNI"] = ClientManager::getInstance()->getNicks(replyTo->getCID())[0];
params["myCID"] = ClientManager::getInstance()->getMe()->getCID().toBase32();
WinUtil::openFile(Text::toT(Util::validateFileName(SETTING(LOG_DIRECTORY) + Util::formatParams(SETTING(LOG_FILE_PRIVATE_CHAT), params, true))));
} else if(Util::stricmp(s.c_str(), _T("help")) == 0) {
addStatus(_T("*** ") + WinUtil::commands + _T(", /getlist, /clear, /grant, /close, /favorite, /log <system, downloads, uploads>"));
} else {
if(replyTo->isOnline()) {
sendMessage(tstring(msg));
} else {
ctrlStatus.SetText(0, CTSTRING(USER_WENT_OFFLINE));
resetText = false;
}
}
} else {
if(replyTo->isOnline()) {
sendMessage(s);
} else {
ctrlStatus.SetText(0, CTSTRING(USER_WENT_OFFLINE));
resetText = false;
}
}
if(resetText)
ctrlMessage.SetWindowText(_T(""));
}
}
void PrivateFrame::sendMessage(const tstring& msg) {
ClientManager::getInstance()->privateMessage(replyTo, Text::fromT(msg));
}
LRESULT PrivateFrame::onClose(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) {
if(!closed) {
ClientManager::getInstance()->removeListener(this);
closed = true;
PostMessage(WM_CLOSE);
return 0;
} else {
frames.erase(replyTo);
bHandled = FALSE;
return 0;
}
}
void PrivateFrame::addLine(const tstring& aLine) {
if(!created) {
if(BOOLSETTING(POPUNDER_PM))
WinUtil::hiddenCreateEx(this);
else
CreateEx(WinUtil::mdiClient);
}
if(BOOLSETTING(LOG_PRIVATE_CHAT)) {
StringMap params;
params["message"] = Text::fromT(aLine);
params["hubNI"] = Util::toString(ClientManager::getInstance()->getHubNames(replyTo->getCID()));
params["hubURL"] = Util::toString(ClientManager::getInstance()->getHubs(replyTo->getCID()));
params["userCID"] = replyTo->getCID().toBase32();
params["userNI"] = ClientManager::getInstance()->getNicks(replyTo->getCID())[0];
params["myCID"] = ClientManager::getInstance()->getMe()->getCID().toBase32();
LOG(LogManager::PM, params);
}
tstring line;
if(BOOLSETTING(TIME_STAMPS)) {
line = Text::toT("\r\n[" + Util::getShortTimeString() + "] ");
} else {
line = _T("\r\n");
}
line += aLine;
ctrlClient.AppendText(line.c_str());
addClientLine(CTSTRING(LAST_CHANGE) + Text::toT(Util::getTimeString()));
if (BOOLSETTING(BOLD_PM)) {
setDirty();
}
}
void PrivateFrame::addStatus(const tstring& aLine) {
if(!created) {
if(BOOLSETTING(POPUNDER_PM))
WinUtil::hiddenCreateEx(this);
else
CreateEx(WinUtil::mdiClient);
}
tstring line;
if(BOOLSETTING(TIME_STAMPS)) {
line = Text::toT("\r\n[" + Util::getShortTimeString() + "] ");
} else {
line = _T("\r\n");
}
line += aLine;
ctrlClient.AppendText(line.c_str());
}
LRESULT PrivateFrame::onTabContextMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/) {
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; // location of mouse click
prepareMenu(tabMenu, UserCommand::CONTEXT_CHAT, ClientManager::getInstance()->getHubs(replyTo->getCID()));
tabMenu.AppendMenu(MF_SEPARATOR);
tabMenu.AppendMenu(MF_STRING, IDC_CLOSE_WINDOW, CTSTRING(CLOSE));
tabMenu.TrackPopupMenu(TPM_LEFTALIGN | TPM_BOTTOMALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, m_hWnd);
tabMenu.DeleteMenu(tabMenu.GetMenuItemCount()-1, MF_BYPOSITION);
tabMenu.DeleteMenu(tabMenu.GetMenuItemCount()-1, MF_BYPOSITION);
cleanMenu(tabMenu);
return TRUE;
}
void PrivateFrame::runUserCommand(UserCommand& uc) {
if(!WinUtil::getUCParams(m_hWnd, uc, ucLineParams))
return;
StringMap ucParams = ucLineParams;
ClientManager::getInstance()->userCommand(replyTo, uc, ucParams, true);
}
LRESULT PrivateFrame::onGetList(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
try {
QueueManager::getInstance()->addList(replyTo, QueueItem::FLAG_CLIENT_VIEW);
} catch(const Exception& e) {
addClientLine(Text::toT(e.getError()));
}
return 0;
}
LRESULT PrivateFrame::onMatchQueue(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
try {
QueueManager::getInstance()->addList(replyTo, QueueItem::FLAG_MATCH_QUEUE);
} catch(const Exception& e) {
addClientLine(Text::toT(e.getError()));
}
return 0;
}
LRESULT PrivateFrame::onGrantSlot(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
UploadManager::getInstance()->reserveSlot(replyTo);
return 0;
}
LRESULT PrivateFrame::onAddToFavorites(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) {
FavoriteManager::getInstance()->addFavoriteUser(replyTo);
return 0;
}
void PrivateFrame::UpdateLayout(BOOL bResizeBars /* = TRUE */) {
RECT rect;
GetClientRect(&rect);
// position bars and offset their dimensions
UpdateBarsPosition(rect, bResizeBars);
if(ctrlStatus.IsWindow()) {
CRect sr;
int w[1];
ctrlStatus.GetClientRect(sr);
w[0] = sr.right - 16;
ctrlStatus.SetParts(1, w);
}
int h = WinUtil::fontHeight + 4;
CRect rc = rect;
rc.bottom -= h + 10;
ctrlClient.MoveWindow(rc);
rc = rect;
rc.bottom -= 2;
rc.top = rc.bottom - h - 5;
rc.left +=2;
rc.right -=2;
ctrlMessage.MoveWindow(rc);
}
LRESULT PrivateFrame::onLButton(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) {
HWND focus = GetFocus();
bHandled = false;
if(focus == ctrlClient.m_hWnd) {
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
tstring x;
tstring::size_type start = (tstring::size_type)WinUtil::textUnderCursor(pt, ctrlClient, x);
tstring::size_type end = x.find(_T(" "), start);
if(end == string::npos)
end = x.length();
bHandled = WinUtil::parseDBLClick(x, start, end);
}
return 0;
}
void PrivateFrame::updateTitle() {
pair<tstring, bool> hubs = WinUtil::getHubNames(replyTo);
if(hubs.second) {
setTabColor(RGB(0, 255, 255));
} else {
setTabColor(RGB(255, 0, 0));
}
SetWindowText((WinUtil::getNicks(replyTo) + _T(" - ") + hubs.first).c_str());
}
void PrivateFrame::readLog() {
StringMap params;
params["hubNI"] = Util::toString(ClientManager::getInstance()->getHubNames(replyTo->getCID()));
params["hubURL"] = Util::toString(ClientManager::getInstance()->getHubs(replyTo->getCID()));
params["userCID"] = replyTo->getCID().toBase32();
params["userNI"] = ClientManager::getInstance()->getNicks(replyTo->getCID())[0];
params["myCID"] = ClientManager::getInstance()->getMe()->getCID().toBase32();
string path = Util::validateFileName(SETTING(LOG_DIRECTORY) + Util::formatParams(SETTING(LOG_FILE_PRIVATE_CHAT), params, true));
try {
if (SETTING(SHOW_LAST_LINES_LOG) > 0) {
File f(path, File::READ, File::OPEN);
int64_t size = f.getSize();
if(size > 32*1024) {
f.setPos(size - 32*1024);
}
StringList lines = StringTokenizer<string>(f.read(32*1024), "\r\n").getTokens();
int linesCount = lines.size();
int i = linesCount > (SETTING(SHOW_LAST_LINES_LOG) + 1) ? linesCount - (SETTING(SHOW_LAST_LINES_LOG) + 1) : 0;
for(; i < (linesCount - 1); ++i){
addStatus(_T("- ") + Text::toT(lines[i]));
}
f.close();
}
} catch(const FileException&){
}
}
void PrivateFrame::closeAll(){
for(FrameIter i = frames.begin(); i != frames.end(); ++i)
i->second->PostMessage(WM_CLOSE, 0, 0);
}
void PrivateFrame::closeAllOffline() {
for(FrameIter i = frames.begin(); i != frames.end(); ++i) {
if(!i->first->isOnline())
i->second->PostMessage(WM_CLOSE, 0, 0);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -