⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 freebusydisplayitem.cpp

📁 一个WinCE6。0下的IP phone的源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    WCHAR *wszTitle, 
    UINT cchTitle
    )
{
    PREFAST_ASSERT(wszTitle);
    
    //only draw if we have FB information
    if (! m_wstrFreeBusy[0] )
    {
        wszTitle[0] = 0;
        return S_FALSE;
    }
    
    HRESULT    hr          = S_OK;
    SYSTEMTIME stNow       = {0}, 
               stEnd       = {0};

    const WCHAR *c_wszDefault    = NULL,
                *c_wszFmt        = NULL,
                *c_wszStatus     = NULL,
                *c_wszNextStatus = NULL;
    
    UINT         idxNow       = 0;
    
    INT          idxChange    = 0;

    WORD         wHourChange, wMinuteChange;
    DWORD        rgdwFormatMessage[3] = {0};

    GetLocalTime(&stNow);
    IncrementTime(&stEnd, &m_stStart, c_nTotalWindowHours);

    //if the current time if before the start of the work day, or after the end
    //of the work day. The string is the default "today's FB status string" 

    //uses overloaded operator> and operator<
    if (stNow < m_stStart || stNow > stEnd)
    {
        goto use_default;
    }

    //otherwise we have a valid time within the "visible" fb status range

    //We need to determine the current value, by finding the index in the string
    //that reprensents the current time. 

    idxNow = \
        (HourDifference(&stNow, &m_stStart) * INTERVALS_PER_HOUR) + //this brings us to the current hour
        (stNow.wMinute / c_FreeBusyIntervalAmount);                 //add the appropriate minute intervals

    
    if (idxNow > m_wstrFreeBusy.length()-1)
    {
        goto use_default;
    }

    //OK - we are currently have a status (e.g. "free") - we need to find when that status changes
    //If can either be a time, or off the end of the fb string
    //We need this to determine XXXX in the string "Free until XXXX" 
    idxChange = idxNow;
    while (
           m_wstrFreeBusy[idxChange] == m_wstrFreeBusy[idxNow] && 
           idxChange < m_wstrFreeBusy.length()-1
           )
    {
        idxChange++;
    }
    if (m_wstrFreeBusy[idxChange] == m_wstrFreeBusy[idxNow])
    {
        idxChange = -1;
    }

    //Determine the format of the string to use
    c_wszStatus = GetStatusString(CharToFBStatus(m_wstrFreeBusy[idxNow]));
    c_wszFmt    = CommonUtilities_t::LoadString(GlobalData_t::s_ModuleInstance,
        (idxChange == -1) ? IDS_FMT_FREEBUSY_FORTHERESTOFTHEDAY :
                            IDS_FMT_FREEBUSY_UNTIL
                                );
    if (c_wszStatus == NULL || c_wszFmt == NULL)
    {
        goto use_default;
    }

    //if this status lasts doesn't go to the end of the day, we need to figure out the 
    //human-readable time in which it changes (e.g. 3:30)
    if (idxChange != -1)
    {
        wHourChange   = ((m_stStart.wHour + (idxChange / INTERVALS_PER_HOUR)) % 24);
        if (! wHourChange ) wHourChange = 12; //if the hour was "24" or 12AM
        
        wMinuteChange = (idxChange % INTERVALS_PER_HOUR) * c_FreeBusyIntervalAmount;
    }

    //format the args for the call to FormatMessage
    rgdwFormatMessage[0] = (DWORD)c_wszStatus;
    rgdwFormatMessage[1] = (DWORD)((wHourChange > 12) ? wHourChange%12 : wHourChange);
    rgdwFormatMessage[2] = (DWORD)wMinuteChange;

    return CommonUtilities_t::ToHR(FormatMessage(
        FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_FROM_STRING,
        c_wszFmt,
        0,
        0,
        wszTitle,
        cchTitle,
        (va_list*)rgdwFormatMessage
        ) != 0);
    
use_default:

    //if something went wrong, load and use the default string
    c_wszDefault = CommonUtilities_t::LoadString(GlobalData_t::s_ModuleInstance, IDS_FMT_FREEBUSY_DEFAULT);
    if (! c_wszDefault)
    {
        ASSERT(FALSE);
        return E_UNEXPECTED;
    }
    
    StringCchCopy(
        wszTitle, 
        cchTitle,
        c_wszDefault
        );
    return S_OK;
}

/*------------------------------------------------------------------------------
    CFreeBusyDisplayItem::DrawFreeBusyTitle
    
    Draw the free busy title (e.g. "Free until 3:15")
------------------------------------------------------------------------------*/
HRESULT CFreeBusyDisplayItem::DrawFreeBusyTitle(
    HDC hdc, 
    const RECT * prc
    )
{
    PREFAST_ASSERT(prc);

    PaintHelper_t   paint;

    HRESULT hr = paint.Attach(hdc);
    if (FAILED(hr))
    {
        ASSERT(FALSE);
        return hr;
    }
    
    RECT     rcDraw       = {0};
    WCHAR    wszBuf[255]  = L"";

    hr = GetFreeBusyTitle(
        wszBuf, 
        _countof(wszBuf)
        );
    if (FAILED(hr))
    {
        ASSERT(FALSE);
        return hr;
    }
    
    //Draw the status
    rcDraw = *prc;
    rcDraw.left += Layout_t::FreeBusyMarginWidth();
    rcDraw.top  += Layout_t::FreeBusyStatusYOffset();

    paint.SetFont(PHGetFont(phfInformationText));

    hr = paint.DrawText(
        wszBuf, 
        -1,
        &rcDraw,
        DT_TOP | DT_LEFT | DT_SINGLELINE | DT_NOPREFIX
        );

    //restore the dc
    paint.End();
    return hr;
}

/*------------------------------------------------------------------------------
    CFreeBusyDisplayItem::DrawFreeBusyGraphics
    
    Draw the freebusy graphics (e.g. blueblock, whiteblock, ...)
------------------------------------------------------------------------------*/
HRESULT CFreeBusyDisplayItem::DrawFreeBusyGraphics(
    HDC hdc, 
    const RECT * prc
    )
{
    PREFAST_ASSERT(prc);
    if (! m_wstrFreeBusy[0])
    {
        return S_FALSE;
    }
    
    HRESULT hr     = S_OK;
    RECT    rcDraw = *prc;

    ce::auto_hpen hpnBorder;
    HPEN          hpnOld;

    HBRUSH        hbrBackground = NULL, 
                  hbrOld        = NULL;

    HFONT         hfntNumbers   = NULL,
                  hfntOld       = NULL;

    INT TotalWidth = prc->right - prc->left;
    const UINT c_cxGraphicsWidthMax = (TotalWidth - 2*Layout_t::FreeBusyMarginWidth() - 2), // 1 px border on each side of the rect
               c_cxPixelPerInterval = (c_cxGraphicsWidthMax / DISPLAY_INTERVALS),
               c_cxPixelPerHour     = (c_cxPixelPerInterval * INTERVALS_PER_HOUR),
               c_cxGraphicsWidth    = (c_cxPixelPerInterval * DISPLAY_INTERVALS) + 2; //add 2 - to account for the 1 px border on each side
                   
    //Format the rectangle for drawing
    rcDraw.left   += Layout_t::FreeBusyMarginWidth();
    rcDraw.right   = rcDraw.left + c_cxGraphicsWidth;
    rcDraw.top    += Layout_t::FreeBusyGraphicsYOffset();
    rcDraw.bottom  = rcDraw.top  + Layout_t::FreeBusyGraphicsHeight();

    hpnBorder = ::CreatePen(PS_SOLID, -1, Colors_t::FreeBusy_GraphicsOutline());

    if (hpnBorder == NULL)
    {
        hr = CommonUtilities_t::GetErrorFromWin32();
    }

    //First draw the border rectangle
    if (SUCCEEDED(hr))
    {
        hpnOld = (HPEN)  SelectObject(hdc, hpnBorder);
        hbrOld = (HBRUSH)SelectObject(hdc, GetStockObject(HOLLOW_BRUSH));
        
        hr = CommonUtilities_t::ToHR(Rectangle(
            hdc, 
            rcDraw.left,
            rcDraw.top,
            rcDraw.right,
            rcDraw.bottom
            ));

        SelectObject(hdc, hpnOld);
        SelectObject(hdc, hbrOld);
    }    

    //Next draw inside the border rectangle
    if (SUCCEEDED(hr))
    {
        //Don't draw over the border rectangle
        rcDraw.left++;
        rcDraw.top++;
        rcDraw.right--;
        rcDraw.bottom--;

        //Draw in "runs" (e.g. draw the current status + all the statuses adjacent that
        //have the same status) - example: 0000000111111111000 will draw 3 times - a block of
        //0's a block of 1's and then another block of 0's
        UINT idxCurrentValue = 0,
             idxMax          = INTERVALS_PER_HOUR*c_nTotalWindowHours;

        while (idxCurrentValue < idxMax)
        {
            UINT idxChange = idxCurrentValue+1;
            ce::auto_hbrush hbrDraw;

            //Determine when the run ends
            while (
                m_wstrFreeBusy[idxChange] == m_wstrFreeBusy[idxCurrentValue] && 
                idxChange < idxMax
                )
            {
                idxChange++;
            }

            //Fill the rect with the necessary brush
            rcDraw.right = rcDraw.left + (c_cxPixelPerInterval * (idxChange - idxCurrentValue));

            hr = DrawRun(
                hdc,
                &rcDraw,
                m_wstrFreeBusy[idxCurrentValue]
                );

            if (FAILED(hr))
            {
                break;
            }
            
            rcDraw.left = rcDraw.right;
            idxCurrentValue = idxChange;
        }
    }

    //Now draw the "now" line, in the appropriate place
    if (SUCCEEDED(hr))
    {
        SYSTEMTIME stNow = {0},
                   stEnd = {0};
        
        GetLocalTime (&stNow);
        IncrementTime(&stEnd, &m_stStart, c_nTotalWindowHours);
        //validate that "now" is within our drawing window
        if (stNow > m_stStart && stNow < stEnd)
        {
            ce::auto_hpen hpnDraw = ::CreatePen(PS_SOLID, -1, Colors_t::FreeBusy_NowLine());
            hpnOld = (HPEN)SelectObject(hdc, hpnDraw);

            //Determine the x value of the drawing line (top and bottom or rcDraw are still accurate)
            INT xDraw = 
                prc->left                                               + 
                Layout_t::FreeBusyMarginWidth()                         + 
                1                                                       + 
                (HourDifference(&stNow, &m_stStart) * c_cxPixelPerHour) + //pixels in an hour
                ((stNow.wMinute * c_cxPixelPerHour) / (MINUTES_IN_HOUR))  //percentage of px in an hour
                ;
            
            POINT rgptDraw[] =
            {
                xDraw, rcDraw.top,
                xDraw, rcDraw.bottom
            };

            //Draw the line
            hr = CommonUtilities_t::ToHR(Polyline(
                hdc,
                rgptDraw,
                _countof(rgptDraw)
                ));

            //restore the dc
            SelectObject(hdc, hpnOld);
        }
    }
    
    //Now draw the time, under the rectangle
    if (SUCCEEDED(hr))
    {
        hfntNumbers = PHGetFont(phfStandardText);
        hr = CommonUtilities_t::ToHR(hfntNumbers != NULL);
    }

    if (SUCCEEDED(hr))
    {
        //Set up the rectangle for the numbers drawing
        rcDraw.top    = prc->top + Layout_t::FreeBusyClockYOffset();
        rcDraw.bottom = prc->bottom;
        rcDraw.left   = prc->left + Layout_t::FreeBusyMarginWidth() - 1;

        hfntOld = (HFONT)SelectObject(hdc, hfntNumbers);

        //Draw each number in our range
        for (UINT i = 0; i <= c_nTotalWindowHours; i++)
        {
            rcDraw.right = rcDraw.left + c_cxPixelPerHour;

            WCHAR wszHour[4] = L"";
            INT   hour = i + m_stStart.wHour;

            while (hour > 12)
            {
                hour -= 12;
            }
            
            _snwprintf(wszHour, _countof(wszHour), L"%d", hour % 13);
            wszHour[_countof(wszHour) - 1] = L'\0'; 

            hr = CommonUtilities_t::ToHR(::DrawText(
                hdc,
                wszHour, 
                -1,
                &rcDraw,
                DT_TOP | DT_LEFT | DT_SINGLELINE | DT_NOPREFIX
                ));

            if (FAILED(hr))
            {
                ASSERT(FALSE);
                break;
            }
            rcDraw.left = rcDraw.right;
        }

        //restore the dc
        SelectObject(hdc, hfntOld);
    }
    
    return hr;
}

/*------------------------------------------------------------------------------
    CFreeBusyDisplayItem::GetSubItemText
    
    Helper function for automation - get each components text
------------------------------------------------------------------------------*/
HRESULT CFreeBusyDisplayItem::GetSubItemText(
    int idxSubItem, 
    WCHAR * wszBuffer, 
    UINT cchBuffer
    )
{
    HRESULT hr  = S_OK;
    UINT    idx = 0;
    
    switch (idxSubItem)
    {
    case c_siDisplayName:
        StringCchCopy(
            wszBuffer, 
            cchBuffer,
            m_wstrDisplayName
            );            

        break;
        
#ifdef AUTOMATION
    case c_siFreeBusyData:
        StringCchCopy(
            wszBuffer, 
            cchBuffer,
            m_wstrFreeBusy
            );            
        break;
        
    case c_siFreeBusyStatus:
        GetFreeBusyTitle(
            wszBuffer, 
            cchBuffer
            );
        break;
        
    case c_siBoundaries:
        {
            SYSTEMTIME stNow = {0}, stEnd = {0};
            GetLocalTime(&stNow);
            IncrementTime(&stEnd, &m_stStart, c_nTotalWindowHours);
            _snwprintf(
                wszBuffer, 
                cchBuffer, 
                L"Start: %d$Now: %d:%d$End:%d", 
                ((m_stStart.wHour > 12) ? m_stStart.wHour - 12 : m_stStart.wHour) % 13,
                stNow.wHour, stNow.wMinute, 
                ((stEnd.wHour > 12) ? stEnd.wHour - 12 : stEnd.wHour) % 13
                );
        }
        break;
#endif        
    default:
        hr = S_FALSE;
        break;
    }

    wszBuffer[ cchBuffer - 1 ] = 0;
    return hr;
}

/*------------------------------------------------------------------------------
    CFreeBusyDisplayItem::GetText
    
    Gets the DiplayName text of the item
------------------------------------------------------------------------------*/
HRESULT CFreeBusyDisplayItem::GetText(
    WCHAR * wszBuffer, 
    INT cchBuffer
    )
{
    return GetSubItemText(c_siDisplayName, wszBuffer, cchBuffer);
}

/*------------------------------------------------------------------------------
    CFreeBusyDisplayItem::NeedsToolTip
    
    Determine if this item needs tool tip. 
------------------------------------------------------------------------------*/
BOOL CFreeBusyDisplayItem::NeedsToolTip(
    RECT *prc
    )
{
    if (! prc)
    {
        return FALSE;
    }
    
    return !CanDrawOnOneLine(
        phfStandardTextBold,
        m_wstrDisplayName, 
        m_wstrDisplayName.length(),
        prc->right - prc->left
        ); 
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -