/*--------------------------------------------------------------------------------------------------------------------------------------------------- Program Listing for: securesockDlg.cpp Project: securesock Namespace: c++ ---------------------------------------------------------------------------------------------------------------------------------------------------- */ // securesockDlg.cpp : implementation file // // since this is the main window, sort of, a lot of stuff is put in here instead of // in the application class. #include "stdafx.h" #include <stdlib.h> #include <stdio.h> #include <time.h> #include <vector> #include "securesock.h" #include "securesockDlg.h" #include "DlgProxy.h" #include "IconChooser.h" #include "PersonalInfoDlg.h" #include "InternetInfoDlg.h" #include "CompDlg.h" #include "WelcomeDlg.h" #include "GetChatID.h" #include "PersP1.h" #include "PersP3.h" #include "Pers_P2.h" #include "PersP4.h" #include "MyPropSheet.h" #include "TreeEdit.h" #include "SendDlg.h" #include "stream_stuff.h" #include "MyColorDialog.h" #include "SockUser.h" #include "Slot.h" #include "LookupContacts.h" #include "MySocket.h" #include "SearchResults.h" #include "MiscStuff1.h" #include "PropDlg.h" #include "MoveContactDlg.h" #include "AcceptContact.h" #include "MyTTC.h" #include "ReadDlg.h" #include <vfw.h> #pragma comment(lib, "winmm.lib") #pragma comment(lib, "vfw32.lib") #include <iostream> #include <iomanip> #include <fstream> #include <ios> // required to make STL functions visible, which I use throughout the app using namespace std; #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif int CSecuresockDlg::CHAT_ID_LOOKUP = 1; int CSecuresockDlg::TYPE_LOOKUP = 2; int CSecuresockDlg::PENDING_MSG_LOOKUP = 3; int CSecuresockDlg::ONLINE_STATUS_MSG_LOOKUP = 4; int CSecuresockDlg::BLINK_UPDATE_CALL = 5; // int m_imy_status; int CSecuresockDlg::ACTIVE = 5; int CSecuresockDlg::BUSY = 6; int CSecuresockDlg::SHORT_AFK = 7; int CSecuresockDlg::LONG_AFK = 8; int CSecuresockDlg::INVISIBLE = 9; VOID CALLBACK BlinkProc(UINT ntimerid, UINT msg, DWORD dwuser, DWORD dwparam1, DWORD dwparam2); volatile bool g_ssd_insocket = false; volatile bool gb_lookat = false; volatile HWND g_md_hwnd = (HWND)0; volatile int g_i_mystatus = 0; HWND GetMainDlgHWND(); void SetMainDlgHWND(HWND x); int GetMyOnlineStatus(); void SetMyOnlineStatus(int status); // certain globals are useful when dealing with threads volatile bool g_attempting_server_contact = false; // used with threads so not in a class (for now) volatile bool g_getting_online_status = false; // this also is accessed by threads hence global vector<TreeStatusHelper> online_chk_vector; // some of these functions are obsolete, they were globals I was using for a time, perhaps remove later CString gettreetext( const CTreeCtrl &piTree, HTREEITEM pitem ); // saveone is a nice function for use with saving a single tree items info, needs to be "classed" void SaveOne(vector <TreeSaver> &tscopy, HTREEITEM hitem, char *param_text, int param_id, int param_parent, int contact_id, int iimage, int isel_image, bool is_expanded = false); void SaveOne(vector <TreeSaver> &tscopy, HTREEITEM hitem, char *param_text, int param_id, int param_parent, ChatItemInfo *pchatinfo, int iimage, int isel_image, bool is_expanded = false); // this may now be obsolete not sure, created some new functions in the class to cover this stuff void gettreeiconindexes( const CTreeCtrl &piTree, HTREEITEM pitem, int &image, int &sel_image, bool &is_expanded ); // another possible obsolete function which may need to be put into the class void settreeexpanded( CTreeCtrl &piTree, HTREEITEM pitem, bool is_expanded ); unsigned int send_msg(LPVOID pParam); unsigned int send_ack_msg(LPVOID pParam); unsigned int check_online_status(LPVOID pParam); vector<TreeGroupInfo> tgiVector; int g_n = 0; ///////////////////////////////////////////////////////////////////////////// // CAboutDlg dialog used for App About class CAboutDlg : public CDialog { public: CAboutDlg(); // Dialog Data //{{AFX_DATA(CAboutDlg) enum { IDD = IDD_ABOUTBOX }; //}}AFX_DATA // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CAboutDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation protected: //{{AFX_MSG(CAboutDlg) //}}AFX_MSG DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { //{{AFX_DATA_INIT(CAboutDlg) //}}AFX_DATA_INIT } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CAboutDlg) //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) //{{AFX_MSG_MAP(CAboutDlg) // No message handlers //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CSecuresockDlg dialog IMPLEMENT_DYNAMIC(CSecuresockDlg, CDialog); CSecuresockDlg::CSecuresockDlg(CWnd* pParent /*=NULL*/) : CDialog(CSecuresockDlg::IDD, pParent) { //{{AFX_DATA_INIT(CSecuresockDlg) //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDI_ICON27); m_ptreefont = (CFont *)0; m_pAutoProxy = NULL; //CDialog::Create(CSecuresockDlg::IDD, pParent); } CSecuresockDlg::~CSecuresockDlg() { // If there is an automation proxy for this dialog, set // its back pointer to this dialog to NULL, so it knows // the dialog has been deleted. if (m_pAutoProxy != NULL) m_pAutoProxy->m_pDialog = NULL; } void CSecuresockDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CSecuresockDlg) DDX_Control(pDX, IDC_TREE1, m_TreeCtrl); DDX_Control(pDX, IDC_MYPERSONALBUTTON, m_mypersonalbutton); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CSecuresockDlg, CDialog) //{{AFX_MSG_MAP(CSecuresockDlg) ON_WM_SYSCOMMAND() ON_WM_DESTROY() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_WM_CLOSE() ON_NOTIFY(NM_RCLICK, IDC_TREE1, OnRclickTree1) ON_BN_CLICKED(IDC_BUTTON1, OnButton1) ON_WM_SIZE() ON_NOTIFY(TVN_ENDLABELEDIT, IDC_TREE1, OnEndlabeleditTree1) ON_NOTIFY(TVN_KEYDOWN, IDC_TREE1, OnKeydownTree1) ON_NOTIFY(NM_RETURN, IDC_TREE1, OnReturnTree1) ON_WM_CHAR() ON_BN_CLICKED(IDC_MYPERSONALBUTTON, OnMypersonalbutton) ON_WM_SHOWWINDOW() ON_WM_HELPINFO() ON_COMMAND(WM_TRAY_ICON, OnTrayIcon) ON_MESSAGE(WM_TRAY_IDD, OnTrayNotification) ON_WM_CANCELMODE() ON_WM_SYSCHAR() ON_UPDATE_COMMAND_UI(ID_CHANGE_ICON1, OnUpdateChangeIcon1) ON_UPDATE_COMMAND_UI(IDC_MYPERSONALBUTTON, OnMyButtonUI) ON_NOTIFY(NM_DBLCLK, IDC_TREE1, OnDblclkTree1) ON_WM_CTLCOLOR() ON_WM_TIMER() ON_WM_SETCURSOR() //}}AFX_MSG_MAP ON_MESSAGE(WM_NEW_MSG, OnNewMessage) ON_MESSAGE(WM_CONNECT_STATUS, OnConnectStatus) ON_MESSAGE(WM_SEND_OUTGOING, OnOutgoingMsg) ON_MESSAGE(WM_SHOW_ONLINE_STATUS, ShowOnlineStatus) ON_MESSAGE(WM_TIMER_BLINK_EVENT, MakePendingsBlink) ON_BN_CLICKED(IDC_CONNECTION, OnConnectionButton) ON_BN_CLICKED(IDC_ADDGROUP, OnAddGroupButton) ON_BN_CLICKED(IDC_ADDCONTACT, OnAddContactButton) ON_BN_CLICKED(IDC_WEB, OnWebButton) ON_BN_CLICKED(IDC_TREESTUFF, OnTreeButton) ON_BN_CLICKED(IDC_STATUSBUTTON, OnStatusButton) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CSecuresockDlg message handlers BOOL CSecuresockDlg::OnInitDialog() { CDialog::OnInitDialog(); // Add "About..." menu item to system menu. fully_loaded = false; cntr = 0; // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } HICON hIconx = ::LoadIcon (AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_ICON27)); // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog //SetIcon(m_hIcon, TRUE); // Set big icon //SetIcon(m_hIcon, FALSE); // Set small icon SetIcon(hIconx, TRUE); // Set big icon SetIcon(hIconx, FALSE); // Set small icon // my stuff follows // for convenience save these two often used pointers to member variables pSockApp = (CSecuresockApp*)AfxGetApp(); pCWnd = (CWnd *)this; pSockApp->pHwndMainDialog = &m_hWnd; pSockApp->pMainDlg = (CDialog *)this; ::SetMainDlgHWND(m_hWnd); // file level global used with threads // create the tool tips object m_TTC.Create(this); // create the buttons on the top of the dialog (note created via code for max flexibility, hard // to set the properties right via dialog controls for icon pushbuttons this way is easier than // defining a bunch of other change window style calls and so on). MyButtonCreate(m_connectionbutton, WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_ICON , 50 , 3, 50 + 32 , 3+32, IDC_CONNECTION); // set the icon to the button CMiscStuff::SetButtonIcon(m_connectionbutton, IDI_ICON118); // add tool tip for button m_TTC.AddWindowTool( (CWnd *)&m_connectionbutton, "Connection Settings"); // repeat, repeat, repeat MyButtonCreate(m_newgroupbutton, WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_ICON , 50 + 32 + 2, 3, 50 + 32*2 + 2 , 3+32, IDC_ADDGROUP ); CMiscStuff::SetButtonIcon(m_newgroupbutton, IDI_ICON119); m_TTC.AddWindowTool( (CWnd *)&m_newgroupbutton, "Add New Group"); MyButtonCreate(m_addcontactbutton, WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_ICON , 50 + (32 + 2)*2, 3, 50 + 32*3 + 2*2 , 3+32, IDC_ADDCONTACT); CMiscStuff::SetButtonIcon(m_addcontactbutton, IDI_ICON120); m_TTC.AddWindowTool( (CWnd *)&m_addcontactbutton, "Add New Contact"); MyButtonCreate(m_treebutton, WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_ICON , 50 + (32 + 2)*3, 3, 50 + 32*4 + 2*3 , 3+32, IDC_TREESTUFF); CMiscStuff::SetButtonIcon(m_treebutton, IDI_ICON123); m_TTC.AddWindowTool( (CWnd *)&m_treebutton, "Tree Properties"); MyButtonCreate(m_logbutton, WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_ICON , 50 + (32 + 2)*4, 3, 50 + 32*5 + 2*4 , 3+32, IDC_LOGBUTTON); CMiscStuff::SetButtonIcon(m_logbutton, IDI_ICON124); m_TTC.AddWindowTool( (CWnd *)&m_logbutton, "Message Logs"); MyButtonCreate(m_securitybutton, WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_ICON , 50 + (32 + 2)*5, 3, 50 + 32*6 + 2*5 , 3+32, IDC_SECURITYBUTTON); CMiscStuff::SetButtonIcon(m_securitybutton, IDI_ICON125); m_TTC.AddWindowTool( (CWnd *)&m_securitybutton, "Security"); MyButtonCreate(m_websitebutton, WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_ICON , 50 + (32 + 2)*6, 3, 50 + 32*7 + 2*6 , 3+32, IDC_WEB); CMiscStuff::SetButtonIcon(m_websitebutton, IDI_ICON122); m_TTC.AddWindowTool( (CWnd *)&m_websitebutton, "Drakis Website"); MyButtonCreate(m_setstatusbutton, WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_ICON , 50 + (32)*7, 3, 50 + 32*7 + 16 , 3+16, IDC_STATUSBUTTON); CMiscStuff::SetButtonIcon(m_setstatusbutton, IDI_ICON126); m_TTC.AddWindowTool( (CWnd *)&m_setstatusbutton, "Set My Status"); // I create the status text "connecting...", etc. // in code because sometimes that lets you create special fonts a bit easier this is not a control // on the dialog, altho m_online_status member variable is Attached to it once it's created. CreateStatusText(); // load in the image list's we use for the tree control, all tree controls have a related image list // an image list is actually somewhat useful in general for other things also LoadImageList(); // I use a group icon vector for convenience when adding new groups (to know what next icon to use by default) iCIV_offset = 0; LoadGroupIconVector(); m_inick = 0; HICON hIcon; int n2 = 0; // first call is member function useful for resizing, altho i think now it's unneeded firstcall = 0; // load up info in registry for previous window size & position, if the registry entry for // "Main Dialog" is found RECT this_rect; if ( pSockApp->GetPosInfo( "Main Dialog", &this_rect) ) { pCWnd->SetWindowPos(NULL, this_rect.left, this_rect.top, this_rect.right - this_rect.left , this_rect.bottom - this_rect.top , SWP_SHOWWINDOW ); // SWP_SHOWWINDOW, SWP_HIDEWINDOW // otherwise default to standard position } else { RECT chkrect; pCWnd->GetWindowRect(&chkrect); CWnd *pwnd = (CWnd *)(&m_TreeCtrl); pwnd->SetWindowPos( NULL , 0, 40, chkrect.right - chkrect.left, chkrect.bottom - chkrect.top - 60, 0 ); } bool bad_load = false; // try to open users.ids // users.ids contains a snapshot of all the users using this machine, like icq I am trying to support // multiple people on the same chat station concept. ifstream optionsFile ( "users.ids"); // if users file doesn't exist this is a first time run so sign them up now if (! optionsFile) { // attempt to signup, if they canceled along the way postquitmessage if (!SignupUser() ) { AfxGetMainWnd()->PostMessage(WM_QUIT); return FALSE; } } else { // load in the users that use this machine into an application vector container if (! LoadUserIds() ) { bad_load = true; AfxMessageBox("couldn't load in the users file or some error Notify programmer"); AfxGetMainWnd()->PostMessage(WM_QUIT); return FALSE; } optionsFile.close(); // if we got here everything is okay, this now loads in the uXXX.ids property file settings // for the current user. their chat_id is now in pSockApp->my_controls.chat_id (amongst other places). pSockApp->my_controls.RestoreFromFile(); //pSockApp->my_controls.MBDumpVals(); } CString temp = pSockApp->my_controls.GetStringByTokenName("user_icon"); int ICONIDD = atoi(temp.GetBuffer(0)); if (ICONIDD == 0) { AfxMessageBox("trouble retrieving your icon"); ICONIDD = IDI_ICON31; } hIcon = ::LoadIcon (AfxGetResourceHandle(), MAKEINTRESOURCE(ICONIDD)); m_mypersonalbutton.SetIcon( hIcon ); m_my_personal_icon_id = ICONIDD; CString response; /* double xx; xx = CMiscStuff::GetSeconds(); CString display; display.Format("seconds:%e", xx); AfxMessageBox(display); Sleep( 1000 ); double xy; xy = CMiscStuff::GetSeconds(); unsigned long yy; yy = (unsigned long)(xy - xx); display.Format("%lu", yy); AfxMessageBox(display); */ bool bUseMyUrlGet = false; // if using my special socket stuff, currently i'm not using it as the default windows stuff for getting // a url file (code in application->url_get method) appears fairly fast. /* if (bUseMyUrlGet) { CMySocket newconn("www.drakis.com"); response = newconn.GetFileAsString("/cgi-bin/check_in.pl?my_scno=101", "www.drakis.com"); } else { // or use the generic wininet windows functions to do the same thing CString log_in; //log_in.Format("http://www.qwest.com/dsl/customerservice/downloads/docs/WIN_67x.pdf"); log_in.Format("http://www.drakis.com/cgi-bin/check_in.pl?my_scno=%lu", pSockApp->my_controls.chat_id); //log_in.Format("http://63.230.230.146/cgi-bin/check_in.pl?my_scno=%lu", pSockApp->my_controls.chat_id); response = pSockApp->url_get(log_in.GetBuffer(0)); } // should get one of the two responses here, "err" or "ok" if ( response.Left(2) == "ok" ) { pSockApp->bTroubleConnecting = FALSE; } else { pSockApp->bTroubleConnecting = TRUE; } */ //CMiscStuff::OpenRead("c:\\autoexec.bat"); bStartupFlag = true; OnTimer(2); //UpdateStatusText(); // add the tray icon (little icon on the system bar) for the App AddTrayIcon(); // try to open saved tree file, if you can open, build the tree settings // from this file if (pSockApp->my_controls.chat_id == 0) { AfxMessageBox("logic error assigning chat_id, notify programmer"); ASSERT(0); return FALSE; } temp.Format("tf_u%lu.dra", pSockApp->my_controls.chat_id); //ifstream treeFile ( "treefile2.ids" ); //ifstream treeFile ( temp.GetBuffer(0) ); CFile *myfile = new CFile(); bool bopenokay = true; try { myfile->Open( temp.GetBuffer(0), CFile::modeRead ); } catch (...) { } if (myfile->m_hFile == (UINT)CFile::hFileNull) { MB("Trouble Opening tree list file related to this user, default tree created"); bopenokay = false; delete myfile; myfile = (CFile *)NULL; } // if treeFile is NULL this is okay it recreates a generic tree BuildTreeFromFile(m_TreeCtrl, myfile, true ); //m_TreeCtrl.SetFont(&m_mainfont); //CEdit *scooby; //scooby = m_TreeCtrl.GetEditControl(); //scooby->SetFont(&m_mainfont); if (myfile) delete myfile; // set back ground color for tree if available CString colors = pSockApp->my_controls.GetStringByTokenName("tree_back_color"); if (! colors.IsEmpty() ) { unsigned long ulcolor = strtoul(colors.GetBuffer(0), NULL, 10); COLORREF x2 = (COLORREF)ulcolor; m_TreeCtrl.SetBkColor(x2) ; } m_hitcancel = 0; srand( (unsigned)time( NULL ) ); fully_loaded = true; m_ilast_dept_insert_icon = 30; // timer tracks whether person has an incoming message and causes their icon to flash, see OnTimer method bUpTimer = false; SetTimer(1, 1000, NULL); //SetTimer(2, 5000, NULL); SetTimer(3, 5000, NULL); SetTimer(4, 500, NULL); AfxBeginThread(send_ack_msg, (LPVOID)0); // blinking is sporadic with normal timer, trying a multimedia timer // is supposed to affect performance we will see //unsigned int ms = 500; //timeBeginPeriod(ms); //unsigned int ntimerid = timeSetEvent(ms, ms, BlinkProc, (DWORD)this->m_hWnd, TIME_PERIODIC); if (1) { // ! ntimerid) { //AfxMessageBox("trouble creating blink timer"); //timeEndPeriod(ms); m_n_mmtimer_id = 0; } else { //m_n_mmtimer_id = ntimerid; } // socket stuff is handled in threads, the main listening thread is now called //CMessages ref = pSockApp->main_msg_list; //unsigned long ul; //HWND hwnd_temp = pSockApp->m_hWnd; if (1) AfxBeginThread(main_thread, &m_hWnd); //main_thread(&ref); CString tempstr; tempstr.Format("current chat user id: %lu", pSockApp->my_controls.chat_id); //AfxMessageBox( tempstr ); CString temp2; temp2.Format("new one:%i", WM_USER); m_TTC.AddWindowTool( (CWnd *)&m_mypersonalbutton, "User Properties"); ::ZeroMemory(&tree_lf, sizeof(tree_lf)); GetTreeFontFromFile(); bTreeFontChanged = false; double n = CMiscStuff::GetSeconds(); temp2.Format("seconds %g", n); // get saved online status (ghost mode, busy, afk, or active, based on their last entry before // last save CString saved_status = pSockApp->my_controls.GetStringByTokenName("user_online_status"); if ( saved_status.IsEmpty() || atoi(saved_status.GetBuffer(0)) == 0) m_imy_status = CSecuresockDlg::ACTIVE; else m_imy_status = atoi(saved_status.GetBuffer(0)); ::SetMyOnlineStatus(m_imy_status); UpdateMyStatusText(); //AfxMessageBox( temp2 ); //CString tempx; //tempx = "hello"; //CMiscStuff::WaitWindow( tempx, this); //Sleep(2000); //CMiscStuff::ClearWaitWindow(); //AfxMessageBox( temp2 ); return TRUE; // return TRUE unless you set the focus to a control } BOOL CSecuresockDlg::MyButtonCreate(CButton &button, long styles, int x, int y, int cx, int cy, int cID) { RECT r1; r1.left = x; r1.top = y; r1.right = cx; r1.bottom = cy; return button.Create("", styles, r1, this, cID); } VOID CALLBACK BlinkProc(UINT ntimerid, UINT msg, DWORD dwuser, DWORD dwparam1, DWORD dwparam2) { PostMessage((HWND)dwuser, WM_TIMER_BLINK_EVENT, 0, 0); } LONG CSecuresockDlg::MakePendingsBlink(WPARAM w, LPARAM l) { double x1, x2; x1 = CMiscStuff::GetSeconds(); bUpTimer = ! bUpTimer; TraverseTree(CSecuresockDlg::BLINK_UPDATE_CALL, 0); //MakePendingsBlink(); x2 = CMiscStuff::GetSeconds(); CString temp; temp.Format("%3.3f", x2 - x1); TRACE("timer 4:%s\n", temp.GetBuffer(0)); return 0L; } void CSecuresockDlg::OnTimer(UINT ntimerid) { double x1, x2; CString temp; // calculate which icons have pending messages and set bPendingMsgs chatiteminfo flag if so if (ntimerid == 1) { x1 = CMiscStuff::GetSeconds(); TraverseTree(CSecuresockDlg::PENDING_MSG_LOOKUP, 0); x2 = CMiscStuff::GetSeconds(); temp.Format("%3.3f", x2 - x1); TRACE("timer 1:%s\n", temp.GetBuffer(0)); } // send "check in" message to server, yes I am on, this is my IP, via thread else if (ntimerid == 2) { /* x1 = CMiscStuff::GetSeconds(); if (g_attempting_server_contact) { TRACE("still in routine, timer send_ack_msg AVOIDED\n"); return; } //AfxMessageBox("on timer 2"); MessageInfo *pMsgInfo = new MessageInfo(); pMsgInfo->ntype = 0; pMsgInfo->chat_id = 0; pMsgInfo->sender_id = unsigned long GetCurrentChatID(void) //pSockApp->my_controls.chat_id; pMsgInfo->msg = ""; // note this is this->m_hWnd (securesockdlg member item m_hWnd) pMsgInfo->phwnd = &m_hWnd; pMsgInfo->n_online_status = this->m_imy_status; TRACE("send ack msg called as normal\n"); AfxBeginThread(send_ack_msg, (LPVOID)pMsgInfo); x2 = CMiscStuff::GetSeconds(); temp.Format("%3.3f", x2 - x1); TRACE("timer 2:%s\n", temp.GetBuffer(0)); */ } // check online status of my chat contacts via thread else if (ntimerid == 3) { x1 = CMiscStuff::GetSeconds(); // calling this function builds a vector of "to be looked up" chat_id's that are current on the // tree control if (g_getting_online_status) { TRACE("still getting online status timer call avoided"); return; } // this vector is a file static global online_chk_vector.clear(); // this traverse tree call will add chat_id for contacts and their HTREEITEMs to the vector TraverseTree(CSecuresockDlg::ONLINE_STATUS_MSG_LOOKUP, 0); // call the thread that gets whether these users are online or not (and updates the tree control // by sending a message back to the window). MessageInfo *pMsgInfo = new MessageInfo(); pMsgInfo->ntype = 0; pMsgInfo->chat_id = 0; pMsgInfo->sender_id = 0; pMsgInfo->msg = ""; // note this is this->m_hWnd (securesockdlg member item m_hWnd) // dont need other info but do need a reference to the main dialog window so we can send // the results of the check_online_status as a message to this window (standard way to return // info from a thread). pMsgInfo->phwnd = &m_hWnd; AfxBeginThread(check_online_status, (LPVOID)pMsgInfo); x2 = CMiscStuff::GetSeconds(); temp.Format("%3.3f", x2 - x1); TRACE("timer 3:%s\n", temp.GetBuffer(0)); } // blink update call based on status of chatiteminfo bPendingMsgs else if (ntimerid == 4) { x1 = CMiscStuff::GetSeconds(); bUpTimer = ! bUpTimer; TraverseTree(CSecuresockDlg::BLINK_UPDATE_CALL, 0); //MakePendingsBlink(); x2 = CMiscStuff::GetSeconds(); temp.Format("%3.3f", x2 - x1); TRACE("timer 4:%s\n", temp.GetBuffer(0)); //m_TreeCtrl.Invalidate(); } } void CSecuresockDlg::OnStatusButton() { DWORD dp = ::GetMessagePos(); CPoint pt ((int) LOWORD( dp ), (int) HIWORD (dp) ); UINT flags = NULL; CMenu menu; menu.LoadMenu(IDR_STATUS); CMenu *x; x = menu.GetSubMenu(0); /*if (m_imy_status; static int CSecuresockDlg::ACTIVE; static int CSecuresockDlg::BUSY; static int CSecuresockDlg::SHORT_AFK; static int CSecuresockDlg::LONG_AFK; static int CSecuresockDlg::INVISIBLE; */ if (m_imy_status == CSecuresockDlg::ACTIVE) { x->CheckMenuItem( ID_ACTIVE, MF_CHECKED); } if (m_imy_status == CSecuresockDlg::BUSY) { x->CheckMenuItem( ID_BUSY, MF_CHECKED); } if (m_imy_status == CSecuresockDlg::SHORT_AFK) { x->CheckMenuItem( ID_SHORT_AFK, MF_CHECKED); } //if (m_imy_status == CSecuresockDlg::LONG_AFK) { // x->CheckMenuItem( ID_LONG_AFK, MF_CHECKED); //} if (m_imy_status == CSecuresockDlg::INVISIBLE) { x->CheckMenuItem( ID_INVISIBLE, MF_CHECKED); } CMenu users_menu; users_menu.CreatePopupMenu(); CRect rect; GetWindowRect(rect); //CPoint y; //::GetCursorPos(&y); //ScreenToClient (&y); CPoint pt2 ((int) LOWORD( dp ), (int) HIWORD (dp) ); int ncmd = x->TrackPopupMenu( TPM_RETURNCMD | TPM_LEFTALIGN , pt2.x, pt2.y, AfxGetMainWnd(), rect ); if (ncmd == ID_ACTIVE) { m_imy_status = CSecuresockDlg::ACTIVE; UpdateMyStatusText(); } if (ncmd == ID_BUSY) { m_imy_status = CSecuresockDlg::BUSY; UpdateMyStatusText(); } if (ncmd == ID_SHORT_AFK) { m_imy_status = CSecuresockDlg::SHORT_AFK; UpdateMyStatusText(); } //if (ncmd == ID_LONG_AFK) { // m_imy_status = CSecuresockDlg::LONG_AFK; // this->m_my_status.SetWindowText("User Status: Long AFK"); //} if (ncmd == ID_INVISIBLE) { m_imy_status = CSecuresockDlg::INVISIBLE; UpdateMyStatusText(); } ::SetMyOnlineStatus(m_imy_status); CString temp; temp.Format("%i", m_imy_status); if (! pSockApp->my_controls.SetStringByTokenName("user_online_status", temp)) { AfxMessageBox("trouble saving online status setting in properties"); } pSockApp->SavePropsToFile(); } void CSecuresockDlg::UpdateMyStatusText(void) { if (m_imy_status == CSecuresockDlg::ACTIVE) this->m_my_status.SetWindowText("User Status: Active"); if (m_imy_status == CSecuresockDlg::BUSY) this->m_my_status.SetWindowText("User Status: Busy"); if (m_imy_status == CSecuresockDlg::SHORT_AFK) this->m_my_status.SetWindowText("User Status: AFK (Away From Keyboard)"); if (m_imy_status == CSecuresockDlg::INVISIBLE) this->m_my_status.SetWindowText("User Status: Invisible"); } void CSecuresockDlg::OnTreeButton() { DWORD dp = ::GetMessagePos(); CPoint pt ((int) LOWORD( dp ), (int) HIWORD (dp) ); UINT flags = NULL; CMenu menu; menu.LoadMenu(IDR_TREESTUFF); CMenu *x; x = menu.GetSubMenu(0); CMenu users_menu; users_menu.CreatePopupMenu(); CRect rect; GetWindowRect(rect); //CPoint y; //::GetCursorPos(&y); //ScreenToClient (&y); CPoint pt2 ((int) LOWORD( dp ), (int) HIWORD (dp) ); int ncmd = x->TrackPopupMenu( TPM_RETURNCMD | TPM_LEFTALIGN , pt2.x, pt2.y, AfxGetMainWnd(), rect ); if (ncmd == ID_TREEBKCOLOR) { //this is retarded but there is no getbackground color function calling set // gets it's value, here we set it to white then quickly set it back COLORREF old = m_TreeCtrl.GetBkColor(); CMyColorDialog x1(old, CC_RGBINIT ); x1.m_cc.lStructSize = sizeof( CHOOSECOLOR ); x1.m_cc.Flags = x1.m_cc.Flags | CC_FULLOPEN ; x1.SetWindowCaption("Select Tree Background Color"); if (x1.DoModal() == IDOK ) { COLORREF x2 = x1.GetColor(); m_TreeCtrl.SetBkColor(x2) ; CString temp; temp.Format("%lu", (unsigned long)x2); if (! pSockApp->my_controls.SetStringByTokenName("tree_back_color", temp)) { AfxMessageBox("trouble saving tree backcolor in properties"); } else { pSockApp->SavePropsToFile(); } } } if (ncmd == ID_TREEFONT) { CHOOSEFONT chf; HDC hDC; hDC = ::GetDC (this->m_hWnd); chf.hDC = CreateCompatibleDC (hDC); ::ReleaseDC (this->m_hWnd, hDC); chf.lStructSize = sizeof (CHOOSEFONT); chf.hwndOwner = this->m_hWnd; chf.lpLogFont = &tree_lf; chf.Flags = CF_SCREENFONTS | CF_EFFECTS | CF_INITTOLOGFONTSTRUCT ; chf.rgbColors = m_TreeCtrl.crForeColor; chf.lCustData = 0; chf.hInstance = AfxGetInstanceHandle(); chf.lpszStyle = (LPTSTR)NULL; chf.nFontType = SCREEN_FONTTYPE; chf.nSizeMin = 0; chf.nSizeMax = 0; int n = ::ChooseFont(&chf); if (n != 0) { if (m_ptreefont) delete m_ptreefont; m_ptreefont = new CFont(); m_ptreefont->CreateFontIndirect(&tree_lf); bTreeFontChanged = true; m_TreeCtrl.SetFont(m_ptreefont); m_TreeCtrl.crForeColor = chf.rgbColors; //m_TreeCtrl.RedrawWindow(); SaveTreeFont(); } //m_TreeCtrl.SetFont(&m_mainfont); } } void CSecuresockDlg::OnAddContactButton() { CLookupContacts lookupdlg; lookupdlg.DoModal(); } void CSecuresockDlg::OnWebButton() { // this should execute internet explorer or whatever browser is the default and open // up a browser window to point to our site's definition of stuff. ::ShellExecute(NULL, NULL, "http://www.drakis.com", NULL, "", SW_SHOW); } void CSecuresockDlg::OnAddGroupButton() { HTREEITEM newone; CString last_icon = pSockApp->my_controls.GetStringByTokenName("last_new_dept_icon"); int next_icon_offset; int next_icon_val; int max_size = m_GroupIcons_CIV_Vector.size(); // remember if offset = max_size this is off the end so reset to zero since can't have // vector[n] where n= vector.size() (this is a bounds error) if ( atoi(last_icon.GetBuffer(0) ) >= max_size || atoi(last_icon.GetBuffer(0)) < 0 ) { // reset offset to zero again next_icon_offset = 0; } else { int ival = atoi(last_icon.GetBuffer(0) ); ival++; if (ival >= max_size ) ival = 0; next_icon_offset = ival; } next_icon_val = GetIndexFromIconID(m_GroupIcons_CIV_Vector[next_icon_offset].ICONIDD); // this shouldn't happen but if it does use default first icon which is currently // index 26 into the imagelist (this may change tho) if (next_icon_val == -1) next_icon_val = 26; CString temp; temp.Format("%i", next_icon_offset); //AfxMessageBox( temp ); pSockApp->my_controls.SetStringByTokenName("last_new_dept_icon", temp); pSockApp->SavePropsToFile(); newone = m_TreeCtrl.InsertItem( "New Group", next_icon_val, next_icon_val, TVI_ROOT, TVI_LAST); ChatItemInfo *citemp; citemp = new ChatItemInfo; citemp->chat_id = 0; citemp->ntype = GROUP; citemp->create_time = GetTimeString() ; citemp->msg = "Contact Group"; add_ptr_to_garbage(citemp, "ChatItemInfo"); m_TreeCtrl.SetItemData( newone, (DWORD)citemp ); m_TreeCtrl.EditLabel(newone); } void CSecuresockDlg::OnConnectionButton() { DWORD dp = ::GetMessagePos(); CPoint pt ((int) LOWORD( dp ), (int) HIWORD (dp) ); UINT flags = NULL; CMenu menu; menu.LoadMenu(IDR_CONNECTION); CMenu *x; x = menu.GetSubMenu(0); CMenu users_menu; users_menu.CreatePopupMenu(); CRect rect; GetWindowRect(rect); //CPoint y; //::GetCursorPos(&y); //ScreenToClient (&y); CPoint pt2 ((int) LOWORD( dp ), (int) HIWORD (dp) ); int ncmd = x->TrackPopupMenu( TPM_RETURNCMD | TPM_LEFTALIGN , pt2.x, pt2.y, AfxGetMainWnd(), rect ); if (ncmd == ID_CHECKLATENCY) { GetLatency() ; } if (ncmd == ID_CONNPROPERTIES) { AfxMessageBox("Under Construction"); } //AfxMessageBox("cli"); } void CSecuresockDlg::CreateStatusText() { CClientDC dc(this); LOGFONT lf; ::ZeroMemory(&lf, sizeof(lf)); lf.lfHeight = 80; lf.lfWeight = FW_BOLD; lf.lfItalic = FALSE; ::lstrcpy( lf.lfFaceName, "Arial"); m_mainfont.CreatePointFontIndirect(&lf); CFont *old_font = dc.SelectObject(&m_mainfont); TEXTMETRIC tm; dc.GetTextMetrics(&tm); int m_cxChar = tm.tmAveCharWidth; int m_cyChar = tm.tmHeight + tm.tmExternalLeading; dc.SelectObject(old_font); CRect rect (m_cxChar * 2, m_cyChar * 2, m_cxChar * 25, m_cyChar * 4); m_online_status.Create("connecting...", WS_CHILD | WS_VISIBLE | SS_LEFT, rect, this); //rect = CRect(m_cxChar * 5, m_cyChar * 5, m_cxChar * 100, m_cyChar * 5); m_my_status.Create("User Status: Active", WS_CHILD | WS_VISIBLE | SS_LEFT, rect, this); m_online_status.SetFont(&m_mainfont); m_my_status.SetFont(&m_mainfont); m_RedBrush.CreateSolidBrush( RGB( 255, 64, 64) ); m_GreenBrush.CreateSolidBrush( RGB( 64, 255, 64) ); m_BlackBrush.CreateSolidBrush( RGB( 0, 0, 0) ); if (1) { RECT chkrect; pCWnd->GetWindowRect(&chkrect); CWnd *pwnd2 = (CWnd *)(&m_my_status); int x, y, cx, cy; x = 0; y = chkrect.bottom - chkrect.top - 43; cx = 100; cy = 20; //ASSERT(0); /* pwnd2->SetWindowPos( NULL , 10 , y, 100, 100 , SWP_SHOWWINDOW ); */ /* pwnd2 = (CWnd *)(&m_my_status); pwnd2->SetWindowPos( NULL, 100 , y, 100, 100, SWP_SHOWWINDOW ); */ } } void CSecuresockDlg::OnSysChar(UINT nChar, UINT nRepCnt, UINT nFlags) { //if (nChar == VK_CANCEL) //AfxMessageBox("cancel hit"); CDialog::OnSysChar(nChar, nRepCnt, nFlags); } // signup a new user by getting various info via dialogs bool CSecuresockDlg::SignupUser(bool bWelcomeScreen ) { int myresult; int choice = 1; char *newptr; if (bWelcomeScreen) { WelcomeDlg mypersonal; myresult = mypersonal.DoModal(); choice = mypersonal.m_choice; if (mypersonal.m_choice == 0) return false; } if (choice == 1 || ! bWelcomeScreen ) { PersonalInfoDlg pid; myresult = pid.DoModal(); if (pSockApp->m_canceled) return false; CCompDlg cid; myresult = cid.DoModal(); if (pSockApp->m_canceled) return false; InternetInfoDlg iid; myresult = iid.DoModal(); if (pSockApp->m_canceled) return false; GetChatID pid2; myresult = pid2.DoModal(); if (pSockApp->m_canceled) return false; IconChooser icd; icd.bGroupIcon = false; // the postncdestroy method in IconChooser will delete this memory allocated // here so this isn't a real memory leak newptr = new char[100]; strcpy(newptr, "Select Your Personal Chat Icon"); // set the caption for the chooser dialog, uses soft logic if not set then uses // a default value (this dialog is called from other places than registration) icd.title = newptr; // this isn't a memory leak the dialog itself will release the // memory via delete [] for this pointer icd.m_signup = 1; // registration level call (screen can be called from different places // in the program this flag helps to differentiate myresult = icd.DoModal(); if (pSockApp->m_canceled) { return false; } int ICONIDD; // if they didn't hit cancel but selected a real icon if (icd.ICON_IDD != -1) { ICONIDD = icd.ICON_IDD; } else { // this is if they canceled instead of selecting an icon AfxMessageBox("A generic icon will be used, you may change this later via \"change icon\" "); ICONIDD = IDI_ICON31; } HICON hIcon; // if selected a real icon if (ICONIDD != -1) { hIcon = ::LoadIcon (AfxGetResourceHandle(), MAKEINTRESOURCE(ICONIDD)); m_mypersonalbutton.SetIcon( hIcon ); } else { // otherwise use the default one ICONIDD = IDI_ICON31; // ICON31 is a default, if they didn't select it we set default to that // rather than show an empty icon button hIcon = ::LoadIcon (AfxGetResourceHandle(), MAKEINTRESOURCE(ICONIDD)); m_mypersonalbutton.SetIcon( hIcon ); } CString temp; temp.Format("%i", ICONIDD); if (! pSockApp->my_controls.SetStringByTokenName("user_icon", temp)) AfxMessageBox("trouble setting user_icon in properties"); // save favorite icon choice to userprop2.ids //ofstream optionsFile2 ( "userprop2.ids", ios::out ); //optionsFile2 << setw(7) << ICONIDD << '\n'; // save this to a class variable also so we can keep track of the last personal icon // add a save function to the destructor m_my_personal_icon_id = ICONIDD; pSockApp->SavePropsToFile(); //pSockApp->AddUser( strtoul( buffer, NULL, 10), cnickname, bdefault ); //char *temp_password = ; CString nickname = pSockApp->my_controls.GetStringByTokenName("nickname"); pSockApp->AddUser( pSockApp->my_controls.GetChatId(), nickname.GetBuffer(0), pSockApp->my_controls.GetPassword(), true); } return true; } bool CSecuresockDlg::LoadUserIds(void) { int n; ifstream users_file ( "users.ids" ); //char buffer[257]; //char cnickname[101]; char is_default; //char discard; bool bdefault; bool hitdefault = false; unsigned long chat_id; char text[256]; int itextlen; //char cchat_id[11]; //ASSERT(0); if (users_file) { n = 0; //users_file.unsetf( ios::skipws ); //users_file.seekg(0); while (! users_file.eof() ) { //stream_stuff::read_long(users_file, &contact_id); if (users_file.read(text, 10) == 0) break; text[10] = (char)0; chat_id = strtoul(text, NULL, 10); users_file.read(text, 1); is_default = text[0]; users_file.read(text, 4); text[4] = 0; itextlen = atoi(text); users_file.read(text, 1); //itextlen++; // add one for zero terminator if (itextlen < 0 || itextlen > 254 ) { ASSERT(0); AfxMessageBox("corrupt users list file serious error, contact programmer"); users_file.close(); return false; } users_file.read(text, itextlen); text[itextlen] = (char)0; bdefault = ! (is_default == '0'); pSockApp->AddUser( chat_id, text, "", bdefault ); hitdefault = hitdefault || bdefault; users_file.read(text,1); } users_file.close(); if (! hitdefault) { CString msg; msg.Format("No User is set to default, setting default to %s", pSockApp->users_array[0].nickname.GetBuffer(0)); AfxMessageBox( msg ); pSockApp->SetDefaultUser( 0 ); } } else { return false; } return true; } void CSecuresockDlg::LoadGroupIconVector(void) { int n; CImageVector temp; m_GroupIcons_CIV_Vector.clear(); int n2 = 0; for (n=IDI_ICON24; n <= IDI_ICON60;n++) { if (n==IDI_ICON31) continue; if (n==IDI_ICON30) continue; if (n==159 || n == 160) continue; temp.nindex = n2++; temp.ICONIDD = n; m_GroupIcons_CIV_Vector.push_back(temp); } } void CSecuresockDlg::LoadImageList() { m_ImageList.Create(16, 16, ILC_MASK | ILC_COLOR, // list does not include masks 0, 1 ); // list will not grow HICON hIcon; int result; // // load the icon images and add them // to the image lists // int n; int n2 = 0; for (n=129;n<159;n++) { hIcon = ::LoadIcon (AfxGetResourceHandle(), MAKEINTRESOURCE(n)); result = m_ImageList.Add(hIcon); CSecuresockApp *ref_app; CImageVector temp; ref_app = (CSecuresockApp *)AfxGetApp(); temp.nindex = n2++; temp.ICONIDD = n; ref_app->m_imagevector.push_back(temp); } for (n=161;n<=190;n++) { hIcon = ::LoadIcon (AfxGetResourceHandle(), MAKEINTRESOURCE(n)); result = m_ImageList.Add(hIcon); CSecuresockApp *ref_app; CImageVector temp; ref_app = (CSecuresockApp *)AfxGetApp(); temp.nindex = n2++; temp.ICONIDD = n; ref_app->m_imagevector.push_back(temp); } for (n=207;n<=214;n++) { hIcon = ::LoadIcon (AfxGetResourceHandle(), MAKEINTRESOURCE(n)); result = m_ImageList.Add(hIcon); CSecuresockApp *ref_app; CImageVector temp; ref_app = (CSecuresockApp *)AfxGetApp(); temp.nindex = n2++; temp.ICONIDD = n; ref_app->m_imagevector.push_back(temp); } n = IDI_ICON83; hIcon = ::LoadIcon (AfxGetResourceHandle(), MAKEINTRESOURCE(n)); result = m_ImageList.Add(hIcon); CSecuresockApp *ref_app; CImageVector temp; ref_app = (CSecuresockApp *)AfxGetApp(); temp.nindex = n2++; temp.ICONIDD = n; ref_app->m_imagevector.push_back(temp); for (n=IDI_ICON84;n<=IDI_ICON93;n++) { hIcon = ::LoadIcon (AfxGetResourceHandle(), MAKEINTRESOURCE(n)); result = m_ImageList.Add(hIcon); CSecuresockApp *ref_app; CImageVector temp; ref_app = (CSecuresockApp *)AfxGetApp(); temp.nindex = n2++; temp.ICONIDD = n; ref_app->m_imagevector.push_back(temp); } for (n=IDI_ICON94; n <= IDI_ICON114;n++) { hIcon = ::LoadIcon (AfxGetResourceHandle(), MAKEINTRESOURCE(n)); result = m_ImageList.Add(hIcon); CSecuresockApp *ref_app; CImageVector temp; ref_app = (CSecuresockApp *)AfxGetApp(); temp.nindex = n2++; temp.ICONIDD = n; ref_app->m_imagevector.push_back(temp); } for (n = IDI_ICON115; n <= IDI_ICON115;n++) { hIcon = ::LoadIcon (AfxGetResourceHandle(), MAKEINTRESOURCE(n)); result = m_ImageList.Add(hIcon); CSecuresockApp *ref_app; CImageVector temp; ref_app = (CSecuresockApp *)AfxGetApp(); temp.nindex = n2++; temp.ICONIDD = n; ref_app->m_imagevector.push_back(temp); } // hIcon = ::LoadIcon (AfxGetResourceHandle(), MAKEINTRESOURCE(234)); result = m_ImageList.Add(hIcon); BOOL bres = m_ImageList.SetOverlayImage( n2, 1 ); ASSERT(bres); n2++; hIcon = ::LoadIcon (AfxGetResourceHandle(), MAKEINTRESOURCE(235)); result = m_ImageList.Add(hIcon); bres = m_ImageList.SetOverlayImage( n2, 2 ); ASSERT(bres); n2++; hIcon = ::LoadIcon (AfxGetResourceHandle(), MAKEINTRESOURCE(236)); result = m_ImageList.Add(hIcon); bres = m_ImageList.SetOverlayImage( n2, 3 ); ASSERT(bres); n2++; hIcon = ::LoadIcon (AfxGetResourceHandle(), MAKEINTRESOURCE(237)); result = m_ImageList.Add(hIcon); bres = m_ImageList.SetOverlayImage( n2, 4 ); ASSERT(bres); n2++; m_TreeCtrl.SetImageList( &m_ImageList, TVSIL_NORMAL); //m_ImageList.DeleteImageList(); } void CSecuresockDlg::AddTrayIcon() { NOTIFYICONDATA nid; nid.cbSize = sizeof(nid); nid.hWnd = this->m_hWnd; nid.uID = 1; nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; nid.uCallbackMessage = WM_TRAY_IDD; HICON hicon2; hicon2 = ::LoadIcon (AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_ICON27)); nid.hIcon = hicon2; strcpy(nid.szTip, "SecureChat"); // use mutex to make sure there isn't another shell icon already up ::CreateMutex(NULL, TRUE, "SecureChatTBIcon"); if ( GetLastError() != ERROR_ALREADY_EXISTS ) Shell_NotifyIcon(NIM_ADD, &nid); // it wasn't there add it now } void CSecuresockDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { //CString output; //output.Format("%u", nID); //AfxMessageBox(output); if (nID == SC_MINIMIZE) { //AfxMessageBox("minimizing"); this->ShowWindow(SW_HIDE); return; } CDialog::OnSysCommand(nID, lParam); } } void CSecuresockDlg::OnDestroy() { WinHelp(0L, HELP_QUIT); ::clean_up_garbage(); if (m_ptreefont) delete m_ptreefont; CDialog::OnDestroy(); } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CSecuresockDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } // The system calls this to obtain the cursor to display while the user drags // the minimized window. HCURSOR CSecuresockDlg::OnQueryDragIcon() { return (HCURSOR) m_hIcon; } // Automation servers should not exit when a user closes the UI // if a controller still holds on to one of its objects. These // message handlers make sure that if the proxy is still in use, // then the UI is hidden but the dialog remains around if it // is dismissed. void CSecuresockDlg::OnClose() { ((CSecuresockApp *)AfxGetApp())->SavePosInfo((CWnd *)this, "Main Dialog"); SaveUsersToFile(); if (CanExit()) CDialog::OnClose(); } void CSecuresockDlg::OnOK() { //AfxMessageBox("ok"); if (CanExit()) { CDialog::OnOK(); //DestroyWindow(); } } void CSecuresockDlg::OnCancel() { //AfxMessageBox("cancel"); if (CanExit()) { CDialog::OnCancel(); //DestroyWindow(); } } BOOL CSecuresockDlg::CanExit() { // If the proxy object is still around, then the automation // controller is still holding on to this application. Leave // the dialog around, but hide its UI. if (m_pAutoProxy != NULL) { ShowWindow(SW_HIDE); return FALSE; } return TRUE; } void CSecuresockDlg::OnRclickTree1(NMHDR* pNMHDR, LRESULT* pResult) { if (0) { sndPlaySound("driveby.wav", SND_ASYNC); } DWORD dp = ::GetMessagePos(); CPoint pt ((int) LOWORD( dp ), (int) HIWORD (dp) ); m_TreeCtrl.ScreenToClient (&pt); UINT flags = NULL; //char buffer[20]; int choice; int myresult; //DWORD this_contact_id; HTREEITEM thishitem = m_TreeCtrl.HitTest( pt, &flags); m_TreeCtrl.SelectItem( thishitem ); bool bHitTestFailed = false; // NULL means they clicked in area which is not an item so ignore if ( thishitem == NULL) { *pResult = 1; bHitTestFailed = true; //return; } ChatItemInfo *tempci; //ChatItemInfo *citemp ; CLookupContacts lookupdlg; CMenu menu; menu.LoadMenu(IDR_MENU1); CMenu *x; bool bGroupLevelCall; bool bSystemMsg = false; bool bIncCR = false; bool bPCGroup = false; bool bChatContact = false; // if we aren't on a non-item, grab the related chatiteminfo pointer from the item selected if (! bHitTestFailed ) { tempci = (ChatItemInfo *)(m_TreeCtrl.GetItemData( thishitem )); bPCGroup = (tempci->ntype == PENDING_CONTACTS_GROUP); bChatContact = (tempci->ntype == CHAT_CONTACT ); } // if on no item then show this short menu if (bHitTestFailed) { x = menu.GetSubMenu(7); // if top level item = department, use department menu, otherwise use contact menu } else if ( m_TreeCtrl.GetParentItem(thishitem) == NULL) { x = menu.GetSubMenu(1); bGroupLevelCall = true; } else { if (tempci->ntype == SYSTEM_MSG) { x = menu.GetSubMenu(5); bSystemMsg = true; } else if ( tempci->ntype == INCOMING_CONTACT_REQUEST ) { x = menu.GetSubMenu(6); bIncCR = true; } else { x = menu.GetSubMenu(0); x->DeleteMenu(ID_RIGHTCLICK_SPLITWINDOWCHAT, MF_GRAYED); } // MF_GRAYED //BOOL ModifyMenu( UINT nPosition, UINT nFlags, UINT nIDNewItem = 0, LPCTSTR lpszNewItem = NULL ); bGroupLevelCall = false; } CRect rect; GetWindowRect(rect); CPoint pt2 ((int) LOWORD( dp ), (int) HIWORD (dp) ); // i get the value back directly rather than map it as a COMMAND message, which would also // be fine. int ncmd = x->TrackPopupMenu( TPM_RETURNCMD | TPM_LEFTALIGN , pt2.x, pt2.y, AfxGetMainWnd(), rect ); // defining variables within case statements is causing a weird bug with default: clause // something about "initialization of variable x not found for default" which makes no sense I think // this is a Visual C++ bug with case statements, i like to define temp variables only within the block // of code used but in this case some are defined at a higher level (temp here and myresult, etc above) CString temp; //ChatItemInfo *tempci = new ChatItemInfo; CString temp1; CPropDlg pd; MyCtrlContainer *ptempCtrlContainer; CMyPropSheet testprop(IDS_MYPROPS, this, 0) ; CPersP1 p1; CPersP3 p3; CPers_P2 p2; CString msg1; CString last_icon; CMoveContactDlg mcd; CAcceptContact acdlg; int nresult; int response; switch (ncmd ) { /*case ID_GET_CHATID: this_contact_id = m_TreeCtrl.GetItemData( thishitem ); temp.Format("chat id:%u", this_contact_id); MessageBox( temp ); break; */ case ID_ACCEPT: ProcessChatRequest(thishitem, tempci, true); //AfxMessageBox("add"); break; case ID_DECLINE: ProcessChatRequest(thishitem, tempci, false); //AfxMessageBox("decline"); break; case ID_VIEW: tempci = (ChatItemInfo *)(m_TreeCtrl.GetItemData( thishitem )); acdlg.m_ContactMsg = tempci->msg; nresult = acdlg.DoModal(); if (acdlg.nstatus == 1) { //AfxMessageBox("add"); ProcessChatRequest(thishitem, tempci, true); } if (acdlg.nstatus == 0) { //AfxMessageBox("decline"); ProcessChatRequest(thishitem, tempci, false); } break; case ID_TREE_ITEM_INFO: tempci = (ChatItemInfo *)(m_TreeCtrl.GetItemData( thishitem )); temp1.Format("related chat id:%lu\nitem type:%s\ndescrip:%s\ncreated:%s", tempci->chat_id, ChatItemInfo::TypeDescrip(tempci->ntype), tempci->msg, tempci->create_time ); //MB( temp1, MB_OK, "Item Properties" ); pd.m_ChatId.Format("%lu", tempci->chat_id); pd.m_Created = tempci->create_time; pd.m_Descrip = tempci->msg; pd.m_ItemType = ChatItemInfo::TypeDescrip(tempci->ntype); pd.m_Nickname = tempci->nickname; pd.m_Time_Received = tempci->time_received; pd.m_Icon_ID.Format("%i", tempci->icon_id); //pd.UpdateData(FALSE); pd.DoModal(); break; case ID_PROPERTIES: // get related chat info item tempci = (ChatItemInfo *)(m_TreeCtrl.GetItemData( thishitem )); // open a new control container with this chat_id as default ptempCtrlContainer = new MyCtrlContainer(); // update the properties in the control container from the web ptempCtrlContainer->BlankAllValues(); ptempCtrlContainer->SetChatId(tempci->chat_id); msg1 = "Getting Server Settings"; CMiscStuff::WaitWindow( msg1, this ); ptempCtrlContainer->UpdateLocalFromURL(); //Sleep(2000); CMiscStuff::ClearWaitWindow(); // assign this temporary control container to the app (used by dialogues saving/ // get window val routines). pSockApp->m_pcontact_mcc = ptempCtrlContainer; // make sure this flag is set back to false when done so signing a new user or viewing // your own properties pulls from the right control container pSockApp->m_bUsingOtherProp = true; testprop.m_psh.dwSize = sizeof(testprop.m_psh); testprop.m_psh.dwFlags |= PSH_NOAPPLYNOW ; testprop.m_bViewingOthers = true; testprop.newtitle.Format("Viewing Properties for User %lu [Read-only]", tempci->chat_id); p1.m_psp.dwFlags &= (~PSH_HASHELP); p2.m_psp.dwFlags &= (~PSH_HASHELP); p3.m_psp.dwFlags &= (~PSH_HASHELP); testprop.AddPage(&p1); testprop.AddPage(&p2); testprop.AddPage(&p3); response = testprop.DoModal(); if (response == IDOK) { //pSockApp->SavePropsToFile(); // save properties to web //pSockApp->my_controls.UpdateURLwithInfo(); } // ALWAYS SET THIS TO FALSE WHEN DONE, lets the app know whether we are looking at someone else's // properties or at those for the current user (or a new user signing on) pSockApp->m_bUsingOtherProp = false; // reset this pointer to zero when not in use pSockApp->m_pcontact_mcc = (MyCtrlContainer *)0; delete ptempCtrlContainer; break; case ID_ADDUSER: if (!SignupUser( false ) ) { AfxMessageBox("Trouble adding this user, notify Programmer"); } case ID_RIGHTCLICK_SPLITWINDOWCHAT: pdlg = new TwoWayDlg(); pdlg->m_bModeless = TRUE; // retrieve this person's image from the tree control int iimage; if ( (iimage = m_TreeCtrl.GetImageIndex(thishitem)) != -1) { pdlg->m_myiconid = iimage; } else { pdlg->m_myiconid = 30; MessageBox("debug note: trouble getting image for this tree item"); } pdlg->Create(); break; case ID_OPTION1_ADDNEWDEPT: OnAddGroupButton(); break; case ID_RIGHTCLICK_NICKNAME: //int itest = rand() % 3; // give them a reminder MessageBox( "You can change this users Nickname to something more preferable, just be sure you don't " "get confused who this contact refers to. You can always right click and select TreeItem Info to see what is " "their common Chat Nickname. This new Nickname will not be sent to them via any mechanism it is simply for your" "own tree display.", "Reminder", MB_OK ) ; m_TreeCtrl.EditLabel(thishitem); CEdit *scooby; scooby = m_TreeCtrl.GetEditControl(); // if we don't subclass it the dialog will override enter and cancel keys which is not // optimal behavior. another trick from an online example. m_TreeEdit.SubclassWindow( scooby->m_hWnd ); m_inick = 1; break; case ID_OPTION1_EDITLABEL: m_TreeCtrl.EditLabel(thishitem); break; case ID_OPTION1_ADDCONTACT: // 30 is the default contact icon for now lookupdlg.DoModal(); //m_TreeCtrl.InsertItem( "New Contact", 30, 30, thishitem); //m_TreeCtrl.Expand( thishitem, TVE_EXPAND); break; case ID_RIGHTCLICK_DELETE: case ID_OPTION1_REMOVEGROUP: char buffer[200]; //ASSERT(0); if (m_TreeCtrl.GetItemData( thishitem ) == 2) { AfxMessageBox("Sorry you can't delete this group as it's needed for keeping track of System Messages. =)"); break; } if (! m_TreeCtrl.GetLabelText(thishitem, buffer, 200) ) strcpy(buffer, ""); if (bSystemMsg) { temp = "Do you wish to delete this system message? Note: pending contact requests and other " "operations will not be adversely affected by deleting system messages. " "All messages will have related entries in the message logs."; } else { if (ncmd == ID_OPTION1_REMOVEGROUP) { if (!bPCGroup) temp.Format("Are you sure you wish to remove the Group %s from your contact list?\n " "Warning: this will remove all attached contacts to this group " "and you will have to re-add them later. Continue?", buffer); else temp.Format("Deleting the Incoming Contact Request Group will delete all Incoming Contact Requests associated with it, continue?", buffer); } else if ( bIncCR ) { temp.Format("Deleting an Incoming Contact Request will remove the Request Message without issuing an accept or decline. Are you sure you wish to do this?", buffer); } else if (bPCGroup ) { temp.Format("Deleting the Incoming Contact Request Group will delete all Incoming Contact Request associated with it, continue?", buffer); } else { temp.Format("Are you sure you wish to remove %s from your contact list?", buffer); } } if ( MB( temp.GetBuffer(0), MB_YESNO, "Delete?" ) == IDYES ) { m_TreeCtrl.DeleteItem( thishitem ); } break; case ID_RIGHTCLICK_SENDMESSAGE : //m_TreeCtrl.SelectItem( thishitem ); CSendDlg *senddlg; //MessageBox("send message"); senddlg = new CSendDlg(); senddlg->iUserIconID = tempci->icon_id; TRACE("calling send dlg, chat id : %lu", tempci->chat_id); //tempci->chat_id //AfxMessageBox( tempci->nickname ); TRACE("nickname: %s", tempci->nickname.GetBuffer(0)); senddlg->m_myiconid = m_TreeCtrl.GetImageIndex(thishitem); senddlg->m_nickname = tempci->nickname; senddlg->chat_id = tempci->chat_id; senddlg->Create(); senddlg->SetActiveWindow(); break; case ID_HISTORY: AfxMessageBox("not yet supported"); break; case ID_MOVE_GROUP: AfxMessageBox("not yet supported"); break; case ID_CHANGE_ICON1: if (! bGroupLevelCall) { int response = MB("You may change a user's display icon in your treeview to something you like more but be " "careful not to get confused as to who they are.\nRemember you can always right click and select Quick Info if you get confused.\nContinue with changing their Icon?", MB_YESNO); if (response != IDYES) break; } IconChooser myChooserDlg; myChooserDlg.bGroupIcon = bGroupLevelCall; myChooserDlg.m_signup = 0; myresult = myChooserDlg.DoModal(); choice = this->GetIndexFromIconID(myChooserDlg.ICON_IDD); if ((myresult == IDOK) && (choice != -1)) { m_TreeCtrl.SetImagesByIndex(thishitem, choice); tempci->icon_id = myChooserDlg.ICON_IDD; // save new icon to the properties file //SaveMyIcon(GetIconIDFromIndex(choice)); } break; //default: // itoa(ncmd, buffer, 10); // MessageBox(buffer, "Unhandled command value"); } //_itoa( ncmd, buffer, 10); //AfxMessageBox(buffer); menu.DestroyMenu(); //SendMessage( WM_LBUTTONUP, 0, MAKELPARAM(1,1)); //::SendMessage( GetDlgItem(IDC_TREE1)->m_hWnd, WM_RBUTTONUP, 0, MAKELPARAM((unsigned)y.x, (unsigned)y.y)); *pResult = 1; return; } void CSecuresockDlg::OnButton1() { if (rclickmenu) { CRect rect; GetWindowRect(rect); char buffer[20]; sprintf(buffer, "%i, %i, %i, %i", rect.left, rect.right, rect.top, rect.bottom); //AfxMessageBox(buffer); rclickmenu->TrackPopupMenu( TPM_LEFTALIGN | TPM_LEFTBUTTON, rect.left, rect.bottom -1, AfxGetMainWnd(), rect); } } void CSecuresockDlg::OnSize(UINT nType, int cx, int cy) { CDialog::OnSize(nType, cx, cy); CWnd *pwnd = (CWnd *)(&m_TreeCtrl); if (::IsWindow(pwnd->m_hWnd)) { pwnd->SetWindowPos( NULL , 0, 38, cx, cy - 60, 0 ); } //CWnd *pwnd2 = (CWnd *)(&m_online_status); RECT rect; /* if (::IsWindow(pwnd2->m_hWnd)) { pwnd2->GetWindowRect(&rect); pwnd2->SetWindowPos( NULL , 10, cy - 17, cx, cy , 0 ); //pwnd2->Invalidate(); // cause color repaint, not sure if strictly necessary } else { //AfxMessageBox("failure with window 1"); } */ CWnd *pwnd3 = (CWnd *)(&m_my_status); if (::IsWindow(pwnd3->m_hWnd)) { pwnd3->SetWindowPos( NULL , 101, cy - 19, 600, cy , 0 ); //pwnd3->GetWindowRect(&rect); //CString out; //out.Format("%i, %i, %i, %i", rect.top, rect.left, rect.bottom, rect.right ); //AfxMessageBox(out); //::InvalidateRect(this->m_hWnd, &rect, TRUE); pwnd3->Invalidate(); // cause color repaint, not sure if strictly necessary } else { //AfxMessageBox("failure with window 2"); } CWnd *pwnd2 = (CWnd *)(&m_online_status); //RECT rect; if (::IsWindow(pwnd2->m_hWnd)) { pwnd2->GetWindowRect(&rect); pwnd2->SetWindowPos( NULL , 0, cy - 19, 79, cy , 0 ); //pwnd2->Invalidate(); // cause color repaint, not sure if strictly necessary } else { //AfxMessageBox("failure with window 1"); } CWnd *mstatusb = (CWnd *)(&m_setstatusbutton); if (::IsWindow(mstatusb->m_hWnd) ) { mstatusb->SetWindowPos(NULL, 80, cy - 20, 20, 20, 0); } this->GetWindowRect(&rect); //::InvalidateRect(this->m_hWnd, &rect, TRUE); firstcall++; } void gettreeiconindexes( const CTreeCtrl &piTree, HTREEITEM pitem, int &image, int &sel_image, bool &is_expanded ) { TVITEM tv; BOOL result; tv.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_STATE ; tv.hItem = pitem; tv.stateMask = TVIS_EXPANDED; is_expanded = false; result = piTree.GetItem( &tv ); if (result) { image = tv.iImage; sel_image = tv.iSelectedImage; is_expanded = ! ((tv.state & TVIS_EXPANDED)==0); if (is_expanded) { //ASSERT(0); } } else { image = sel_image = -1; } } void settreeexpanded( CTreeCtrl &piTree, HTREEITEM pitem, bool is_expanded ) { TVITEM tv; BOOL result; tv.mask = TVIF_STATE ; tv.hItem = pitem; tv.stateMask = TVIS_EXPANDED; if (is_expanded ) tv.state = TVIS_EXPANDED; else tv.state = 0; result = piTree.SetItem( &tv ); if (!result) { ASSERT(0); } } CString gettreetext( const CTreeCtrl &piTree, HTREEITEM pitem ) { TVITEM tv; BOOL result; CString x1; tv.mask = TVIF_TEXT ; tv.hItem = pitem; tv.stateMask = 0; char buffer3[200]; tv.pszText = buffer3; tv.cchTextMax = 200; result = piTree.GetItem( &tv ); if (result) { x1 = tv.pszText; } else { x1 = ""; } return x1; } void SaveOne(vector <TreeSaver> &tscopy, HTREEITEM hitem, char *param_text, int param_id, int param_parent, int contact_id, int iimage, int isel_image, bool is_expanded) { TreeSaver thisone; thisone.id = param_id; thisone.parent_id = param_parent; if (strlen( param_text) > 99) { strncpy(thisone.text, param_text, 99); thisone.text[99] = (char)0; } else { strcpy(thisone.text, param_text ); } thisone.contact_id = contact_id; thisone.hitem = hitem; thisone.iimage = iimage; thisone.isel_image = isel_image; thisone.is_expanded = is_expanded; tscopy.push_back( thisone ); } // new saveone now uses ChatItemInfo pointer for 32 bit value void SaveOne(vector <TreeSaver> &tscopy, HTREEITEM hitem, char *param_text, int param_id, int param_parent, ChatItemInfo *pchatinfo, int iimage, int isel_image, bool is_expanded) { TreeSaver thisone; thisone.id = param_id; thisone.parent_id = param_parent; if (strlen( param_text) > 99) { strncpy(thisone.text, param_text, 99); thisone.text[99] = (char)0; } else { strcpy(thisone.text, param_text ); } thisone.contact_id = pchatinfo->chat_id; thisone.hitem = hitem; thisone.iimage = iimage; thisone.isel_image = isel_image; thisone.is_expanded = is_expanded; thisone.ntype = pchatinfo->ntype; thisone.msg = pchatinfo->msg; //thisone. thisone.create_time = pchatinfo->create_time; thisone.time_received = pchatinfo->time_received; thisone.nickname = pchatinfo->nickname; thisone.icon_id = pchatinfo->icon_id; tscopy.push_back( thisone ); } void CSecuresockDlg::OnEndlabeleditTree1(NMHDR* pNMHDR, LRESULT* pResult) { TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR; char buffer3[200]; if (pTVDispInfo->item.pszText == NULL) { *pResult = 0; return; } if (strlen(pTVDispInfo->item.pszText) > 199) { AfxMessageBox("Max item text length is 200, retry"); *pResult = 0; return; } strcpy(buffer3, pTVDispInfo->item.pszText ); TVITEM tv; BOOL result; tv.mask = TVIF_TEXT ; tv.hItem = pTVDispInfo->item.hItem; tv.stateMask = 0; tv.pszText = buffer3; tv.cchTextMax = 200; result = m_TreeCtrl.SetItem( &tv ); // TODO: Add your control notification handler code here *pResult = 0; } void CSecuresockDlg::OnKeydownTree1(NMHDR* pNMHDR, LRESULT* pResult) { TV_KEYDOWN* pTVKeyDown = (TV_KEYDOWN*)pNMHDR; HTREEITEM s = m_TreeCtrl.GetSelectedItem( ); if (s == NULL) { *pResult = 0; return; } CString temp; temp.Format("pushed key:%i", pTVKeyDown->wVKey); //AfxMessageBox(temp); if (pTVKeyDown->wVKey == 46) { CString x1; CString x2 = gettreetext( m_TreeCtrl, s ); ChatItemInfo *tempci; bool bIncCR = false; tempci = (ChatItemInfo *)(m_TreeCtrl.GetItemData( s )); if (tempci->ntype == INCOMING_CONTACT_REQUEST ) bIncCR = true; if (m_TreeCtrl.GetParentItem(s) == NULL) { x1.Format("Are you sure you wish to remove Group %s from your contact list?\n Warning: this will remove all attached contacts to this department and you will have to re-add them later. Continue?", x2.GetBuffer(10)); } else if (bIncCR) { x1.Format("Deleting an Incoming Contact Request will remove the Request Message without issuing an accept or decline. Are you sure you wish to do this?", x2.GetBuffer(0)); } else { x1.Format("Are you sure you wish to remove %s from your contact list?", x2.GetBuffer(10)); } if ( IDYES == ::MessageBox( this->m_hWnd, // handle of owner window x1.GetBuffer(10), // address of text in message box "Delete?", // address of title of message box MB_YESNO // style of message box ) ) { m_TreeCtrl.DeleteItem( s ); } } *pResult = 1; } void CSecuresockDlg::OnReturnTree1(NMHDR* pNMHDR, LRESULT* pResult) { // TODO: Add your control notification handler code here //CString temp; //temp.Format("pushed key:%i", pTVKeyDown->wVKey); //AfxMessageBox("hit return"); *pResult = 0; } void CSecuresockDlg::SaveImageList() { // test code for image archive CFile *newone = new CFile( "image_list.ids", CFile::modeWrite | CFile::modeCreate ); if (newone) { CArchive *test = new CArchive( newone, CArchive::store ); m_ImageList.Write( test ); delete test; } else { AfxMessageBox("Trouble creating image archive"); } delete newone; } void CSecuresockDlg::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) { CString temp; temp.Format("pushed key:%i", nChar); AfxMessageBox(temp); CDialog::OnChar(nChar, nRepCnt, nFlags); } void CSecuresockDlg::SaveMyIcon(int ICONID) { // save favorite icon choice to userprop2.ids ofstream optionsFile2 ( "userprop2.ids", ios::out ); if (ofstream) { optionsFile2 << setw(7) << ICONID << '\n'; } } int CSecuresockDlg::GetIconIDFromIndex(int nindex) { // this is my default icon, a "normal user" icon int iret = IDI_ICON31; // get reference to app (for convenience in expression below in loop) CSecuresockApp *ref_app; ref_app = (CSecuresockApp *)AfxGetApp(); // loop thru the applications "imagevector" class, this is one of my own classes (in securesockDlg.h) // I use it to track the index in the cimagelist to the actual dialog ID // note that altho the imagelist (used by the treecontrol and elsewhere) tracks much other // info once you've added an image it doesn't really track the image's DIALOG_ID (e.g. the constants // from resource.h) -- // which is at times useful to get. hence my self-created imagevector class which relates these // two together (the index in the m_ImageList to the actual dialogs control ID from resource.h). // iterate thru the imagevector list for (int n=0; n < ref_app->m_imagevector.size(); n++) { // when we find the index item, get it's DIALOG_ID if (ref_app->m_imagevector[n].nindex == nindex) { iret = ref_app->m_imagevector[n].ICONIDD; break; } } return (iret); } int CSecuresockDlg::GetIndexFromIconID(int nicon) { // this is my default icon, a "normal user" icon int iret = -1; // get reference to app (for convenience in expression below in loop) CSecuresockApp *ref_app; ref_app = (CSecuresockApp *)AfxGetApp(); // loop thru the applications "imagevector" class, this is one of my own classes (in securesockDlg.h) // I use it to track the index in the cimagelist to the actual dialog ID // note that altho the imagelist (used by the treecontrol and elsewhere) tracks much other // info once you've added an image it doesn't really track the image's DIALOG_ID (e.g. the constants // from resource.h) -- // which is at times useful to get. hence my self-created imagevector class which relates these // two together (the index in the m_ImageList to the actual dialogs control ID from resource.h). // iterate thru the imagevector list for (int n=0; n < ref_app->m_imagevector.size(); n++) { // when we find the index item, get it's DIALOG_ID if (ref_app->m_imagevector[n].ICONIDD == nicon) { iret = ref_app->m_imagevector[n].nindex; break; } } return (iret); } void CSecuresockDlg::PostNcDestroy() { // this is the last destruction point but class vars may not be there at this point so // don't save tree structure here, but save it on destroy window method below stop_threads(); Sleep(120); CDialog::PostNcDestroy(); //delete this; //PostQuitMessage(0); } // TraverseTree does various things, by traversing thru the whole tree control for all items // in one case, to set flashing on or off - used with timer // this is like GetTreeItemByCriteria somewhat but it doesn't just return the first match but // rather traverses the whole tree and processes each tree item with the conditions in check_type // and val (based on a call to CheckTreeItem). void CSecuresockDlg::TraverseTree( int check_type, int val, bool bIgnoreGroups ) { HTREEITEM lastroot; HTREEITEM mynext, prevchild; CString mystring; //vector <TreeSaver> ts; //HTREEITEM firstchild; int last_id = 1; int last_contact = 101; int cur_root_id; bool firstone; int image, sel_image; bool expanded; HTREEITEM myroot = m_TreeCtrl.GetRootItem( ); lastroot = myroot; if (myroot == NULL) { } else { mystring = gettreetext(m_TreeCtrl, myroot); //AfxMessageBox( mystring.GetBuffer(10) ); lastroot = myroot; cur_root_id = last_id; gettreeiconindexes( m_TreeCtrl, myroot, image, sel_image, expanded ); if (! bIgnoreGroups ) CheckTreeItem( m_TreeCtrl, myroot, check_type, val); bool veryfirst = true; //ASSERT(0); while (1) { firstone = 1; while (1) { if (firstone) { mynext = m_TreeCtrl.GetNextItem( lastroot, TVGN_CHILD ); if (mynext == NULL) break; mystring = gettreetext(m_TreeCtrl, mynext); //AfxMessageBox( mystring.GetBuffer(10) ); gettreeiconindexes( m_TreeCtrl, mynext, image, sel_image, expanded ); CheckTreeItem( m_TreeCtrl, mynext, check_type, val); prevchild = mynext; } else { mynext = m_TreeCtrl.GetNextItem( prevchild, TVGN_NEXT ); if (mynext == NULL) break; mystring = gettreetext(m_TreeCtrl, mynext); //AfxMessageBox( mystring.GetBuffer(10) ); gettreeiconindexes( m_TreeCtrl, mynext, image, sel_image, expanded ); CheckTreeItem( m_TreeCtrl, mynext, check_type, val); prevchild = mynext; } firstone = 0; } lastroot = m_TreeCtrl.GetNextItem( lastroot, TVGN_NEXT ); if (lastroot == NULL) break; mystring = gettreetext(m_TreeCtrl, lastroot); cur_root_id = last_id; //AfxMessageBox( mystring.GetBuffer(10) ); gettreeiconindexes( m_TreeCtrl, lastroot, image, sel_image, expanded ); //SaveOne(ts, lastroot, mystring.GetBuffer(10), last_id++, 0, 0, image, sel_image, expanded); if (! bIgnoreGroups ) CheckTreeItem( m_TreeCtrl, lastroot, check_type, val); } } //ASSERT(0); } // traverse a tree to find something, according to a type of checking and a value, return // the related HTREEITEM if one is found HTREEITEM CSecuresockDlg::GetTreeItemByCriteria(int check_type, int val) { HTREEITEM lastroot; HTREEITEM mynext, prevchild; CString mystring; //vector <TreeSaver> ts; //HTREEITEM firstchild; int last_id = 1; int last_contact = 101; int cur_root_id; bool firstone; //int image, sel_image; //bool expanded; HTREEITEM myroot = m_TreeCtrl.GetRootItem( ); lastroot = myroot; if (myroot == NULL) { } else { //mystring = gettreetext(m_TreeCtrl, myroot); if ( CheckTreeItem( m_TreeCtrl, myroot, check_type, val) ) return myroot; //AfxMessageBox( mystring.GetBuffer(10) ); lastroot = myroot; cur_root_id = last_id; //gettreeiconindexes( m_TreeCtrl, myroot, image, sel_image, expanded ); bool veryfirst = true; //ASSERT(0); while (1) { firstone = 1; while (1) { if (firstone) { mynext = m_TreeCtrl.GetNextItem( lastroot, TVGN_CHILD ); if (mynext == NULL) break; if ( CheckTreeItem( m_TreeCtrl, mynext, check_type, val) ) return mynext; //mystring = gettreetext(m_TreeCtrl, mynext); //AfxMessageBox( mystring.GetBuffer(10) ); //gettreeiconindexes( m_TreeCtrl, mynext, image, sel_image, expanded ); prevchild = mynext; } else { mynext = m_TreeCtrl.GetNextItem( prevchild, TVGN_NEXT ); if (mynext == NULL) break; if ( CheckTreeItem( m_TreeCtrl, mynext, check_type, val) ) return mynext; //mystring = gettreetext(m_TreeCtrl, mynext); //AfxMessageBox( mystring.GetBuffer(10) ); //gettreeiconindexes( m_TreeCtrl, mynext, image, sel_image, expanded ); prevchild = mynext; } firstone = 0; } lastroot = m_TreeCtrl.GetNextItem( lastroot, TVGN_NEXT ); if (lastroot == NULL) break; if ( CheckTreeItem( m_TreeCtrl, lastroot, check_type, val) ) return lastroot; //mystring = gettreetext(m_TreeCtrl, lastroot); cur_root_id = last_id; //AfxMessageBox( mystring.GetBuffer(10) ); //gettreeiconindexes( m_TreeCtrl, lastroot, image, sel_image, expanded ); //SaveOne(ts, lastroot, mystring.GetBuffer(10), last_id++, 0, 0, image, sel_image, expanded); } } //ASSERT(0); return (HTREEITEM)0; } // traverse a tree to find something, according to a type of checking and a value, return // the related HTREEITEM if one is found HTREEITEM CSecuresockDlg::GetGroupLabels(bool bGroup) { HTREEITEM lastroot; HTREEITEM mynext, prevchild; CString mystring; //vector <TreeSaver> ts; //vector<TreeGroupInfo> tgiVector; tgiVector.clear(); //tgiVector //HTREEITEM firstchild; int last_id = 1; int last_contact = 101; int cur_root_id; bool firstone; //int image, sel_image; //bool expanded; char buffer[256]; HTREEITEM myroot = m_TreeCtrl.GetRootItem( ); lastroot = myroot; if (myroot == NULL) { } else { if (! m_TreeCtrl.GetLabelText(myroot, buffer, 255) ) { AfxMessageBox("trouble getting a group label possible error in getlabeltext function in mytreectrl"); } else { if ( NotSystemGroup(myroot) ) tgiVector.push_back( TreeGroupInfo( buffer, myroot ) ); } //AfxMessageBox( mystring.GetBuffer(10) ); lastroot = myroot; cur_root_id = last_id; //gettreeiconindexes( m_TreeCtrl, myroot, image, sel_image, expanded ); bool veryfirst = true; while (1) { firstone = 1; while (1) { if (firstone) { mynext = m_TreeCtrl.GetNextItem( lastroot, TVGN_CHILD ); if (mynext == NULL) break; if (! bGroup) { if (! m_TreeCtrl.GetLabelText(mynext, buffer, 255) ) { AfxMessageBox("trouble getting a group label possible error in getlabeltext function in mytreectrl"); } else { tgiVector.push_back( TreeGroupInfo( buffer, mynext ) ); } } //mystring = gettreetext(m_TreeCtrl, mynext); //AfxMessageBox( mystring.GetBuffer(10) ); //gettreeiconindexes( m_TreeCtrl, mynext, image, sel_image, expanded ); prevchild = mynext; } else { mynext = m_TreeCtrl.GetNextItem( prevchild, TVGN_NEXT ); if (mynext == NULL) break; if (! bGroup ) { if (! m_TreeCtrl.GetLabelText(mynext, buffer, 255) ) { AfxMessageBox("trouble getting a group label possible error in getlabeltext function in mytreectrl"); } else { tgiVector.push_back( TreeGroupInfo( buffer, mynext ) ); } } //mystring = gettreetext(m_TreeCtrl, mynext); //AfxMessageBox( mystring.GetBuffer(10) ); //gettreeiconindexes( m_TreeCtrl, mynext, image, sel_image, expanded ); prevchild = mynext; } firstone = 0; } lastroot = m_TreeCtrl.GetNextItem( lastroot, TVGN_NEXT ); if (lastroot == NULL) break; if (! m_TreeCtrl.GetLabelText(lastroot, buffer, 255) ) { AfxMessageBox("trouble getting a group label possible error in getlabeltext function in mytreectrl"); } else { if ( NotSystemGroup(lastroot) ) tgiVector.push_back( TreeGroupInfo( buffer, lastroot ) ); } //mystring = gettreetext(m_TreeCtrl, lastroot); cur_root_id = last_id; //AfxMessageBox( mystring.GetBuffer(10) ); //gettreeiconindexes( m_TreeCtrl, lastroot, image, sel_image, expanded ); //SaveOne(ts, lastroot, mystring.GetBuffer(10), last_id++, 0, 0, image, sel_image, expanded); } } //ASSERT(0); return (HTREEITEM)0; } bool CSecuresockDlg::NotSystemGroup(HTREEITEM thishitem) { ChatItemInfo *citemp; bool bRet; citemp = (ChatItemInfo *)(m_TreeCtrl.GetItemData( thishitem )); bRet = (citemp->ntype != SYSTEM_GROUP && citemp->ntype != PENDING_CONTACTS_GROUP ); return bRet; } // see if this tree item or it's related info match a certain type of lookup and value bool CSecuresockDlg::CheckTreeItem(CTreeCtrl &reftree, HTREEITEM &hitem, int check_type, int val) { bool bRet = false; ChatItemInfo *citemp; int x; // check for a specific chat_id if (check_type == CSecuresockDlg::CHAT_ID_LOOKUP) { citemp = (ChatItemInfo *)(m_TreeCtrl.GetItemData( hitem )); if ( val == citemp->chat_id ) { bRet = true; } } // check for a specific type, like system lookup else if (check_type == CSecuresockDlg::TYPE_LOOKUP) { citemp = (ChatItemInfo *)(m_TreeCtrl.GetItemData( hitem )); if ( val == citemp->ntype ) { bRet = true; } } else if (check_type == CSecuresockDlg::ONLINE_STATUS_MSG_LOOKUP) { citemp = (ChatItemInfo *)(m_TreeCtrl.GetItemData( hitem )); if ( citemp->ntype == CHAT_CONTACT ) { online_chk_vector.push_back( TreeStatusHelper( hitem, citemp->chat_id) ); TRACE("hit again\n"); TRACE("%s", citemp->msg.GetBuffer(0) ); bRet = true; } } // check for any pending messages for this chat_id, note this is somewhat of an odd // call since it actually causes the flashing also, so this is more CheckTreeItemandFlash // when called in this case (val is also ignored, since the chat_id is checked against a // message list vector of unprocessed messages which is a part of pSockApp). // split this into two cases, one gets whether or not there are pending messages and if so // sets a citemp value (bPendingMsgs) to true. // BLINK_UPDATE_CALL handles the actual update and executes every half second else if (check_type == CSecuresockDlg::PENDING_MSG_LOOKUP) { citemp = (ChatItemInfo *)(m_TreeCtrl.GetItemData( hitem )); if ( citemp->ntype != CHAT_CONTACT ) return false; int new_icon; bRet = pSockApp->bPendingMsgsByChatID( citemp->chat_id, &new_icon ); if (bRet) { if (new_icon != citemp->icon_id && new_icon != 0) { citemp->icon_id = new_icon; } } TRACE("checking msg for %lu\n", citemp->chat_id ); citemp->bPendingMsgs = bRet; } else if (check_type == BLINK_UPDATE_CALL) { citemp = (ChatItemInfo *)(m_TreeCtrl.GetItemData( hitem )); bRet = citemp->bPendingMsgs; if ( citemp->ntype != CHAT_CONTACT ) return false; if (!bRet) { TRACE("no match found\n"); // if message was handled when showing invisible icon, need to set back to real icon if (m_TreeCtrl.GetImageIndex( hitem ) == GetIndexFromIconID(IDI_ICON115) ) { TRACE("fixing lost in down state bug\n"); x = GetIndexFromIconID( citemp->icon_id ); m_TreeCtrl.SetImagesByIndex( hitem, x); // citemp->icon_id } } else { if (bUpTimer) { // icon115 aka "the empty icon" x = GetIndexFromIconID(IDI_ICON115); m_TreeCtrl.SetImagesByIndex( hitem, x); //m_TreeCtrl.SetItemOverlayIndex( hitem, 0); } else { x = GetIndexFromIconID( citemp->icon_id ); // we can't really put up a messagebox on this bug so set everything to kyle and they will // know there is a bug if (x == - 1) { TRACE("BUG: this icon_id not found in index list\n"); x = 2; } m_TreeCtrl.SetImagesByIndex( hitem, x); // citemp->icon_id } } } return bRet; } // saves tree structure to treefile.ids via standard iostream stuff void CSecuresockDlg::SaveTreeFont(void) { CString temp; temp.Format("tf_u%lu_font.dra", pSockApp->my_controls.chat_id); ofstream myOutFile2( temp.GetBuffer(0), ios::out ); //myOutFile2 << this->tree_lf; if (myOutFile2) { stream_stuff::write_long2( myOutFile2, (DWORD)(m_TreeCtrl.crForeColor)); CString temp; temp.Format("%lu", (DWORD)(m_TreeCtrl.crForeColor) ); //AfxMessageBox( temp ); stream_stuff::write_signed_long( myOutFile2, this->tree_lf.lfHeight); stream_stuff::write_signed_long( myOutFile2, this->tree_lf.lfWidth); stream_stuff::write_signed_long( myOutFile2, this->tree_lf.lfEscapement); stream_stuff::write_signed_long( myOutFile2, this->tree_lf.lfOrientation); stream_stuff::write_signed_long( myOutFile2, this->tree_lf.lfWeight); stream_stuff::write_signed_char( myOutFile2, this->tree_lf.lfItalic); stream_stuff::write_signed_char( myOutFile2, this->tree_lf.lfUnderline); stream_stuff::write_signed_char( myOutFile2, this->tree_lf.lfStrikeOut); stream_stuff::write_signed_char( myOutFile2, this->tree_lf.lfCharSet); stream_stuff::write_signed_char( myOutFile2, this->tree_lf.lfOutPrecision); stream_stuff::write_signed_char( myOutFile2, this->tree_lf.lfClipPrecision); stream_stuff::write_signed_char( myOutFile2, this->tree_lf.lfQuality); stream_stuff::write_signed_char( myOutFile2, this->tree_lf.lfPitchAndFamily); } else { AfxMessageBox("Trouble opening tree font save file"); } // one longer for paranoia and to avoid bad assignment to CString // put the lfFaceName into a CString and use the normal writeCString helper function char buffer[LF_FACESIZE+1]; buffer[LF_FACESIZE] = (char)0; ::lstrcpyn(buffer, this->tree_lf.lfFaceName, LF_FACESIZE); temp = buffer; stream_stuff::writeCString( myOutFile2, temp ); myOutFile2.close(); } // load in tree font (if they've set it to other than default) - for current user bool CSecuresockDlg::GetTreeFontFromFile(void) { CString temp; temp.Format("tf_u%lu_font.dra", pSockApp->my_controls.chat_id); CFile *myfile = new CFile(); COLORREF crValue; crValue = RGB(0,0,0); try { myfile->Open( temp.GetBuffer(0), CFile::modeRead ); } catch (...) { } // avoid runtime errors most likely one is just file doesn't exist which will cause // a runtime if we don't catch it here if (myfile->m_hFile != (UINT)CFile::hFileNull) { //long ltemp; bool bokay = false; while (1) { unsigned long ultemp; stream_stuff::read_long2(myfile, &ultemp); crValue = (COLORREF)ultemp; if ( ! stream_stuff::read_signed_long(myfile, &(tree_lf.lfHeight) ) ) { break; } if ( ! stream_stuff::read_signed_long(myfile, &(tree_lf.lfWidth) ) ) { break; } if ( ! stream_stuff::read_signed_long(myfile, &(tree_lf.lfEscapement) ) ) { break; } if ( ! stream_stuff::read_signed_long(myfile, &(tree_lf.lfOrientation) ) ) { break; } if ( ! stream_stuff::read_signed_long(myfile, &(tree_lf.lfWeight) ) ) { break; } if ( ! stream_stuff::read_char(myfile, &(tree_lf.lfItalic) ) ) { break; } if ( ! stream_stuff::read_char(myfile, &(tree_lf.lfUnderline) ) ) { break; } if ( ! stream_stuff::read_char(myfile, &(tree_lf.lfStrikeOut) ) ) { break; } if ( ! stream_stuff::read_char(myfile, &(tree_lf.lfCharSet) ) ) { break; } if ( ! stream_stuff::read_char(myfile, &(tree_lf.lfOutPrecision) ) ) { break; } if ( ! stream_stuff::read_char(myfile, &(tree_lf.lfClipPrecision) ) ) { break; } if ( ! stream_stuff::read_char(myfile, &(tree_lf.lfQuality) ) ) { break; } if ( ! stream_stuff::read_char(myfile, &(tree_lf.lfPitchAndFamily) ) ) { break; } bokay = true; break; } if (bokay) { char buffer[LF_FACESIZE+1]; char size_buffer[6]; int num_read = myfile->Read(size_buffer, 4); size_buffer[num_read] = 0; int itextlen = atoi(size_buffer); if (itextlen > LF_FACESIZE) { itextlen = LF_FACESIZE; } // skip comma myfile->Read(size_buffer, 1); num_read = myfile->Read(buffer, itextlen); buffer[num_read] = (char)0; ::lstrcpy(this->tree_lf.lfFaceName, buffer); } myfile->Close(); } else { ::ZeroMemory( &tree_lf, sizeof(tree_lf) ); tree_lf.lfHeight = -11; tree_lf.lfWeight = 700; tree_lf.lfOutPrecision = 3; tree_lf.lfClipPrecision = 2; tree_lf.lfQuality = 1; tree_lf.lfPitchAndFamily = 34; ::lstrcpy(tree_lf.lfFaceName, "Arial"); crValue = RGB(0,0,0); } delete myfile; CHOOSEFONT chf; HDC hDC; hDC = ::GetDC (this->m_hWnd); chf.hDC = CreateCompatibleDC (hDC); ::ReleaseDC (this->m_hWnd, hDC); chf.lStructSize = sizeof (CHOOSEFONT); chf.hwndOwner = this->m_hWnd; chf.lpLogFont = &tree_lf; chf.Flags = CF_SCREENFONTS | CF_EFFECTS | CF_INITTOLOGFONTSTRUCT ; chf.rgbColors = RGB (0, 0, 0); chf.lCustData = 0; chf.hInstance = AfxGetInstanceHandle(); chf.lpszStyle = (LPTSTR)NULL; chf.nFontType = SCREEN_FONTTYPE; chf.nSizeMin = 0; chf.nSizeMax = 0; if (m_ptreefont) delete m_ptreefont; m_ptreefont = new CFont(); m_ptreefont->CreateFontIndirect(&tree_lf); bTreeFontChanged = true; m_TreeCtrl.SetFont(m_ptreefont); m_TreeCtrl.crForeColor = crValue; return true; /* LONG lfHeight; LONG lfWidth; LONG lfEscapement; LONG lfOrientation; LONG lfWeight; BYTE lfItalic; BYTE lfUnderline; BYTE lfStrikeOut; BYTE lfCharSet; BYTE lfOutPrecision; BYTE lfClipPrecision; BYTE lfQuality; BYTE lfPitchAndFamily; TCHAR lfFaceName[LF_FACESIZE]; /* stream_stuff::write_signed_char( myOutFile2, this->tree_lf.lfItalic); stream_stuff::write_signed_char( myOutFile2, this->tree_lf.lfUnderline); stream_stuff::write_signed_char( myOutFile2, this->tree_lf.lfStrikeOut); stream_stuff::write_signed_char( myOutFile2, this->tree_lf.lfCharSet); stream_stuff::write_signed_char( myOutFile2, this->tree_lf.lfOutPrecision); stream_stuff::write_signed_char( myOutFile2, this->tree_lf.lfClipPrecision); stream_stuff::write_signed_char( myOutFile2, this->tree_lf.lfQuality); stream_stuff::write_signed_char( myOutFile2, this->tree_lf.lfPitchAndFamily); // one longer for paranoia and to avoid bad assignment to CString // put the lfFaceName into a CString and use the normal writeCString helper function char buffer[LF_FACESIZE+1]; buffer[LF_FACESIZE] = (char)0; ::lstrcpyn(buffer, this->tree_lf.lfFaceName, LF_FACESIZE); temp = buffer; stream_stuff::writeCString( myOutFile2, temp ); */ } // saves tree structure to treefile.ids via standard iostream stuff void CSecuresockDlg::SaveTree() { HTREEITEM lastroot; HTREEITEM mynext, prevchild; CString mystring; vector <TreeSaver> ts; //HTREEITEM firstchild; int last_id = 1; int last_contact = 101; int cur_root_id; bool firstone; int image, sel_image; bool expanded; //unsigned long chat_id; ChatItemInfo *tempci; //tempci->msg = ""; //tempci->ntype = UNKNOWN; //tempci->create_time = ""; HTREEITEM myroot = m_TreeCtrl.GetRootItem( ); lastroot = myroot; if (myroot == NULL) { } else { mystring = gettreetext(m_TreeCtrl, myroot); //AfxMessageBox( mystring.GetBuffer(10) ); lastroot = myroot; cur_root_id = last_id; gettreeiconindexes( m_TreeCtrl, myroot, image, sel_image, expanded ); //tempci->chat_id = m_TreeCtrl.GetItemData( myroot); tempci = (ChatItemInfo *)(m_TreeCtrl.GetItemData( myroot)); if (! tempci ) ASSERT(0); //SaveOne(ts, lastroot, mystring.GetBuffer(10), last_id++, 0, chat_id, image, sel_image, expanded); // save info to a vector via SaveOne, then later use this vector to write to the file SaveOne(ts, lastroot, mystring.GetBuffer(10), last_id++, 0, tempci, image, sel_image, expanded); //ASSERT(0); while (1) { firstone = 1; while (1) { if (firstone) { mynext = m_TreeCtrl.GetNextItem( lastroot, TVGN_CHILD ); if (mynext == NULL) break; mystring = gettreetext(m_TreeCtrl, mynext); //AfxMessageBox( mystring.GetBuffer(10) ); gettreeiconindexes( m_TreeCtrl, mynext, image, sel_image, expanded ); //tempci->chat_id = m_TreeCtrl.GetItemData( mynext); tempci = (ChatItemInfo *)(m_TreeCtrl.GetItemData( mynext)); //SaveOne(ts, mynext, mystring.GetBuffer(10), last_id++, cur_root_id, chat_id, image, sel_image); SaveOne(ts, mynext, mystring.GetBuffer(10), last_id++, cur_root_id, tempci, image, sel_image); prevchild = mynext; } else { mynext = m_TreeCtrl.GetNextItem( prevchild, TVGN_NEXT ); if (mynext == NULL) break; mystring = gettreetext(m_TreeCtrl, mynext); //AfxMessageBox( mystring.GetBuffer(10) ); gettreeiconindexes( m_TreeCtrl, mynext, image, sel_image, expanded ); //tempci->chat_id = m_TreeCtrl.GetItemData( mynext); tempci = (ChatItemInfo *)(m_TreeCtrl.GetItemData( mynext)); //SaveOne(ts, mynext, mystring.GetBuffer(10), last_id++, cur_root_id, chat_id, image, sel_image); SaveOne(ts, mynext, mystring.GetBuffer(10), last_id++, cur_root_id, tempci, image, sel_image); prevchild = mynext; } firstone = 0; } lastroot = m_TreeCtrl.GetNextItem( lastroot, TVGN_NEXT ); if (lastroot == NULL) break; mystring = gettreetext(m_TreeCtrl, lastroot); cur_root_id = last_id; //AfxMessageBox( mystring.GetBuffer(10) ); gettreeiconindexes( m_TreeCtrl, lastroot, image, sel_image, expanded ); //tempci->chat_id = m_TreeCtrl.GetItemData( lastroot); tempci = (ChatItemInfo *)(m_TreeCtrl.GetItemData( lastroot)); //SaveOne(ts, lastroot, mystring.GetBuffer(10), last_id++, 0, chat_id, image, sel_image, expanded); SaveOne(ts, lastroot, mystring.GetBuffer(10), last_id++, 0, tempci, image, sel_image, expanded); } } //ASSERT(0); //CString curdir; //::GetCurrentDirectory(MAX_PATH, curdir.GetBuffer(MAX_PATH)); //curdir.ReleaseBuffer(); //AfxMessageBox( curdir.GetBuffer(MAX_PATH)); CString temp; temp.Format("tf_u%lu.dra", pSockApp->my_controls.chat_id); ofstream myOutFile2( temp.GetBuffer(0), ios::out ); myOutFile2 << "y"; char buffer[256]; DWORD id, parent_id, contact_id, iimage, isel_image, is_expanded; int textlen; int i; for (i=0; i<ts.size(); i++) { id = ts[i].id; parent_id = ts[i].parent_id; contact_id = ts[i].contact_id; iimage = ts[i].iimage; isel_image = ts[i].isel_image; is_expanded = ts[i].is_expanded; stream_stuff::write_long2( myOutFile2, (unsigned long)(ts[i].id)); stream_stuff::write_long2( myOutFile2, (unsigned long)(ts[i].parent_id)); stream_stuff::write_long2( myOutFile2, (unsigned long)(ts[i].contact_id)); stream_stuff::write_long2( myOutFile2, (unsigned long)(ts[i].iimage)); stream_stuff::write_long2( myOutFile2, (unsigned long)(ts[i].isel_image)); stream_stuff::write_long2( myOutFile2, (unsigned long)(ts[i].is_expanded)); stream_stuff::write_long2( myOutFile2, (unsigned long)(ts[i].ntype) ) ; stream_stuff::write_long2( myOutFile2, (unsigned long)(ts[i].icon_id) ); textlen = strlen(ts[i].text); myOutFile2 << setw(4) << strlen(ts[i].text) ; myOutFile2 << ","; myOutFile2 << ts[i].text ; strcpy( buffer, ts[i].text); stream_stuff::writeCString( myOutFile2, ts[i].msg ); /* char *ctemp; textlen = strlen(ts[i].msg.GetBuffer(0) ); myOutFile2 << setw(4) << textlen ; myOutFile2 << ","; ctemp = ts[i].msg.GetBuffer(0); myOutFile2 << ctemp; strcpy( buffer, ts[i].msg.GetBuffer(0)); */ stream_stuff::writeCString( myOutFile2, ts[i].create_time); /* textlen = strlen(ts[i].create_time.GetBuffer(0) ); myOutFile2 << setw(4) << textlen ; myOutFile2 << ","; ctemp = ts[i].create_time.GetBuffer(0); myOutFile2 << ctemp ; strcpy( buffer, ts[i].create_time.GetBuffer(0) ); */ stream_stuff::writeCString( myOutFile2, ts[i].time_received); stream_stuff::writeCString( myOutFile2, ts[i].nickname); /* enum TypeInfo { UNKNOWN = 0, CHAT_CONTACT, GROUP, SYSTEM_MSG }; TypeInfo ntype; CString msg; CString create_time; */ myOutFile2 << '\n'; } //m_TreeCtrl.Detach(); //if (ts.size() == 0) AfxMessageBox("No elements"); } // reads in tree structure from file treefile.ids via standard iostream stuff void CSecuresockDlg::BuildTreeFromFile(CTreeCtrl &piTree, CFile *myfile, bool newformat) { CString outstring; char buffer[256]; char msg[256]; char create_time[256]; char time_received[256]; char nickname[256]; //ASSERT(0); /* ifs.seekg(0, ios::end); long pos = ifs.tellg(); ifs.seekg(0); */ unsigned long length = 0; int num_read; bool bNewFormat; ChatItemInfo *tempci; ChatItemInfo *newci; if (myfile) { length = myfile->GetLength(); myfile->Read(buffer, 1); bNewFormat = ! (buffer[0] == 'x'); } if (! myfile || length < 10) { HTREEITEM system = piTree.InsertItem( "System Notifications", 29, 29, TVI_ROOT, TVI_LAST); CString string_time = GetTimeString(); newci = new ChatItemInfo(0L, SYSTEM_GROUP, CString("Basic System Notifications Group"), string_time ); piTree.SetItemData( system, (DWORD)newci ); add_ptr_to_garbage(newci, "ChatItemInfo"); newci = NULL; newci = new ChatItemInfo(0L, GROUP, CString("Contacts Group"), string_time ); HTREEITEM work = piTree.InsertItem( "Work Contacts", 27, 27, TVI_ROOT, TVI_LAST); piTree.SetItemData( work, (DWORD)newci ); add_ptr_to_garbage(newci, "ChatItemInfo"); newci = NULL; newci = new ChatItemInfo(0L, GROUP, CString("Contacts Group"), string_time ); HTREEITEM personal = piTree.InsertItem( "Personal Contacts", 28, 28, TVI_ROOT, TVI_LAST); piTree.SetItemData( personal, (DWORD)newci ); add_ptr_to_garbage(newci, "ChatItemInfo"); } else { unsigned long id, contact_id, parent_id, iimage, isel_image; unsigned long ntype; int itextlen; char text[256]; unsigned long long_bool; bool is_expanded; char buffer[200]; unsigned long icon_id; HTREEITEM last_root; stream_stuff::eof = false; while ( ! stream_stuff::eof ) { id = 0; stream_stuff::warning = false; stream_stuff::read_long2(myfile, &id); stream_stuff::warning = true; // eof is failing on last record (at least at that point) so this is a kludge but effective for now if (stream_stuff::eof ) { break; } stream_stuff::read_long2(myfile, &parent_id); if (stream_stuff::eof ) { break; } stream_stuff::read_long2(myfile, &contact_id); if (stream_stuff::eof ) { break; } stream_stuff::read_long2(myfile, &iimage); if (stream_stuff::eof ) { break; } stream_stuff::read_long2(myfile, &isel_image); if (stream_stuff::eof ) { break; } stream_stuff::read_long2(myfile, &long_bool); if (stream_stuff::eof ) { break; } is_expanded = !(long_bool == 0); stream_stuff::read_long2(myfile, &ntype); if (stream_stuff::eof ) { break; } stream_stuff::read_long2(myfile, &icon_id); if (stream_stuff::eof ) { break; } num_read = myfile->Read(buffer, 4); buffer[num_read] = 0; itextlen = atoi(buffer); myfile->Read(buffer, 1); num_read = myfile->Read(text, itextlen); text[num_read] = (char)0; num_read = myfile->Read(buffer, 4); buffer[num_read] = 0; itextlen = atoi(buffer); myfile->Read(buffer, 1); num_read = myfile->Read(msg, itextlen); msg[num_read] = (char)0; num_read = myfile->Read(buffer, 4); buffer[num_read] = 0; itextlen = atoi(buffer); myfile->Read(buffer, 1); num_read = myfile->Read(create_time, itextlen); create_time[num_read] = (char)0; //stream_stuff:: num_read = myfile->Read(buffer, 4); buffer[num_read] = 0; itextlen = atoi(buffer); myfile->Read(buffer, 1); num_read = myfile->Read(time_received, itextlen); time_received[num_read] = (char)0; num_read = myfile->Read(buffer, 4); buffer[num_read] = 0; itextlen = atoi(buffer); myfile->Read(buffer, 1); num_read = myfile->Read(nickname, itextlen); nickname[num_read] = (char)0; // read CRLF now myfile->Read(buffer, 2); // if parent item if (parent_id == 0) { last_root = piTree.InsertItem( text, iimage, isel_image, TVI_ROOT, TVI_LAST); if (bNewFormat ) { tempci = NULL; ChatItemInfo *tempci = new ChatItemInfo; add_ptr_to_garbage(tempci, "ChatItemInfo"); tempci->chat_id = contact_id; tempci->msg = msg; tempci->create_time = create_time; tempci->time_received = time_received; tempci->nickname = nickname; tempci->ntype = ChatItemInfo::translate(ntype); tempci->icon_id = (int)icon_id; piTree.SetItemData( last_root, (DWORD)tempci ); } else { piTree.SetItemData( last_root, contact_id ); } if (last_root && is_expanded) { //ASSERT(0); settreeexpanded( piTree, last_root, is_expanded ); } } else { int iconindex; if (icon_id != 0) { iconindex = GetIndexFromIconID( (int)icon_id ); if (iconindex != -1 ) { iimage = iconindex; isel_image = iconindex; } } HTREEITEM newone = piTree.InsertItem( text, iimage, isel_image, last_root); if (! bNewFormat) { piTree.SetItemData( newone, contact_id ); } else { tempci = NULL; ChatItemInfo *tempci = new ChatItemInfo; add_ptr_to_garbage(tempci, "ChatItemInfo"); tempci->chat_id = contact_id; tempci->msg = msg; tempci->create_time = create_time; tempci->ntype = ChatItemInfo::translate(ntype); tempci->time_received = time_received; tempci->nickname = nickname; tempci->icon_id = (int)icon_id; piTree.SetItemData( newone, (DWORD)tempci ); } } } } } BOOL CSecuresockDlg::DestroyWindow() { //MessageBox("called"); if (fully_loaded) SaveTree(); if (bTreeFontChanged) { SaveTreeFont(); } // close the taskbar icon on main dialog shutdown NOTIFYICONDATA nid; nid.cbSize = sizeof(nid); nid.hWnd = this->m_hWnd; nid.uID = 1; nid.uFlags = 0; Shell_NotifyIcon(NIM_DELETE, &nid); KillTimer(1); KillTimer(2); KillTimer(3); //KillTimer(4); // turn off multimedia timer also used to make sure blinking isn't weird (normal timers aren't reliable // and act weird) note this causes a performance hit but I think if we assume systems with modern processors // and ram this shouldn't be a big issue. if (m_n_mmtimer_id != 0) { timeKillEvent(m_n_mmtimer_id); timeEndPeriod(500); } return CDialog::DestroyWindow(); } void CSecuresockDlg::OnMypersonalbutton() { DWORD dp = ::GetMessagePos(); CPoint pt ((int) LOWORD( dp ), (int) HIWORD (dp) ); //CTreeCtrl piTree; //piTree.Attach( GetDlgItem(IDC_TREE1)->m_hWnd); //m_TreeCtrl.ScreenToClient (&pt); UINT flags = NULL; //char buffer[20]; CMenu menu; menu.LoadMenu(IDR_MENU1); CMenu *x; x = menu.GetSubMenu(2); //x->AppendMenu(MF_STRING, WM_USER + 301, "appended item"); CMenu users_menu; users_menu.CreatePopupMenu(); int i; int ncnt = 0; for (i=0;i< pSockApp->users_array.size(); i++) { users_menu.AppendMenu(MF_STRING, WM_USER + 300 + ncnt++, pSockApp->users_array[i].nickname.GetBuffer(0) ); if (pSockApp->users_array[i].chat_id == pSockApp->my_controls.chat_id) { users_menu.CheckMenuItem(WM_USER + 300 + ncnt - 1, MF_CHECKED); } } x->InsertMenu(3, MF_BYPOSITION | MF_POPUP, (unsigned int)(users_menu.m_hMenu), "Change User"); CRect rect; GetWindowRect(rect); //CPoint y; //::GetCursorPos(&y); //ScreenToClient (&y); CPoint pt2 ((int) LOWORD( dp ), (int) HIWORD (dp) ); int ncmd = x->TrackPopupMenu( TPM_RETURNCMD | TPM_LEFTALIGN , pt2.x, pt2.y, AfxGetMainWnd(), rect ); if (ncmd >= WM_USER + 300 && ncmd <= WM_USER + 399 ) { SwitchUsers(ncmd - (WM_USER + 300) ); return; } if (ncmd == ID_MYPROPERTIES ) { //pSockApp->ShowMessageList(); CMyPropSheet testprop(IDS_MYPROPS, this, 0) ; testprop.m_psh.dwFlags |= PSH_NOAPPLYNOW ; CPersP1 p1; CPersP3 p3; CPers_P2 p2; CPersP4 p4; p1.m_psp.dwFlags &= (~PSH_HASHELP); p2.m_psp.dwFlags &= (~PSH_HASHELP); p3.m_psp.dwFlags &= (~PSH_HASHELP); p4.m_psp.dwFlags &= (~PSH_HASHELP); testprop.AddPage(&p1); testprop.AddPage(&p2); testprop.AddPage(&p3); testprop.AddPage(&p4); testprop.newtitle.Format("Change My Properties [Chat ID %lu]", pSockApp->my_controls.chat_id); int response = testprop.DoModal(); if (response == IDOK) { //MessageBox("saving"); CSecuresockApp *pSockApp; pSockApp = (CSecuresockApp *)AfxGetApp(); CString msg1; msg1 = "Saving Settings to Server"; CMiscStuff::WaitWindow( msg1, this ); pSockApp->SavePropsToFile(); // save properties to web pSockApp->my_controls.UpdateURLwithInfo(); //Sleep(1000); CMiscStuff::ClearWaitWindow(); } } if (ncmd == ID_CHECKLATENCY) { GetLatency() ; } if (ncmd == ID_CHANGE_ICON1) { IconChooser icd; icd.bGroupIcon = false; // the postncdestroy method in IconChooser will delete this memory allocated // here so this isn't a real memory leak char *newptr = new char[100]; strcpy(newptr, "Select Your Personal Chat Icon"); // set the caption for the chooser dialog, uses soft logic if not set then uses // a default value (this dialog is called from other places than registration) icd.title = newptr; // this isn't a memory leak the dialog itself will release the // memory via delete [] for this pointer icd.m_signup = 0; // registration level call (screen can be called from different places // in the program this flag helps to differentiate icd.m_me = 1; int myresult = icd.DoModal(); int ICONIDD; if (! pSockApp->m_canceled && icd.ICON_IDD != -1 && myresult == IDOK) { ICONIDD = icd.ICON_IDD; HICON hIcon; hIcon = ::LoadIcon (AfxGetResourceHandle(), MAKEINTRESOURCE(ICONIDD)); m_mypersonalbutton.SetIcon( hIcon ); CString temp; temp.Format("%i", ICONIDD); if (! pSockApp->my_controls.SetStringByTokenName("user_icon", temp)) AfxMessageBox("trouble setting user_icon in properties"); m_my_personal_icon_id = ICONIDD; pSockApp->SavePropsToFile(); } // save favorite icon choice to userprop2.ids //ofstream optionsFile2 ( "userprop2.ids", ios::out ); //optionsFile2 << setw(7) << ICONIDD << '\n'; // save this to a class variable also so we can keep track of the last personal icon // add a save function to the destructor } if (ncmd == ID_OPTION1_ADDNEWDEPT) { HTREEITEM newone; m_ilast_dept_insert_icon++; // alternate between three types of insert icons for departments (for now) if (m_ilast_dept_insert_icon > 28) m_ilast_dept_insert_icon = 26; newone = m_TreeCtrl.InsertItem( "New Group", m_ilast_dept_insert_icon, m_ilast_dept_insert_icon, TVI_ROOT, TVI_LAST); ChatItemInfo *citemp; citemp = new ChatItemInfo; citemp->chat_id = 0; citemp->ntype = GROUP; citemp->create_time = GetTimeString() ; citemp->msg = "Contact Group"; add_ptr_to_garbage(citemp, "ChatItemInfo"); m_TreeCtrl.SetItemData( newone, (DWORD)citemp ); //m_TreeCtrl.SetItemData( newone, 0 ); m_TreeCtrl.EditLabel(newone); } if (ncmd == ID_ADDUSER) { if (!SignupUser( false ) ) { AfxMessageBox("Adding New User Canceled"); } else { m_TreeCtrl.DeleteAllItems(); // if treeFile is NULL this is okay it recreates a generic tree //ifstream failure("impossible_name_234asdfaw34rfs"); BuildTreeFromFile(m_TreeCtrl, NULL, true); COLORREF cref = RGB( 255, 255, 255); CString temp; temp.Format("%lu", (unsigned long)cref); m_TreeCtrl.SetBkColor(cref) ; if (! pSockApp->my_controls.SetStringByTokenName("tree_back_color", temp)) { AfxMessageBox("trouble saving tree backcolor in properties"); } else { pSockApp->SavePropsToFile(); } } } if (ncmd == ID_TREEBKCOLOR) { /* CMySocket newconn("www.drakis.com"); CString response = newconn.GetFileAsString("/cgi-bin/check_in.pl?my_scno=101", "www.drakis.com"); MB( response ); return; */ //this is retarded but there is no getbackground color function calling set // gets it's value, here we set it to white then quickly set it back COLORREF old = m_TreeCtrl.GetBkColor(); CMyColorDialog x1(old, CC_RGBINIT ); x1.m_cc.lStructSize = sizeof( CHOOSECOLOR ); x1.m_cc.Flags = x1.m_cc.Flags | CC_FULLOPEN ; x1.SetWindowCaption("Select Tree Background Color"); if (x1.DoModal() == IDOK ) { COLORREF x2 = x1.GetColor(); m_TreeCtrl.SetBkColor(x2) ; CString temp; temp.Format("%lu", (unsigned long)x2); if (! pSockApp->my_controls.SetStringByTokenName("tree_back_color", temp)) { AfxMessageBox("trouble saving tree backcolor in properties"); } else { pSockApp->SavePropsToFile(); } } } } void CSecuresockDlg::OnShowWindow(BOOL bShow, UINT nStatus) { //char buffer[20]; //_itoa(nStatus, buffer, 10); //AfxMessageBox(buffer); CDialog::OnShowWindow(bShow, nStatus); // TODO: Add your message handler code here } BOOL CSecuresockDlg::OnHelpInfo(HELPINFO* pHelpInfo) { // TODO: Add your message handler code here and/or call default //AfxMessageBox("they hit f1"); return CDialog::OnHelpInfo(pHelpInfo); } BOOL CSecuresockDlg::OnCommand(WPARAM wParam, LPARAM lParam) { // TODO: Add your specialized code here and/or call the base class /*AfxMessageBox("on command called"); CString out; out.Format("%li:%li", wParam, lParam); AfxMessageBox(out); */ if (lParam == WM_TRAY_IDD) AfxMessageBox("c"); if (wParam == WM_TRAY_IDD) AfxMessageBox("d"); return CDialog::OnCommand(wParam, lParam); } BOOL CSecuresockDlg::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo) { // TODO: Add your specialized code here and/or call the base class if (nID == WM_TRAY_IDD) AfxMessageBox("nID"); if (nCode == WM_TRAY_IDD) AfxMessageBox("nCode"); return CDialog::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo); } BOOL CSecuresockDlg::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) { // TODO: Add your specialized code here and/or call the base class //AfxMessageBox("notify"); return CDialog::OnNotify(wParam, lParam, pResult); } BOOL CSecuresockDlg::PreCreateWindow(CREATESTRUCT& cs) { // TODO: Add your specialized code here and/or call the base class AfxMessageBox("precreate window"); cs.style |= WS_VISIBLE; //cs.style |= WS_EX_TOOLWINDOW; cs.dwExStyle &= (~WS_EX_APPWINDOW); cs.dwExStyle |= WS_EX_TOOLWINDOW; cs.dwExStyle |= WS_EX_PALETTEWINDOW ; return CDialog::PreCreateWindow(cs); } /* The rules the taskbar uses to decide whether a button should be shown for a window are really quite simple, but are not well documented. When you create a window, the taskbar examines the window’s extended style to see if either the WS_EX_APPWINDOW (defined as 0x00040000) or WS_EX_TOOLWINDOW (defined as 0x00000080) style is turned on. If WS_EX_APPWINDOW is turned on, the taskbar shows a button for the window, and if WS_EX_ TOOLWINDOW is turned on, the taskbar does not show a button for the window. You should never create a window that has both of these extended styles. LRESULT CMWDlg::OnTrayNotification(WPARAM uID, LPARAM lEvent) { if ( lEvent == WM_LBUTTONDBLCLK ) { m_okToShow = TRUE; // Allow the dialog to be shown if ( !IsWindowVisible() ) ShowWindow( SW_SHOW ); if ( IsIconic() ) ShowWindow( SW_RESTORE ); } #if 1 else if ( lEvent == WM_RBUTTONUP ) { CMenu * pSysMenu = GetSystemMenu( FALSE ); if ( pSysMenu ) { CPoint mouse; GetCursorPos(&mouse); pSysMenu->TrackPopupMenu( TPM_CENTERALIGN, mouse.x, mouse.y, this ); // delete pSysMenu; } } #endif return 0; } */ LRESULT CSecuresockDlg::OnTrayNotification(WPARAM uID, LPARAM lEvent){ if (lEvent == WM_LBUTTONDOWN) { CWnd *pwnd = CWnd::GetDesktopWindow()->GetWindow(GW_CHILD); CString test; while (pwnd) { pwnd->GetWindowText(test); //AfxMessageBox(test); if (test == "Drakis SecureChat 1.0") { //if (pwnd->IsIconic() ) // isiconic isn't reliable when i'm minimizing/hiding - // in those cases isiconic returns false (since it's invis). // the sneaky way to not have it show up in desktop bar // that lists apps (or alt-tab list). this is how winamp // handles minimization also. call sw_restore always shouldn't // hurt anything for now. pwnd->ShowWindow(SW_RESTORE); pwnd->SetForegroundWindow(); pwnd->GetLastActivePopup()->SetForegroundWindow(); return TRUE; } pwnd = pwnd->GetWindow( GW_HWNDNEXT); } } if (lEvent == WM_RBUTTONDOWN) { DWORD dp = ::GetMessagePos(); CPoint mouse; GetCursorPos(&mouse); CPoint pt2 ((int) LOWORD( dp ), (int) HIWORD (dp) ); CMenu menu; menu.LoadMenu(IDR_MENU1); CMenu *x; x = menu.GetSubMenu(4); CRect rect; GetWindowRect(rect); int ncmd = x->TrackPopupMenu( TPM_RETURNCMD | TPM_RIGHTALIGN , mouse.x, mouse.y, AfxGetMainWnd(), NULL ); if (ncmd == ID_CLOSE_NOW) AfxGetMainWnd()->PostMessage(WM_QUIT); } if (false) { static LPCSTR MouseMessages[] = { "WM_MOUSEMOVE", "WM_LBUTTONDOWN", "WM_LBUTTONUP", "WM_LBUTTONDBLCLK", "WM_RBUTTONDOWN", "WM_RBUTTONUP", "WM_RBUTTONDBLCLK", "WM_MBUTTONDOWN", "WM_MBUTTONUP", "WM_MBUTTONDBLCLK" }; CString s; s.Format("Tray notification: ID=%d, lEvent=0x%04x %s\r\n", uID, lEvent, WM_MOUSEFIRST<=lEvent && lEvent<=WM_MOUSELAST ? MouseMessages[lEvent-WM_MOUSEFIRST] : "(Unknown)"); //AfxMessageBox(s); } // let tray icon do default stuff return true; } void CSecuresockDlg::OnTrayIcon() { //AfxMessageBox("on tray icon call"); // TODO: Add your command handler code here } BOOL CSecuresockDlg::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) { // TODO: Add your specialized code here and/or call the base class ASSERT(0); return CDialog::Create(IDD, pParentWnd); } void CSecuresockDlg::OnCancelMode() { CDialog::OnCancelMode(); m_hitcancel = 1; //AfxMessageBox("here"); } BOOL CSecuresockDlg::PreTranslateMessage(MSG* pMsg) { // this is a known bug with the edit control for a tree control not being // able to receive return or escape messages when the dialog "steals" them so to speak // if GetEditControl returns a valid pointer than we are in editting mode, in which case // go ahead and manually route the message to the edit control // reference knowledge base Article ID: Q167960 if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE) { CEdit* edit = m_TreeCtrl.GetEditControl(); if (edit) { edit->SendMessage(WM_KEYDOWN, pMsg->wParam, pMsg->lParam); return TRUE; } // for now since i don't want esc or return to do anything, just return here // note that both hitting cancel key and the cancel button on the dialog both call // OnCancel directly. So removing OnCancel or making it inoperable means you can't close // the app from the normal close dialog button (X button). It is hard to separate this from // the actions of them hitting cancel key also, as cancel key doesn't appear to travel thru // the normal WM_CHAR or WM_SYS_CHAR functions at all but also goes directly to OnCancel if it // exists. this is highly annoying behavior and another reason for manually overriding this stuff // in pretranslatemessage, so we can kill the escape key hits without disallowing them to close // via the normal dialog close button. return TRUE; } return CDialog::PreTranslateMessage(pMsg); } void CSecuresockDlg::OnUpdateChangeIcon1(CCmdUI* pCmdUI) { // TODO: Add your command update UI handler code here } void CSecuresockDlg::OnMyButtonUI(CCmdUI* pCmdUI) { if (1) { AfxMessageBox("b"); ASSERT(0); } // TODO: Add your command update UI handler code here } void CSecuresockDlg::OnDblclkTree1(NMHDR* pNMHDR, LRESULT* pResult) { DWORD dp = ::GetMessagePos(); CPoint pt ((int) LOWORD( dp ), (int) HIWORD (dp) ); m_TreeCtrl.ScreenToClient (&pt); UINT flags = NULL; //char buffer[20]; HTREEITEM thishitem = m_TreeCtrl.HitTest( pt, &flags); // if top level item = department, use department menu, otherwise use contact menu if ( m_TreeCtrl.GetParentItem(thishitem) == NULL || thishitem == NULL) { return; } ChatItemInfo *tempci; tempci = (ChatItemInfo *)(m_TreeCtrl.GetItemData( thishitem )); // dont open send message dialog for a system message if (tempci->ntype == SYSTEM_MSG) { return; } else if (tempci->ntype == INCOMING_CONTACT_REQUEST ) { CAcceptContact acdlg; //tempci = (ChatItemInfo *)(m_TreeCtrl.GetItemData( thishitem )); acdlg.m_ContactMsg = tempci->msg; int nresult = acdlg.DoModal(); if (acdlg.nstatus == 1) { ProcessChatRequest(thishitem, tempci, true); } if (acdlg.nstatus == 0) { ProcessChatRequest(thishitem, tempci, false); } return; } else { if ( (tempci->ntype == CHAT_CONTACT) && pSockApp->bPendingMsgsByChatID( tempci->chat_id ) ) { CReadDlg *readdlg; CString temp; int noffset = pSockApp->GetPendingMsgByChatID( tempci->chat_id, &temp); if (noffset == -1 ) { AfxMessageBox("trouble finding related message to this chat id, bug"); } else { // modeless dialog creation readdlg = new CReadDlg(); readdlg->iUserIconID = tempci->icon_id; readdlg->msg_text = temp.GetBuffer(0); readdlg->m_myiconid = m_TreeCtrl.GetImageIndex(thishitem); readdlg->chat_id = tempci->chat_id; readdlg->m_nickname = tempci->nickname; readdlg->s_backcolor = pSockApp->main_msg_list.msg_vector[noffset].backcolor.GetBuffer(0); readdlg->Create(); pSockApp->UpdateMsgListFlag(noffset, true) ; } } else { m_TreeCtrl.SelectItem( thishitem ); CSendDlg *senddlg; //MessageBox("send message"); senddlg = new CSendDlg(); senddlg->iUserIconID = tempci->icon_id; CString temp; TRACE("calling send dlg, chat id : %lu", tempci->chat_id); //tempci->chat_id //AfxMessageBox( tempci->nickname ); TRACE("nickname: %s", tempci->nickname.GetBuffer(0)); senddlg->m_myiconid = m_TreeCtrl.GetImageIndex(thishitem); senddlg->m_nickname = tempci->nickname; senddlg->chat_id = tempci->chat_id; senddlg->Create(); senddlg->SetActiveWindow(); } *pResult = 0; } return; } // save the current users array to users.ids file // note they can switch between users so this is an array bool CSecuresockDlg::SaveUsersToFile(void) { //ASSERT(0); CString ifname; int n; ifname = "users.ids"; ofstream users_file ( ifname.GetBuffer(0), ios::out ); if (users_file) { for (n=0;n<pSockApp->users_array.size();n++) { users_file << setw(10) << pSockApp->users_array[n].chat_id; users_file << setw(1) << pSockApp->users_array[n].is_default ; users_file << setw(4) << pSockApp->users_array[n].nickname.GetLength() ; users_file << ","; users_file << pSockApp->users_array[n].nickname.GetBuffer(0) ; users_file << '\n'; //users_file << pSockApp->users_array[n].nickname.GetBuffer(0) << endl; } users_file.close(); } else { return false; } return true; } HBRUSH CSecuresockDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor); if (m_my_status.m_hWnd == pWnd->m_hWnd) { pDC->SetBkColor( RGB( 0, 0, 0) ); if (m_imy_status == ACTIVE) pDC->SetTextColor( RGB( 0, 255, 0) ); else if (m_imy_status == BUSY) pDC->SetTextColor( RGB( 0, 255, 255) ); else if (m_imy_status == SHORT_AFK) pDC->SetTextColor( RGB( 255, 255, 0) ); else if (m_imy_status == LONG_AFK) pDC->SetTextColor( RGB( 255, 128, 0) ); else if (m_imy_status == INVISIBLE) pDC->SetTextColor( RGB( 192, 192, 192) ); else pDC->SetTextColor( RGB( 255, 0, 255) ); return (HBRUSH)m_BlackBrush; //pWnd->Invalidate(TRUE); } else if (m_online_status.m_hWnd == pWnd->m_hWnd ) { if (pSockApp->bTroubleConnecting ) { pDC->SetTextColor( RGB( 255, 0, 0) ); pDC->SetBkColor( RGB( 0, 0, 0) ); //return (HBRUSH)m_BlackBrush; } else { pDC->SetTextColor( RGB( 0, 192, 64) ); pDC->SetBkColor( RGB( 0, 0, 0) ); //return (HBRUSH)m_BlackBrush; //return (HBRUSH)m_GreenBrush; } return (HBRUSH)m_BlackBrush; } return hbr; } // process an incoming message, param w is a CSingleMessage pointer of the received message's info LONG CSecuresockDlg::OnNewMessage(WPARAM w, LPARAM l) { CSingleMessage *temp = (CSingleMessage *)w; // if you call methods on the csm object created in the other thread (via slot.cpp) it appears to cause an error // on delete. this is not consistent and relates to possibly the fact that a csm has cstrings in it and // calling methods on an object across thread boundaries is a bit dangerous in MFC. so we create a copy of // of the csinglemessage and then delete the CSingleMessage pointer passed in from slot.cpp (which runs in a // separate thread and processes incoming chat messages from there, and then posts a message to the window // which then gets directed to this function, which runs in the main thread). See Prosise on threading for // more details on how to pass info back and forth from threads. it is generally okay to access variables // from an object created in another thread but assigning these variables values or calling the methods on // the object seems to sometimes cause problems with delete, it gives an error "damage in header block on // delete" which is often a critical error. // further note: when this happens after fixing error or while rebuilding the app completely can help it to // return to state, sometimes it can get in a dangerously unstable situation where it shows phantom bugs all // over (in other deletes for example that should not be buggy). rebuild all seems to clear the heap pointer // mechanism somehow and stop this phantom bug problem (whereas incremental rebuild, or even quitting and coming // back into Visual Studio, doesn't appear to make the unstable state go away). CSingleMessage copy_of_csm; // this statement is possible because i've explicitly defined operator= for CSingleMessage class, see class details for // more info copy_of_csm = *temp; // make sure we delete the object passed in via the message parameters, after we've copied it to a usable object // again, don't use an object created in another thread by reassignign values to object variables, or // by calling methods on it, or you will get likely // crashes/memory leaks/very bad things. this is a thread issue with MFC delete temp; // adds a message to the messages to be processed list (a vector of messages in a container class) int nmsgoffset = pSockApp->AddMessage(©_of_csm); if (nmsgoffset < 0) { AfxMessageBox("trouble adding a message to the internal message vector make note for Scott"); } CString temp2; // this is a serious bug just quit function if true if (copy_of_csm.chat_id_to == 0) { AfxMessageBox("bug, new msg received with incoming chat id of zero"); return 0L; } // this is if the message was sent to another user on this same machine, this shouldn't happen often // but is possible, if so we queue it up in the messages but don't mark it as processed yet // note: currently used chat_id = psockapp->my_controls.chat_id if ( copy_of_csm.chat_id_to != pSockApp->my_controls.chat_id ) { // mark message as not being processed (this is not strictly necessary as it's created with a false // value but good to do for clarity here I think). if (nmsgoffset >= 0) pSockApp->UpdateMsgListFlag(nmsgoffset, false); copy_of_csm.SaveMsgToLog(false, false); long li = 1; return li; } // received, i.e. incoming, contact request if (copy_of_csm.msg_type == CSingleMessage::CONTACT_REQUEST) { HTREEITEM hi = GetPendingContactGroup(); int icon_id = copy_of_csm.icon_id; int nindex = GetGoodIndex( &icon_id ); //copy_of_csm.icon_id = icon_id; //if (pSockApp->GetCurrentUserBoolSetting("show_notif_in_tree") ) { temp2.Format("Incoming contact request from:%s", copy_of_csm.nickname.GetBuffer(0) ); HTREEITEM newitem = m_TreeCtrl.InsertItem( temp2.GetBuffer(0), nindex, nindex, hi); m_TreeCtrl.Expand( hi, TVE_EXPAND); ChatItemInfo *citemp = new ChatItemInfo (copy_of_csm.chat_id_from, INCOMING_CONTACT_REQUEST, copy_of_csm.msg, copy_of_csm.time_sent, copy_of_csm.time_received, copy_of_csm.nickname, icon_id ); // since the user may delete objects and they are added constantly i'm using a version of garbage // collection for now to delete all this on application shutdown. the second param shows what time to cast // the pointer to before you delete it, source to function is in securesock.cpp add_ptr_to_garbage(citemp, "ChatItemInfo"); m_TreeCtrl.SetItemData( newitem, (DWORD)citemp ); //} if (nmsgoffset >= 0) pSockApp->UpdateMsgListFlag(nmsgoffset, true); copy_of_csm.SaveMsgToLog(false, false); } // contact acceptance (reply from contact request in affirmative) else if (copy_of_csm.msg_type == CSingleMessage::CR_ACCEPTED) { CString temp_string; temp_string.Format("%s - contact acceptance msg received", copy_of_csm.nickname.GetBuffer(0) ); CString descrip; descrip = "contact request acceptance received"; //AddSystemMsg( ©_of_csm, copy_of_csm.msg_type, temp_string, descrip ); NewInsertSystemMessage(temp_string, copy_of_csm.chat_id_from, copy_of_csm.msg, copy_of_csm.nickname, copy_of_csm.time_sent); CString temp3; temp3.Format("Your chat request to %s has been approved -- please specify what Group you would like " "to put them into.", copy_of_csm.nickname.GetBuffer(0) ); AfxMessageBox( temp3 ); this->GetGroupLabels( ); CMoveContactDlg mcd; mcd.nocopy = true; mcd.ptgiVector = tgiVector; mcd.DoModal(); int nindex = GetIndexFromIconID(copy_of_csm.icon_id); HTREEITEM higroup; if (mcd.nchoice == -1) { higroup = m_TreeCtrl.GetRootItem(); if (higroup == 0) { higroup = m_TreeCtrl.InsertItem( "New Group", nindex, nindex, TVI_ROOT, TVI_LAST); } } else { higroup = tgiVector[mcd.nchoice].htItem; } HTREEITEM newitem = m_TreeCtrl.InsertItem( copy_of_csm.nickname.GetBuffer(0), nindex, nindex, higroup); m_TreeCtrl.Expand( higroup, TVE_EXPAND); ChatItemInfo *citemp = new ChatItemInfo; citemp->chat_id = copy_of_csm.chat_id_from; citemp->ntype = CHAT_CONTACT; citemp->create_time = GetTimeString() ; citemp->msg = ""; citemp->icon_id = copy_of_csm.icon_id ; citemp->nickname = copy_of_csm.nickname.GetBuffer(0); // since the user may delete objects and they are added constantly i'm using a version of garbage // collection for now to delete all this on application shutdown. the second param shows what time to cast // the pointer to before you delete it, source to function is in securesock.cpp add_ptr_to_garbage(citemp, "ChatItemInfo"); m_TreeCtrl.SetItemData( newitem, (DWORD)citemp ); if (nmsgoffset >= 0) pSockApp->UpdateMsgListFlag(nmsgoffset, true); copy_of_csm.SaveMsgToLog(false, false); } // contact decline message (reply from contact request in negative) else if (copy_of_csm.msg_type == CSingleMessage::CR_DECLINED) { CString temp_string; temp_string.Format("%s - contact declined msg received", copy_of_csm.nickname.GetBuffer(0) ); CString descrip; descrip = "contact request decline received"; //AddSystemMsg( ©_of_csm, copy_of_csm.msg_type, temp_string, descrip ); NewInsertSystemMessage(temp_string, copy_of_csm.chat_id_from, copy_of_csm.msg, copy_of_csm.nickname, copy_of_csm.time_sent); TRACE("in declined handler\n"); // the current messages list/ messages vector has a flag whether it has been processed yet, it has so set this flag // to a true value. upon creation (in addmessages) it will be set to false. if i receive a message for, // say another user on this computer by accident (there is a short window of somewhere under 30 seconds // when you switch accounts when you might get a message for the old user), // i can tell by this flag on the message whether the message still // needs to be processed, eventually this message list will be serialized so that on shutdown or whatever // the messagelist will be recreated for these unprocessed messages (note this is separate from the log // which is more just a history of what happens). the serialization will have to be a constant thing to avoid // power lossage/loss of info problems. if (nmsgoffset >= 0) pSockApp->UpdateMsgListFlag(nmsgoffset, true); copy_of_csm.SaveMsgToLog(false, false); } // contact decline message (reply from contact request in negative) else if (copy_of_csm.msg_type == CSingleMessage::MESSAGE) { CString temp_string; temp_string.Format("%s - incoming msg received", copy_of_csm.nickname.GetBuffer(0) ); CString descrip; descrip = "New Message Received"; if (pSockApp->GetCurrentUserBoolSetting("show_notif_in_tree") ) { //AddSystemMsg( ©_of_csm, copy_of_csm.msg_type, temp_string, descrip ); NewInsertSystemMessage(temp_string, copy_of_csm.chat_id_from, descrip, copy_of_csm.nickname, copy_of_csm.time_sent); } TRACE("in message received handler\n"); sndPlaySound("driveby.wav", SND_ASYNC); // the current messages list/ messages vector has a flag whether it has been processed yet, it has so set this flag // to a true value. upon creation (in addmessages) it will be set to false. if i receive a message for, // say another user on this computer by accident (there is a short window of somewhere under 30 seconds // when you switch accounts when you might get a message for the old user), // i can tell by this flag on the message whether the message still // needs to be processed, eventually this message list will be serialized so that on shutdown or whatever // the messagelist will be recreated for these unprocessed messages (note this is separate from the log // which is more just a history of what happens). the serialization will have to be a constant thing to avoid // power lossage/loss of info problems. if (nmsgoffset >= 0) pSockApp->UpdateMsgListFlag(nmsgoffset, false); copy_of_csm.SaveMsgToLog(false, false); } long li = 1; return li; } HTREEITEM CSecuresockDlg::NewInsertSystemMessage(CString label_text, unsigned long chat_id, CString msg, CString nickname, CString created ) { HTREEITEM hi; hi = GetTreeItemByCriteria(CSecuresockDlg::TYPE_LOOKUP, (int)SYSTEM_GROUP) ; if ( hi == 0) { hi = m_TreeCtrl.InsertSysNotifyGrp(); if (! hi) { AfxMessageBox("warning, unable to create new system group, make note for programmer"); hi = m_TreeCtrl.GetRootItem(); if (hi == 0) { AfxMessageBox("new system message lost, notify Scott"); return false; } } } if (chat_id == 0) { AfxMessageBox("associated chat id for this system message is zero, possible bug," " make note for programmer"); return false; } int nindex = GetIndexFromIconID(IDI_ICON83); HTREEITEM newitem = m_TreeCtrl.InsertItem( label_text.GetBuffer(0), nindex, nindex, hi); m_TreeCtrl.Expand( hi, TVE_EXPAND); ChatItemInfo *citemp = new ChatItemInfo; citemp->chat_id = chat_id; citemp->ntype = SYSTEM_MSG; CString time; GetTimeString(&time); citemp->create_time = time.GetBuffer(0) ; //citemp-> citemp->msg = msg.GetBuffer(0); citemp->nickname = nickname.GetBuffer(0); // since the user may delete objects and they are added constantly i'm using a version of garbage // collection for now to delete all this on application shutdown. the second param shows what time to cast // the pointer to before you delete it, source to function is in securesock.cpp add_ptr_to_garbage( (LPVOID)citemp, "ChatItemInfo"); m_TreeCtrl.SetItemData( newitem, (DWORD)citemp ); return newitem; } int CSecuresockDlg::GetGoodIndex(int *icon_id) { int iret; if (*icon_id == 0) { iret = GetIndexFromIconID(IDI_ICON31); *icon_id = IDI_ICON31; } else { iret = GetIndexFromIconID(*icon_id); if (iret == -1) { iret = GetIndexFromIconID(IDI_ICON31); *icon_id = IDI_ICON31; } } return iret; } HTREEITEM CSecuresockDlg::GetPendingContactGroup(void) { HTREEITEM hi; hi = GetTreeItemByCriteria(CSecuresockDlg::TYPE_LOOKUP, (int)PENDING_CONTACTS_GROUP) ; if ( hi == 0) { hi = m_TreeCtrl.InsertItem( "Pending Contact Requests", 29, 29, TVI_ROOT, TVI_LAST); CString string_time = GetTimeString(); ChatItemInfo *newci = new ChatItemInfo(0L, PENDING_CONTACTS_GROUP, CString("Pending Contact Requests Group"), string_time ); m_TreeCtrl.SetItemData( hi, (DWORD)newci ); add_ptr_to_garbage(newci, "ChatItemInfo"); } return hi; } void CSecuresockDlg::GetLatency() { if (pSockApp->bTroubleConnecting) { AfxMessageBox("You don't appear to be online, hence your latency is infinite"); return; } DWORD start = GetTickCount(); // attempt to check in CString send_url; send_url.Format("/cgi-bin/check_in.pl?my_scno=%lu", pSockApp->my_controls.chat_id); CMySocket newconn("www.drakis.com"); CString response; newconn.GetFileAsString( send_url.GetBuffer(0), "www.drakis.com", &response); bool bConnected = true; if ( response.Find("ok^", 0) == -1 ) { //AfxMessageBox("trouble connecting"); bConnected = false; } else { //AfxMessageBox("connected"); } DWORD end = GetTickCount(); if ( end < start ) { AfxMessageBox("the timer just cycled it does this every 49 days, the chances of this happening are like one " "in ten billion. Unfortunately there is no lottery award =(. Retry to check latency."); return; } double diff = end - start; diff = diff / (double)1000; CString temp_string; temp_string.Format("Server Latency: %3.3f seconds\n " "A lower latency means a better connection, if your latency is high the server may " "be busy or you may be on a bad connection.", diff); AfxMessageBox(temp_string); } void CSecuresockDlg::SwitchUsers(int offset) { int newchat_id = 126; // make sure you save any new groups, contacts, etc. so call SaveTree before // changing the default ID (via pSockApp->my_controls.chat_id). SaveTree(); // note this also will return false (i.e. fail) if we are already set to this chat_id, which // means we really dont need to do anything, just return if (! pSockApp->SetDefaultUser( offset ) ) { //AfxMessageBox("trouble finding this new chat_id internal logic synch error notify Scott"); //note: error msg handled in method itself not needed here //AfxMessageBox("did nothing"); return; } CString temp = pSockApp->my_controls.GetStringByTokenName("user_icon"); int ICONIDD = atoi(temp.GetBuffer(0)); if (ICONIDD == 0) { AfxMessageBox("trouble retrieving new users icon"); ICONIDD = IDI_ICON31; } HICON hIcon = ::LoadIcon (AfxGetResourceHandle(), MAKEINTRESOURCE(ICONIDD)); m_mypersonalbutton.SetIcon( hIcon ); m_my_personal_icon_id = ICONIDD; temp.Format("tf_u%lu.dra", pSockApp->my_controls.chat_id); CFile *myfile = new CFile(); bool bopenokay = true; try { myfile->Open( temp.GetBuffer(0), CFile::modeRead ); } catch ( ... ) { } if (myfile->m_hFile == (UINT)CFile::hFileNull) { delete myfile; myfile = (CFile *)NULL; } m_TreeCtrl.DeleteAllItems(); // if treeFile is NULL this is okay it recreates a generic tree BuildTreeFromFile(m_TreeCtrl, myfile, true ); delete myfile; // set back ground color for tree if available CString colors = pSockApp->my_controls.GetStringByTokenName("tree_back_color"); if (! colors.IsEmpty() ) { unsigned long ulcolor = strtoul(colors.GetBuffer(0), NULL, 10); COLORREF x2 = (COLORREF)ulcolor; m_TreeCtrl.SetBkColor(x2) ; } GetTreeFontFromFile(); // get saved online status (ghost mode, busy, afk, or active, based on their last entry before // last save CString saved_status = pSockApp->my_controls.GetStringByTokenName("user_online_status"); if ( saved_status.IsEmpty() || atoi(saved_status.GetBuffer(0)) == 0) m_imy_status = CSecuresockDlg::ACTIVE; else m_imy_status = atoi(saved_status.GetBuffer(0)); ::SetMyOnlineStatus(m_imy_status); UpdateMyStatusText(); temp.Format("Changed control to user:%s", pSockApp->my_controls.nickname.GetBuffer(0) ); AfxMessageBox(temp ); //temp.Format("new chat id is now: %lu", pSockApp->my_controls.chat_id); //AfxMessageBox( temp ); } // update the "status: online" kind of textbox, to whatever is current condition void CSecuresockDlg::UpdateStatusText(void) { CWnd *pwnd2 = (CWnd *)(&m_online_status); // m_online_status is created via code not as a dialog item on // the resource (for various reasons, like ease of setting font stuff) if (pSockApp->bTroubleConnecting) pwnd2->SetWindowText("Server: Offline"); else pwnd2->SetWindowText("Server: Online"); //pwnd2->Invalidate(); // cause color repaint, not sure if strictly necessary // color is changed in WM_CTL_COLOR handler //pwnd2 = (CWnd *)(&m_my_status); //CString temp; //pwnd2->GetWindowText(temp); //pwnd2->SetWindowText( "scooby" ); //pwnd2->Invalidate(TRUE); } bool CSecuresockDlg::OnSend(ITEMINFO *pItem) { OnOutgoingMsg((WPARAM)pItem, 0); return true; } bool CSecuresockDlg::ProcessChatRequest(HTREEITEM thishitem, ChatItemInfo *tempci, bool bAccept) { //vector<TreeGroupInfo> tgiVector; // if they accepted the chat request if (bAccept) { this->GetGroupLabels(); CMoveContactDlg mcd; mcd.nocopy = true; mcd.ptgiVector = tgiVector; mcd.DoModal(); int nindex = GetIndexFromIconID(tempci->icon_id); HTREEITEM higroup; if (mcd.nchoice == -1) { higroup = m_TreeCtrl.GetRootItem(); if (higroup == 0) { higroup = m_TreeCtrl.InsertItem( "New Group", nindex, nindex, TVI_ROOT, TVI_LAST); } } else { higroup = tgiVector[mcd.nchoice].htItem; } HTREEITEM newitem = m_TreeCtrl.InsertItem( tempci->nickname.GetBuffer(0), nindex, nindex, higroup); m_TreeCtrl.Expand( higroup, TVE_EXPAND); ChatItemInfo *citemp = new ChatItemInfo; citemp->chat_id = tempci->chat_id; citemp->ntype = CHAT_CONTACT; citemp->create_time = GetTimeString() ; citemp->msg = ""; citemp->icon_id = tempci->icon_id ; citemp->nickname = tempci->nickname; add_ptr_to_garbage(citemp, "ChatItemInfo"); m_TreeCtrl.SetItemData( newitem, (DWORD)citemp ); // pointer deleted in onoutgoingmsg ITEMINFO *pItem = new ITEMINFO(); // this would be a good place for a operator= method probably will add this to ITEMINFO at // some point, right now it's just a plain old structure not a class. pItem->chat_id.Format("%lu", tempci->chat_id); pItem->nickname = pSockApp->my_controls.GetStringByTokenName("nickname"); pItem->nickname_to = tempci->nickname.GetBuffer(0); pItem->msg = "Contact request accepted"; pItem->csm_msg_type = CSingleMessage::CR_ACCEPTED; pItem->ntype = OUTGOING_MSG; OnOutgoingMsg((WPARAM)pItem, 0); } else { // pointer deleted in onoutgoingmsg ITEMINFO *pItem = new ITEMINFO(); pItem->chat_id.Format("%lu", tempci->chat_id); pItem->msg = "Contact request declined"; pItem->csm_msg_type = CSingleMessage::CR_DECLINED; pItem->ntype = OUTGOING_MSG; pItem->nickname = pSockApp->my_controls.GetStringByTokenName("nickname"); pItem->nickname_to = tempci->nickname.GetBuffer(0); OnOutgoingMsg((WPARAM)pItem, 0); } m_TreeCtrl.DeleteItem( thishitem ); return true; } LONG CSecuresockDlg::ShowOnlineStatus(WPARAM w, LPARAM l) { OnlineResults *por = (OnlineResults *)w; //CString display; //display.Format("%lu", por->chat_id); if (por->bOnline) { //display += " is online"; if (por->nstatus == 0 || por->nstatus == this->ACTIVE) m_TreeCtrl.SetItemOverlayIndex( por->hitem, 1); if ( por->nstatus == this->BUSY) m_TreeCtrl.SetItemOverlayIndex( por->hitem, 3); if ( por->nstatus == this->SHORT_AFK) m_TreeCtrl.SetItemOverlayIndex( por->hitem, 4); if ( por->nstatus == this->LONG_AFK) m_TreeCtrl.SetItemOverlayIndex( por->hitem, 4); if ( por->nstatus == this->INVISIBLE) m_TreeCtrl.SetItemOverlayIndex( por->hitem, 2); } else { //display += " is NOT online"; m_TreeCtrl.SetItemOverlayIndex( por->hitem, 2); } //AfxMessageBox(display); delete por; return 0L; } LONG CSecuresockDlg::OnOutgoingMsg(WPARAM w, LPARAM l) { ITEMINFO *pItem = (ITEMINFO *)w; // this is chat_id to send to, in this case unsigned long chat_id = strtoul( pItem->chat_id.GetBuffer(0), NULL, 10 ); CString temp; CString created; created = ""; CString descrip; //HICON hIcon = ::LoadIcon (AfxGetResourceHandle(), // MAKEINTRESOURCE(ICONIDD)); //m_mypersonalbutton.SetIcon( hIcon ); //m_my_personal_icon_id = ICONIDD; // ultra paranoia here but to be safe if (chat_id == 0) { AfxMessageBox("attempt to send a message to a chat_id of ZERO " "probable logic error in OnOutgoingMsg function, notify programmer " "msg not sent."); temp.Format("%s - msg not sent logic error", pItem->nickname.GetBuffer(0) ); // second parameter not strictly necessary but provided for clarity // add a system message to the tree control about what we are doing descrip = "error with send: chat id was zero."; NewInsertSystemMessage(temp, 0L, descrip, pItem->nickname_to, created); //AddSystemMsg( pItem, CSingleMessage::NOT_SENT_LOGIC_ERROR, temp, descrip ); return 0L; } if (pItem->csm_msg_type == CSingleMessage::CONTACT_REQUEST) { temp.Format("%s - contact request sent", pItem->nickname.GetBuffer(0) ); //pItem->msg = "outgoing contact request"; CString msg_text = "Outgoing contact request sent"; // second parameter not strictly necessary but provided for clarity // add a system message to the tree control about what we are doing //AddSystemMsg( pItem, pItem->csm_msg_type, temp, msg_text ); if (pSockApp->GetCurrentUserBoolSetting("show_notif_in_tree") ) { NewInsertSystemMessage(temp, chat_id, msg_text, pItem->nickname_to, created); } // create a message info structure of info to pass to thread MessageInfo *pMsgInfo = new MessageInfo( pItem->csm_msg_type, chat_id, pSockApp->my_controls.chat_id, pSockApp->my_controls.GetStringByTokenName("nickname"), pItem->msg, m_my_personal_icon_id ); AfxBeginThread(send_msg, pMsgInfo); } if (pItem->csm_msg_type == CSingleMessage::CR_ACCEPTED) { temp.Format("%s - contact accept msg sent", pItem->nickname_to.GetBuffer(0) ); descrip = "contact acceptance msg sent"; //AddSystemMsg( pItem, pItem->csm_msg_type, temp, descrip ); if (pSockApp->GetCurrentUserBoolSetting("show_notif_in_tree") ) { NewInsertSystemMessage(temp, chat_id, descrip, pItem->nickname_to, created); } MessageInfo *pMsgInfo = new MessageInfo( pItem->csm_msg_type, chat_id, pSockApp->my_controls.chat_id, pSockApp->my_controls.GetStringByTokenName("nickname"), pItem->msg, m_my_personal_icon_id); AfxBeginThread(send_msg, pMsgInfo); gb_lookat = true; } if (pItem->csm_msg_type == CSingleMessage::CR_DECLINED) { temp.Format("%s - contact decline msg sent", pItem->nickname_to.GetBuffer(0) ); descrip = "contact decline msg sent"; //AddSystemMsg( pItem, pItem->csm_msg_type, temp, descrip ); if (pSockApp->GetCurrentUserBoolSetting("show_notif_in_tree") ) { NewInsertSystemMessage(temp, chat_id, descrip, pItem->nickname_to, created); } MessageInfo *pMsgInfo = new MessageInfo( pItem->csm_msg_type, chat_id, pSockApp->my_controls.chat_id, pSockApp->my_controls.GetStringByTokenName("nickname"), pItem->msg, m_my_personal_icon_id ); AfxBeginThread(send_msg, pMsgInfo); } if (pItem->csm_msg_type == CSingleMessage::MESSAGE) { temp.Format("chat message sent to %s", pItem->nickname_to.GetBuffer(0) ); //pItem->msg = "outgoing contact request"; CString msg_text = "Chat message sent"; // second parameter not strictly necessary but provided for clarity // add a system message to the tree control about what we are doing //AddSystemMsg( pItem, pItem->csm_msg_type, temp, msg_text ); if (pSockApp->GetCurrentUserBoolSetting("show_notif_in_tree") ) { NewInsertSystemMessage(temp, chat_id, msg_text, pItem->nickname_to, created); } // create a message info structure of info to pass to thread MessageInfo *pMsgInfo = new MessageInfo( pItem->csm_msg_type, chat_id, pSockApp->my_controls.chat_id, pSockApp->my_controls.GetStringByTokenName("nickname"), pItem->msg, m_my_personal_icon_id, pItem->backcolor.GetBuffer(0) ); AfxBeginThread(send_msg, pMsgInfo); } delete pItem; return 0L; } /* HTREEITEM CSecuresockDlg::InsertSystemMessage(CString label_text, HTREEITEM &hiGrp, unsigned long chat_id, TypeInfo ti_type, CString msg, ITEMINFO *pItemInfo, CString param_msg) { int nindex = GetIndexFromIconID(IDI_ICON83); HTREEITEM newitem = m_TreeCtrl.InsertItem( label_text.GetBuffer(0), nindex, nindex, hiGrp); m_TreeCtrl.Expand( hiGrp, TVE_EXPAND); ChatItemInfo *citemp = new ChatItemInfo; citemp->chat_id = chat_id; citemp->ntype = ti_type; CString time = "n/a"; //GetTimeString(); citemp->create_time = time.GetBuffer(0) ; citemp->msg = param_msg.GetBuffer(0); citemp->nickname = pItemInfo->nickname.GetBuffer(0); add_ptr_to_garbage( (LPVOID)citemp, "ChatItemInfo"); //delete citemp; m_TreeCtrl.SetItemData( newitem, (DWORD)citemp ); return newitem; } bool CSecuresockDlg::AddSystemMsg(CSingleMessage *temp, int imsg_type, CString label_text, CString msg) { ITEMINFO *newii = new ITEMINFO(); CString temp_string; temp_string.Format("%lu", temp->chat_id_from ); newii->chat_id = temp_string.GetBuffer(0); newii->csm_msg_type = temp->msg_type; newii->msg = temp->msg.GetBuffer(0); newii->nickname = temp->nickname.GetBuffer(0); newii->nickname_to = temp->nickname.GetBuffer(0); return AddSystemMsg( newii, imsg_type, label_text, msg); } bool CSecuresockDlg::AddSystemMsg(ITEMINFO *pItemInfo, int imsg_type, CString label_text, CString msg) { HTREEITEM hi; hi = GetTreeItemByCriteria(CSecuresockDlg::TYPE_LOOKUP, (int)SYSTEM_GROUP) ; if ( hi == 0) { hi = m_TreeCtrl.InsertSysNotifyGrp(); if (! hi) { AfxMessageBox("warning, unable to create new system group, make note for programmer"); hi = m_TreeCtrl.GetRootItem(); if (hi == 0) return false; } } unsigned long chat_id = strtoul( pItemInfo->chat_id.GetBuffer(0), NULL, 10 ); if (chat_id == 0) { AfxMessageBox("associated chat id for this system message is zero, possible bug," " make note for programmer"); return false; } InsertSystemMessage(label_text, hi, chat_id, SYSTEM_MSG, pItemInfo->msg, pItemInfo, msg); return true; } */ // handler method for WM_CONNECT_STATUS message LONG CSecuresockDlg::OnConnectStatus(WPARAM w, LPARAM l) { CONNECTINFO *conn_info = (CONNECTINFO *)w; // this is called from wm_init_dialog sort of in a roundabout way, this is when // we have first connected (or failed). it only gets called once from here this is // done so that the whole dialog doesn't pause if it can't connect (for 17 seconds) // which happens when called this logic directly and trying to connect. so I handle this // special case with the same code as normal default handler operation for the ACK or the // "try to connect when not connected" timer calls that usually are handled in code below this. if (bStartupFlag) { bStartupFlag = false; pSockApp->bTroubleConnecting = ! conn_info->bIsConnected ; UpdateStatusText(); delete conn_info; return 0L; } // if something has changed, handle it, if it has changed from connected to not connected // or not connected to connected, change the timer value, and change the status text accordingly if ( conn_info->bIsConnected && pSockApp->bTroubleConnecting) { pSockApp->bTroubleConnecting = false; UpdateStatusText(); //KillTimer(2); // when online okay send acks every 5 seconds //SetTimer(2, 5000, NULL); } else if (! conn_info->bIsConnected && ! pSockApp->bTroubleConnecting) { pSockApp->bTroubleConnecting = true; UpdateStatusText(); //KillTimer(2); // when trouble connecting only retry every 25 seconds //SetTimer(2, 5000, NULL); } delete conn_info; return 0L; } // this thread has to do with sending messages or sending chat partner requests or similar // pParam is a MessageInfo pointer unsigned int send_msg(LPVOID pParam) { // retrieve the structure MessageInfo *pHelper = (MessageInfo *)pParam; TRACE("entering send_msg\n"); int i = 0; if (gb_lookat) { //ASSERT(0); gb_lookat = false; } CString temp; temp.Format("%i sends a message saying: %s", pHelper->chat_id, pHelper->msg.GetBuffer(0)); //AfxMessageBox( temp ); // get this persons IP if they are online CString send_url; send_url.Format("http://www.drakis.com/cgi-bin/get_recent_url.pl?chat_id=%lu", pHelper->chat_id); //AfxMessageBox( send_url ); //TRACE( send_url ); CString response = ::url_get(send_url.GetBuffer(0)); bool bSentOkay = false; CString direct_response; CString direct_msg; // this class CSingleMessage wraps some miscellaneous sending and receiving functions CSingleMessage msg; msg.chat_id_from = pHelper->sender_id; msg.chat_id_to = pHelper->chat_id; msg.time_sent = GetTimeString(); msg.server_time_sent = ""; msg.bfrom_server = 0; msg.msg = pHelper->msg; msg.msg_length = pHelper->msg.GetLength(); msg.msg_type = pHelper->ntype; msg.nickname = pHelper->nickname; msg.icon_id = pHelper->icon_id; //ASSERT(0); msg.backcolor = pHelper->backcolor.GetBuffer(0); //ASSERT(0); // if "ok" then they have a recent IP, try to send to it if (response.Left(2) == "ok" ) { CString IP = response.Mid(3); IP.Replace("^", ""); // strip out EOM character, I use caret (^) as an informal end of message marker at times // create a socket and try to connect to this IP # at socket 29807, this is the default securesock // service IP for send or receive CMySocket newconn(IP.GetBuffer(0), 29807 ); // if connected okay if (! newconn.bError ) { // build the socket "string", "look Mom no RPC" // (we know that RPC was created by demons at the behest of their leader, Bill) // RPC is a way of bundling data when sending it across computer wires which is related to IDL // and COM (at least in the Microsoft implementation). I prefer to write my data encoding and // extracting routines via a raw string that I then parse the results out of. This makes it humanly // readable if you haven't spent 9 months studying COM books. CString direct_msg; // create a socket send string from this message object msg.CreateStringFromObj(&direct_msg); // attempt to send this string via the socket newconn.socksend( direct_msg.GetBuffer(0) ); // if no errors (so far) if (! newconn.bError ) { //char *cresponse; int ncnt = 0; // sometimes there is a slight delay after connect before reading is allowed, // since this is in a thread we can just // use a slight pause (unscientific but appears to work) Sleep(400); // loop thru a few times and see if we can get a confirmation string back, like "ok" char *direct_response2 = new char[201]; direct_response2[0] = (char)0; int ioffset = 0; // try for 5 seconds total, no reply or activity within 5 seconds is a sign they didn't get it while (! newconn.bFinished && ! newconn.bError && (ncnt++ < 20) ) { // attempt to receive anything pending in socket buffer, note this is non-blocking (hence // the while loop) TRACE("calling sock receive\n"); newconn.sockreceive(); if ( strlen(newconn.myout) > 0) { if ( strlen(newconn.myout) + ioffset > 200 ) { strncpy(direct_response2 + ioffset, newconn.myout, 200 - ioffset ); direct_response2[200] = (char)0; break; } TRACE("appending to direct response 2\n"); strcpy(direct_response2 + ioffset, newconn.myout); ioffset += strlen(newconn.myout); //direct_response += newconn.myout; } // calling sleep is nice otherwise we are performance hogging a bit which isn't necessary // there is no real hurry going on here no need to continually be hitting sockreceive // i could also make sockreceive blocking I might do that, but this offers a nice level of // extra control. blocking timeout vals are weird under Windows. Sleep(100); // how does multi-tasking under windows handle sleep? does it ignore the function // or thread that is calling sleep for a bit? I hope so but not sure. } direct_response = direct_response2; delete [] direct_response2; // they should send "ok:" type messages back, add further confirmation type processing later // e.g. checksums back or something to verify they got the full message or whatever if ( direct_response.Left(2) == "ok") { // save info on send to the local log file TRACE("saving message to log\n"); msg.SaveMsgToLog(true, true); bSentOkay = true; } } } //bSentOkay = true; } // trouble sending directly or server didn't have current IP, so sending via offline (server msg) if (! bSentOkay ) { CString send_url; // when sending special characters via CGI params remember some characters don't work so // I wrote my own cgi_encode type function, source in securesock.cpp. see notes on how cgi // handles parameters with characters like % or = in any text on http or related RFC's. CString url_string; // create a string with parameters in CGI format for sending to server msg.CreateURLStringFromObj(&url_string); // create full send string now send_url.Format("http://www.drakis.com/cgi-bin/offline_msg.pl?%s", url_string.GetBuffer(0) ); CString tempx; tempx = "sent via server"; CMiscStuff::WaitWindow( tempx, NULL); Sleep(500); CMiscStuff::ClearWaitWindow(); //AfxMessageBox("User offline - sent via server"); //AfxMessageBox( send_url ); // maybe replace this with my version of socket send using mysocket object // at times ::url_get is failing if sending the same info it is not truly sending but pretending to // send and pulling from the cache, this happens even if you set DONTUSECACHE flag on (possible bug). CString response = ::url_get(send_url.GetBuffer(0)); // if we receive a happy response, save to log file and continue if ( response.Left(2) == "ok" ) { msg.SaveMsgToLog(true, false); } else { // otherwise set the error flag, this is important to have because we may try adding in resend logic msg.bSendFailure = true; // save to log as usual msg.SaveMsgToLog(true, false); // warning AfxMessageBox("the last message could not be sent directly and server may have been down so " "it was not sent. It will be queued and retried in the background until server is backup."); } } delete pHelper; TRACE("leaving send_msg\n"); return 0; } // this thread has to do with sending messages ack to the server to tell them we are on line // pParam is a MessageInfo pointer unsigned int send_ack_msg(LPVOID pParam) { /* if (g_attempting_server_contact) { TRACE("still in routine, timer send_ack_msg AVOIDED\n"); return; } */ double x1 = CMiscStuff::GetSeconds(); MessageInfo *pMsgInfo = new MessageInfo(); CString send_url; while (1) { Sleep(5000); pMsgInfo->ntype = 0; pMsgInfo->chat_id = 0; pMsgInfo->sender_id = ::GetCurrentChatID(); //unsigned long x = pSockApp->my_controls.chat_id; pMsgInfo->msg = ""; // note this is this->m_hWnd (securesockdlg member item m_hWnd) HWND hwndmd = ::GetMainDlgHWND(); pMsgInfo->phwnd = &hwndmd; pMsgInfo->n_online_status = ::GetMyOnlineStatus(); // this->m_imy_status; //TRACE("send ack msg called as normal\n"); //AfxBeginThread(send_ack_msg, (LPVOID)pMsgInfo); //x2 = CMiscStuff::GetSeconds(); //temp.Format("%3.3f", x2 - x1); //TRACE("timer 2:%s\n", temp.GetBuffer(0)); //g_attempting_server_contact = true; //TRACE("entering send_msg_ack\n"); //MessageInfo *pMsgInfo = (MessageInfo *)pParam; // retrieve the structure HWND *phwnd = pMsgInfo->phwnd; int i = 0; int nstatus = pMsgInfo->n_online_status; // attempt to check in send_url.Format("/cgi-bin/check_in.pl?my_scno=%lu&my_status=%i", pMsgInfo->sender_id, pMsgInfo->n_online_status); // calling raw methods not class methods (raw functions, global functions) helps to avoid problems with // threads accessing CObject related thingies which can sometimes cause problems. //send_url.Format("http://www.drakis.com/cgi-bin/check_in.pl?my_scno=%lu", pMsgInfo->sender_id); //CString response = ::url_get(send_url.GetBuffer(0)); // using the "other way" via url_get has some issues with it and less control // a. the default windows timeout value is very high, like 18 seconds or so on my computer // b. sometimes it hits the cache even when you tell it not to // url_get uses the cinternetfile and similar windows inet functions, whereas using cmysocket // creates a raw socket connection. doing it with raw sockets avoids a) (you can set the timeout to whatever // you want) and b) (it never pulls from the cache, which since this lookup is called every 20 seconds or so // is a prime example of something windows would pull from the cache, and does, even when you set a flag to // explicitly not use the cache. at least, this was my experience with a recent bug). while (g_ssd_insocket) Sleep(20); g_ssd_insocket = true; CMySocket newconn("www.drakis.com"); CString response; newconn.GetFileAsString( send_url.GetBuffer(0), "www.drakis.com", &response); g_ssd_insocket = false; // since this runs in a thread it could be operating during a shutdown if so we want to return quickly if (::stopping_threads() ) { TRACE("leaving thread okay\n"); break; } // if "ok" then they connected, updated okay bool bConnected = true; if ( response.Find("ok^", 0) == -1 ) { //AfxMessageBox("trouble connecting"); bConnected = false; } else { bConnected = true; //AfxMessageBox("connected"); } CONNECTINFO *conn_info = new CONNECTINFO; // pointer deleted in message receiving function // passing info back to the window via a message, again this is thread stuff see Prosise conn_info->bIsConnected = bConnected; //pMsgInfo->phwnd = &m_hWnd; // thread safe way to return value, post to a windows message ::PostMessage(*phwnd, WM_CONNECT_STATUS, (WPARAM)conn_info, 0); //g_attempting_server_contact = false; } delete pMsgInfo; TRACE("leaving send_msg_ack\n"); return 0; } // this thread gets whether the related users are online or not unsigned int check_online_status(LPVOID pParam) { g_getting_online_status = true; MessageInfo *pMsgInfo = (MessageInfo *)pParam; // retrieve the structure HWND *phwnd = pMsgInfo->phwnd; CString response; CString send_url; TRACE("entering get online status\n"); int n; for (n=0;n < online_chk_vector.size(); n++) { TRACE("getting online status for %lu", online_chk_vector[n].chat_id ); // get this persons IP if they are online send_url.Format("/cgi-bin/get_recent_url.pl?chat_id=%lu", online_chk_vector[n].chat_id ); while (g_ssd_insocket) ; g_ssd_insocket = true; CMySocket newconn("www.drakis.com"); // clear response not sure if necessary response = ""; newconn.GetFileAsString( send_url.GetBuffer(0), "www.drakis.com", &response); newconn.sockclose(); g_ssd_insocket = false; //AfxMessageBox( response ); // if "ok" then they have a recent IP == they are online now if ( response.Find("ok:", 0) != -1 ) { //AfxMessageBox( response ); int npos = response.Find("ok:", 0); int npos2 = response.Find("^", 0); int npos3 = response.Find("status:", 0); CString str_status; int nstatus; if (npos3 != -1) { str_status = response.Mid(npos3+7); str_status = str_status.Left(5); //CString showstat; nstatus = atoi( str_status.GetBuffer(0) ) ; //showstat.Format("%i", atoi( str_status.GetBuffer(0) ) ); //AfxMessageBox( showstat ); } else { nstatus = 0; } CString IP; if (npos != -1 && npos2 != -1 && npos2 >= npos + 3 ) { IP = response.Mid(npos+3); IP = IP.Left( npos2 - npos - 3 ); } else { IP = ""; } //AfxMessageBox( IP ); IP.Replace("^", ""); // strip out EOM character, I use caret (^) as an informal end of message marker at times OnlineResults *por = new OnlineResults( online_chk_vector[n].chat_id, online_chk_vector[n].hitem, IP.GetBuffer(0), true, nstatus); // thread safe way to return value, post to a windows message ::PostMessage(*phwnd, WM_SHOW_ONLINE_STATUS, (WPARAM)por, 0); } else { OnlineResults *por = new OnlineResults( online_chk_vector[n].chat_id, online_chk_vector[n].hitem, "", false, 0 ); // thread safe way to return value, post to a windows message ::PostMessage(*phwnd, WM_SHOW_ONLINE_STATUS, (WPARAM)por, 0); } } delete pMsgInfo; g_getting_online_status = false; return 0; } ChatItemInfo::ChatItemInfo() { this->chat_id = 0; this->create_time = ""; this->msg = ""; this->ntype = UNKNOWN; this->time_received = ""; this->nickname = ""; this->icon_id = 0; this->bPendingMsgs = false; } ChatItemInfo::ChatItemInfo(unsigned long chat_id, TypeInfo ntype, CString msg, CString create_time, CString time_received, CString nickname, int icon_id ) { this->chat_id = chat_id; this->create_time = create_time.GetBuffer(0); this->msg = msg.GetBuffer(0); this->ntype = ntype; this->time_received = time_received.GetBuffer(0); this->nickname = nickname.GetBuffer(0); this->icon_id = icon_id; this->bPendingMsgs = false; } ChatItemInfo::ChatItemInfo(unsigned long tchat_id, TypeInfo ntype, CString msg, CString create_time) { this->chat_id = tchat_id; this->create_time = create_time.GetBuffer(0); this->msg = msg.GetBuffer(0); this->ntype = ntype; this->time_received = ""; this->nickname = ""; this->icon_id = 0; this->bPendingMsgs = false; } TreeGroupInfo::TreeGroupInfo(CString tlabel, HTREEITEM thtItem) { label = tlabel; htItem = thtItem; } TreeGroupInfo::TreeGroupInfo(char *tlabel, HTREEITEM thtItem) { label = tlabel; htItem = thtItem; } CString ChatItemInfo::TypeDescrip(TypeInfo s) { CString temp; if (s==UNKNOWN) { temp = "Unknown Type"; } if (s==CHAT_CONTACT) { temp = "Chat Contact"; } if (s==GROUP) { temp = "Group" ; } if (s==SYSTEM_MSG) { temp = "System Message"; } if (s==SYSTEM_GROUP) { temp = "System Group" ; } if (s==PENDING_CONTACTS_GROUP) { temp = "Pending Contacts Group"; } if (s==INCOMING_CONTACT_REQUEST) { temp = "Incoming Contact Request"; } if (s==OUTGOING_CONTACT_REQUEST) { temp = "Outgoing Contact Request"; } return temp; } MessageInfo::MessageInfo() { this->ntype = UNKNOWN; this->chat_id = 0L; this->sender_id = 0L; this->nickname = ""; this->msg = ""; this->icon_id = 0; this->backcolor = ""; this->n_online_status = CSecuresockDlg::ACTIVE; } MessageInfo::MessageInfo(int ntype, unsigned long chat_id, unsigned long sender_id, CString nickname, CString msg, int icon_id, char *pbackcolor) { this->ntype = ntype; this->chat_id = chat_id; this->sender_id = sender_id; this->nickname = nickname.GetBuffer(0); this->msg = msg.GetBuffer(0); this->icon_id = icon_id; if (pbackcolor) this->backcolor = pbackcolor; else this->backcolor = ""; this->n_online_status = CSecuresockDlg::ACTIVE; } BOOL CSecuresockDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { // TODO: Add your message handler code here and/or call default // turn this on to set the main cursor to a blue arrow /* if (1) { // message == 512) { SetCursor( AfxGetApp()->LoadCursor(IDC_CURSOR8)); //TRACE("%lu\n", message ); return TRUE; } */ return CDialog::OnSetCursor(pWnd, nHitTest, message); } TreeStatusHelper::TreeStatusHelper(HTREEITEM hitem, unsigned long chat_id) { this->hitem = hitem; this->chat_id = chat_id; } OnlineResults::OnlineResults(unsigned long chat_id, HTREEITEM hitem, char *IP, bool bOnline, int nstatus) { this->chat_id = chat_id; this->hitem = hitem; this->IP = IP; this->bOnline = bOnline; this->nstatus = nstatus; } HWND GetMainDlgHWND() { return g_md_hwnd; } void SetMainDlgHWND(HWND x) { g_md_hwnd = x; } int GetMyOnlineStatus() { return g_i_mystatus; } void SetMyOnlineStatus(int status) { g_i_mystatus = status; }