mirror of https://github.com/BOINC/boinc.git
1648 lines
51 KiB
C++
Executable File
1648 lines
51 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 "wingui_mainwindow.h"
|
|
|
|
CMyApp g_myApp;
|
|
CMainWindow* g_myWnd = NULL;
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
// 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, RUN_MUTEX) == 0 || GetLastError() == ERROR_ALREADY_EXISTS) {
|
|
UINT nShowMsg = RegisterWindowMessage(SHOW_WIN_MSG);
|
|
PostMessage(HWND_BROADCAST, nShowMsg, 0, 0);
|
|
return FALSE;
|
|
}
|
|
m_pMainWnd = new CMainWindow();
|
|
if(gstate.projects.size() == 0) {
|
|
((CMainWindow*)m_pMainWnd)->SendMessage(WM_COMMAND, ID_SETTINGS_LOGIN);
|
|
}
|
|
if(gstate.start_saver) {
|
|
UINT nStartSaver = RegisterWindowMessage(START_SS_MSG);
|
|
((CMainWindow*)m_pMainWnd)->SendMessage(nStartSaver, 0);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
int CMyApp::ExitInstance()
|
|
{
|
|
if (m_pMainWnd)
|
|
m_pMainWnd->DestroyWindow();
|
|
|
|
gstate.free_mem();
|
|
|
|
return CWinApp::ExitInstance();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
// CMainWindow message map and member functions
|
|
|
|
BEGIN_MESSAGE_MAP(CMainWindow, CWnd)
|
|
ON_WM_CLOSE()
|
|
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_CONNECTION_CONNECTNOW, OnCommandConnectionConnectNow)
|
|
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_WORK_SHOWGRAPHICS, OnCommandWorkShowGraphics)
|
|
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_WM_TIMER()
|
|
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);
|
|
|
|
m_nShowMsg = RegisterWindowMessage(SHOW_WIN_MSG);
|
|
m_nNetActivityMsg = RegisterWindowMessage(NET_ACTIVITY_MSG);
|
|
}
|
|
|
|
//////////
|
|
// CMainWindow::GetPieColor
|
|
// arguments: nPiece: index of pie piece
|
|
// returns: the color that piece should be
|
|
// function: detemines colors for pie pieces in usage control
|
|
COLORREF CMainWindow::GetPieColor(int nPiece)
|
|
{
|
|
int nR = 0, nG = 0, nB = 0;
|
|
if(nPiece == 0) {
|
|
return RGB(255, 0, 255);
|
|
} else if(nPiece == 1) {
|
|
return RGB(192, 64, 192);
|
|
}
|
|
nPiece -= 2;
|
|
switch(nPiece % 4) {
|
|
case 0:
|
|
return RGB(0, 0, 255);
|
|
case 1:
|
|
return RGB(64, 0, 192);
|
|
case 2:
|
|
return RGB(128, 0, 128);
|
|
default:
|
|
return RGB(192, 0, 64);
|
|
}
|
|
return RGB(0, 0, 0);
|
|
}
|
|
|
|
//////////
|
|
// 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
|
|
m_ProjectListCtrl.SetRedraw(FALSE);
|
|
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);
|
|
}
|
|
}
|
|
m_ProjectListCtrl.SetRedraw(TRUE);
|
|
|
|
// update results
|
|
m_ResultListCtrl.SetRedraw(FALSE);
|
|
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, at->fraction_done * 100);
|
|
}
|
|
|
|
// to completion
|
|
double tocomp;
|
|
if(!at || at->fraction_done == 0) {
|
|
tocomp = re->wup->seconds_to_complete;
|
|
} else {
|
|
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(g_szMiscItems[0]); break;
|
|
case RESULT_FILES_DOWNLOADED:
|
|
if (at)
|
|
strBuf.Format(g_szMiscItems[1]);
|
|
else
|
|
strBuf.Format(g_szMiscItems[2]);
|
|
break;
|
|
case RESULT_COMPUTE_DONE:
|
|
strBuf.Format(g_szMiscItems[3]); break;
|
|
default:
|
|
if (re->server_ack) {
|
|
strBuf.Format(g_szMiscItems[5]); break;
|
|
} else if (re->ready_to_ack) {
|
|
strBuf.Format(g_szMiscItems[4]); break;
|
|
} else {
|
|
strBuf.Format(g_szMiscItems[6]); break;
|
|
}
|
|
}
|
|
m_ResultListCtrl.SetItemText(i, 6, strBuf);
|
|
}
|
|
m_ResultListCtrl.SetRedraw(TRUE);
|
|
|
|
// update xfers
|
|
m_XferListCtrl.SetRedraw(FALSE);
|
|
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, g_szMiscItems[7]);
|
|
m_XferListCtrl.SetItemText(i, 5, "0.00 KBps");
|
|
m_XferListCtrl.SetItemText(i, 6, g_szMiscItems[7]);
|
|
continue;
|
|
}
|
|
|
|
// project
|
|
m_XferListCtrl.SetItemText(i, 0, fi->fip->project->project_name);
|
|
|
|
// file
|
|
m_XferListCtrl.SetItemText(i, 1, fi->fip->name);
|
|
|
|
// progress
|
|
double xSent = 0;
|
|
if (fi->fxp) {
|
|
xSent = fi->fxp->bytes_xferred;
|
|
}
|
|
m_XferListCtrl.SetItemProgress(i, 2, 100 * xSent / fi->fip->nbytes);
|
|
|
|
// size
|
|
strBuf.Format("%0.0f/%0.0fKB", xSent / 1024, fi->fip->nbytes / 1024);
|
|
m_XferListCtrl.SetItemText(i, 3, strBuf.GetBuffer(0));
|
|
|
|
// time
|
|
double xtime = 0;
|
|
xtime = fi->time_so_far;
|
|
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));
|
|
|
|
// speed
|
|
strBuf.Format("0.00 KBps");
|
|
if(fi->fxp) {
|
|
strBuf.Format("%0.2f KBps", fi->fxp->xfer_speed/1024);
|
|
}
|
|
m_XferListCtrl.SetItemText(i, 5, strBuf.GetBuffer(0));
|
|
|
|
// status
|
|
if (fi->next_request_time > time(0)) {
|
|
double xtime = fi->next_request_time-time(0);
|
|
int xhour = (int)(xtime / (60 * 60));
|
|
int xmin = (int)(xtime / 60) % 60;
|
|
int xsec = (int)(xtime) % 60;
|
|
strBuf.Format("%s %0.2d:%0.2d:%0.2d", g_szMiscItems[10], xhour, xmin, xsec);
|
|
m_XferListCtrl.SetItemText(i, 6, strBuf);
|
|
} else if (fi->fip->status == ERR_GIVEUP_DOWNLOAD) {
|
|
strBuf.Format(g_szMiscItems[11]);
|
|
m_XferListCtrl.SetItemText(i, 6, strBuf);
|
|
} else if (fi->fip->status == ERR_GIVEUP_UPLOAD) {
|
|
strBuf.Format(g_szMiscItems[12]);
|
|
m_XferListCtrl.SetItemText(i, 6, strBuf);
|
|
} else {
|
|
m_XferListCtrl.SetItemText(i, 6, fi->fip->generated_locally?g_szMiscItems[8]:g_szMiscItems[9]);
|
|
}
|
|
}
|
|
m_XferListCtrl.SetRedraw(TRUE);
|
|
|
|
// 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);
|
|
|
|
while(m_UsagePieCtrl.GetItemCount() - 4 < gstate.projects.size()) {
|
|
m_UsagePieCtrl.AddPiece("", GetPieColor(m_UsagePieCtrl.GetItemCount()), 0);
|
|
}
|
|
|
|
while(m_UsagePieCtrl.GetItemCount() - 4 > gstate.projects.size()) {
|
|
m_UsagePieCtrl.RemovePiece(m_UsagePieCtrl.GetItemCount() - 1);
|
|
}
|
|
|
|
m_UsagePieCtrl.SetTotal(xDiskTotal);
|
|
m_UsagePieCtrl.SetPiece(0, xDiskFree - (xDiskAllow - xDiskUsage)); // Free (non-BOINC)
|
|
m_UsagePieCtrl.SetPiece(1, xDiskAllow - xDiskUsage); // Free (BOINC)
|
|
m_UsagePieCtrl.SetPiece(2, xDiskUsed - xDiskUsage); // Used (non-BOINC)
|
|
for(i = 0; i < gstate.projects.size(); i ++) {
|
|
double xUsage;
|
|
CString strLabel;
|
|
strLabel.Format("%s %s", g_szUsageItems[4], gstate.projects[i]->project_name);
|
|
gstate.project_disk_usage(gstate.projects[i], xUsage);
|
|
m_UsagePieCtrl.SetPieceLabel(i + 4, strLabel.GetBuffer(0));
|
|
m_UsagePieCtrl.SetPiece(i + 4, xUsage);
|
|
xDiskUsage -= xUsage;
|
|
}
|
|
m_UsagePieCtrl.SetPiece(3, xDiskUsage); // Used (BOINC)
|
|
m_UsagePieCtrl.RedrawWindow(NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW|RDW_NOERASE|RDW_FRAME);
|
|
|
|
// make icon flash if needed
|
|
if(m_bMessage || m_bRequest) {
|
|
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 MSG_ERROR priority, flashes the status icon,
|
|
// then adds to message edit control.
|
|
void CMainWindow::MessageUser(char* szProject, char* szMessage, int szPriority)
|
|
{
|
|
if(!m_MessageListCtrl.GetSafeHwnd()) return;
|
|
|
|
int nNewPos = m_MessageListCtrl.GetItemCount();
|
|
m_MessageListCtrl.InsertItem(nNewPos, szProject);
|
|
|
|
CTime curTime = CTime::GetCurrentTime();
|
|
CString strTime;
|
|
strTime = curTime.Format("%c");
|
|
m_MessageListCtrl.SetItemText(nNewPos, 1, strTime);
|
|
|
|
m_MessageListCtrl.SetItemText(nNewPos, 2, szMessage);
|
|
|
|
// set status icon to flash
|
|
if((szPriority == MSG_ERROR) && (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 gstate.suspend_requested;
|
|
}
|
|
|
|
//////////
|
|
// CMainWindow::RequestNetConnect
|
|
// arguments: void
|
|
// returns: true if the user can connect, false otherwise
|
|
// function: asks the user for permission to connect to the network
|
|
BOOL CMainWindow::RequestNetConnect()
|
|
{
|
|
if(GetForegroundWindow() != this || !IsWindowVisible()) {
|
|
m_bRequest = true;
|
|
return FALSE;
|
|
}
|
|
CConnectDialog dlg(IDD_CONNECT);
|
|
int retval = dlg.DoModal();
|
|
m_bRequest = false;
|
|
if(retval == IDOK) {
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//////////
|
|
// 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;
|
|
memset( &icon_data, 0, sizeof(NOTIFYICONDATA) );
|
|
icon_data.cbSize = sizeof(NOTIFYICONDATA);
|
|
icon_data.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
|
|
icon_data.hWnd = GetSafeHwnd();
|
|
icon_data.uID = STATUS_ICON_ID;
|
|
safe_strncpy(icon_data.szTip, WND_TITLE, sizeof(icon_data.szTip));
|
|
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::SaveListControls
|
|
// arguments: void
|
|
// returns: void
|
|
// function: saves relevant elements of list controls
|
|
void CMainWindow::SaveListControls()
|
|
{
|
|
char szPath[256];
|
|
CString strKey, strVal;
|
|
GetCurrentDirectory(256, szPath);
|
|
strcat(szPath, "\\");
|
|
strcat(szPath, LIST_STATE_FILE_NAME);
|
|
file_delete(szPath);
|
|
m_ProjectListCtrl.SaveInactive(szPath, "PROJECTS");
|
|
m_ResultListCtrl.SaveInactive(szPath, "WORK");
|
|
m_XferListCtrl.SaveInactive(szPath, "TRANSFERS");
|
|
m_MessageListCtrl.SaveInactive(szPath, "MESSAGES");
|
|
}
|
|
|
|
//////////
|
|
// CMainWindow::LoadListControls
|
|
// arguments: void
|
|
// returns: void
|
|
// function: loads relevant elements of list controls
|
|
void CMainWindow::LoadListControls()
|
|
{
|
|
char szPath[256];
|
|
CString strKey, strVal;
|
|
GetCurrentDirectory(256, szPath);
|
|
strcat(szPath, "\\");
|
|
strcat(szPath, LIST_STATE_FILE_NAME);
|
|
m_ProjectListCtrl.LoadInactive(szPath, "PROJECTS");
|
|
m_ResultListCtrl.LoadInactive(szPath, "WORK");
|
|
m_XferListCtrl.LoadInactive(szPath, "TRANSFERS");
|
|
m_MessageListCtrl.LoadInactive(szPath, "MESSAGES");
|
|
}
|
|
|
|
//////////
|
|
// CMainWindow::SaveUserSettings
|
|
// arguments: void
|
|
// returns: void
|
|
// function: saves relevant user settings to boinc ini file
|
|
void CMainWindow::SaveUserSettings()
|
|
{
|
|
char szPath[256];
|
|
CString strKey, strVal;
|
|
GetCurrentDirectory(256, szPath);
|
|
strcat(szPath, "\\");
|
|
strcat(szPath, INI_FILE_NAME);
|
|
int colorder[MAX_COLS];
|
|
int i;
|
|
|
|
// get rid of old lists
|
|
file_delete(szPath);
|
|
|
|
// 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 file
|
|
void CMainWindow::LoadUserSettings()
|
|
{
|
|
char szPath[256];
|
|
CString strKey;
|
|
GetCurrentDirectory(256, szPath);
|
|
strcat(szPath, "\\");
|
|
strcat(szPath, INI_FILE_NAME);
|
|
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;
|
|
|
|
CRect rtScreen, rtInt;
|
|
HDC screenDC=::GetDC(NULL);
|
|
rtScreen.left = rtScreen.top = 0;
|
|
rtScreen.right=GetDeviceCaps(screenDC, HORZRES);
|
|
rtScreen.bottom=GetDeviceCaps(screenDC, VERTRES);
|
|
::ReleaseDC(NULL, screenDC);
|
|
|
|
rtInt.IntersectRect(&rt, &rtScreen);
|
|
if(rtInt.IsRectEmpty()) {
|
|
rt.SetRect(100, 100, 600, 400);
|
|
}
|
|
SetWindowPos(&wndNoTopMost, rt.left, rt.top, rt.Width(), rt.Height(), 0);
|
|
|
|
// 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::LoadLanguage
|
|
// arguments: void
|
|
// returns: void
|
|
// function: loads new captions from language file
|
|
void CMainWindow::LoadLanguage()
|
|
{
|
|
char szPath[256];
|
|
int col;
|
|
CString strSection;
|
|
GetCurrentDirectory(256, szPath);
|
|
strcat(szPath, "\\");
|
|
strcat(szPath, LANGUAGE_FILE_NAME);
|
|
|
|
// load column headers
|
|
strSection.Format("HEADER-%s", g_szTabItems[PROJECT_ID]);
|
|
for(col = 0; col < PROJECT_COLS; col ++) {
|
|
GetPrivateProfileString(strSection, g_szColumnTitles[PROJECT_ID][col], g_szColumnTitles[PROJECT_ID][col], g_szColumnTitles[PROJECT_ID][col], 256, szPath);
|
|
}
|
|
GetPrivateProfileString(strSection, "Title", g_szTabItems[PROJECT_ID], g_szTabItems[PROJECT_ID], 16, szPath);
|
|
strSection.Format("HEADER-%s", g_szTabItems[RESULT_ID]);
|
|
for(col = 0; col < RESULT_COLS; col ++) {
|
|
GetPrivateProfileString(strSection, g_szColumnTitles[RESULT_ID][col], g_szColumnTitles[RESULT_ID][col], g_szColumnTitles[RESULT_ID][col], 256, szPath);
|
|
}
|
|
GetPrivateProfileString(strSection, "Title", g_szTabItems[RESULT_ID], g_szTabItems[RESULT_ID], 16, szPath);
|
|
strSection.Format("HEADER-%s", g_szTabItems[XFER_ID]);
|
|
for(col = 0; col < XFER_COLS; col ++) {
|
|
GetPrivateProfileString(strSection, g_szColumnTitles[XFER_ID][col], g_szColumnTitles[XFER_ID][col], g_szColumnTitles[XFER_ID][col], 256, szPath);
|
|
}
|
|
GetPrivateProfileString(strSection, "Title", g_szTabItems[XFER_ID], g_szTabItems[XFER_ID], 16, szPath);
|
|
strSection.Format("HEADER-%s", g_szTabItems[MESSAGE_ID]);
|
|
for(col = 0; col < MESSAGE_COLS; col ++) {
|
|
GetPrivateProfileString(strSection, g_szColumnTitles[MESSAGE_ID][col], g_szColumnTitles[MESSAGE_ID][col], g_szColumnTitles[MESSAGE_ID][col], 256, szPath);
|
|
}
|
|
GetPrivateProfileString(strSection, "Title", g_szTabItems[MESSAGE_ID], g_szTabItems[MESSAGE_ID], 16, szPath);
|
|
|
|
// load usage labels
|
|
strSection.Format("HEADER-%s", g_szTabItems[USAGE_ID]);
|
|
for(col = 0; col < MAX_USAGE_STR; col ++) {
|
|
GetPrivateProfileString(strSection, g_szUsageItems[col], g_szUsageItems[col], g_szUsageItems[col], 256, szPath);
|
|
}
|
|
GetPrivateProfileString(strSection, "Title", g_szTabItems[USAGE_ID], g_szTabItems[USAGE_ID], 16, szPath);
|
|
|
|
// load miscellaneous text
|
|
strSection.Format("HEADER-MISC");
|
|
for(col = 0; col < MAX_MISC_STR; col ++) {
|
|
GetPrivateProfileString(strSection, g_szMiscItems[col], g_szMiscItems[col], g_szMiscItems[col], 256, szPath);
|
|
}
|
|
|
|
// load menu items
|
|
CString strItem, strItemNoAmp;
|
|
char szItem[256];
|
|
int i, is;
|
|
for(i = 0; i < m_MainMenu.GetMenuItemCount(); i ++) {
|
|
m_MainMenu.GetMenuString(i, strItem, MF_BYPOSITION);
|
|
strItemNoAmp = strItem; strItemNoAmp.Remove('&');
|
|
strSection.Format("MENU-%s", strItemNoAmp);
|
|
GetPrivateProfileString(strSection, "Title", strItem, szItem, 256, szPath);
|
|
m_MainMenu.ModifyMenu(i, MF_BYPOSITION|MF_STRING, 0, szItem);
|
|
CMenu* pSubMenu = m_MainMenu.GetSubMenu(i);
|
|
if(!pSubMenu) continue;
|
|
for(is = 0; is < pSubMenu->GetMenuItemCount(); is ++) {
|
|
pSubMenu->GetMenuString(is, strItem, MF_BYPOSITION);
|
|
if(strItem.IsEmpty()) continue;
|
|
strItemNoAmp = strItem; strItemNoAmp.Remove('&');
|
|
GetPrivateProfileString(strSection, strItemNoAmp, strItem, szItem, 256, szPath);
|
|
pSubMenu->ModifyMenu(is, MF_BYPOSITION|MF_STRING, pSubMenu->GetMenuItemID(is), szItem);
|
|
}
|
|
}
|
|
for(i = 0; i < m_ContextMenu.GetMenuItemCount(); i ++) {
|
|
m_ContextMenu.GetMenuString(i, strItem, MF_BYPOSITION);
|
|
strItemNoAmp = strItem; strItemNoAmp.Remove('&');
|
|
strSection.Format("MENU-%s", strItemNoAmp);
|
|
GetPrivateProfileString(strSection, "Title", strItem, szItem, 256, szPath);
|
|
m_ContextMenu.ModifyMenu(i, MF_BYPOSITION|MF_STRING, 0, szItem);
|
|
CMenu* pSubMenu = m_ContextMenu.GetSubMenu(i);
|
|
if(!pSubMenu) continue;
|
|
for(is = 0; is < pSubMenu->GetMenuItemCount(); is ++) {
|
|
pSubMenu->GetMenuString(is, strItem, MF_BYPOSITION);
|
|
if(strItem.IsEmpty()) continue;
|
|
strItemNoAmp = strItem; strItemNoAmp.Remove('&');
|
|
GetPrivateProfileString(strSection, strItemNoAmp, strItem, szItem, 256, szPath);
|
|
pSubMenu->ModifyMenu(is, MF_BYPOSITION|MF_STRING, pSubMenu->GetMenuItemID(is), szItem);
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////
|
|
// 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) {
|
|
typedef DWORD (CALLBACK* GetFn)();
|
|
GetFn fn;
|
|
fn = (GetFn)GetProcAddress(m_hIdleDll, "IdleTrackerGetLastTickCount");
|
|
if(fn) {
|
|
return GetTickCount() - fn();
|
|
} else {
|
|
typedef void (CALLBACK* TermFn)();
|
|
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)
|
|
{
|
|
if(m_nShowMsg == message) {
|
|
ShowWindow(SW_SHOW);
|
|
SetForegroundWindow();
|
|
return 0;
|
|
} else if(m_nNetActivityMsg == message) {
|
|
gstate.net_sleep(0);
|
|
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()
|
|
{
|
|
if(GetForegroundWindow() != this || !IsWindowVisible()) {
|
|
return;
|
|
}
|
|
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()
|
|
{
|
|
CAboutDialog dlg(IDD_ABOUTBOX);
|
|
int nResult = dlg.DoModal();
|
|
}
|
|
|
|
//////////
|
|
// 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::OnCommandConnectionConnectNow
|
|
// arguments: void
|
|
// returns: void
|
|
// function: causes the client to connect to the network
|
|
void CMainWindow::OnCommandConnectionConnectNow()
|
|
{
|
|
bool bOldConfirm = gstate.global_prefs.confirm_before_connecting;
|
|
gstate.global_prefs.confirm_before_connecting = false;
|
|
NetOpen();
|
|
gstate.global_prefs.confirm_before_connecting = bOldConfirm;
|
|
for(int ii = 0; ii < gstate.projects.size(); ii ++) {
|
|
gstate.projects[ii]->sched_rpc_pending = true;
|
|
}
|
|
NetClose();
|
|
}
|
|
|
|
//////////
|
|
// 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::OnCommandWorkShowGraphics
|
|
// arguments: void
|
|
// returns: void
|
|
// function: brings up the graphics window for the selescted app
|
|
void CMainWindow::OnCommandWorkShowGraphics()
|
|
{
|
|
RESULT* resToShow = (RESULT*)m_ResultListCtrl.GetItemData(m_nContextItem);
|
|
if(resToShow) {
|
|
ACTIVE_TASK* at = gstate.lookup_active_task_by_result(resToShow);
|
|
if(at) {
|
|
CWnd* pAppWnd = GetWndFromProcId(at->pid);
|
|
if(pAppWnd && IsWindow(pAppWnd->m_hWnd)) {
|
|
pAppWnd->PostMessage(RegisterWindowMessage(APP_SET_MSG), MODE_WINDOW, MODE_DEFAULT);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////
|
|
// 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;
|
|
|
|
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;
|
|
|
|
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.cleanup_and_exit();
|
|
PostQuitMessage(0);
|
|
KillTimer(m_nGuiTimerID);
|
|
|
|
// 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();
|
|
m_ContextMenu.DestroyMenu();
|
|
|
|
// free dll and idle detection
|
|
if(m_hIdleDll) {
|
|
typedef void (CALLBACK* TermFn)();
|
|
TermFn fn;
|
|
fn = (TermFn)GetProcAddress(m_hIdleDll, "IdleTrackerTerm");
|
|
if(!fn) {
|
|
show_message(NULL, "Error in DLL \"boinc.dll\"", MSG_INFO);
|
|
} else {
|
|
fn();
|
|
}
|
|
FreeLibrary(m_hIdleDll);
|
|
m_hIdleDll = NULL;
|
|
}
|
|
|
|
SaveUserSettings();
|
|
SaveListControls();
|
|
|
|
delete m_pSSWnd;
|
|
|
|
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];
|
|
char* szTitles[MAX_COLS];
|
|
int i;
|
|
|
|
if (CWnd::OnCreate(lpcs) == -1) {
|
|
return -1;
|
|
}
|
|
|
|
// Determine the OS version
|
|
UtilInitOSVersion();
|
|
|
|
g_myWnd = this;
|
|
m_nIconState = ICON_OFF;
|
|
m_bMessage = false;
|
|
m_bRequest = false;
|
|
m_nContextItem = -1;
|
|
m_pSSWnd = new CSSWindow();
|
|
|
|
// load menus
|
|
m_ContextMenu.LoadMenu(IDR_CONTEXT);
|
|
m_MainMenu.LoadMenu(IDR_MAINFRAME);
|
|
SetMenu(&m_MainMenu);
|
|
|
|
LoadLanguage();
|
|
|
|
// 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(i = 0; i < MAX_COLS; i ++) szTitles[i] = g_szColumnTitles[PROJECT_ID][i];
|
|
m_ProjectListCtrl.SetMenuItems(szTitles, PROJECT_COLS);
|
|
for(i = 0; i < PROJECT_COLS; i ++) {
|
|
m_ProjectListCtrl.InsertColumn(i, g_szColumnTitles[PROJECT_ID][i], LVCFMT_LEFT, DEF_COL_WIDTH, -1);
|
|
}
|
|
|
|
// 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 < MAX_COLS; i ++) szTitles[i] = g_szColumnTitles[RESULT_ID][i];
|
|
m_ResultListCtrl.SetMenuItems(szTitles, RESULT_COLS);
|
|
for(i = 0; i < RESULT_COLS; i ++) {
|
|
m_ResultListCtrl.InsertColumn(i, g_szColumnTitles[RESULT_ID][i], LVCFMT_LEFT, DEF_COL_WIDTH, -1);
|
|
}
|
|
|
|
// 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 < MAX_COLS; i ++) szTitles[i] = g_szColumnTitles[XFER_ID][i];
|
|
m_XferListCtrl.SetMenuItems(szTitles, XFER_COLS);
|
|
for(i = 0; i < XFER_COLS; i ++) {
|
|
m_XferListCtrl.InsertColumn(i, g_szColumnTitles[XFER_ID][i], LVCFMT_LEFT, DEF_COL_WIDTH, -1);
|
|
}
|
|
|
|
// 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 < MAX_COLS; i ++) szTitles[i] = g_szColumnTitles[MESSAGE_ID][i];
|
|
m_MessageListCtrl.SetMenuItems(szTitles, MESSAGE_COLS);
|
|
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, -1);
|
|
}
|
|
|
|
// 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(g_szUsageItems[0], GetPieColor(0), 0);
|
|
m_UsagePieCtrl.AddPiece(g_szUsageItems[1], GetPieColor(1), 0);
|
|
m_UsagePieCtrl.AddPiece(g_szUsageItems[2], GetPieColor(2), 0);
|
|
m_UsagePieCtrl.AddPiece(g_szUsageItems[3], GetPieColor(3), 0);
|
|
|
|
// set up image list for tab control
|
|
m_TabIL.Create(16, 16, ILC_COLOR8|ILC_MASK, MAX_TABS, 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, g_szTabItems[0], 0);
|
|
m_TabCtrl.InsertItem(2, g_szTabItems[1], 1);
|
|
m_TabCtrl.InsertItem(3, g_szTabItems[2], 2);
|
|
m_TabCtrl.InsertItem(4, g_szTabItems[3], 3);
|
|
m_TabCtrl.InsertItem(5, g_szTabItems[4], 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);
|
|
|
|
// 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
|
|
//
|
|
// 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();
|
|
|
|
LoadUserSettings();
|
|
LoadListControls();
|
|
|
|
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;
|
|
}
|
|
|
|
m_nGuiTimerID = SetTimer(GUI_TIMER, GUI_WAIT, (TIMERPROC) NULL);
|
|
|
|
// load dll and start idle detection
|
|
m_hIdleDll = LoadLibrary("boinc.dll");
|
|
if(!m_hIdleDll) {
|
|
show_message(NULL,"Can't load \"boinc.dll\", will not be able to determine idle time", MSG_ERROR);
|
|
} else {
|
|
typedef BOOL (CALLBACK* InitFn)();
|
|
InitFn fn;
|
|
fn = (InitFn)GetProcAddress(m_hIdleDll, "IdleTrackerInit");
|
|
if(!fn) {
|
|
show_message(NULL,"Error in DLL \"boinc.dll\", will not be able to determine idle time", MSG_INFO);
|
|
FreeLibrary(m_hIdleDll);
|
|
m_hIdleDll = NULL;
|
|
} else {
|
|
if(!fn()) {
|
|
show_message(NULL,"Error in DLL \"boinc.dll\", will not be able to determine idle time", MSG_INFO);
|
|
FreeLibrary(m_hIdleDll);
|
|
m_hIdleDll = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
UpdateGUI(&gstate);
|
|
|
|
// see if we need to add this to startup
|
|
if(gstate.global_prefs.run_on_startup) {
|
|
UtilGetRegStr("ClientPath", curDir);
|
|
if(strlen(curDir)) {
|
|
strcat(curDir, " -min");
|
|
UtilSetRegStartupStr("boincclient", curDir);
|
|
}
|
|
} else {
|
|
UtilSetRegStartupStr("boincclient", "");
|
|
}
|
|
|
|
// see if we need to hide the window
|
|
if(gstate.global_prefs.run_minimized || gstate.start_saver) {
|
|
ShowWindow(SW_HIDE);
|
|
} else {
|
|
ShowWindow(SW_SHOW);
|
|
}
|
|
|
|
if(gstate.suspend_requested) OnCommandSuspend();
|
|
else 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* 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)) {
|
|
pContextMenu = m_ContextMenu.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);
|
|
}
|
|
if(m_bRequest) {
|
|
m_bRequest = false;
|
|
if(RequestNetConnect()) OnCommandConnectionConnectNow();
|
|
}
|
|
}
|
|
|
|
//////////
|
|
// 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, TOP_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+TOP_BUFFER, 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* pSubmenu;
|
|
pSubmenu = m_ContextMenu.GetSubMenu(STATUS_MENU);
|
|
if(IsSuspended()) {
|
|
pSubmenu->EnableMenuItem(ID_STATUSICON_SUSPEND, MF_GRAYED);
|
|
pSubmenu->EnableMenuItem(ID_STATUSICON_RESUME, MF_ENABLED);
|
|
} else {
|
|
pSubmenu->EnableMenuItem(ID_STATUSICON_SUSPEND, MF_ENABLED);
|
|
pSubmenu->EnableMenuItem(ID_STATUSICON_RESUME, MF_GRAYED);
|
|
}
|
|
pSubmenu->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON, point.x, point.y, this);
|
|
} else if(lParam == WM_LBUTTONDOWN) {
|
|
if(IsWindowVisible()) {
|
|
SetForegroundWindow();
|
|
}
|
|
} else if(lParam == WM_LBUTTONDBLCLK) {
|
|
if(IsWindowVisible()) {
|
|
ShowWindow(SW_HIDE);
|
|
} else {
|
|
ShowWindow(SW_SHOW);
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
//////////
|
|
// CMainWindow::OnTimer
|
|
// arguments: uEventID: timer's id
|
|
// returns: void
|
|
// function: checks idle time, updates client state, flushed output streams,
|
|
// and updates gui display.
|
|
void CMainWindow::OnTimer(UINT uEventID)
|
|
{
|
|
if(uEventID == m_nGuiTimerID) {
|
|
// stop the timer while we do processing
|
|
KillTimer(m_nGuiTimerID);
|
|
|
|
// update state and gui
|
|
while(gstate.do_something());
|
|
NetCheck(); // need to check if network connection can be terminated
|
|
fflush(stdout);
|
|
fflush(stderr);
|
|
if(!IsSuspended()) {
|
|
// check user's idle time for suspension of apps
|
|
if (gstate.global_prefs.idle_time_to_run > 0) {
|
|
if (GetUserIdleTime() > 1000 * gstate.global_prefs.idle_time_to_run) {
|
|
gstate.user_idle = true;
|
|
} else {
|
|
gstate.user_idle = false;
|
|
}
|
|
} else {
|
|
gstate.user_idle = true;
|
|
}
|
|
|
|
UpdateGUI(&gstate);
|
|
}
|
|
|
|
// Start the timer again
|
|
m_nGuiTimerID = SetTimer(GUI_TIMER, GUI_WAIT, (TIMERPROC) NULL);
|
|
}
|
|
}
|