Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1193 lines
26 KiB

#include "precomp.h"
#include "resource.h"
#include "AudioLvl.h"
static const int g_nAudIconWidth = 16;
static const int g_nAudIconHeight = 16;
static const int g_nAudChkbWidth = 13;
static const int g_nAudChkbHeight = 13;
static const int g_nAudChkbXMargin = 13;
static const int g_nAudChkbYMargin = 12;
static const int g_nAudIconXMargin = g_nAudChkbXMargin + g_nAudChkbWidth + 3;
static const int g_nAudIconYMargin = 10;
static const int g_nAudMeterXMargin = g_nAudIconXMargin + g_nAudIconWidth + 5;
static const int g_nAudMeterHeight = 7;
static const int g_nAudMeterYMargin = g_nAudIconYMargin + (g_nAudMeterHeight/2);
static const int g_nAudMeterRightMargin = 5; // 5 pixels from end
static const int g_nAudTrkRangeMin = 0;
static const int g_nAudTrkRangeMax = 99;
static const int g_nAudTrkRangeSeg = 0xFFFF / g_nAudTrkRangeMax;
static const int g_nAudTrkTickFreq = 20;
static const int g_nAudTrkRightGap = 3;
static const int g_nAudTrkXMargin = g_nAudIconXMargin + g_nAudIconWidth + 5;
static const int g_nAudTrkYMargin = 2;
static const int g_nAudTrkHeight = 25;
static const int g_nAudTrkMinWidth = 50;
static const int RECTANGLE_WIDTH = 10;
static const int RECTANGLE_LEADING = 1;
static inline WORD ScaleMixer(DWORD dwVol)
{
// NOTE: the "+ g_nAudTrkRangeSeg - 1" provides for a correction that
// takes place while truncating the position when we are setting the
// volume. See bug 1634
return (((LOWORD(dwVol) + g_nAudTrkRangeSeg - 1) *
g_nAudTrkRangeMax) / 0xFFFF);
}
CAudioLevel::CAudioLevel(CAudioControl *pAudioControl) :
m_hwndParent(NULL),
m_hwndMicTrack(NULL),
m_hwndMicTrackTT(NULL),
m_hwndSpkTrack(NULL),
m_hwndSpkTrackTT(NULL),
m_hIconMic(NULL),
m_hIconSpkr(NULL),
m_hwndChkbRecMute(NULL),
m_hwndChkbSpkMute(NULL),
m_hwndChkbRecMuteTT(NULL),
m_hwndChkbSpkMuteTT(NULL),
m_fVisible(FALSE),
m_fMicTrkVisible(TRUE),
m_fSpkTrkVisible(TRUE),
m_dwMicTrackPos(0xFFFFFFFF),
m_dwSpkTrackPos(0xFFFFFFFF),
m_dwMicLvl(0),
m_dwSpkLvl(0),
m_hGreyBrush(NULL), m_hBlackBrush(NULL), m_hRedBrush(NULL),
m_hGreenBrush(NULL), m_hYellowBrush(NULL), m_hHiLitePen(NULL),
m_hShadowPen(NULL), m_hDkShadowPen(NULL), m_hLitePen(NULL)
{
ClearStruct(&m_rect);
m_pAudioControl = pAudioControl;
// load icons
m_hIconSpkr = (HICON) ::LoadImage( ::GetInstanceHandle(),
MAKEINTRESOURCE(IDI_SPKEMPTY),
IMAGE_ICON,
g_nAudIconWidth,
g_nAudIconHeight,
LR_DEFAULTCOLOR | LR_SHARED);
m_hIconMic = (HICON) ::LoadImage( ::GetInstanceHandle(),
MAKEINTRESOURCE(IDI_MICEMPTY),
IMAGE_ICON,
g_nAudIconWidth,
g_nAudIconHeight,
LR_DEFAULTCOLOR | LR_SHARED);
// create the brushes used for painting the signal level
CreateBrushes();
}
CAudioLevel::~CAudioLevel()
{
if (m_hGreyBrush)
DeleteObject(m_hGreyBrush);
if (m_hRedBrush)
DeleteObject(m_hRedBrush);
if (m_hYellowBrush)
DeleteObject(m_hYellowBrush);
if (m_hGreenBrush)
DeleteObject(m_hGreenBrush);
if (m_hBlackBrush)
DeleteObject(m_hBlackBrush);
if (m_hHiLitePen)
DeleteObject(m_hHiLitePen);
if (m_hDkShadowPen)
DeleteObject(m_hDkShadowPen);
if (m_hShadowPen)
DeleteObject(m_hShadowPen);
if (m_hLitePen)
DeleteObject(m_hLitePen);
}
CAudioLevel::Create(HWND hwndParent)
{
BOOL fCanSetRecVolume, fCanSetSpkVolume;
BOOL fCheck;
m_hwndParent = hwndParent;
m_hwndParentParent = GetParent(hwndParent);
fCanSetRecVolume = m_pAudioControl->CanSetRecorderVolume();
fCanSetSpkVolume = m_pAudioControl->CanSetSpeakerVolume();
// create the mute check box for microphone
m_hwndChkbRecMute = ::CreateWindow( _TEXT("BUTTON"),
g_szEmpty,
WS_CHILD | WS_CLIPSIBLINGS |
BS_AUTOCHECKBOX,
0, 0, 0, 0,
m_hwndParent,
(HMENU) IDM_MUTE_MICROPHONE,
GetInstanceHandle(),
NULL);
if (m_hwndChkbRecMute != NULL)
{
// mute is initially off
fCheck = !(m_pAudioControl->IsRecMuted());
::SendMessage(m_hwndChkbRecMute, BM_SETCHECK, fCheck, 0);
// create the tool tip
m_hwndChkbRecMuteTT = CreateWindowEx(0,
TOOLTIPS_CLASS,
(LPSTR) NULL,
0, // styles
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
m_hwndParent,
(HMENU) NULL,
::GetInstanceHandle(),
NULL);
if (NULL != m_hwndChkbRecMuteTT)
{
TOOLINFO ti;
ti.cbSize = sizeof(TOOLINFO);
ti.uFlags = TTF_SUBCLASS | TTF_IDISHWND;
ti.hwnd = m_hwndParent;
ti.hinst = ::GetInstanceHandle();
ti.uId = (UINT) m_hwndChkbRecMute;
ti.lpszText = (LPTSTR) IDS_AUDIO_REC_MUTE_TT;
::SendMessage( m_hwndChkbRecMuteTT, TTM_ADDTOOL, 0,
(LPARAM) (LPTOOLINFO) &ti);
}
}
// create the mute check box for speaker
m_hwndChkbSpkMute = ::CreateWindow( _TEXT("BUTTON"),
g_szEmpty,
WS_CHILD | WS_CLIPSIBLINGS
| BS_AUTOCHECKBOX,
0, 0, 0, 0,
m_hwndParent,
(HMENU) IDM_MUTE_SPEAKER,
GetInstanceHandle(),
NULL);
if (NULL != m_hwndChkbSpkMute)
{
// set appropriate mute status in microphone's mute check box
fCheck = !(m_pAudioControl->IsSpkMuted());
// Mute is off - so check it
::SendMessage(m_hwndChkbSpkMute, BM_SETCHECK, fCheck, 0);
// create the tool tip
m_hwndChkbSpkMuteTT = CreateWindowEx(0,
TOOLTIPS_CLASS,
(LPSTR) NULL,
0, // styles
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
m_hwndParent,
(HMENU) NULL,
::GetInstanceHandle(),
NULL);
if (NULL != m_hwndChkbSpkMuteTT)
{
TOOLINFO ti;
ti.cbSize = sizeof(TOOLINFO);
ti.uFlags = TTF_SUBCLASS | TTF_IDISHWND;
ti.hwnd = m_hwndParent;
ti.hinst = ::GetInstanceHandle();
ti.uId = (UINT) m_hwndChkbSpkMute;
ti.lpszText = (LPTSTR) IDS_AUDIO_SPK_MUTE_TT;
::SendMessage( m_hwndChkbSpkMuteTT, TTM_ADDTOOL, 0,
(LPARAM) (LPTOOLINFO) &ti);
}
}
// create the mic level trackbar:
m_hwndMicTrack = ::CreateWindowEx( 0L,
TRACKBAR_CLASS,
g_szEmpty,
WS_CHILD | WS_CLIPSIBLINGS
| TBS_HORZ | TBS_NOTICKS | TBS_BOTH
| (fCanSetRecVolume ? 0 : WS_DISABLED),
0, 0, 0, 0,
m_hwndParent,
(HMENU) ID_AUDIODLG_MIC_TRACK,
::GetInstanceHandle(),
NULL);
if (NULL != m_hwndMicTrack)
{
::SendMessage( m_hwndMicTrack,
TBM_SETRANGE,
FALSE,
MAKELONG(g_nAudTrkRangeMin, g_nAudTrkRangeMax));
::SendMessage( m_hwndMicTrack,
TBM_SETTICFREQ,
g_nAudTrkTickFreq,
g_nAudTrkRangeMin);
WORD wPos = (g_nAudTrkRangeMax - g_nAudTrkRangeMin) / 2;
if (fCanSetRecVolume)
{
wPos = ScaleMixer(m_pAudioControl->GetRecorderVolume());
}
::SendMessage( m_hwndMicTrack,
TBM_SETPOS,
TRUE,
wPos);
m_hwndMicTrackTT = CreateWindowEx( 0,
TOOLTIPS_CLASS,
(LPSTR) NULL,
0, // styles
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
m_hwndParent,
(HMENU) NULL,
::GetInstanceHandle(),
NULL);
if (NULL != m_hwndMicTrackTT)
{
TOOLINFO ti;
ti.cbSize = sizeof(TOOLINFO);
ti.uFlags = TTF_SUBCLASS | TTF_IDISHWND;
ti.hwnd = m_hwndParent;
ti.hinst = ::GetInstanceHandle();
ti.uId = (UINT) m_hwndMicTrack;
ti.lpszText = (LPTSTR) IDS_AUDIO_MIC_TRACK_TT;
::SendMessage(m_hwndMicTrackTT, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &ti);
}
}
// create the speaker level trackbar:
m_hwndSpkTrack = ::CreateWindowEx( 0L,
TRACKBAR_CLASS,
g_szEmpty,
WS_CHILD | WS_CLIPSIBLINGS
| TBS_HORZ | TBS_NOTICKS | TBS_BOTH
| (fCanSetSpkVolume ? 0 : WS_DISABLED),
0, 0, 0, 0,
m_hwndParent,
(HMENU) ID_AUDIODLG_SPKR_TRACK,
::GetInstanceHandle(),
NULL);
if (NULL != m_hwndSpkTrack)
{
::SendMessage( m_hwndSpkTrack,
TBM_SETRANGE,
FALSE,
MAKELONG(g_nAudTrkRangeMin, g_nAudTrkRangeMax));
::SendMessage( m_hwndSpkTrack,
TBM_SETTICFREQ,
g_nAudTrkTickFreq,
g_nAudTrkRangeMin);
WORD wPos = (g_nAudTrkRangeMax - g_nAudTrkRangeMin) / 2;
if (fCanSetSpkVolume)
{
wPos = ScaleMixer(m_pAudioControl->GetSpeakerVolume());
}
::SendMessage( m_hwndSpkTrack,
TBM_SETPOS,
TRUE,
wPos);
m_hwndSpkTrackTT = CreateWindowEx( 0,
TOOLTIPS_CLASS,
(LPSTR) NULL,
0, // styles
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
m_hwndParent,
(HMENU) NULL,
::GetInstanceHandle(),
NULL);
if (NULL != m_hwndSpkTrackTT)
{
TOOLINFO ti;
ti.cbSize = sizeof(TOOLINFO);
ti.uFlags = TTF_SUBCLASS | TTF_IDISHWND;
ti.hwnd = m_hwndParent;
ti.hinst = ::GetInstanceHandle();
ti.uId = (UINT) m_hwndSpkTrack;
ti.lpszText = (LPTSTR) IDS_AUDIO_SPK_TRACK_TT;
::SendMessage(m_hwndSpkTrackTT, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &ti);
}
}
return TRUE;
}
BOOL CAudioLevel::ForwardSysChangeMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CreateBrushes();
if (NULL != m_hwndMicTrack)
{
::SendMessage(m_hwndMicTrack, uMsg, wParam, lParam);
}
if (NULL != m_hwndSpkTrack)
{
::SendMessage(m_hwndSpkTrack, uMsg, wParam, lParam);
}
return TRUE;
}
BOOL CAudioLevel::CreateBrushes()
{
// the background color may change on us!
COLORREF GreyColor = GetSysColor(COLOR_3DFACE);
COLORREF BlackColor = GetSysColor(COLOR_BTNTEXT);
const COLORREF RedColor = RGB(255,0,0);
const COLORREF YellowColor = RGB(255,255,0);
const COLORREF GreenColor = RGB(0,255,0);
COLORREF ShadowColor = GetSysColor(COLOR_3DSHADOW);
COLORREF HiLiteColor = GetSysColor(COLOR_3DHIGHLIGHT);
COLORREF LiteColor = GetSysColor(COLOR_3DLIGHT);
COLORREF DkShadowColor = GetSysColor(COLOR_3DDKSHADOW);
if (m_hGreyBrush)
{
DeleteObject(m_hGreyBrush);
}
m_hGreyBrush = CreateSolidBrush(GreyColor);
if (m_hBlackBrush)
{
DeleteObject(m_hBlackBrush);
}
m_hBlackBrush = CreateSolidBrush(BlackColor);
if (m_hHiLitePen)
{
DeleteObject(m_hHiLitePen);
}
m_hHiLitePen = CreatePen(PS_SOLID, 0, HiLiteColor);
if (m_hLitePen)
{
DeleteObject(m_hLitePen);
}
m_hLitePen = CreatePen(PS_SOLID, 0, LiteColor);
if (m_hDkShadowPen)
{
DeleteObject(m_hDkShadowPen);
}
m_hDkShadowPen = CreatePen(PS_SOLID, 0, DkShadowColor);
if (m_hShadowPen)
{
DeleteObject(m_hShadowPen);
}
m_hShadowPen = CreatePen(PS_SOLID, 0, ShadowColor);
// red, yellow, green will never change
if (!m_hRedBrush)
m_hRedBrush = CreateSolidBrush (RedColor);
if (!m_hGreenBrush)
m_hGreenBrush = CreateSolidBrush(GreenColor);
if (!m_hYellowBrush)
m_hYellowBrush = CreateSolidBrush(YellowColor);
return TRUE;
}
BOOL CAudioLevel::OnCommand(WPARAM wParam, LPARAM lParam)
{
LRESULT lCheck;
BOOL fSpeaker;
switch (LOWORD(wParam))
{
default:
return FALSE;
case IDM_MUTE_MICROPHONE_ACCEL:
lCheck = BST_CHECKED;
fSpeaker = FALSE;
break;
case IDM_MUTE_MICROPHONE:
lCheck = BST_UNCHECKED;
fSpeaker = FALSE;
break;
case IDM_MUTE_SPEAKER_ACCEL:
lCheck = BST_CHECKED;
fSpeaker = TRUE;
break;
case IDM_MUTE_SPEAKER:
lCheck = BST_UNCHECKED;
fSpeaker = TRUE;
break;
}
BOOL fMute = (lCheck == ::SendMessage(
fSpeaker ? m_hwndChkbSpkMute : m_hwndChkbRecMute,
BM_GETCHECK, 0, 0));
m_pAudioControl->MuteAudio(fSpeaker, fMute);
return TRUE;
}
BOOL CAudioLevel::ShiftFocus(HWND hwndCur, BOOL fForward)
{
BOOL bRet = FALSE;
HWND aHwnds[] = {m_hwndChkbSpkMute,m_hwndSpkTrack,m_hwndChkbRecMute,m_hwndMicTrack};
int nSizeArray = ARRAY_ELEMENTS(aHwnds);
int nIndex, nSelect;
HWND hwndNewFocus=NULL;
if (m_fVisible)
{
if (hwndCur == NULL)
{
hwndNewFocus = m_hwndSpkTrack;
}
else
{
for (nIndex = 0; nIndex < nSizeArray; nIndex++)
{
if (aHwnds[nIndex] == hwndCur)
{
nSelect = (nIndex + (fForward ? 1 : -1)) % nSizeArray;
if (nSelect < 0)
nSelect += nSizeArray;
hwndNewFocus = aHwnds[nSelect];
break;
}
}
}
if (hwndNewFocus)
{
SetFocus(hwndNewFocus);
bRet = TRUE;
}
}
return bRet;
}
BOOL CAudioLevel::IsChildWindow(HWND hwnd)
{
if (hwnd)
{
if ((hwnd == m_hwndSpkTrack) || (hwnd == m_hwndMicTrack) ||
(hwnd == m_hwndChkbRecMute) || (hwnd == m_hwndChkbSpkMute))
{
return TRUE;
}
}
return FALSE;
}
BOOL CAudioLevel::OnMuteChange(BOOL fSpeaker, BOOL fMute)
{
SendMessage(fSpeaker ? m_hwndChkbSpkMute : m_hwndChkbRecMute,
BM_SETCHECK, fMute ? BST_UNCHECKED : BST_CHECKED, 0);
return TRUE;
}
BOOL CAudioLevel::OnPaint(PAINTSTRUCT* pps)
{
if (m_fVisible)
{
ASSERT(pps);
ASSERT(pps->hdc);
PaintIcons(pps->hdc);
}
return TRUE;
}
BOOL CAudioLevel::PaintChannel(BOOL fSpeaker, HDC hdc)
{
BOOL bGotDC = FALSE;
DWORD dwVolume;
int nVuWidth, nDiff;
RECT rect, rectDraw;
HBRUSH hCurrentBrush;
HPEN hOldPen;
int nRects;
int nRectangleWidth;
int nIndex;
const int NUM_RECTANGLES_MAX = 16;
const int NUM_RECTANGLES_MIN = 6;
int nRectsTotal;
bool bTransmitting;
POINT ptOld, pt;
if (fSpeaker)
{
dwVolume = LOWORD(m_dwSpkLvl);
bTransmitting = HIWORD(m_dwSpkLvl) & SIGNAL_STATUS_TRANSMIT;
}
else
{
dwVolume = LOWORD(m_dwMicLvl);
bTransmitting = HIWORD(m_dwMicLvl) & SIGNAL_STATUS_TRANSMIT;
}
if (!hdc)
{
if ((fSpeaker) && (m_hwndSpkTrack))
hdc = GetDC(m_hwndSpkTrack);
else if (m_hwndMicTrack)
hdc = GetDC(m_hwndMicTrack);
bGotDC = TRUE;
}
if (!hdc)
return FALSE;
// rectangle leading is 1
if (dwVolume > 100)
dwVolume = 100;
if (fSpeaker)
rect = m_rcChannelSpk;
else
rect = m_rcChannelMic;
nVuWidth = rect.right - rect.left;
if (nVuWidth < (NUM_RECTANGLES_MIN*2))
return FALSE;
// "rect" represents the edges of the meter's outer rectangle
// compute the number of individual rectangles to use
// we do the computation this way so that sizing the rebar band
// makes the size changes consistant
nRectsTotal = NUM_RECTANGLES_MAX;
nRectsTotal = (nVuWidth + (g_nAudMeterHeight - 1)) / g_nAudMeterHeight;
nRectsTotal = min(nRectsTotal, NUM_RECTANGLES_MAX);
nRectsTotal = max(nRectsTotal, NUM_RECTANGLES_MIN);
// nRectangleWidth - width of colored rectangle - no leading
nRectangleWidth = ((nVuWidth-2)/nRectsTotal) - 1;
// nVuWidth - width of entire VU meter including edges
nVuWidth = (nRectangleWidth + 1)*nRectsTotal + 2;
// re-adjust meter size to be an integral number of rects
nDiff = rect.right - (rect.left + nVuWidth);
rect.right = rect.left + nVuWidth;
// center vu-meter across whole channel area so that the
// slider's thumb is always covering some portion of the channel
rect.left += (nDiff/2);
rect.right += (nDiff/2);
// draw the 3D frame border
hOldPen = (HPEN) SelectObject (hdc, m_hHiLitePen);
MoveToEx(hdc, rect.right, rect.top, &ptOld);
LineTo(hdc, rect.right, rect.bottom);
LineTo(hdc, rect.left-1, rect.bottom); // -1 because LineTo stops just short of this point
SelectObject(hdc, m_hShadowPen);
MoveToEx(hdc, rect.left, rect.bottom-1, &pt);
LineTo(hdc, rect.left, rect.top);
LineTo(hdc, rect.right, rect.top);
SelectObject(hdc, m_hDkShadowPen);
MoveToEx(hdc, rect.left+1, rect.bottom-2, &pt);
LineTo(hdc, rect.left+1, rect.top+1);
LineTo(hdc, rect.right-1, rect.top+1);
SelectObject(hdc, m_hLitePen);
MoveToEx(hdc, rect.left+1, rect.bottom-1, &pt);
LineTo(hdc, rect.right-1, rect.bottom-1);
LineTo(hdc, rect.right-1, rect.top);
SelectObject(hdc, m_hShadowPen);
// the top and left of the meter has a 2 line border
// the bottom and right of the meter has a 2 line border
rectDraw.top = rect.top + 2;
rectDraw.bottom = rect.bottom - 1 ;
rectDraw.left = rect.left + 2;
rectDraw.right = rectDraw.left + nRectangleWidth;
// how many colored rectangles do we draw ?
nRects = (dwVolume * nRectsTotal) / 100;
// not transmitting - don't show anything
if ((false == bTransmitting) && (false == fSpeaker))
nRects = 0;
// transmitting or receiving something very quiet -
// light up at least one rectangle
else if ((bTransmitting) && (nRects == 0))
nRects = 1;
hCurrentBrush = m_hGreenBrush;
for (nIndex = 0; nIndex < nRectsTotal; nIndex++)
{
// far left fourth of the bar is green
// right fourth of the bar is red
// middle is yellow
if (nIndex > ((nRectsTotal*3)/4))
hCurrentBrush = m_hRedBrush;
else if (nIndex >= nRectsTotal/2)
hCurrentBrush = m_hYellowBrush;
if (nIndex >= nRects)
hCurrentBrush = m_hGreyBrush;
FillRect(hdc, &rectDraw, hCurrentBrush);
if (nIndex != (nRectsTotal-1))
{
MoveToEx(hdc, rectDraw.left + nRectangleWidth, rectDraw.top, &pt);
LineTo(hdc, rectDraw.left + nRectangleWidth, rectDraw.bottom);
}
rectDraw.left += nRectangleWidth + 1; // +1 for the leading
rectDraw.right = rectDraw.left + nRectangleWidth;
}
MoveToEx(hdc, ptOld.x, ptOld.y, &pt);
SelectObject (hdc, hOldPen);
if (bGotDC)
{
DeleteDC(hdc);
}
return TRUE;
}
BOOL CAudioLevel::OnTimer(WPARAM wTimerID)
{
DWORD dwLevel;
if (m_fVisible && (NULL != m_pAudioControl))
{
dwLevel = m_pAudioControl->GetAudioSignalLevel(FALSE /*fSpeaker*/); // This level ranges from 0-100
if (dwLevel != m_dwMicLvl)
{
m_dwMicLvl = dwLevel;
// HACK: SETRANGEMAX is the only way to force the slider to update itself...
SendMessage(m_hwndMicTrack, TBM_SETRANGEMAX, TRUE, g_nAudTrkRangeMax);
}
dwLevel = m_pAudioControl->GetAudioSignalLevel(TRUE /*fSpeaker*/); // This level ranges from 0-100
if (dwLevel != m_dwSpkLvl)
{
m_dwSpkLvl = dwLevel;
SendMessage(m_hwndSpkTrack, TBM_SETRANGEMAX, TRUE, g_nAudTrkRangeMax);
}
}
return TRUE;
}
// returns the coordinates of where one of the icons should be drawn
BOOL CAudioLevel::GetIconArea(BOOL fSpeaker, RECT *pRect)
{
int nIconY;
int nLeftMic;
int nLeftSpk;
nIconY = (m_rect.bottom - m_rect.top - g_nAudIconHeight - 1) / 2;
pRect->top = m_rect.top + nIconY;
pRect->bottom = pRect->top + g_nAudIconHeight;
if (fSpeaker)
{
pRect->left = m_rect.left + ((m_rect.right - m_rect.left) / 2) + g_nAudIconXMargin;
}
else
{
pRect->left = m_rect.left + g_nAudIconXMargin;
}
pRect->right = pRect->left + g_nAudIconWidth;
return TRUE;
}
BOOL CAudioLevel::PaintIcons(HDC hdc)
{
int nIconY;
ASSERT(hdc);
RECT rect;
if (NULL != m_hIconMic)
{
GetIconArea(FALSE, &rect);
DrawIconEx( hdc,
rect.left,
rect.top,
m_hIconMic,
rect.right - rect.left,
rect.bottom - rect.top,
0,
NULL,
DI_NORMAL);
}
if (NULL != m_hIconSpkr)
{
GetIconArea(TRUE, &rect);
DrawIconEx( hdc,
rect.left,
rect.top,
m_hIconSpkr,
rect.right - rect.left,
rect.bottom - rect.top,
0,
NULL,
DI_NORMAL);
}
return TRUE;
}
BOOL CAudioLevel::OnDeviceStatusChanged(BOOL fSpeaker, UINT uEvent, UINT uSubCode)
{
UINT uIconID;
HICON *phIcon;
UINT *puIconID;
RECT rectInvalid;
switch (uEvent)
{
case NM_STREAMEVENT_DEVICE_CLOSED:
{
uIconID = fSpeaker ? IDI_SPKEMPTY : IDI_MICEMPTY;
break;
}
case NM_STREAMEVENT_DEVICE_OPENED:
{
uIconID = fSpeaker ? IDI_SPEAKER : IDI_MICFONE;
break;
}
case NM_STREAMEVENT_DEVICE_FAILURE:
{
uIconID = fSpeaker ? IDI_SPKERROR : IDI_MICERROR;
break;
}
default:
return FALSE;
}
phIcon = fSpeaker ? &m_hIconSpkr : &m_hIconMic;
puIconID = fSpeaker ? &m_uIconSpkrID : &m_uIconMicID;
if (*puIconID == uIconID)
return TRUE;
*phIcon = (HICON) ::LoadImage( ::GetInstanceHandle(),
MAKEINTRESOURCE(uIconID),
IMAGE_ICON,
g_nAudIconWidth,
g_nAudIconHeight,
LR_DEFAULTCOLOR | LR_SHARED);
// invalidate the icon regions
if (m_hwndParentParent)
{
RECT rect;
GetIconArea(fSpeaker, &rect);
::MapWindowPoints(m_hwndParent, m_hwndParentParent, (LPPOINT) &rect, 2);
::InvalidateRect(m_hwndParentParent, &rect, TRUE /* erase bkgnd */);
::UpdateWindow(m_hwndParentParent);
}
return TRUE;
}
BOOL CAudioLevel::Resize(int nLeft, int nTop, int nWidth, int nHeight)
{
int nCBY, nTBY; // checkbox, trackbar, and Icon y positions
// Disable redraws:
ASSERT(m_hwndChkbRecMute && m_hwndChkbSpkMute && m_hwndMicTrack && m_hwndSpkTrack);
if (m_fVisible)
{
::SendMessage(m_hwndChkbRecMute, WM_SETREDRAW, FALSE, 0);
::SendMessage(m_hwndChkbSpkMute, WM_SETREDRAW, FALSE, 0);
::SendMessage(m_hwndMicTrack, WM_SETREDRAW, FALSE, 0);
::SendMessage(m_hwndSpkTrack, WM_SETREDRAW, FALSE, 0);
}
m_rect.left = nLeft;
m_rect.top = nTop;
m_rect.right = nLeft + nWidth;
m_rect.bottom = nTop + nHeight;
nCBY = (m_rect.bottom - m_rect.top - g_nAudChkbHeight) / 2;
if (nCBY < 0)
nCBY = 0;
// "+1" so the trackbar is better centered with the checkbox and icon
nTBY = (m_rect.bottom - m_rect.top - g_nAudTrkHeight + 1) / 2;
if (nTBY < 0)
nTBY = 0;
int nHalfPoint = nLeft + (nWidth / 2);
if (NULL != m_hwndChkbRecMute)
{
::MoveWindow( m_hwndChkbRecMute,
nLeft + g_nAudChkbXMargin,
nTop + nCBY,
g_nAudChkbWidth,
g_nAudChkbHeight,
TRUE /* repaint */);
}
if (NULL != m_hwndChkbSpkMute)
{
::MoveWindow( m_hwndChkbSpkMute,
nHalfPoint + g_nAudChkbXMargin,
nTop + nCBY,
g_nAudChkbWidth,
g_nAudChkbHeight,
TRUE /* repaint */);
}
m_fMicTrkVisible = m_fVisible;
if (NULL != m_hwndMicTrack)
{
int nMicTrkWidth = nHalfPoint - g_nAudTrkRightGap - (nLeft + g_nAudTrkXMargin);
::MoveWindow( m_hwndMicTrack,
nLeft + g_nAudTrkXMargin,
nTop + nTBY,
nMicTrkWidth,
g_nAudTrkHeight,
FALSE /* don't repaint */);
m_fMicTrkVisible = (nMicTrkWidth > g_nAudTrkMinWidth);
}
m_fSpkTrkVisible = m_fVisible;
if (NULL != m_hwndSpkTrack)
{
int nSpkTrkWidth = nLeft + nWidth - g_nAudTrkRightGap
- (nHalfPoint + g_nAudTrkXMargin);
::MoveWindow( m_hwndSpkTrack,
nHalfPoint + g_nAudTrkXMargin,
nTop + nTBY,
nSpkTrkWidth,
g_nAudTrkHeight,
FALSE /* don't repaint */);
m_fSpkTrkVisible = (nSpkTrkWidth > g_nAudTrkMinWidth);
}
// enable redraws
if (m_fVisible)
{
::SendMessage(m_hwndChkbRecMute, WM_SETREDRAW, TRUE, 0);
::SendMessage(m_hwndChkbSpkMute, WM_SETREDRAW, TRUE, 0);
// Enable redraws:
if (m_fMicTrkVisible)
{
::SendMessage(m_hwndMicTrack, WM_SETREDRAW, TRUE, 0);
}
if (m_fSpkTrkVisible)
{
::SendMessage(m_hwndSpkTrack, WM_SETREDRAW, TRUE, 0);
}
// Force the title area to repaint:
::InvalidateRect(m_hwndChkbRecMute, NULL, TRUE /* erase bkgnd */);
::InvalidateRect(m_hwndChkbSpkMute, NULL, TRUE /* erase bkgnd */);
::InvalidateRect(m_hwndMicTrack, NULL, TRUE /* erase bkgnd */);
::InvalidateRect(m_hwndSpkTrack, NULL, TRUE /* erase bkgnd */);
ASSERT(m_hwndParent);
ASSERT(m_hwndParentParent);
RECT rctTemp = m_rect;
::MapWindowPoints(m_hwndParent, m_hwndParentParent, (LPPOINT) &rctTemp, 2);
::InvalidateRect(m_hwndParentParent, &rctTemp, TRUE /* erase bkgnd */);
::UpdateWindow(m_hwndParentParent);
}
return TRUE;
}
BOOL CAudioLevel::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT *plRet)
{
LPNMCUSTOMDRAW pCustomDraw;
BOOL bRet = FALSE, fSpeaker;
RECT *pChannelRect;
*plRet = 0;
fSpeaker = (wParam == ID_AUDIODLG_SPKR_TRACK);
if (fSpeaker)
{
pChannelRect = &m_rcChannelSpk;
}
else
{
pChannelRect = &m_rcChannelMic;
}
pCustomDraw = (LPNMCUSTOMDRAW)lParam;
switch (pCustomDraw->dwDrawStage)
{
case CDDS_PREPAINT:
bRet = TRUE;
*plRet = CDRF_NOTIFYITEMDRAW | CDRF_NOTIFYPOSTPAINT;
break;
case CDDS_ITEMPREPAINT:
if (pCustomDraw->dwItemSpec == TBCD_CHANNEL)
{
*plRet = CDRF_SKIPDEFAULT;
bRet = TRUE;
pCustomDraw->rc.top -= 2;
pCustomDraw->rc.bottom += 2;
*pChannelRect = pCustomDraw->rc;
PaintChannel(fSpeaker, pCustomDraw->hdc);
}
break;
default:
break;
}
return bRet;
}
BOOL CAudioLevel::OnScroll(WPARAM wParam, LPARAM lParam)
{
BOOL bRet = FALSE;
if ((HWND) lParam == m_hwndMicTrack)
{
DWORD dwCurMicTrackPos = ::SendMessage((HWND) lParam, TBM_GETPOS, 0, 0);
if (m_dwMicTrackPos != dwCurMicTrackPos)
{
m_dwMicTrackPos = dwCurMicTrackPos;
m_pAudioControl->SetRecorderVolume(
(m_dwMicTrackPos * 0xFFFF) / g_nAudTrkRangeMax);
}
bRet = TRUE;
}
else if ((HWND) lParam == m_hwndSpkTrack)
{
DWORD dwCurSpkTrackPos = ::SendMessage((HWND) lParam, TBM_GETPOS, 0, 0);
if (m_dwSpkTrackPos != dwCurSpkTrackPos)
{
m_dwSpkTrackPos = dwCurSpkTrackPos;
m_pAudioControl->SetSpeakerVolume(
(m_dwSpkTrackPos * 0xFFFF) / g_nAudTrkRangeMax);
}
bRet = TRUE;
}
return bRet;
}
BOOL CAudioLevel::OnLevelChange(BOOL fSpeaker, DWORD dwVolume)
{
if (fSpeaker)
{
if (NULL != m_hwndSpkTrack)
{
DWORD dwTrackPos = ScaleMixer(dwVolume);
if (m_dwSpkTrackPos != dwTrackPos)
{
m_dwSpkTrackPos = dwTrackPos;
TRACE_OUT(("Setting Spk Volume to %d", m_dwSpkTrackPos));
::SendMessage( m_hwndSpkTrack,
TBM_SETPOS,
TRUE,
m_dwSpkTrackPos);
}
}
}
else
{
if (NULL != m_hwndMicTrack)
{
DWORD dwTrackPos = ScaleMixer(dwVolume);
if (m_dwMicTrackPos != dwTrackPos)
{
m_dwMicTrackPos = dwTrackPos;
TRACE_OUT(("Setting Mic Volume to %d", m_dwMicTrackPos));
::SendMessage( m_hwndMicTrack,
TBM_SETPOS,
TRUE,
m_dwMicTrackPos);
}
}
}
return TRUE;
}
BOOL CAudioLevel::OnDeviceChanged(void)
{
ASSERT(m_pAudioControl);
EnableWindow(m_hwndMicTrack, m_pAudioControl->CanSetRecorderVolume());
EnableWindow(m_hwndSpkTrack, m_pAudioControl->CanSetSpeakerVolume());
return TRUE;
}
BOOL CAudioLevel::Show(BOOL fVisible)
{
m_fVisible = fVisible;
if (m_fVisible)
{
// Start mic sensitivity timer:
::SetTimer(m_hwndParent, AUDIODLG_MIC_TIMER, AUDIODLG_MIC_TIMER_PERIOD, NULL);
}
else
{
// Stop mic sensitivity timer:
::KillTimer(m_hwndParent, AUDIODLG_MIC_TIMER);
}
// Hide or show all windows:
if (NULL != m_hwndChkbRecMute)
{
::ShowWindow(m_hwndChkbRecMute, fVisible ? SW_SHOW : SW_HIDE);
}
if (NULL != m_hwndChkbSpkMute)
{
::ShowWindow(m_hwndChkbSpkMute, fVisible ? SW_SHOW : SW_HIDE);
}
if (NULL != m_hwndMicTrack)
{
::ShowWindow(m_hwndMicTrack, (fVisible && m_fMicTrkVisible) ? SW_SHOW : SW_HIDE);
}
if (NULL != m_hwndSpkTrack)
{
::ShowWindow(m_hwndSpkTrack, (fVisible && m_fSpkTrkVisible) ? SW_SHOW : SW_HIDE);
}
return TRUE;
}