You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3865 lines
105 KiB
3865 lines
105 KiB
// File: ftui.h
|
|
#include "mbftpch.h"
|
|
#include <commctrl.h>
|
|
#include <regentry.h>
|
|
#include "ftui.h"
|
|
#include "version.h"
|
|
#include <iappldr.h>
|
|
#include <nmhelp.h>
|
|
|
|
static ULONG s_cMsgBox2Dlg = 0; // for alignment
|
|
static ULONG s_cRecvDlg = 0; // for alignment
|
|
static ULONG s_sort = -1;
|
|
ULONG _GetPercent(ULONG cbTotalRecvSize , ULONG cbFileSize);
|
|
|
|
TCHAR s_szMSFT[64];
|
|
static TCHAR s_szScratchText[MAX_PATH*2];
|
|
static const TCHAR s_cszHtmlHelpFile[] = TEXT("conf.chm");
|
|
|
|
#define MAX_FILE_NAME_LENGTH 30
|
|
|
|
LRESULT CALLBACK FtMainWndProc(HWND, UINT, WPARAM, LPARAM);
|
|
INT_PTR CALLBACK RecvDlgProc(HWND, UINT, WPARAM, LPARAM);
|
|
LPTSTR PathNameToFileName(LPTSTR pszPathName);
|
|
HRESULT GetRecvFolder(LPTSTR pszInFldr, LPTSTR pszOutFldr);
|
|
BOOL MsgBox2(CAppletWindow *pWindow, LPTSTR pszText);
|
|
|
|
void ShiftFocus(HWND hwndTop, BOOL bForward);
|
|
|
|
void EnsureTrailingSlash(LPTSTR);
|
|
int MyLoadString(UINT idStr);
|
|
int MyLoadString(UINT idStr, LPTSTR pszDstStr);
|
|
int MyLoadString(UINT idStr, LPTSTR pszDstStr, LPTSTR pszElement);
|
|
int MyLoadString(UINT idStr, LPTSTR pszDstStr, LPTSTR pszElement1, LPTSTR pszElement2);
|
|
__inline int MyLoadString(UINT idStr, LPTSTR pszDstStr, UINT_PTR nElement)
|
|
{ return MyLoadString(idStr, pszDstStr, (LPTSTR) nElement); }
|
|
__inline int MyLoadString(UINT idStr, LPTSTR pszDstStr, UINT_PTR nElement1, UINT_PTR nElement2)
|
|
{ return MyLoadString(idStr, pszDstStr, (LPTSTR) nElement1, (LPTSTR) nElement2); }
|
|
int MyLoadString(UINT idStr, LPTSTR pszDstStr, LPTSTR pszElement1, UINT_PTR nElement2)
|
|
{ return MyLoadString(idStr, pszDstStr, pszElement1, (LPTSTR) nElement2); }
|
|
__inline int MyLoadString(UINT idStr, LPTSTR pszDstStr, UINT_PTR nElement1, LPTSTR pszElement2)
|
|
{ return MyLoadString(idStr, pszDstStr, (LPTSTR) nElement1, pszElement2); }
|
|
|
|
#define count_of(array) (sizeof(array) / sizeof(array[0]))
|
|
|
|
void OnChangeFolder(void);
|
|
BOOL FBrowseForFolder(LPTSTR pszFolder, UINT cchMax, LPCTSTR pszTitle);
|
|
extern BOOL g_fShutdownByT120;
|
|
|
|
|
|
void OPT_GetFTWndPosition(RECT *pRect)
|
|
{
|
|
int iLeft, iTop, iRight, iBottom;
|
|
RegEntry reWnd( FILEXFER_KEY, HKEY_CURRENT_USER);
|
|
|
|
iLeft = reWnd.GetNumber(REGVAL_WINDOW_XPOS, 0);
|
|
iTop = reWnd.GetNumber(REGVAL_WINDOW_YPOS, 0);
|
|
iRight = reWnd.GetNumber(REGVAL_WINDOW_WIDTH, 0) + iLeft;
|
|
iBottom = reWnd.GetNumber(REGVAL_WINDOW_HEIGHT, 0) + iTop;
|
|
|
|
// If it was empty, use the new rect
|
|
if (!(iBottom || iTop || iLeft || iRight))
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Make sure that the window rectangle is (at least partially) on
|
|
// screen, and not too large. First get the screen size
|
|
int screenWidth = ::GetSystemMetrics(SM_CXSCREEN);
|
|
int screenHeight = ::GetSystemMetrics(SM_CYSCREEN);
|
|
// Check the window size
|
|
if ((iRight - iLeft) > screenWidth)
|
|
{
|
|
iRight = iLeft + screenWidth;
|
|
}
|
|
|
|
if ((iBottom - iTop) > screenHeight)
|
|
{
|
|
iTop = screenHeight;
|
|
}
|
|
|
|
// Check the window position
|
|
if (iLeft >= screenWidth)
|
|
{
|
|
// Off screen to the right - keep the width the same
|
|
iLeft = screenWidth - (iRight - iLeft);
|
|
iRight = screenWidth;
|
|
}
|
|
|
|
if (iRight < 0)
|
|
{
|
|
// Off screen to the left - keep the width the same
|
|
iRight = iRight - iLeft;
|
|
iLeft = 0;
|
|
}
|
|
|
|
if (iTop >= screenHeight)
|
|
{
|
|
// Off screen to the bottom - keep the height the same
|
|
iTop = screenHeight - (iBottom - iTop);
|
|
iBottom = screenHeight;
|
|
}
|
|
|
|
if (iBottom < 0)
|
|
{
|
|
// Off screen to the top - keep the height the same
|
|
iBottom = (iBottom - iTop);
|
|
iTop = 0;
|
|
}
|
|
|
|
pRect->left = iLeft;
|
|
pRect->top = iTop;
|
|
pRect->right = iRight - iLeft;
|
|
pRect->bottom = iBottom - iTop;
|
|
}
|
|
|
|
|
|
CAppletWindow::CAppletWindow(BOOL fNoUI, HRESULT *pHr)
|
|
:
|
|
CRefCount(MAKE_STAMP_ID('F','T','U','I')),
|
|
m_hwndMainUI(NULL),
|
|
m_pToolbar(NULL),
|
|
m_hwndListView(NULL),
|
|
m_hwndStatusBar(NULL),
|
|
m_pEngine(NULL),
|
|
m_fInFileOpenDialog(FALSE),
|
|
m_pCurrSendFileInfo(NULL),
|
|
m_nCurrSendEventHandle(0),
|
|
m_hIconInCall(NULL),
|
|
m_hIconNotInCall(NULL)
|
|
{
|
|
m_UIMode = fNoUI ? FTUIMODE_NOUI : FTUIMODE_UIHIDDEN;
|
|
::GetCurrentDirectory(MAX_PATH, m_szDefaultDir);
|
|
|
|
*pHr = E_FAIL; // failure, at default
|
|
|
|
// create window class name
|
|
::wsprintf(&m_szFtMainWndClassName[0], TEXT("FTMainWnd%0X_%0X"), ::GetCurrentProcessId(), ::GetTickCount());
|
|
ASSERT(::lstrlenA(&m_szFtMainWndClassName[0]) < sizeof(m_szFtMainWndClassName));
|
|
|
|
// register window class first
|
|
WNDCLASS wc;
|
|
::ZeroMemory(&wc, sizeof(wc));
|
|
//wc.style = 0;
|
|
wc.lpfnWndProc = FtMainWndProc;
|
|
// wc.cbClsExtra = 0;
|
|
// wc.cbWndExtra = 0;
|
|
wc.hInstance = g_hDllInst;
|
|
wc.hIcon = ::LoadIcon(g_hDllInst, MAKEINTRESOURCE(IDI_FILE_TRANSFER));
|
|
// wc.hbrBackground = NULL;
|
|
// wc.hCursor = NULL;
|
|
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU_FT);
|
|
wc.lpszClassName = m_szFtMainWndClassName;
|
|
if (::RegisterClass(&wc))
|
|
{
|
|
::MyLoadString(IDS_MSFT_NOT_IN_CALL_WINDOW_CAPTION);
|
|
m_hwndMainUI = ::CreateWindow(
|
|
m_szFtMainWndClassName,
|
|
s_szScratchText,
|
|
WS_OVERLAPPEDWINDOW | WS_TABSTOP,
|
|
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
|
|
NULL, // no parent window
|
|
NULL, // use class' menu
|
|
g_hDllInst,
|
|
(LPVOID) this); // this window is for this object
|
|
if (NULL != m_hwndMainUI)
|
|
{
|
|
// success
|
|
*pHr = S_OK;
|
|
}
|
|
}
|
|
m_hAccel = ::LoadAccelerators(g_hDllInst, MAKEINTRESOURCE(RECVDLGACCELTABLE));
|
|
m_hLVAccel = ::LoadAccelerators(g_hDllInst, MAKEINTRESOURCE(LISTVIEWACCELTABLE));
|
|
}
|
|
|
|
|
|
|
|
CAppletWindow::~CAppletWindow(void)
|
|
{
|
|
ASSERT(NULL == m_hwndMainUI);
|
|
|
|
::UnregisterClass(m_szFtMainWndClassName, g_hDllInst);
|
|
|
|
ClearSendInfo(FALSE);
|
|
ClearRecvInfo();
|
|
|
|
if (m_hIconInCall)
|
|
::DestroyIcon(m_hIconInCall);
|
|
if (m_hIconNotInCall)
|
|
::DestroyIcon(m_hIconNotInCall);
|
|
|
|
ASSERT(NULL == m_pEngine);
|
|
}
|
|
|
|
|
|
BOOL CAppletWindow::FilterMessage(MSG *pMsg)
|
|
{
|
|
CRecvDlg *pRecvDlg;
|
|
HWND hwndError;
|
|
HWND hwndForeground = ::GetForegroundWindow();
|
|
|
|
m_RecvDlgList.Reset();
|
|
while (NULL != (pRecvDlg = m_RecvDlgList.Iterate()))
|
|
{
|
|
if (::IsDialogMessage(pRecvDlg->GetHwnd(), pMsg))
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
if (hwndForeground == m_hwndMainUI)
|
|
{
|
|
BOOL fRet = ::TranslateAccelerator(m_hwndMainUI, m_hLVAccel, pMsg);
|
|
return fRet;
|
|
}
|
|
|
|
|
|
|
|
|
|
m_ErrorDlgList.Reset();
|
|
while (NULL != (hwndError = m_ErrorDlgList.Iterate()))
|
|
{
|
|
if (::IsDialogMessage(hwndError, pMsg))
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL CAppletWindow::QueryShutdown(BOOL fShutdown)
|
|
{
|
|
if (m_UIMode != FTUIMODE_NOUI)
|
|
{
|
|
int id = 0;
|
|
if (m_nCurrSendEventHandle)
|
|
{
|
|
id = (fShutdown)?IDS_QUERY_SEND_SHUTDOWN:IDS_QUERY_SEND_HANGUP;
|
|
}
|
|
else if (IsReceiving())
|
|
{
|
|
id = (fShutdown)?IDS_QUERY_RECVING_SHUTDOWN:IDS_QUERY_RECVING_HANGUP;
|
|
}
|
|
|
|
if (id)
|
|
{
|
|
// could be in any thread
|
|
TCHAR szText[MAX_PATH];
|
|
if (::MyLoadString(id, szText))
|
|
{
|
|
if (IDNO == ::MessageBox(NULL, szText, s_szMSFT, MB_TASKMODAL | MB_YESNO | MB_ICONQUESTION))
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m_nCurrSendEventHandle)
|
|
{
|
|
OnStopSending();
|
|
}
|
|
if (IsReceiving())
|
|
{
|
|
CRecvDlg *pRecvDlg = NULL;
|
|
m_RecvDlgList.Reset();
|
|
while (NULL != (pRecvDlg = m_RecvDlgList.Iterate()))
|
|
{
|
|
DBG_SAVE_FILE_LINE
|
|
GetEngine()->SafePostMessage(
|
|
new FileTransferControlMsg(
|
|
pRecvDlg->GetEventHandle(),
|
|
pRecvDlg->GetFileHandle(),
|
|
NULL,
|
|
NULL,
|
|
FileTransferControlMsg::EnumAbortFile));
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void CAppletWindow::RegisterEngine(MBFTEngine *pEngine)
|
|
{
|
|
ASSERT(NULL == m_pEngine);
|
|
pEngine->AddRef();
|
|
m_pEngine = pEngine;
|
|
UpdateUI();
|
|
}
|
|
|
|
|
|
void CAppletWindow::UnregisterEngine(void)
|
|
{
|
|
if (NULL != m_pEngine)
|
|
{
|
|
m_pEngine->Release();
|
|
m_pEngine = NULL;
|
|
ClearSendInfo(TRUE);
|
|
ClearRecvInfo();
|
|
}
|
|
if (UIHidden())
|
|
{ // exit
|
|
::PostMessage(m_hwndMainUI, WM_CLOSE, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
UpdateUI(); // don't quit
|
|
}
|
|
}
|
|
|
|
|
|
void CAppletWindow::RegisterRecvDlg(CRecvDlg *pDlg)
|
|
{
|
|
m_RecvDlgList.Prepend(pDlg);
|
|
}
|
|
|
|
|
|
void CAppletWindow::UnregisterRecvDlg(CRecvDlg *pDlg)
|
|
{
|
|
m_RecvDlgList.Remove(pDlg);
|
|
FocusNextRecvDlg();
|
|
}
|
|
|
|
|
|
BOOL CAppletWindow::IsReceiving(void)
|
|
{
|
|
BOOL fRet = FALSE;
|
|
CRecvDlg *pDlg;
|
|
CUiRecvFileInfo *pRecvFile;
|
|
m_RecvDlgList.Reset();
|
|
while (NULL != (pDlg = m_RecvDlgList.Iterate()))
|
|
{
|
|
pRecvFile = pDlg->GetRecvFileInfo();
|
|
if (pRecvFile && (pRecvFile->GetTotalRecvSize() < pRecvFile->GetSize()))
|
|
{
|
|
fRet = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
CRecvDlg * CAppletWindow::FindDlgByHandles(MBFTEVENTHANDLE nEventHandle, MBFTFILEHANDLE nFileHandle)
|
|
{
|
|
CRecvDlg *pDlg;
|
|
m_RecvDlgList.Reset();
|
|
while (NULL != (pDlg = m_RecvDlgList.Iterate()))
|
|
{
|
|
if (nEventHandle == pDlg->GetEventHandle() &&
|
|
nFileHandle == pDlg->GetFileHandle())
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
return pDlg;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// WM_CREATE
|
|
//
|
|
|
|
LRESULT OnCreate(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
CREATESTRUCT *p = (CREATESTRUCT *) lParam;
|
|
CAppletWindow *pWindow = (CAppletWindow *) p->lpCreateParams;
|
|
|
|
ASSERT(NULL != pWindow);
|
|
::SetWindowLongPtr(hwnd, GWLP_USERDATA, (LPARAM) p->lpCreateParams);
|
|
|
|
pWindow->SetHwnd(hwnd);
|
|
|
|
::InitCommonControls();
|
|
|
|
pWindow->CreateToolBar();
|
|
pWindow->CreateStatusBar();
|
|
pWindow->CreateListView();
|
|
|
|
::DragAcceptFiles(hwnd, g_fSendAllowed);
|
|
|
|
// resize the window
|
|
MINMAXINFO mmi;
|
|
::ZeroMemory(&mmi, sizeof(mmi));
|
|
pWindow->OnGetMinMaxInfo(&mmi);
|
|
RECT rcUI;
|
|
|
|
::GetWindowRect(pWindow->GetHwnd(), &rcUI);
|
|
rcUI.right = mmi.ptMinTrackSize.x;
|
|
rcUI.bottom = mmi.ptMinTrackSize.y + 30;
|
|
OPT_GetFTWndPosition(&rcUI);
|
|
|
|
::MoveWindow(pWindow->GetHwnd(), rcUI.left, rcUI.top,
|
|
rcUI.right, rcUI.bottom, TRUE);
|
|
|
|
pWindow->UpdateUI();
|
|
|
|
#if defined(TEST_PLUGABLE) && defined(_DEBUG)
|
|
::OnPluggableBegin(hwnd);
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
|
|
enum
|
|
{
|
|
TB_IDX_ADD_FILES = 0,
|
|
TB_IDX_REMOVE_FILES,
|
|
TB_IDX_BREAK_1,
|
|
TB_IDX_IDM_SEND_ALL,
|
|
TB_IDX_IDM_SEND_ONE,
|
|
TB_IDX_IDM_STOP_SENDING,
|
|
TB_IDX_BREAK_2,
|
|
TB_IDX_IDM_OPEN_RECV_FOLDER,
|
|
TB_IDX_IDM_CHANGE_FOLDER,
|
|
TB_IDX_BREAK_3,
|
|
TB_IDX_IDM_HELP,
|
|
};
|
|
|
|
|
|
static Buttons buttons [] =
|
|
{
|
|
{IDB_ADDFILES, CBitmapButton::Disabled+1, 1, IDM_ADD_FILES, (LPCSTR)IDS_MENU_ADD_FILES,},
|
|
{IDB_REMOVEFILES, CBitmapButton::Disabled+1, 1, IDM_REMOVE_FILES, (LPCSTR)IDS_MENU_REMOVE_FILES,},
|
|
{0, 0, 0, 0, 0,},
|
|
{IDB_SENDFILE, CBitmapButton::Disabled+1, 1, IDM_SEND_ALL, (LPCSTR)IDS_MENU_SEND_ALL,},
|
|
{IDB_STOPSEND, CBitmapButton::Disabled+1, 1, IDM_STOP_SENDING, (LPCSTR)IDS_MENU_STOP_SENDING,},
|
|
{0, 0, 0, 0, 0,},
|
|
{IDB_FOLDER, CBitmapButton::Disabled+1, 1, IDM_OPEN_RECV_FOLDER, (LPCSTR)IDS_MENU_OPEN_RECV_FOLDER,},
|
|
{0, 0, 0, 0, 0},
|
|
};
|
|
|
|
|
|
BOOL CAppletWindow::CreateToolBar(void)
|
|
{
|
|
DBG_SAVE_FILE_LINE
|
|
m_pToolbar = new CComboToolbar();
|
|
if (m_pToolbar)
|
|
{
|
|
m_pToolbar->Create(m_hwndMainUI, &buttons[0], count_of(buttons), this);
|
|
m_pToolbar->Release();
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL CAppletWindow::CreateStatusBar(void)
|
|
{
|
|
m_hwndStatusBar = ::CreateWindowEx(0,
|
|
STATUSCLASSNAME, // status bar class
|
|
TEXT(""), // no default text
|
|
WS_CHILD | WS_VISIBLE | SBS_SIZEGRIP,
|
|
0, 0, 0, 0,
|
|
m_hwndMainUI,
|
|
(HMENU) IDC_STATUS_BAR,
|
|
g_hDllInst,
|
|
NULL);
|
|
ASSERT(NULL != m_hwndStatusBar);
|
|
if (NULL != m_hwndStatusBar)
|
|
{
|
|
// Load Call Icons
|
|
m_hIconInCall = (HICON) ::LoadImage(g_hDllInst,
|
|
MAKEINTRESOURCE(IDI_INCALL),
|
|
IMAGE_ICON,
|
|
::GetSystemMetrics(SM_CXSMICON),
|
|
::GetSystemMetrics(SM_CYSMICON),
|
|
LR_DEFAULTCOLOR);
|
|
m_hIconNotInCall = (HICON) ::LoadImage(g_hDllInst,
|
|
MAKEINTRESOURCE(IDI_NOT_INCALL),
|
|
IMAGE_ICON,
|
|
::GetSystemMetrics(SM_CXSMICON),
|
|
::GetSystemMetrics(SM_CYSMICON),
|
|
LR_DEFAULTCOLOR);
|
|
if (CreateProgressBar())
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL CAppletWindow::CreateProgressBar(void)
|
|
{
|
|
RECT rcl;
|
|
|
|
GetClientRect(m_hwndStatusBar, &rcl);
|
|
m_hwndProgressBar = ::CreateWindowEx(0, PROGRESS_CLASS, TEXT(""),
|
|
WS_CHILD | WS_VISIBLE | PBS_SMOOTH,
|
|
rcl.right/2 + 2, 2, rcl.right - rcl.right/2 - 40, rcl.bottom - 8,
|
|
m_hwndStatusBar, (HMENU)IDC_PROGRESS_BAR,
|
|
g_hDllInst, NULL);
|
|
|
|
if (m_hwndProgressBar)
|
|
{
|
|
::SendMessage(m_hwndProgressBar, PBM_SETRANGE, 0L, MAKELONG(0, 100));
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL CAppletWindow::CreateListView(void)
|
|
{
|
|
// get the size and position of the main window
|
|
RECT rcWindow, rcToolBar, rcStatusBar;
|
|
SIZE szToolBar;
|
|
::GetClientRect(m_hwndMainUI, &rcWindow);
|
|
m_pToolbar->GetDesiredSize(&szToolBar);
|
|
::GetWindowRect(m_hwndStatusBar, &rcStatusBar);
|
|
|
|
ULONG x = 0;
|
|
ULONG y = szToolBar.cy - 1;
|
|
ULONG cx = rcWindow.right - rcWindow.left;
|
|
ULONG cy = rcWindow.bottom - rcWindow.top - y - (rcStatusBar.bottom - rcStatusBar.top) + 1;
|
|
|
|
// create the list view window
|
|
m_hwndListView = ::CreateWindowEx(WS_EX_CLIENTEDGE, // sunken look
|
|
WC_LISTVIEW , // list view class
|
|
TEXT(""), // no default text
|
|
WS_VISIBLE | WS_CHILD | WS_BORDER | LVS_REPORT |WS_TABSTOP |
|
|
LVS_AUTOARRANGE | WS_CLIPCHILDREN | LVS_SHOWSELALWAYS,
|
|
x, y, cx, cy,
|
|
m_hwndMainUI,
|
|
(HMENU) IDC_LIST_VIEW,
|
|
g_hDllInst,
|
|
NULL);
|
|
ASSERT(NULL != m_hwndListView);
|
|
if (NULL != m_hwndListView)
|
|
{
|
|
// set extended list view styles
|
|
DWORD dwExtStyle = ListView_GetExtendedListViewStyle(m_hwndListView);
|
|
dwExtStyle |= (LVS_EX_HEADERDRAGDROP | LVS_EX_SUBITEMIMAGES | LVS_EX_FULLROWSELECT);
|
|
ListView_SetExtendedListViewStyle(m_hwndListView, dwExtStyle);
|
|
|
|
// enable window only if we can send files
|
|
::EnableWindow(m_hwndListView, g_fSendAllowed);
|
|
|
|
// set up the columns
|
|
ULONG i;
|
|
LVCOLUMN lvc;
|
|
LVITEM lvi;
|
|
TCHAR szText[64];
|
|
int iColumnSize[NUM_LIST_VIEW_COLUMNS] = {150, 80, 70, 130}; // listview column size
|
|
|
|
// initialize the common part of the columns
|
|
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
|
|
lvc.fmt = LVCFMT_LEFT; // left-aligned column
|
|
lvc.pszText = szText;
|
|
|
|
// initialize columns one by one
|
|
for (i = 0; i < NUM_LIST_VIEW_COLUMNS; i++)
|
|
{
|
|
lvc.iSubItem = i;
|
|
::LoadString(g_hDllInst, IDS_LV_FILE_NAME + i, szText, count_of(szText));
|
|
lvc.cx = iColumnSize[i];
|
|
int iRet = ListView_InsertColumn(m_hwndListView, lvc.iSubItem, &lvc);
|
|
ASSERT(-1 != iRet);
|
|
}
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
BOOL CAppletWindow::DrawItem(LPDRAWITEMSTRUCT pdis)
|
|
{
|
|
ASSERT(pdis);
|
|
if (NULL != (pdis->itemData))
|
|
{
|
|
int nWidth = pdis->rcItem.right - pdis->rcItem.left;
|
|
int nHeight = pdis->rcItem.bottom - pdis->rcItem.top;
|
|
int nLeft = pdis->rcItem.left;
|
|
int nTop = pdis->rcItem.top;
|
|
int xSmIcon = ::GetSystemMetrics(SM_CXSMICON);
|
|
int ySmIcon = ::GetSystemMetrics(SM_CYSMICON);
|
|
|
|
if (nWidth > xSmIcon)
|
|
{
|
|
nLeft += (nWidth - xSmIcon) / 2 - 5;
|
|
nWidth = xSmIcon;
|
|
}
|
|
if (nHeight > ySmIcon)
|
|
{
|
|
nTop += (nHeight - ySmIcon) / 2;
|
|
nHeight = ySmIcon;
|
|
}
|
|
|
|
::DrawIconEx( pdis->hDC,
|
|
nLeft,
|
|
nTop,
|
|
(HICON) (pdis->itemData),
|
|
nWidth,
|
|
nHeight,
|
|
0,
|
|
NULL,
|
|
DI_NORMAL);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void CAppletWindow::OnCommand(WORD wId, HWND hwndCtl, WORD codeNotify)
|
|
{
|
|
switch (wId)
|
|
{
|
|
case IDM_ADD_FILES:
|
|
OnAddFiles();
|
|
UpdateUI();
|
|
break;
|
|
|
|
case IDM_REMOVE_FILES:
|
|
OnRemoveFiles();
|
|
UpdateUI();
|
|
break;
|
|
|
|
case IDM_SEND_ALL:
|
|
s_cMsgBox2Dlg = 0;
|
|
SetSendMode(TRUE);
|
|
OnSendAll();
|
|
UpdateUI();
|
|
break;
|
|
|
|
case IDM_SEND_ONE:
|
|
s_cMsgBox2Dlg = 0;
|
|
SetSendMode(FALSE);
|
|
OnSendOne();
|
|
UpdateUI();
|
|
break;
|
|
|
|
case IDM_STOP_SENDING:
|
|
OnStopSending();
|
|
UpdateUI();
|
|
break;
|
|
|
|
case IDM_OPEN_RECV_FOLDER:
|
|
OnOpenRecvFolder();
|
|
break;
|
|
|
|
case IDM_CHANGE_FOLDER:
|
|
OnChangeFolder();
|
|
break;
|
|
|
|
case IDM_EXIT:
|
|
OnExit();
|
|
break;
|
|
|
|
case IDM_HELP:
|
|
OnHelp();
|
|
break;
|
|
|
|
case ID_NAV_TAB:
|
|
ShiftFocus(m_hwndMainUI, TRUE);
|
|
if(GetFocus() == m_hwndListView)
|
|
{
|
|
SetListViewFocus();
|
|
}
|
|
break;
|
|
|
|
case ID_NAV_SHIFT_TAB:
|
|
ShiftFocus(m_hwndMainUI, FALSE);
|
|
if(GetFocus() == m_hwndListView)
|
|
{
|
|
SetListViewFocus();
|
|
|
|
}
|
|
break;
|
|
|
|
case IDM_ABOUT:
|
|
OnAbout();
|
|
break;
|
|
|
|
default:
|
|
WARNING_OUT(("FT::OnCommand: unknown command ID=%u", (UINT) wId));
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// WM_COMMAND
|
|
//
|
|
|
|
LRESULT OnCommand(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
|
if (NULL != pWindow)
|
|
{
|
|
WORD wNotifyCode = GET_WM_COMMAND_CMD(wParam, lParam); // notification code
|
|
WORD wID = GET_WM_COMMAND_ID(wParam, lParam); // item, control, or accelerator identifier
|
|
HWND hwndCtl = (HWND) lParam; // handle of control
|
|
|
|
pWindow->OnCommand(wID, hwndCtl, wNotifyCode);
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
WARNING_OUT((" CAppletWindow::OnCommand--Received unhandled window message.\n"));
|
|
}
|
|
return (DefWindowProc(hwnd, WM_COMMAND, wParam, lParam));
|
|
}
|
|
|
|
|
|
//
|
|
// OnAddFiles
|
|
//
|
|
|
|
UINT_PTR APIENTRY SendFileDlgHookProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if (WM_INITDIALOG == uMsg)
|
|
{
|
|
hdlg = ::GetParent(hdlg); // Real dialog is this window's parent
|
|
|
|
if (::MyLoadString(IDS_FILEDLG_SEND))
|
|
{
|
|
::SetDlgItemText(hdlg, IDOK, s_szScratchText);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void CAppletWindow::OnAddFiles(void)
|
|
{
|
|
TCHAR szTitle[MAX_PATH];
|
|
TCHAR szFilter[MAX_PATH];
|
|
TCHAR szDirSav[MAX_PATH];
|
|
TCHAR szSendDir[MAX_PATH];
|
|
|
|
// Load dialog title and filter strings
|
|
if (::MyLoadString(IDS_FILEDLG_TITLE, szTitle) &&
|
|
::MyLoadString(IDS_FILEDLG_FILTER, szFilter))
|
|
{
|
|
// replace '|' to '\0'
|
|
LPTSTR pszFltr = szFilter;
|
|
while (TEXT('\0') != *pszFltr)
|
|
{
|
|
if (TEXT('|') == *pszFltr)
|
|
{
|
|
*pszFltr = TEXT('\0');
|
|
pszFltr++; // cannot use CharNext
|
|
}
|
|
else
|
|
{
|
|
pszFltr = ::CharNext(pszFltr);
|
|
}
|
|
}
|
|
|
|
// only allow one "Select a file to send" dialog
|
|
if (! m_fInFileOpenDialog)
|
|
{
|
|
m_fInFileOpenDialog = TRUE;
|
|
|
|
// Allocate a really large buffer to hold the file list
|
|
ULONG cbBufSize = 8192;
|
|
DBG_SAVE_FILE_LINE
|
|
LPTSTR pszBuffer = new TCHAR[cbBufSize];
|
|
if (NULL != pszBuffer)
|
|
{
|
|
*pszBuffer = TEXT('\0'); // start with null string
|
|
|
|
OPENFILENAME ofn;
|
|
::ZeroMemory(&ofn, sizeof(ofn));
|
|
ofn.lStructSize = sizeof(ofn);
|
|
ofn.hwndOwner = m_hwndMainUI;
|
|
ofn.hInstance = g_hDllInst;
|
|
ofn.lpstrFilter = &szFilter[0];
|
|
ofn.nFilterIndex = 1L; // FUTURE: remember filter preference
|
|
ofn.lpstrFile = pszBuffer;
|
|
ofn.nMaxFile = cbBufSize - 1; // Number of TCHAR in pszFiles (not including NULL)
|
|
ofn.lpstrTitle = &szTitle[0];
|
|
ofn.lpstrInitialDir = m_szDefaultDir;
|
|
ofn.lpfnHook = SendFileDlgHookProc;
|
|
|
|
ofn.Flags = OFN_ALLOWMULTISELECT | OFN_ENABLEHOOK | // OFN_HIDEREADONLY |
|
|
OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_EXPLORER;
|
|
|
|
// remember current directory
|
|
::ZeroMemory(szSendDir, sizeof(szSendDir));
|
|
::GetCurrentDirectory(count_of(szDirSav), szDirSav);
|
|
::lstrcpyn(szSendDir, szDirSav, count_of(szSendDir));
|
|
|
|
if (::GetOpenFileName(&ofn))
|
|
{
|
|
// if there is only a single file, the first string is the full path.
|
|
// if there are more than one file, the first string is the directory path
|
|
// and followed by a list of file names. terminated by double null
|
|
|
|
// remember the working directory for next time
|
|
ULONG cchDirPath;
|
|
LPTSTR pszFileName;
|
|
ULONG cchFile = ::lstrlen(ofn.lpstrFile);
|
|
if (TEXT('\0') == ofn.lpstrFile[cchFile] && TEXT('\0') == ofn.lpstrFile[cchFile+1])
|
|
{
|
|
//
|
|
// only a single file
|
|
//
|
|
pszFileName = ::PathNameToFileName(ofn.lpstrFile);
|
|
cchDirPath = (ULONG)(pszFileName - ofn.lpstrFile);
|
|
if (cchDirPath)
|
|
{
|
|
cchDirPath--; // back to '\\'
|
|
}
|
|
ASSERT(TEXT('\\') == ofn.lpstrFile[cchDirPath]);
|
|
ofn.lpstrFile[cchDirPath] = TEXT('\0');
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// multiple files
|
|
//
|
|
cchDirPath = ::lstrlen(ofn.lpstrFile);
|
|
pszFileName = ofn.lpstrFile + cchDirPath + 1;
|
|
}
|
|
::lstrcpy(m_szDefaultDir, ofn.lpstrFile);
|
|
|
|
EnsureTrailingSlash(m_szDefaultDir);
|
|
|
|
::ZeroMemory(szSendDir, sizeof(szSendDir));
|
|
::CopyMemory(szSendDir, ofn.lpstrFile, cchDirPath * sizeof(TCHAR));
|
|
EnsureTrailingSlash(szSendDir);
|
|
|
|
// set up the common portion of list view item
|
|
LVITEM lvi;
|
|
::ZeroMemory(&lvi, sizeof(lvi));
|
|
// lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
|
|
lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
|
|
|
|
// iterate the file name
|
|
while ('\0' != *pszFileName)
|
|
{
|
|
BOOL fRet;
|
|
DBG_SAVE_FILE_LINE
|
|
CUiSendFileInfo *pFileInfo = new CUiSendFileInfo(this, szSendDir, pszFileName, &fRet);
|
|
if (NULL != pFileInfo && fRet)
|
|
{
|
|
// put it to the list view
|
|
lvi.iItem = ListView_GetItemCount(m_hwndListView);
|
|
lvi.iSubItem = 0;
|
|
// we are responsible for storing the text to display
|
|
lvi.pszText = LPSTR_TEXTCALLBACK;
|
|
lvi.cchTextMax = MAX_PATH;
|
|
lvi.lParam = (LPARAM) pFileInfo;
|
|
int iRet = ListView_InsertItem(m_hwndListView, &lvi);
|
|
ASSERT(-1 != iRet);
|
|
// UpdateListView(pFileInfo);
|
|
}
|
|
else
|
|
{
|
|
delete pFileInfo;
|
|
}
|
|
|
|
// get to the next file name
|
|
pszFileName += ::lstrlen(pszFileName) + 1;
|
|
} // while
|
|
}
|
|
else
|
|
{
|
|
// err code for cancel is zero, which is ok.
|
|
ASSERT(! ::CommDlgExtendedError());
|
|
}
|
|
|
|
// restore old working directory
|
|
::SetCurrentDirectory(szDirSav);
|
|
}
|
|
|
|
delete [] pszBuffer;
|
|
m_fInFileOpenDialog = FALSE;
|
|
}
|
|
else
|
|
{
|
|
// bring the active dialog to the front
|
|
BringToFront();
|
|
}
|
|
} // if LoadString
|
|
}
|
|
|
|
|
|
//
|
|
// OnRemoveFiles
|
|
//
|
|
|
|
void CAppletWindow::OnRemoveFiles(void)
|
|
{
|
|
UINT nState;
|
|
ULONG cItems = ListView_GetItemCount(m_hwndListView);
|
|
LVITEM lvi;
|
|
::ZeroMemory(&lvi, sizeof(lvi));
|
|
lvi.mask = LVIF_PARAM | LVIF_STATE;
|
|
lvi.stateMask = LVIS_SELECTED;
|
|
ULONG i = 0;
|
|
while (i < cItems)
|
|
{
|
|
lvi.iItem = i;
|
|
BOOL fRet = ListView_GetItem(m_hwndListView, &lvi);
|
|
if (fRet && lvi.state & LVIS_SELECTED)
|
|
{
|
|
CUiSendFileInfo *pFileInfo = (CUiSendFileInfo *) lvi.lParam;
|
|
if (pFileInfo == m_pCurrSendFileInfo)
|
|
{
|
|
OnStopSending();
|
|
ClearSendInfo(FALSE);
|
|
}
|
|
delete pFileInfo;
|
|
|
|
fRet = ListView_DeleteItem(m_hwndListView, i);
|
|
ASSERT(fRet);
|
|
|
|
cItems--;
|
|
ASSERT((ULONG) ListView_GetItemCount(m_hwndListView) == cItems);
|
|
}
|
|
else
|
|
{
|
|
i++;
|
|
}
|
|
}
|
|
if (cItems > 0) // set focus to first remaining item
|
|
{
|
|
SetListViewFocus();
|
|
}
|
|
}
|
|
|
|
|
|
void CAppletWindow::OnRemoveAllFiles(void)
|
|
{
|
|
BOOL fRet;
|
|
CUiSendFileInfo *pFileInfo;
|
|
ULONG cItems = ListView_GetItemCount(m_hwndListView);
|
|
LVITEM lvi;
|
|
::ZeroMemory(&lvi, sizeof(lvi));
|
|
lvi.mask = LVIF_PARAM;
|
|
for (ULONG i = 0; i < cItems; i++)
|
|
{
|
|
lvi.iItem = i;
|
|
fRet = ListView_GetItem(m_hwndListView, &lvi);
|
|
ASSERT(fRet);
|
|
pFileInfo = (CUiSendFileInfo *) lvi.lParam;
|
|
if (pFileInfo == m_pCurrSendFileInfo)
|
|
{
|
|
ClearSendInfo(FALSE);
|
|
}
|
|
delete pFileInfo;
|
|
}
|
|
|
|
fRet = ListView_DeleteAllItems(m_hwndListView);
|
|
ASSERT(fRet);
|
|
}
|
|
|
|
|
|
void CAppletWindow::OnSendAll(void)
|
|
{
|
|
if ((NULL == m_pCurrSendFileInfo)&&(NULL != m_pEngine))
|
|
{
|
|
CUiSendFileInfo *pFileInfo = ChooseFirstUnSentFile();
|
|
SendNow(pFileInfo);
|
|
}
|
|
}
|
|
|
|
void CAppletWindow::OnSendOne(void)
|
|
{
|
|
if ((NULL == m_pCurrSendFileInfo)&&(NULL != m_pEngine))
|
|
{
|
|
CUiSendFileInfo *pFileInfo = ChooseSelectedFile();
|
|
if (!pFileInfo)
|
|
{
|
|
pFileInfo = ChooseFirstUnSentFile();
|
|
}
|
|
SendNow(pFileInfo);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// SendNow
|
|
//
|
|
|
|
BOOL CAppletWindow::SendNow(CUiSendFileInfo *pFileInfo)
|
|
{
|
|
BOOL fRet;
|
|
|
|
if (NULL != pFileInfo)
|
|
{
|
|
// send this file now...
|
|
m_pCurrSendFileInfo = pFileInfo;
|
|
m_nCurrSendEventHandle = ::GetNewEventHandle();
|
|
pFileInfo->SetFileHandle(::GetNewFileHandle());
|
|
|
|
// duplicate full file name
|
|
ULONG cbSize = ::lstrlen(pFileInfo->GetFullName()) + 1;
|
|
DBG_SAVE_FILE_LINE
|
|
LPTSTR pszFullName = new TCHAR[cbSize];
|
|
if (NULL != pszFullName)
|
|
{
|
|
::CopyMemory(pszFullName, pFileInfo->GetFullName(), cbSize);
|
|
|
|
DBG_SAVE_FILE_LINE
|
|
if (S_OK == m_pEngine->SafePostMessage(
|
|
new CreateSessionMsg(MBFT_PRIVATE_SEND_TYPE,
|
|
m_nCurrSendEventHandle)))
|
|
{
|
|
int iSelect;
|
|
MEMBER_ID nMemberID;
|
|
iSelect = m_pToolbar->GetSelectedItem((LPARAM*)&nMemberID);
|
|
if (0 == iSelect)
|
|
{ // Send to All
|
|
DBG_SAVE_FILE_LINE
|
|
if (S_OK == m_pEngine->SafePostMessage(
|
|
new SubmitFileSendMsg(0, 0, pszFullName,
|
|
pFileInfo->GetFileHandle(),
|
|
m_nCurrSendEventHandle,
|
|
FALSE)))
|
|
{
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
ERROR_OUT(("CAppletWindow::SendNow: cannot create SubmitFileSendMsg"));
|
|
}
|
|
}
|
|
else
|
|
{ // Send to one
|
|
T120UserID uidRecv = GET_PEER_ID_FROM_MEMBER_ID(nMemberID);
|
|
|
|
DBG_SAVE_FILE_LINE
|
|
if (S_OK == m_pEngine->SafePostMessage(
|
|
new SubmitFileSendMsg(uidRecv, 0, pszFullName,
|
|
pFileInfo->GetFileHandle(),
|
|
m_nCurrSendEventHandle,
|
|
FALSE)))
|
|
{
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
ERROR_OUT(("CAppletWindow::SendNow: cannot create SubmitFileSendMsg to 1"));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ERROR_OUT(("CAppletWindow::SendNow: cannot create CreateSessionMsg"));
|
|
}
|
|
|
|
delete [] pszFullName;
|
|
}
|
|
ClearSendInfo(TRUE);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
CUiSendFileInfo *CAppletWindow::ChooseFirstUnSentFile(void)
|
|
{
|
|
CUiSendFileInfo *pFileInfo = NULL;
|
|
ULONG cItems = ListView_GetItemCount(m_hwndListView);
|
|
|
|
if (cItems > 0)
|
|
{
|
|
// examine each item one by one
|
|
LVITEM lvi;
|
|
::ZeroMemory(&lvi, sizeof(lvi));
|
|
lvi.mask = LVIF_PARAM;
|
|
for (ULONG i = 0; i < cItems; i++, pFileInfo = NULL)
|
|
{
|
|
lvi.iItem = i;
|
|
BOOL fRet = ListView_GetItem(m_hwndListView, &lvi);
|
|
ASSERT(fRet);
|
|
pFileInfo = (CUiSendFileInfo *) lvi.lParam;
|
|
// if file handle is not zero, then it has been sent
|
|
if (! pFileInfo->GetFileHandle())
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return pFileInfo;
|
|
}
|
|
|
|
CUiSendFileInfo *CAppletWindow::ChooseSelectedFile(void)
|
|
{
|
|
CUiSendFileInfo *pFileInfo = NULL;
|
|
ULONG cItems = ListView_GetItemCount(m_hwndListView);
|
|
LVITEM lvi;
|
|
::ZeroMemory(&lvi, sizeof(lvi));
|
|
lvi.mask = LVIF_PARAM | LVIF_STATE;
|
|
lvi.stateMask = LVIS_SELECTED;
|
|
ULONG i = 0;
|
|
while (i < cItems)
|
|
{
|
|
lvi.iItem = i;
|
|
BOOL fRet = ListView_GetItem(m_hwndListView, &lvi);
|
|
if (fRet && lvi.state & LVIS_SELECTED)
|
|
{
|
|
pFileInfo = (CUiSendFileInfo *) lvi.lParam;
|
|
pFileInfo->SetErrorCode(iMBFT_OK);
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
i++;
|
|
pFileInfo = NULL;
|
|
}
|
|
}
|
|
return pFileInfo;
|
|
}
|
|
|
|
|
|
//
|
|
// OnMenuSelect
|
|
//
|
|
|
|
void CAppletWindow::OnMenuSelect(UINT uiItemID, UINT uiFlags, HMENU hSysMenu)
|
|
{
|
|
UINT firstMenuId;
|
|
UINT statusId;
|
|
|
|
//
|
|
// Work out the help ID for the menu item. We have to store this now
|
|
// because when the user presses F1 from a menu item, we can't tell
|
|
// which item it was.
|
|
//
|
|
|
|
if ((uiFlags & MF_POPUP) && (uiFlags & MF_SYSMENU))
|
|
{
|
|
// System menu selected
|
|
statusId = (m_pCurrSendFileInfo)?IDS_STBAR_SENDING_XYZ:IDS_STBAR_NOT_TRANSFERING;
|
|
}
|
|
else if (uiFlags & MF_POPUP)
|
|
{
|
|
// get popup menu handle and first item
|
|
HMENU hPopup = ::GetSubMenu( hSysMenu, uiItemID );
|
|
firstMenuId = ::GetMenuItemID( hPopup, 0 );
|
|
|
|
switch(firstMenuId)
|
|
{
|
|
case IDM_ADD_FILES:
|
|
statusId = IDS_MENU_FILE;
|
|
break;
|
|
|
|
case IDM_HELP:
|
|
statusId = IDS_MENU_HELP;
|
|
break;
|
|
|
|
default:
|
|
statusId = (m_pCurrSendFileInfo)?IDS_STBAR_SENDING_XYZ:IDS_STBAR_NOT_TRANSFERING;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// A normal menu item has been selected
|
|
statusId = uiItemID;
|
|
}
|
|
|
|
// Set the new help text
|
|
TCHAR szStatus[256];
|
|
|
|
if (::LoadString(g_hDllInst, statusId, szStatus, 256))
|
|
{
|
|
::SendMessage(m_hwndStatusBar, SB_SETTEXT, SBP_TRANSFER_FILE, (LPARAM)szStatus);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// OnStopSending
|
|
//
|
|
|
|
void CAppletWindow::OnStopSending(void)
|
|
{
|
|
m_fSendALL = FALSE;
|
|
if (m_nCurrSendEventHandle)
|
|
{
|
|
DBG_SAVE_FILE_LINE
|
|
HRESULT hr = m_pEngine->SafePostMessage(
|
|
new FileTransferControlMsg(
|
|
m_nCurrSendEventHandle,
|
|
m_pCurrSendFileInfo->GetFileHandle(),
|
|
NULL,
|
|
NULL,
|
|
FileTransferControlMsg::EnumAbortFile));
|
|
ASSERT(hr == S_OK);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// OnOpenRecvFolder
|
|
//
|
|
|
|
void CAppletWindow::OnOpenRecvFolder(void)
|
|
{
|
|
TCHAR szRecvFolder[MAX_PATH];
|
|
|
|
while (1)
|
|
{
|
|
if (S_OK == ::GetRecvFolder(NULL, szRecvFolder))
|
|
{
|
|
::ShellExecute(NULL, NULL, szRecvFolder, NULL, NULL, SW_SHOWNORMAL);
|
|
break;
|
|
}
|
|
else if (m_UIMode != FTUIMODE_NOUI)
|
|
{
|
|
::MyLoadString(IDS_RECVDLG_DIRNOEXIST, s_szScratchText, szRecvFolder);
|
|
if (IDYES == ::MessageBox(m_hwndMainUI, s_szScratchText, s_szMSFT, MB_YESNO))
|
|
{
|
|
OnChangeFolder();
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// OnChageFolder
|
|
//
|
|
|
|
void OnChangeFolder(void)
|
|
{
|
|
BOOL rc;
|
|
TCHAR szPath[MAX_PATH];
|
|
|
|
::GetRecvFolder(NULL, szPath);
|
|
if (::lstrlen(szPath) > MAX_FILE_NAME_LENGTH)
|
|
{
|
|
LPTSTR psz = szPath;
|
|
int i = MAX_FILE_NAME_LENGTH - 1;
|
|
while (i)
|
|
{
|
|
psz = CharNext(psz);
|
|
i--;
|
|
}
|
|
::lstrcpy(psz, TEXT("..."));
|
|
}
|
|
::MyLoadString(IDS_BROWSETITLE, s_szScratchText, szPath);
|
|
|
|
if (FBrowseForFolder(szPath, CCHMAX(szPath), s_szScratchText))
|
|
{
|
|
::GetRecvFolder(szPath, szPath);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// OnExit
|
|
//
|
|
|
|
void CAppletWindow::OnExit(BOOL fNoQuery)
|
|
{
|
|
if ((g_pFileXferApplet->InConf() || g_pFileXferApplet->HasSDK())
|
|
&& ! g_fShutdownByT120)
|
|
{
|
|
// There 2.x node inside the conference
|
|
// hide the window
|
|
::ShowWindow(m_hwndMainUI, SW_HIDE);
|
|
m_UIMode = g_fNoUI ? FTUIMODE_NOUI : FTUIMODE_UIHIDDEN;
|
|
}
|
|
else
|
|
if (fNoQuery || QueryShutdown())
|
|
{
|
|
#if defined(TEST_PLUGABLE) && defined(_DEBUG)
|
|
::OnPluggableEnd();
|
|
#endif
|
|
|
|
MBFTEngine *pEngine = m_pEngine;
|
|
|
|
::T120_AppletStatus(APPLET_ID_FT, APPLET_CLOSING);
|
|
|
|
if (NULL != m_pEngine)
|
|
{
|
|
GCCAppPermissionToEnrollInd Ind;
|
|
::ZeroMemory(&Ind, sizeof(Ind));
|
|
Ind.nConfID = m_pEngine->GetConfID();
|
|
Ind.fPermissionGranted = FALSE;
|
|
m_pEngine->OnPermitToEnrollIndication(&Ind);
|
|
UnregisterEngine();
|
|
}
|
|
|
|
OnRemoveAllFiles();
|
|
|
|
::SetWindowLongPtr(m_hwndMainUI, GWLP_USERDATA, 0);
|
|
|
|
SaveWindowPosition();
|
|
HWND hwnd = m_hwndMainUI;
|
|
m_hwndMainUI = NULL;
|
|
::DestroyWindow(hwnd);
|
|
|
|
if (NULL != g_pFileXferApplet)
|
|
{
|
|
g_pFileXferApplet->UnregisterWindow(this);
|
|
g_pFileXferApplet->UnregisterEngine(pEngine);
|
|
}
|
|
|
|
Release();
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// OnHelp
|
|
//
|
|
|
|
void CAppletWindow::OnHelp(void)
|
|
{
|
|
DebugEntry(CAppletWindow::OnHelp);
|
|
ShowNmHelp(s_cszHtmlHelpFile);
|
|
DebugExitVOID(CAppletWindow::OnHelp);
|
|
}
|
|
|
|
|
|
//
|
|
// OnAbout
|
|
//
|
|
|
|
INT_PTR AboutDlgProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
BOOL fHandled = FALSE;
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
TCHAR szFormat[256];
|
|
TCHAR szVersion[512];
|
|
|
|
::GetDlgItemText(hdlg, IDC_ABOUT_VERSION, szFormat, count_of(szFormat));
|
|
::wsprintf(szVersion, szFormat, VER_PRODUCTRELEASE_STR,
|
|
VER_PRODUCTVERSION_STR);
|
|
::SetDlgItemText(hdlg, IDC_ABOUT_VERSION, szVersion);
|
|
|
|
fHandled = TRUE;
|
|
}
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (GET_WM_COMMAND_ID(wParam, lParam))
|
|
{
|
|
case IDOK:
|
|
case IDCANCEL:
|
|
case IDCLOSE:
|
|
switch (GET_WM_COMMAND_CMD(wParam, lParam))
|
|
{
|
|
case BN_CLICKED:
|
|
::EndDialog(hdlg, IDCANCEL);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
fHandled = TRUE;
|
|
break;
|
|
}
|
|
|
|
return(fHandled);
|
|
}
|
|
|
|
void CAppletWindow::OnAbout(void)
|
|
{
|
|
::DialogBoxParam(g_hDllInst, MAKEINTRESOURCE(IDD_ABOUTBOX), m_hwndMainUI,
|
|
AboutDlgProc, 0);
|
|
}
|
|
|
|
|
|
BOOL FBrowseForFolder(LPTSTR pszFolder, UINT cchMax, LPCTSTR pszTitle)
|
|
{
|
|
LPITEMIDLIST pidlRoot;
|
|
if(FAILED(SHGetSpecialFolderLocation(HWND_DESKTOP, CSIDL_DRIVES, &pidlRoot)))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
BROWSEINFO bi;
|
|
ClearStruct(&bi);
|
|
bi.hwndOwner = NULL;
|
|
bi.lpszTitle = pszTitle;
|
|
bi.ulFlags = BIF_RETURNONLYFSDIRS;
|
|
bi.pidlRoot = pidlRoot;
|
|
|
|
LPITEMIDLIST pidl = SHBrowseForFolder(&bi);
|
|
BOOL fRet = (pidl != NULL);
|
|
if (fRet)
|
|
{
|
|
ASSERT(cchMax >= MAX_PATH);
|
|
SHGetPathFromIDList(pidl, pszFolder);
|
|
ASSERT(lstrlen(pszFolder) < (int) cchMax);
|
|
}
|
|
|
|
// Get the shell's allocator to free PIDLs
|
|
LPMALLOC lpMalloc;
|
|
if (FAILED(SHGetMalloc(&lpMalloc)) && (NULL != lpMalloc))
|
|
{
|
|
if (NULL != pidlRoot)
|
|
{
|
|
lpMalloc->Free(pidlRoot);
|
|
}
|
|
if (pidl)
|
|
{
|
|
lpMalloc->Free(pidl);
|
|
}
|
|
lpMalloc->Release();
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// WM_NOTIFY
|
|
//
|
|
|
|
LRESULT OnNotify(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
|
if (NULL != pWindow)
|
|
{
|
|
switch (wParam)
|
|
{
|
|
case IDC_LIST_VIEW:
|
|
pWindow->OnNotifyListView(lParam);
|
|
break;
|
|
|
|
default:
|
|
if (TTN_NEEDTEXT == ((NMHDR *) lParam)->code)
|
|
{
|
|
// display the tool tip text
|
|
TOOLTIPTEXT *pToolTipText = (TOOLTIPTEXT *) lParam;
|
|
ULONG_PTR nID;
|
|
|
|
// get id and hwnd
|
|
if (pToolTipText->uFlags & TTF_IDISHWND)
|
|
{
|
|
// idFrom is actually the HWND of the tool
|
|
nID = ::GetDlgCtrlID((HWND) pToolTipText->hdr.idFrom);
|
|
}
|
|
else
|
|
{
|
|
nID = pToolTipText->hdr.idFrom;
|
|
}
|
|
|
|
// give it to em
|
|
pToolTipText->lpszText = MAKEINTRESOURCE(nID);
|
|
pToolTipText->hinst = g_hDllInst;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int CALLBACK ListViewCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
|
|
{
|
|
CUiSendFileInfo *pFileInfo1 = (CUiSendFileInfo *) lParam1;
|
|
CUiSendFileInfo *pFileInfo2 = (CUiSendFileInfo *) lParam2;
|
|
int iResult;
|
|
|
|
iResult = 0; // equal, at default
|
|
switch (lParamSort)
|
|
{
|
|
case (IDS_LV_FILE_NAME - IDS_LV_FILE_NAME):
|
|
iResult = lstrcmpi(pFileInfo1->GetName(), pFileInfo2->GetName());
|
|
break;
|
|
case (IDS_LV_FILE_SIZE - IDS_LV_FILE_NAME):
|
|
if (pFileInfo1->GetSize() > pFileInfo2->GetSize())
|
|
{
|
|
iResult = 1;
|
|
}
|
|
else
|
|
if (pFileInfo1->GetSize() < pFileInfo2->GetSize())
|
|
{
|
|
iResult = -1;
|
|
}
|
|
break;
|
|
case (IDS_LV_FILE_STATUS - IDS_LV_FILE_NAME):
|
|
if ((pFileInfo1->GetTotalSend() == pFileInfo1->GetSize()) >( pFileInfo2->GetTotalSend() == pFileInfo2->GetSize()))
|
|
{
|
|
iResult = 1;
|
|
}
|
|
else
|
|
if ((pFileInfo1->GetTotalSend() == pFileInfo1->GetSize()) < (pFileInfo2->GetTotalSend() == pFileInfo2->GetSize()))
|
|
{
|
|
iResult = -1;
|
|
}
|
|
break;
|
|
|
|
case (IDS_LV_FILE_MODIFIED - IDS_LV_FILE_NAME):
|
|
FILETIME fTime1 = pFileInfo1->GetLastWrite();
|
|
FILETIME fTime2 = pFileInfo2->GetLastWrite();
|
|
iResult = CompareFileTime(&fTime1,&fTime2);
|
|
break;
|
|
}
|
|
return iResult*s_sort;
|
|
}
|
|
|
|
|
|
void CAppletWindow::OnNotifyListView(LPARAM lParam)
|
|
{
|
|
LV_DISPINFO *pDispInfo = (LV_DISPINFO *) lParam;
|
|
NM_LISTVIEW *pLVN = (NM_LISTVIEW *) lParam;
|
|
FILETIME ftFileTime;
|
|
SYSTEMTIME stSystemTime;
|
|
CUiSendFileInfo *pFileInfo;
|
|
int iSize;
|
|
TCHAR szBuffer[MAX_PATH];
|
|
|
|
|
|
|
|
switch (pLVN->hdr.code)
|
|
{
|
|
case LVN_GETDISPINFO:
|
|
pFileInfo = (CUiSendFileInfo *) pDispInfo->item.lParam;
|
|
ASSERT(NULL != pFileInfo);
|
|
|
|
switch (pDispInfo->item.iSubItem)
|
|
{
|
|
case (IDS_LV_FILE_NAME - IDS_LV_FILE_NAME):
|
|
pDispInfo->item.pszText = pFileInfo->GetName();
|
|
break;
|
|
case (IDS_LV_FILE_SIZE - IDS_LV_FILE_NAME):
|
|
::wsprintf(szBuffer, TEXT("%u"), pFileInfo->GetSize());
|
|
iSize = GetNumberFormat(LOCALE_SYSTEM_DEFAULT, LOCALE_NOUSEROVERRIDE,
|
|
szBuffer, NULL, s_szScratchText, MAX_PATH);
|
|
s_szScratchText[iSize - 4] = '\0'; // remove the trailing ".00"
|
|
pDispInfo->item.pszText = s_szScratchText;
|
|
break;
|
|
case (IDS_LV_FILE_STATUS - IDS_LV_FILE_NAME):
|
|
{
|
|
ULONG cbTotalSend = pFileInfo->GetTotalSend();
|
|
ULONG cbFileSize = pFileInfo->GetSize();
|
|
s_szScratchText[0] = TEXT('\0');
|
|
|
|
switch (pFileInfo->GetErrorCode())
|
|
{
|
|
case iMBFT_OK:
|
|
case iMBFT_MULT_RECEIVER_ABORTED:
|
|
if (!pFileInfo->GetFileHandle())
|
|
break; // handle == NULL, if cbTotalSend == 0, zero length file to be sent.
|
|
if (cbTotalSend >= cbFileSize)
|
|
{
|
|
::MyLoadString(IDS_LV_FILE_SENT);
|
|
}
|
|
else
|
|
if (cbTotalSend)
|
|
{
|
|
if (m_pEngine)
|
|
{
|
|
::MyLoadString(IDS_LV_FILE_SENDING);
|
|
}
|
|
else
|
|
{
|
|
::MyLoadString(IDS_LV_FILE_CANCELED);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case iMBFT_SENDER_ABORTED:
|
|
case iMBFT_RECEIVER_ABORTED:
|
|
case iMBFT_NO_MORE_FILES:
|
|
::MyLoadString(IDS_LV_FILE_CANCELED);
|
|
break;
|
|
|
|
default:
|
|
::MyLoadString(IDS_LV_FILE_FAILED);
|
|
break;
|
|
}
|
|
|
|
pDispInfo->item.pszText = s_szScratchText;
|
|
}
|
|
break;
|
|
|
|
case (IDS_LV_FILE_MODIFIED - IDS_LV_FILE_NAME):
|
|
ftFileTime = pFileInfo->GetLastWrite();
|
|
FileTimeToSystemTime(&ftFileTime, &stSystemTime);
|
|
iSize = GetDateFormat(LOCALE_SYSTEM_DEFAULT, 0, &stSystemTime,
|
|
"MM'/'dd'/'yyyy", s_szScratchText, MAX_PATH);
|
|
GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, &stSystemTime,
|
|
" hh':'mm tt", &s_szScratchText[iSize - 1], MAX_PATH-iSize-1);
|
|
pDispInfo->item.pszText = s_szScratchText;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case LVN_COLUMNCLICK:
|
|
{
|
|
s_sort = s_sort *(-1);
|
|
BOOL fRet = ListView_SortItems(pLVN->hdr.hwndFrom, ListViewCompareProc, (LPARAM) pLVN->iSubItem);
|
|
ASSERT(fRet);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// WM_DROPFILES
|
|
//
|
|
|
|
LRESULT OnDropFiles(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
|
ASSERT(NULL != pWindow);
|
|
|
|
if (g_fSendAllowed)
|
|
{
|
|
return pWindow->OnDropFiles((HANDLE) wParam);
|
|
}
|
|
else
|
|
{
|
|
::MyLoadString(IDS_MSGBOX_POL_PREVENT);
|
|
::MessageBox(pWindow->GetHwnd(), s_szScratchText, s_szMSFT, MB_OK | MB_ICONSTOP);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
LRESULT CAppletWindow::OnDropFiles(HANDLE hDrop)
|
|
{
|
|
if (NULL != m_pEngine && m_pEngine->GetPeerCount() > 1)
|
|
{
|
|
HRESULT hr;
|
|
|
|
// get the number of dropped files
|
|
ULONG cFiles = ::DragQueryFile((HDROP) hDrop, 0xFFFFFFFF, NULL, 0);
|
|
|
|
// set up the common portion of list view item
|
|
LVITEM lvi;
|
|
::ZeroMemory(&lvi, sizeof(lvi));
|
|
// lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
|
|
lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
|
|
|
|
// iterate on these files
|
|
for (ULONG i = 0; i < cFiles; i++)
|
|
{
|
|
BOOL fRet;
|
|
TCHAR szFile[MAX_PATH];
|
|
|
|
if (::DragQueryFile((HDROP) hDrop, i, szFile, count_of(szFile)))
|
|
{
|
|
DBG_SAVE_FILE_LINE
|
|
CUiSendFileInfo *pFileInfo = new CUiSendFileInfo(this, NULL, szFile, &fRet);
|
|
if (NULL != pFileInfo && fRet)
|
|
{
|
|
// put it to the list view
|
|
lvi.iItem = ListView_GetItemCount(m_hwndListView);
|
|
lvi.iSubItem = 0;
|
|
// we are responsible for storing the text to display
|
|
lvi.pszText = LPSTR_TEXTCALLBACK;
|
|
lvi.cchTextMax = MAX_PATH;
|
|
lvi.lParam = (LPARAM) pFileInfo;
|
|
int iRet = ListView_InsertItem(m_hwndListView, &lvi);
|
|
ASSERT(-1 != iRet);
|
|
// UpdateListView(pFileInfo);
|
|
}
|
|
else
|
|
{
|
|
// BUGBUG: we should pop up some error message box here!
|
|
::MyLoadString(IDS_INVALID_FILENAME, s_szScratchText, szFile);
|
|
::MessageBox(m_hwndMainUI, s_szScratchText, s_szMSFT, MB_OK | MB_ICONSTOP);
|
|
delete pFileInfo;
|
|
}
|
|
}
|
|
}
|
|
|
|
::DragFinish((HDROP) hDrop);
|
|
SetForegroundWindow(m_hwndMainUI);
|
|
|
|
UpdateUI();
|
|
return 0;
|
|
}
|
|
|
|
::MyLoadString(IDS_MSGBOX_NO_CONF);
|
|
::SetForegroundWindow(m_hwndMainUI);
|
|
::MessageBox(m_hwndMainUI, s_szScratchText, s_szMSFT, MB_OK | MB_ICONSTOP);
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// WM_CONTEXTMENU
|
|
//
|
|
|
|
LRESULT OnContextMenu(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
LRESULT rc = 0;
|
|
|
|
CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
|
ASSERT(NULL != pWindow);
|
|
|
|
if ((WPARAM) pWindow->GetHwnd() == wParam)
|
|
{
|
|
// BUGBUG use TrackPopupMenu to show context sensitive menu
|
|
pWindow->OnContextMenuForMainUI(lParam);
|
|
}
|
|
else
|
|
if ((WPARAM) pWindow->GetListView() == wParam)
|
|
{
|
|
// BUGBUG use TrackPopupMenu to show context sensitive menu
|
|
pWindow->OnContextMenuForListView(lParam);
|
|
}
|
|
else
|
|
{
|
|
rc = 1;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
enum
|
|
{
|
|
MENU_IDX_ADD_FILES,
|
|
MENU_IDX_REMOVE_FILES,
|
|
MENU_IDX_BREAK_1,
|
|
MENU_IDX_SEND_ALL,
|
|
MENU_IDX_SEND_ONE,
|
|
MENU_IDX_STOP_SENDING,
|
|
MENU_IDX_BREAK_2,
|
|
MENU_IDX_OPEN_RECV_FOLDER,
|
|
};
|
|
|
|
static UI_MENU_INFO s_aMenuInfo[] =
|
|
{
|
|
{ IDS_MENU_ADD_FILES, IDM_ADD_FILES, MF_ENABLED | MF_STRING },
|
|
{ IDS_MENU_REMOVE_FILES, IDM_REMOVE_FILES, MF_ENABLED | MF_STRING },
|
|
{ 0, 0, MF_SEPARATOR}, // menu break
|
|
{ IDS_MENU_SEND_ALL, IDM_SEND_ALL, MF_ENABLED | MF_STRING },
|
|
{ IDS_MENU_SEND_ONE, IDM_SEND_ONE, MF_ENABLED | MF_STRING },
|
|
{ IDS_MENU_STOP_SENDING, IDM_STOP_SENDING, MF_ENABLED | MF_STRING },
|
|
{ 0, 0, MF_SEPARATOR}, // menu break
|
|
{ IDS_MENU_OPEN_RECV_FOLDER, IDM_OPEN_RECV_FOLDER, MF_ENABLED | MF_STRING },
|
|
{ IDS_MENU_CHANGE_FOLDER, IDM_CHANGE_FOLDER, MF_ENABLED | MF_STRING },
|
|
{ 0, 0, MF_SEPARATOR }, // menu break
|
|
{ IDS_MENU_EXIT, IDM_EXIT, MF_ENABLED | MF_STRING },
|
|
};
|
|
|
|
|
|
void CAppletWindow::SetContextMenuStates(void)
|
|
{
|
|
if (g_fSendAllowed)
|
|
{
|
|
BOOL fMoreThanOne = (NULL != m_pEngine) && (m_pEngine->GetPeerCount() > 1);
|
|
s_aMenuInfo[MENU_IDX_ADD_FILES].nFlags = fMoreThanOne ? (MF_ENABLED | MF_STRING) : (MF_GRAYED | MF_STRING);
|
|
|
|
ULONG cItems = ListView_GetItemCount(m_hwndListView);
|
|
s_aMenuInfo[MENU_IDX_REMOVE_FILES].nFlags = cItems ? (MF_ENABLED | MF_STRING) : (MF_GRAYED | MF_STRING);
|
|
s_aMenuInfo[MENU_IDX_SEND_ALL].nFlags = (fMoreThanOne && ! m_nCurrSendEventHandle && HasUnSentFiles(TRUE)) ? (MF_ENABLED | MF_STRING) : (MF_GRAYED | MF_STRING);
|
|
s_aMenuInfo[MENU_IDX_SEND_ONE].nFlags = (fMoreThanOne && ! m_nCurrSendEventHandle && HasUnSentFiles(FALSE)) ? (MF_ENABLED | MF_STRING) : (MF_GRAYED | MF_STRING);
|
|
s_aMenuInfo[MENU_IDX_STOP_SENDING].nFlags = m_nCurrSendEventHandle ? (MF_ENABLED | MF_STRING) : (MF_GRAYED | MF_STRING);
|
|
}
|
|
else
|
|
{
|
|
s_aMenuInfo[MENU_IDX_ADD_FILES].nFlags =(MF_GRAYED | MF_STRING);
|
|
s_aMenuInfo[MENU_IDX_REMOVE_FILES].nFlags =(MF_GRAYED | MF_STRING);
|
|
s_aMenuInfo[MENU_IDX_SEND_ALL].nFlags = (MF_GRAYED | MF_STRING);
|
|
s_aMenuInfo[MENU_IDX_SEND_ONE].nFlags = (MF_GRAYED | MF_STRING);
|
|
s_aMenuInfo[MENU_IDX_STOP_SENDING].nFlags = (MF_GRAYED | MF_STRING);
|
|
}
|
|
}
|
|
|
|
|
|
void CAppletWindow::OnContextMenuForMainUI(LPARAM lParam)
|
|
{
|
|
SetContextMenuStates();
|
|
CreateMenu(lParam, count_of(s_aMenuInfo), &s_aMenuInfo[0]);
|
|
}
|
|
|
|
|
|
void CAppletWindow::OnContextMenuForListView(LPARAM lParam)
|
|
{
|
|
SetContextMenuStates();
|
|
CreateMenu(lParam, 6, &s_aMenuInfo[0]);
|
|
}
|
|
|
|
|
|
void CAppletWindow::CreateMenu(LPARAM lParam, ULONG cItems, UI_MENU_INFO aMenuInfo[])
|
|
{
|
|
HMENU hMenu = ::CreatePopupMenu();
|
|
if (NULL != hMenu)
|
|
{
|
|
for (ULONG i = 0; i < cItems; i++)
|
|
{
|
|
if (aMenuInfo[i].idCommand)
|
|
{
|
|
if (::MyLoadString(aMenuInfo[i].idString))
|
|
{
|
|
::AppendMenu(hMenu, aMenuInfo[i].nFlags, aMenuInfo[i].idCommand, s_szScratchText);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
::AppendMenu(hMenu, aMenuInfo[i].nFlags, 0, 0);
|
|
}
|
|
}
|
|
|
|
::TrackPopupMenu(hMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RIGHTBUTTON,
|
|
GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam),
|
|
0, // reserved, must be zero
|
|
m_hwndMainUI,
|
|
NULL); // ignore
|
|
}
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// WM_SIZE
|
|
//
|
|
|
|
LRESULT OnSize(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
|
ASSERT(NULL != pWindow);
|
|
|
|
pWindow->OnSizeToolBar();
|
|
pWindow->OnSizeStatusBar();
|
|
pWindow->OnSizeListView();
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
void CAppletWindow::OnSizeToolBar(void)
|
|
{
|
|
RECT rcWindow;
|
|
SIZE szToolBar;
|
|
|
|
::GetClientRect(m_hwndMainUI, &rcWindow);
|
|
m_pToolbar->GetDesiredSize(&szToolBar);
|
|
|
|
ULONG cx = rcWindow.right - rcWindow.left;
|
|
ULONG cy = szToolBar.cy;;
|
|
ULONG x = 0;
|
|
ULONG y = 0;
|
|
|
|
::MoveWindow(m_pToolbar->GetWindow(), x, y, cx, cy, TRUE);
|
|
}
|
|
|
|
|
|
void CAppletWindow::OnSizeStatusBar(void)
|
|
{
|
|
RECT rcWindow, rcStatusBar;
|
|
::GetClientRect(m_hwndMainUI, &rcWindow);
|
|
::GetWindowRect(m_hwndStatusBar, &rcStatusBar);
|
|
|
|
ULONG cx = rcWindow.right - rcWindow.left;
|
|
ULONG cy = rcStatusBar.bottom - rcStatusBar.top;
|
|
ULONG x = 0;
|
|
ULONG y = rcWindow.bottom - cy;
|
|
|
|
::MoveWindow(m_hwndStatusBar, x, y, cx, cy, TRUE);
|
|
::MoveWindow(m_hwndProgressBar, x + cx/2, y, cx/2 - 40, cy, TRUE);
|
|
|
|
int aWidths[NUM_STATUS_BAR_PARTS];
|
|
aWidths[0] = cx / 2; // conference state
|
|
aWidths[1] = cx - 40; // transfer name
|
|
aWidths[2] = -1; // transfer percentage
|
|
ASSERT(3 == NUM_STATUS_BAR_PARTS);
|
|
|
|
::SendMessage(m_hwndStatusBar, SB_SETPARTS, NUM_STATUS_BAR_PARTS, (LPARAM) &aWidths[0]);
|
|
}
|
|
|
|
|
|
void CAppletWindow::OnSizeListView(void)
|
|
{
|
|
// get the size and position of the main window
|
|
RECT rcWindow, rcToolBar, rcStatusBar;
|
|
SIZE szToolBar;
|
|
::GetClientRect(m_hwndMainUI, &rcWindow);
|
|
m_pToolbar->GetDesiredSize(&szToolBar);
|
|
::GetWindowRect(m_hwndStatusBar, &rcStatusBar);
|
|
|
|
ULONG x = 0;
|
|
ULONG y = szToolBar.cy - 1;
|
|
ULONG cx = rcWindow.right - rcWindow.left;
|
|
ULONG cy = rcWindow.bottom - rcWindow.top - y - (rcStatusBar.bottom - rcStatusBar.top) + 1;
|
|
|
|
::MoveWindow(m_hwndListView, x, y, cx, cy, TRUE);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// WM_HELP
|
|
//
|
|
|
|
LRESULT OnHelp(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
|
ASSERT(NULL != pWindow);
|
|
|
|
pWindow->OnHelp();
|
|
return 0;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// WM_CLOSE
|
|
//
|
|
|
|
LRESULT OnClose(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
|
ASSERT(NULL != pWindow);
|
|
|
|
if (NULL != pWindow)
|
|
{
|
|
pWindow->OnExit();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// WM_INITMENUPOPUP
|
|
//
|
|
/*
|
|
LRESULT OnInitMenuPopup(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if (0 != HIWORD(lParam)) // System menu flag
|
|
{
|
|
HMENU hMenu = (HMENU) wParam; // handle of pop-up menu
|
|
::EnableMenuItem(hMenu, SC_MAXIMIZE, MF_GRAYED);
|
|
::EnableMenuItem(hMenu, SC_SIZE, MF_GRAYED);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
*/
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// WM_MENUSELECT
|
|
//
|
|
|
|
LRESULT OnMenuSelect(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
|
ASSERT(NULL != pWindow);
|
|
|
|
if (NULL != pWindow)
|
|
{
|
|
pWindow->OnMenuSelect(GET_WM_MENUSELECT_CMD(wParam, lParam),
|
|
GET_WM_MENUSELECT_FLAGS(wParam, lParam),
|
|
GET_WM_MENUSELECT_HMENU(wParam, lParam));
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// WM_INITMENUPOPUP
|
|
//
|
|
|
|
LRESULT OnGetMinMaxInfo(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
|
|
|
if (NULL != pWindow)
|
|
{
|
|
pWindow->OnGetMinMaxInfo((LPMINMAXINFO) lParam);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
|
|
void CAppletWindow::OnGetMinMaxInfo(LPMINMAXINFO pMMI)
|
|
{
|
|
static BOOL s_fEnterBefore = FALSE;
|
|
|
|
static SIZE s_csFrame;
|
|
static SIZE s_csSeparator;
|
|
static SIZE s_csScrollBars;
|
|
static SIZE s_csToolBar;
|
|
static SIZE s_csStatusBar;
|
|
static SIZE s_csSum;
|
|
|
|
if (! s_fEnterBefore)
|
|
{
|
|
s_fEnterBefore = TRUE;
|
|
|
|
s_csFrame.cx = ::GetSystemMetrics(SM_CXSIZEFRAME);
|
|
s_csFrame.cy = ::GetSystemMetrics(SM_CYSIZEFRAME);
|
|
|
|
s_csSeparator.cx = ::GetSystemMetrics(SM_CXEDGE);
|
|
s_csSeparator.cy = ::GetSystemMetrics(SM_CYEDGE);
|
|
|
|
s_csScrollBars.cx = ::GetSystemMetrics(SM_CXVSCROLL);
|
|
s_csScrollBars.cy = ::GetSystemMetrics(SM_CYHSCROLL);
|
|
|
|
m_pToolbar->GetDesiredSize(&s_csToolBar);
|
|
|
|
RECT rcStatusBar;
|
|
::GetWindowRect(m_hwndStatusBar, &rcStatusBar);
|
|
s_csStatusBar.cx = rcStatusBar.right - rcStatusBar.left;
|
|
s_csStatusBar.cy = rcStatusBar.bottom - rcStatusBar.top;
|
|
|
|
s_csSum.cx = (s_csFrame.cx << 1);
|
|
s_csSum.cy = (s_csFrame.cy << 1) + (s_csSeparator.cy << 3) +
|
|
s_csToolBar.cy + (rcStatusBar.bottom - rcStatusBar.top) +
|
|
::GetSystemMetrics( SM_CYCAPTION ) + ::GetSystemMetrics( SM_CYMENU );
|
|
}
|
|
|
|
RECT rcListViewItem;
|
|
SIZE csListView;
|
|
csListView.cx = 0;
|
|
for (ULONG i = 0; i < NUM_LIST_VIEW_COLUMNS; i++)
|
|
{
|
|
csListView.cx += ListView_GetColumnWidth(m_hwndListView, i);
|
|
}
|
|
if (ListView_GetItemRect(m_hwndListView, 0, &rcListViewItem, LVIR_BOUNDS))
|
|
{
|
|
csListView.cy = 20 + 3 * (rcListViewItem.bottom - rcListViewItem.top);
|
|
}
|
|
else
|
|
{
|
|
csListView.cy = 20 + 30;
|
|
}
|
|
|
|
// Set the minimum width and height of the window
|
|
pMMI->ptMinTrackSize.x = s_csSum.cx + max(s_csToolBar.cx, csListView.cx);
|
|
pMMI->ptMinTrackSize.y = s_csSum.cy + csListView.cy;
|
|
|
|
//
|
|
// Retrieves the size of the work area on the primary display monitor. The work
|
|
// area is the portion of the screen not obscured by the system taskbar or by
|
|
// application desktop toolbars
|
|
//
|
|
|
|
RECT rcWorkArea;
|
|
::SystemParametersInfo( SPI_GETWORKAREA, 0, (&rcWorkArea), NULL );
|
|
|
|
SIZE csMaxSize;
|
|
csMaxSize.cx = rcWorkArea.right - rcWorkArea.left;
|
|
csMaxSize.cy = rcWorkArea.bottom - rcWorkArea.top;
|
|
|
|
pMMI->ptMaxPosition.x = 0;
|
|
pMMI->ptMaxPosition.y = 0;
|
|
pMMI->ptMaxSize.x = csMaxSize.cx;
|
|
pMMI->ptMaxSize.y = csMaxSize.cy;
|
|
pMMI->ptMaxTrackSize.x = csMaxSize.cx;
|
|
pMMI->ptMaxTrackSize.y = csMaxSize.cy;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// WM_QUERYENDSESSION
|
|
//
|
|
|
|
LRESULT OnQueryEndSession(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
|
ASSERT(NULL != pWindow);
|
|
|
|
if (NULL != pWindow)
|
|
{
|
|
return pWindow->QueryShutdown(); // TRUE: ok to send session; FALSE, no.
|
|
}
|
|
return TRUE; // ok to end session
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// WM_ENDSESSION
|
|
//
|
|
|
|
LRESULT OnEndSession(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
|
|
|
if (wParam && NULL != pWindow)
|
|
{
|
|
pWindow->OnExit(TRUE);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// WM_DRAWITEM
|
|
//
|
|
|
|
LRESULT OnDrawItem(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
|
|
|
if (wParam && NULL != pWindow)
|
|
{
|
|
pWindow->DrawItem((DRAWITEMSTRUCT *)lParam);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// WM_SEND_NEXT
|
|
//
|
|
|
|
LRESULT OnSendNext(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
CAppletWindow *pWindow = (CAppletWindow *) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
|
|
|
if (NULL != pWindow)
|
|
{
|
|
pWindow->OnSendAll();
|
|
pWindow->UpdateUI();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// Main windows procedure
|
|
//
|
|
|
|
LRESULT CALLBACK FtMainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
LRESULT rc = 0;
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_CREATE:
|
|
rc = ::OnCreate(hwnd, wParam, lParam);
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
rc = ::OnCommand(hwnd, wParam, lParam);
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
rc = ::OnNotify(hwnd, wParam, lParam);
|
|
break;
|
|
|
|
case WM_DROPFILES:
|
|
rc = ::OnDropFiles(hwnd, wParam, lParam);
|
|
break;
|
|
|
|
case WM_CONTEXTMENU:
|
|
rc = ::OnContextMenu(hwnd, wParam, lParam);
|
|
break;
|
|
|
|
case WM_SIZE:
|
|
rc = ::OnSize(hwnd, wParam, lParam);
|
|
break;
|
|
|
|
case WM_HELP:
|
|
rc = ::OnHelp(hwnd, wParam, lParam);
|
|
break;
|
|
|
|
case WM_DRAWITEM:
|
|
rc = ::OnDrawItem(hwnd, wParam, lParam);
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
rc = ::OnClose(hwnd, wParam, lParam);
|
|
break;
|
|
|
|
case WM_INITMENUPOPUP:
|
|
// rc = ::OnInitMenuPopup(hwnd, wParam, lParam);
|
|
break;
|
|
|
|
case WM_MENUSELECT:
|
|
rc = ::OnMenuSelect(hwnd, wParam, lParam);
|
|
break;
|
|
|
|
case WM_GETMINMAXINFO:
|
|
rc = ::OnGetMinMaxInfo(hwnd, wParam, lParam);
|
|
break;
|
|
|
|
case WM_QUERYENDSESSION:
|
|
rc = OnQueryEndSession(hwnd, wParam, lParam);
|
|
break;
|
|
|
|
case WM_ENDSESSION:
|
|
rc = ::OnEndSession(hwnd, wParam, lParam);
|
|
break;
|
|
|
|
case WM_SEND_NEXT:
|
|
rc = ::OnSendNext(hwnd, wParam, lParam);
|
|
break;
|
|
|
|
|
|
#if defined(TEST_PLUGABLE) && defined(_DEBUG)
|
|
case WM_PLUGABLE_SOCKET:
|
|
rc = ::OnPluggableSocket(hwnd, wParam, lParam);
|
|
break;
|
|
#endif
|
|
|
|
default:
|
|
rc = ::DefWindowProc(hwnd, uMsg, wParam, lParam);
|
|
break;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// OnEngineNotify
|
|
//
|
|
|
|
void CAppletWindow::OnEngineNotify(MBFTMsg *pMsg)
|
|
{
|
|
BOOL fHeartBeat = FALSE;
|
|
|
|
switch (pMsg->GetMsgType())
|
|
{
|
|
case EnumFileOfferNotifyMsg:
|
|
if (m_UIMode != FTUIMODE_NOUI)
|
|
{
|
|
HandleFileOfferNotify((FileOfferNotifyMsg *) pMsg);
|
|
}
|
|
break;
|
|
|
|
case EnumFileTransmitMsg:
|
|
if (m_UIMode != FTUIMODE_NOUI)
|
|
{
|
|
HandleProgressNotify((FileTransmitMsg *) pMsg);
|
|
}
|
|
fHeartBeat = TRUE;
|
|
break;
|
|
|
|
case EnumFileErrorMsg:
|
|
if (m_UIMode != FTUIMODE_NOUI)
|
|
{
|
|
HandleErrorNotify((FileErrorMsg *) pMsg);
|
|
}
|
|
break;
|
|
|
|
case EnumPeerMsg:
|
|
HandlePeerNotification((PeerMsg *) pMsg);
|
|
break;
|
|
|
|
case EnumInitUnInitNotifyMsg:
|
|
HandleInitUninitNotification((InitUnInitNotifyMsg *) pMsg);
|
|
break;
|
|
|
|
case EnumFileEventEndNotifyMsg:
|
|
if (m_UIMode != FTUIMODE_NOUI)
|
|
{
|
|
HandleFileEventEndNotification((FileEventEndNotifyMsg *) pMsg);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
ASSERT(0);
|
|
break;
|
|
} // switch
|
|
}
|
|
|
|
|
|
void CAppletWindow::HandleFileOfferNotify(FileOfferNotifyMsg *pMsg)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
if (g_fRecvAllowed)
|
|
{
|
|
DBG_SAVE_FILE_LINE
|
|
CUiRecvFileInfo *pRecvFileInfo = new CUiRecvFileInfo(pMsg, &hr);
|
|
if (NULL != pRecvFileInfo && S_OK == hr)
|
|
{
|
|
if (NULL != m_pEngine)
|
|
{
|
|
DBG_SAVE_FILE_LINE
|
|
CRecvDlg *pDlg = new CRecvDlg(this,
|
|
m_pEngine->GetConfID(),
|
|
pMsg->m_NodeID,
|
|
pMsg->m_EventHandle,
|
|
pRecvFileInfo,
|
|
&hr);
|
|
if (NULL != pDlg && S_OK == hr)
|
|
{
|
|
DBG_SAVE_FILE_LINE
|
|
if (S_OK == m_pEngine->SafePostMessage(
|
|
new FileTransferControlMsg(
|
|
pMsg->m_EventHandle,
|
|
pMsg->m_hFile,
|
|
pRecvFileInfo->GetRecvFolder(),
|
|
pMsg->m_szFileName,
|
|
FileTransferControlMsg::EnumAcceptFile)))
|
|
{
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
ERROR_OUT(("CAppletWindow::HandleFileOfferNotify: cannot confirm file offer"));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ERROR_OUT(("CAppletWindow::HandleFileOfferNotify: cannot allocate CRecvDlg, hr=0x%x", hr));
|
|
}
|
|
delete pDlg;
|
|
}
|
|
else
|
|
{
|
|
ERROR_OUT(("CAppletWindow::HandleFileOfferNotify: no file transfer engine"));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ERROR_OUT(("CAppletWindow::HandleFileOfferNotify: cannot allocate CUiRecvFileInfo, hr=0x%x", hr));
|
|
}
|
|
delete pRecvFileInfo;
|
|
}
|
|
else
|
|
{
|
|
DBG_SAVE_FILE_LINE
|
|
if (S_OK != m_pEngine->SafePostMessage(
|
|
new FileTransferControlMsg(
|
|
pMsg->m_EventHandle,
|
|
pMsg->m_hFile,
|
|
NULL,
|
|
pMsg->m_szFileName,
|
|
FileTransferControlMsg::EnumRejectFile)))
|
|
{
|
|
ERROR_OUT(("CAppletWindow::HandleFileOfferNotify: cannot confirm file offer"));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CAppletWindow::HandleProgressNotify(FileTransmitMsg *pMsg)
|
|
{
|
|
CRecvDlg *pDlg = NULL;
|
|
MBFT_NOTIFICATION wMBFTCode = (MBFT_NOTIFICATION) pMsg->m_TransmitStatus;
|
|
ULONG totalSent = 0;
|
|
ULONG fileSize = 0;
|
|
ULONG percentSent = 0;
|
|
|
|
switch (wMBFTCode)
|
|
{
|
|
case iMBFT_FILE_SEND_BEGIN:
|
|
// fall through... because the file start PDU can have data.
|
|
|
|
case iMBFT_FILE_SEND_PROGRESS:
|
|
if (NULL != m_pCurrSendFileInfo)
|
|
{
|
|
ASSERT(m_nCurrSendEventHandle == pMsg->m_EventHandle);
|
|
ASSERT(m_pCurrSendFileInfo->GetFileHandle() == pMsg->m_hFile);
|
|
ASSERT(m_pCurrSendFileInfo->GetSize() == pMsg->m_FileSize);
|
|
fileSize = m_pCurrSendFileInfo->GetSize();
|
|
totalSent = m_pCurrSendFileInfo->GetTotalSend();
|
|
|
|
m_pCurrSendFileInfo->SetTotalSend(pMsg->m_BytesTransmitted);
|
|
|
|
percentSent = _GetPercent(totalSent, fileSize)*10;
|
|
|
|
if(m_pCurrSendFileInfo->GetPercentSent()!= percentSent || fileSize == totalSent)
|
|
{
|
|
UpdateListView(m_pCurrSendFileInfo);
|
|
UpdateStatusBar();
|
|
m_pCurrSendFileInfo->SetPercentSent(percentSent);
|
|
}
|
|
}
|
|
break;
|
|
|
|
break;
|
|
|
|
case iMBFT_FILE_SEND_END:
|
|
if (NULL != m_pCurrSendFileInfo)
|
|
{
|
|
UpdateListView(m_pCurrSendFileInfo);
|
|
UpdateStatusBar();
|
|
}
|
|
break;
|
|
|
|
|
|
case iMBFT_FILE_RECEIVE_BEGIN:
|
|
// fall through... because the file start PDU can have data.
|
|
|
|
case iMBFT_FILE_RECEIVE_PROGRESS:
|
|
pDlg = FindDlgByHandles(pMsg->m_EventHandle, pMsg->m_hFile);
|
|
if (NULL != pDlg)
|
|
{
|
|
pDlg->OnProgressUpdate(pMsg);
|
|
}
|
|
break;
|
|
|
|
case iMBFT_FILE_RECEIVE_END:
|
|
// doing nothing...
|
|
break;
|
|
|
|
default:
|
|
ASSERT(0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
void CAppletWindow::HandleErrorNotify(FileErrorMsg *pMsg)
|
|
{
|
|
MBFTFILEHANDLE nFileHandle = pMsg->m_hFile;
|
|
if(LOWORD(nFileHandle) == LOWORD(_iMBFT_PROSHARE_ALL_FILES))
|
|
{
|
|
nFileHandle = _iMBFT_PROSHARE_ALL_FILES;
|
|
}
|
|
|
|
if (m_nCurrSendEventHandle == pMsg->m_EventHandle &&
|
|
m_pCurrSendFileInfo->GetFileHandle() == nFileHandle)
|
|
{
|
|
m_pCurrSendFileInfo->SetErrorCode((MBFT_ERROR_CODE) pMsg->m_ErrorCode);
|
|
|
|
UINT idString;
|
|
switch ((MBFT_ERROR_CODE) pMsg->m_ErrorCode)
|
|
{
|
|
case iMBFT_OK:
|
|
idString = 0;
|
|
break;
|
|
case iMBFT_SENDER_ABORTED:
|
|
case iMBFT_RECEIVER_ABORTED:
|
|
case iMBFT_NO_MORE_FILES:
|
|
idString = IDS_MSGBOX2_CANCELED;
|
|
break;
|
|
case iMBFT_MULT_RECEIVER_ABORTED:
|
|
idString = IDS_MSGBOX2_MULT_CANCEL;
|
|
break;
|
|
// case iMBFT_RECEIVER_REJECTED:
|
|
default:
|
|
idString = IDS_MSGBOX2_SEND_FAILED;
|
|
break;
|
|
}
|
|
if (idString)
|
|
{
|
|
if (! m_pCurrSendFileInfo->HasShownUI())
|
|
{
|
|
if (::MyLoadString(idString, s_szScratchText, m_pCurrSendFileInfo->GetName()))
|
|
{
|
|
m_pCurrSendFileInfo->SetShowUI();
|
|
::MsgBox2(this, s_szScratchText);
|
|
}
|
|
else
|
|
{
|
|
ASSERT(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
UpdateListView(m_pCurrSendFileInfo);
|
|
UpdateStatusBar();
|
|
|
|
ClearSendInfo(TRUE);
|
|
if (! idString)
|
|
{
|
|
// send the next one now
|
|
if (m_fSendALL)
|
|
{
|
|
::PostMessage(m_hwndMainUI, WM_SEND_NEXT, 0, 0);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CRecvDlg *pDlg = FindDlgByHandles(pMsg->m_EventHandle, nFileHandle);
|
|
if (NULL != pDlg)
|
|
{
|
|
switch ((MBFT_ERROR_CODE) pMsg->m_ErrorCode)
|
|
{
|
|
case iMBFT_RECEIVER_ABORTED:
|
|
case iMBFT_MULT_RECEIVER_ABORTED:
|
|
pDlg->OnCanceled();
|
|
break;
|
|
default:
|
|
pDlg->OnRejectedFile();
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch((MBFT_ERROR_CODE) pMsg->m_ErrorCode)
|
|
{
|
|
case iMBFT_INVALID_PATH:
|
|
::MyLoadString(IDS_MSGBOX2_INVALID_DIRECTORY,
|
|
s_szScratchText, pMsg->m_stFileInfo.szFileName);
|
|
break;
|
|
|
|
case iMBFT_DIRECTORY_FULL_ERROR:
|
|
::MyLoadString(IDS_MSGBOX2_DIRECTORY_FULL,
|
|
s_szScratchText, pMsg->m_stFileInfo.lFileSize,
|
|
pMsg->m_stFileInfo.szFileName);
|
|
break;
|
|
|
|
case iMBFT_FILE_ACCESS_DENIED:
|
|
::MyLoadString(IDS_MSGBOX2_FILE_CREATE_FAILED,
|
|
s_szScratchText, pMsg->m_stFileInfo.szFileName);
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
::MsgBox2(this, s_szScratchText);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CAppletWindow::HandlePeerNotification(PeerMsg *pMsg)
|
|
{
|
|
|
|
m_pToolbar->HandlePeerNotification(m_pEngine->GetConfID(),
|
|
m_pEngine->GetNodeID(), pMsg);
|
|
}
|
|
|
|
|
|
void CAppletWindow::HandleInitUninitNotification(InitUnInitNotifyMsg *pMsg)
|
|
{
|
|
if (pMsg->m_iNotifyMessage == EnumInvoluntaryUnInit)
|
|
{
|
|
UnregisterEngine();
|
|
}
|
|
}
|
|
|
|
|
|
void CAppletWindow::HandleFileEventEndNotification(FileEventEndNotifyMsg *pMsg)
|
|
{
|
|
if (m_nCurrSendEventHandle == pMsg->m_EventHandle)
|
|
{
|
|
ClearSendInfo(TRUE);
|
|
// send the next one now
|
|
if (m_fSendALL)
|
|
{
|
|
::PostMessage(m_hwndMainUI, WM_SEND_NEXT, 0, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// Main UI methods
|
|
//
|
|
|
|
void CAppletWindow::BringToFront(void)
|
|
{
|
|
if (NULL != m_hwndMainUI)
|
|
{
|
|
int nCmdShow = SW_SHOW;
|
|
|
|
WINDOWPLACEMENT wp;
|
|
::ZeroMemory(&wp, sizeof(wp));
|
|
wp.length = sizeof(wp);
|
|
|
|
if (::GetWindowPlacement(m_hwndMainUI, &wp))
|
|
{
|
|
if (SW_MINIMIZE == wp.showCmd || SW_SHOWMINIMIZED == wp.showCmd)
|
|
{
|
|
// The window is minimized - restore it:
|
|
nCmdShow = SW_RESTORE;
|
|
}
|
|
}
|
|
|
|
// show the window now
|
|
::ShowWindow(m_hwndMainUI, nCmdShow);
|
|
m_UIMode = FTUIMODE_SHOWUI;
|
|
// bring it to the foreground
|
|
::SetForegroundWindow(m_hwndMainUI);
|
|
}
|
|
}
|
|
|
|
|
|
void CAppletWindow::ClearSendInfo(BOOL fUpdateUI)
|
|
{
|
|
m_pCurrSendFileInfo = NULL;
|
|
m_nCurrSendEventHandle = NULL;
|
|
|
|
if (fUpdateUI)
|
|
{
|
|
UpdateUI();
|
|
}
|
|
}
|
|
|
|
|
|
void CAppletWindow::ClearRecvInfo(void)
|
|
{
|
|
CRecvDlg *pDlg;
|
|
while (NULL != (pDlg = m_RecvDlgList.Get()))
|
|
{
|
|
::EndDialog(pDlg->GetHwnd(), IDCLOSE);
|
|
pDlg->Release();
|
|
}
|
|
}
|
|
|
|
|
|
BOOL CAppletWindow::HasUnSentFiles(BOOL fUnSentOnly)
|
|
{
|
|
BOOL fRc = FALSE;
|
|
ULONG cItems = ListView_GetItemCount(m_hwndListView);
|
|
CUiSendFileInfo *pFileInfo;
|
|
LVITEM lvi;
|
|
|
|
if (!fUnSentOnly && cItems) {
|
|
return TRUE;
|
|
}
|
|
|
|
::ZeroMemory(&lvi, sizeof(lvi));
|
|
lvi.mask = LVIF_PARAM; // examine each item one by one
|
|
for (ULONG i = 0; i < cItems; i++, pFileInfo = NULL)
|
|
{
|
|
lvi.iItem = i;
|
|
BOOL fRet = ListView_GetItem(m_hwndListView, &lvi);
|
|
ASSERT(fRet);
|
|
pFileInfo = (CUiSendFileInfo *) lvi.lParam;
|
|
if (!pFileInfo->GetFileHandle()) // if file handle is not zero, then it has been sent or cancelled
|
|
{
|
|
fRc = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
return fRc;
|
|
}
|
|
|
|
|
|
void CAppletWindow::UpdateUI(void)
|
|
{
|
|
UpdateTitle();
|
|
UpdateMenu();
|
|
UpdateToolBar();
|
|
UpdateStatusBar();
|
|
}
|
|
|
|
|
|
void CAppletWindow::UpdateTitle(void)
|
|
{
|
|
UINT captionID;
|
|
if ((! m_pEngine) || (m_pEngine->GetPeerCount() <= 1))
|
|
{
|
|
captionID = IDS_MSFT_NOT_IN_CALL_WINDOW_CAPTION;
|
|
}
|
|
else
|
|
{
|
|
captionID = IDS_MSFT_IN_CALL_WINDOW_CAPTION;
|
|
}
|
|
|
|
::LoadString(g_hDllInst, captionID, s_szMSFT, sizeof(s_szMSFT));
|
|
|
|
SetWindowText(m_hwndMainUI, s_szMSFT);
|
|
}
|
|
|
|
|
|
void CAppletWindow::UpdateMenu(void)
|
|
{
|
|
HMENU hMenu = ::GetMenu(m_hwndMainUI);
|
|
if (NULL != hMenu)
|
|
{
|
|
if (g_fSendAllowed)
|
|
{
|
|
BOOL fMoreThanOne = (NULL != m_pEngine) && (m_pEngine->GetPeerCount() > 1);
|
|
::EnableMenuItem(hMenu, IDM_ADD_FILES, fMoreThanOne ? MF_ENABLED : MF_GRAYED);
|
|
|
|
ULONG cItems = ListView_GetItemCount(m_hwndListView);
|
|
::EnableMenuItem(hMenu, IDM_REMOVE_FILES, cItems ? MF_ENABLED : MF_GRAYED);
|
|
::EnableMenuItem(hMenu, IDM_SEND_ALL, (fMoreThanOne && ! m_nCurrSendEventHandle && HasUnSentFiles(TRUE)) ? MF_ENABLED : MF_GRAYED);
|
|
::EnableMenuItem(hMenu, IDM_SEND_ONE, (fMoreThanOne && ! m_nCurrSendEventHandle && HasUnSentFiles(FALSE)) ? MF_ENABLED : MF_GRAYED);
|
|
::EnableMenuItem(hMenu, IDM_STOP_SENDING, m_nCurrSendEventHandle ? MF_ENABLED : MF_GRAYED);
|
|
}
|
|
else
|
|
{
|
|
::EnableMenuItem(hMenu, IDM_ADD_FILES, MF_GRAYED);
|
|
::EnableMenuItem(hMenu, IDM_REMOVE_FILES, MF_GRAYED);
|
|
::EnableMenuItem(hMenu, IDM_SEND_ALL, MF_GRAYED);
|
|
::EnableMenuItem(hMenu, IDM_SEND_ONE, MF_GRAYED);
|
|
::EnableMenuItem(hMenu, IDM_STOP_SENDING, MF_GRAYED);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CAppletWindow::UpdateToolBar(void)
|
|
{
|
|
int iFlags[count_of(buttons)];
|
|
|
|
::ZeroMemory(iFlags, sizeof(iFlags));
|
|
|
|
iFlags[2] = iFlags[5] = iFlags[6] = 1; // separators
|
|
iFlags[7] = 1; // open recv folders
|
|
|
|
|
|
if (g_fSendAllowed)
|
|
{
|
|
BOOL fMoreThanOne = (NULL != m_pEngine) && (m_pEngine->GetPeerCount() > 1);
|
|
ULONG cItems = ListView_GetItemCount(m_hwndListView);
|
|
|
|
iFlags[0] = fMoreThanOne ? TRUE : FALSE; // Add files
|
|
iFlags[1] = cItems ? TRUE : FALSE; // Delete files
|
|
iFlags[3] = (fMoreThanOne && ! m_nCurrSendEventHandle && HasUnSentFiles(TRUE)) ? TRUE : FALSE; // Send file(s)
|
|
iFlags[4] = m_nCurrSendEventHandle ? TRUE : FALSE; // Stop sending
|
|
|
|
m_pToolbar->UpdateButton(iFlags);
|
|
}
|
|
else
|
|
{
|
|
m_pToolbar->UpdateButton(iFlags);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void CAppletWindow::UpdateStatusBar(void)
|
|
{
|
|
int idString, iPos = 0;
|
|
HICON hIcon;
|
|
RECT rc;
|
|
|
|
// set the text in part 0
|
|
s_szScratchText[0] = TEXT('\0');
|
|
if ((NULL != m_pEngine) && (NULL != m_pCurrSendFileInfo))
|
|
{
|
|
idString = IDS_STBAR_SENDING_XYZ;
|
|
::MyLoadString(idString, s_szScratchText, m_pCurrSendFileInfo->GetName());
|
|
}
|
|
else if (NULL == m_pEngine)
|
|
{
|
|
::MyLoadString(IDS_STBAR_NOT_IN_CALL);
|
|
}
|
|
else
|
|
{
|
|
::MyLoadString(IDS_STBAR_NOT_TRANSFERING);
|
|
}
|
|
::SendMessage(m_hwndStatusBar, SB_SETTEXT, SBP_TRANSFER_FILE, (LPARAM) s_szScratchText);
|
|
|
|
// set the progres bar in part 1
|
|
if ((NULL != m_pCurrSendFileInfo)&&m_pCurrSendFileInfo->GetSize())
|
|
{
|
|
iPos = (int)_GetPercent(m_pCurrSendFileInfo->GetTotalSend(), m_pCurrSendFileInfo->GetSize());
|
|
}
|
|
::SendMessage(m_hwndStatusBar, SB_GETRECT, SBP_PROGRESS, (LPARAM)&rc);
|
|
::MoveWindow(m_hwndProgressBar,
|
|
rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
|
|
FALSE);
|
|
::SendMessage(m_hwndProgressBar, PBM_SETPOS, iPos, 0);
|
|
|
|
// set the icon in part 2
|
|
hIcon = (NULL != m_pEngine) ? m_hIconInCall : m_hIconNotInCall;
|
|
::SendMessage(m_hwndStatusBar, SB_SETTEXT, SBP_SBICON | SBT_OWNERDRAW, (LPARAM)hIcon);
|
|
}
|
|
|
|
|
|
void CAppletWindow::UpdateListView(CUiSendFileInfo *pFileInfo)
|
|
{
|
|
LVFINDINFO lvfi;
|
|
::ZeroMemory(&lvfi, sizeof(lvfi));
|
|
lvfi.flags = LVFI_PARAM;
|
|
lvfi.lParam = (LPARAM) pFileInfo;
|
|
int iItem = ListView_FindItem(m_hwndListView, -1, &lvfi);
|
|
|
|
if (-1 != iItem)
|
|
{
|
|
for (ULONG i = 0; i < NUM_LIST_VIEW_COLUMNS; i++)
|
|
{
|
|
ListView_SetItemText(m_hwndListView, iItem, i, LPSTR_TEXTCALLBACK);
|
|
}
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Save window position for File Transfer
|
|
//
|
|
|
|
void CAppletWindow::SaveWindowPosition(void)
|
|
{
|
|
RECT rcWnd;
|
|
RegEntry reWnd( FILEXFER_KEY, HKEY_CURRENT_USER);
|
|
|
|
// If we are not maximized or minimized
|
|
if (!::IsZoomed(m_hwndMainUI) && !::IsIconic(m_hwndMainUI))
|
|
{
|
|
::GetWindowRect(m_hwndMainUI, &rcWnd);
|
|
|
|
reWnd.SetValue (REGVAL_WINDOW_XPOS, rcWnd.left);
|
|
reWnd.SetValue (REGVAL_WINDOW_YPOS, rcWnd.top);
|
|
reWnd.SetValue (REGVAL_WINDOW_WIDTH, rcWnd.right - rcWnd.left);
|
|
reWnd.SetValue (REGVAL_WINDOW_HEIGHT, rcWnd.bottom - rcWnd.top);
|
|
}
|
|
}
|
|
|
|
void CAppletWindow::FocusNextRecvDlg(void)
|
|
{
|
|
if (!m_RecvDlgList.IsEmpty())
|
|
{
|
|
m_RecvDlgList.Reset();
|
|
CRecvDlg *pRecvDlg = m_RecvDlgList.Iterate();
|
|
if (pRecvDlg)
|
|
{
|
|
SetFocus(pRecvDlg->GetHwnd());
|
|
}
|
|
}
|
|
}
|
|
|
|
void CAppletWindow::FocusNextErrorDlg(void)
|
|
{
|
|
if (!m_ErrorDlgList.IsEmpty())
|
|
{
|
|
m_ErrorDlgList.Reset();
|
|
HWND hwndErrorDlg = m_ErrorDlgList.Iterate();
|
|
if (hwndErrorDlg)
|
|
{
|
|
::SetFocus(hwndErrorDlg);
|
|
}
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// Utilities
|
|
//
|
|
|
|
LPTSTR PathNameToFileName(LPTSTR pszPathName)
|
|
{
|
|
LPTSTR psz = pszPathName;
|
|
while (*psz != '\0')
|
|
{
|
|
BOOL fDirChar = (*psz == TEXT('\\'));
|
|
psz = ::CharNext(psz);
|
|
if (fDirChar)
|
|
{
|
|
pszPathName = psz;
|
|
}
|
|
}
|
|
return pszPathName;
|
|
}
|
|
|
|
|
|
int MyLoadString(UINT idStr)
|
|
{
|
|
s_szScratchText[0] = TEXT('\0');
|
|
int iRet = ::LoadString(g_hDllInst, idStr, s_szScratchText, MAX_PATH);
|
|
ASSERT(iRet);
|
|
return iRet;
|
|
}
|
|
|
|
|
|
int MyLoadString(UINT idStr, LPTSTR pszDstStr)
|
|
{
|
|
*pszDstStr = TEXT('\0');
|
|
int iRet = ::LoadString(g_hDllInst, idStr, pszDstStr, MAX_PATH);
|
|
ASSERT(iRet);
|
|
return iRet;
|
|
}
|
|
|
|
|
|
int MyLoadString(UINT idStr, LPTSTR pszDstStr, LPTSTR pszElement)
|
|
{
|
|
int cch;
|
|
TCHAR szText[MAX_PATH];
|
|
|
|
cch = ::LoadString(g_hDllInst, idStr, szText, count_of(szText));
|
|
if (cch)
|
|
{
|
|
::wsprintf(pszDstStr, szText, pszElement);
|
|
}
|
|
else
|
|
{
|
|
ASSERT(0);
|
|
*pszDstStr = TEXT('\0');
|
|
}
|
|
return cch;
|
|
}
|
|
|
|
|
|
int MyLoadString(UINT idStr, LPTSTR pszDstStr, LPTSTR pszElement1, LPTSTR pszElement2)
|
|
{
|
|
int cch;
|
|
TCHAR szText[MAX_PATH];
|
|
|
|
cch = ::LoadString(g_hDllInst, idStr, szText, count_of(szText));
|
|
if (cch)
|
|
{
|
|
::wsprintf(pszDstStr, szText, pszElement1, pszElement2);
|
|
}
|
|
else
|
|
{
|
|
ASSERT(0);
|
|
*pszDstStr = TEXT('\0');
|
|
}
|
|
return cch;
|
|
}
|
|
|
|
|
|
void LoadDefaultStrings(void)
|
|
{
|
|
// load file transfer name
|
|
s_szMSFT[0] = TEXT('\0');
|
|
::LoadString(g_hDllInst, IDS_MSFT_NOT_IN_CALL_WINDOW_CAPTION,
|
|
s_szMSFT, count_of(s_szMSFT));
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// CUiSendFileInfo
|
|
//
|
|
|
|
CUiSendFileInfo::CUiSendFileInfo(CAppletWindow *pWindow, TCHAR szDir[], TCHAR szFile[], BOOL *pfRet)
|
|
:
|
|
m_nFileHandle(0),
|
|
m_cbTotalSend(0),
|
|
m_eSendErrorCode(iMBFT_OK),
|
|
m_percentSent(-1),
|
|
m_fAlreadyShowUI(FALSE),
|
|
m_pszFullName(NULL)
|
|
{
|
|
*pfRet = FALSE; // failure as default
|
|
HANDLE hFile;
|
|
|
|
// build a full name
|
|
hFile = GetOpenFile(pWindow, szDir, szFile, TRUE); // try to resolve
|
|
if (INVALID_HANDLE_VALUE == hFile)
|
|
{
|
|
hFile = GetOpenFile(pWindow, szDir, szFile, FALSE);
|
|
}
|
|
|
|
if (INVALID_HANDLE_VALUE != hFile)
|
|
{
|
|
// get the file info
|
|
::ZeroMemory(&m_FileInfo, sizeof(m_FileInfo));
|
|
BOOL rc = ::GetFileInformationByHandle(hFile, &m_FileInfo);
|
|
::CloseHandle(hFile);
|
|
if (rc)
|
|
{
|
|
ASSERT(0 == m_FileInfo.nFileSizeHigh);
|
|
|
|
// make sure the file size is smaller than what the policy says
|
|
if ((! g_cbMaxSendFileSize) || GetSize() <= g_cbMaxSendFileSize * 1024)
|
|
{
|
|
*pfRet = TRUE;
|
|
}
|
|
else if (pWindow->GetUIMode() != FTUIMODE_NOUI)
|
|
{
|
|
::MyLoadString(IDS_MSGBOX_SEND_BIG_FILE, s_szScratchText, (LPTSTR) g_cbMaxSendFileSize, m_pszFileName);
|
|
::MessageBox(pWindow->GetHwnd(), s_szScratchText, s_szMSFT, MB_OK | MB_ICONSTOP);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
CUiSendFileInfo::~CUiSendFileInfo(void)
|
|
{
|
|
delete m_pszFullName;
|
|
}
|
|
|
|
|
|
HANDLE CUiSendFileInfo::GetOpenFile(CAppletWindow *pWindow, TCHAR szDir[], TCHAR szFile[], BOOL fResolve)
|
|
{
|
|
// build a full name
|
|
ULONG cch;
|
|
TCHAR szName[MAX_PATH*2];
|
|
HANDLE hFile = INVALID_HANDLE_VALUE;
|
|
|
|
if ((NULL != szDir)&&(!_StrChr(szFile, '\\')))
|
|
{
|
|
cch = ::lstrlen(szDir);
|
|
::wsprintf(szName, (TEXT('\\') == szDir[cch-1]) ? TEXT("%s%s") : TEXT("%s\\%s"), szDir, szFile);
|
|
}
|
|
else
|
|
{
|
|
// file name is the full name
|
|
::lstrcpy(szName, szFile);
|
|
}
|
|
|
|
// resolve shortcut if necessary
|
|
cch = ::lstrlen(szName) + 1;
|
|
if (fResolve&&(cch >= 4))
|
|
{
|
|
if (! lstrcmpi(&szName[cch-5], TEXT(".lnk")))
|
|
{
|
|
pWindow->ResolveShortcut(szName, szName);
|
|
cch = ::lstrlen(szName) + 1;
|
|
}
|
|
}
|
|
|
|
if (m_pszFullName)
|
|
{
|
|
delete [] m_pszFullName;
|
|
}
|
|
|
|
// construct the full name
|
|
DBG_SAVE_FILE_LINE
|
|
m_pszFullName = new TCHAR[cch];
|
|
if (NULL != m_pszFullName)
|
|
{
|
|
::CopyMemory(m_pszFullName, szName, cch * sizeof(TCHAR));
|
|
m_pszFileName = ::PathNameToFileName(m_pszFullName);
|
|
|
|
// open the file
|
|
hFile = ::CreateFile(m_pszFullName, GENERIC_READ,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL, OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL, NULL);
|
|
}
|
|
return hFile;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// CUiRecvFileInfo
|
|
//
|
|
|
|
CUiRecvFileInfo::CUiRecvFileInfo(FileOfferNotifyMsg *pMsg, HRESULT *pHr)
|
|
:
|
|
m_nFileHandle(pMsg->m_hFile),
|
|
m_FileDateTime(pMsg->m_FileDateTime),
|
|
m_cbFileSize(pMsg->m_FileSize),
|
|
m_cbTotalRecvSize(0),
|
|
m_pszFullName(NULL),
|
|
m_pszRecvFolder(NULL)
|
|
{
|
|
*pHr = E_FAIL; // failure, at default
|
|
|
|
ULONG cchTotal = ::lstrlen(pMsg->m_szFileName);
|
|
|
|
// construct the full name
|
|
DBG_SAVE_FILE_LINE
|
|
m_pszFullName = new TCHAR[cchTotal+2];
|
|
if (NULL != m_pszFullName)
|
|
{
|
|
// construct full name and file name
|
|
strcpy(m_pszFullName, pMsg->m_szFileName);
|
|
m_pszFileName = PathNameToFileName(m_pszFullName);
|
|
ULONG cchFile = ::lstrlen(m_pszFileName);
|
|
DBG_SAVE_FILE_LINE
|
|
m_pszRecvFolder = new TCHAR[cchTotal - cchFile + 2];
|
|
if (NULL != m_pszRecvFolder)
|
|
{
|
|
::CopyMemory(m_pszRecvFolder, m_pszFullName, cchTotal - cchFile);
|
|
m_pszRecvFolder[cchTotal - cchFile - 1] = TEXT('\0');
|
|
*pHr = S_OK;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
CUiRecvFileInfo::~CUiRecvFileInfo(void)
|
|
{
|
|
delete m_pszFullName;
|
|
delete m_pszRecvFolder;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// Receive Dialog
|
|
//
|
|
|
|
CRecvDlg::CRecvDlg
|
|
(
|
|
CAppletWindow *pWindow,
|
|
T120ConfID nConfID,
|
|
T120NodeID nidSender,
|
|
MBFTEVENTHANDLE nEventHandle,
|
|
CUiRecvFileInfo *pFileInfo,
|
|
HRESULT *pHr
|
|
)
|
|
:
|
|
CRefCount(MAKE_STAMP_ID('F','T','R','D')),
|
|
m_pWindow(pWindow),
|
|
m_nConfID(nConfID),
|
|
m_nidSender(nidSender),
|
|
m_nEventHandle(nEventHandle),
|
|
m_pRecvFileInfo(pFileInfo),
|
|
m_fRecvComplete(FALSE),
|
|
m_fShownRecvCompleteUI(FALSE),
|
|
m_idResult(0),
|
|
m_dwEstTimeLeft(0),
|
|
m_dwPreviousTime(0),
|
|
m_dwPreviousTransferred(0),
|
|
m_dwBytesPerSec(0),
|
|
m_dwStartTime(::GetTickCount())
|
|
{
|
|
*pHr = E_FAIL; // failure, at default
|
|
|
|
m_hwndRecvDlg = ::CreateDialogParam(g_hDllInst, MAKEINTRESOURCE(IDD_RECVDLG),
|
|
pWindow->GetHwnd(), RecvDlgProc, (LPARAM) this);
|
|
ASSERT(NULL != m_hwndRecvDlg);
|
|
if (NULL != m_hwndRecvDlg)
|
|
{
|
|
::ShowWindow(m_hwndRecvDlg, SW_SHOWNORMAL);
|
|
m_pWindow->RegisterRecvDlg(this);
|
|
*pHr = S_OK;
|
|
::SetForegroundWindow(m_hwndRecvDlg);
|
|
}
|
|
}
|
|
|
|
|
|
CRecvDlg::~CRecvDlg(void)
|
|
{
|
|
delete m_pRecvFileInfo;
|
|
|
|
m_pWindow->UnregisterRecvDlg(this);
|
|
|
|
if (NULL != m_hwndRecvDlg)
|
|
{
|
|
HWND hwnd = m_hwndRecvDlg;
|
|
m_hwndRecvDlg = NULL;
|
|
::EndDialog(hwnd, IDCLOSE);
|
|
}
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// RecvDlg_OnInitDialog
|
|
//
|
|
|
|
void RecvDlg_OnInitDialog(HWND hdlg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
CRecvDlg *pDlg = (CRecvDlg *) ::GetWindowLongPtr(hdlg, DWLP_USER);
|
|
ASSERT(NULL != pDlg);
|
|
|
|
CUiRecvFileInfo *pFileInfo = (CUiRecvFileInfo *) pDlg->GetRecvFileInfo();
|
|
ASSERT(NULL != pFileInfo);
|
|
|
|
// move the window to proper location
|
|
ULONG nCaptionHeight = ::GetSystemMetrics(SM_CYCAPTION);
|
|
ULONG nShift = nCaptionHeight * (s_cRecvDlg++ % 8);
|
|
RECT rcDlg;
|
|
::GetWindowRect(hdlg, &rcDlg);
|
|
::MoveWindow(hdlg, rcDlg.left + nShift, rcDlg.top + nShift,
|
|
rcDlg.right - rcDlg.left, rcDlg.bottom - rcDlg.top, FALSE);
|
|
|
|
// Set font (for international)
|
|
HFONT hfont = (HFONT) ::GetStockObject(DEFAULT_GUI_FONT);
|
|
ASSERT(NULL != hfont);
|
|
::SendDlgItemMessage(hdlg, IDE_RECVDLG_RECFILE, WM_SETFONT, (WPARAM) hfont, 0);
|
|
::SendDlgItemMessage(hdlg, IDE_RECVDLG_RECDIR, WM_SETFONT, (WPARAM) hfont, 0);
|
|
::SendDlgItemMessage(hdlg, IDE_RECVDLG_SENDER, WM_SETFONT, (WPARAM) hfont, 0);
|
|
|
|
// cache names
|
|
LPTSTR pszFileName = pFileInfo->GetName();
|
|
LPTSTR pszFullName = pFileInfo->GetFullName();
|
|
|
|
// title
|
|
TCHAR szText[MAX_PATH*2];
|
|
if (::MyLoadString(IDS_RECVDLG_TITLE, szText, pszFileName))
|
|
{
|
|
::SetWindowText(hdlg, szText);
|
|
}
|
|
|
|
// filename
|
|
::lstrcpyn(szText, pszFileName, MAX_FILE_NAME_LENGTH);
|
|
if (::lstrlen(pszFileName) > MAX_FILE_NAME_LENGTH)
|
|
{
|
|
LPTSTR psz = szText;
|
|
int i = MAX_FILE_NAME_LENGTH - 1;
|
|
while (i)
|
|
{
|
|
psz = CharNext(psz);
|
|
i--;
|
|
}
|
|
::lstrcpy(psz, TEXT("..."));
|
|
}
|
|
::SetDlgItemText(hdlg, IDE_RECVDLG_RECFILE, szText);
|
|
|
|
// directory Name
|
|
LPTSTR psz = szText;
|
|
::lstrcpyn(szText, pszFullName, (int)(pszFileName - pszFullName));
|
|
HDC hdc = ::GetDC(hdlg);
|
|
if (NULL != hdc)
|
|
{
|
|
SIZE size;
|
|
if (::GetTextExtentPoint32(hdc, szText, ::lstrlen(szText), &size))
|
|
{
|
|
RECT rc;
|
|
::GetWindowRect(::GetDlgItem(hdlg, IDE_RECVDLG_RECDIR), &rc);
|
|
if (size.cx > (rc.right - rc.left))
|
|
{
|
|
// Just display the folder name
|
|
psz = (LPTSTR) ::GetFileNameFromPath(szText);
|
|
}
|
|
}
|
|
}
|
|
::ReleaseDC(hdlg, hdc);
|
|
::SetDlgItemText(hdlg, IDE_RECVDLG_RECDIR, psz);
|
|
|
|
// sender Name
|
|
if (::T120_GetNodeName(pDlg->GetConfID(), pDlg->GetSenderID(), szText, count_of(szText)))
|
|
{
|
|
::SetDlgItemText(hdlg, IDE_RECVDLG_SENDER, szText);
|
|
}
|
|
|
|
// update "Received xxx bytes of yyy"
|
|
if (::MyLoadString(IDS_RECVDLG_RECBYTES, szText, pFileInfo->GetTotalRecvSize(), pFileInfo->GetSize()))
|
|
{
|
|
::SetDlgItemText(hdlg, IDE_RECVDLG_RECBYTES, szText);
|
|
}
|
|
|
|
// progress bar
|
|
::SendMessage(GetDlgItem(hdlg, IDC_RECVDLG_PROGRESS), PBM_SETPOS, pDlg->GetPercent(), 0);
|
|
|
|
// start animation
|
|
Animate_Open(GetDlgItem(hdlg, IDC_RECVDLG_ANIMATE), MAKEINTRESOURCE(IDA_RECVDLG_ANIMATION));
|
|
|
|
// do the animation work
|
|
if (! pDlg->IsRecvComplete())
|
|
{
|
|
Animate_Play(GetDlgItem(hdlg, IDC_RECVDLG_ANIMATE), 0, -1, -1);
|
|
if (::LoadString(g_hDllInst, IDS_RECVDLG_START, szText, count_of(szText)))
|
|
{
|
|
::SetDlgItemText(hdlg, IDE_RECVDLG_TIME, szText);
|
|
}
|
|
}
|
|
|
|
// show the window now
|
|
::ShowWindow(hdlg, SW_SHOWNORMAL);
|
|
|
|
// UpdateProgress();
|
|
pDlg->OnProgressUpdate();
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// RecvDlg_OnCommand
|
|
//
|
|
|
|
void RecvDlg_OnCommand(HWND hdlg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
CRecvDlg *pDlg = (CRecvDlg *) ::GetWindowLongPtr(hdlg, DWLP_USER);
|
|
ASSERT(NULL != pDlg);
|
|
|
|
switch (GET_WM_COMMAND_ID(wParam, lParam))
|
|
{
|
|
case IDM_RECVDLG_DELETE:
|
|
pDlg->OnDelete();
|
|
break;
|
|
|
|
case IDM_RECVDLG_OPEN:
|
|
pDlg->OnOpen();
|
|
break;
|
|
|
|
case IDM_RECVDLG_ACCEPT:
|
|
case IDOK:
|
|
case IDCANCEL:
|
|
case IDCLOSE:
|
|
pDlg->OnAccept();
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
|
|
// dismiss the dialog
|
|
::EndDialog(hdlg, GET_WM_COMMAND_ID(wParam, lParam));
|
|
pDlg->Release();
|
|
}
|
|
|
|
|
|
void CRecvDlg::OnOpen(void)
|
|
{
|
|
// create short version of the path name
|
|
TCHAR szDir[MAX_PATH];
|
|
::GetShortPathName(m_pRecvFileInfo->GetRecvFolder(), szDir, count_of(szDir));
|
|
|
|
// create short version of the full name
|
|
TCHAR szFile[MAX_PATH];
|
|
szFile[0] = TEXT('\0');
|
|
::wsprintf(szFile, TEXT("%s\\%s"), szDir, m_pRecvFileInfo->GetName());
|
|
|
|
TRACE_OUT(("FT: Opening [%s] in [%]", m_pRecvFileInfo->GetName(), szDir));
|
|
|
|
HINSTANCE hInst = ::ShellExecute(m_pWindow->GetHwnd(),
|
|
NULL,
|
|
szFile,
|
|
NULL,
|
|
szDir,
|
|
SW_SHOWDEFAULT);
|
|
if (32 >= (DWORD_PTR) hInst)
|
|
{
|
|
WARNING_OUT(("Unable to open [%s] - showing file", szFile));
|
|
::ShellExecute(m_pWindow->GetHwnd(),
|
|
NULL,
|
|
szDir,
|
|
m_pRecvFileInfo->GetFullName(),
|
|
NULL,
|
|
SW_SHOWDEFAULT);
|
|
}
|
|
}
|
|
|
|
|
|
void CRecvDlg::OnDelete(void)
|
|
{
|
|
StopAnimation();
|
|
|
|
// check if transfer has completed
|
|
if (! m_fRecvComplete)
|
|
{
|
|
DBG_SAVE_FILE_LINE
|
|
m_pWindow->GetEngine()->SafePostMessage(
|
|
new FileTransferControlMsg(
|
|
m_nEventHandle,
|
|
m_pRecvFileInfo->GetFileHandle(),
|
|
NULL,
|
|
NULL,
|
|
FileTransferControlMsg::EnumAbortFile));
|
|
}
|
|
else
|
|
{
|
|
::DeleteFile(m_pRecvFileInfo->GetFullName());
|
|
}
|
|
}
|
|
|
|
|
|
void CRecvDlg::OnAccept(void)
|
|
{
|
|
StopAnimation();
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// RecvDlg_OnInitMenuPopup
|
|
//
|
|
|
|
void RecvDlg_OnInitMenuPopup(HWND hdlg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if (0 != HIWORD(lParam)) // System menu flag
|
|
{
|
|
HMENU hMenu = (HMENU) wParam; // handle of pop-up menu
|
|
::EnableMenuItem(hMenu, SC_MAXIMIZE, MF_GRAYED);
|
|
::EnableMenuItem(hMenu, SC_SIZE, MF_GRAYED);
|
|
}
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// RecvDlgProc
|
|
//
|
|
|
|
INT_PTR CALLBACK RecvDlgProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
BOOL fRet = TRUE; // processed
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
ASSERT(NULL != lParam);
|
|
::SetWindowLongPtr(hdlg, DWLP_USER, lParam);
|
|
RecvDlg_OnInitDialog(hdlg, wParam, lParam);
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
RecvDlg_OnCommand(hdlg, wParam, lParam);
|
|
break;
|
|
|
|
case WM_INITMENUPOPUP:
|
|
RecvDlg_OnInitMenuPopup(hdlg, wParam, lParam);
|
|
fRet = FALSE;
|
|
break;
|
|
|
|
// This means user wants to delete the file.
|
|
case WM_CLOSE:
|
|
RecvDlg_OnCommand(hdlg, IDCLOSE, lParam);
|
|
break;;
|
|
|
|
default:
|
|
fRet = FALSE; // not processed
|
|
break;
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// RecvDlg Animation
|
|
//
|
|
|
|
void CRecvDlg::StopAnimation(void)
|
|
{
|
|
HWND hwnd = ::GetDlgItem(m_hwndRecvDlg, IDC_RECVDLG_ANIMATE);
|
|
if (NULL != hwnd)
|
|
{
|
|
Animate_Stop(hwnd);
|
|
Animate_Close(hwnd);
|
|
}
|
|
}
|
|
|
|
|
|
ULONG _GetPercent(ULONG cbTotalRecvSize , ULONG cbFileSize)
|
|
{
|
|
|
|
if (! cbFileSize || (cbTotalRecvSize >= cbFileSize))
|
|
{
|
|
return 100;
|
|
}
|
|
|
|
// FUTURE: Consider using EnlargedUnsignedMultiply
|
|
|
|
if (cbFileSize < 0x01000000)
|
|
{
|
|
return (cbTotalRecvSize * 100) / cbFileSize;
|
|
}
|
|
|
|
return cbTotalRecvSize / (cbFileSize / 100);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// RecvDlg Progress
|
|
//
|
|
|
|
ULONG CRecvDlg::GetPercent(void)
|
|
{
|
|
return _GetPercent(m_pRecvFileInfo->GetTotalRecvSize(), m_pRecvFileInfo->GetSize());
|
|
}
|
|
|
|
|
|
|
|
void CRecvDlg::OnProgressUpdate(FileTransmitMsg *pMsg)
|
|
{
|
|
|
|
if (NULL != pMsg)
|
|
{
|
|
ASSERT(iMBFT_FILE_RECEIVE_PROGRESS == (MBFT_NOTIFICATION) pMsg->m_TransmitStatus ||
|
|
iMBFT_FILE_RECEIVE_BEGIN == (MBFT_NOTIFICATION) pMsg->m_TransmitStatus);
|
|
|
|
ASSERT(m_nEventHandle == pMsg->m_EventHandle);
|
|
ASSERT(m_pRecvFileInfo->GetFileHandle() == pMsg->m_hFile);
|
|
ASSERT(m_pRecvFileInfo->GetSize() == pMsg->m_FileSize);
|
|
|
|
m_pRecvFileInfo->SetTotalRecvSize(pMsg->m_BytesTransmitted);
|
|
|
|
if (pMsg->m_BytesTransmitted >= pMsg->m_FileSize)
|
|
{
|
|
m_fRecvComplete = TRUE;
|
|
m_idResult = IDS_RECVDLG_COMPLETE;
|
|
}
|
|
}
|
|
|
|
if (m_fRecvComplete && ! m_fShownRecvCompleteUI)
|
|
{
|
|
m_fRecvComplete = TRUE;
|
|
|
|
TCHAR szText[MAX_PATH];
|
|
if (::LoadString(g_hDllInst, IDS_RECVDLG_CLOSE, szText, count_of(szText)))
|
|
{
|
|
::SetDlgItemText(m_hwndRecvDlg, IDM_RECVDLG_ACCEPT, szText);
|
|
}
|
|
|
|
if (IDS_RECVDLG_COMPLETE == m_idResult)
|
|
{
|
|
::EnableWindow(::GetDlgItem(m_hwndRecvDlg, IDM_RECVDLG_OPEN), TRUE);
|
|
}
|
|
else
|
|
{
|
|
::EnableWindow(::GetDlgItem(m_hwndRecvDlg, IDM_RECVDLG_DELETE), FALSE);
|
|
}
|
|
|
|
// Reset animation
|
|
HWND hwnd = ::GetDlgItem(m_hwndRecvDlg, IDC_RECVDLG_ANIMATE);
|
|
Animate_Stop(hwnd);
|
|
Animate_Close(hwnd);
|
|
Animate_Open(hwnd, MAKEINTRESOURCE(IDA_RECVDLG_DONE));
|
|
Animate_Seek(hwnd, ((IDS_RECVDLG_COMPLETE == m_idResult) ? 0 : 1));
|
|
|
|
m_fShownRecvCompleteUI = TRUE;
|
|
}
|
|
|
|
ULONG cbTotalRecvSize = m_pRecvFileInfo->GetTotalRecvSize();
|
|
ULONG cbFileSize = m_pRecvFileInfo->GetSize();
|
|
|
|
DWORD dwNow = ::GetTickCount();
|
|
DWORD dwBytesPerSec;
|
|
DWORD dwBytesRead;
|
|
TCHAR szOut[MAX_PATH];
|
|
|
|
if (m_dwPreviousTransferred != cbTotalRecvSize)
|
|
{
|
|
TCHAR szFmt[MAX_PATH];
|
|
|
|
// Update "Received xxx bytes of yyy"
|
|
if (::LoadString(g_hDllInst, IDS_RECVDLG_RECBYTES, szFmt, count_of(szFmt)))
|
|
{
|
|
::wsprintf(szOut, szFmt, cbTotalRecvSize, cbFileSize);
|
|
::SetDlgItemText(m_hwndRecvDlg, IDE_RECVDLG_RECBYTES, szOut);
|
|
}
|
|
|
|
// Update Progress Bar
|
|
if (cbTotalRecvSize)
|
|
{
|
|
::SendMessage(GetDlgItem(m_hwndRecvDlg, IDC_RECVDLG_PROGRESS), PBM_SETPOS, GetPercent(), 0);
|
|
}
|
|
}
|
|
|
|
// check if no time estimate is required
|
|
if (m_fRecvComplete)
|
|
{
|
|
if (::LoadString(g_hDllInst, m_idResult, szOut, count_of(szOut)))
|
|
{
|
|
::SetDlgItemText(m_hwndRecvDlg, IDE_RECVDLG_TIME, szOut);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// first time we're in here for this file?
|
|
if (! m_dwPreviousTime || ! cbTotalRecvSize)
|
|
{
|
|
// no data, yet
|
|
m_dwPreviousTime = dwNow - 1000;
|
|
ASSERT(! m_dwPreviousTransferred);
|
|
ASSERT(! m_dwBytesPerSec);
|
|
return;
|
|
}
|
|
|
|
// Has enough time elapsed to update the display?
|
|
// We do this about every 5 seconds (note the adjustment for first time)
|
|
if ((dwNow - m_dwPreviousTime) < 5000)
|
|
return;
|
|
|
|
dwBytesRead = cbTotalRecvSize - m_dwPreviousTransferred;
|
|
|
|
// We take 10 times the number of bytes and divide by the number of
|
|
// tenths of a second to minimize both overflow and roundoff
|
|
dwBytesPerSec = dwBytesRead * 10 / ((dwNow - m_dwPreviousTime) / 100);
|
|
if (! dwBytesPerSec)
|
|
{
|
|
// very low transmission rate! Ignore the information?
|
|
return;
|
|
}
|
|
if (m_dwBytesPerSec)
|
|
{
|
|
// Take the average of the current transfer rate and the
|
|
// previously computed one, just to try to smooth out
|
|
// some random fluctuations
|
|
dwBytesPerSec = (dwBytesPerSec + m_dwBytesPerSec) / 2;
|
|
}
|
|
m_dwBytesPerSec = dwBytesPerSec;
|
|
|
|
// Calculate time remaining (round up by adding 1)
|
|
m_dwEstTimeLeft = ((cbFileSize - cbTotalRecvSize) / m_dwBytesPerSec) + 1;
|
|
|
|
// Reset time and # of bytes read
|
|
m_dwPreviousTime = dwNow;
|
|
m_dwPreviousTransferred = cbTotalRecvSize;
|
|
|
|
if (m_dwEstTimeLeft < 3)
|
|
{
|
|
// szOut[0] = _T('\0'); // don't bother updating when almost done
|
|
return;
|
|
}
|
|
if (m_dwEstTimeLeft > 99)
|
|
{
|
|
// dwTime is about 2 mintes
|
|
::MyLoadString(IDS_RECVDLG_MINUTES, szOut, ((m_dwEstTimeLeft / 60) + 1));
|
|
}
|
|
else
|
|
{
|
|
// Round up to 5 seconds so it doesn't look so random
|
|
::MyLoadString(IDS_RECVDLG_SECONDS, szOut, (((m_dwEstTimeLeft + 4) / 5) * 5) );
|
|
}
|
|
|
|
::SetDlgItemText(m_hwndRecvDlg, IDE_RECVDLG_TIME, szOut);
|
|
}
|
|
|
|
|
|
void CRecvDlg::OnCanceled(void)
|
|
{
|
|
m_idResult = IDS_RECVDLG_CANCEL;
|
|
m_fRecvComplete = TRUE;
|
|
OnProgressUpdate();
|
|
}
|
|
|
|
|
|
void CRecvDlg::OnRejectedFile(void)
|
|
{
|
|
m_idResult = IDS_RECVDLG_SENDER_CANCEL;
|
|
m_fRecvComplete = TRUE;
|
|
OnProgressUpdate();
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Shortcut/Link Management
|
|
//
|
|
|
|
void CAppletWindow::ResolveShortcut(LPTSTR pszSrcFile, LPTSTR pszDstFile)
|
|
{
|
|
ASSERT(NULL != pszSrcFile && '\0' != *pszSrcFile);
|
|
ASSERT(NULL != pszDstFile);
|
|
|
|
IShellLink *psl;
|
|
HRESULT hr = ::CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_IShellLink, (LPVOID *) &psl);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IPersistFile *ppf;
|
|
hr = psl->QueryInterface(IID_IPersistFile, (LPVOID *) &ppf);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
WCHAR wsz[MAX_PATH]; /* Buffer for unicode string */
|
|
#ifdef _UNICODE
|
|
::lstrcpyn(wsz, pszSrcFile, MAX_PATH);
|
|
#else
|
|
::MultiByteToWideChar(CP_ACP, 0, pszSrcFile, -1, wsz, MAX_PATH);
|
|
#endif
|
|
|
|
hr = ppf->Load(wsz, STGM_READ);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
/* Resolve the link, this may post UI to find the link */
|
|
hr = psl->Resolve(m_hwndMainUI, SLR_ANY_MATCH);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
psl->GetPath(pszDstFile, MAX_PATH, NULL, 0);
|
|
}
|
|
|
|
TRACE_OUT(("CAppletWindow::ResolveShortcut: File resolved to [%s]", pszDstFile));
|
|
}
|
|
ppf->Release();
|
|
}
|
|
psl->Release();
|
|
}
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// Non-blocking Message Box
|
|
//
|
|
|
|
INT_PTR MsgBox2DlgProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
BOOL fHandled = FALSE;
|
|
CAppletWindow *pWindow;
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
// get the text to display
|
|
LPTSTR pszText = (LPTSTR) lParam;
|
|
ASSERT(NULL != pszText && TEXT('\0') != *pszText);
|
|
|
|
// estimate how big the read-only edit control should be
|
|
HDC hdc = ::GetDC(hdlg);
|
|
if (NULL != hdc)
|
|
{
|
|
SIZE csEdit;
|
|
if (::GetTextExtentPoint32(hdc, pszText, ::lstrlen(pszText), &csEdit))
|
|
{
|
|
const ULONG c_nMarginX = 0;
|
|
const ULONG c_nMarginY = 10;
|
|
|
|
ULONG nCaptionHeight = ::GetSystemMetrics(SM_CYCAPTION);
|
|
ULONG nShift = nCaptionHeight * (s_cMsgBox2Dlg++ % 8);
|
|
|
|
// move the edit control
|
|
HWND hwndEdit = ::GetDlgItem(hdlg, IDE_MSGBOX2_TEXT);
|
|
POINT ptEdit;
|
|
ptEdit.x = c_nMarginX;
|
|
ptEdit.y = c_nMarginY + (c_nMarginY >> 1);
|
|
csEdit.cx += c_nMarginX << 1;
|
|
csEdit.cy += c_nMarginY << 1;
|
|
::MoveWindow(hwndEdit, ptEdit.x, ptEdit.y, csEdit.cx, csEdit.cy, FALSE);
|
|
|
|
// move the ok button
|
|
HWND hwndOK = ::GetDlgItem(hdlg, IDOK);
|
|
RECT rcOK;
|
|
::GetWindowRect(hwndOK, &rcOK);
|
|
SIZE csOK;
|
|
csOK.cx = rcOK.right - rcOK.left;
|
|
csOK.cy = rcOK.bottom - rcOK.top;
|
|
POINT ptOK;
|
|
ptOK.x = ptEdit.x + (csEdit.cx >> 1) - (csOK.cx >> 1);
|
|
ptOK.y = ptEdit.y + csEdit.cy + (c_nMarginY >> 1);
|
|
::MoveWindow(hwndOK, ptOK.x, ptOK.y, csOK.cx, csOK.cy, FALSE);
|
|
|
|
// adjust all the windows
|
|
RECT rcDlg, rcClient;
|
|
::GetWindowRect(hdlg, &rcDlg);
|
|
POINT ptDlg;
|
|
ptDlg.x = rcDlg.left + nShift;
|
|
ptDlg.y = rcDlg.top + nShift;
|
|
::GetClientRect(hdlg, &rcClient);
|
|
SIZE csDlg;
|
|
csDlg.cx = (rcDlg.right - rcDlg.left) - (rcClient.right - rcClient.left);
|
|
csDlg.cy = (rcDlg.bottom - rcDlg.top) - (rcClient.bottom - rcClient.top);
|
|
csDlg.cx += ptEdit.x + csEdit.cx + c_nMarginX;
|
|
csDlg.cy += ptOK.y + csOK.cy + c_nMarginY;
|
|
::MoveWindow(hdlg, ptDlg.x, ptDlg.y, csDlg.cx, csDlg.cy, FALSE);
|
|
}
|
|
::ReleaseDC(hdlg, hdc);
|
|
}
|
|
|
|
::SetDlgItemText(hdlg, IDE_MSGBOX2_TEXT, pszText);
|
|
delete [] pszText; // free the display text
|
|
fHandled = TRUE;
|
|
}
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (GET_WM_COMMAND_ID(wParam, lParam))
|
|
{
|
|
case IDOK:
|
|
case IDCANCEL:
|
|
case IDCLOSE:
|
|
switch (GET_WM_COMMAND_CMD(wParam, lParam))
|
|
{
|
|
case BN_CLICKED:
|
|
pWindow = (CAppletWindow*)::GetWindowLongPtr(hdlg, DWLP_USER);
|
|
ASSERT (pWindow);
|
|
if (pWindow)
|
|
{
|
|
pWindow->RemoveErrorDlg(hdlg);
|
|
pWindow->FocusNextErrorDlg();
|
|
}
|
|
::EndDialog(hdlg, IDOK);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
fHandled = TRUE;
|
|
break;
|
|
}
|
|
|
|
return(fHandled);
|
|
}
|
|
|
|
|
|
BOOL MsgBox2(CAppletWindow *pWindow, LPTSTR pszText)
|
|
{
|
|
BOOL fRet = FALSE;
|
|
ULONG cch = ::lstrlen(pszText) + 1;
|
|
DBG_SAVE_FILE_LINE
|
|
LPTSTR pszNew = new TCHAR[cch];
|
|
if (NULL != pszNew)
|
|
{
|
|
::CopyMemory(pszNew, pszText, cch);
|
|
HWND hwndDlg = ::CreateDialogParam(g_hDllInst, MAKEINTRESOURCE(IDD_MSGBOX2),
|
|
pWindow->GetHwnd(), MsgBox2DlgProc, (LPARAM) pszNew);
|
|
|
|
ASSERT(NULL != hwndDlg);
|
|
if (NULL != hwndDlg)
|
|
{
|
|
::ShowWindow(hwndDlg, SW_SHOWNORMAL);
|
|
fRet = TRUE;
|
|
::SetForegroundWindow(hwndDlg);
|
|
::SetWindowLongPtr(hwndDlg, DWLP_USER, (LPARAM)pWindow);
|
|
pWindow->AddErrorDlg(hwndDlg);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ERROR_OUT(("FT::MsgBox2: cannot duplicate string [%s]", pszText));
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
//
|
|
// Receive Folder Management
|
|
//
|
|
|
|
HRESULT GetRecvFolder(LPTSTR pszInFldr, LPTSTR pszOutFldr)
|
|
{
|
|
LPTSTR psz;
|
|
TCHAR szPath[MAX_PATH];
|
|
|
|
RegEntry reFileXfer(FILEXFER_KEY, HKEY_CURRENT_USER);
|
|
|
|
if (NULL == pszInFldr)
|
|
{
|
|
// NULL directory specified - get info from registry or use default
|
|
psz = reFileXfer.GetString(REGVAL_FILEXFER_PATH);
|
|
if (NULL != psz && TEXT('\0') != *psz)
|
|
{
|
|
::lstrcpyn(szPath, psz, count_of(szPath));
|
|
}
|
|
else
|
|
{
|
|
TCHAR szInstallDir[MAX_PATH];
|
|
::GetInstallDirectory(szInstallDir);
|
|
::MyLoadString(IDS_RECDIR_DEFAULT, szPath, szInstallDir);
|
|
}
|
|
|
|
pszInFldr = szPath;
|
|
}
|
|
|
|
::lstrcpyn(pszOutFldr, pszInFldr, MAX_PATH);
|
|
|
|
// Remove trailing backslash, if any
|
|
for (psz = pszOutFldr; *psz; psz = CharNext(psz))
|
|
{
|
|
if ('\\' == *psz && '\0' == *CharNext(psz))
|
|
{
|
|
*psz = '\0';
|
|
break;
|
|
}
|
|
}
|
|
|
|
HRESULT hr;
|
|
if (!FEnsureDirExists(pszOutFldr))
|
|
{
|
|
WARNING_OUT(("ChangeRecDir: FT directory is invalid [%s]", pszOutFldr));
|
|
hr = E_FAIL;
|
|
}
|
|
else
|
|
{
|
|
// update the registry
|
|
reFileXfer.SetValue(REGVAL_FILEXFER_PATH, pszOutFldr);
|
|
hr = S_OK;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
void EnsureTrailingSlash(LPTSTR psz)
|
|
{
|
|
LPTSTR psz2;
|
|
|
|
// Make sure the directory name has a trailing '\'
|
|
while (TEXT('\0') != *psz)
|
|
{
|
|
psz2 = ::CharNext(psz);
|
|
if (TEXT('\\') == *psz && TEXT('\0') == *psz2)
|
|
{
|
|
// The path already ends with a backslash
|
|
return;
|
|
}
|
|
psz = psz2;
|
|
}
|
|
|
|
// Append a trailing backslash
|
|
*psz = TEXT('\\');
|
|
psz = ::CharNext(psz);
|
|
*psz = TEXT('\0');
|
|
}
|
|
|