// The contents of this file are subject to the Mozilla Public License // Version 1.0 (the "License"); you may not use this file except in // compliance with the License. You may obtain a copy of the License at // http://www.mozilla.org/MPL/ // // Software distributed under the License is distributed on an "AS IS" // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the // License for the specific language governing rights and limitations // under the License. // // The Original Code is the Berkeley Open Infrastructure for Network Computing. // // The Initial Developer of the Original Code is the SETI@home project. // Portions created by the SETI@home project are Copyright (C) 2002 // University of California at Berkeley. All Rights Reserved. // // Contributor(s): // // include header #include "wingui.h" #include "util.h" // globals int OSVersion; CMainWindow* g_myWnd = NULL; CMyApp g_myApp; char* g_szColumnTitles[MAX_LIST_ID][MAX_COLS] = { {"Project", "Account", "Total Credit", "Avg. Credit", "Resource Share", NULL, NULL}, {"Project", "Application", "Name", "CPU time", "Progress", "To Completion", "Status"}, {"Project", "File", "Progress", "Size", "Time", "Direction", NULL}, {"Project", "Time", "Message", NULL, NULL, NULL, NULL} }; void show_message(char* message, char* priority) { if(g_myWnd) { g_myWnd->MessageUser("BOINC", message, priority); } } void show_project_message(PROJECT* project, char* message, char* priority) { if(g_myWnd) { if(strcmp(project->project_name, "")) { g_myWnd->MessageUser(project->project_name, message, priority); } else { g_myWnd->MessageUser(project->master_url, message, priority); } } } int get_initial_project() { return 0; } void GetByteString(double nbytes, CString* str) { double xTera = (1024.0*1024*1024*1024); double xGiga = (1024.0*1024*1024); double xMega = (1024.0*1024); double xKilo = (1024.0); if (nbytes >= xTera) { str->Format("%0.2f TB", nbytes/xTera); } else if (nbytes >= xGiga) { str->Format("%0.2f GB", nbytes/xGiga); } else if (nbytes >= xMega) { str->Format("%0.2f MB", nbytes/xMega); } else if (nbytes >= xKilo) { str->Format("%0.2f KB", nbytes/xKilo); } else { str->Format("%0.0f bytes", nbytes); } } ///////////////////////////////////////////////////////////////////////// // CProgressHeaderCtrl message map and member functions BEGIN_MESSAGE_MAP(CProgressBarCtrl, CProgressCtrl) ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() ON_WM_RBUTTONDOWN() END_MESSAGE_MAP() ////////// // CProgressBarCtrl::CProgressBarCtrl // arguments: void // returns: void // function: void CProgressBarCtrl::CProgressBarCtrl() { } ////////// // CProgressBarCtrl::OnLButtonDown // arguments: nFlags: message flags (keys down) // point: mouse's point // returns: void // function: convert point to parent window's coordinates and forward message. void CProgressBarCtrl::OnLButtonDown(UINT nFlags, CPoint point) { CProgressCtrl::OnLButtonDown(nFlags, point); // if this control has a parent, repackage this message and forward it CWnd* pWndParent = GetParent(); if(pWndParent) { MapWindowPoints(pWndParent, &point, 1); WPARAM wParam = nFlags; LPARAM lParam = MAKELPARAM(point.x, point.y); pWndParent->SendMessage(WM_LBUTTONDOWN, wParam, lParam); } } ////////// // CProgressBarCtrl::OnLButtonUp // arguments: nFlags: message flags (keys down) // point: mouse's point // returns: void // function: convert point to parent window's coordinates and forward message. void CProgressBarCtrl::OnLButtonUp(UINT nFlags, CPoint point) { CProgressCtrl::OnLButtonUp(nFlags, point); // if this control has a parent, repackage this message and forward it CWnd* pWndParent = GetParent(); if(pWndParent) { MapWindowPoints(pWndParent, &point, 1); WPARAM wParam = nFlags; LPARAM lParam = MAKELPARAM(point.x, point.y); pWndParent->SendMessage(WM_LBUTTONUP, wParam, lParam); } } ////////// // CProgressBarCtrl::OnRButtonDown // arguments: nFlags: message flags (keys down) // point: mouse's point // returns: void // function: convert point to parent window's coordinates and forward message. void CProgressBarCtrl::OnRButtonDown(UINT nFlags, CPoint point) { CProgressCtrl::OnRButtonDown(nFlags, point); // if this control has a parent, repackage this message and forward it CWnd* pWndParent = GetParent(); if(pWndParent) { MapWindowPoints(pWndParent, &point, 1); WPARAM wParam = nFlags; LPARAM lParam = MAKELPARAM(point.x, point.y); pWndParent->SendMessage(WM_RBUTTONDOWN, wParam, lParam); } } ///////////////////////////////////////////////////////////////////////// // CProgressHeaderCtrl message map and member functions BEGIN_MESSAGE_MAP(CProgressHeaderCtrl, CHeaderCtrl) ON_WM_RBUTTONDOWN() ON_WM_RBUTTONUP() END_MESSAGE_MAP() ////////// // CProgressHeaderCtrl::CProgressHeaderCtrl // arguments: void // returns: void // function: void CProgressHeaderCtrl::CProgressHeaderCtrl() { } ////////// // CProgressHeaderCtrl::OnRButtonDown // arguments: nFlags: message flags (keys down) // point: mouse's point // returns: void // function: convert point to parent window's coordinates and forward message. void CProgressHeaderCtrl::OnRButtonDown(UINT nFlags, CPoint point) { CHeaderCtrl::OnRButtonDown(nFlags, point); // if this control has a parent, repackage this message and forward it CWnd* pWndParent = GetParent(); if(pWndParent) { MapWindowPoints(pWndParent, &point, 1); WPARAM wParam = nFlags; LPARAM lParam = MAKELPARAM(point.x, point.y); pWndParent->SendMessage(WM_RBUTTONDOWN, wParam, lParam); } } ////////// // CProgressHeaderCtrl::OnRButtonUp // arguments: nFlags: message flags (keys down) // point: mouse's point // returns: void // function: convert point to parent window's coordinates and forward message. void CProgressHeaderCtrl::OnRButtonUp(UINT nFlags, CPoint point) { CHeaderCtrl::OnRButtonUp(nFlags, point); // if this control has a parent, repackage this message and forward it CWnd* pWndParent = GetParent(); if(pWndParent) { MapWindowPoints(pWndParent, &point, 1); WPARAM wParam = nFlags; LPARAM lParam = MAKELPARAM(point.x, point.y); pWndParent->SendMessage(WM_RBUTTONUP, wParam, lParam); } } ///////////////////////////////////////////////////////////////////////// // CProgressListCtrl message map and member functions BEGIN_MESSAGE_MAP(CProgressListCtrl, CListCtrl) ON_WM_CREATE() ON_WM_DESTROY() ON_WM_PAINT() ON_WM_SETCURSOR() ON_WM_LBUTTONDOWN() ON_WM_RBUTTONDOWN() ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw) END_MESSAGE_MAP() ////////// // CProgressListCtrl::CProgressListCtrl // arguments: void // returns: void // function: void CProgressListCtrl::CProgressListCtrl() { } ////////// // CProgressListCtrl::~CProgressListCtrl // arguments: void // returns: void // function: destroys menu CProgressListCtrl::~CProgressListCtrl() { m_PopupMenu.DestroyMenu(); } ////////// // CProgressListCtrl::InsertColumn // arguments: nCol: index of new column // lpszColumnHeading: string for column heading // nFormat: text alignment // nWidth: width of column // nSubitem: subitem assosciated with column // returns: index of new column if successful,otherwise -1 // function: adds a new column to the list control int CProgressListCtrl::InsertColumn(int nCol, LPCTSTR lpszColumnHeading, int nFormat = LVCFMT_LEFT, int nWidth = -1, int nSubItem = -1) { m_ColWidths.SetAtGrow(nCol, nWidth); return CListCtrl::InsertColumn(nCol, lpszColumnHeading, nFormat, nWidth, nSubItem); } ////////// // CProgressListCtrl::InsertItem // arguments: nItem: index of new item // lpszItem: text of new item // returns: index of new item if successful,otherwise -1 // function: adds a new item to the list control int CProgressListCtrl::InsertItem(int nItem, LPCTSTR lpszItem) { m_ItemColors.InsertAt(nItem, RGB(0, 0, 0)); CString StrEmpty; m_ProjectURLs.InsertAt(nItem, StrEmpty); return CListCtrl::InsertItem(nItem, lpszItem); } ////////// // CProgressListCtrl::GetColumnWidth // arguments: nCol: column to get width of // returns: width of column // function: gets the width of a column, negative width means hidden int CProgressListCtrl::GetColumnWidth(int nCol) { if(m_ColWidths.GetAt(nCol) >= 0) { return CListCtrl::GetColumnWidth(nCol); } else { return m_ColWidths.GetAt(nCol); } } ////////// // CProgressListCtrl::SetColumnWidth // arguments: nCol: column to set width of // cx: new width of column // returns: true if successful, otherwise false // function: sets the width of the given column, negative means hidden, // also checking or unchecking the menu item appropriate to // the column's visibility BOOL CProgressListCtrl::SetColumnWidth(int nCol, int cx) { if(cx < 0) { m_PopupMenu.CheckMenuItem(nCol, MF_UNCHECKED); m_ColWidths.SetAtGrow(nCol, cx); return CListCtrl::SetColumnWidth(nCol, 0); } else { m_PopupMenu.CheckMenuItem(nCol, MF_CHECKED); m_ColWidths.SetAtGrow(nCol, cx); return CListCtrl::SetColumnWidth(nCol, cx); } } ////////// // CProgressListCtrl::DeleteItem // arguments: nItem: item index // returns: true if sucessful, false otherwise // function: deletes given item from the list control BOOL CProgressListCtrl::DeleteItem(int nItem) { int i, si; // remove array info m_ItemColors.RemoveAt(nItem); CString empty; m_ProjectURLs.RemoveAt(nItem); CString strbuf; CProgressCtrl* pProgCtrl = NULL; // go through all the subitems and see if they have a progess control for(si = 0; si < GetHeaderCtrl()->GetItemCount(); si ++) { strbuf.Format("%d:%d", nItem, si); pProgCtrl = NULL; m_Progs.Lookup(strbuf, (CObject*&)pProgCtrl); if(pProgCtrl) { m_Progs.RemoveKey(strbuf); delete pProgCtrl; } } // move other progress controls up for(i = nItem + 1; i < GetItemCount(); i ++) { for(si = 0; si < GetHeaderCtrl()->GetItemCount(); si ++) { strbuf.Format("%d:%d", i, si); pProgCtrl = NULL; m_Progs.Lookup(strbuf, (CObject*&)pProgCtrl); if(pProgCtrl) { m_Progs.RemoveKey(strbuf); strbuf.Format("%d:%d", i - 1, si); m_Progs.SetAt(strbuf, pProgCtrl); } } } return CListCtrl::DeleteItem(nItem); } ////////// // CProgressListCtrl::SetItemProgress // arguments: nItem: item index // nSubitem: item's subitem to set progress for // nProg: position to set progress control // returns: void // function: sets the position of a progress control for a given // item and subitem; if there is none there, creates a new // one, otherwise sets the progress of the one it finds. void CProgressListCtrl::SetItemProgress(int nItem, int nSubItem, int nProg) { CRect rt; CString strbuf; CProgressCtrl* pProgCtrl = NULL; if(nProg < 0) nProg = 0; if(nProg > 100) nProg = 100; // lookup the position of the progress control strbuf.Format("%d:%d", nItem, nSubItem); m_Progs.Lookup(strbuf, (CObject*&)pProgCtrl); if(pProgCtrl) { // found, so just update it's progress pProgCtrl->SetPos(nProg); } else { // not found, create one and put it in the map GetSubItemRect(nItem, nSubItem, LVIR_BOUNDS, rt); pProgCtrl = new CProgressBarCtrl(); pProgCtrl->Create(PBS_SMOOTH|WS_CHILD|WS_VISIBLE, rt, this, 0); pProgCtrl->SetPos(nProg); m_Progs.SetAt(strbuf, pProgCtrl); } } ////////// // CProgressListCtrl::RepositionProgress // arguments: void // returns: void // function: repositions and resizes all progress controls appropriate // to the current window, fitting them into their given subitem. void CProgressListCtrl::RepositionProgress() { int nItem, nSubItem; CRect rt, hrt; CString strbuf; CProgressCtrl* pProgCtrl = NULL; GetHeaderCtrl()->GetClientRect(hrt); // iterate through each progress control POSITION pos = m_Progs.GetStartPosition(); while (pos != NULL) { // look at the progress control and move it m_Progs.GetNextAssoc(pos, strbuf, (CObject*&)pProgCtrl); sscanf(strbuf.GetBuffer(0), "%d:%d", &nItem, &nSubItem); GetSubItemRect(nItem, nSubItem, LVIR_BOUNDS, rt); rt.top ++; rt.left ++; rt.bottom --; rt.right --; // if it's over the header, move it to where it can't be seen if(rt.top < hrt.bottom) { rt.top = -10; rt.bottom = 0; } pProgCtrl->MoveWindow(rt, false); } } ////////// // CProgressListCtrl::SwapItems // arguments: nItem1: index of the first item to swap // nItem2: index of the second item to swap // returns: void // function: swaps all relevant information of the two given items. this // includes text and progress controls of subitems and // item data void CProgressListCtrl::SwapItems(int nItem1, int nItem2) { int nCols = GetHeaderCtrl()->GetItemCount(); CProgressCtrl* pProgCtrl1; CProgressCtrl* pProgCtrl2; CString StrTxt1, StrTxt2; DWORD dwData1, dwData2; int nSubItem; // check item indicies if(nItem1 >= GetItemCount() || nItem2 >= GetItemCount()) { return; } // swap url data bool bOk1 = false, bOk2 = false; CString StrTemp1, StrTemp2, StrEmpty; if(nItem1 < m_ProjectURLs.GetSize()) { StrTemp1 = m_ProjectURLs.GetAt(nItem1); bOk1 = true; } if(nItem2 < m_ProjectURLs.GetSize()) { StrTemp2 = m_ProjectURLs.GetAt(nItem2); bOk2 = true; } if(bOk1) { m_ProjectURLs.SetAtGrow(nItem2, StrTemp1); } else { m_ProjectURLs.SetAtGrow(nItem2, StrEmpty); } if(bOk2) { m_ProjectURLs.SetAtGrow(nItem1, StrTemp2); } else { m_ProjectURLs.SetAtGrow(nItem1, StrEmpty); } // swap color data bOk1 = false; bOk2 = false; COLORREF tempclr1, tempclr2, emptyclr = RGB(0, 0, 0); if(nItem1 < m_ItemColors.GetSize()) { tempclr1 = m_ItemColors.GetAt(nItem1); bOk1 = true; } if(nItem2 < m_ItemColors.GetSize()) { tempclr2 = m_ItemColors.GetAt(nItem2); bOk2 = true; } if(bOk1) { m_ItemColors.SetAtGrow(nItem2, tempclr1); } else { m_ItemColors.SetAtGrow(nItem2, emptyclr); } if(bOk2) { m_ItemColors.SetAtGrow(nItem1, tempclr2); } else { m_ItemColors.SetAtGrow(nItem1, emptyclr); } // swap indices dwData1 = GetItemData(nItem1); dwData2 = GetItemData(nItem2); SetItemData(nItem1, dwData2); SetItemData(nItem2, dwData1); for(nSubItem = 0; nSubItem < nCols; nSubItem ++) { // swap text StrTxt1 = GetItemText(nItem1, nSubItem); StrTxt2 = GetItemText(nItem2, nSubItem); SetItemText(nItem1, nSubItem, StrTxt2); SetItemText(nItem2, nSubItem, StrTxt1); // swap progress control if found StrTxt1.Format("%d:%d", nItem1, nSubItem); StrTxt2.Format("%d:%d", nItem2, nSubItem); pProgCtrl1 = NULL; pProgCtrl2 = NULL; m_Progs.Lookup(StrTxt1, (CObject*&)pProgCtrl1); m_Progs.Lookup(StrTxt2, (CObject*&)pProgCtrl2); if(pProgCtrl1) { m_Progs.RemoveKey(StrTxt2); m_Progs.SetAt(StrTxt2, (CObject*&)pProgCtrl1); } if(pProgCtrl2) { m_Progs.RemoveKey(StrTxt1); m_Progs.SetAt(StrTxt1, (CObject*&)pProgCtrl2); } } } ////////// // CProgressListCtrl::Sort // arguments: nSubItem: subitem to sort by // nOrder: the order to sort by, either SORT_ASCEND or SORT_DESCEND // returns: void // function: sorts items by the given subitem into the given order. if there // is a progress control, converts the position to a string for // comparison, otherwise sorts by the string at that subitem. void CProgressListCtrl::Sort(int nSubItem, int nOrder) { int i, j, min, z; CString Stri, Strj; CProgressCtrl* pProgCtrli = NULL; CProgressCtrl* pProgCtrlj = NULL; // check subitem is in bounds if(nSubItem >= GetHeaderCtrl()->GetItemCount()) { return; } // run selection sort for now int items = GetItemCount(); for(z = 0; z < GetItemCount(); z ++) { for(i = 0; i < items-1; i ++) { min = i; for(j = i+1; j < items; j ++) { // see if there is a progress control here, and set its // progress as the comparison string, otherwise, // just get the text Stri.Format("%d:%d", i, nSubItem); Strj.Format("%d:%d", j, nSubItem); pProgCtrli = NULL; pProgCtrlj = NULL; m_Progs.Lookup(Stri, (CObject*&)pProgCtrli); m_Progs.Lookup(Strj, (CObject*&)pProgCtrlj); if(pProgCtrli) { Stri.Format("%0.3d", pProgCtrli->GetPos()); } else { Stri = GetItemText(i, nSubItem); } if(pProgCtrlj) { Strj.Format("%0.3d", pProgCtrlj->GetPos()); } else { Strj = GetItemText(j, nSubItem); } if(nOrder == SORT_ASCEND && strcmp(Stri, Strj) > 0) min = j; if(nOrder == SORT_DESCEND && strcmp(Stri, Strj) < 0) min = j; } SwapItems(i, min); } } RepositionProgress(); } ////////// // CProgressListCtrl::SwapColumnVisibility // arguments: nCol: the column whose visibility to swap // returns: void // function: if the given column is visible, makes it invisible, otherwise // makes it visible. void CProgressListCtrl::SwapColumnVisibility(int nCol) { int nOldWidth; CHeaderCtrl* header = GetHeaderCtrl(); if(header && nCol < header->GetItemCount()) { nOldWidth = m_ColWidths.GetAt(nCol); if(nOldWidth < 0) { CListCtrl::SetColumnWidth(nCol, -1 * (nOldWidth - 1)); m_ColWidths.SetAtGrow(nCol, -1 * (nOldWidth - 1)); m_PopupMenu.CheckMenuItem(nCol, MF_CHECKED); } else { CListCtrl::SetColumnWidth(nCol, 0); m_ColWidths.SetAtGrow(nCol, -1 * (nOldWidth + 1)); m_PopupMenu.CheckMenuItem(nCol, MF_UNCHECKED); } } } ////////// // CProgressListCtrl::SetItemColor // arguments: nItem: item whose color is to be set // crNew: the new color // returns: void // function: causes an item to be displayed in the given color void CProgressListCtrl::SetItemColor(int nItem, COLORREF newclr) { m_ItemColors.SetAtGrow(nItem, newclr); } ////////// // CProgressListCtrl::SetProjectURL // arguments: nItem: the item to set the url for // szUrl: the url for the link // returns: void // function: sets the url for a project's link, causing the text of // the first subitem for the given item to be displayed // as a link void CProgressListCtrl::SetProjectURL(int nItem, char* szUrl) { CString StrUrl; StrUrl.Format("%s", szUrl); m_ProjectURLs.SetAtGrow(nItem, StrUrl); } ////////// // CProgressListCtrl::GetTextRect // arguments: nItem: item to get the rect of // nSubItem: subitem to get the rect of // lpRect: pointer to rect to fill with result // returns: void // function: calculates the rect of the text for the given // item and subitem void CProgressListCtrl::GetTextRect(int nItem, int nSubItem, LPRECT lpRect) { CRect hrt, vrt; int left, top, right, bottom; GetItemRect(nItem, vrt, LVIR_BOUNDS); GetHeaderCtrl()->GetItemRect(nSubItem, hrt); left = hrt.left + 3; top = vrt.top + 1; right = hrt.left + GetStringWidth(GetItemText(nItem, nSubItem)) + 5; if(hrt.right < right) right = hrt.right - 5; bottom = vrt.bottom - 1; if(right < left) right = left; if(bottom < top) bottom = top; lpRect->left = left; lpRect->top = top; lpRect->right = right; lpRect->bottom = bottom; } ////////// // CProgressListCtrl::OnCreate // arguments: lpcs: a pointer to the create structure // returns: 0 if successful, otherwise -1 // function: sets up the context menu and subclasses the header. int CProgressListCtrl::OnCreate(LPCREATESTRUCT lpcs) { if(CListCtrl::OnCreate(lpcs) == -1) { return -1; } // load popup menu m_PopupMenu.CreatePopupMenu(); for(int i = 0; i < MAX_COLS; i ++) { if(g_szColumnTitles[GetDlgCtrlID()][i]) { m_PopupMenu.AppendMenu(MF_STRING, i, g_szColumnTitles[GetDlgCtrlID()][i]); m_PopupMenu.CheckMenuItem(i, MF_CHECKED); } } // subclass header CHeaderCtrl* pHeader = GetHeaderCtrl(); if(pHeader) { HWND hWnd = pHeader->GetSafeHwnd(); if(hWnd) { m_Header.SubclassWindow(hWnd); } } m_OldFont = NULL; m_nSort = 0; return 0; } ////////// // CProgressListCtrl::OnCustomDraw // arguments: pNMHDR: pointer to notification message header // pResult: pointer to result // returns: void // function: handles special cases of drawing text, including changing // an item's color or displaying project names as links void CProgressListCtrl::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult) { NMLVCUSTOMDRAW* pLVCD = (NMLVCUSTOMDRAW*)pNMHDR; *pResult = CDRF_DODEFAULT; if(pLVCD->nmcd.dwDrawStage == CDDS_PREPAINT) { // before painting, get notifications for each item *pResult = CDRF_NOTIFYITEMDRAW; } else if(pLVCD->nmcd.dwDrawStage == CDDS_ITEMPREPAINT) { // before item, get notifications for each subitem *pResult = CDRF_NOTIFYSUBITEMDRAW; } else if(pLVCD->nmcd.dwDrawStage == (CDDS_ITEMPREPAINT | CDDS_SUBITEM)) { // before subitem, set font pLVCD->clrText = RGB(0, 0, 0); CDC* cdc = CDC::FromHandle(pLVCD->nmcd.hdc); CFont* curFont = cdc->GetCurrentFont(); LOGFONT lf; curFont->GetLogFont(&lf); if(pLVCD->nmcd.dwItemSpec < m_ItemColors.GetSize()) { pLVCD->clrText = m_ItemColors.GetAt(pLVCD->nmcd.dwItemSpec); } if(pLVCD->nmcd.dwItemSpec < m_ProjectURLs.GetSize() && !m_ProjectURLs.GetAt(pLVCD->nmcd.dwItemSpec).IsEmpty()) { if(pLVCD->iSubItem == 0) { lf.lfUnderline = true; pLVCD->clrText = RGB(0, 0, 255); } } CFont* pNewFont = new CFont; pNewFont->CreateFontIndirect(&lf); m_OldFont = cdc->SelectObject(pNewFont); *pResult = CDRF_NOTIFYPOSTPAINT; } else if(pLVCD->nmcd.dwDrawStage == (CDDS_ITEMPOSTPAINT | CDDS_SUBITEM)) { // after subitem, restore font CDC* pDC = CDC::FromHandle(pLVCD->nmcd.hdc); m_OldFont = pDC->SelectObject(m_OldFont); m_OldFont->DeleteObject(); delete m_OldFont; m_OldFont = NULL; *pResult = CDRF_DODEFAULT; } } ////////// // CProgressListCtrl::OnDestroy // arguments: void // returns: void // function: deletes progress controls void CProgressListCtrl::OnDestroy() { CString sKey; CProgressCtrl* pProgCtrl = NULL; // iterate through each progress control POSITION pos = m_Progs.GetStartPosition(); while (pos != NULL) { // remove the control and delete it m_Progs.GetNextAssoc(pos, sKey, (CObject*&)pProgCtrl); m_Progs.RemoveKey(sKey); delete pProgCtrl; } } ////////// // CProgressListCtrl::OnSetCursor // arguments: pWnd: window containing the cursor // nHitTest: hit test area code // message: mouse message number // returns: true if the message should not be processed further, false otherwise // function: checks if the cursor is over a link, if so, // changes it to the hand BOOL CProgressListCtrl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { CPoint point; GetCursorPos(&point); ScreenToClient(&point); CRect hit; for(int i = 0; i < GetItemCount(); i ++) { if(i < m_ProjectURLs.GetSize() && !m_ProjectURLs.GetAt(i).IsEmpty()) { GetTextRect(i, 0, &hit); if(hit.PtInRect(point)) { HCURSOR hand = LoadCursor(NULL, IDC_HAND); if(hand) { SetCursor(hand); return TRUE; } } } } return CWnd::OnSetCursor(pWnd, nHitTest, message); } ////////// // CProgressListCtrl::OnLButtonDown // arguments: nFlags: message flags (keys down) // point: mouse's point // returns: void // function: stops control from highlighting items, opens links void CProgressListCtrl::OnLButtonDown(UINT nFlags, CPoint point) { CRect hit; for(int i = 0; i < GetItemCount(); i ++) { if(i < m_ProjectURLs.GetSize() && !m_ProjectURLs.GetAt(i).IsEmpty()) { GetTextRect(i, 0, &hit); if(hit.PtInRect(point)) { ShellExecute(GetSafeHwnd(), "open", m_ProjectURLs.GetAt(i).GetBuffer(0), "", "", SW_SHOWNORMAL); } } } } ////////// // CProgressListCtrl::OnRButtonDown // arguments: nFlags: message flags (keys down) // point: mouse's point // returns: void // function: if user clicks on a header, show its context menu, otherwise // do nothing. void CProgressListCtrl::OnRButtonDown(UINT nFlags, CPoint point) { ClientToScreen(&point); // see if user clicked on header and do its popup menu CHeaderCtrl* header = GetHeaderCtrl(); if(header) { CRect rt; header->GetWindowRect(&rt); if(rt.PtInRect(point)) { m_PopupMenu.TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON, point.x, point.y, this); return; } } CWnd* pParentWnd = GetParent(); if(pParentWnd) { MapWindowPoints(pParentWnd, &point, 1); WPARAM wParam = nFlags; LPARAM lParam = MAKELPARAM(point.x, point.y); pParentWnd->SendMessage(WM_RBUTTONDOWN, wParam, lParam); } //CListCtrl::OnRButtonDown(nFlags, point); } ////////// // CProgressListCtrl::OnNotify // arguments: wParam: notification's wparam // lParam: notification's lparam // pResult: pointer to result of notification // returns: true if the notification is processed, otherwise false // function: handles notifications from children, including: // user clicking a header sorts by that column. // user double clicking a header does not resize it. // user tracking a hidden column does not resize it. BOOL CProgressListCtrl::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) { HD_NOTIFY* phdn = (HD_NOTIFY*)lParam; // notification from header, user has clicked a header if(phdn->hdr.code == HDN_ITEMCLICKA || phdn->hdr.code == HDN_ITEMCLICKW) { int newSort = phdn->iItem + 1; // if this header was clicked before, alternate sorts, other wise just sort if(newSort == abs(m_nSort)) { m_nSort *= -1; if(m_nSort < 0) Sort(abs(m_nSort)-1, SORT_DESCEND); else Sort(abs(m_nSort)-1, SORT_ASCEND); } else { m_nSort = newSort; Sort(abs(m_nSort)-1, SORT_ASCEND); } } // notification from header, user has double clicked a column divider if(phdn->hdr.code == HDN_DIVIDERDBLCLICKA || phdn->hdr.code == HDN_DIVIDERDBLCLICKW) { // stop the column from resizing *pResult = TRUE; return TRUE; } // notification from header, user has started tracking a header if(phdn->hdr.code == HDN_BEGINTRACKA || phdn->hdr.code == HDN_BEGINTRACKW) { // stop the header from tracking int nCol = phdn->iItem; if(m_ColWidths.GetAt(nCol) < 0) { *pResult = TRUE; return TRUE; } } return CListCtrl::OnNotify(wParam, lParam, pResult); } ////////// // CProgressListCtrl::OnPaint // arguments: void // returns: void // function: repositions progress bars. void CProgressListCtrl::OnPaint() { RepositionProgress(); CListCtrl::OnPaint(); // iterate through each progress control CProgressCtrl* progCtrl = NULL; CString str; POSITION pos = m_Progs.GetStartPosition(); while (pos != NULL) { // remove the control and delete it m_Progs.GetNextAssoc(pos, str, (CObject*&)progCtrl); progCtrl->RedrawWindow(NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_NOERASE); } } ////////// // CProgressListCtrl::OnCommand // arguments: wParam: command's wparam // lParam: command's lparam // returns: true if the command is processed, otherwise false // function: assumes this command is from the context menu and the wparam // is the column number to swap visibility of. BOOL CProgressListCtrl::OnCommand(WPARAM wParam, LPARAM lParam) { SwapColumnVisibility(wParam); return CListCtrl::OnCommand(wParam, lParam); } ///////////////////////////////////////////////////////////////////////// // CPieChartCtrl member functions BEGIN_MESSAGE_MAP(CPieChartCtrl, CWnd) ON_WM_PAINT() END_MESSAGE_MAP() ////////// // CPieChartCtrl::CPieChartCtrl // arguments: void // returns: void // function: initializes members CPieChartCtrl::CPieChartCtrl() { m_xTotal = 0; m_pFont = NULL; } ////////// // CPieChartCtrl::AddPiece // arguments: szLabel: label for the piece // clr: color of the piece // xValue: the initial value for the piece // returns: void // function: adds a piece to the pie void CPieChartCtrl::AddPiece(LPTSTR szLabel, COLORREF clr, double xValue) { if(xValue < 0) xValue = 0; m_xValues.Add(xValue); m_colors.Add(clr); CString strLabel; strLabel.Format("%s", szLabel); m_strLabels.Add(strLabel); } ////////// // CPieChartCtrl::SetPiece // arguments: nIndex: index of piece to change // xValue: the new value for the piece // returns: void // function: changes the piece's value void CPieChartCtrl::SetPiece(int nIndex, double xValue) { if(nIndex < 0 || nIndex >= m_xValues.GetSize()) return; if(xValue < 0) xValue = 0; m_xValues.SetAt(nIndex, xValue); } ////////// // CPieChartCtrl::Create // arguments: dwStyle: the style of control to create // rect: size and position // pParentWnd: control's parent window // nID: control's id // returns: true if successful, otherwise false // function: creates this control BOOL CPieChartCtrl::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID) { CString strWndClass = AfxRegisterWndClass (0, NULL, (HBRUSH)GetStockObject(WHITE_BRUSH), NULL); return CWnd::Create(strWndClass, NULL, dwStyle, rect, pParentWnd, nID); } ////////// // CPieChartCtrl::DrawPiece // arguments: pDC: pointer to dc to draw in // xStartAngle: starting angle of piece // xEndAngle: ending angle of piece // returns: void // function: draws a pie piece in the dc void CPieChartCtrl::DrawPiePiece(CDC* pDC, double xStartAngle, double xEndAngle) { if(xEndAngle - xStartAngle <= 0.05) return; // gdi objects needed CRect rt, rt2; CRgn rellipsehi, rellipselow, rrect, rdepthcurve, rdepth; CPoint pt1, pt2, pt3, pt4; CRgn rpie, rangle, rellipse; CPoint poly[8]; // set up coordinates GetWindowRect(&rt); ScreenToClient(&rt); CPoint cp; int major = (int)((rt.Width() - 2 * PIE_BUFFER) * 0.5); int minor = (int)((rt.Height() - 2 * PIE_BUFFER) * 0.25); int maxmajor = pDC->GetDeviceCaps(HORZRES) * PIE_MAJOR_MAX; int maxminor = pDC->GetDeviceCaps(VERTRES) * PIE_MINOR_MAX; if(major > maxmajor) major = maxmajor; if(minor > maxminor) minor = maxminor; int depth = minor * PIE_DEPTH; cp.x = rt.Width() * 0.5; cp.y = rt.Height() - minor - PIE_BUFFER - depth; rt.SetRect(cp.x - major, cp.y - minor, cp.x + major, cp.y + minor); rt2.SetRect(cp.x - major, cp.y - minor + depth, cp.x + major, cp.y + minor + depth); // draw elliptical part of piece // set up coordinates poly[0].x = cp.x; poly[0].y = cp.y; EllipsePoint(&rt, xStartAngle + (xEndAngle - xStartAngle) * 0.00f, &poly[1]); CirclePoint(&cp, major * 2, xStartAngle + (xEndAngle - xStartAngle) * 0.00f, &poly[2]); CirclePoint(&cp, major * 2, xStartAngle + (xEndAngle - xStartAngle) * 0.25f, &poly[3]); CirclePoint(&cp, major * 2, xStartAngle + (xEndAngle - xStartAngle) * 0.50f, &poly[4]); CirclePoint(&cp, major * 2, xStartAngle + (xEndAngle - xStartAngle) * 0.75f, &poly[5]); CirclePoint(&cp, major * 2, xStartAngle + (xEndAngle - xStartAngle) * 1.00f, &poly[6]); EllipsePoint(&rt, xStartAngle + (xEndAngle - xStartAngle) * 1.00f, &poly[7]); // filled part rellipse.CreateEllipticRgnIndirect(&rt); rangle.CreatePolygonRgn(poly, 8, ALTERNATE); rpie.CreateRectRgnIndirect(&rt); rpie.CombineRgn(&rellipse, &rangle, RGN_AND); pDC->FillRgn(&rpie, pDC->GetCurrentBrush()); // outline pDC->MoveTo(rt.CenterPoint()); pDC->LineTo(poly[1]); pDC->Arc(&rt, poly[1], poly[7]); pDC->MoveTo(poly[7]); pDC->LineTo(rt.CenterPoint()); // clean up rellipse.DeleteObject(); rangle.DeleteObject(); rpie.DeleteObject(); // draw depth part of pie piece if needed if(xStartAngle >= 180 || xEndAngle >= 180) { // set up coordinates int xLowerAngle = 180; if(xStartAngle > 180) xLowerAngle = xStartAngle; int xHigherAngle = 360; if(xEndAngle < 360) xHigherAngle = xEndAngle; EllipsePoint(&rt, xLowerAngle, &pt1); EllipsePoint(&rt, xHigherAngle, &pt2); EllipsePoint(&rt2, xLowerAngle, &pt3); EllipsePoint(&rt2, xHigherAngle, &pt4); if(xStartAngle > 180) { pt1.x = poly[1].x; pt3.x = poly[1].x; } if(xEndAngle < 360) { pt2.x = poly[7].x; pt4.x = poly[7].x; } // filled part rellipsehi.CreateEllipticRgnIndirect(&rt); rellipselow.CreateEllipticRgnIndirect(&rt2); rrect.CreateRectRgn(pt1.x, rt.top, pt4.x, rt2.bottom); rdepthcurve.CreateRectRgnIndirect(&rt2); rdepthcurve.CombineRgn(&rellipselow, &rellipsehi, RGN_DIFF); rdepth.CreateRectRgnIndirect(&rt2); rdepth.CombineRgn(&rdepthcurve, &rrect, RGN_AND); pDC->FillRgn(&rdepth, pDC->GetCurrentBrush()); // ouline pDC->Arc(&rt, pt1, pt2); pDC->Arc(&rt2, pt3, pt4); pDC->MoveTo(pt1); pDC->LineTo(pt3); pDC->MoveTo(pt4); pDC->LineTo(pt2); // clean up rellipsehi.DeleteObject(); rellipselow.DeleteObject(); rdepthcurve.DeleteObject(); rdepth.DeleteObject(); } } ////////// // CPieChartCtrl::CirclePoint // arguments: center: center point of circle // nRadius: radius of circle // xAngle: angle of radius // pResult: pointer to CPoint to put result in // returns: void // function: calculates the point on the circle at the given angle void CPieChartCtrl::CirclePoint(CPoint* center, int nRadius, double xAngle, CPoint* pResult) { pResult->x = center->x + nRadius * cos(xAngle * (PI / 180)); pResult->y = center->y - nRadius * sin(xAngle * (PI / 180)); } ////////// // CPieChartCtrl::EllipsePoint // arguments: rt: pointer to rect of ellipse // xAngle: angle of radius // pResult: pointer to CPoint to put result in // returns: void // function: calculates the point on the ellipse in the given rect at // the given angle void CPieChartCtrl::EllipsePoint(CRect* rt, double xAngle, CPoint* pResult) { pResult->x = rt->CenterPoint().x + (rt->Width() / 2) * cos(xAngle * (PI / 180)); pResult->y = rt->CenterPoint().y - (rt->Height() / 2) * sin(xAngle * (PI / 180)); } ////////// // CPieChartCtrl::SetFont // arguments: pFont: pointer to font to set // returns: void // function: sets this control's font void CPieChartCtrl::SetFont(CFont* pFont) { m_pFont = pFont; } ////////// // CPieChartCtrl::SetTotal // arguments: xTotal: the total amount of the pie chart // returns: void // function: sets the tag for data, which is a string that will be displayed // after the numbers in the label void CPieChartCtrl::SetTotal(double xTotal) { if(xTotal >= 0) m_xTotal = xTotal; } ////////// // CPieChartCtrl::OnPaint // arguments: void // returns: void // function: draws the control by drawing the labels and pie pieces for // each piece of the pie void CPieChartCtrl::OnPaint() { CWnd::OnPaint(); // no pieces, so dont do anything if(m_xValues.GetSize() == 0) return; // gdi objects needed CClientDC cdc(this); CRect rt; CDC MemDC; CBitmap MemBmp; CBrush MemBrush; CPen MemPen; CBitmap* pOldBmp = NULL; CBrush* pOldBrush = NULL; CPen* pOldPen = NULL; CFont* pOldFont = NULL; // create offscreen buffer GetClientRect(&rt); MemDC.CreateCompatibleDC(&cdc); MemBmp.CreateCompatibleBitmap(&cdc, rt.Width(), rt.Height()); MemPen.CreatePen(PS_SOLID, 0, RGB(0, 0, 0)); // select gdi objects pOldBmp = MemDC.SelectObject(&MemBmp); pOldPen = MemDC.SelectObject(&MemPen); pOldFont = MemDC.SelectObject(m_pFont); MemDC.FillSolidRect(&rt, RGB(255, 255, 255)); // go through each xPercent and draw its label and pie double xSoFar = 0; CRect wndrect; CRect textrect; GetWindowRect(&wndrect); for(int i = 0; i < m_xValues.GetSize(); i ++) { MemBrush.CreateSolidBrush(m_colors.GetAt(i)); pOldBrush = MemDC.SelectObject(&MemBrush); int texti = i; if(texti == 2) texti = 3; else if(texti == 3) texti = 2; // display color box and label if(PIE_BUFFER + 20 + texti * 20 < wndrect.Height() / 2) { textrect.SetRect(PIE_BUFFER + 0, PIE_BUFFER + texti * 20 + 4, PIE_BUFFER + 11, PIE_BUFFER + 20 + texti * 20 - 4); MemDC.FillRect(&textrect, &MemBrush); MemDC.MoveTo(textrect.left, textrect.top); MemDC.LineTo(textrect.right, textrect.top); MemDC.LineTo(textrect.right, textrect.bottom); MemDC.LineTo(textrect.left, textrect.bottom); MemDC.LineTo(textrect.left, textrect.top); textrect.SetRect(PIE_BUFFER + 16, PIE_BUFFER + texti * 20, wndrect.Width() - PIE_BUFFER, PIE_BUFFER + 20 + texti * 20); CString strBytes; GetByteString(m_xValues.GetAt(i), &strBytes); CString strBuf; strBuf.Format("%s (%s)", m_strLabels.GetAt(i).GetBuffer(0), strBytes.GetBuffer(0)); MemDC.DrawText(strBuf, textrect, DT_SINGLELINE|DT_VCENTER|DT_LEFT); } // display pie piece double xPercent = 0; if(m_xTotal > 0) xPercent = m_xValues.GetAt(i) / m_xTotal; DrawPiePiece(&MemDC, xSoFar * 360, (xSoFar + xPercent) * 360); xSoFar += xPercent; MemDC.SelectObject(pOldBrush); MemBrush.DeleteObject(); } // copy offscreen buffer to screen cdc.BitBlt(0, 0, rt.Width(), rt.Height(), &MemDC, 0, 0, SRCCOPY); // clean up MemDC.SelectObject(pOldBmp); MemDC.SelectObject(pOldPen); MemDC.SelectObject(pOldFont); MemPen.DeleteObject(); MemBmp.DeleteObject(); MemBrush.DeleteObject(); MemDC.DeleteDC(); } ///////////////////////////////////////////////////////////////////////// // CMyApp member functions ////////// // CMyApp::InitInstance // arguments: void // returns: true if initialization is successful, otherwise false // function: creates and shows the main window if boinc is not running, // otherwise shows the currently running window BOOL CMyApp::InitInstance() { if(CreateMutex(NULL, false, "BOINC_MUTEX") == 0 || GetLastError() == ERROR_ALREADY_EXISTS) { UINT nShowMsg = RegisterWindowMessage("BOINC_SHOW_MESSAGE"); PostMessage(HWND_BROADCAST, nShowMsg, 0, 0); return FALSE; } m_pMainWnd = new CMainWindow(); if (gstate.minimize) m_pMainWnd->ShowWindow(SW_HIDE); else m_pMainWnd->ShowWindow(SW_SHOW); m_pMainWnd->UpdateWindow(); return TRUE; } ///////////////////////////////////////////////////////////////////////// // CMainWindow message map and member functions BEGIN_MESSAGE_MAP(CMainWindow, CWnd) ON_WM_CLOSE() ON_COMMAND(ID_FILE_SHOWGRAPHICS, OnCommandFileShowGraphics) ON_COMMAND(ID_FILE_CLEARINACTIVE, OnCommandFileClearInactive) ON_COMMAND(ID_FILE_CLEARMESSAGES, OnCommandFileClearMessages) ON_COMMAND(ID_FILE_HIDE, OnCommandHide) ON_COMMAND(ID_FILE_SUSPEND, OnCommandSuspend) ON_COMMAND(ID_FILE_RESUME, OnCommandResume) ON_COMMAND(ID_FILE_EXIT, OnCommandExit) ON_COMMAND(ID_SETTINGS_LOGIN, OnCommandSettingsLogin) ON_COMMAND(ID_SETTINGS_QUIT, OnCommandSettingsQuit) ON_COMMAND(ID_SETTINGS_PROXYSERVER, OnCommandSettingsProxyServer) ON_COMMAND(ID_HELP_ABOUT, OnCommandHelpAbout) ON_COMMAND(ID_PROJECT_RELOGIN, OnCommandProjectRelogin) ON_COMMAND(ID_PROJECT_QUIT, OnCommandProjectQuit) ON_COMMAND(ID_STATUSICON_HIDE, OnCommandHide) ON_COMMAND(ID_STATUSICON_SUSPEND, OnCommandSuspend) ON_COMMAND(ID_STATUSICON_RESUME, OnCommandResume) ON_COMMAND(ID_STATUSICON_EXIT, OnCommandExit) ON_WM_CREATE() ON_WM_RBUTTONDOWN() ON_WM_SIZE() ON_WM_SETFOCUS() ON_MESSAGE(STATUS_ICON_ID, OnStatusIcon) END_MESSAGE_MAP() ////////// // CMainWindow::CMainWindow // arguments: void // returns: void // function: registers window class, creates and poisitions window. CMainWindow::CMainWindow() { // register window class CString strWndClass = AfxRegisterWndClass (0, g_myApp.LoadStandardCursor(IDC_ARROW), (HBRUSH)(COLOR_3DFACE+1), g_myApp.LoadIcon(IDI_ICON)); // create and position window CreateEx(0, strWndClass, WND_TITLE, WS_OVERLAPPEDWINDOW|WS_EX_OVERLAPPEDWINDOW|WS_CLIPCHILDREN, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL); } ////////// // CMainWindow::TimerProc // arguments: hWnd: the window assosciated with the timer // uMsg: the WM_TIMER message // uID: the timer's id // dwTime: milliseconds since system started // returns: void // function: checks idle time, updates client state, flushed output streams, // and updates gui display. void CALLBACK CMainWindow::TimerProc(HWND hWnd, UINT uMsg, UINT uID, DWORD dwTime) { // update state and gui while(gstate.do_something()); fflush(stdout); fflush(stderr); if(g_myWnd && !g_myWnd->IsSuspended()) { // check user's idle time for suspension of apps if (gstate.global_prefs.idle_time_to_run > 0) { if (g_myWnd->GetUserIdleTime() > 1000 * gstate.global_prefs.idle_time_to_run) { gstate.user_idle = true; } else { gstate.user_idle = false; } } else { gstate.user_idle = true; } g_myWnd->UpdateGUI(&gstate); } } ////////// // CMainWindow::UpdateGUI // arguments: pcs: pointer to the client state for the gui to display // returns: void // function: syncronizes list controls with vectors in client state // and displays them. void CMainWindow::UpdateGUI(CLIENT_STATE* pcs) { CString strBuf; int i; // display projects float totalres = 0; Syncronize(&m_ProjectListCtrl, (vector*)(&pcs->projects)); for(i = 0; i < pcs->projects.size(); i ++) { totalres += pcs->projects[i]->resource_share; } for(i = 0; i < m_ProjectListCtrl.GetItemCount(); i ++) { PROJECT* pr = (PROJECT*)m_ProjectListCtrl.GetItemData(i); if(!pr) { m_ProjectListCtrl.SetItemColor(i, RGB(128, 128, 128)); m_ProjectListCtrl.SetProjectURL(i, ""); m_ProjectListCtrl.SetItemProgress(i, 4, 0); continue; } // project if(!strcmp(pr->project_name, "")) { m_ProjectListCtrl.SetItemText(i, 0, pr->master_url); } else { m_ProjectListCtrl.SetItemText(i, 0, pr->project_name); } m_ProjectListCtrl.SetProjectURL(i, pr->master_url); // account m_ProjectListCtrl.SetItemText(i, 1, pr->user_name); // total credit strBuf.Format("%0.2f", pr->user_total_credit); m_ProjectListCtrl.SetItemText(i, 2, strBuf); // avg credit strBuf.Format("%0.2f", pr->user_expavg_credit); m_ProjectListCtrl.SetItemText(i, 3, strBuf); // resource share if(totalres <= 0) { m_ProjectListCtrl.SetItemProgress(i, 4, 100); } else { m_ProjectListCtrl.SetItemProgress(i, 4, (100 * pr->resource_share) / totalres); } } // update results Syncronize(&m_ResultListCtrl, (vector*)(&pcs->results)); for(i = 0; i < m_ResultListCtrl.GetItemCount(); i ++) { RESULT* re = (RESULT*)m_ResultListCtrl.GetItemData(i); if(!re) { m_ResultListCtrl.SetItemColor(i, RGB(128, 128, 128)); m_ResultListCtrl.SetItemProgress(i, 4, 100); m_ResultListCtrl.SetItemText(i, 5, "00:00:00"); continue; } // project m_ResultListCtrl.SetItemText(i, 0, re->project->project_name); // application m_ResultListCtrl.SetItemText(i, 1, re->app->name); // name m_ResultListCtrl.SetItemText(i, 2, re->name); // cpu time ACTIVE_TASK* at = gstate.lookup_active_task_by_result(re); double cur_cpu; if (at) { cur_cpu = at->current_cpu_time; } else { if(re->state < RESULT_COMPUTE_DONE) cur_cpu = 0; else cur_cpu = re->final_cpu_time; } int cpuhour = (int)(cur_cpu / (60 * 60)); int cpumin = (int)(cur_cpu / 60) % 60; int cpusec = (int)(cur_cpu) % 60; strBuf.Format("%0.2d:%0.2d:%0.2d", cpuhour, cpumin, cpusec); m_ResultListCtrl.SetItemText(i, 3, strBuf); // progress if(!at) { m_ResultListCtrl.SetItemProgress(i, 4, 0); } else { m_ResultListCtrl.SetItemProgress(i, 4, (int)(at->fraction_done * 100)); } // to completion if(!at || at->fraction_done == 0) { double tocomp = re->wup->seconds_to_complete; cpuhour = (int)(tocomp / (60 * 60)); cpumin = (int)(tocomp / 60) % 60; cpusec = (int)(tocomp) % 60; } else { double tocomp = at->est_time_to_completion(); cpuhour = (int)(tocomp / (60 * 60)); cpumin = (int)(tocomp / 60) % 60; cpusec = (int)(tocomp) % 60; } strBuf.Format("%0.2d:%0.2d:%0.2d", cpuhour, cpumin, cpusec); m_ResultListCtrl.SetItemText(i, 5, strBuf); // status switch(re->state) { case RESULT_NEW: strBuf.Format("%s", "New"); break; case RESULT_FILES_DOWNLOADED: if (at) strBuf.Format("%s", "Running"); else strBuf.Format("%s", "Ready to run"); break; case RESULT_COMPUTE_DONE: strBuf.Format("%s", "Computation done"); break; case RESULT_READY_TO_ACK: strBuf.Format("%s", "Results uploaded"); break; case RESULT_SERVER_ACK: strBuf.Format("%s", "Acknowledged"); break; default: strBuf.Format("%s", "Error: invalid state"); break; } m_ResultListCtrl.SetItemText(i, 6, strBuf); } // update xfers Syncronize(&m_XferListCtrl, (vector*)(&pcs->pers_xfers->pers_file_xfers)); for(i = 0; i < m_XferListCtrl.GetItemCount(); i ++) { PERS_FILE_XFER* fi = (PERS_FILE_XFER*)m_XferListCtrl.GetItemData(i); if(!fi) { m_XferListCtrl.SetItemColor(i, RGB(128, 128, 128)); m_XferListCtrl.SetItemProgress(i, 2, 100); m_XferListCtrl.SetItemText(i, 3, "Completed"); continue; } // project m_XferListCtrl.SetItemText(i, 0, fi->fip->project->project_name); // file m_XferListCtrl.SetItemText(i, 1, fi->fip->name); // progress if(fi->fxp) { m_XferListCtrl.SetItemProgress(i, 2, 100 * (fi->fxp->nbytes_xfered / fi->fip->nbytes)); } else { m_XferListCtrl.SetItemProgress(i, 2, 0); } // size if(fi->fxp) { strBuf.Format("%0.0f/%0.0fKB", fi->fxp->nbytes_xfered / 1024, fi->fip->nbytes / 1024); } else { strBuf.Format("%0.0f/%0.0fKB", 0, fi->fip->nbytes / 1024); } m_XferListCtrl.SetItemText(i, 3, strBuf.GetBuffer(0)); // time double xtime; if(fi->fxp) { xtime = (double)time(0) - fi->fxp->start_time; } else { xtime = 0; } int xhour = (int)(xtime / (60 * 60)); int xmin = (int)(xtime / 60) % 60; int xsec = (int)(xtime) % 60; strBuf.Format("%0.2d:%0.2d:%0.2d", xhour, xmin, xsec); m_XferListCtrl.SetItemText(i, 4, strBuf.GetBuffer(0)); // direction m_XferListCtrl.SetItemText(i, 5, fi->fip->generated_locally?"Upload":"Download"); } // update usage double xDiskTotal; double xDiskFree; get_host_disk_info(xDiskTotal, xDiskFree); double xDiskUsed = xDiskTotal - xDiskFree; double xDiskAllow; gstate.allowed_disk_usage(xDiskAllow); double xDiskUsage; gstate.current_disk_usage(xDiskUsage); m_UsagePieCtrl.SetTotal(xDiskTotal); m_UsagePieCtrl.SetPiece(0, xDiskUsed - xDiskUsage); // Used (non-BOINC) m_UsagePieCtrl.SetPiece(1, xDiskFree - (xDiskAllow - xDiskUsage)); // Free (non-BOINC) m_UsagePieCtrl.SetPiece(2, xDiskAllow - xDiskUsage); // Free (non-BOINC) m_UsagePieCtrl.SetPiece(3, xDiskUsage); // Used (BOINC) // make icon flash if needed if(m_bMessage) { if(m_nIconState == ICON_NORMAL) { SetStatusIcon(ICON_HIGHLIGHT); } else if(m_nIconState == ICON_HIGHLIGHT) { SetStatusIcon(ICON_NORMAL); } } } ////////// // CMainWindow::MessageUser // arguments: message: message string to display // priority: string with priority of message // returns: void // function: if message is "high" priority, flashes the status icon, then // adds to message edit control. void CMainWindow::MessageUser(char* szProject, char* szMessage, char* szPriority) { if(!m_MessageListCtrl.GetSafeHwnd()) return; m_MessageListCtrl.InsertItem(0, szProject); CTime curTime = CTime::GetCurrentTime(); CString strTime; strTime = curTime.Format("%c"); m_MessageListCtrl.SetItemText(0, 1, strTime); m_MessageListCtrl.SetItemText(0, 2, szMessage); // set status icon to flash if(!strcmp(szPriority, "high") && (m_TabCtrl.GetCurSel() != MESSAGE_ID || GetForegroundWindow() != this)) { m_bMessage = true; } } ////////// // CMainWindow::IsSuspended // arguments: void // returns: true if the window is suspended, false otherwise // function: tells if the window is suspended BOOL CMainWindow::IsSuspended() { return m_bSuspend; } ////////// // CMainWindow::ShowTab // arguments: nTab: tab number to show // returns: void // function: handles everything necessary to switch to a new tab void CMainWindow::ShowTab(int nTab) { m_TabCtrl.SetCurSel(nTab); // make the selected control visible, all the rest invisible if(nTab == PROJECT_ID) { m_ProjectListCtrl.ModifyStyle(0, WS_VISIBLE); m_ResultListCtrl.ModifyStyle(WS_VISIBLE, 0); m_XferListCtrl.ModifyStyle(WS_VISIBLE, 0); m_MessageListCtrl.ModifyStyle(WS_VISIBLE, 0); m_UsagePieCtrl.ModifyStyle(WS_VISIBLE, 0); m_ProjectListCtrl.RedrawWindow(NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_FRAME); } else if(nTab == RESULT_ID) { m_ProjectListCtrl.ModifyStyle(WS_VISIBLE, 0); m_ResultListCtrl.ModifyStyle(0, WS_VISIBLE); m_XferListCtrl.ModifyStyle(WS_VISIBLE, 0); m_MessageListCtrl.ModifyStyle(WS_VISIBLE, 0); m_UsagePieCtrl.ModifyStyle(WS_VISIBLE, 0); m_ResultListCtrl.RedrawWindow(NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_FRAME); } else if(nTab == XFER_ID) { m_ProjectListCtrl.ModifyStyle(WS_VISIBLE, 0); m_ResultListCtrl.ModifyStyle(WS_VISIBLE, 0); m_XferListCtrl.ModifyStyle(0, WS_VISIBLE); m_MessageListCtrl.ModifyStyle(WS_VISIBLE, 0); m_UsagePieCtrl.ModifyStyle(WS_VISIBLE, 0); m_XferListCtrl.RedrawWindow(NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_FRAME); } else if(nTab == MESSAGE_ID) { m_ProjectListCtrl.ModifyStyle(WS_VISIBLE, 0); m_ResultListCtrl.ModifyStyle(WS_VISIBLE, 0); m_XferListCtrl.ModifyStyle(WS_VISIBLE, 0); m_MessageListCtrl.ModifyStyle(0, WS_VISIBLE); m_UsagePieCtrl.ModifyStyle(WS_VISIBLE, 0); if(m_bMessage) { m_bMessage = false; SetStatusIcon(ICON_NORMAL); } m_MessageListCtrl.RedrawWindow(NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_FRAME); } else if(nTab == USAGE_ID) { m_ProjectListCtrl.ModifyStyle(WS_VISIBLE, 0); m_ResultListCtrl.ModifyStyle(WS_VISIBLE, 0); m_XferListCtrl.ModifyStyle(WS_VISIBLE, 0); m_MessageListCtrl.ModifyStyle(WS_VISIBLE, 0); m_UsagePieCtrl.ModifyStyle(0, WS_VISIBLE); m_UsagePieCtrl.RedrawWindow(NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_FRAME); } m_TabCtrl.RedrawWindow(NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_FRAME); RedrawWindow(); } ////////// // CMainWindow::SetStatusIcon // arguments: dwMessage: hide or show the icon // returns: void // function: controls the status icon in the taskbar void CMainWindow::SetStatusIcon(DWORD dwMessage) { if(dwMessage != ICON_OFF && dwMessage != ICON_NORMAL && dwMessage != ICON_HIGHLIGHT) { return; } // if icon is in that state already, there is nothing to do if(dwMessage == m_nIconState) return; NOTIFYICONDATA icon_data; icon_data.cbSize = sizeof(icon_data); icon_data.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; icon_data.hWnd = GetSafeHwnd(); icon_data.uID = STATUS_ICON_ID; strcpy(icon_data.szTip, WND_TITLE); icon_data.uCallbackMessage = STATUS_ICON_ID; if(dwMessage == ICON_OFF) { icon_data.hIcon = NULL; Shell_NotifyIcon(NIM_DELETE, &icon_data); } else if(dwMessage == ICON_NORMAL) { icon_data.hIcon = g_myApp.LoadIcon(IDI_ICON); if(m_nIconState == ICON_OFF) { Shell_NotifyIcon(NIM_ADD, &icon_data); } else { Shell_NotifyIcon(NIM_MODIFY, &icon_data); } } else if(dwMessage == ICON_HIGHLIGHT) { icon_data.hIcon = g_myApp.LoadIcon(IDI_ICONHIGHLIGHT); if(m_nIconState == ICON_OFF) { Shell_NotifyIcon(NIM_ADD, &icon_data); } else { Shell_NotifyIcon(NIM_MODIFY, &icon_data); } } m_nIconState = dwMessage; } ////////// // CMainWindow::SaveUserSettings // arguments: void // returns: void // function: saves relevant user settings to boinc.ini void CMainWindow::SaveUserSettings() { char szPath[256]; CString strKey, strVal; GetCurrentDirectory(256, szPath); strcat(szPath, "\\boinc.ini"); int colorder[MAX_COLS]; int i; // save window size/position CRect rt; GetWindowRect(&rt); strVal.Format("%d", rt.left); WritePrivateProfileString("WINDOW", "xposition", strVal, szPath); strVal.Format("%d", rt.top); WritePrivateProfileString("WINDOW", "yposition", strVal, szPath); strVal.Format("%d", rt.Width()); WritePrivateProfileString("WINDOW", "width", strVal, szPath); strVal.Format("%d", rt.Height()); WritePrivateProfileString("WINDOW", "height", strVal, szPath); // save selected tab strVal.Format("%d", m_TabCtrl.GetCurSel()); WritePrivateProfileString("WINDOW", "selection", strVal, szPath); // save project columns m_ProjectListCtrl.GetColumnOrderArray(colorder, PROJECT_COLS); WritePrivateProfileStruct("HEADERS", "projects-order", colorder, sizeof(colorder), szPath); for(i = 0; i < m_ProjectListCtrl.GetHeaderCtrl()->GetItemCount(); i ++) { strKey.Format("projects-%d", i); strVal.Format("%d", m_ProjectListCtrl.GetColumnWidth(i)); WritePrivateProfileString("HEADERS", strKey, strVal, szPath); } // save result columns m_ResultListCtrl.GetColumnOrderArray(colorder, RESULT_COLS); WritePrivateProfileStruct("HEADERS", "results-order", colorder, sizeof(colorder), szPath); for(i = 0; i < m_ResultListCtrl.GetHeaderCtrl()->GetItemCount(); i ++) { strKey.Format("results-%d", i); strVal.Format("%d", m_ResultListCtrl.GetColumnWidth(i)); WritePrivateProfileString("HEADERS", strKey, strVal, szPath); } // save xfer columns m_XferListCtrl.GetColumnOrderArray(colorder, XFER_COLS); WritePrivateProfileStruct("HEADERS", "xfers-order", colorder, sizeof(colorder), szPath); for(i = 0; i < m_XferListCtrl.GetHeaderCtrl()->GetItemCount(); i ++) { strKey.Format("xfers-%d", i); strVal.Format("%d", m_XferListCtrl.GetColumnWidth(i)); WritePrivateProfileString("HEADERS", strKey, strVal, szPath); } // save xfer columns m_MessageListCtrl.GetColumnOrderArray(colorder, MESSAGE_COLS); WritePrivateProfileStruct("HEADERS", "messages-order", colorder, sizeof(colorder), szPath); for(i = 0; i < m_MessageListCtrl.GetHeaderCtrl()->GetItemCount(); i ++) { strKey.Format("messages-%d", i); strVal.Format("%d", m_MessageListCtrl.GetColumnWidth(i)); WritePrivateProfileString("HEADERS", strKey, strVal, szPath); } } ////////// // CMainWindow::LoadUserSettings // arguments: void // returns: void // function: loads relevant user settings from boinc.ini void CMainWindow::LoadUserSettings() { char szPath[256]; CString strKey; GetCurrentDirectory(256, szPath); strcat(szPath, "\\boinc.ini"); int i, nBuf; int colorder[MAX_COLS]; // load window size/position CRect rt; nBuf = GetPrivateProfileInt("WINDOW", "xposition", 100, szPath); rt.left = nBuf; nBuf = GetPrivateProfileInt("WINDOW", "yposition", 100, szPath); rt.top = nBuf; nBuf = GetPrivateProfileInt("WINDOW", "width", 600, szPath); rt.right = nBuf + rt.left; nBuf = GetPrivateProfileInt("WINDOW", "height", 400, szPath); rt.bottom = nBuf + rt.top; SetWindowPos(&wndNoTopMost, rt.left, rt.top, rt.Width(), rt.Height(), gstate.minimize?SWP_HIDEWINDOW:SWP_SHOWWINDOW); // load selected tab nBuf = GetPrivateProfileInt("WINDOW", "selection", 0, szPath); ShowTab(nBuf); // load project columns if(GetPrivateProfileStruct("HEADERS", "projects-order", colorder, sizeof(colorder), szPath)) { m_ProjectListCtrl.SetColumnOrderArray(PROJECT_COLS, colorder); } for(i = 0; i < m_ProjectListCtrl.GetHeaderCtrl()->GetItemCount(); i ++) { strKey.Format("projects-%d", i); nBuf = GetPrivateProfileInt("HEADERS", strKey.GetBuffer(0), DEF_COL_WIDTH, szPath); m_ProjectListCtrl.SetColumnWidth(i, nBuf); } // load result columns if(GetPrivateProfileStruct("HEADERS", "results-order", colorder, sizeof(colorder), szPath)) { m_ResultListCtrl.SetColumnOrderArray(RESULT_COLS, colorder); } for(i = 0; i < m_ResultListCtrl.GetHeaderCtrl()->GetItemCount(); i ++) { strKey.Format("results-%d", i); nBuf = GetPrivateProfileInt("HEADERS", strKey.GetBuffer(0), DEF_COL_WIDTH, szPath); m_ResultListCtrl.SetColumnWidth(i, nBuf); } // load xfer columns if(GetPrivateProfileStruct("HEADERS", "xfers-order", colorder, sizeof(colorder), szPath)) { m_XferListCtrl.SetColumnOrderArray(XFER_COLS, colorder); } for(i = 0; i < m_XferListCtrl.GetHeaderCtrl()->GetItemCount(); i ++) { strKey.Format("xfers-%d", i); nBuf = GetPrivateProfileInt("HEADERS", strKey.GetBuffer(0), DEF_COL_WIDTH, szPath); m_XferListCtrl.SetColumnWidth(i, nBuf); } // load message columns if(GetPrivateProfileStruct("HEADERS", "messages-order", colorder, sizeof(colorder), szPath)) { m_MessageListCtrl.SetColumnOrderArray(MESSAGE_COLS, colorder); } for(i = 0; i < m_MessageListCtrl.GetHeaderCtrl()->GetItemCount(); i ++) { strKey.Format("messages-%d", i); int nWidth = DEF_COL_WIDTH; if(i == 1) nWidth *= 1.5; if(i == 2) nWidth *= 4; nBuf = GetPrivateProfileInt("HEADERS", strKey.GetBuffer(0), nWidth, szPath); m_MessageListCtrl.SetColumnWidth(i, nBuf); } } ////////// // CMainWindow::GetUserIdleTime // arguments: void // returns: time the user has been idle in milliseconds // function: calls a dll function to determine the the user's idle time DWORD CMainWindow::GetUserIdleTime() { if(m_hIdleDll) { GetFn fn; fn = (GetFn)GetProcAddress(m_hIdleDll, "IdleTrackerGetLastTickCount"); if(fn) { return GetTickCount() - fn(); } else { TermFn tfn; tfn = (TermFn)GetProcAddress(m_hIdleDll, "IdleTrackerTerm"); if(tfn) { tfn(); } FreeLibrary(m_hIdleDll); m_hIdleDll = NULL; } } return 0; } ////////// // CMainWindow::Syncronize // arguments: pProg: pointer to a progress list control // pVect: pointer to a vector of pointers // returns: void // function: first, goes through the vector and adds items to the list // control for any pointers it does not already contain, then // goes through the list control and removes any pointers the // vector does not contain. void CMainWindow::Syncronize(CProgressListCtrl* pProg, vector* pVect) { int i, j; // add items to list that are not already in it for(i = 0; i < pVect->size(); i ++) { void* item = (*pVect)[i]; BOOL contained = false; for(j = 0; j < pProg->GetItemCount(); j ++) { if((DWORD)item == pProg->GetItemData(j)) { contained = true; break; } } if(!contained) { pProg->InsertItem(i, ""); pProg->SetItemData(i, (DWORD)item); } } // remove items from list that are not in vector // now just set the pointer to NULL but leave the item in the list for(i = 0; i < pProg->GetItemCount(); i ++) { DWORD item = pProg->GetItemData(i); BOOL contained = false; for(j = 0; j < pVect->size(); j ++) { if(item == (DWORD)(*pVect)[j]) { contained = true; break; } } if(!contained) { pProg->SetItemData(i, (DWORD)NULL); } } } ////////// // CMainWindow::PostNcDestroy // arguments: void // returns: void // function: takes care of window being destroyed void CMainWindow::PostNcDestroy() { delete this; } ////////// // CMainWindow::DefWindowProc // arguments: message: message received // wParam: message's wparam // lParam: message's lparam // returns: dependent on message // function: handles any messages not handled by the window previously LRESULT CMainWindow::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam) { UINT uShowMsg = RegisterWindowMessage("BOINC_SHOW_MESSAGE"); if(uShowMsg == message) { ShowWindow(SW_SHOW); SetForegroundWindow(); return 0; } return CWnd::DefWindowProc(message, wParam, lParam); } ////////// // CMainWindow::OnClose // arguments: void // returns: void // function: hides the window, keeps status icon void CMainWindow::OnClose() { ShowWindow(SW_HIDE); } ////////// // CMainWindow::OnCommandSettingsQuit // arguments: void // returns: void // function: shows the account quit dialog box void CMainWindow::OnCommandSettingsQuit() { CQuitDialog dlg(IDD_QUIT); int nResult = dlg.DoModal(); if(nResult == IDOK) { CString str; if(strcmp(gstate.projects[dlg.m_nSel]->project_name, "")) { str.Format("Are you sure you want to quit the project %s?", gstate.projects[dlg.m_nSel]->project_name); } else { str.Format("Are you sure you want to quit the project %s?", gstate.projects[dlg.m_nSel]->master_url); } if(AfxMessageBox(str, MB_YESNO, 0) == IDYES) { gstate.quit_project(dlg.m_nSel); } } } ////////// // CMainWindow::OnCommandSettingsLogin // arguments: void // returns: void // function: shows the account login dialog box void CMainWindow::OnCommandSettingsLogin() { CLoginDialog dlg(IDD_LOGIN, "", ""); int nResult = dlg.DoModal(); if(nResult == IDOK) { gstate.add_project(dlg.m_strUrl.GetBuffer(0), dlg.m_strAuth.GetBuffer(0)); } } ////////// // CMainWindow::OnCommandSettingsProxyServer // arguments: void // returns: void // function: shows the proxy dialog box void CMainWindow::OnCommandSettingsProxyServer() { CProxyDialog dlg(IDD_PROXY); int nResult = dlg.DoModal(); } ////////// // CMainWindow::OnCommandHelpAbout // arguments: void // returns: void // function: shows the about dialog box void CMainWindow::OnCommandHelpAbout() { CDialog dlg(IDD_ABOUTBOX); int nResult = dlg.DoModal(); } ////////// // CMainWindow::OnCommandFileShowGraphics // arguments: void // returns: void // function: brings up the current app's graphics window by // broadcasting a message void CMainWindow::OnCommandFileShowGraphics() { int nGraphicsMsg = RegisterWindowMessage("BOINC_GFX_MODE"); ::PostMessage(HWND_BROADCAST, nGraphicsMsg, 0, MODE_WINDOW); } ////////// // CMainWindow::OnCommandFileClearInactive // arguments: void // returns: void // function: clears inactive items from lists void CMainWindow::OnCommandFileClearInactive() { int i; for(i = 0; i < m_ProjectListCtrl.GetItemCount();) { if(!m_ProjectListCtrl.GetItemData(i)) { m_ProjectListCtrl.DeleteItem(i); } else { i ++; } } for(i = 0; i < m_ResultListCtrl.GetItemCount();) { if(!m_ResultListCtrl.GetItemData(i)) { m_ResultListCtrl.DeleteItem(i); } else { i ++; } } for(i = 0; i < m_XferListCtrl.GetItemCount();) { if(!m_XferListCtrl.GetItemData(i)) { m_XferListCtrl.DeleteItem(i); } else { i ++; } } } ////////// // CMainWindow::OnCommandFileClearMessages // arguments: void // returns: void // function: clears messages void CMainWindow::OnCommandFileClearMessages() { m_MessageListCtrl.DeleteAllItems(); } ////////// // CMainWindow::OnCommandProjectRelogin // arguments: void // returns: void // function: lets a user change the properties for an account void CMainWindow::OnCommandProjectRelogin() { if(m_nContextItem < 0 || m_nContextItem > m_ProjectListCtrl.GetItemCount()) return; PROJECT* pToRelogin = (PROJECT*)m_ProjectListCtrl.GetItemData(m_nContextItem); m_nContextItem = -1; if(!pToRelogin) return; // find project index int i; for(i = 0; i < gstate.projects.size(); i ++) { if(gstate.projects[i] == pToRelogin) break; } if(i == gstate.projects.size()) return; // get info and relogin CLoginDialog dlg(IDD_LOGIN, gstate.projects[i]->master_url, gstate.projects[i]->authenticator); int retval = dlg.DoModal(); if(retval == IDOK) { gstate.change_project(i, dlg.m_strUrl.GetBuffer(0), dlg.m_strAuth.GetBuffer(0)); } } ////////// // CMainWindow::OnCommandProjectQuit // arguments: void // returns: void // function: lets the user quit a project void CMainWindow::OnCommandProjectQuit() { if(m_nContextItem < 0 || m_nContextItem > m_ProjectListCtrl.GetItemCount()) return; PROJECT* pToQuit = (PROJECT*)m_ProjectListCtrl.GetItemData(m_nContextItem); m_nContextItem = -1; if(!pToQuit) return; // find project index int i; for(i = 0; i < gstate.projects.size(); i ++) { if(gstate.projects[i] == pToQuit) break; } if(i == gstate.projects.size()) return; // confirm and quit CString strBuf; if(strcmp(gstate.projects[i]->project_name, "")) { strBuf.Format("Are you sure you want to quit the project %s?", gstate.projects[i]->project_name); } else { strBuf.Format("Are you sure you want to quit the project %s?", gstate.projects[i]->master_url); } if(AfxMessageBox(strBuf, MB_YESNO, 0) == IDYES) { gstate.quit_project(i); } } ////////// // CMainWindow::OnCommandHide // arguments: void // returns: void // function: hides or shows the window void CMainWindow::OnCommandHide() { CMenu* pMainMenu; CMenu* pFileMenu; pMainMenu = GetMenu(); if(pMainMenu) { pFileMenu = pMainMenu->GetSubMenu(0); } if(IsWindowVisible()) { ShowWindow(SW_HIDE); if(pFileMenu) { pFileMenu->CheckMenuItem(ID_FILE_HIDE, MF_CHECKED); } } else { ShowWindow(SW_SHOW); if(pFileMenu) { pFileMenu->CheckMenuItem(ID_FILE_HIDE, MF_UNCHECKED); } } } ////////// // CMainWindow::OnCommandSuspend // arguments: void // returns: void // function: suspends client void CMainWindow::OnCommandSuspend() { gstate.suspend_requested = true; m_bSuspend = true; CMenu* pMainMenu; CMenu* pFileMenu; pMainMenu = GetMenu(); if(pMainMenu) { pFileMenu = pMainMenu->GetSubMenu(0); } if(pFileMenu) { pFileMenu->EnableMenuItem(ID_FILE_SUSPEND, MF_GRAYED); pFileMenu->EnableMenuItem(ID_FILE_RESUME, MF_ENABLED); } } ////////// // CMainWindow::OnCommandResume // arguments: void // returns: void // function: resumes client void CMainWindow::OnCommandResume() { gstate.suspend_requested = false; m_bSuspend = false; CMenu* pMainMenu; CMenu* pFileMenu; pMainMenu = GetMenu(); if(pMainMenu) { pFileMenu = pMainMenu->GetSubMenu(0); } if(pFileMenu) { pFileMenu->EnableMenuItem(ID_FILE_SUSPEND, MF_ENABLED); pFileMenu->EnableMenuItem(ID_FILE_RESUME, MF_GRAYED); } } ////////// // CMainWindow::OnCommandExit // arguments: void // returns: void // function: cleans up, closes and quits everything void CMainWindow::OnCommandExit() { // quit gstate.exit(); PostQuitMessage(0); // status icon in taskbar SetStatusIcon(ICON_OFF); // clean up and delete objects m_Font.DeleteObject(); m_TabBMP[0].DeleteObject(); m_TabBMP[1].DeleteObject(); m_TabBMP[2].DeleteObject(); m_TabBMP[3].DeleteObject(); m_TabBMP[4].DeleteObject(); m_TabIL.DeleteImageList(); m_MainMenu.DestroyMenu(); // free dll and idle detection if(m_hIdleDll) { TermFn fn; fn = (TermFn)GetProcAddress(m_hIdleDll, "IdleTrackerTerm"); if(!fn) { MessageUser("", "Error in DLL \"boinc.dll\"", "low"); } else { fn(); } FreeLibrary(m_hIdleDll); m_hIdleDll = NULL; } SaveUserSettings(); CWnd::OnClose(); } ////////// // CMainWindow::OnCreate // arguments: lpcs: a pointer to the create structure // returns: 0 if successful, otherwise -1 // function: sets window's global variable, loads resource, creates child // windows, and initializes client state and timer int CMainWindow::OnCreate(LPCREATESTRUCT lpcs) { char curDir[512]; if (CWnd::OnCreate(lpcs) == -1) { return -1; } g_myWnd = this; m_nIconState = ICON_OFF; m_bSuspend = false; m_bMessage = false; m_nContextItem = -1; // load main menu m_MainMenu.LoadMenu(IDR_MAINFRAME); SetMenu(&m_MainMenu); // create project list control m_ProjectListCtrl.Create(LVS_REPORT|WS_CHILD|WS_BORDER|WS_VISIBLE, CRect(0,0,0,0), this, PROJECT_ID); m_ProjectListCtrl.SetExtendedStyle(m_ProjectListCtrl.GetExtendedStyle()|LVS_EX_HEADERDRAGDROP|LVS_EX_FULLROWSELECT); for(int i = 0; i < PROJECT_COLS; i ++) { m_ProjectListCtrl.InsertColumn(i, g_szColumnTitles[PROJECT_ID][i], LVCFMT_LEFT, DEF_COL_WIDTH); } // create result list control m_ResultListCtrl.Create(LVS_REPORT|WS_CHILD|WS_BORDER|WS_VISIBLE, CRect(0,0,0,0), this, RESULT_ID); m_ResultListCtrl.SetExtendedStyle(m_ResultListCtrl.GetExtendedStyle()|LVS_EX_HEADERDRAGDROP|LVS_EX_FULLROWSELECT); m_ResultListCtrl.ModifyStyle(WS_VISIBLE, 0); for(i = 0; i < RESULT_COLS; i ++) { m_ResultListCtrl.InsertColumn(i, g_szColumnTitles[RESULT_ID][i], LVCFMT_LEFT, DEF_COL_WIDTH); } // create xfer list control m_XferListCtrl.Create(LVS_REPORT|WS_CHILD|WS_BORDER|WS_VISIBLE, CRect(0,0,0,0), this, XFER_ID); m_XferListCtrl.SetExtendedStyle(m_XferListCtrl.GetExtendedStyle()|LVS_EX_HEADERDRAGDROP|LVS_EX_FULLROWSELECT); m_XferListCtrl.ModifyStyle(WS_VISIBLE, 0); for(i = 0; i < XFER_COLS; i ++) { m_XferListCtrl.InsertColumn(i, g_szColumnTitles[XFER_ID][i], LVCFMT_LEFT, DEF_COL_WIDTH); } // create message edit control // create xfer list control m_MessageListCtrl.Create(LVS_REPORT|WS_CHILD|WS_BORDER|WS_VISIBLE, CRect(0,0,0,0), this, MESSAGE_ID); m_MessageListCtrl.SetExtendedStyle(m_MessageListCtrl.GetExtendedStyle()|LVS_EX_HEADERDRAGDROP|LVS_EX_FULLROWSELECT); m_MessageListCtrl.ModifyStyle(WS_VISIBLE, 0); for(i = 0; i < MESSAGE_COLS; i ++) { int width = DEF_COL_WIDTH; if(i == 1) width *= 1.5; if(i == 2) width *= 4; m_MessageListCtrl.InsertColumn(i, g_szColumnTitles[MESSAGE_ID][i], LVCFMT_LEFT, width); } // create usage pie control m_UsagePieCtrl.Create(WS_CHILD|WS_BORDER|WS_VISIBLE, CRect(0,0,0,0), this, USAGE_ID); m_UsagePieCtrl.ModifyStyle(WS_VISIBLE, 0); /* m_UsagePieCtrl.AddPiece("Free space", RGB(192, 192, 192), 0); m_UsagePieCtrl.AddPiece("Used space", RGB(0, 0, 255), 0); m_UsagePieCtrl.AddPiece("Used space (BOINC)", RGB(255, 255, 0), 0); m_UsagePieCtrl.AddPiece("Free space (BOINC)", RGB(255, 128, 0), 0); */ m_UsagePieCtrl.AddPiece("Used space (Non-BOINC)", RGB(0, 0, 255), 0); m_UsagePieCtrl.AddPiece("Free space (Non-BOINC)", RGB(255, 0, 255), 0); m_UsagePieCtrl.AddPiece("Free space (BOINC)", RGB(192, 0, 192), 0); m_UsagePieCtrl.AddPiece("Used space (BOINC)", RGB(0, 0, 192), 0); // set up image list for tab control m_TabIL.Create(16, 16, ILC_COLOR8|ILC_MASK, 5, 1); m_TabBMP[0].LoadBitmap(IDB_PROJ); m_TabIL.Add(&m_TabBMP[0], RGB(255, 0, 255)); m_TabBMP[1].LoadBitmap(IDB_RESULT); m_TabIL.Add(&m_TabBMP[1], RGB(255, 0, 255)); m_TabBMP[2].LoadBitmap(IDB_XFER); m_TabIL.Add(&m_TabBMP[2], RGB(255, 0, 255)); m_TabBMP[3].LoadBitmap(IDB_MESS); m_TabIL.Add(&m_TabBMP[3], RGB(255, 0, 255)); m_TabBMP[4].LoadBitmap(IDB_USAGE); m_TabIL.Add(&m_TabBMP[4], RGB(255, 0, 255)); // create tab control m_TabCtrl.Create(TCS_FIXEDWIDTH|TCS_BUTTONS|TCS_FLATBUTTONS|TCS_FOCUSNEVER|WS_CHILD|WS_VISIBLE, CRect(0,0,0,0), this, TAB_ID); m_TabCtrl.SetImageList(&m_TabIL); m_TabCtrl.InsertItem(1, "Projects", 0); m_TabCtrl.InsertItem(2, "Work", 1); m_TabCtrl.InsertItem(3, "Transfers", 2); m_TabCtrl.InsertItem(4, "Messages", 3); m_TabCtrl.InsertItem(5, "Usage", 4); // make all fonts the same nice font CFont* pFont; pFont = m_ProjectListCtrl.GetFont(); LOGFONT lf; ZeroMemory(&lf, sizeof(LOGFONT)); pFont->GetLogFont(&lf); m_Font.CreateFontIndirect(&lf); m_TabCtrl.SetFont(&m_Font); m_UsagePieCtrl.SetFont(&m_Font); // Determine the OS version UtilInitOSVersion(); // Set the current directory to the default UtilGetRegStr("ClientDir", curDir); if (strlen(curDir)) SetCurrentDirectory(curDir); // add status icon to taskbar SetStatusIcon(ICON_NORMAL); // take care of other things // NetOpen(); // Redirect stdout and stderr to files freopen(STDOUT_FILE_NAME, "w", stdout); freopen(STDERR_FILE_NAME, "w", stderr); // Check what (if any) activities should be logged read_log_flags(); LPSTR command_line; char* argv[100]; int argc; command_line = GetCommandLine(); argc = parse_command_line( command_line, argv ); gstate.parse_cmdline(argc, argv); int retval = gstate.init(); if (retval) { OnCommandExit(); return 0; } SetTimer(ID_TIMER, 1000, TimerProc); // load dll and start idle detection m_hIdleDll = LoadLibrary("boinc.dll"); if(!m_hIdleDll) { MessageUser("", "Can't load \"boinc.dll\", will not be able to determine idle time", "high"); } else { InitFn fn; fn = (InitFn)GetProcAddress(m_hIdleDll, "IdleTrackerInit"); if(!fn) { MessageUser("", "Error in DLL \"boinc.dll\", will not be able to determine idle time", "low"); FreeLibrary(m_hIdleDll); m_hIdleDll = NULL; } else { if(!fn()) { MessageUser("", "Error in DLL \"boinc.dll\", will not be able to determine idle time", "low"); FreeLibrary(m_hIdleDll); m_hIdleDll = NULL; } } } LoadUserSettings(); UpdateGUI(&gstate); OnCommandResume(); return 0; } ////////// // CMainWindow::OnNotify // arguments: wParam: notification's wparam // lParam: notification's lparam // pResult: pointer to result of notification // returns: true if the notification is processed, otherwise false // function: handles notifications from children, including: // user selecting a new tab sets display to selected tab's control BOOL CMainWindow::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) { HD_NOTIFY* phdn = (HD_NOTIFY*)lParam; // notification from tab control, user is changing the selection if(phdn->hdr.code == TCN_SELCHANGE) { int newTab = m_TabCtrl.GetCurSel(); ShowTab(newTab); } return CWnd::OnNotify(wParam, lParam, pResult); } ////////// // CMainWindow::OnRButtonDown // arguments: nFlags: message flags (keys down) // point: mouse's point // returns: void // function: shows context menu for list items void CMainWindow::OnRButtonDown(UINT nFlags, CPoint point) { CMenu WholeMenu; CMenu* pContextMenu = NULL; GetCursorPos(&point); CRect rt; CListCtrl* pMenuCtrl = NULL; int nMenuId = -1; if(m_ProjectListCtrl.IsWindowVisible()) { pMenuCtrl = &m_ProjectListCtrl; nMenuId = PROJECT_MENU; } else if(m_ResultListCtrl.IsWindowVisible()) { pMenuCtrl = &m_ResultListCtrl; nMenuId = RESULT_MENU; } else if(m_XferListCtrl.IsWindowVisible()) { pMenuCtrl = &m_XferListCtrl; nMenuId = XFER_MENU; } if(pMenuCtrl) { for(int i = 0; i < pMenuCtrl->GetItemCount(); i ++) { pMenuCtrl->GetItemRect(i, &rt, LVIR_BOUNDS); pMenuCtrl->ClientToScreen(&rt); if(rt.PtInRect(point)) { WholeMenu.LoadMenu(IDR_CONTEXT); pContextMenu = WholeMenu.GetSubMenu(nMenuId); if(pContextMenu) { pContextMenu->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON, point.x, point.y, this); m_nContextItem = i; } break; } } } //CWnd::OnRButtonDown(nFlags, point); } ////////// // CMainWindow::OnFocus // arguments: pOldWnd: pointer to previous window that had focus // returns: void // function: if there is a message for the user when this window // gets the focus, selects the message tab void CMainWindow::OnSetFocus(CWnd* pOldWnd) { if(m_TabCtrl.GetSafeHwnd() && m_bMessage) { m_TabCtrl.SetCurSel(MESSAGE_ID); m_ProjectListCtrl.ModifyStyle(WS_VISIBLE, 0); m_ResultListCtrl.ModifyStyle(WS_VISIBLE, 0); m_XferListCtrl.ModifyStyle(WS_VISIBLE, 0); m_MessageListCtrl.ModifyStyle(0, WS_VISIBLE); m_UsagePieCtrl.ModifyStyle(WS_VISIBLE, 0); m_MessageListCtrl.RedrawWindow(NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_FRAME); m_bMessage = false; SetStatusIcon(ICON_NORMAL); } } ////////// // CMainWindow::OnSize // arguments: nType: type of resizing // cx: new width of window // cy: new height of window // returns: void // function: calculates new rectangles for child windows and resizes // them appropriately void CMainWindow::OnSize(UINT nType, int cx, int cy) { CWnd::OnSize(nType, cx, cy); // calculate the main rect for the tab control RECT rt = {EDGE_BUFFER, EDGE_BUFFER, cx-EDGE_BUFFER, cy-EDGE_BUFFER*2}; RECT irt = {0, 0, 0, 0}; if(m_TabCtrl.GetSafeHwnd()) { m_TabCtrl.MoveWindow(&rt, false); m_TabCtrl.GetItemRect(0, &irt); // calculate the rects for other controls inside the tab control RECT srt = {rt.left+EDGE_BUFFER, irt.bottom+EDGE_BUFFER*2, rt.right-EDGE_BUFFER, rt.bottom-EDGE_BUFFER}; if(m_ProjectListCtrl.GetSafeHwnd()) { m_ProjectListCtrl.MoveWindow(&srt, false); m_ProjectListCtrl.RedrawWindow(NULL,NULL,RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_FRAME); } if(m_ResultListCtrl.GetSafeHwnd()) { m_ResultListCtrl.MoveWindow(&srt, false); m_ResultListCtrl.RedrawWindow(NULL,NULL,RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_FRAME); } if(m_XferListCtrl.GetSafeHwnd()) { m_XferListCtrl.MoveWindow(&srt, false); m_XferListCtrl.RedrawWindow(NULL,NULL,RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_FRAME); } if(m_MessageListCtrl.GetSafeHwnd()) { m_MessageListCtrl.MoveWindow(&srt, false); m_MessageListCtrl.RedrawWindow(NULL,NULL,RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_FRAME); } if(m_UsagePieCtrl.GetSafeHwnd()) { m_UsagePieCtrl.MoveWindow(&srt, false); m_UsagePieCtrl.RedrawWindow(NULL,NULL,RDW_INVALIDATE|RDW_UPDATENOW|RDW_NOERASE|RDW_FRAME); } m_TabCtrl.RedrawWindow(NULL,NULL,RDW_INVALIDATE|RDW_UPDATENOW|RDW_NOERASE|RDW_FRAME); RedrawWindow(NULL,NULL,RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_FRAME); } } ////////// // CMainWindow::OnStatusIcon // arguments: wParam: id of icon clicked // lParam: message from icon // returns: true if the menu is shown, false otherwise // function: handles messages from status icon, including: // right click: shows popup menu // double click: alternates visibility of window LRESULT CMainWindow::OnStatusIcon(WPARAM wParam, LPARAM lParam) { if(lParam == WM_RBUTTONDOWN) { CPoint point; SetForegroundWindow(); GetCursorPos(&point); CMenu Menu, *pSubmenu; if(!Menu.LoadMenu(IDR_CONTEXT)) { return FALSE; } pSubmenu = Menu.GetSubMenu(STATUS_MENU); if(!pSubmenu) { Menu.DestroyMenu(); return FALSE; } if(m_bSuspend) { pSubmenu->EnableMenuItem(ID_STATUSICON_SUSPEND, MF_GRAYED); } else { pSubmenu->EnableMenuItem(ID_STATUSICON_RESUME, MF_GRAYED); } pSubmenu->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON, point.x, point.y, this); Menu.DestroyMenu(); } else if(lParam == WM_LBUTTONDOWN) { if(IsWindowVisible()) { SetForegroundWindow(); } } else if(lParam == WM_LBUTTONDBLCLK) { if(IsWindowVisible()) { ShowWindow(SW_HIDE); } else { ShowWindow(SW_SHOW); } } return TRUE; } ///////////////////////////////////////////////////////////////////////// // CLoginDialog message map and member functions BEGIN_MESSAGE_MAP(CLoginDialog, CDialog) ON_BN_CLICKED(IDOK, OnOK) ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipNotify) ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipNotify) END_MESSAGE_MAP() ////////// // CLoginDialog::CLoginDialog // arguments: y: dialog box resource id // szUrl: the initial url // szAuth: the initial autorization // returns: void // function: calls parents contructor, sets member variables CLoginDialog::CLoginDialog(UINT y, LPCTSTR szUrl, LPCTSTR szAuth) : CDialog(y) { m_strUrl.Format("%s", szUrl); m_strAuth.Format("%s", szAuth); } ////////// // CLoginDialog::OnInitDialog // arguments: void // returns: true if windows needs to give dialog focus, false if dialog has taken focus // function: initializes and centers dialog box BOOL CLoginDialog::OnInitDialog() { CDialog::OnInitDialog(); CWnd* pWndUrl = GetDlgItem(IDC_LOGIN_URL); if(pWndUrl) { pWndUrl->SetWindowText(m_strUrl); } CWnd* pWndAuth = GetDlgItem(IDC_LOGIN_AUTH); if(pWndAuth) { pWndAuth->SetWindowText(m_strAuth); } CWnd* pWndFocus = GetDlgItem(IDC_LOGIN_URL); if(pWndFocus) pWndFocus->SetFocus(); CenterWindow(); EnableToolTips(TRUE); return FALSE; } ////////// // CLoginDialog::OnOK // arguments: void // returns: void // function: copies strings from edit controls to member variables. void CLoginDialog::OnOK() { GetDlgItemText(IDC_LOGIN_URL, m_strUrl); GetDlgItemText(IDC_LOGIN_AUTH, m_strAuth); CDialog::OnOK(); } ////////// // CLoginDialog::OnToolTipNotify // arguments: id: id of the window, actually its hwnd // pNMHDR: pointer to notification message header // pResult: pointer to result of notification // returns: true if the notification is processed, otherwise false // function: handles notifications of tool tips by filling in // text for tool tips BOOL CLoginDialog::OnToolTipNotify(UINT id, NMHDR *pNMHDR, LRESULT *pResult) { // need to handle both ANSI and UNICODE versions of the message TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR; TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR; CString strTipText; UINT nID = pNMHDR->idFrom; if(pNMHDR->code == TTN_NEEDTEXTA && (pTTTA->uFlags & TTF_IDISHWND) || pNMHDR->code == TTN_NEEDTEXTW && (pTTTW->uFlags & TTF_IDISHWND)) { // idFrom is actually the HWND of the tool CWnd* wnd = CWnd::FromHandle((HWND)nID); if(wnd) nID = wnd->GetDlgCtrlID(); } if(nID == IDC_LOGIN_URL) strTipText.Format("The url for the website of the project."); if(nID == IDC_LOGIN_AUTH) strTipText.Format("The authorization code recieved in your confirmation email."); if(pNMHDR->code == TTN_NEEDTEXTA) { lstrcpyn(pTTTA->szText, strTipText, sizeof(pTTTA->szText)); } else { _mbstowcsz(pTTTW->szText, strTipText, sizeof(pTTTW->szText)); } *pResult = 0; // message was handled return TRUE; } ///////////////////////////////////////////////////////////////////////// // CQuitDialog message map and member functions BEGIN_MESSAGE_MAP(CQuitDialog, CDialog) ON_BN_CLICKED(IDOK, OnOK) ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipNotify) ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipNotify) END_MESSAGE_MAP() ////////// // CQuitDialog::CQuitDialog // arguments: y: dialog box resource id // returns: void // function: calls parents contructor. CQuitDialog::CQuitDialog(UINT y) : CDialog(y) { } ////////// // CQuitDialog::OnInitDialog // arguments: void // returns: true if windows needs to give dialog focus, false if dialog has taken focus // function: initializes and centers dialog box BOOL CQuitDialog::OnInitDialog() { CDialog::OnInitDialog(); CListBox* pListBox = (CListBox*)GetDlgItem(IDC_LIST); if(pListBox) { for(int i = 0; i < gstate.projects.size(); i ++) { if(!strcmp(gstate.projects[i]->project_name, "")) { pListBox->AddString(gstate.projects[i]->master_url); } else { pListBox->AddString(gstate.projects[i]->project_name); } } pListBox->SetFocus(); } CenterWindow(); EnableToolTips(TRUE); return TRUE; } ////////// // CQuitDialog::OnOK // arguments: void // returns: void // function: sets member variables, selected project to quit void CQuitDialog::OnOK() { m_nSel = -1; CListBox* pListBox = (CListBox*)GetDlgItem(IDC_LIST); if(pListBox) { m_nSel = pListBox->GetCurSel(); } if(m_nSel >= 0) CDialog::OnOK(); else CDialog::OnCancel(); } ////////// // CQuitDialog::OnToolTipNotify // arguments: id: id of the window, actually its hwnd // pNMHDR: pointer to notification message header // pResult: pointer to result of notification // returns: true if the notification is processed, otherwise false // function: handles notifications of tool tips by filling in // text for tool tips BOOL CQuitDialog::OnToolTipNotify(UINT id, NMHDR *pNMHDR, LRESULT *pResult) { // need to handle both ANSI and UNICODE versions of the message TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR; TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR; CString strTipText; UINT nID = pNMHDR->idFrom; if(pNMHDR->code == TTN_NEEDTEXTA && (pTTTA->uFlags & TTF_IDISHWND) || pNMHDR->code == TTN_NEEDTEXTW && (pTTTW->uFlags & TTF_IDISHWND)) { // idFrom is actually the HWND of the tool CWnd* wnd = CWnd::FromHandle((HWND)nID); if(wnd) nID = wnd->GetDlgCtrlID(); } if(nID == IDC_LIST) strTipText.Format("Select the project you wish to quit."); if(pNMHDR->code == TTN_NEEDTEXTA) { lstrcpyn(pTTTA->szText, strTipText, sizeof(pTTTA->szText)); } else { _mbstowcsz(pTTTW->szText, strTipText, sizeof(pTTTW->szText)); } *pResult = 0; // message was handled return TRUE; } ///////////////////////////////////////////////////////////////////////// // CProxyDialog message map and member functions BEGIN_MESSAGE_MAP(CProxyDialog, CDialog) ON_BN_CLICKED(IDC_CHECK_HTTP, OnHttp) ON_BN_CLICKED(IDC_CHECK_SOCKS, OnSocks) ON_BN_CLICKED(IDOK, OnOK) END_MESSAGE_MAP() ////////// // CProxyDialog::CProxyDialog // arguments: y: dialog box resource id // returns: void // function: calls parents contructor. CProxyDialog::CProxyDialog(UINT y) : CDialog(y) { } ////////// // CProxyDialog::OnInitDialog // arguments: void // returns: true if windows needs to give dialog focus, false if dialog has taken focus // function: initializes and centers dialog box BOOL CProxyDialog::OnInitDialog() { CDialog::OnInitDialog(); CButton* pBtn; // fill in http pBtn = (CButton*)GetDlgItem(IDC_CHECK_HTTP); if(pBtn) pBtn->SetCheck(gstate.use_proxy?BST_CHECKED:BST_UNCHECKED); SetDlgItemText(IDC_EDIT_HTTP_ADDR, gstate.proxy_server_name); CString portBuf; if(gstate.proxy_server_port > 0) portBuf.Format("%d", gstate.proxy_server_port); else portBuf.Format("80"); SetDlgItemText(IDC_EDIT_HTTP_PORT, portBuf.GetBuffer(0)); EnableHttp(gstate.use_proxy); // fill in socks pBtn = (CButton*)GetDlgItem(IDC_CHECK_SOCKS); if(pBtn) pBtn->EnableWindow(false); SetDlgItemText(IDC_EDIT_SOCKS_PORT, "1080"); EnableSocks(false); CenterWindow(); return TRUE; } ////////// // CProxyDialog::EnableHttp // arguments: bEnable: true to enable, false to disable // returns: void // function: enables or disables the http section of the dialog void CProxyDialog::EnableHttp(BOOL bEnable) { CEdit* pEdit; pEdit = (CEdit*)GetDlgItem(IDC_EDIT_HTTP_ADDR); if(pEdit) pEdit->EnableWindow(bEnable); pEdit = (CEdit*)GetDlgItem(IDC_EDIT_HTTP_PORT); if(pEdit) pEdit->EnableWindow(bEnable); } ////////// // CProxyDialog::EnableSocks // arguments: bEnable: true to enable, false to disable // returns: void // function: enables or disables the socks section of the dialog void CProxyDialog::EnableSocks(BOOL bEnable) { CEdit* pEdit; pEdit = (CEdit*)GetDlgItem(IDC_EDIT_SOCKS_ADDR); if(pEdit) pEdit->EnableWindow(bEnable); pEdit = (CEdit*)GetDlgItem(IDC_EDIT_SOCKS_PORT); if(pEdit) pEdit->EnableWindow(bEnable); pEdit = (CEdit*)GetDlgItem(IDC_EDIT_SOCKS_NAME); if(pEdit) pEdit->EnableWindow(bEnable); pEdit = (CEdit*)GetDlgItem(IDC_EDIT_SOCKS_PASS); if(pEdit) pEdit->EnableWindow(bEnable); } ////////// // CProxyDialog::OnOK // arguments: void // returns: void // function: handles http check box void CProxyDialog::OnHttp() { CButton* pBtn; pBtn = (CButton*)GetDlgItem(IDC_CHECK_HTTP); if(pBtn) { if(pBtn->GetCheck() == BST_CHECKED) { EnableHttp(true); } else { EnableHttp(false); } } } ////////// // CProxyDialog::OnSocks // arguments: void // returns: void // function: handles socks check box void CProxyDialog::OnSocks() { } ////////// // CProxyDialog::OnOK // arguments: void // returns: void // function: sets member variables, selected project to quit void CProxyDialog::OnOK() { CButton* pBtn; CString strbuf; // get http info pBtn = (CButton*)GetDlgItem(IDC_CHECK_HTTP); if(pBtn) { if(pBtn->GetCheck() == BST_CHECKED) { gstate.use_proxy = true; } else { gstate.use_proxy = false; } } GetDlgItemText(IDC_EDIT_HTTP_ADDR, strbuf); strcpy(gstate.proxy_server_name, strbuf.GetBuffer(0)); GetDlgItemText(IDC_EDIT_HTTP_PORT, strbuf); gstate.proxy_server_port = atoi(strbuf.GetBuffer(0)); CDialog::OnOK(); } ////////// // Function: UtilGetRegStr // arguments: name: name of key, str: where to store value of key // returns: int indicating error // function: reads string value in specified key int UtilGetRegStr(char *name, char *str ) { LONG error; DWORD type = REG_SZ; DWORD size = 128; HKEY boinc_key; if ( OSVersion == OS_WIN95 ) { error = RegOpenKeyEx( HKEY_LOCAL_MACHINE, "SOFTWARE\\BOINC", 0, KEY_ALL_ACCESS, &boinc_key ); if ( error != ERROR_SUCCESS ) return -1; } else { error = RegOpenKeyEx( HKEY_CURRENT_USER, "SOFTWARE\\BOINC", 0, KEY_ALL_ACCESS, &boinc_key ); if ( error != ERROR_SUCCESS ) return -1; } error = RegQueryValueEx( boinc_key, name, NULL, &type, (BYTE*)str, &size ); RegCloseKey( boinc_key ); if ( error != ERROR_SUCCESS ) return -1; return 0; } ////////// // Function: UtilInitOSVersion // arguments: void // returns: int indicating error // function: sets global variable "OSVersion" to the current OS (Win95/NT/Unknown) int UtilInitOSVersion( void ) { OSVERSIONINFO osinfo; osinfo.dwOSVersionInfoSize = sizeof(osinfo); if (!GetVersionEx( &osinfo )) return FALSE; if (osinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) OSVersion = OS_WIN95; else if ( osinfo.dwPlatformId == VER_PLATFORM_WIN32_NT) OSVersion = OS_WINNT; else OSVersion = OS_UNKNOWN; return TRUE; }