mirror of https://github.com/BOINC/boinc.git
2919 lines
85 KiB
C++
Executable File
2919 lines
85 KiB
C++
Executable File
// 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<void*>*)(&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<void*>*)(&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<void*>*)(&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<void*>* 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;
|
|
|
|
}
|