//+------------------------------------------------------------------------- // // 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;ifTextRectValid) { // 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; }