?? statusregion.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 "StatusRegion.hpp"
#include "Common.hpp"
#include "Debug.hpp"
#include "Layout.hpp"
#include "Resource.h"
const UINT c_cmsMainTimer = 250;
/*------------------------------------------------------------------------------
StatusHeaderImpl_t::StatusHeaderImpl_t
Constructor.
------------------------------------------------------------------------------*/
StatusHeaderImpl_t::StatusHeaderImpl_t(
)
{
TRACE(ZONE_COMMON_CTOR);
//clean out the message array
ZeroMemory(m_Messages, sizeof(m_Messages));
m_IndexActiveMessage = -1;
}
/*------------------------------------------------------------------------------
StatusHeaderImpl_t::~StatusHeaderImpl_t
Destructor.
------------------------------------------------------------------------------*/
StatusHeaderImpl_t::~StatusHeaderImpl_t(
)
{
TRACE(ZONE_COMMON_CTOR);
//Free the strings in the array.
for (int i = 0; i < _countof(m_Messages); i++)
{
ClearEntry(&m_Messages[i]);
}
}
bool
StatusHeaderImpl_t::IsValidIndex(
int Index
)
{
return (Index >= 0 && Index < _countof(m_Messages));
}
/*------------------------------------------------------------------------------
StatusHeaderImpl_t::ControlWindowProc
Handle messages
------------------------------------------------------------------------------*/
LRESULT
StatusHeaderImpl_t::ControlWindowProc(
UINT Message,
WPARAM wParam,
LPARAM lParam,
bool& Handled
)
{
LRESULT Result;
//by default assume we handled the message
Handled = true;
switch (Message)
{
case WM_ERASEBKGND:
//Fake erasing the background since we paint the whole client area
return 1;
case WM_PAINT:
return OnPaint(reinterpret_cast<HDC>(wParam));
case WM_STATUSHEADER_ADDSTATUSNOTIFICATION:
return OnAddNotification(reinterpret_cast<STATUS_HEADER_PARAMETERS*>(lParam), wParam);
case WM_STATUSHEADER_GETSTATUSCOOKIE:
return OnGetCookie();
case WM_STATUSHEADER_REMOVESTATUSNOTIFICATION:
return OnRemoveNotification(static_cast<DWORD>(wParam));
case WM_TIMER:
return OnTimer(wParam, reinterpret_cast<TIMERPROC*>(lParam));
case WM_CLOSE:
Handled = ForwardMessageToParent(Message, wParam, lParam, &Result);
return Result;
default:
Handled = false;
return 0;
}
}
/*------------------------------------------------------------------------------
StatusHeaderImpl_t::OnDrawItem
WM_PAINT handler for the button. Draws it.
------------------------------------------------------------------------------*/
LRESULT
StatusHeaderImpl_t::OnPaint(
HDC hdc
)
{
HRESULT hr;
WCHAR TextBuffer[MAX_PATH] = L"";
PaintHelper_t paint;
//start the painting operation
hr = paint.Begin(m_hwnd);
if (FAILED(hr))
{
return 0;
}
RECT ClientRect;
GetClientRect(m_hwnd, &ClientRect);
if (!m_Background)
{
if (FAILED(m_Background.LoadBitmap(
GlobalData_t::s_ModuleInstance,
IDB_STATUS
)))
{
return 0;
}
}
//Draw the background
hr = paint.TileBlt(
&m_Background,
&ClientRect,
NULL,
Layout_t::StatusHeaderTileLeft(),
Layout_t::StatusHeaderTileTop(),
Layout_t::StatusHeaderTileRight(),
Layout_t::StatusHeaderTileBottom(),
CLR_INVALID
);
ASSERT(SUCCEEDED(hr));
//If there is a string to display, then draw it
if (GetWindowText(m_hwnd, TextBuffer, _countof(TextBuffer)) > 0)
{
paint.SetBkMode(TRANSPARENT);
paint.SetFont(Fonts_t::StandardText());
paint.SetTextColor(Colors_t::DefaultTextColor());
InflateRect(
&ClientRect,
-Layout_t::StatusHeaderTextMargin(),
0
);
paint.DrawText(
TextBuffer,
-1,
&ClientRect,
DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX | DT_END_ELLIPSIS
);
}
ASSERT(SUCCEEDED(hr));
paint.End();
return 0;
}
/*------------------------------------------------------------------------------
StatusHeaderImpl_t::OnTimer
Updates the notify button based on the current time.
------------------------------------------------------------------------------*/
LRESULT
StatusHeaderImpl_t::OnTimer(
UINT TimerId,
TIMERPROC* pTimerProc
)
{
StatusHeaderMessage_t* pmCurrent = NULL;
//If there is no active message to display, ignore the timer event
if (!IsValidIndex(m_IndexActiveMessage))
{
ASSERT(m_IndexActiveMessage == -1);
return 0;
}
//Update the tick count for the Active Message
pmCurrent = &m_Messages[m_IndexActiveMessage];
if (pmCurrent->m_CurrentTick == INFINITE)
{
return 0;
}
pmCurrent->m_CurrentTick++;
//If necessary, remove that item
if (pmCurrent->m_CurrentTick > pmCurrent->m_TimeoutTick)
{
OnRemoveNotification(pmCurrent->m_Cookie);
}
return 0;
}
/*------------------------------------------------------------------------------
StatusHeaderImpl_t::AddNotification
Adds a notification to the button. This notification may not be displayed
immediately if its priority is not high enough
Parameters:
pParameters: A STATUS_HEADER_PARAMETERS or STATUS_HEADER_PARAMETERS_EX structure
SizeInBytes: size of the structure pointed by pParameters
------------------------------------------------------------------------------*/
HRESULT
StatusHeaderImpl_t::OnAddNotification(
STATUS_HEADER_PARAMETERS* pParameters,
UINT SizeInBytes
)
{
HRESULT hr = S_OK;
DWORD TimeoutTick = INFINITE;
StatusHeaderMessage_t* pnbmCurrent = NULL;
const WCHAR* pDisplay = NULL;
int cchToAllocate;
bool HaveString = false;
if (pParameters == NULL)
{
ASSERT(FALSE);
return E_POINTER;
}
switch (SizeInBytes)
{
case sizeof(STATUS_HEADER_PARAMETERS):
break;
case sizeof(STATUS_HEADER_PARAMETERS_EX):
{
STATUS_HEADER_PARAMETERS_EX* pExtended = reinterpret_cast<STATUS_HEADER_PARAMETERS_EX*>(pParameters);
pDisplay = pExtended->pwszDisplayString;
HaveString = true;
}
break;
default:
ASSERT(FALSE);
return E_INVALIDARG;
break;
}
if (!HaveString)
{
pDisplay = reinterpret_cast<WCHAR*>(LoadString(
pParameters->Instance,
pParameters->ResourceId,
NULL,
0
));
}
//validate parameters
if (pDisplay == NULL)
{
ASSERT(FALSE);
return E_POINTER;
}
//The string cannot be empty
int Length = wcslen(pDisplay);
if (! Length)
{
return E_INVALIDARG;
}
cchToAllocate = Length + 1;
if (cchToAllocate <= 1)
{
ASSERT(FALSE);
return E_INVALIDARG;
}
//Prorities must fit in the acceptable priority range
if (!IsValidIndex(pParameters->Priority))
{
ASSERT(FALSE);
return E_INVALIDARG;
}
if (SUCCEEDED(hr))
{
if (pParameters->secTimeout != INFINITE)
{
TimeoutTick = (pParameters->secTimeout*1000 / c_cmsMainTimer);
}
//If there is currently a StatusHeaderMessage_t of the same priority
//the existing message has to be removed
pnbmCurrent = &m_Messages[pParameters->Priority];
ClearEntry(pnbmCurrent);
//Fill in the struct with the new valid parameters
pnbmCurrent->m_pDisplay = reinterpret_cast<WCHAR*>(TrackAlloc(
sizeof(WCHAR) * cchToAllocate
));
if (pnbmCurrent->m_pDisplay == NULL)
{
hr = E_OUTOFMEMORY;
}
else
{
StringCchCopyW(
pnbmCurrent->m_pDisplay,
cchToAllocate,
pDisplay
);
}
}
if (SUCCEEDED(hr))
{
//Copy over the rest of the params
pnbmCurrent->m_IsValid = TRUE;
pnbmCurrent->m_Cookie = pParameters->Cookie;
pnbmCurrent->m_Priority = pParameters->Priority;
pnbmCurrent->m_TimeoutTick = TimeoutTick;
//Now there is at least 1 message, ensure the active message
//takes this new one into account
hr = UpdateActiveMessage();
ASSERT(hr == S_OK);
}
return hr;
}
/*------------------------------------------------------------------------------
StatusHeaderImpl_t::OnRemoveNotification
Message Handler that removes a notification by cookie
Params: WPARAM - DWORD cookie val of the notification to remove
------------------------------------------------------------------------------*/
LRESULT
StatusHeaderImpl_t::OnRemoveNotification(
DWORD Cookie
)
{
LRESULT Result = 1;
int Index = 0;
//Find the first valid message with the matching cookie
for (Index = 0; Index < _countof(m_Messages); Index++)
{
StatusHeaderMessage_t* pnbmCurrent = &m_Messages[Index];
if (pnbmCurrent->m_IsValid && pnbmCurrent->m_Cookie == Cookie)
{
ClearEntry(pnbmCurrent);
break;
}
}
//If the item was found and removed, we need to update the index of the
//active message
if (IsValidIndex(Index))
{
Result = UpdateActiveMessage();
}
return Result;
}
/*------------------------------------------------------------------------------
StatusHeaderImpl_t::OnGetCookie
Gets the cookie of the currently active notification
------------------------------------------------------------------------------*/
LRESULT
StatusHeaderImpl_t::OnGetCookie(
void
)
{
if (m_IndexActiveMessage != -1)
{
return m_Messages[m_IndexActiveMessage].m_Cookie;
}
return (LRESULT)(DWORD)-1;
}
/*------------------------------------------------------------------------------
StatusHeaderImpl_t::UpdateActiveMessage
Figure out which message is currently active
------------------------------------------------------------------------------*/
LRESULT
StatusHeaderImpl_t::UpdateActiveMessage(
)
{
int Index = 0;
int IndexOld = m_IndexActiveMessage;
bool Invalidate = false;
//Reset the active message index
m_IndexActiveMessage = -1;
//Search for the first valid message, since the array
//is layed out in order of priority
for (Index = 0; Index < _countof(m_Messages); Index++)
{
if (m_Messages[Index].m_IsValid)
{
m_IndexActiveMessage = Index;
break;
}
}
// Update the window text
if(m_IndexActiveMessage != -1)
{
WCHAR TextBuffer[MAX_PATH];
// Get the current window text
GetWindowText(m_hwnd, TextBuffer, _countof(TextBuffer));
// Compare the strings, then the linkage. If nothing has changed, we don't need to
// update.
if(wcscmp(TextBuffer, m_Messages[m_IndexActiveMessage].m_pDisplay))
{
Invalidate = true;
SetWindowText(m_hwnd, m_Messages[m_IndexActiveMessage].m_pDisplay);
}
}
else
{
Invalidate = true;
SetWindowText(m_hwnd, L"");
}
if (Invalidate)
{
//Redraw the notify button
InvalidateRect(m_hwnd, NULL, TRUE);
}
//if a valid message was not found, the index will remain at -1
return IsValidIndex(Index) ? 0 : 1;
}
/*------------------------------------------------------------------------------
StatusHeaderImpl_t::ClearEntry
Frees the allocated members of the specified notify message
------------------------------------------------------------------------------*/
void
StatusHeaderImpl_t::ClearEntry(
StatusHeaderMessage_t* pnbmCurrent
)
{
if (!pnbmCurrent)
{
ASSERT(0);
return;
}
//The pDisplay member was allocated using TrackAlloc
if (pnbmCurrent->m_pDisplay != NULL)
{
TrackFree(pnbmCurrent->m_pDisplay);
}
//Clear out the entire struct
ZeroMemory(pnbmCurrent, sizeof(StatusHeaderMessage_t));
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -