windows-nt/Source/XPSP1/NT/enduser/netmeeting/ui/conf/popupmsg.cpp
2020-09-26 16:20:57 +08:00

1190 lines
30 KiB
C++

// File: popupmsg.cpp
#include "precomp.h"
#include "resource.h"
#include "PopupMsg.h"
#include "conf.h"
#include "call.h"
#include "certui.h"
const int POPUPMSG_LEFT_MARGIN = 2;
const int POPUPMSG_TOP_MARGIN = 2;
const int POPUPMSG_CLIENT_MARGIN = 5;
const int POPUPMSG_ICON_GAP = 3;
const int POPUPMSG_WIDTH = 350;
const int POPUPMSG_HEIGHT = 32;
const int POPUPMSG_DLG_DEF_TEXT_WIDTH = 100;
const TCHAR g_cszTrayWndClass[] = _TEXT("Shell_TrayWnd");
const TCHAR g_cszTrayNotifyWndClass[] = _TEXT("TrayNotifyWnd");
extern GUID g_csguidSecurity;
///////////////////////////////////////////////////////////////////////////
UINT CPopupMsg::m_uVisiblePixels = 0;
/*static*/ CSimpleArray<CPopupMsg*>* CPopupMsg::m_splstPopupMsgs = NULL;
CPopupMsg::CPopupMsg(PMCALLBACKPROC pcp, LPVOID pContext):
m_pCallbackProc (pcp),
m_pContext (pContext),
m_fRing (FALSE),
m_hwnd (NULL),
m_hIcon (NULL),
m_fAutoSize (FALSE),
m_hInstance (NULL),
m_nWidth (0),
m_nHeight (0),
m_nTextWidth (POPUPMSG_DLG_DEF_TEXT_WIDTH)
{
TRACE_OUT(("Constructing CPopupMsg"));
if (NULL != m_splstPopupMsgs)
{
CPopupMsg* p = const_cast<CPopupMsg*>(this);
m_splstPopupMsgs->Add(p);
}
}
CPopupMsg::~CPopupMsg()
{
TRACE_OUT(("Destructing CPopupMsg"));
if (NULL != m_hIcon)
{
DestroyIcon(m_hIcon);
}
if (NULL != m_hwnd)
{
KillTimer(m_hwnd, POPUPMSG_TIMER);
KillTimer(m_hwnd, POPUPMSG_RING_TIMER);
DestroyWindow(m_hwnd);
if (m_fAutoSize)
{
m_uVisiblePixels -= m_nHeight;
}
}
if (NULL != m_splstPopupMsgs)
{
CPopupMsg* p = const_cast<CPopupMsg*>(this);
if( !m_splstPopupMsgs->Remove(p) )
{
TRACE_OUT(("CPopupMsg object is not in the list"));
}
}
}
/****************************************************************************
*
* CLASS: CPopupMsg
*
* MEMBER: PlaySound()
*
* PURPOSE: Plays the sound or beeps the system speaker
*
****************************************************************************/
VOID CPopupMsg::PlaySound()
{
if (FALSE == ::PlaySound(m_szSound, NULL,
SND_APPLICATION | SND_ALIAS | SND_ASYNC | SND_NOWAIT))
{
// Use the computer speaker to beep:
TRACE_OUT(("PlaySound() failed, trying MessageBeep()"));
::MessageBeep(0xFFFFFFFF);
}
}
/****************************************************************************
*
* CLASS: CPopupMsg
*
* MEMBER: Change(LPCTSTR)
*
* PURPOSE: Changes the text on an existing popup message
*
****************************************************************************/
BOOL CPopupMsg::Change(LPCTSTR pcszText)
{
BOOL bRet = FALSE;
// BUGBUG: doesn't handle dialog message
if (NULL != m_hwnd)
{
bRet = ::SetWindowText(m_hwnd, pcszText);
}
return bRet;
}
/****************************************************************************
*
* CLASS: CPopupMsg
*
* MEMBER: Init()
*
* PURPOSE: Allocates a static list of these objects
*
****************************************************************************/
BOOL CPopupMsg::Init()
{
ASSERT(NULL == m_splstPopupMsgs);
return (NULL != (m_splstPopupMsgs = new CSimpleArray<CPopupMsg*>));
}
/****************************************************************************
*
* CLASS: CPopupMsg
*
* MEMBER: Cleanup()
*
* PURPOSE: Removes all of the objects of this type
*
****************************************************************************/
VOID CPopupMsg::Cleanup()
{
if (NULL != m_splstPopupMsgs)
{
for( int i = 0; i < m_splstPopupMsgs->GetSize(); ++i )
{
ASSERT( (*m_splstPopupMsgs)[i] != NULL);
CPopupMsg *pThis = (*m_splstPopupMsgs)[i];
delete pThis;
}
delete m_splstPopupMsgs;
m_splstPopupMsgs = NULL;
}
}
/****************************************************************************
*
* CLASS: CPopupMsg
*
* MEMBER: PMWndProc(HWND, unsigned, WORD, LONG)
*
* PURPOSE:
*
****************************************************************************/
LRESULT CALLBACK CPopupMsg::PMWndProc(
HWND hWnd, /* window handle */
UINT message, /* type of message */
WPARAM wParam, /* additional information */
LPARAM lParam) /* additional information */
{
CPopupMsg* ppm;
LPCREATESTRUCT lpcs;
switch (message)
{
case WM_CREATE:
{
TRACE_OUT(("PopupMsg Window created"));
lpcs = (LPCREATESTRUCT) lParam;
ppm = (CPopupMsg*) lpcs->lpCreateParams;
ASSERT(ppm && "NULL object passed in WM_CREATE!");
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) ppm);
// Create a timer to make the window time-out and disappear:
::SetTimer(hWnd, POPUPMSG_TIMER, ppm->m_uTimeout, NULL);
// For now, if you pass a callback, you get ringing.
// If not, there is no ring
if (NULL != ppm->m_fPlaySound)
{
ppm->PlaySound();
if (NULL != ppm->m_fRing)
{
// Create a timer to make the ringer start:
::SetTimer(hWnd, POPUPMSG_RING_TIMER, POPUPMSG_RING_INTERVAL, NULL);
}
}
break;
}
case WM_TIMER:
{
ppm = (CPopupMsg*) GetWindowLongPtr(hWnd, GWLP_USERDATA);
if (POPUPMSG_TIMER == wParam)
{
// Message timed out:
if (NULL != ppm)
{
PMCALLBACKPROC pCallback;
if (NULL != (pCallback = ppm->m_pCallbackProc))
{
ppm->m_pCallbackProc = NULL;
pCallback(ppm->m_pContext, PMF_CANCEL | PMF_TIMEOUT);
}
// Self-destruct:
if (NULL != ppm->m_hwnd)
{
// NULL out the object pointer:
SetWindowLongPtr(hWnd, GWLP_USERDATA, 0L);
delete ppm;
}
}
}
else if (POPUPMSG_RING_TIMER == wParam)
{
if (NULL != ppm)
{
ppm->PlaySound();
}
// Create a timer to make it ring again:
::SetTimer( hWnd,
POPUPMSG_RING_TIMER,
POPUPMSG_RING_INTERVAL,
NULL);
}
break;
}
case WM_LBUTTONUP:
{
// Clicked on the message:
ppm = (CPopupMsg*) GetWindowLongPtr(hWnd, GWLP_USERDATA);
if (NULL != ppm)
{
::PlaySound(NULL, NULL, 0); // stop playing the ring sound
::KillTimer(ppm->m_hwnd, POPUPMSG_TIMER);
::KillTimer(ppm->m_hwnd, POPUPMSG_RING_TIMER);
PMCALLBACKPROC pCallback;
if (NULL != (pCallback = ppm->m_pCallbackProc))
{
ppm->m_pCallbackProc = NULL;
pCallback(ppm->m_pContext, PMF_OK);
}
// Self-destruct:
if (NULL != ppm->m_hwnd)
{
// NULL out the object pointer:
SetWindowLongPtr(hWnd, GWLP_USERDATA, 0L);
delete ppm;
}
}
break;
}
case WM_PAINT:
{
// Handle painting:
PAINTSTRUCT ps;
HDC hdc;
int nHorizTextOffset = POPUPMSG_LEFT_MARGIN;
if (hdc = ::BeginPaint(hWnd, &ps))
{
// Start by painting the icon (if needed)
ppm = (CPopupMsg*) ::GetWindowLongPtr(hWnd, GWLP_USERDATA);
if ((NULL != ppm) &&
(NULL != ppm->m_hIcon))
{
if (::DrawIconEx( hdc,
POPUPMSG_LEFT_MARGIN,
POPUPMSG_TOP_MARGIN,
ppm->m_hIcon,
POPUPMSG_ICON_WIDTH,
POPUPMSG_ICON_HEIGHT,
0,
NULL,
DI_NORMAL))
{
// We painted an icon, so make sure the text is shifted
// to the right by the right amount:
nHorizTextOffset += (POPUPMSG_ICON_WIDTH + POPUPMSG_ICON_GAP);
}
}
// Draw the text with a transparent background:
int bkOld = ::SetBkMode(hdc, TRANSPARENT);
COLORREF crOld = ::SetTextColor(hdc, ::GetSysColor(COLOR_WINDOWTEXT));
HFONT hFontOld = (HFONT) ::SelectObject(hdc, g_hfontDlg);
TCHAR szWinText[POPUPMSG_MAX_LENGTH];
szWinText[0] = _T('\0');
::GetWindowText(hWnd, szWinText, sizeof(szWinText));
RECT rctClient;
if (::GetClientRect(hWnd, &rctClient))
{
rctClient.left += nHorizTextOffset;
::DrawText( hdc, szWinText, -1, &rctClient,
DT_SINGLELINE | DT_NOCLIP | DT_VCENTER | DT_NOPREFIX);
}
::SetBkMode(hdc, bkOld);
::SetTextColor(hdc, crOld);
::SelectObject(hdc, hFontOld);
::EndPaint(hWnd, &ps);
}
break;
}
default:
{
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
return(FALSE);
}
/****************************************************************************
*
* CLASS: CPopupMsg
*
* MEMBER: PMDlgProc(HWND, UINT, WPARAM, LPARAM)
*
* PURPOSE: Handles messages associated with the incoming call dialog
*
****************************************************************************/
INT_PTR CALLBACK CPopupMsg::PMDlgProc( HWND hDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
CPopupMsg* ppm;
switch (uMsg)
{
case WM_INITDIALOG:
{
TRACE_OUT(("PopupMsg Window created"));
AddModelessDlg(hDlg);
ppm = (CPopupMsg*) lParam;
ASSERT(ppm && "NULL object passed in WM_INITDIALOG!");
::SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR) ppm);
TRACE_OUT(("CPopupMsg m_nTextWidth=%d in WM_INITDIALOG", ppm->m_nTextWidth));
// If the dialog is too big, then resize the text width.
RECT rctDlg;
RECT rctDesk;
HWND hwndDesk;
if (::GetWindowRect(hDlg, &rctDlg) &&
(hwndDesk = ::GetDesktopWindow()) &&
::GetWindowRect(hwndDesk, &rctDesk))
{
int nDlgWidth = rctDlg.right - rctDlg.left;
ppm->m_nTextWidth -= max( 0,
nDlgWidth + ppm->m_nTextWidth -
(rctDesk.right - rctDesk.left));
}
RECT rctCtrl;
// Move the "Authenticate" button, if it's there
HWND hwndAuth = ::GetDlgItem(hDlg, IDB_AUTH);
if ((NULL != hwndAuth) && ::GetWindowRect(hwndAuth, &rctCtrl)) {
// Turn rctCtrl's top and left into client coords:
::MapWindowPoints(NULL, hDlg, (LPPOINT) &rctCtrl, 1);
::SetWindowPos( hwndAuth,
NULL,
rctCtrl.left + ppm->m_nTextWidth,
rctCtrl.top,
0, 0,
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE | SWP_NOREDRAW);
}
// Move the "Accept" button (IDOK)
HWND hwndOK = ::GetDlgItem(hDlg, IDOK);
if ((NULL != hwndOK) && ::GetWindowRect(hwndOK, &rctCtrl))
{
// Turn rctCtrl's top and left into client coords:
::MapWindowPoints(NULL, hDlg, (LPPOINT) &rctCtrl, 1);
::SetWindowPos( hwndOK,
NULL,
rctCtrl.left + ppm->m_nTextWidth,
rctCtrl.top,
0, 0,
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE | SWP_NOREDRAW);
}
// Move the "Ignore" button (IDCANCEL)
HWND hwndCancel = ::GetDlgItem(hDlg, IDCANCEL);
if ((NULL != hwndCancel) && ::GetWindowRect(hwndCancel, &rctCtrl))
{
// Turn rctCtrl's top and left into client coords:
::MapWindowPoints(NULL, hDlg, (LPPOINT) &rctCtrl, 1);
::SetWindowPos( hwndCancel,
NULL,
rctCtrl.left + ppm->m_nTextWidth,
rctCtrl.top,
0, 0,
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE | SWP_NOREDRAW);
}
// Stretch the text field:
HWND hwndText = ::GetDlgItem(hDlg, IDC_MSG_STATIC);
if ((NULL != hwndText) && ::GetWindowRect(hwndText, &rctCtrl))
{
::SetWindowPos( hwndText,
NULL,
0, 0,
ppm->m_nTextWidth,
rctCtrl.bottom - rctCtrl.top,
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE | SWP_NOREDRAW);
// and set the font
::SendMessage(hwndText, WM_SETFONT, (WPARAM) g_hfontDlg, 0);
}
// Create a timer to make the window time-out and disappear:
::SetTimer(hDlg, POPUPMSG_TIMER, ppm->m_uTimeout, NULL);
// For now, if you pass a callback, you get ringing.
// If not, there is no ring
if (NULL != ppm->m_fPlaySound)
{
ppm->PlaySound();
if (NULL != ppm->m_fRing)
{
// Create a timer to make the ringer start:
::SetTimer(hDlg, POPUPMSG_RING_TIMER, POPUPMSG_RING_INTERVAL, NULL);
}
}
return TRUE;
}
case WM_TIMER:
{
ppm = (CPopupMsg*) GetWindowLongPtr(hDlg, GWLP_USERDATA);
if (POPUPMSG_TIMER == wParam)
{
// Message timed out:
if (NULL != ppm)
{
PMCALLBACKPROC pCallback;
if (NULL != (pCallback = ppm->m_pCallbackProc))
{
ppm->m_pCallbackProc = NULL;
// hide the dialog in case the callback doesn't
// return immediately
::ShowWindow(ppm->m_hwnd, SW_HIDE);
pCallback(ppm->m_pContext, PMF_CANCEL | PMF_TIMEOUT);
}
// Self-destruct:
if (NULL != ppm->m_hwnd)
{
// NULL out the object pointer:
SetWindowLongPtr(hDlg, GWLP_USERDATA, 0L);
delete ppm;
}
}
}
else if (POPUPMSG_RING_TIMER == wParam)
{
if (NULL != ppm)
{
ppm->PlaySound();
}
// Create a timer to make it ring again:
::SetTimer( hDlg,
POPUPMSG_RING_TIMER,
POPUPMSG_RING_INTERVAL,
NULL);
}
return TRUE;
}
case WM_COMMAND:
{
// Clicked on one of the buttons:
ppm = (CPopupMsg*) GetWindowLongPtr(hDlg, GWLP_USERDATA);
if (NULL != ppm)
{
// stop playing the ring sound
::PlaySound(NULL, NULL, 0);
::KillTimer(ppm->m_hwnd, POPUPMSG_RING_TIMER);
::KillTimer(ppm->m_hwnd, POPUPMSG_TIMER);
PMCALLBACKPROC pCallback;
if (NULL != (pCallback = ppm->m_pCallbackProc))
{
ppm->m_pCallbackProc = NULL; // prevent this from firing twice
// hide the dialog in case the callback doesn't
// return immediately
::ShowWindow(ppm->m_hwnd, SW_HIDE);
pCallback(ppm->m_pContext,
(IDB_AUTH == LOWORD(wParam)) ? PMF_AUTH : (IDOK == LOWORD(wParam)) ? PMF_OK : PMF_CANCEL);
}
// Self-destruct:
if (NULL != ppm->m_hwnd)
{
// NULL out the object pointer:
SetWindowLongPtr(hDlg, GWLP_USERDATA, 0L);
delete ppm;
}
}
return TRUE;
}
case WM_DESTROY:
{
::RemoveModelessDlg(hDlg);
break;
}
default:
break;
} /* switch (uMsg) */
return FALSE;
}
/****************************************************************************
*
* CLASS: CPopupMsg
*
* MEMBER: SecurePMDlgProc(HWND, UINT, WPARAM, LPARAM)
*
* PURPOSE: Handles messages associated with the incoming call dialog
*
****************************************************************************/
INT_PTR CALLBACK CPopupMsg::SecurePMDlgProc( HWND hDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
CPopupMsg* ppm;
switch (uMsg)
{
case WM_INITDIALOG:
{
TRACE_OUT(("PopupMsg Window created"));
AddModelessDlg(hDlg);
ppm = (CPopupMsg*) lParam;
ASSERT(ppm && "NULL object passed in WM_INITDIALOG!");
::SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR) ppm);
TRACE_OUT(("CPopupMsg m_nTextWidth=%d in WM_INITDIALOG", ppm->m_nTextWidth));
RegEntry re(UI_KEY, HKEY_CURRENT_USER);
if (1 == re.GetNumber(REGVAL_SHOW_SECUREDETAILS, DEFAULT_SHOW_SECUREDETAILS)) {
ExpandSecureDialog(hDlg,ppm);
}
// Create a timer to make the window time-out and disappear:
::SetTimer(hDlg, POPUPMSG_TIMER, ppm->m_uTimeout, NULL);
// For now, if you pass a callback, you get ringing.
// If not, there is no ring
if (NULL != ppm->m_fPlaySound)
{
ppm->PlaySound();
if (NULL != ppm->m_fRing)
{
// Create a timer to make the ringer start:
::SetTimer(hDlg, POPUPMSG_RING_TIMER, POPUPMSG_RING_INTERVAL, NULL);
}
}
return TRUE;
}
case WM_TIMER:
{
ppm = (CPopupMsg*) GetWindowLongPtr(hDlg, GWLP_USERDATA);
if (POPUPMSG_TIMER == wParam)
{
// Message timed out:
if (NULL != ppm)
{
PMCALLBACKPROC pCallback;
if (NULL != (pCallback = ppm->m_pCallbackProc))
{
ppm->m_pCallbackProc = NULL;
// hide the dialog in case the callback doesn't
// return immediately
::ShowWindow(ppm->m_hwnd, SW_HIDE);
pCallback(ppm->m_pContext, PMF_CANCEL | PMF_TIMEOUT);
}
// Self-destruct:
if (NULL != ppm->m_hwnd)
{
// NULL out the object pointer:
SetWindowLongPtr(hDlg, GWLP_USERDATA, 0L);
delete ppm;
}
}
}
else if (POPUPMSG_RING_TIMER == wParam)
{
if (NULL != ppm)
{
ppm->PlaySound();
}
// Create a timer to make it ring again:
::SetTimer( hDlg,
POPUPMSG_RING_TIMER,
POPUPMSG_RING_INTERVAL,
NULL);
}
return TRUE;
}
case WM_COMMAND:
{
ppm = (CPopupMsg*) GetWindowLongPtr(hDlg, GWLP_USERDATA);
switch (LOWORD(wParam)) {
case IDOK:
case IDCANCEL:
// Clicked on one of the buttons:
if (NULL != ppm)
{
// stop playing the ring sound
::PlaySound(NULL, NULL, 0);
::KillTimer(ppm->m_hwnd, POPUPMSG_RING_TIMER);
::KillTimer(ppm->m_hwnd, POPUPMSG_TIMER);
PMCALLBACKPROC pCallback;
if (NULL != (pCallback = ppm->m_pCallbackProc))
{
ppm->m_pCallbackProc = NULL; // prevent this from firing twice
// hide the dialog in case the callback doesn't
// return immediately
::ShowWindow(ppm->m_hwnd, SW_HIDE);
pCallback(ppm->m_pContext, (IDOK == LOWORD(wParam)) ? PMF_OK : PMF_CANCEL);
}
// Self-destruct:
if (NULL != ppm->m_hwnd)
{
// NULL out the object pointer:
SetWindowLongPtr(hDlg, GWLP_USERDATA, 0L);
delete ppm;
}
}
break;
case IDB_DETAILS:
RegEntry re(UI_KEY, HKEY_CURRENT_USER);
if (1 == re.GetNumber(REGVAL_SHOW_SECUREDETAILS,DEFAULT_SHOW_SECUREDETAILS)) {
// Currently expanded, so shrink
re.SetValue(REGVAL_SHOW_SECUREDETAILS,(DWORD)0);
ShrinkSecureDialog(hDlg);
}
else {
// Currently shrunk, so expand
re.SetValue(REGVAL_SHOW_SECUREDETAILS,1);
ExpandSecureDialog(hDlg,ppm);
}
break;
}
return TRUE;
}
case WM_DESTROY:
{
::RemoveModelessDlg(hDlg);
break;
}
default:
break;
} /* switch (uMsg) */
return FALSE;
}
/****************************************************************************
*
* CLASS: CPopupMsg
*
* MEMBER: Create()
*
* PURPOSE: Creates a popup message window
*
****************************************************************************/
HWND CPopupMsg::Create( LPCTSTR pcszText, BOOL fRing, LPCTSTR pcszIconName,
HINSTANCE hInstance, UINT uIDSoundEvent,
UINT uTimeout, int xCoord, int yCoord)
{
ASSERT(pcszText);
m_fRing = fRing;
m_fPlaySound = (BOOL) uIDSoundEvent;
m_uTimeout = uTimeout;
// First try to load the icon:
m_hInstance = hInstance;
if ((NULL != m_hInstance) && (NULL != pcszIconName))
{
m_hIcon = (HICON) LoadImage(m_hInstance,
pcszIconName,
IMAGE_ICON,
POPUPMSG_ICON_WIDTH,
POPUPMSG_ICON_HEIGHT,
LR_DEFAULTCOLOR);
}
else
{
m_hIcon = NULL;
}
if ((NULL == m_hInstance) ||
(!::LoadString( m_hInstance,
uIDSoundEvent,
m_szSound,
CCHMAX(m_szSound))))
{
m_szSound[0] = _T('\0');
}
// initialize window size with default values:
m_nWidth = POPUPMSG_WIDTH;
m_nHeight = POPUPMSG_HEIGHT;
HWND hwndDesktop = GetDesktopWindow();
if (NULL != hwndDesktop)
{
RECT rctDesktop;
::GetWindowRect(hwndDesktop, &rctDesktop);
HDC hdc = GetDC(hwndDesktop);
if (NULL != hdc)
{
HFONT hFontOld = (HFONT) SelectObject(hdc, g_hfontDlg);
SIZE size;
if (GetTextExtentPoint32(hdc, pcszText, lstrlen(pcszText), &size))
{
// don't make it wider than the desktop
m_nWidth = min( rctDesktop.right - rctDesktop.left,
size.cx + (2 * POPUPMSG_CLIENT_MARGIN));
m_nHeight = size.cy + (2 * POPUPMSG_CLIENT_MARGIN);
// If we have succesfully loaded an icon, make size
// adjustments:
if (NULL != m_hIcon)
{
m_nWidth += POPUPMSG_ICON_WIDTH + POPUPMSG_ICON_GAP;
if (size.cy < POPUPMSG_ICON_HEIGHT)
{
m_nHeight = POPUPMSG_ICON_HEIGHT +
(2 * POPUPMSG_CLIENT_MARGIN);
}
}
}
// Reselect old font
SelectObject(hdc, hFontOld);
ReleaseDC(hwndDesktop, hdc);
}
POINT pt;
GetIdealPosition(&pt, xCoord, yCoord);
m_hwnd = CreateWindowEx(WS_EX_PALETTEWINDOW,
g_szPopupMsgWndClass,
pcszText,
WS_POPUP | /* WS_VISIBLE |*/ WS_DLGFRAME,
pt.x, pt.y,
m_nWidth, m_nHeight,
NULL,
NULL,
::GetInstanceHandle(),
(LPVOID) this);
if (m_fAutoSize)
{
m_uVisiblePixels += m_nHeight;
}
// Show, but don't activate
::ShowWindow(m_hwnd, SW_SHOWNA);
// Repaint
::UpdateWindow(m_hwnd);
return m_hwnd;
}
// Something went wrong
return NULL;
}
/****************************************************************************
*
* CLASS: CPopupMsg
*
* MEMBER: CreateDlg()
*
* PURPOSE: Creates a popup dialog message window
*
****************************************************************************/
HWND CPopupMsg::CreateDlg( LPCTSTR pcszText, BOOL fRing, LPCTSTR pcszIconName,
HINSTANCE hInstance, UINT uIDSoundEvent,
UINT uTimeout, int xCoord, int yCoord)
{
ASSERT(pcszText);
m_fRing = fRing;
m_fPlaySound = (BOOL) uIDSoundEvent;
m_uTimeout = uTimeout;
// First try to load the icon:
m_hInstance = hInstance;
if ((NULL != m_hInstance) && (NULL != pcszIconName))
{
m_hIcon = (HICON) LoadImage(m_hInstance,
pcszIconName,
IMAGE_ICON,
POPUPMSG_ICON_WIDTH,
POPUPMSG_ICON_HEIGHT,
LR_DEFAULTCOLOR);
}
else
{
m_hIcon = NULL;
}
if ((NULL == m_hInstance) ||
(!::LoadString( m_hInstance,
uIDSoundEvent,
m_szSound,
sizeof(m_szSound))))
{
m_szSound[0] = _T('\0');
}
// init with large defaults in case getwindowrect fails
RECT rctDesktop = { 0x0000, 0x0000, 0xFFFF, 0xFFFF };
HWND hwndDesktop = GetDesktopWindow();
if (NULL != hwndDesktop)
{
::GetWindowRect(hwndDesktop, &rctDesktop);
HDC hdc = GetDC(hwndDesktop);
if (NULL != hdc)
{
HFONT hFontOld = (HFONT) SelectObject(hdc, g_hfontDlg);
SIZE size;
if (::GetTextExtentPoint32(hdc, pcszText, lstrlen(pcszText), &size))
{
m_nTextWidth = size.cx;
}
::SelectObject(hdc, hFontOld);
::ReleaseDC(hwndDesktop, hdc);
}
}
KillScrnSaver();
INmCall * pCall = NULL;
PBYTE pb = NULL;
ULONG cb = 0;
int id;
if (m_pContext != NULL) {
pCall = ((CCall *)m_pContext)->GetINmCall();
}
if (NULL != pCall && S_OK == pCall->GetUserData(g_csguidSecurity,&pb,&cb)) {
// This is an encrypted call
CoTaskMemFree(pb);
id = IDD_SECURE_INCOMING_CALL;
m_hwnd = ::CreateDialogParam(m_hInstance, MAKEINTRESOURCE(id),
::GetMainWindow(),CPopupMsg::SecurePMDlgProc,(LPARAM) this);
}
else {
id = IDD_INCOMING_CALL;
m_hwnd = ::CreateDialogParam(m_hInstance, MAKEINTRESOURCE(id),
::GetMainWindow(),CPopupMsg::PMDlgProc,(LPARAM) this);
}
if (NULL != m_hwnd)
{
::SetDlgItemText(m_hwnd, IDC_MSG_STATIC, pcszText);
RECT rctDlg;
::GetWindowRect(m_hwnd, &rctDlg);
// Stretch the width to fit the person's name,
// but not wider than the desktop.
// int nDeskWidth = rctDesktop.right - rctDesktop.left;
// Resize the non-secure dialog
m_nWidth = (rctDlg.right - rctDlg.left) + ((IDD_INCOMING_CALL == id) ? m_nTextWidth : 0);
// if (m_nWidth > nDeskWidth)
// {
// m_nTextWidth -= (m_nWidth - nDeskWidth);
// m_nWidth = nDeskWidth;
// }
m_nHeight = rctDlg.bottom - rctDlg.top;
POINT pt;
GetIdealPosition(&pt, xCoord, yCoord);
// Show, move, make topmost, but don't activate
::SetWindowPos( m_hwnd,
HWND_TOPMOST,
pt.x,
pt.y,
m_nWidth,
m_nHeight,
SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_DRAWFRAME);
if (m_fAutoSize)
{
m_uVisiblePixels += m_nHeight;
}
}
return m_hwnd;
}
BOOL CPopupMsg::GetIdealPosition(LPPOINT ppt, int xCoord, int yCoord)
{
ASSERT(ppt);
BOOL bRet = FALSE;
HWND hwndDesktop = GetDesktopWindow();
RECT rctDesktop;
if (NULL != hwndDesktop)
{
int yBottomofTrayRect = 0;
if ((-1 == xCoord) && (-1 == yCoord))
{
m_fAutoSize = TRUE;
// BUGBUG: We search for the tray notification window by looking for
// hard coded window class names. This is safe if we're running
// Win 95 build 950.6, but maybe not otherwise...
HWND hwndTray = FindWindowEx(NULL, NULL, g_cszTrayWndClass, NULL);
if (NULL != hwndTray)
{
HWND hwndTrayNotify = FindWindowEx(hwndTray, NULL, g_cszTrayNotifyWndClass, NULL);
if (NULL != hwndTrayNotify)
{
RECT rctTrayNotify;
if (GetWindowRect(hwndTrayNotify, &rctTrayNotify))
{
xCoord = rctTrayNotify.right;
yCoord = rctTrayNotify.top;
yBottomofTrayRect = rctTrayNotify.bottom;
}
}
}
}
if (GetWindowRect(hwndDesktop, &rctDesktop))
{
// Make sure that xCoord and yCoord are on the screen (bugs 1817,1819):
xCoord = min(rctDesktop.right, xCoord);
xCoord = max(rctDesktop.left, xCoord);
yCoord = min(rctDesktop.bottom, yCoord);
yCoord = max(rctDesktop.top, yCoord);
// First attempt will be to center the toolbar horizontally
// with respect to the mouse position and place it directly
// above vertically.
ppt->x = xCoord - (m_nWidth / 2);
// Make the window higher if there are exisiting visible messages
ppt->y = yCoord - m_uVisiblePixels - m_nHeight;
// If we are too high on the screen (the taskbar is probably
// docked on top), then use the click position as the top of
// where the toolbar will appear.
if (ppt->y < 0)
{
ppt->y = yCoord;
// Even better, if we have found the tray rect and we know that
// we have docked on top, then use the bottom of the rect instead
// of the top
if (0 != yBottomofTrayRect)
{
ppt->y = yBottomofTrayRect;
// Make the window lower if there are
// exisiting visible messages
ppt->y += m_uVisiblePixels;
}
}
// Repeat the same logic for the horizontal position
if (ppt->x < 0)
{
ppt->x = xCoord;
}
// If the toolbar if off the screen to the right, then right-justify it
if (ppt->x > (rctDesktop.right - m_nWidth))
{
ppt->x = max(0, xCoord - m_nWidth);
}
bRet = TRUE;
}
}
return bRet;
}
VOID CPopupMsg::ExpandSecureDialog(HWND hDlg,CPopupMsg * ppm)
{
RECT rect, editrect;
// Change the dialog to the expanded version.
if (GetWindowRect(hDlg,&rect) &&
GetWindowRect(GetDlgItem(hDlg,IDC_SECURE_CALL_EDIT),&editrect)) {
int nHeight = rect.bottom - rect.top;
int nWidth = rect.right - rect.left;
//
// Grow by height of edit control plus 7 dialog unit margin as
// given by edit control offset within control:
//
int deltaHeight = ( editrect.bottom - editrect.top ) +
( editrect.left - rect.left );
SetWindowPos(hDlg,NULL,
rect.left,(rect.top - deltaHeight > 0 ? rect.top - deltaHeight : 0),
nWidth,nHeight + deltaHeight, SWP_NOZORDER);
// Make the edit box visible.
HWND hEditBox = GetDlgItem(hDlg, IDC_SECURE_CALL_EDIT);
if (hEditBox != NULL) {
ShowWindow(hEditBox,SW_SHOW);
EnableWindow(hEditBox, TRUE);
// Get security information, if any.
if (NULL != ppm) {
INmCall * pCall = NULL;
PBYTE pb = NULL;
ULONG cb = 0;
if (NULL != ppm->m_pContext) {
pCall = ((CCall *)ppm->m_pContext)->GetINmCall();
}
if (NULL != pCall && S_OK == pCall->GetUserData(g_csguidSecurity,&pb,&cb)) {
ASSERT(pb);
ASSERT(cb);
if ( TCHAR * pCertText = FormatCert( pb, cb )) {
SetDlgItemText(hDlg,IDC_SECURE_CALL_EDIT,pCertText);
delete pCertText;
}
else {
ERROR_OUT(("FormatCert failed"));
}
CoTaskMemFree(pb);
}
}
}
// Move the buttons southward.
HWND hButton = GetDlgItem(hDlg, IDOK);
if (hButton && GetWindowRect(hButton,&rect)) {
MapWindowPoints(HWND_DESKTOP,hDlg,(LPPOINT)&rect,2);
SetWindowPos(hButton,NULL,rect.left,rect.top + deltaHeight,0,0,
SWP_NOZORDER | SWP_NOSIZE);
}
hButton = GetDlgItem(hDlg, IDCANCEL);
if (hButton && GetWindowRect(hButton,&rect)) {
MapWindowPoints(HWND_DESKTOP,hDlg,(LPPOINT)&rect,2);
SetWindowPos(hButton,NULL,rect.left,rect.top + deltaHeight,0,0,
SWP_NOZORDER | SWP_NOSIZE);
}
hButton = GetDlgItem(hDlg, IDB_DETAILS);
if (hButton && GetWindowRect(hButton,&rect)) {
MapWindowPoints(HWND_DESKTOP,hDlg,(LPPOINT)&rect,2);
SetWindowPos(hButton,NULL,rect.left,rect.top + deltaHeight,0,0,
SWP_NOZORDER | SWP_NOSIZE);
// Change text on Details button
TCHAR lpButtonString[MAX_PATH];
::FLoadString(IDS_SECURITY_NODETAILS, lpButtonString, MAX_PATH);
SetDlgItemText(hDlg,IDB_DETAILS,lpButtonString);
}
}
}
VOID CPopupMsg::ShrinkSecureDialog(HWND hDlg)
{
RECT rect,editrect;
// Change the dialog to the normal version.
if (GetWindowRect(hDlg,&rect) &&
GetWindowRect(GetDlgItem(hDlg,IDC_SECURE_CALL_EDIT),&editrect)) {
int nHeight = rect.bottom - rect.top;
int nWidth = rect.right - rect.left;
//
// Grow by height of edit control plus 7 dialog unit margin as
// given by edit control offset within control:
//
int deltaHeight = ( editrect.bottom - editrect.top ) +
( editrect.left - rect.left );
SetWindowPos(hDlg,NULL,
rect.left,(rect.top - deltaHeight > 0 ? rect.top + deltaHeight : 0),
nWidth,nHeight - deltaHeight,SWP_NOZORDER);
// Make the edit box invisible.
HWND hEditBox = GetDlgItem(hDlg, IDC_SECURE_CALL_EDIT);
if (hEditBox != NULL) {
ShowWindow(hEditBox,SW_HIDE);
EnableWindow(hEditBox,FALSE);
}
// Move the buttons northward.
HWND hButton = GetDlgItem(hDlg, IDOK);
if (hButton && GetWindowRect(hButton,&rect)) {
MapWindowPoints(HWND_DESKTOP,hDlg,(LPPOINT)&rect,2);
SetWindowPos(hButton,NULL,rect.left,rect.top - deltaHeight,0,0,
SWP_NOZORDER | SWP_NOSIZE);
}
hButton = GetDlgItem(hDlg, IDCANCEL);
if (hButton && GetWindowRect(hButton,&rect)) {
MapWindowPoints(HWND_DESKTOP,hDlg,(LPPOINT)&rect,2);
SetWindowPos(hButton,NULL,rect.left,rect.top - deltaHeight,0,0,
SWP_NOZORDER | SWP_NOSIZE);
}
hButton = GetDlgItem(hDlg, IDB_DETAILS);
if (hButton && GetWindowRect(hButton,&rect)) {
MapWindowPoints(HWND_DESKTOP,hDlg,(LPPOINT)&rect,2);
SetWindowPos(hButton,NULL,rect.left,rect.top - deltaHeight,0,0,
SWP_NOZORDER | SWP_NOSIZE);
TCHAR lpButtonString[MAX_PATH];
::FLoadString(IDS_SECURITY_DETAILS, lpButtonString, MAX_PATH);
SetDlgItemText(hDlg,IDB_DETAILS,lpButtonString);
}
}
}