📄 calldisplayitem.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 <windows.h>
#define INITGUID
#include <initguid.h>
#include "DisplayItem.hpp"
#undef INITGUID
#include "CallDisplayItem.h"
#include "Common.hpp"
#include "UIManager.hpp"
#include "NewResource.hpp"
#include "auto_xxx.hxx"
#include "Debug.hpp"
#include "CallBase.hpp"
#include <winuserm.h>
#include "LayoutColor.hpp"
#include "VoIPApp.hpp"
/*------------------------------------------------------------------------------
FormatRectForLabeledControl
helper function to format the rect for call control
------------------------------------------------------------------------------*/
HRESULT
FormatRectForLabeledControl(
RECT *prcOriginal,
RECT *prcAdjust,
UINT idLabel,
short AfterLabelMargin,
short RightMargin,
short TopMargin,
short BottomMargin
)
{
HDC hdc = CreateCompatibleDC(NULL);
if (hdc == NULL)
{
return E_FAIL;
}
HRESULT hr = CommonUtilities_t::ToHR(::DrawText(
hdc,
CommonUtilities_t::LoadString(GlobalData_t::s_ModuleInstance, idLabel),
-1,
prcAdjust,
DT_LEFT | DT_WORDBREAK | DT_CALCRECT | DT_NOPREFIX
));
if (FAILED(hr))
{
goto exit;
}
prcAdjust->left = prcAdjust->right + AfterLabelMargin;
prcAdjust->right = prcOriginal->right - RightMargin;
prcAdjust->top = prcOriginal->top + TopMargin;
prcAdjust->bottom = prcOriginal->bottom - BottomMargin;
exit:
DeleteDC(hdc);
return hr;
}
/*------------------------------------------------------------------------------
FormatDurationString
Helper function used to format the duration of a call
Parameters:
: pstDuration - the systemtime struct containing the duration
: wszBuf - the buffer to copy the string into
: cchBuf - the size of wszBuf in wide-characters
Returns (HRESULT): indicating success or failure
------------------------------------------------------------------------------*/
HRESULT
FormatDurationString(
const SYSTEMTIME * pstDuration,
WCHAR * wszBuf,
INT cchBuf
)
{
HRESULT hr = S_OK;
hr = CommonUtilities_t::ToHR(GetTimeFormat(
LOCALE_USER_DEFAULT,
TIME_FORCE24HOURFORMAT,
pstDuration,
CommonUtilities_t::LoadString(GlobalData_t::s_ModuleInstance, IDS_TIME_FMT_DURATION), // GetTimeFormat will fail if this call fails
wszBuf,
cchBuf
));
return hr;
}
//Internal constants
//If the item is not dialing or transferring, the state defers to the
//state of the currentcall inside the item, this #define represents
//that deferring state
#define e_csDeferToCallStatus (CallDisplayItemState)-3
// Speed of the animation, in milliseconds / frame
const INT c_cmsAnimateSpeed = 500;
//Subitem text indicies
//Mapping between a callstatus and the glyphs to be used for animating
//the call in the corresponding state
struct CallAnimationEntry
{
RTC_SESSION_STATE CallStatus; // Call status
INT idxGlyphOffset; // Offset from the top of the glyph BMP, in "glyph units"
INT cGlyphFrames; // Number of frames in the glyph animation
};
const UINT c_idxGlyphInvalid = 0; const UINT c_cFramesInvalid = 1;
const UINT c_idxGlyphConnected = 1; const UINT c_cFramesConnected = 1;
const UINT c_idxGlyphInConference = 2; const UINT c_cFramesInConference = 1;
const UINT c_idxGlyphInProgress = 3; const UINT c_cFramesInProgress = 4;
const UINT c_idxGlyphHolding = 4; const UINT c_cFramesHolding = 2;
const UINT c_idxGlyphDisconnected = 5; const UINT c_cFramesDisconnected = 1;
const UINT c_idxGlyphSentToConference = 6; const UINT c_cFramesSentToConference = 1;
const UINT c_idxGlyphReferring = 7; const UINT c_cFramesReferring = 1;
const UINT c_idxGlyphIncoming = 8; const UINT c_cFramesIncoming = 1;
const UINT c_idxGlyphAnswerring = 8; const UINT c_cFramesAnswerring = 1;
//Table for the entire mapping
CallAnimationEntry sc_AnimationEntryLookup[] =
{
{ RTCSS_IDLE, c_idxGlyphInvalid, c_cFramesInvalid },
{ RTCSS_INCOMING, c_idxGlyphIncoming, c_cFramesIncoming },
{ RTCSS_INPROGRESS, c_idxGlyphInProgress, c_cFramesInProgress },
{ RTCSS_ANSWERING, c_idxGlyphAnswerring, c_cFramesAnswerring },
{ RTCSS_REFER, c_idxGlyphReferring, c_cFramesReferring },
{ RTCSS_CONNECTED, c_idxGlyphConnected, c_cFramesConnected },
{ RTCSS_DISCONNECTED, c_idxGlyphDisconnected, c_cFramesDisconnected },
{ RTCSS_HOLD, c_idxGlyphHolding, c_cFramesHolding },
};
/*------------------------------------------------------------------------------
FindAnimationStatusEntry
Finds a animation entry by callstatus by iterating over the
lookup table.
Parameters:
CallStatus: Call status whose entry is requested.
Returns (CallAnimationEntry): A pointer to the animation entry,
or NULL if the call status was not found.
------------------------------------------------------------------------------*/
inline const CallAnimationEntry* FindAnimationStatusEntry(RTC_SESSION_STATE status)
{
for (INT i = 0; i < ARRAYSIZE(sc_AnimationEntryLookup); i++)
{
if (sc_AnimationEntryLookup[i].CallStatus == status)
{
return &sc_AnimationEntryLookup[i];
}
}
return NULL;
}
/*------------------------------------------------------------------------------
CallDisplayItem_t::CallDisplayItem_t
Constructor for a channel item.
Parameters:
pCall: Current call to associate with this item.
------------------------------------------------------------------------------*/
CallDisplayItem_t::CallDisplayItem_t(
Call_t *pCall /* = NULL */
)
{
TRACE(ZONE_PHONEAPP_FUNCTION);
m_State = (pCall == NULL) ? e_csDialing : e_csDeferToCallStatus;
m_cpCall = pCall;
m_tk = 0;
m_RemovingEditControl = false;
}
CallDisplayItem_t::~CallDisplayItem_t()
{
;
}
HRESULT
CallDisplayItem_t::QueryInterface(
REFIID riid,
void** ppvObject
)
{
if (!ppvObject)
{
return E_INVALIDARG;
}
HRESULT hr = S_OK;
if (riid == IID_IVoIPDisplayControl)
{
*ppvObject = (IVoIPDisplayControl*)this;
}
else
{
*ppvObject = NULL;
hr = E_NOTIMPL;
}
return hr;
}
BOOL
CallDisplayItem_t::GetHeight(
UINT* pHeight
)
{
PREFAST_ASSERT(pHeight);
*pHeight = Layout_t::CallItemHeight();
return TRUE;
}
HRESULT
CallDisplayItem_t::ShowControls(
BOOL IsVisible
)
{
if (!(HWND)m_EditControl || m_RemovingEditControl)
{
return S_FALSE;
}
if (!IsVisible || m_State == e_csDeferToCallStatus)
{
ShowWindow(m_EditControl, SW_HIDE);
}
else
{
ShowWindow(m_EditControl, SW_SHOW);
}
return S_OK;
}
/*------------------------------------------------------------------------------
CallDisplayItem_t::Position
Positions the commcontrols on the display item
Parameters:
hwndLV: HWND of the parent for the controls
pRECT: RECT of the display item
fVisible: TRUE if this control is on-screen
Returns (HRESULT):
------------------------------------------------------------------------------*/
HRESULT
CallDisplayItem_t::PositionControls(
HWND VirtualListBox,
RECT* pRECT
)
{
if (pRECT == NULL)
{
return E_INVALIDARG;
}
//if we are not visible or just NOT showing the control, hide the control
if (m_State == e_csDeferToCallStatus)
{
if ((HWND)m_EditControl)
{
ShowWindow(
m_EditControl,
SW_HIDE
);
}
return S_OK;
}
//Otherwise we need to show/create the control
//Move/Size the rectangle where we are placing the control
//based on our state
RECT rcControl = *pRECT;
if (m_State == e_csDialing)
{
FormatRectForLabeledControl(
pRECT,
&rcControl,
IDS_LABEL_DIAL,
Layout_t::DialingStateAfterLabelMargin(),
Layout_t::DialingStateRightMargin(),
Layout_t::DialingStateTopMargin(),
Layout_t::DialingStateBottomMargin()
);
}
if (m_State == e_csTransferring)
{
FormatRectForLabeledControl(
pRECT,
&rcControl,
IDS_LABEL_DIAL,
Layout_t::TransferringStateAfterLabelMargin(),
Layout_t::TransferringStateRightMargin(),
Layout_t::TransferringStateTopMargin(),
Layout_t::TransferringStateBottomMargin()
);
}
HRESULT hr = S_OK;
//Create the control if necessary
if (!(HWND)m_EditControl)
{
hr = m_EditControl.Create(
WNDCLASS_EDIT,
NULL,
WS_VISIBLE | WS_CHILD | ES_AUTOHSCROLL | WS_BORDER,
0,
VirtualListBox,
rcControl.left,
rcControl.top,
rcControl.right - rcControl.left,
rcControl.bottom - rcControl.top
);
if (FAILED(hr))
{
ASSERT(FALSE);
return hr;
}
m_EditControl.SetCallbackPointer((INT_PTR)this);
m_rcControl = rcControl;
///TODO: need to hook up with the input button
SendMessage(
m_EditControl,
EM_SETINPUTMODE,
0,
(LPARAM)EIM_NUMBERS
);
WCHAR AlreadyDialedString[MAX_PATH] = L"";
GetApp()->GetUIManager().GetAlreadyDialedString(
AlreadyDialedString,
ARRAYSIZE(AlreadyDialedString)
);
if (AlreadyDialedString[0] != L'\0')
{
SendMessage(
m_EditControl,
WM_SETTEXT,
0,
reinterpret_cast<LPARAM>(AlreadyDialedString)
);
GetApp()->GetUIManager().UpdateMenuBar();
}
return S_OK;
}
//only move the control, if the window pos has changed since last time we placed
//the control
if (memcmp(&m_rcControl, &rcControl, sizeof(RECT)) != 0)
{
m_rcControl = rcControl;
hr = MoveWindow(
m_EditControl,
rcControl.left,
rcControl.top,
rcControl.right - rcControl.left,
rcControl.bottom - rcControl.top,
TRUE
);
}
return S_OK;
}
/*------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -