windows-nt/Source/XPSP1/NT/shell/ext/ftp/statusbr.cpp
2020-09-26 16:20:57 +08:00

370 lines
12 KiB
C++

/*****************************************************************************
*
* statusbr.cpp - Take care of the status bar.
*
*****************************************************************************/
#include "priv.h"
#include "statusbr.h"
// HACKHACK:
// \nt\public\sdk\inc\multimon.h overrides the normal GetSystemMetrics() with
// xGetSystemMetrics(). The problem is that you can't link because you need to
// have at least one file in your project that #defines COMPILE_MULTIMON_STUBS
// so that these stub override functions will get implemented.
#define COMPILE_MULTIMON_STUBS
#include "multimon.h"
#define PANE_WIDTH_USERNAME 125
#define STATUS_PANES 3
//////////////////////////////////////////////////////////////////
// General Text Pane
//////////////////////////////////////////////////////////////////
void CStatusBar::SetStatusMessage(UINT nMessageID, LPCTSTR pszExtra)
{
if (NULL == this)
return;
_InitStatusBar(); // This is a NO-OP if it's already inited.
ASSERTNONCRITICAL;
if (m_hwndStatus)
{
TCHAR szMsg[256] = TEXT("%s");
TCHAR szBuf[1024];
if (nMessageID)
LoadString(g_hinst, nMessageID, szMsg, ARRAYSIZE(szMsg));
wnsprintf(szBuf, ARRAYSIZE(szBuf), szMsg, pszExtra);
// TraceMsg(TF_FTPSTATUSBAR, "CStatusBar::SetStatusMessage() Message=%s", szBuf);
SendMessage(m_hwndStatus, SB_SETTEXT, STATUS_PANE_STATUS, (LPARAM)szBuf);
SendMessage(m_hwndStatus, SB_SETTIPTEXT, STATUS_PANE_STATUS, (LPARAM)szBuf);
UpdateWindow(m_hwndStatus);
}
}
//////////////////////////////////////////////////////////////////
// User Name Pane
//////////////////////////////////////////////////////////////////
void CStatusBar::SetUserName(LPCTSTR pszUserName, BOOL fAnnonymous)
{
TCHAR szTipText[MAX_PATH];
TCHAR szStrTemplate[MAX_PATH];
_InitStatusBar(); // This is a NO-OP if it's already inited.
//TraceMsg(TF_FTPSTATUSBAR, "CStatusBar::SetUserName(pszUserName=%s, fAnnonymous=%d)", pszUserName, fAnnonymous);
ASSERT(pszUserName);
LoadString(HINST_THISDLL, IDS_USER_TEMPLATE, szStrTemplate, ARRAYSIZE(szStrTemplate));
if (fAnnonymous)
{
TCHAR szAnnonymousName[MAX_PATH];
LoadString(HINST_THISDLL, IDS_USER_ANNONYMOUS, szAnnonymousName, ARRAYSIZE(szAnnonymousName));
wnsprintf(szTipText, ARRAYSIZE(szTipText), szStrTemplate, szAnnonymousName);
}
else
wnsprintf(szTipText, ARRAYSIZE(szTipText), szStrTemplate, pszUserName);
Str_SetPtr(&m_pszUserName, szTipText);
LoadString(HINST_THISDLL, (fAnnonymous ? IDS_USER_ANNONTOOLTIP : IDS_USER_USERTOOLTIP), szStrTemplate, ARRAYSIZE(szStrTemplate));
wnsprintf(szTipText, ARRAYSIZE(szTipText), szStrTemplate, pszUserName);
Str_SetPtr(&m_pszUserNameTT, szTipText);
_SetUserParts();
}
void CStatusBar::_SetUserParts(void)
{
SendMessage(m_hwndStatus, SB_SETTEXT, STATUS_PANE_USERNAME, (LPARAM)(m_pszUserName ? m_pszUserName : TEXT("")));
SendMessage(m_hwndStatus, SB_SETTIPTEXT, STATUS_PANE_USERNAME, (LPARAM)(m_pszUserNameTT ? m_pszUserNameTT : TEXT("")));
}
//////////////////////////////////////////////////////////////////
// Icons Panes (Read, Write, ...)
//////////////////////////////////////////////////////////////////
#define GET_RESID_FROM_PERMISSION(nType, nAllowed) (IDS_BEGIN_SB_TOOLTIPS + nType + (nAllowed ? 0 : 1))
void CStatusBar::SetFolderAttribute(BOOL fWriteAllowed)
{
TCHAR szToolTip[MAX_PATH];
_InitStatusBar(); // This is a NO-OP if it's already inited.
m_fWriteAllowed = fWriteAllowed;
LoadString(HINST_THISDLL, GET_RESID_FROM_PERMISSION(ITD_WriteAllowed, fWriteAllowed), szToolTip, ARRAYSIZE(szToolTip));
_SetIconAndTip(ISLOT_WritePermission, fWriteAllowed ? ITD_WriteAllowed : ITD_WriteNotAllowed, szToolTip);
}
HRESULT CStatusBar::_SetIconAndTip(ICON_SLOT nIconSlot, ICON_TODISPLAY nIconToDisplay, LPCTSTR pszTip)
{
/*
if (EVAL(m_hwndStatus))
{
if (!m_arhiconGeneral[nIconToDisplay])
{
m_arhiconGeneral[nIconToDisplay] = (HICON)LoadImage(HINST_THISDLL, MAKEINTRESOURCE(nIconToDisplay + IDI_WRITE_ALLOWED),
IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0);
}
SendMessage(m_hwndStatus, SB_SETICON, STATUS_PANE_WRITEICON, (LPARAM)m_arhiconGeneral[nIconToDisplay]);
SendMessage(m_hwndStatus, SB_SETTIPTEXT, STATUS_PANE_WRITEICON, (LPARAM)pszTip);
}
*/
return S_OK;
}
//////////////////////////////////////////////////////////////////
// Zones Pane
//////////////////////////////////////////////////////////////////
void CStatusBar::UpdateZonesPane(LPCTSTR pszUrl)
{
_InitStatusBar(); // This is a NO-OP if it's already inited.
if (EVAL(SUCCEEDED(_LoadZoneInfo(pszUrl))))
EVAL(SUCCEEDED(_SetZone()));
}
HRESULT CStatusBar::_LoadZoneInfo(LPCTSTR pszUrl)
{
m_lCurrentZone = ZONE_UNKNOWN;
if (!m_pism)
CoCreateInstance(CLSID_InternetSecurityManager, NULL, CLSCTX_INPROC_SERVER, IID_IInternetSecurityManager, (void **)&m_pism);
if (m_pism)
{
WCHAR wzUrl[MAX_URL_STRING];
SHTCharToUnicode(pszUrl, wzUrl, ARRAYSIZE(wzUrl));
m_pism->MapUrlToZone(wzUrl, (DWORD*)&m_lCurrentZone, 0);
}
return S_OK;
}
HRESULT CStatusBar::_SetZone(void)
{
ZONEATTRIBUTES za = {SIZEOF(za)};
HICON hIcon = NULL;
if (!m_arhiconZones[0])
_CacheZonesIcons();
if (m_pizm && (m_lCurrentZone != ZONE_UNKNOWN))
{
m_pizm->GetZoneAttributes(m_lCurrentZone, &za);
hIcon = m_arhiconZones[m_lCurrentZone];
}
else
_LoadStringW(HINST_THISDLL, IDS_ZONES_UNKNOWN, za.szDisplayName, ARRAYSIZE(za.szDisplayName));
SendMessage(m_hwndStatus, SB_SETTEXTW, STATUS_PANE_ZONE, (LPARAM)za.szDisplayName);
SendMessage(m_hwndStatus, SB_SETTIPTEXTW, STATUS_PANE_ZONE, (LPARAM)za.szDisplayName);
SendMessage(m_hwndStatus, SB_SETICON, STATUS_PANE_ZONE, (LPARAM)hIcon);
return S_OK;
}
void CStatusBar::_CacheZonesIcons(void)
{
DWORD dwZoneCount = 0;
if (!m_pizm)
CoCreateInstance(CLSID_InternetZoneManager, NULL, CLSCTX_INPROC_SERVER, IID_IInternetZoneManager, (void **)&m_pizm);
if (m_pizm)
{
DWORD dwZoneEnum;
if (EVAL(SUCCEEDED(m_pizm->CreateZoneEnumerator(&dwZoneEnum, &dwZoneCount, 0))))
{
for (int nIndex=0; (DWORD)nIndex < dwZoneCount; nIndex++)
{
DWORD dwZone;
ZONEATTRIBUTES za = {sizeof(ZONEATTRIBUTES)};
WORD iIcon=0;
HICON hIcon = NULL;
m_pizm->GetZoneAt(dwZoneEnum, nIndex, &dwZone);
// get the zone attributes for this zone
m_pizm->GetZoneAttributes(dwZone, &za);
// Zone icons are in two formats.
// wininet.dll#1200 where 1200 is the res id.
// or foo.ico directly pointing to an icon file.
// search for the '#'
LPWSTR pwsz = StrChrW(za.szIconPath, TEXTW('#'));
if (pwsz)
{
TCHAR szIconPath[MAX_PATH];
// if we found it, then we have the foo.dll#00001200 format
pwsz[0] = TEXTW('\0');
SHUnicodeToTChar(za.szIconPath, szIconPath, ARRAYSIZE(szIconPath));
iIcon = (WORD)StrToIntW(pwsz+1);
ExtractIconEx(szIconPath,(INT)(-1*iIcon), NULL, &hIcon, 1 );
}
else
hIcon = (HICON)ExtractAssociatedIconExW(HINST_THISDLL, za.szIconPath, (LPWORD)&iIcon, &iIcon);
if (nIndex < MAX_NUM_ZONES_ICONS)
m_arhiconZones[nIndex] = hIcon;
}
m_pizm->DestroyZoneEnumerator(dwZoneEnum);
}
}
}
HRESULT CStatusBar::Resize(LONG x, LONG y)
{
return _SetParts();
}
//////////////////////////////////////////////////////////////////
// General Functions
//////////////////////////////////////////////////////////////////
HRESULT CStatusBar::_InitStatusBar(void)
{
HRESULT hr = S_OK;
// Only reformat the StatusBar if we haven't yet, or
// if someone formatted it away from us. (@!%*#)
if ((!m_fInited) ||
(STATUS_PANES != SendMessage(m_hwndStatus, SB_GETPARTS, 0, 0L)))
{
m_fInited = TRUE;
hr = _SetParts();
}
return hr;
}
HRESULT CStatusBar::_SetParts(void)
{
HRESULT hr = S_OK;
RECT rc;
ASSERTNONCRITICAL;
#ifdef OLD_STYLE_STATUSBAR
SendMessage(hwnd, SB_SETTEXT, 1 | SBT_NOBORDERS, 0);
#else // OLD_STYLE_STATUSBAR
GetClientRect(m_hwndStatus, &rc);
const UINT cxZone = ZoneComputePaneSize(m_hwndStatus);
const UINT cxUserName = PANE_WIDTH_USERNAME;
INT nStatusBarWidth = rc.right - rc.left;
INT arnRtEdge[STATUS_PANES] = {1};
INT nIconPaneWidth = GetSystemMetrics(SM_CXSMICON) + (GetSystemMetrics(SM_CXEDGE) * 4);
INT nWidthReqd = cxZone + cxUserName + (nIconPaneWidth * 1);
arnRtEdge[STATUS_PANE_STATUS] = max(1, nStatusBarWidth - nWidthReqd);
nWidthReqd -= cxUserName;
arnRtEdge[STATUS_PANE_USERNAME] = max(1, nStatusBarWidth - nWidthReqd);
/*
nWidthReqd -= (nIconPaneWidth);
arnRtEdge[STATUS_PANE_WRITEICON] = max(1, nStatusBarWidth - nWidthReqd);
*/
arnRtEdge[STATUS_PANE_ZONE] = -1;
LRESULT nParts = 0;
nParts = SendMessage(m_hwndStatus, SB_GETPARTS, 0, 0L);
if (nParts != STATUS_PANES)
{
for ( int n = 0; n < nParts; n++)
{
SendMessage(m_hwndStatus, SB_SETTEXT, n, NULL);
SendMessage(m_hwndStatus, SB_SETICON, n, NULL);
}
SendMessage(m_hwndStatus, SB_SETPARTS, 0, 0L);
}
SendMessage(m_hwndStatus, SB_SETPARTS, STATUS_PANES, (LPARAM)arnRtEdge);
SendMessage(m_hwndStatus, SB_GETRECT, 1, (LPARAM)&rc);
InflateRect(&rc, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
SendMessage(m_hwndStatus, SB_SETTEXT, 1, (LPARAM)SZ_EMPTY);
SendMessage(m_hwndStatus, SB_SETMINHEIGHT, GetSystemMetrics(SM_CYSMICON) + GetSystemMetrics(SM_CYBORDER) * 2, 0L);
_SetZone();
_SetUserParts();
#endif // OLD_STYLE_STATUSBAR
return hr;
}
/****************************************************\
Constructor
\****************************************************/
CStatusBar::CStatusBar(HWND hwndStatus)
{
DllAddRef();
// This needs to be allocated in Zero Inited Memory.
// Assert that all Member Variables are inited to Zero.
ASSERT(!m_pism);
ASSERT(!m_pizm);
ASSERT(!m_pszUserName);
ASSERT(!m_pszUserNameTT);
m_hwndStatus = hwndStatus;
m_lCurrentZone = ZONE_UNKNOWN;
LEAK_ADDREF(LEAK_CStatusBar);
}
/****************************************************\
Destructor
\****************************************************/
CStatusBar::~CStatusBar(void)
{
int nIndex;
IUnknown_Set((IUnknown **) &m_pism, NULL);
IUnknown_Set((IUnknown **) &m_pizm, NULL);
Str_SetPtr(&m_pszUserName, NULL);
Str_SetPtr(&m_pszUserNameTT, NULL);
for (nIndex = 0; nIndex < MAX_NUM_ZONES_ICONS; nIndex++)
{
if (m_arhiconZones[nIndex])
DestroyIcon(m_arhiconZones[nIndex]);
}
for (nIndex = 0; nIndex < ITD_MAX; nIndex++)
{
if (m_arhiconGeneral[nIndex])
DestroyIcon(m_arhiconGeneral[nIndex]);
}
ASSERTNONCRITICAL;
SendMessage(m_hwndStatus, SB_SETTEXT, 1 | SBT_NOBORDERS, 0);
DllRelease();
LEAK_DELREF(LEAK_CStatusBar);
}