// 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::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(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(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)); } /**************************************************************************** * * 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); } } }