windows-nt/Source/XPSP1/NT/com/mobile/syncmgr/exe/progtab.cpp
2020-09-26 16:20:57 +08:00

586 lines
15 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997.
//
// File: Progtab.cpp
//
// Contents: Progress tab
//
// Classes:
//
// Notes: Handle the custom results pane.
//
// History: 05-Nov-97 Susia Created.
//
//--------------------------------------------------------------------------
#include "precomp.h"
extern HINSTANCE g_hInst; // current instance
extern BOOL CALLBACK ProgressWndProc(HWND hwnd, UINT uMsg,WPARAM wParam,LPARAM lParam);
BOOL CALLBACK ResultsProgressWndProc(HWND hwnd, UINT uMsg,WPARAM wParam,LPARAM lParam);
//--------------------------------------------------------------------------------
//
// FUNCTION: ListBox_HitTest(HWND hwnd, LONG xPos, LONG yPos)
//
// PURPOSE: HitTest for a ListBox, since Windows was nice enough to not provide one
// This is really a function to see if the hittest falls in the range
// of the More Info Jump text.
//
// COMMENTS: Implemented on main thread.
//
//--------------------------------------------------------------------------------
INT ListBox_HitTest(HWND hwnd, LONG xPos, LONG yPos)
{
int begin = ListBox_GetTopIndex(hwnd);
int end = ListBox_GetCount(hwnd);
int i;
RECT rcRect;
for (i=begin;i<end;i++)
{
LBDATA *pData = NULL;
if (ListBox_GetItemRect(hwnd, i, &rcRect))
{
pData = (LBDATA *) ListBox_GetItemData(hwnd,i);
if (pData == NULL)
{
// if no data then try the next one
continue;
}
// if textRect not calculated then this isn't visible.
if (pData->fTextRectValid)
{
// only use left and right vars for hit test. top and bottom
// can change.
// compare y values first since they are the ones
// most likely to be different.
if ( (yPos >= rcRect.top) &&
(yPos <= rcRect.bottom) &&
(xPos >= pData->rcTextHitTestRect.left) &&
(xPos <= pData->rcTextHitTestRect.right) )
{
return i;
}
}
}
}
return -1;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: OnProgressResultsDrawItem(HWND hwnd, UINT idCtl, LPDRAWITEMSTRUCT lpdis)
//
// PURPOSE: Handle DrawItem events for Progress Dialog Results Tab
//
// COMMENTS: Implemented on main thread.
//
//--------------------------------------------------------------------------------
BOOL OnProgressResultsDrawItem(HWND hwnd,CProgressDlg *pProgress,UINT idCtl, const DRAWITEMSTRUCT* lpDrawItem)
{
HDC hdc = lpDrawItem->hDC;
COLORREF clrText, clrBack;
RECT rcText, rcFocus;
LOGFONT lf;
HGDIOBJ hFont, hFontOld;
HFONT hFontJumpText = NULL;
int nSavedDC;
LBDATA *pData = (LBDATA *) lpDrawItem->itemData;
if (!hdc || !pData)
{
return FALSE;
}
nSavedDC = SaveDC(hdc);
Assert(lpDrawItem->CtlType == ODT_LISTBOX);
if (lpDrawItem->itemID == -1)
goto exit;
clrBack = SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
// Clear the item for drawing
// + 1 is just the way you do it for some reason
FillRect(hdc, &(lpDrawItem->rcItem),
(HBRUSH) (COLOR_WINDOW + 1) );
if (pData->IconIndex != -1)
{
ImageList_Draw(pProgress->m_errorimage,
pData->IconIndex,
hdc,
BULLET_INDENT,
lpDrawItem->rcItem.top + BULLET_INDENT,
ILD_TRANSPARENT);
}
// Set up the font, text and background colors
hFont = (HFONT) SendMessage(hwnd, WM_GETFONT, 0, 0);
if (hFont)
{
Assert(NULL == hFontJumpText);
if (pData->fIsJump && GetObject(hFont,sizeof(LOGFONT),&lf))
{
lf.lfUnderline = TRUE;
hFontJumpText = CreateFontIndirect(&lf);
if (hFontJumpText)
{
hFontOld = SelectObject(hdc,hFontJumpText);
}
}
if (!hFontJumpText)
{
hFontOld = SelectObject(hdc,hFont);
}
}
// set up colors
if (pData->fIsJump)
{
// even if don't get font change the attribs;
if (pData->fHasBeenClicked)
{
clrText = SetTextColor(hdc, RGB(128,0,128));
}
else
{
clrText = SetTextColor(hdc, RGB(0,0,255));
}
}
else
{
clrText = SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
}
// calc what the drawText should be. Need to take our stored
// text value and adjust the top.
{
RECT rpDataRect = pData->rcText;
rcText = lpDrawItem->rcItem;
rcText.top = lpDrawItem->rcItem.top + BULLET_INDENT;
rcText.left += rpDataRect.left;
rcText.right = rcText.left + WIDTH(rpDataRect);
}
/* rcText = lpDrawItem->rcItem;
rcText.left += (pProgress->m_iIconMetricX*3)/2 + BULLET_INDENT; // move over Icon distance
rcText.top += BULLET_INDENT;
*/
// draw the text using the TextBox we calc'd in Measure Item
DrawText(hdc,pData->pszText, -1,
&rcText,
DT_NOCLIP | DT_WORDBREAK );
// If we need a focus rect, do that too
if (lpDrawItem->itemState & ODS_FOCUS)
{
rcFocus = lpDrawItem->rcItem;
// rcFocus.left += (pProgress->m_iIconMetricX*3)/2;
rcFocus.top += BULLET_INDENT;
rcFocus.left += BULLET_INDENT;
DrawFocusRect(hdc, &rcFocus);
}
// SetBkColor(hdc, clrBack);
// SetTextColor(hdc, clrText);
if (nSavedDC)
{
RestoreDC(hdc,nSavedDC);
}
if (hFontJumpText)
{
DeleteObject(hFontJumpText);
}
exit:
return TRUE;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: OnProgressResultsMeasureItem(HWND hwnd, CProgressDlg *pProgress, UINT *horizExtent UINT idCtl, MEASUREITEMSTRUCT *pMeasureItem)
//
// PURPOSE: Handle MeasureItem events for Progress Dialog Results Tab
//
// COMMENTS: Implemented on main thread.
//
//--------------------------------------------------------------------------------
BOOL OnProgressResultsMeasureItem(HWND hwnd,CProgressDlg *pProgress, UINT *horizExtent, UINT /* idCtl */, MEASUREITEMSTRUCT *pMeasureItem)
{
LBDATA *pData = NULL;
HWND hwndList = GetDlgItem(hwnd,IDC_LISTBOXERROR);
if (!hwndList)
{
return FALSE;
}
pData = (LBDATA *) ListBox_GetItemData(hwndList, pMeasureItem->itemID);
if (pData == NULL)
{
Assert(pProgress != NULL);
Assert(pProgress->m_CurrentListEntry != NULL);
pData = pProgress->m_CurrentListEntry;
}
if (pData == NULL)
{
return FALSE;
}
HFONT hfont = NULL;
HFONT hFontJumpText = NULL;
HDC hdc;
int iHeight;
int nSavedDC;
hdc = GetDC(hwndList);
if (NULL == hdc)
{
return FALSE;
}
nSavedDC = SaveDC(hdc);
// Get the size of the string
hfont = (HFONT) SendMessage(hwnd, WM_GETFONT, 0, 0);
// if can't get font or jump text font just use the
// current font.
if (hfont)
{
// if this is jump text then change some
// font attributes.
if (pData->fIsJump)
{
LOGFONT lf;
if (GetObject(hfont,sizeof(LOGFONT),&lf))
{
lf.lfUnderline = TRUE;
hFontJumpText = CreateFontIndirect(&lf);
}
}
if (hFontJumpText)
{
SelectFont(hdc, hFontJumpText);
}
else
{
SelectFont(hdc, hfont);
}
}
int cxResultsWidth;
RECT rcRect;
// GetClientRect seems to subtract off the Scroll Bars for us.
GetClientRect(hwndList, &rcRect);
cxResultsWidth = rcRect.right;
SetRect(&rcRect, 0, 0, cxResultsWidth, 0);
// subtract off the length of Icon + 1/2
rcRect.right -= ((pProgress->m_iIconMetricX*3)/2
+ BULLET_INDENT );
int tempwidth = rcRect.right;
iHeight = DrawText(hdc, pData->pszText, -1, &rcRect,
DT_NOCLIP | DT_CALCRECT | DT_WORDBREAK) + BULLET_INDENT;
//We have a smegging word in the string wider than the rect.
if (rcRect.right > tempwidth)
{
*horizExtent = cxResultsWidth + (rcRect.right - tempwidth);
// fix up the proper width
rcRect.right = cxResultsWidth + (rcRect.right - tempwidth);
}
else
{
rcRect.right = cxResultsWidth;
}
rcRect.left += ((pProgress->m_iIconMetricX*3)/2
+ BULLET_INDENT );
// bottom is either the height of the line or if it has
// an icon the max of these two.
if (-1 != pData->IconIndex)
{
rcRect.bottom = max(iHeight,pProgress->m_iIconMetricY + BULLET_INDENT*2);
}
else
{
rcRect.bottom = iHeight;
}
// if need to add space on the end then do that
if (pData->fAddLineSpacingAtEnd)
{
SIZE Size;
if (!GetTextExtentPoint(hdc,SZ_SYNCMGRNAME,
lstrlen(SZ_SYNCMGRNAME),&Size))
{
// if can't get size make up a number
Size.cy = 13;
}
// lets do 2/3 a line spacing.
rcRect.bottom += (Size.cy*2)/3;
}
// store the TextRect in the pData field.
pMeasureItem->itemHeight = rcRect.bottom;
pMeasureItem->itemWidth = cxResultsWidth;
pData->rcText = rcRect;
pData->fTextRectValid = TRUE;
pData->rcTextHitTestRect = rcRect;
if (pData->fIsJump)
{
SIZE size;
// on jump text want the hit test only over the actual text
// in the horizontal location.
if(GetTextExtentPoint(hdc,pData->pszText,lstrlen(pData->pszText), &size))
{
pData->rcTextHitTestRect.right = size.cx + pData->rcTextHitTestRect.left;
}
}
if (nSavedDC)
{
RestoreDC(hdc,nSavedDC);
}
if (hFontJumpText)
{
DeleteObject(hFontJumpText);
}
ReleaseDC(hwndList, hdc);
return TRUE;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: OnProgressResultsDeleteItem(HWND hwnd, UINT idCtl, const DELETEITEMSTRUCT * lpDeleteItem)
//
// PURPOSE: Handle DeleteItem events for Progress Dialog Results Tab
//
// COMMENTS: Implemented on main thread.
//
//--------------------------------------------------------------------------------
BOOL OnProgressResultsDeleteItem(HWND hwnd,UINT idCtl, const DELETEITEMSTRUCT * lpDeleteItem)
{
// Assert(lpDeleteItem->itemData);
if (lpDeleteItem->itemData)
{
FREE((LPVOID) lpDeleteItem->itemData);
}
return TRUE;
}
void OnProgressResultsSize(HWND hwnd,CProgressDlg *pProgress,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
HWND hwndList = GetDlgItem(hwnd,IDC_LISTBOXERROR);
int iItems = ListBox_GetCount(hwndList);
int iCurItem;
MEASUREITEMSTRUCT measureItem;
RECT rect;
UINT horizExtent = 0;
SendMessage(hwndList,WM_SETREDRAW,FALSE /*fRedraw */,0);
GetClientRect(hwndList,&rect);
for (iCurItem = 0 ; iCurItem < iItems; ++iCurItem)
{
measureItem.itemID = iCurItem;
if (OnProgressResultsMeasureItem(hwnd,pProgress,&horizExtent, -1,&measureItem))
{
ListBox_SetItemHeight(hwndList, iCurItem, measureItem.itemHeight);
}
}
//make sure there is a horizontal scroll bar if needed.
SendMessage(hwndList, LB_SETHORIZONTALEXTENT, horizExtent, 0L);
SendMessage(hwndList,WM_SETREDRAW,TRUE /*fRedraw */,0);
InvalidateRect(hwndList,&rect,FALSE);
}
//--------------------------------------------------------------------------------
//
// FUNCTION: ResultsListBoxWndProc(HWND hwnd, UINT uMsg,WPARAM wParam,LPARAM lParam)
//
// PURPOSE: Callback for Progress Dialog Update Tab
//
// COMMENTS: Implemented on main thread.
//
//--------------------------------------------------------------------------------
BOOL CALLBACK ResultsListBoxWndProc(HWND hwnd, UINT uMsg,WPARAM wParam,LPARAM lParam)
{
CProgressDlg *pProgressDlg = (CProgressDlg *) GetWindowLongPtr(GetParent(hwnd), DWLP_USER);
// OUR PARENT HAS A POINTER TO THE progress in dwl_user.
switch (uMsg)
{
case WM_POWERBROADCAST:
{
DWORD dwRet = TRUE;
if (wParam == PBT_APMQUERYSUSPEND)
{
// if just created or syncing don't suspend
if (pProgressDlg)
{
if ( (pProgressDlg->m_dwProgressFlags & PROGRESSFLAG_NEWDIALOG)
|| (pProgressDlg->m_dwProgressFlags & PROGRESSFLAG_SYNCINGITEMS))
{
dwRet = BROADCAST_QUERY_DENY;
}
}
return dwRet;
}
}
break;
case WM_SETCURSOR:
return TRUE; // rely on mousemove to set the cursor.
break;
case WM_MOUSEMOVE:
{
int index = ListBox_HitTest(hwnd, (LONG) LOWORD(lParam),(LONG) HIWORD(lParam));
LBDATA *lbData =(LBDATA *) ListBox_GetItemData(hwnd, index);
if (lbData)
{
if ((index != -1) && (lbData->fIsJump))
{
SetCursor(LoadCursor(g_hInst,MAKEINTRESOURCE(IDC_HARROW)));
}
else
{
SetCursor(LoadCursor(NULL,IDC_ARROW));
}
}
}
break;
case WM_KEYDOWN:
case WM_LBUTTONDBLCLK:
case WM_LBUTTONDOWN:
{
int index = -1;
LBDATA *lbData = NULL;
// get index either through hittest of selection based on
// if keydown or not.
if (uMsg == WM_KEYDOWN)
{
if (VK_SPACE == ((int) wParam) )
{
index = ListBox_GetCurSel(hwnd);
}
else
{
break; // don't mess with any other keys
}
}
else
{
index = ListBox_HitTest(hwnd, (LONG) LOWORD(lParam),(LONG) HIWORD(lParam));
}
if (-1 != index)
{
lbData =(LBDATA *) ListBox_GetItemData(hwnd, index);
}
if ((lbData) && (lbData->fIsJump))
{
if (pProgressDlg)
{
if (NOERROR == pProgressDlg->OnShowError(lbData->pHandlerID,
hwnd,
lbData->ErrorID))
{
lbData->fHasBeenClicked = TRUE;
RedrawWindow(hwnd, NULL,NULL, RDW_INVALIDATE | RDW_UPDATENOW);
}
return 0;
}
}
break;
}
default:
break;
}
if (pProgressDlg && pProgressDlg->m_fnResultsListBox)
{
return (BOOL)CallWindowProc(pProgressDlg->m_fnResultsListBox, hwnd, uMsg, wParam, lParam);
}
return TRUE;
}