📄 myicqdlg.cpp
字号:
/***************************************************************************
* *
* 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. *
* *
* copyright : (C) 2002 by Zhang Yong *
* email : z-yong163@163.com *
***************************************************************************/
// myicqDlg.cpp : implementation file
//
#include "stdafx.h"
#include "myicq.h"
#include "myicqDlg.h"
#include <mmsystem.h>
#include "serversession.h"
#include "tcpsession.h"
#include "icqwindow.h"
#include "icqdb.h"
#include "icqconfig.h"
#include "icqplugin.h"
#include "GfxPopupMenu.h"
#include "LoginDlg.h"
#include "RegWizard.h"
#include "ViewDetailDlg.h"
#include "SendMsgDlg.h"
#include "SearchWizard.h"
#include "SysMsgDlg.h"
#include "ViewMsgDlg.h"
#include "SysHistoryDlg.h"
#include "DelFriendDlg.h"
#include "ModifyDetailDlg.h"
#include "SysOptionDlg.h"
#include "LoginAgainDlg.h"
#include "NotifyWnd.h"
#include "AboutDlg.h"
#include "MsgMgrWnd.h"
#include "SendRequestDlg.h"
#include "BroadcastDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define ID_GFX_SHOWONLINE 50001
#define ID_GFX_RENAME 50002
#define ID_GFX_REMOVE 50003
#define ID_STATUS_AWAY 40000
#define ID_PLUGIN 60000
#define ID_SKIN_FIRST 70000
#define IDC_OUTBAR 1001
#define ID_HOTKEY 1002
#define ID_TOOLTIP 1003
#define ID_NOTIFYICON 1004
#define IDT_RESEND 1001
#define IDT_KEEPALIVE 1002
#define IDT_STATUS 1003
#define IDT_BLINK 1004
#define IDT_DBLCLK 1005
#define IDT_HOVER 1006
#define IDT_AUTO_SWITCH_STATUS 1007
#define WM_HOSTFOUND (WM_USER + 101)
#define WM_NOTIFYICON (WM_USER + 102)
#define HOTKEY_DEFAULT MAKELONG(0x5a, MOD_CONTROL | MOD_ALT)
enum {
ALIGN_NONE,
ALIGN_TOP,
ALIGN_LEFT,
ALIGN_RIGHT
};
/////////////////////////////////////////////////////////////////////////////
// CIcqDlg dialog
CIcqDlg::CIcqDlg(CWnd* pParent /*=NULL*/)
: CCaptionBtnDlg(2, CIcqDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CIcqDlg)
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
iconBlank = (HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_BLANK),
IMAGE_ICON, 0, 0, 0);
iconSysMsg = (HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_SYSMSG),
IMAGE_ICON, 0, 0, 0);
regMode = -1;
alignType = ALIGN_NONE;
isHide = FALSE;
currentMenu = NULL;
curContact = NULL;
outbarCtrl.setListener(this);
outbarCtrl.setImageList(&getApp()->largeImageList, &getApp()->smallImageList);
}
CIcqDlg::~CIcqDlg()
{
}
void *CIcqDlg::getFaceIcon(int face, int status)
{
int i = getApp()->getImageIndex(face, status);
return (void *) getApp()->largeImageList.ExtractIcon(i);
}
void CIcqDlg::popupMsg(void *icon, const char *text, uint32 t)
{
new CNotifyWnd((HICON) icon, text, t);
}
void CIcqDlg::drawCaptionBtn(CDC *pDC, CRect &rc, int button, BOOL pressed)
{
ASSERT(button < 2);
if (!pressed) {
pDC->Draw3dRect(rc, GetSysColor(COLOR_BTNHILIGHT), GetSysColor(COLOR_3DDKSHADOW));
rc.InflateRect(-1, -1);
pDC->Draw3dRect(rc, GetSysColor(COLOR_BTNFACE), GetSysColor(COLOR_3DSHADOW));
} else {
pDC->Draw3dRect(rc, GetSysColor(COLOR_3DDKSHADOW), GetSysColor(COLOR_BTNHILIGHT));
rc.InflateRect(-1, -1);
pDC->Draw3dRect(rc, GetSysColor(COLOR_3DSHADOW), GetSysColor(COLOR_BTNFACE));
}
rc.InflateRect(-1, -1);
pDC->FillSolidRect(rc, GetSysColor(COLOR_BTNFACE));
CPen pen(PS_SOLID, 1, GetSysColor(COLOR_BTNTEXT));
CPen *penOld = pDC->SelectObject(&pen);
int x, y;
x = rc.left;
y = (rc.top + rc.bottom) / 2;
if (pressed) {
x++;
y++;
}
pDC->MoveTo(x, y);
pDC->LineTo(x + rc.Width() - 2, y);
if (button == 1) {
x = (rc.left + rc.right) / 2 - 1;
y = rc.top + 1;
if (pressed) {
x++;
y++;
}
pDC->MoveTo(x, y);
pDC->LineTo(x, y + rc.Height() - 2);
}
pDC->SelectObject(penOld);
}
void CIcqDlg::onCaptionBtnClicked(int button)
{
ASSERT(button < 2);
if (button == 0) {
ShowWindow(SW_MINIMIZE);
ShowWindow(SW_HIDE);
} else if (button == 1) {
CGfxPopupMenu menu;
menu.CreatePopupMenu();
int id = 1000;
menu.appendMenu(id, options.skin.empty() ? IDB_CHECK : IDB_FOLDER, IDS_SKIN_RESTORE);
CFileFind finder;
BOOL cont = finder.FindFile(getApp()->rootDir + "skins\\*");
while (cont) {
cont = finder.FindNextFile();
if (!finder.IsDots() && finder.IsDirectory()) {
int bmpID = (finder.GetFileTitle() == options.skin.c_str() ? IDB_CHECK : IDB_FOLDER);
menu.appendMenu(++id, bmpID, finder.GetFileTitle());
}
}
CPoint pt;
GetCursorPos(&pt);
id = menu.TrackPopupMenu(TPM_RETURNCMD, pt.x, pt.y, this);
if (id == 0)
return;
ShowWindow(SW_MINIMIZE);
if (id == 1000) {
outbarCtrl.setSkin(NULL);
options.skin = "";
} else {
CString str;
menu.GetMenuString(id, str, 0);
if (skin.load(getApp()->rootDir + "skins\\" + str))
outbarCtrl.setSkin(&skin);
options.skin = str;
}
IcqDB::saveOptions(options);
ShowWindow(SW_NORMAL);
}
}
void CIcqDlg::onSendError(uint32 seq)
{
if (!seq) {
// Destination port is unreachable.
IcqWindow *win = findWindow(WIN_REG_WIZARD);
if (win) {
((CRegWizard *) win)->onSendError(seq);
return;
}
} else if (lastSeq != seq) {
IcqLink::onSendError(seq);
return;
}
lastSeq = 0;
onError();
}
void CIcqDlg::onConnect(bool success)
{
IcqWindow *win = findWindow(WIN_REG_WIZARD);
if (win) {
((CRegWizard *) win)->onConnect(success);
return;
}
if (success)
lastSeq = serverSession()->login(myInfo.passwd.c_str(), pendingStatus);
else {
myInfo.status = STATUS_OFFLINE;
updateStatusIcon();
logout();
}
}
IcqContact *CIcqDlg::addContact(uint32 uin, int folder)
{
outbarCtrl.removeContact(uin);
IcqContact *c = findContact(uin);
if (!c) {
c = new IcqContact;
c->uin = uin;
CString nick;
nick.Format("%lu", uin);
c->nick = nick;
contactList.push_back(c);
}
int n = outbarCtrl.getFolderCount();
if (folder == n - 1)
c->type = CONTACT_IGNORE;
else if (folder == n - 2)
c->type = CONTACT_STRANGER;
else
c->type = CONTACT_FRIEND;
outbarCtrl.addContact(folder, c);
outbarCtrl.repaintInsideRect();
saveGroupInfo();
return c;
}
void CIcqDlg::login(uint32 status)
{
pendingStatus = status;
SetTimer(IDT_STATUS, 250, NULL);
m_btnStatus.setText(IDS_STATUS_LOGGING_IN);
resolveHost();
}
void CIcqDlg::logout()
{
IcqLink::logout();
KillTimer(IDT_RESEND);
KillTimer(IDT_KEEPALIVE);
KillTimer(IDT_AUTO_SWITCH_STATUS);
PtrList::iterator it;
for (it = contactList.begin(); it != contactList.end(); ++it) {
IcqContact *c = (IcqContact *) *it;
outbarCtrl.update(c->uin, TRUE);
}
}
void CIcqDlg::addFriend(IcqContact *c, int folder)
{
if (folder < 0)
folder = outbarCtrl.getSelFolder();
c->type = CONTACT_FRIEND;
CSysMsgDlg *win = new CSysMsgDlg(c->uin);
win->Create(IDD_SYS_MESSAGE);
}
BOOL CIcqDlg::delFriend(IcqContact *c, int folder)
{
CString str;
str.Format(IDS_PROMPT_DEL_FRIEND, c->uin);
if (AfxMessageBox(str, MB_YESNO) != IDYES)
return FALSE;
{
CDelFriendDlg dlg(c->uin);
if (dlg.DoModal() != IDOK)
return FALSE;
}
int n = outbarCtrl.getFolderCount();
if (folder == n - 1 || folder < 0)
destroyContact(c->uin);
if (folder == n - 2 || folder < 0)
IcqDB::delContact(c->uin);
outbarCtrl.removeContact(c->uin);
if (folder >= 0) {
outbarCtrl.addContact(folder, c);
saveGroupInfo();
c->type = (folder == n - 1 ? CONTACT_IGNORE : CONTACT_STRANGER);
} else {
contactList.remove(c);
delete c;
}
return TRUE;
}
void CIcqDlg::onHostFound(in_addr &addr)
{
if (addr.s_addr != INADDR_NONE)
serverSession()->connect(inet_ntoa(addr), options.port);
else
onError();
}
void CIcqDlg::onlineNotify(IcqContact *c)
{
if (options.flags.test(UF_ONLINE_NOTIFY)) {
options.playSound(SOUND_ONLINE, c);
outbarCtrl.blinkText(c->uin);
if (c->flags.test(CF_OPTION_POPUP_ONLINE)) {
CString str;
str.Format(IDS_NOTIFY_ONLINE, c->nick.c_str(), c->uin);
new CNotifyWnd(getApp()->largeImageList.ExtractIcon(c->face), str);
}
}
}
void CIcqDlg::addNotifyIcon()
{
NOTIFYICONDATA tnid;
tnid.cbSize = sizeof(NOTIFYICONDATA);
tnid.hWnd = m_hWnd;
tnid.uID = ID_NOTIFYICON;
tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
tnid.uCallbackMessage = WM_NOTIFYICON;
tnid.hIcon = getApp()->m_hIcon;
lstrcpy(tnid.szTip, AfxGetAppName());
Shell_NotifyIcon(NIM_ADD, &tnid);
}
void CIcqDlg::removeNotifyIcon()
{
NOTIFYICONDATA tnid;
tnid.cbSize = sizeof(NOTIFYICONDATA);
tnid.hWnd = m_hWnd;
tnid.uID = ID_NOTIFYICON;
Shell_NotifyIcon(NIM_DELETE, &tnid);
}
void CIcqDlg::modifyNotifyIcon(HICON hIcon)
{
NOTIFYICONDATA tnid;
tnid.cbSize = sizeof(NOTIFYICONDATA);
tnid.hWnd = m_hWnd;
tnid.uID = ID_NOTIFYICON;
tnid.uFlags = NIF_ICON;
tnid.hIcon = hIcon;
Shell_NotifyIcon(NIM_MODIFY, &tnid);
}
void CIcqDlg::popupMainMenu(UINT nFlags, CPoint &pt)
{
CGfxPopupMenu menu;
CMenu tmp;
tmp.LoadMenu(IDR_MAIN);
menu.Attach(*tmp.GetSubMenu(0));
CGfxPopupMenu fileMenu;
fileMenu.Attach(*menu.GetSubMenu(0));
fileMenu.modifyMenu(ID_MESSAGE_MGR, IDB_MSG_HISTORY);
fileMenu.modifyMenu(ID_CONTACT_MGR, IDB_CONTACT_MGR);
menu.modifyMenu(0, IDB_FILEMGR, FALSE);
menu.modifyMenu(ID_CHANGE_USER, IDB_CHANGE_USER);
menu.modifyMenu(ID_REG_WIZARD, IDB_REG_WIZARD);
menu.modifyMenu(ID_MODIFY_INFO, IDB_VIEW_DETAIL);
menu.modifyMenu(ID_SYS_OPTION, IDB_SYS_OPTION);
menu.modifyMenu(ID_HELP, IDB_HELP);
menu.modifyMenu(ID_APP_EXIT, IDB_EXIT);
if (myInfo.uin >= 1000)
menu.DeleteMenu(ID_BROADCAST_MSG, 0);
else
menu.modifyMenu(ID_BROADCAST_MSG, iconSysMsg);
menu.setVertBitmap(IDB_VERT);
currentMenu = &menu;
menu.TrackPopupMenu(nFlags, pt.x, pt.y, this);
currentMenu = NULL;
}
void CIcqDlg::popupStatusMenu(UINT nFlags, CPoint &pt)
{
CMenu tmp;
tmp.LoadMenu(IDR_STATUS);
CGfxPopupMenu statusMenu;
statusMenu.Attach(*tmp.GetSubMenu(0));
CGfxPopupMenu awayMenu;
awayMenu.Attach(*statusMenu.GetSubMenu(2));
statusMenu.modifyMenu(ID_STATUS_ONLINE, IDB_STATUS_ONLINE);
statusMenu.modifyMenu(2, IDB_STATUS_AWAY, FALSE);
statusMenu.modifyMenu(ID_STATUS_INVIS, IDB_STATUS_INVIS);
statusMenu.modifyMenu(ID_STATUS_OFFLINE, IDB_STATUS_OFFLINE);
bool autoReply = options.flags.test(UF_AUTO_REPLY);
UINT bitmap;
StrList l;
IcqDB::loadAutoReply(l);
int pos = 0;
UINT id = ID_STATUS_AWAY;
StrList::iterator it;
for (it = l.begin(); it != l.end(); ++it) {
bitmap = (autoReply && *it == options.autoReplyText) ?
IDB_STATUS_AWAY : IDB_STATUS_OFFLINE;
CString str = (*it).c_str();
if (str.GetLength() > 20)
str = str.Left(20) + "...";
awayMenu.InsertMenu(pos, MF_BYPOSITION, id++, str);
awayMenu.modifyMenu(pos++, bitmap, FALSE);
awayMenu.InsertMenu(pos++, MF_SEPARATOR | MF_BYPOSITION);
}
bitmap = autoReply ? IDB_STATUS_OFFLINE : IDB_STATUS_AWAY;
awayMenu.modifyMenu(ID_STATUS_AWAY_NOREPLY, bitmap);
awayMenu.modifyMenu(ID_STATUS_AWAY_CUSTOM, IDB_SYS_OPTION);
currentMenu = &statusMenu;
statusMenu.TrackPopupMenu(nFlags, pt.x, pt.y, this);
currentMenu = NULL;
}
void CIcqDlg::updateStatusIcon()
{
KillTimer(IDT_STATUS);
switch (myInfo.status) {
case STATUS_ONLINE:
m_btnStatus.setText(IDS_STATUS_ONLINE);
break;
case STATUS_OFFLINE:
m_btnStatus.setText(IDS_STATUS_OFFLINE);
break;
case STATUS_AWAY:
m_btnStatus.setText(IDS_STATUS_AWAY);
break;
case STATUS_INVIS:
m_btnStatus.setText(IDS_STATUS_INVIS);
break;
}
HICON hIcon = statusImgList.ExtractIcon(myInfo.status);
m_btnStatus.SetIcon(hIcon);
modifyNotifyIcon(hIcon);
}
void CIcqDlg::animateStatus()
{
SetTimer(IDT_STATUS, 250, NULL);
OnTimer(IDT_STATUS);
}
void CIcqDlg::hideWindow(BOOL hide)
{
CRect rc;
GetWindowRect(rc);
int moves = 20;
int xStep, yStep;
int xEnd, yEnd;
int cxScreen;
switch (alignType) {
case ALIGN_TOP:
xStep = 0;
xEnd = rc.left;
if (hide) {
yStep = -rc.bottom / moves;
yEnd = -rc.Height() + 2;
} else {
yStep = -rc.top / moves;
yEnd = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -