📄 uimanager.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 "UIManager.hpp"
#include "Common.hpp"
#include "NewResource.hpp"
#include "CallBase.hpp"
#include "VoIPApp.hpp"
#include "Debug.hpp"
#include "CommonFunctions.hpp"
#include "RTCErr.h"
#include "voipstore.h"
#include "CallDisplayItem.h"
#include "DatabaseAPI.hpp"
#include "SettingsAPI.hpp"
/*------------------------------------------------------------------------------
GetStringIdForRTCError
helper function to get string id for RTC error
------------------------------------------------------------------------------*/
UINT
GetStringIdForRTCError(
LONG ErrorCode
)
{
unsigned int Code = HRESULT_CODE(ErrorCode);
if (Code >= MAX_RTCAPIERR)
{
return IDS_ERROR_UNKNOWN;
}
return (IDS_ERROR_RTCAPI_E_BASE + Code);
}
/*------------------------------------------------------------------------------
GetStringIdForSIPPINTError
helper function to get string id for SIPPINError
------------------------------------------------------------------------------*/
UINT
GetStringIdForSIPPINTError(
LONG ErrorCode
)
{
switch (ErrorCode)
{
case RTC_E_STATUS_REDIRECT_MULTIPLE_CHOICES:
return IDS_RTCERR_STATUS_REDIRECT_MULTIPLE_CHOICES;
case RTC_E_STATUS_REDIRECT_MOVED_PERMANENTLY:
return IDS_RTCERR_STATUS_REDIRECT_MOVED_PERMANENTLY;
case RTC_E_STATUS_REDIRECT_MOVED_TEMPORARILY:
return IDS_RTCERR_STATUS_REDIRECT_MOVED_TEMPORARILY;
case RTC_E_STATUS_REDIRECT_SEE_OTHER:
return IDS_RTCERR_STATUS_REDIRECT_SEE_OTHER;
case RTC_E_STATUS_REDIRECT_USE_PROXY:
return IDS_RTCERR_STATUS_REDIRECT_USE_PROXY;
case RTC_E_STATUS_REDIRECT_ALTERNATIVE_SERVICE:
return IDS_RTCERR_STATUS_REDIRECT_ALTERNATIVE_SERVICE;
case RTC_E_STATUS_CLIENT_BAD_REQUEST:
return IDS_RTCERR_STATUS_CLIENT_BAD_REQUEST;
case RTC_E_STATUS_CLIENT_UNAUTHORIZED:
return IDS_RTCERR_STATUS_CLIENT_UNAUTHORIZED;
case RTC_E_STATUS_CLIENT_PAYMENT_REQUIRED:
return IDS_RTCERR_STATUS_CLIENT_PAYMENT_REQUIRED;
case RTC_E_STATUS_CLIENT_FORBIDDEN:
return IDS_RTCERR_STATUS_CLIENT_FORBIDDEN;
case RTC_E_STATUS_CLIENT_NOT_FOUND:
return IDS_RTCERR_STATUS_CLIENT_NOT_FOUND;
case RTC_E_STATUS_CLIENT_METHOD_NOT_ALLOWED:
return IDS_RTCERR_STATUS_CLIENT_METHOD_NOT_ALLOWED;
case RTC_E_STATUS_CLIENT_NOT_ACCEPTABLE:
return IDS_RTCERR_STATUS_CLIENT_NOT_ACCEPTABLE;
case RTC_E_STATUS_CLIENT_PROXY_AUTHENTICATION_REQUIRED:
return IDS_RTCERR_STATUS_CLIENT_PROXY_AUTHENTICATION_REQUIRED;
case RTC_E_STATUS_CLIENT_REQUEST_TIMEOUT:
return IDS_RTCERR_STATUS_CLIENT_REQUEST_TIMEOUT;
case RTC_E_STATUS_CLIENT_CONFLICT:
return IDS_RTCERR_STATUS_CLIENT_CONFLICT;
case RTC_E_STATUS_CLIENT_GONE:
return IDS_RTCERR_STATUS_CLIENT_GONE;
case RTC_E_STATUS_CLIENT_LENGTH_REQUIRED:
return IDS_RTCERR_STATUS_CLIENT_LENGTH_REQUIRED;
case RTC_E_STATUS_CLIENT_REQUEST_ENTITY_TOO_LARGE:
return IDS_RTCERR_STATUS_CLIENT_REQUEST_ENTITY_TOO_LARGE;
case RTC_E_STATUS_CLIENT_REQUEST_URI_TOO_LARGE:
return IDS_RTCERR_STATUS_CLIENT_REQUEST_URI_TOO_LARGE;
case RTC_E_STATUS_CLIENT_UNSUPPORTED_MEDIA_TYPE:
return IDS_RTCERR_STATUS_CLIENT_UNSUPPORTED_MEDIA_TYPE;
case RTC_E_STATUS_CLIENT_BAD_EXTENSION:
return IDS_RTCERR_STATUS_CLIENT_BAD_EXTENSION;
case RTC_E_STATUS_CLIENT_TEMPORARILY_NOT_AVAILABLE:
return IDS_RTCERR_STATUS_CLIENT_TEMPORARILY_NOT_AVAILABLE;
case RTC_E_STATUS_CLIENT_TRANSACTION_DOES_NOT_EXIST:
return IDS_RTCERR_STATUS_CLIENT_TRANSACTION_DOES_NOT_EXIST;
case RTC_E_STATUS_CLIENT_LOOP_DETECTED:
return IDS_RTCERR_STATUS_CLIENT_LOOP_DETECTED;
case RTC_E_STATUS_CLIENT_TOO_MANY_HOPS:
return IDS_RTCERR_STATUS_CLIENT_TOO_MANY_HOPS;
case RTC_E_STATUS_CLIENT_ADDRESS_INCOMPLETE:
return IDS_RTCERR_STATUS_CLIENT_ADDRESS_INCOMPLETE;
case RTC_E_STATUS_CLIENT_AMBIGUOUS:
return IDS_RTCERR_STATUS_CLIENT_AMBIGUOUS;
case RTC_E_STATUS_CLIENT_BUSY_HERE:
return IDS_RTCERR_STATUS_CLIENT_BUSY_HERE;
case RTC_E_STATUS_REQUEST_TERMINATED:
return IDS_RTCERR_STATUS_REQUEST_TERMINATED;
case RTC_E_STATUS_NOT_ACCEPTABLE_HERE:
return IDS_RTCERR_STATUS_NOT_ACCEPTABLE_HERE;
case RTC_E_STATUS_SERVER_INTERNAL_ERROR:
return IDS_RTCERR_STATUS_SERVER_INTERNAL_ERROR;
case RTC_E_STATUS_SERVER_NOT_IMPLEMENTED:
return IDS_RTCERR_STATUS_SERVER_NOT_IMPLEMENTED;
case RTC_E_STATUS_SERVER_BAD_GATEWAY:
return IDS_RTCERR_STATUS_SERVER_BAD_GATEWAY;
case RTC_E_STATUS_SERVER_SERVICE_UNAVAILABLE:
return IDS_RTCERR_STATUS_SERVER_SERVICE_UNAVAILABLE;
case RTC_E_STATUS_SERVER_SERVER_TIMEOUT:
return IDS_RTCERR_STATUS_SERVER_SERVER_TIMEOUT;
case RTC_E_STATUS_SERVER_VERSION_NOT_SUPPORTED:
return IDS_RTCERR_STATUS_SERVER_VERSION_NOT_SUPPORTED;
case RTC_E_STATUS_GLOBAL_BUSY_EVERYWHERE:
return IDS_RTCERR_STATUS_GLOBAL_BUSY_EVERYWHERE;
case RTC_E_STATUS_GLOBAL_DECLINE:
return IDS_RTCERR_STATUS_GLOBAL_DECLINE;
case RTC_E_STATUS_GLOBAL_DOES_NOT_EXIST_ANYWHERE:
return IDS_RTCERR_STATUS_GLOBAL_DOES_NOT_EXIST_ANYWHERE;
case RTC_E_STATUS_GLOBAL_NOT_ACCEPTABLE:
return IDS_RTCERR_STATUS_GLOBAL_NOT_ACCEPTABLE;
case RTC_E_PINT_STATUS_REJECTED_BUSY:
return IDS_RTCERR_PINT_STATUS_REJECTED_BUSY;
case RTC_E_PINT_STATUS_REJECTED_NO_ANSWER:
return IDS_RTCERR_PINT_STATUS_REJECTED_NO_ANSWER;
case RTC_E_PINT_STATUS_REJECTED_ALL_BUSY:
return IDS_RTCERR_PINT_STATUS_REJECTED_ALL_BUSY;
case RTC_E_PINT_STATUS_REJECTED_PL_FAILED:
return IDS_RTCERR_PINT_STATUS_REJECTED_PL_FAILED;
case RTC_E_PINT_STATUS_REJECTED_SW_FAILED:
return IDS_RTCERR_PINT_STATUS_REJECTED_SW_FAILED;
case RTC_E_PINT_STATUS_REJECTED_CANCELLED:
return IDS_RTCERR_PINT_STATUS_REJECTED_CANCELLED;
case RTC_E_PINT_STATUS_REJECTED_BADNUMBER:
return IDS_RTCERR_PINT_STATUS_REJECTED_BADNUMBER;
default:
return IDS_ERROR_UNKNOWN;
}
}
const WCHAR UIManager_t::sc_ListenerWindowClassName[] = L"UIListenerWindowClass";
const WCHAR UIManager_t::sc_ListenerWindowName[] = L"UIListenerWindow";
const UINT UIManager_t::sc_RefreshUITimeout = 250;
const UINT UIManager_t::sc_DisconnectLag = 2000;
const DWORD UIManager_t::sc_StatusHeaderCookie = 0;
const DWORD UIManager_t::sc_ErrorNotificationTimeOut = 3;
/*------------------------------------------------------------------------------
UIManager_t::UIManager_t
Constructor for the class
------------------------------------------------------------------------------*/
UIManager_t::UIManager_t(
void
)
{
m_MainDialog = NULL;
m_ListenerWindow = NULL;
m_MessageBox = NULL;
m_Initialized = false;
m_RefreshUITimerId = 0;
m_AlreadyDialedString.clear();
}
/*------------------------------------------------------------------------------
UIManager_t::~UIManager_t
Destructor
------------------------------------------------------------------------------*/
UIManager_t::~UIManager_t(
void
)
{
Uninitialize();
}
LRESULT WINAPI
UIManager_t::s_ListenerWindowProc(
HWND WindowHandle,
UINT Message,
WPARAM wParam,
LPARAM lParam
)
{
UIManager_t* pThis = NULL;
if (Message == WM_CREATE)
{
CREATESTRUCT *pCreateStruct = reinterpret_cast<CREATESTRUCT*>(lParam);
if (! pCreateStruct)
{
ASSERT(FALSE);
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"CreateStruct is empty - cannot create this window"));
return -1;
}
pThis = reinterpret_cast<UIManager_t*>(pCreateStruct->lpCreateParams);
if (pThis == NULL)
{
ASSERT(FALSE);
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"No UIManager_t object in the create struct - cannot create this window"));
return -1;
}
//Pack the canvas object into the window for future retrieval
SetWindowLong(WindowHandle, GWL_USERDATA, reinterpret_cast<LONG>(pThis));
}
//Retrieve the object from the window userdata section
pThis = reinterpret_cast<UIManager_t*>(GetWindowLong(WindowHandle, GWL_USERDATA));
if (pThis == NULL)
{
return DefWindowProc(WindowHandle, Message, wParam, lParam);
}
LRESULT ReturnValue = pThis->ListenerWindowProc(
WindowHandle,
Message,
wParam,
lParam
);
if (Message == WM_DESTROY)
{
SetWindowLong(WindowHandle, GWL_USERDATA, 0);
}
return ReturnValue;
}
LRESULT
UIManager_t::ListenerWindowProc(
HWND WindowHandle,
UINT Message,
WPARAM wParam,
LPARAM lParam
)
{
HWND ParentHandle = NULL;
LRESULT ReturnValue;
switch (Message)
{
case WM_INITDIALOG:
break;
case WM_ERASEBKGND:
break;
case WM_COMMAND:
break;
case WM_HELP:
OnHelp();
break;
case WM_NOTIFY:
if (reinterpret_cast<NMHDR*>(lParam)->code == EN_UPDATE)
{
//get udpate from the edit control
OnEditControlUpdate();
break;
}
if (reinterpret_cast<NMHDR*>(lParam)->hwndFrom == m_ListBox)
{
//it is notify from listbox
OnListboxNotify(reinterpret_cast<NMHDR*>(lParam)->code);
break;
}
ParentHandle = GetParent(reinterpret_cast<NMHDR*>(lParam)->hwndFrom);
if (ParentHandle == m_MainDialog || ParentHandle == m_MessageBox)
{
//it is a menu button either from maindialog or messagebox
OnCommand(wParam);
break;
}
break;
default:
ReturnValue = DefWindowProc(
WindowHandle,
Message,
wParam,
lParam
);
}
return ReturnValue;
}
/*------------------------------------------------------------------------------
UIManager_t::Initialize
Initialize the desktop and subsequent windows
Returns (HRESULT): indicating success or failure
------------------------------------------------------------------------------*/
HRESULT
UIManager_t::Initialize(
bool IsVisible
)
{
HRESULT hr = CreateListenerWindow();
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed at creating listener window, hr = 0x%x", hr));
return hr;
}
hr = CreateMainDialog(IsVisible);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed at creating main dialog, hr = 0x%x", hr));
return hr;
}
hr = GetApp()->GetTimers().AddTimer(
sc_RefreshUITimeout,
static_cast<ITimerHandler_t*>(this),
&m_RefreshUITimerId
);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"could not create the refresh UI timer, hr = 0x%x", hr));
return hr;
}
m_Initialized = true;
return S_OK;
}
/*------------------------------------------------------------------------------
UIManager_t::Uninitialize
Uninitializes the UI components
------------------------------------------------------------------------------*/
HRESULT
UIManager_t::Uninitialize(
void
)
{
if (m_RefreshUITimerId != 0)
{
GetApp()->GetTimers().RemoveTimer(m_RefreshUITimerId);
m_RefreshUITimerId = 0;
}
if (m_MessageBox != NULL)
{
DestroyWindow(m_MessageBox);
}
if (m_MainDialog != NULL)
{
SendMessage(
m_ListBox,
LB_RESETCONTENT,
0, 0
);
DestroyWindow(m_MainDialog);
}
if (m_ListenerWindow != NULL)
{
DestroyWindow(m_ListenerWindow);
}
m_Initialized = false;
return S_OK;
}
HRESULT
UIManager_t::OnHookModeChange(
bool IsOnHook
)
{
if (!m_Initialized)
{
return S_FALSE;
}
if (!IsOnHook)
{
//bring the window to foreground
ShowWindow(m_MainDialog, SW_SHOW);
SetForegroundWindow(m_MainDialog);
PHSetValue(
phsPhoneAppStatus,
PHGetSetting(phsPhoneAppStatus) | VOIP_PHONEAPP_ACTIVE_BITMASK
);
ForceCloseCurrentMessageBox();
}
UpdateDialBand();
UpdateMenuBar();
return S_OK;
}
HRESULT
UIManager_t::OnCallEvent(
Call_t* pCall
)
{
if (pCall == NULL)
{
ASSERT(FALSE);
return E_INVALIDARG;
}
if (!m_Initialized)
{
return S_FALSE;
}
HRESULT hr = UpdateIncomingCall(pCall);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed at updating message box, hr = 0x%x", hr));
}
if (pCall->GetCallStatus() != RTCSS_INCOMING)
{
hr = UpdateExistingCalls(pCall);
}
return hr;
}
/*------------------------------------------------------------------------------
UIManager_t::UpdateIncomingCall
Update the message box when call status changes
Returns (HRESULT): indicating success or failure
------------------------------------------------------------------------------*/
HRESULT
UIManager_t::UpdateIncomingCall(
Call_t* pCall
)
{
if (pCall == NULL)
{
ASSERT(FALSE);
return E_INVALIDARG;
}
HRESULT hr = S_OK;
switch (pCall->GetCallStatus())
{
//if its a new call, present the new call message box
case RTCSS_INCOMING:
GetApp()->StartRing(pCall);
m_cpIncomingCall = pCall;
hr = CreateIncomingCallMessageBox();
break;
//if the call is disconnected for an abnormal reason, notify the user
case RTCSS_DISCONNECTED:
//If there was a popup messagebox for this call (a newincomingcall message
//box), then we need to close the message box
if (m_cpIncomingCall == pCall && ThereIsCurrentMessageBox())
{
ForceCloseCurrentMessageBox();
m_cpIncomingCall = NULL;
GetApp()->StopRing();
}
break;
//otherwise we don't care
default:
//if the incoming call changed status, its not an incoming call anymore -
//clear out the variable
if (pCall == m_cpIncomingCall)
{
GetApp()->StopRing();
m_cpIncomingCall = NULL;
}
break;
}
return hr;
}
/*------------------------------------------------------------------------------
UIManager_t::UpdateExistingCalls
Update the main dialog when call status changes
Returns (HRESULT): indicating success or failure
------------------------------------------------------------------------------*/
HRESULT
UIManager_t::UpdateExistingCalls(
Call_t* pCall
)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -