2025-11-28 00:35:46 +09:00

450 lines
11 KiB
C++

// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
#include "StdAfx.h"
#include "AlarmClient.h"
#include "AlarmContent.h"
//
// This APPLICATION_ID is the unique ID for this
// Windows SideShow application. It is a GUID.
//
// {0F11B914-F461-4785-877C-482AB481CF7A}
static const GUID ALARM_CLIENT_APPLICATION_ID =
{ 0xf11b914, 0xf461, 0x4785, { 0x87, 0x7c, 0x48, 0x2a, 0xb4, 0x81, 0xcf, 0x7a } };
CAlarmClient::CAlarmClient() :
m_pSession(NULL),
m_pContentMgr(NULL),
m_pContent(NULL),
m_pNotificationMgr(NULL),
m_pNotification(NULL),
m_pAlarms(NULL),
m_lastNotificationId(0)
{
m_pAlarms = new Alarm();
}
CAlarmClient::~CAlarmClient()
{
//
// Release the memory used for all of the alarms
//
while (NULL != m_pAlarms)
{
Alarm* tmp = m_pAlarms->m_pNext;
delete m_pAlarms;
m_pAlarms = tmp;
}
}
void CAlarmClient::SetAlarm(SYSTEMTIME* pAlarmTime)
{
if (NULL != pAlarmTime)
{
Alarm* pLastAlarm = m_pAlarms;
//
// Find the last Alarm in the list
//
while (pLastAlarm->m_pNext != NULL)
{
pLastAlarm = pLastAlarm->m_pNext;
}
//
// Increment the last-used NOTIFICATION_ID so
// we have a new one to assign to this alarm
//
m_lastNotificationId++;
//
// Initialize the Alarm struct; this is empty
// because the last item in the list is always
// an empty structure.
//
pLastAlarm->m_bSet = TRUE;
pLastAlarm->m_time = *pAlarmTime;
pLastAlarm->m_notificationId= m_lastNotificationId;
pLastAlarm->m_pClient = this;
pLastAlarm->m_pNext = new Alarm();
//
// Start a thread that will fire the alarm when it's time
//
StartAlarmThread(pLastAlarm);
::MessageBox(NULL, L"You have set the alarm.", L"Alarm Set", MB_OK);
}
}
void CAlarmClient::ShowNotification(Alarm* pAlarm)
{
if (NULL != m_pNotification)
{
HRESULT hr = S_OK;
WCHAR wszMsg[32];
SYSTEMTIME expTime;
//
// Set the NotificationId property
//
hr = m_pNotification->put_NotificationId(pAlarm->m_notificationId);
if (FAILED(hr))
{
//
// handle failure case
//
}
//
// Set the Title property
//
hr = m_pNotification->put_Title(L"Alarm!!!");
if (FAILED(hr))
{
//
// handle failure case
//
}
//
// Set the Message property
// Use the safe string functions so the buffer doesn't
// get overrun.
//
hr = StringCchPrintf(wszMsg,
ARRAYSIZE(wszMsg),
L"Alarm %d set for %02d:%02d",
pAlarm->m_notificationId,
pAlarm->m_time.wHour,
pAlarm->m_time.wMinute);
if (SUCCEEDED(hr))
{
hr = m_pNotification->put_Message(wszMsg);
if (FAILED(hr))
{
//
// handle failure case
//
}
}
else
{
//
// If StringCchPrintf failed above, just use a default message for
// the alarm so that it doesn't appear blank.
//
hr = m_pNotification->put_Message(L"The Alarm just went off!");
if (FAILED(hr))
{
//
// handle failure case
//
}
}
//
// Set the Notification to expire after 90 days
//
::GetLocalTime(&expTime);
FILETIME ft = { 0 };
SystemTimeToFileTime(&expTime, &ft);
ULARGE_INTEGER u = { 0 };
memcpy(&u, &ft, sizeof(u));
u.QuadPart += 90 * 24 * 60 * 60 * 10000000LLU; // 90 days
memcpy(&ft, &u, sizeof(ft));
FileTimeToSystemTime(&ft, &expTime);
hr = m_pNotification->put_ExpirationTime(&expTime);
if (FAILED(hr))
{
//
// handle failure case
//
}
//
// Show the notification on the device, and
// revoke it when the user dismisses the alarm
//
if (NULL != m_pNotificationMgr)
{
m_pNotificationMgr->Show(m_pNotification);
::MessageBox(NULL, wszMsg, L"Alarm went off!", MB_OK);
m_pNotificationMgr->Revoke(pAlarm->m_notificationId);
}
}
}
DWORD WINAPI CAlarmClient::TimeMonitor(LPVOID lpParam)
{
Alarm* pAlarm = (Alarm*)lpParam;
if (NULL == pAlarm)
{
return 0;
}
SYSTEMTIME sysTime;
FILETIME ftNow;
FILETIME ftAlarm;
bool fNotificationShown = false;
::SystemTimeToFileTime(&(pAlarm->m_time), &ftAlarm);
while (!fNotificationShown)
{
//
// Get the local system time
//
::GetLocalTime(&sysTime);
::SystemTimeToFileTime(&sysTime, &ftNow);
//
// Compare the times; if it is currently past the
// time for the Alarm to fire, then show it.
//
if (::CompareFileTime(&ftNow, &ftAlarm) >= 0)
{
pAlarm->m_pClient->ShowNotification(pAlarm);
fNotificationShown = true;
}
else
{
Sleep(1000);
}
}
return 0;
}
void CAlarmClient::StartAlarmThread(Alarm* pAlarm)
{
HANDLE hThread = ::CreateThread(NULL,
0,
this->TimeMonitor,
pAlarm,
0,
NULL);
if (NULL == hThread)
{
//
// Failed to start alarm thread
//
}
}
void CAlarmClient::CreateNotification()
{
if (NULL != m_pSession &&
NULL == m_pNotificationMgr)
{
HRESULT hr = ::CoCreateInstance(CLSID_SideShowNotification,
NULL,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&m_pNotification));
if (FAILED(hr))
{
//
// Failed to CoCreate SideShowNotification
//
}
else
{
//
// Register with the platform so that we can provide Notifications
// to the devices
//
hr = m_pSession->RegisterNotifications(ALARM_CLIENT_APPLICATION_ID,
&m_pNotificationMgr);
if (S_OK == hr)
{
//
// Successfully registered notifications with Windows SideShow platform.
//
}
else if (S_FALSE == hr)
{
//
// Successfully registered notifications with Windows SideShow platform,
// but no devices available or enabled.
//
}
else if (E_INVALIDARG == hr)
{
//
// ISideShowSession::RegisterNotifications failed with Invalid Argument.
// Registry data is missing.
//
}
else
{
//
// ISideShowSession::RegisterNotifications failed.
//
}
}
}
}
void CAlarmClient::Register()
{
//
// Create the SideShowSession object that
// enables us to talk to the platform.
//
HRESULT hr = S_OK;
if (NULL == m_pSession &&
NULL == m_pContentMgr)
{
hr = ::CoCreateInstance(CLSID_SideShowSession,
NULL,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&m_pSession));
if (FAILED(hr))
{
//
// Failed to CoCreate SideShowSession.
//
}
else
{
//
// Register this client application with the platform
// so that it can send content to devices
//
hr = m_pSession->RegisterContent(ALARM_CLIENT_APPLICATION_ID,
SIDESHOW_ENDPOINT_SIMPLE_CONTENT_FORMAT,
&m_pContentMgr);
if (SUCCEEDED(hr))
{
//
// Successfully registered with Windows SideShow platform,
// now go register for Notifications
//
CreateNotification();
}
else if (E_INVALIDARG == hr)
{
//
// ISideShowSession::RegisterContent failed with Invalid Argument:
// Have you added the proper information to the registry for this application?
//
}
else
{
//
// ISideShowSession::RegisterContent failed
//
}
}
}
else
{
//
// This instance has already registered with the Windows SideShow platform
//
}
}
void CAlarmClient::Unregister()
{
if (NULL != m_pNotification)
{
m_pNotification->Release();
m_pNotification = NULL;
}
if (NULL != m_pNotificationMgr)
{
m_pNotificationMgr->Release();
m_pNotificationMgr = NULL;
}
if (NULL != m_pContent)
{
m_pContent->Release();
m_pContent = NULL;
}
if (NULL != m_pContentMgr)
{
m_pContentMgr->Release();
m_pContentMgr = NULL;
}
if (NULL != m_pSession)
{
m_pSession->Release();
m_pSession = NULL;
}
}
void CAlarmClient::AddContent()
{
if (NULL != m_pContentMgr)
{
//
// Create an instance of the content object if it doesn't exist
//
if (NULL == m_pContent)
{
m_pContent = new CAlarmContent();
}
HRESULT hr = m_pContentMgr->Add(m_pContent);
if (SUCCEEDED(hr))
{
//
// Successfully added content
//
}
else
{
//
// Failed to add content
//
}
}
}
void CAlarmClient::RemoveAllContent()
{
if (NULL != m_pContentMgr)
{
HRESULT hr = m_pContentMgr->RemoveAll();
if (SUCCEEDED(hr))
{
//
// Removed all content.
//
}
else
{
//
// Failed to remove content.
//
}
}
}