📄 view.cpp
字号:
/*****************************************************************************\
FILE: view.cpp
DESCRIPTION:
This is our ShellView which implements FTP specific behavior. We get
the default DefView implementation and then use IShellFolderViewCB to
override behavior specific to us.
\*****************************************************************************/
#include "priv.h"
#include "view.h"
#include "ftpobj.h"
#include "statusbr.h"
#include "dialogs.h"
#include <inetcpl.h>
#include <htmlhelp.h>
#include "newmenu.h"
extern ULONG g_cRef_CFtpView;
// {FBDB45F0-DBF8-11d2-BB9B-006097DF5BD4} Private to msieftp.dll, NEVER EVER use outside of this DLL
const GUID IID_CFtpViewPrivThis = { 0xfbdb45f0, 0xdbf8, 0x11d2, { 0xbb, 0x9b, 0x0, 0x60, 0x97, 0xdf, 0x5b, 0xd4 } };
/*****************************************************************************
*
* COLINFO, c_rgci
*
* Column information for DVM_GETDETAILSOF.
*
*****************************************************************************/
const struct COLINFO {
UINT cchCol;
UINT uiFmt;
} c_rgci[] = {
{ 30, LVCFMT_LEFT },
{ 10, LVCFMT_RIGHT },
{ 20, LVCFMT_LEFT },
{ 20, LVCFMT_LEFT },
};
BOOL CFtpView::IsForegroundThread(void)
{
return (GetCurrentThreadId() == m_nThreadID);
}
/*****************************************************************************\
FUNCTION: _MOTDDialogProc
DESCRIPTION:
\*****************************************************************************/
INT_PTR CALLBACK CFtpView::_MOTDDialogProc(HWND hDlg, UINT wm, WPARAM wParam, LPARAM lParam)
{
LRESULT lResult = FALSE;
switch (wm)
{
case WM_INITDIALOG:
{
CFtpView * pThis = (CFtpView *) lParam;
CFtpGlob * pfg = pThis->m_pff->GetSiteMotd();
if (EVAL(pfg))
{
// TODO: NT #250018. Format the message and make it look pretty.
// so it doesn't have the FTP status numbers. We may also
// want to filter only the message that comes thru with
// status numbers 230
EVAL(SetWindowText(GetDlgItem(hDlg, IDC_MOTDDLG_MESSAGE), pfg->GetHGlobAsTCHAR()));
pfg->Release();
}
}
break;
case WM_COMMAND:
if ((IDOK == GET_WM_COMMAND_ID(wParam, lParam)) ||
(IDCANCEL == GET_WM_COMMAND_ID(wParam, lParam)))
EndDialog(hDlg, TRUE);
break;
}
return lResult;
}
/*****************************************************************************
*
* _ShowMotdPsf
*
* Show the motd for a particular psf.
*
*****************************************************************************/
void CFtpView::_ShowMotdPsf(HWND hwndOwner)
{
DialogBoxParam(HINST_THISDLL, MAKEINTRESOURCE(IDD_MOTDDLG), hwndOwner, _MOTDDialogProc, (LPARAM)this);
}
/*****************************************************************************
*
* _ShowMotd
*
* When Explorer finally goes idle, this procedure will be called,
* and we will show the FTP site's (new) motd.
*
*****************************************************************************/
void CFtpView::_ShowMotd(void)
{
m_hgtiWelcome = 0;
if (EVAL(m_pff))
_ShowMotdPsf(m_hwndOwner);
else
{
// We got cancelled prematurely
}
}
/*****************************************************************************
*
* _OnGetDetailsOf
*
* ici - column for which information is requested
* pdi -> DETAILSINFO
*
* If pdi->pidl is 0, then we are asking for information about
* what columns to display. If pdi->pidl is nonzero, then we
* are asking for particular information about the specified pidl.
*
* _UNDOCUMENTED_: This callback and the DETAILSINFO structure
* are not documented. Nor is the quirk about pdi->pidl as
* noted above.
*
*****************************************************************************/
#define MAX_SIZE_STR 30
HRESULT CFtpView::_OnGetDetailsOf(UINT ici, PDETAILSINFO pdi)
{
HRESULT hr;
if (ici < COL_MAX)
{
pdi->str.uType = STRRET_CSTR;
pdi->str.cStr[0] = '\0';
if (pdi->pidl)
{
switch (ici)
{
case COL_NAME:
{
WCHAR wzDisplayName[MAX_PATH];
hr = FtpItemID_GetDisplayName(pdi->pidl, wzDisplayName, ARRAYSIZE(wzDisplayName));
if (EVAL(SUCCEEDED(hr)))
StringToStrRetW(wzDisplayName, &pdi->str);
}
break;
case COL_SIZE:
// (Directories don't get a size. Shell rules.)
if (!FtpPidl_IsDirectory(pdi->pidl, TRUE))
{
LONGLONG llSize = (LONGLONG) FtpItemID_GetFileSize(pdi->pidl);
WCHAR wzSizeStr[MAX_SIZE_STR];
if (StrFormatByteSizeW(llSize, wzSizeStr, ARRAYSIZE(wzSizeStr)))
SHUnicodeToAnsi(wzSizeStr, pdi->str.cStr, ARRAYSIZE(pdi->str.cStr));
else
StrFormatByteSizeA(FtpItemID_GetFileSizeLo(pdi->pidl), pdi->str.cStr, ARRAYSIZE(pdi->str.cStr));
}
hr = S_OK;
break;
case COL_TYPE:
hr = FtpPidl_GetFileTypeStrRet(pdi->pidl, &pdi->str);
break;
case COL_MODIFIED:
{
TCHAR szDateTime[MAX_PATH];
FILETIME ftLastModified = FtpPidl_GetFTPFileTime(pdi->pidl);
DWORD dwFlags = FDTF_SHORTDATE | FDTF_SHORTTIME;
switch (pdi->fmt)
{
case LVCFMT_LEFT_TO_RIGHT :
dwFlags |= FDTF_LTRDATE;
break;
case LVCFMT_RIGHT_TO_LEFT :
dwFlags |= FDTF_RTLDATE;
break;
}
Misc_StringFromFileTime(szDateTime, ARRAYSIZE(szDateTime), &ftLastModified, dwFlags);
hr = StringToStrRetW(szDateTime, &pdi->str);
}
break;
}
}
else
{
WCHAR wzColumnLable[MAX_PATH];
pdi->fmt = c_rgci[ici].uiFmt;
pdi->cxChar = c_rgci[ici].cchCol;
EVAL(LoadStringW(HINST_THISDLL, IDS_HEADER_NAME(ici), wzColumnLable, ARRAYSIZE(wzColumnLable)));
hr = StringToStrRetW(wzColumnLable, &pdi->str);
}
}
else
hr = E_NOTIMPL;
return hr;
}
/*****************************************************************************\
FUNCTION: _OnColumnClick
DESCRIPTION:
_UNDOCUMENTED_: This callback and its parameters are not documented.
_UNDOCUMENTED_: ShellFolderView_ReArrange is not documented.
PARAMETERS:
hwnd - view window
ici - column that was clicked
\*****************************************************************************/
HRESULT CFtpView::_OnColumnClick(UINT ici)
{
ShellFolderView_ReArrange(m_hwndOwner, ici);
return S_OK;
}
HRESULT CFtpView::_OnAddPropertyPages(SFVM_PROPPAGE_DATA * pData)
{
return AddFTPPropertyPages(pData->pfn, pData->lParam, &m_hinstInetCpl, m_psfv);
}
/*****************************************************************************\
FUNCTION: _OnInitMenuPopup
DESCRIPTION:
We use IContextMenu::QueryContectMenu() to merge background items into
the File menu. This doesn't work on browser only because it's not supported
so we would like to see if this works.
PARAMETERS:
\*****************************************************************************/
HRESULT CFtpView::_OnInitMenuPopup(HMENU hmenu, UINT idCmdFirst, UINT nIndex)
{
return S_OK;
}
/*****************************************************************************\
FUNCTION: _OnMergeMenu
DESCRIPTION:
_UNDOCUMENTED_: This callback and its parameters are not documented.
_UNDOCUMENTED_: Nothing about menu merging is documented.
PARAMETERS:
pqcm - QueryContextMenu info
\*****************************************************************************/
HRESULT CFtpView::_OnMergeMenu(LPQCMINFO pqcm)
{
HRESULT hr;
HMENU hmenu = LoadMenu(HINST_THISDLL, MAKEINTRESOURCE(IDM_FTPMERGE));
if (SHELL_VERSION_W95NT4 != GetShellVersion())
{
// We prefer to add "New" and "Login As" via
// IContextMenu::QueryContextMenu() but it wasn't implemented
// in browser only. The IDM_FTPMERGE menu contains a second
// copy for the browser only case so we need to remove them
// if it's not browser only.
EVAL(DeleteMenu(hmenu, FCIDM_MENU_FILE, MF_BYCOMMAND));
}
if (SHELL_VERSION_IE4 < GetShellVersion())
{
// Remove "Help.FTP Help" because we will have that work done
// in "Help.Help Topics" on NT5 and after. We don't do this for
// earlier versions of shell32 because shell32 in NT5 is the
// first version to support "HtmlHelp" over WinHelp. This is
// needed because FTP's help is stored in IE's HTML Help files.
EVAL(DeleteMenu(hmenu, IDC_ITEM_FTPHELP, MF_BYCOMMAND));
}
if (hmenu)
{
MergeMenuHierarchy(pqcm->hmenu, hmenu, pqcm->idCmdFirst, pqcm->idCmdLast);
m_idMergedMenus = pqcm->idCmdFirst;
m_nMenuItemsAdded = GetMenuItemCount(hmenu);
DestroyMenu(hmenu);
// Remove duplicate items. (Browser Only)
_SHPrettyMenu(pqcm->hmenu);
hr = S_OK;
}
else
{
hr = E_OUTOFMEMORY;
}
// NT #267081, some other people (IE) will reformat the StatusBar during the
// asynch navigation. I take this event (MergeMenus) and reformat the
// status bar if necessary.
_InitStatusBar();
return hr;
}
/*****************************************************************************\
FUNCTION: UnMergeMenu
DESCRIPTION:
PARAMETERS:
\*****************************************************************************/
HRESULT UnMergeMenu(HMENU hMenu, UINT idOffset, HMENU hMenuTemplate)
{
HRESULT hr = S_OK;
UINT nIndex;
UINT nEnd = GetMenuItemCount(hMenuTemplate);
for (nIndex = 0; nIndex < nEnd; nIndex++)
{
UINT idToDelete = GetMenuItemID(hMenuTemplate, nIndex);
if (-1 != idToDelete)
DeleteMenu(hMenu, (idToDelete + idOffset), MF_BYPOSITION);
else
{
// It may be a submenu, so we may need to recurse.
MENUITEMINFO mii;
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_SUBMENU;
mii.cch = 0; // just in case
if (GetMenuItemInfo(hMenuTemplate, nIndex, TRUE, &mii) && mii.hSubMenu)
{
// It is a sub menu, so delete those items also.
hr = UnMergeMenu(hMenu, idOffset, mii.hSubMenu);
}
}
}
return hr;
}
HRESULT CFtpView::_OnUnMergeMenu(HMENU hMenu)
{
HRESULT hr = S_OK;
// Did I merge anything?
if (m_idMergedMenus && m_nMenuItemsAdded)
{
HMENU hMenuFTP = LoadMenu(HINST_THISDLL, MAKEINTRESOURCE(IDM_FTPMERGE));
if (hMenuFTP)
{
hr = UnMergeMenu(hMenu, m_idMergedMenus, hMenuFTP);
DestroyMenu(hMenuFTP);
}
m_idMergedMenus = 0;
}
return hr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -