//--------------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation 1993-1994 // // File: dobj.c // // This file contains support routines for the reconciliation-action // control class code // // // History: // 09-13-93 ScottH Extracted from recact.c // //--------------------------------------------------------------------------- ///////////////////////////////////////////////////// INCLUDES #include "pch.h" #include "extra.h" #include "resource.h" #include "recact.h" #include "dobj.h" ///////////////////////////////////////////////////// CONTROLLING DEFINES ///////////////////////////////////////////////////// DEFINES #define DT_CALCWRAP (DT_CALCRECT | DT_CENTER | DT_WORDBREAK | DT_NOPREFIX) #define DT_CALC (DT_CALCRECT | DT_CENTER | DT_SINGLELINE | DT_NOPREFIX) /*---------------------------------------------------------- Purpose: Formats the given path to the correct location format Returns: -- Cond: -- */ void PRIVATE FormatLocationPath( LPCSTR pszPath, LPSTR pszBuffer) // Must be MAX_PATH { UINT ids; // tHACK char szBrfDir[MAX_PATH]; LPCSTR psz; LPSTR pszMsg; // The format for the directory location is: // // Inside briefcase: "In Briefcase" // Below briefcase: "In Briefcase\FolderName" // Outside briefcase: "In FullPath" // // We assume that paths outside the current briefcase // never consist of a briefcase name of another. // #if 0 // tHACK if (PathGetLocality(pszPath, szBrfDir) != PL_FALSE) { // Inside the briefcase psz = &pszPath[lstrlen(szBrfDir)]; ids = IDS_InBriefcase; } else #endif { // Outside the briefcase psz = pszPath; ids = IDS_InLocation; } if (ConstructMessage(&pszMsg, vhinstCur, MAKEINTRESOURCE(ids), psz)) { lstrcpy(pszBuffer, pszMsg); GFree(pszMsg); } else *pszBuffer = 0; } /*---------------------------------------------------------- Purpose: Return the string describing the status of this sideitem Returns: ptr to status string Cond: -- */ LPSTR PRIVATE SideItem_GetStatus( LPSIDEITEM this, LPSTR pszBuf, UINT cchBuf) { switch (this->uState) { case SI_CHANGED: return SzFromIDS(IDS_STATE_Changed, pszBuf, cchBuf); case SI_UNCHANGED: return SzFromIDS(IDS_STATE_Unchanged, pszBuf, cchBuf); case SI_NEW: return SzFromIDS(IDS_STATE_NewFile, pszBuf, cchBuf); case SI_UNAVAILABLE: return SzFromIDS(IDS_STATE_Unavailable, pszBuf, cchBuf); default: return NULL; } } /*---------------------------------------------------------- Purpose: Displays the 3-liner: location, status, and timestamp Returns: -- Cond: -- */ void PRIVATE SideItem_Display( LPSIDEITEM this, HDC hdc, LPRECT prc, int cxEllipses, int cyText) { char sz[MAX_PATH]; char szBuf[MAXBUFLEN]; LPSTR psz; RECT rc = *prc; // Directory location. FormatLocationPath(this->pszDir, sz); // strcpy(sz, "a long path tHACKed"); MyDrawText(hdc, sz, &rc, MDT_LEFT | MDT_TRANSPARENT | MDT_ELLIPSES, cyText, cxEllipses, CLR_DEFAULT, CLR_DEFAULT); // Status string psz = SideItem_GetStatus(this, szBuf, sizeof(szBuf)); if (psz) { // Only bother with these two lines if the file actually // exists. rc.top += cyText; MyDrawText(hdc, psz, &rc, MDT_LEFT | MDT_TRANSPARENT, cyText, cxEllipses, CLR_DEFAULT, CLR_DEFAULT); // Date stamp. Skip this if this is a folder or unavailable. // if (this->fs.fscond != FS_COND_UNAVAILABLE) { FileTimeToDateTimeString(&this->fs.ftMod, sz, sizeof(sz)); rc.top += cyText; MyDrawText(hdc, sz, &rc, MDT_LEFT | MDT_TRANSPARENT, cyText, cxEllipses, CLR_DEFAULT, CLR_DEFAULT); } } } /*---------------------------------------------------------- Purpose: Return the bounding rect for a labelled image. Returns: -- Cond: -- */ void PUBLIC ComputeImageRects( LPCSTR psz, HDC hdc, LPPOINT pptInOut, LPRECT prcWhole, // May be NULL LPRECT prcLabel, // May be NULL int cxIcon, int cyIcon, int cxIconSpacing, int cyText) { RECT rc; int yLabel; int cxLabel; int cyLabel; int cchLabel; POINT pt; ASSERT(psz); // Set our minimum rect size for icon spacing if (cxIconSpacing < cxIcon) cxIconSpacing = cxIcon + g_cxIconMargin * 2; // Upon entry, *pptInOut is expected to be the upper left corner of the // icon-spacing rect. This function will set it to the upper left // corner of the icon itself. pt.x = pptInOut->x + (cxIconSpacing - cxIcon) / 2; pt.y = pptInOut->y + g_cyIconMargin; // Determine rectangle of label with wrap rc.left = rc.top = rc.bottom = 0; rc.right = cxIconSpacing - g_cxLabelMargin * 2; cchLabel = lstrlen(psz); if (0 < cchLabel) { DrawText(hdc, psz, cchLabel, &rc, DT_CALCWRAP); } else { rc.bottom = rc.top + cyText; } yLabel = pptInOut->y + g_cyIconMargin + cyIcon + g_cyLabelSpace; cxLabel = (rc.right - rc.left) + 2 * g_cxLabelMargin; cyLabel = rc.bottom - rc.top; if (prcWhole) { prcWhole->left = pptInOut->x; prcWhole->right = prcWhole->left + cxIconSpacing; prcWhole->top = pptInOut->y; prcWhole->bottom = max(prcWhole->top + g_cyIconSpacing, yLabel + cyLabel + g_cyLabelSpace); } if (prcLabel) { prcLabel->left = pptInOut->x + ((cxIconSpacing - cxLabel) / 2); prcLabel->right = prcLabel->left + cxLabel; prcLabel->top = yLabel; prcLabel->bottom = prcLabel->top + cyLabel; } *pptInOut = pt; } /*---------------------------------------------------------- Purpose: Set the colors for the given HDC. The previous colors are stored in pcrText and pcrBk. Returns: uStyle to pass to ImageList_Draw (specific to images only) Cond: -- */ UINT PRIVATE Dobj_SetColors( LPDOBJ this, HDC hdc, UINT uState, COLORREF clrBkgnd) { COLORREF clrText; COLORREF clrBk; UINT uStyleILD = ILD_NORMAL; BOOL bSetColors = FALSE; BOOL bDiffer; BOOL bMenu; BOOL bDisabled; // Determine selection colors // bDiffer = IsFlagSet(this->uFlags, DOF_DIFFER); bMenu = IsFlagSet(this->uFlags, DOF_MENU); bDisabled = IsFlagSet(this->uFlags, DOF_DISABLED); switch (this->uKind) { case DOK_STRING: case DOK_IDS: case DOK_SIDEITEM: bSetColors = TRUE; break; } // Set the text and background colors // if (bSetColors) { if (bDiffer) { // Make the colors differ based on selection state // if (bMenu) { if (bDisabled) clrText = GetSysColor(COLOR_GRAYTEXT); else clrText = GetSysColor(ColorMenuText(uState)); clrBk = GetSysColor(ColorMenuBk(uState)); } else { if (bDisabled) clrText = GetSysColor(COLOR_GRAYTEXT); else clrText = GetSysColor(ColorText(uState)); clrBk = GetSysColor(ColorBk(uState)); } } else { // Transparent colors // if (bMenu) { if (bDisabled) clrText = GetSysColor(COLOR_GRAYTEXT); else clrText = GetSysColor(COLOR_MENUTEXT); clrBk = GetSysColor(COLOR_MENU); } else { if (bDisabled) clrText = GetSysColor(COLOR_GRAYTEXT); else clrText = GetSysColor(COLOR_WINDOWTEXT); clrBk = clrBkgnd; } } SetTextColor(hdc, clrText); SetBkColor(hdc, clrBk); } return uStyleILD; } /*---------------------------------------------------------- Purpose: Draw the menu image and text Returns: -- Cond: -- */ void PRIVATE Dobj_DrawMenuImage( LPDOBJ this, HDC hdc, UINT uState, int cyText, COLORREF clrBkgnd) { UINT uStyleILD; UINT uFlagsETO; LPCSTR psz; char szIDS[MAXBUFLEN]; int cch; HIMAGELIST himl = this->himl; COLORREF clrText; COLORREF clrBk; int x; int y; int cxIcon; RECT rc; if (IsFlagSet(this->uFlags, DOF_USEIDS)) psz = SzFromIDS((UINT)this->lpvObject, szIDS, sizeof(szIDS)); else psz = (LPCSTR)this->lpvObject; ASSERT(psz); cch = lstrlen(psz); ImageList_GetImageRect(himl, this->iImage, &rc); cxIcon = rc.right-rc.left; // Draw the text first uFlagsETO = ETO_OPAQUE | ETO_CLIPPED; x = this->rcLabel.left + g_cxMargin + cxIcon + g_cxMargin; y = this->rcLabel.top + ((this->rcLabel.bottom - this->rcLabel.top - cyText) / 2); if (IsFlagSet(this->uFlags, DOF_DISABLED) && IsFlagClear(uState, ODS_SELECTED)) { int imodeOld; COLORREF crOld; // For disabled menu strings (not selected), we draw the string // twice. The first is offset down and to the right and drawn // in the 3D hilight color. The second time is the disabled text // color in the normal offset. // crOld = SetTextColor(hdc, GetSysColor(COLOR_3DHILIGHT)); imodeOld = SetBkMode(hdc, TRANSPARENT); ExtTextOut(hdc, x+1, y+1, uFlagsETO, &this->rcLabel, psz, cch, NULL); // Reset back to original color. Also, turn off the opaqueness. // SetTextColor(hdc, crOld); uFlagsETO ^= ETO_OPAQUE; } if (IsFlagSet(this->uFlags, DOF_DISABLED)) clrText = GetSysColor(COLOR_GRAYTEXT); else clrText = GetSysColor(ColorMenuText(uState)); clrBk = GetSysColor(ColorMenuBk(uState)); SetTextColor(hdc, clrText); SetBkColor(hdc, clrBk); ExtTextOut(hdc, x, y, uFlagsETO, &this->rcLabel, psz, cch, NULL); // Draw the image if (GetBkColor(hdc) == ImageList_GetBkColor(himl)) uStyleILD = ILD_NORMAL; // Paint quicker else uStyleILD = ILD_TRANSPARENT; ImageList_Draw(himl, this->iImage, hdc, this->x, this->y, uStyleILD); } /*---------------------------------------------------------- Purpose: Draw the icon image and label Returns: -- Cond: -- */ void PRIVATE Dobj_DrawIconImage( LPDOBJ this, HDC hdc, UINT uState, int cxEllipses, int cyText, COLORREF clrBkgnd) { UINT uStyleILD; UINT uFlagsMDT; LPCSTR psz; char szIDS[MAXBUFLEN]; if (IsFlagSet(this->uFlags, DOF_USEIDS)) psz = SzFromIDS((UINT)this->lpvObject, szIDS, sizeof(szIDS)); else psz = (LPCSTR)this->lpvObject; ASSERT(psz); // Draw the image // if (IsFlagClear(this->uFlags, DOF_IGNORESEL)) { uStyleILD = GetImageDrawStyle(uState); uFlagsMDT = IsFlagSet(uState, ODS_SELECTED) ? MDT_SELECTED : MDT_DESELECTED; } else { uStyleILD = ILD_NORMAL; uFlagsMDT = MDT_DESELECTED; ClearFlag(uState, ODS_FOCUS); } ImageList_Draw(this->himl, this->iImage, hdc, this->x, this->y, uStyleILD); // Draw the file label. Wrap if it is long. if (this->rcLabel.bottom - this->rcLabel.top > cyText) uFlagsMDT |= MDT_DRAWTEXT; MyDrawText(hdc, psz, &this->rcLabel, MDT_CENTER | uFlagsMDT, cyText, cxEllipses, CLR_DEFAULT, clrBkgnd); // (uState may have been changed above) if (IsFlagSet(uState, ODS_FOCUS)) DrawFocusRect(hdc, &this->rcLabel); } #ifdef UNUSED /*---------------------------------------------------------- Purpose: Draw a picture Returns: -- Cond: -- */ void PRIVATE Dobj_DrawPicture( LPDOBJ this, HDC hdc, UINT uState, UINT uDrawStyle) { HIMAGELIST himl; HDC hdcMem; HBITMAP hbmp; BITMAP bm; RECT rc; int iImage; int cx; int x; int y; switch (this->uKind) { case DOK_BITMAP: hbmp = (HBITMAP)(DWORD)this->lpvObject; GetObject(hbmp, sizeof(BITMAP), &bm); cx = this->rcSrc.right - this->rcSrc.left; break; case DOK_ICON: cx = 32; break; } // We only align horizontally // y = this->y; if (IsFlagSet(this->uFlags, DOF_CENTER)) x = this->x - (cx / 2); else if (IsFlagSet(this->uFlags, DOF_RIGHT)) x = this->x - cx; else x = this->x; // Draw the object // switch (this->uKind) { case DOK_ICON: // BUGBUG: we don't handle DOF_DIFFER for icons DrawIcon(hdc, x, y, (HICON)(DWORD)this->lpvObject); break; case DOK_BITMAP: hdcMem = CreateCompatibleDC(hdc); if (hdcMem) { SIZE size; SelectBitmap(hdcMem, hbmp); size.cx = this->rcSrc.right - this->rcSrc.left; size.cy = this->rcSrc.bottom - this->rcSrc.top; if (IsFlagSet(this->uFlags, DOF_MENU) && IsFlagSet(this->uFlags, DOF_DISABLED) && IsFlagClear(uState, ODS_SELECTED)) { COLORREF crOld; // For disabled menu strings (not selected), we draw the bitmap // twice. The first is offset down and to the right and drawn // in the 3D hilight color. The second time is the disabled // color in the normal offset. // crOld = SetTextColor(hdc, GetSysColor(COLOR_3DHILIGHT)); BitBlt(hdc, x+1, y+1, size.cx, size.cy, hdcMem, this->rcSrc.left, this->rcSrc.top, SRCCOPY); // Reset back to original color. Also, turn off the opaqueness. // SetTextColor(hdc, crOld); } BitBlt(hdc, x, y, size.cx, size.cy, hdcMem, this->rcSrc.left, this->rcSrc.top, SRCCOPY); DeleteDC(hdcMem); } break; } } #endif /*---------------------------------------------------------- Purpose: Draw a string Returns: -- Cond: -- */ void PRIVATE Dobj_DrawString( LPDOBJ this, HDC hdc, UINT uState, int cxEllipses, int cyText) { UINT ufAlignSav; ASSERT(this); // Prep the alignment // if (this->uFlags & (DOF_LEFT | DOF_CENTER | DOF_RIGHT)) { UINT ufMode; ufMode = IsFlagSet(this->uFlags, DOF_CENTER) ? TA_CENTER : (IsFlagSet(this->uFlags, DOF_RIGHT) ? TA_RIGHT : TA_LEFT); ufAlignSav = SetTextAlign(hdc, ufMode); } // Draw the string // switch (this->uKind) { case DOK_IDS: case DOK_STRING: { char szBuf[MAXBUFLEN]; LPSTR lpsz; UINT uflag = ETO_OPAQUE; if (this->uKind == DOK_IDS) lpsz = SzFromIDS((UINT)(DWORD)this->lpvObject, szBuf, sizeof(szBuf)); else lpsz = (LPSTR)this->lpvObject; if (!IsRectEmpty(&this->rcClip)) uflag |= ETO_CLIPPED; if (IsFlagSet(this->uFlags, DOF_MENU) && IsFlagSet(this->uFlags, DOF_DISABLED) && IsFlagClear(uState, ODS_SELECTED)) { int imodeOld; COLORREF crOld; // For disabled menu strings (not selected), we draw the string // twice. The first is offset down and to the right and drawn // in the 3D hilight color. The second time is the disabled text // color in the normal offset. // crOld = SetTextColor(hdc, GetSysColor(COLOR_3DHILIGHT)); imodeOld = SetBkMode(hdc, TRANSPARENT); ExtTextOut(hdc, this->x+1, this->y+1, uflag, &this->rcClip, lpsz, lstrlen(lpsz), NULL); // Reset back to original color. Also, turn off the opaqueness. // SetTextColor(hdc, crOld); uflag ^= ETO_OPAQUE; } ExtTextOut(hdc, this->x, this->y, uflag, &this->rcClip, lpsz, lstrlen(lpsz), NULL); } break; case DOK_SIDEITEM: SideItem_Display((LPSIDEITEM)this->lpvObject, hdc, &this->rcClip, cxEllipses, cyText); break; } // Clean up // if (this->uFlags & (DOF_LEFT | DOF_CENTER | DOF_RIGHT)) { SetTextAlign(hdc, ufAlignSav); } } /*---------------------------------------------------------- Purpose: Draw an object Returns: -- Cond: -- */ void PUBLIC Dobj_Draw( HDC hdc, LPDOBJ rgdobj, int cItems, UINT uState, // ODS_* int cxEllipses, int cyText, COLORREF clrBkgnd) { UINT uDrawStyle; LPDOBJ pdobj; int i; ASSERT(rgdobj); for (i = 0, pdobj = rgdobj; i < cItems; i++, pdobj++) { if (IsFlagSet(pdobj->uFlags, DOF_NODRAW)) continue ; uDrawStyle = Dobj_SetColors(pdobj, hdc, uState, clrBkgnd); // Draw the object // switch (pdobj->uKind) { case DOK_IMAGE: if (IsFlagSet(pdobj->uFlags, DOF_MENU)) Dobj_DrawMenuImage(pdobj, hdc, uState, cyText, clrBkgnd); else Dobj_DrawIconImage(pdobj, hdc, uState, cxEllipses, cyText, clrBkgnd); break; #ifdef UNUSED case DOK_BITMAP: case DOK_ICON: Dobj_DrawPicture(pdobj, hdc, uState, uDrawStyle); break; #endif case DOK_IDS: case DOK_STRING: case DOK_SIDEITEM: Dobj_DrawString(pdobj, hdc, uState, cxEllipses, cyText); break; } } }