📄 freebusydisplayitem.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
#include "FreeBusyDisplayItem.h"
#include "auto_xxx.hxx"
#include "Resource.h"
#include "InfoApp.hpp"
#include "Common.hpp"
#include "PaintHelper.hpp"
#include "SystemTimeUtils.h"
#include "Layout.hpp"
//Settings used by the exchange client
const UINT c_FreeBusyIntervalAmount = 15; //interval of time for each fb character
//settings for the drawn time (the window that we care about)
const UINT c_nTotalWindowHours = 9;
//Helper constants (also need to be moved to registry)
///TODO: Move to registry
#define MINUTES_IN_HOUR 60
#define INTERVALS_PER_HOUR (MINUTES_IN_HOUR / c_FreeBusyIntervalAmount) //4 //60 / 15 = 4
#define DISPLAY_INTERVALS (INTERVALS_PER_HOUR * c_nTotalWindowHours) //9*4 = 36
enum FreeBusyStatus
{
StatusFree = L'0',
StatusTentative = L'1',
StatusBusy = L'2',
StatusOOF = L'3',
StatusUnknown
};
inline FreeBusyStatus CharToFBStatus(
WCHAR Char
)
{
if (Char >= StatusFree && Char <= StatusOOF)
{
return static_cast<FreeBusyStatus>(Char);
}
return StatusUnknown;
}
/*------------------------------------------------------------------------------
GetStatusString
Helper function to get the resource string
for the specified status char (from outlook)
0 - free
1 - tentative
2 - busy
3 - oof
4+ - unknown
------------------------------------------------------------------------------*/
const WCHAR* GetStatusString(
FreeBusyStatus status
)
{
UINT idStatus = 0;
switch (status)
{
case StatusFree:
idStatus = IDS_STATUS_FREEBUSY_FREE;
break;
case StatusTentative:
idStatus = IDS_STATUS_FREEBUSY_TENTATIVE;
break;
case StatusBusy:
idStatus = IDS_STATUS_FREEBUSY_BUSY;
break;
case StatusOOF:
idStatus = IDS_STATUS_FREEBUSY_OOF;
break;
case StatusUnknown:
default:
idStatus = IDS_STATUS_FREEBUSY_UNKNOWN;
break;
}
return CommonUtilities_t::LoadString(GlobalData_t::s_ModuleInstance, idStatus);
}
/*------------------------------------------------------------------------------
DrawTentative
Drawing helper function. Draws the tentative bitmap into
the rectangle.
Because we don't want to strecth the bitmap, we will
repeatedly blt the bitmap to cover the rect
------------------------------------------------------------------------------*/
HRESULT DrawTentative(
HDC hdc,
RECT *prc
)
{
PREFAST_ASSERT(prc);
HRESULT hr = S_OK;
RECT rcDraw = *prc;
HBITMAP hbmpTentative = GlobalData_t::s_GDICacheObject.LoadCachedBitmap(IDB_TENTATIVE);
ce::auto_hdc hdcTentative; //the dc to blt from
hr = CommonUtilities_t::ToHR(hbmpTentative != NULL);
if (FAILED(hr))
{
ASSERT(FALSE);
return hr;
}
//Load the cached bitmap into the bltfrom DC
hdcTentative = CreateCompatibleDC(hdc);
hr = CommonUtilities_t::ToHR(hdcTentative != NULL);
if (FAILED(hr))
{
ASSERT(FALSE);
return hr;
}
//Select the bitmap into the bltting dc
HBITMAP hbmpOld = (HBITMAP)SelectObject(hdcTentative, hbmpTentative);
rcDraw.right = min(rcDraw.left + Layout_t::TentativeBmpWidth(), prc->right);
while (1)
{
//blt this portion of the bitmap
hr = CommonUtilities_t::ToHR(BitBlt(
hdc,
rcDraw.left,
rcDraw.top,
rcDraw.right - rcDraw.left,
rcDraw.bottom - rcDraw.top,
hdcTentative,
0,
0,
SRCCOPY
));
ASSERT(SUCCEEDED(hr));
if (rcDraw.right == prc->right)
{
break;
}
rcDraw.left = rcDraw.right;
rcDraw.right = min(rcDraw.left + Layout_t::TentativeBmpWidth(), prc->right);
}
//restore the bltting dc
SelectObject(hdcTentative, hbmpOld);
return hr;
}
/*------------------------------------------------------------------------------
DrawRun
Helper function to draw a run of free busy data.
------------------------------------------------------------------------------*/
HRESULT DrawRun(
HDC hdc,
RECT *prc,
const WCHAR wcStatus
)
{
FreeBusyStatus Status = CharToFBStatus(wcStatus);
//tentative is special
if (Status == StatusTentative)
{
return DrawTentative(hdc, prc);
}
//all other draws use a solid color brush
HRESULT hr = S_OK;
COLORREF crSolidBrush = 0;
ce::auto_hbrush hbrDraw;
switch (wcStatus)
{
case L'0':
crSolidBrush = Colors_t::FreeBusy_Free();
break;
case L'2':
crSolidBrush = Colors_t::FreeBusy_Busy();
break;
case L'3':
crSolidBrush = Colors_t::FreeBusy_OOF();
break;
default:
crSolidBrush = Colors_t::FreeBusy_Unknown();
break;
}
hbrDraw = CreateSolidBrush(crSolidBrush);
hr = CommonUtilities_t::ToHR(hbrDraw != NULL);
if (FAILED(hr))
{
ASSERT(FALSE);
return hr;
}
return CommonUtilities_t::ToHR(FillRect(
hdc,
prc,
hbrDraw
) != 0);
}
inline BOOL CanDrawOnOneLine(
PH_FONT Font,
__in const WCHAR* pText,
UINT cchText,
UINT LineWidth
)
{
RECT CalculateRect = {0};
PaintHelper_t::CalculateTextDimensions(
pText,
-1,
PHGetFont(Font),
&CalculateRect,
DT_TOP | DT_LEFT | DT_NOPREFIX
);
return (LineWidth >= RECTWIDTH(CalculateRect));
}
/*------------------------------------------------------------------------------
CFreeBusyDisplayItem::CFreeBusyDisplayItem
Ctor
------------------------------------------------------------------------------*/
CFreeBusyDisplayItem::CFreeBusyDisplayItem()
{
ZeroMemory(&m_stStart, sizeof(SYSTEMTIME));
}
CFreeBusyDisplayItem::~CFreeBusyDisplayItem()
{
}
/*------------------------------------------------------------------------------
CFreeBusyDisplayItem::GetHeight
Gets the height of the item
Parameters:
pfHeight: OUT - The height to fill in
Returns (BOOL): TRUE if we set the height
------------------------------------------------------------------------------*/
BOOL CFreeBusyDisplayItem::GetHeight(
UINT *pfHeight
)
{
PREFAST_ASSERT(pfHeight);
*pfHeight = Layout_t::FreeBusyItemHeight();
return TRUE;
}
/*------------------------------------------------------------------------------
CFreeBusyDisplayItem::SetDisplayName
Sets the name to display
------------------------------------------------------------------------------*/
HRESULT CFreeBusyDisplayItem::SetDisplayName(
const WCHAR * c_wszDisplayName
)
{
if (c_wszDisplayName == NULL)
{
ASSERT(FALSE);
return E_POINTER;
}
if (! m_wstrDisplayName.assign(c_wszDisplayName))
{
return E_OUTOFMEMORY;
}
return S_OK;
}
/*------------------------------------------------------------------------------
CFreeBusyDisplayItem::SetFreeBusyStatus
Sets the free busy status string
------------------------------------------------------------------------------*/
HRESULT CFreeBusyDisplayItem::SetFreeBusyStatus(
const WCHAR * c_wszFreeBusyStatus,
SYSTEMTIME * pstStart
)
{
PREFAST_ASSERT(pstStart && c_wszFreeBusyStatus);
#ifdef DEBUG
//verify this is a good systemtime
FILETIME ft = {0};
ASSERT(SystemTimeToFileTime(pstStart, &ft));
#endif
memcpy(&m_stStart, pstStart, sizeof(SYSTEMTIME));
if (! m_wstrFreeBusy.assign(c_wszFreeBusyStatus))
{
return E_OUTOFMEMORY;
}
return S_OK;
}
/*------------------------------------------------------------------------------
CFreeBusyDisplayItem::Draw
Draws the free busy item
Parameters:
hdc: The DC to draw into
prc: The rectangle to draw into
fSelected: TRUE iff we are the selected item in the ListBox
Returns (HRESULT): indicating success or failure
------------------------------------------------------------------------------*/
HRESULT CFreeBusyDisplayItem::Draw(
HDC hdc,
const RECT * prc,
BOOL fSelected,
BOOL fTopItem
)
{
PREFAST_ASSERT(prc);
PaintHelper_t paint;
HBRUSH hbrBackground;
HRESULT hr;
//Set up the DC for drawing text
hr = paint.Attach(hdc);
if (FAILED(hr))
{
ASSERT(FALSE);
return hr;
}
paint.SetTextColor(Colors_t::FreeBusy_TextColor());
paint.SetBkMode(TRANSPARENT);
//The item always has the same background
hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
ASSERT(hbrBackground != NULL);
if (fSelected)
{
hr = DrawBand(
hdc,
prc,
fSelected,
fTopItem
);
}
else
{
hr = CommonUtilities_t::ToHR(FillRect(
hdc,
prc,
hbrBackground
));
}
ASSERT(SUCCEEDED(hr));
//Draw the different components of the item
hr = DrawName(hdc, prc);
ASSERT(SUCCEEDED(hr));
hr = DrawMain(hdc, prc);
ASSERT(SUCCEEDED(hr));
//restore the dc
paint.End();
return S_OK;
}
HRESULT CFreeBusyDisplayItem::DrawMain(
HDC hdc,
const RECT *prc
)
{
HRESULT hr = DrawFreeBusyTitle(hdc, prc);
ASSERT(SUCCEEDED(hr));
hr = DrawFreeBusyGraphics(hdc, prc);
ASSERT(SUCCEEDED(hr));
return S_OK;
}
/*------------------------------------------------------------------------------
CFreeBusyDisplayItem::DrawName
Draw the name into the display items rect
------------------------------------------------------------------------------*/
HRESULT CFreeBusyDisplayItem::DrawName(
HDC hdc,
const RECT *prc
)
{
PREFAST_ASSERT(prc);
HRESULT hr = S_OK;
RECT rcDraw = *prc,
rcCalc = {0};
if (! m_wstrDisplayName[0])
{
return S_FALSE;
}
PaintHelper_t paint;
hr = paint.Attach(hdc);
if (FAILED(hr))
{
ASSERT(FALSE);
return hr;
}
//Move/resize the rectangle for drawing
rcDraw.top += Layout_t::FreeBusyMarginHeight();
rcDraw.left += Layout_t::FreeBusyMarginWidth();
//Create the font to use
paint.SetFont(PHGetFont(phfLargeText));
//Make sure that the name fits in the rectangle
//if the width is greater than what we have, choose a smaller font
if (! CanDrawOnOneLine(
phfLargeText,
m_wstrDisplayName,
m_wstrDisplayName.length(),
rcDraw.right - rcDraw.left
))
{
paint.SetFont(PHGetFont(phfStandardTextBold));
}
//Draw the name (with ellipsis if necessary)
hr = paint.DrawText(
m_wstrDisplayName,
-1,
&rcDraw,
DT_TOP | DT_LEFT | DT_SINGLELINE | DT_NOPREFIX | DT_END_ELLIPSIS
);
ASSERT(SUCCEEDED(hr));
//restore the dc
paint.End();
return hr;
}
/*------------------------------------------------------------------------------
CFreeBusyDisplayItem::GetFreeBusyTitle
Helper function that gets the freebusy title based on current time
(e.g. "Busy until 5:00")
------------------------------------------------------------------------------*/
HRESULT CFreeBusyDisplayItem::GetFreeBusyTitle(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -