//+---------------------------------------------------------------------------- // // File: StatusDlg.cpp // // Module: CMMON32.EXE // // Synopsis: Implement status/count-down dialog class CStatusDlg // // Copyright (c) 1998-1999 Microsoft Corporation // // Author: ????? Created 02/20/98 // //+---------------------------------------------------------------------------- #include "cmmaster.h" #include "StatusDlg.h" #include "Connection.h" #include "resource.h" #include "Monitor.h" #include "cmmgr32.h" // help IDs #include "cm_misc.h" #include "resource.h" // // Map of control id to help id // const DWORD CStatusDlg::m_dwHelp[] = {IDOK, IDH_OK_CONNECTED, IDC_DISCONNECT, IDH_STATUS_DISCONNECT, IDC_DETAILS, IDH_DETAILS, 0,0}; //+---------------------------------------------------------------------------- // // Function: CStatusDlg::CStatusDlg // // Synopsis: Constructor // // Arguments: CCmConnection* pConnection - The connection to notify event // // Returns: Nothing // // History: Created Header 2/20/98 // //+---------------------------------------------------------------------------- CStatusDlg::CStatusDlg(CCmConnection* pConnection):CModelessDlg(m_dwHelp) { m_pConnection = pConnection; m_fDisplayStatus = FALSE; m_fStatusWindowVisible = FALSE; } //+---------------------------------------------------------------------------- // // Function: CStatusDlg::Create // // Synopsis: Create a modeless status dialog // // Arguments: HINSTANCE hInstance - Instance of the resource // HWND hWndParent - Parent window // LPCTSTR lpszTitle - Dialog window title // HICON hIcon - Dialog icon // // Returns: HWND - The dialog window handle // // History: Created Header 2/20/98 // //+---------------------------------------------------------------------------- HWND CStatusDlg::Create(HINSTANCE hInstance, HWND hWndParent, LPCTSTR lpszTitle, HICON hIcon) { MYDBGASSERT(lpszTitle); MYDBGASSERT(hIcon); DWORD dwStatusDlgId = OS_NT4 ? IDD_CONNSTATNT4 : IDD_CONNSTAT; if (!CModelessDlg::Create(hInstance, dwStatusDlgId, hWndParent)) { MYDBGASSERT(FALSE); return NULL; } EnableWindow(m_hWnd, FALSE); UpdateFont(m_hWnd); SetWindowTextU(m_hWnd,lpszTitle); SendDlgItemMessageA(m_hWnd,IDC_CONNSTAT_ICON,STM_SETIMAGE, IMAGE_ICON,(LPARAM) hIcon); MakeBold(GetDlgItem(m_hWnd,IDC_CONNSTAT_DISCONNECT_DISPLAY), FALSE); m_uiHwndMsgTaskBar = RegisterWindowMessageA("TaskbarCreated"); return m_hWnd; } //+---------------------------------------------------------------------------- // // Function: CStatusDlg::OnInitDialog // // Synopsis: Called when dialog is intialized and WM_INITDIALOG is received. // // Arguments: None // // Returns: BOOL - FALSE is focus was assigned to a control. // // History: nickball 03/22/00 Created // //+---------------------------------------------------------------------------- BOOL CStatusDlg::OnInitDialog() { SetForegroundWindow(m_hWnd); return FALSE; } //+---------------------------------------------------------------------------- // // Function: CStatusDlg::OnOtherCommand // // Synopsis: Process WM_COMMAND other than IDOK and IDCANCEL // // Arguments: WPARAM wParam - wParam of the message // LPARAM - // // Returns: DWORD - Return value of the message // // History: fengsun Created Header 2/20/98 // //+---------------------------------------------------------------------------- DWORD CStatusDlg::OnOtherCommand(WPARAM wParam, LPARAM) { switch (LOWORD(wParam)) { case IDC_DISCONNECT: KillRasMonitorWindow(); // // The thread message loop will handle thread message // PostThreadMessageU(GetCurrentThreadId(), CCmConnection::WM_CONN_EVENT, CCmConnection::EVENT_USER_DISCONNECT, 0); break; case IDC_DETAILS: m_pConnection->OnStatusDetails(); break; case IDMC_TRAY_STATUS: // // Don't show the UI if we are at Winlogon unless we are on NT4 // if (!IsLogonAsSystem() || OS_NT4) { BringToTop(); } break; case WM_DESTROY: ReleaseBold(GetDlgItem(m_hWnd, IDC_CONNSTAT_DISCONNECT_DISPLAY)); break; default: // // Should be message comes from additional tray icon menu item // if (LOWORD(wParam) >= CCmConnection::IDM_TRAYMENU && LOWORD(wParam) <= (CCmConnection::IDM_TRAYMENU + 100)) { m_pConnection->OnAdditionalTrayMenu(LOWORD(wParam)); } break; } return FALSE; } //+---------------------------------------------------------------------------- // // Function: CStatusDlg::OnOtherMessage // // Synopsis: Process message other than WM_COMMAND and WM_INITDIALOG // // Arguments: UINT uMsg - the message // WPARAM wParam - wParam of the message // LPARAM lParam - lParam of the message // // Returns: DWORD - return value of the message // // History: Created Header 2/20/98 // //+---------------------------------------------------------------------------- DWORD CStatusDlg::OnOtherMessage(UINT uMsg, WPARAM wParam, LPARAM lParam ) { switch (uMsg) { case CCmConnection::WM_TRAYICON: return m_pConnection->OnTrayIcon(wParam, lParam); case WM_TIMER: // CMMON does not use WM_TIMER MYDBGASSERT(0); return 0; case WM_SHOWWINDOW: if (wParam) //fShow == TRUE { // // Statistics is not updated if window is invisible. // Force a update of statistics now. // m_pConnection->StateConnectedOnTimer(); } break; default: if (uMsg == m_uiHwndMsgTaskBar && !m_pConnection->IsTrayIconHidden()) { // // we need to re-add the trayicon // m_pConnection->ReInstateTrayIcon(); } break; } return FALSE; } //+---------------------------------------------------------------------------- // // Function: CStatusDlg::OnCancel // // Synopsis: Virtual function. Process WM_COMMAND IDCANCEL // // Arguments: None // // Returns: Nothing // // History: fengsun Created Header 2/20/98 // //+---------------------------------------------------------------------------- void CStatusDlg::OnCancel() { // // Even through, the status dialog does not have a cancel button, this message // is send when user click Esc, or close from system menu // // // As if OK/StayOnLine is clicked // OnOK(); } //+---------------------------------------------------------------------------- // // Function: CStatusDlg::OnOK // // Synopsis: Virtual function. Process WM_COMMAND IDOK // // Arguments: None // // Returns: Nothing // // History: fengsun Created Header 2/20/98 // //+---------------------------------------------------------------------------- void CStatusDlg::OnOK() { if (m_fDisplayStatus) { ShowWindow(m_hWnd, SW_HIDE); EnableWindow(m_hWnd, FALSE); } else // in count-down state { m_pConnection->OnStayOnLine(); // // If window is was up previously and a countdown is being // terminated leave the window active. Otherwise restore // window to previous hidden state. // if (!m_fStatusWindowVisible) { ShowWindow(m_hWnd,SW_HIDE); EnableWindow(m_hWnd, FALSE); } } if (!IsWindowVisible(m_hWnd)) { // // Minimize the working set after hide the window. // CMonitor::MinimizeWorkingSet(); } } //+---------------------------------------------------------------------------- // // Function: CStatusDlg::ChangeToCountDown // // Synopsis: Change the status dialog to count-down dialog // // Arguments: None // // Returns: Nothing // // History: fengsun Created Header 2/20/98 // //+---------------------------------------------------------------------------- void CStatusDlg::ChangeToCountDown() { MYDBGASSERT(m_fDisplayStatus); // is status; m_fDisplayStatus = FALSE; // // After user clicked "Stay Online", we need to restore the visible state // Convert is to real boolean // m_fStatusWindowVisible = IsWindowVisible(m_hWnd) != FALSE; KillRasMonitorWindow(); // // Change OK to Stay Online // LPTSTR pszTmp = CmLoadString(CMonitor::GetInstance(),IDMSG_CONNDISC_STAYONLINE); SetDlgItemTextU(m_hWnd,IDOK,pszTmp); CmFree(pszTmp); // // Change Disconnect to Disconnect Now // pszTmp = CmLoadString(CMonitor::GetInstance(),IDMSG_CONNDISC_DISCNOW); SetDlgItemTextU(m_hWnd,IDC_DISCONNECT,pszTmp); CmFree(pszTmp); // Hide/Show the windows for countdown mode if (!OS_NT4) { // // Hide 9X statistics control // ShowWindow(GetDlgItem(m_hWnd,IDC_CONNSTAT_SPEED_DISPLAY),SW_HIDE); ShowWindow(GetDlgItem(m_hWnd,IDC_CONNSTAT_RECEIVED_DISPLAY),SW_HIDE); ShowWindow(GetDlgItem(m_hWnd,IDC_CONNSTAT_SENT_DISPLAY),SW_HIDE); } ShowWindow(GetDlgItem(m_hWnd,IDC_AUTODISC),SW_SHOW); SetForegroundWindow(m_hWnd); // // Make sure we're flashing and topmost for countdown // SetWindowPos(m_hWnd, HWND_TOPMOST, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE); Flash(); } //+---------------------------------------------------------------------------- // // Function: CStatusDlg::ChangeToStatus // // Synopsis: Change the count-down dialog to status dialog // // Arguments: None // // Returns: Nothing // // History: fengsun Created Header 2/20/98 // //+---------------------------------------------------------------------------- void CStatusDlg::ChangeToStatus() { MYDBGASSERT(!m_fDisplayStatus); // is count down m_fDisplayStatus = TRUE; // Set text for buttons and static to standard mode SetDlgItemTextU(m_hWnd,IDC_CONNSTAT_DISCONNECT_DISPLAY,TEXT("")); // // Change back to OK // LPTSTR pszTmp = CmLoadString(CMonitor::GetInstance(),IDMSG_CONNDISC_OK); SetDlgItemTextU(m_hWnd,IDOK,pszTmp); CmFree(pszTmp); // // Change back to Disconnect // pszTmp = CmLoadString(CMonitor::GetInstance(),IDMSG_CONNDISC_DISCONNECT); SetDlgItemTextU(m_hWnd,IDC_DISCONNECT,pszTmp); CmFree(pszTmp); // Hide/Show the windows for standard mode ShowWindow(GetDlgItem(m_hWnd,IDC_AUTODISC),SW_HIDE); if (!OS_NT4) { ShowWindow(GetDlgItem(m_hWnd,IDC_CONNSTAT_SPEED_DISPLAY),SW_SHOW); ShowWindow(GetDlgItem(m_hWnd,IDC_CONNSTAT_RECEIVED_DISPLAY),SW_SHOW); ShowWindow(GetDlgItem(m_hWnd,IDC_CONNSTAT_SENT_DISPLAY),SW_SHOW); } // // Make sure we're not top-most, just on top, when we switch to status // SetWindowPos(m_hWnd, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE); } //+---------------------------------------------------------------------------- // // Function: CStatusDlg::UpdateCountDown // // Synopsis: Update the "xx seconds until disconnect" of the count-down dialog // // Arguments: DWORD dwDuration: connection duration // DWORD dwSeconds - seconds remain to disconnect // // Returns: Nothing // // History: fengsun Created Header 2/20/98 // //+---------------------------------------------------------------------------- void CStatusDlg::UpdateCountDown(DWORD dwDuration, DWORD dwSeconds) { MYDBGASSERT(!m_fDisplayStatus); MYDBGASSERT(dwSeconds < 0xFFFF); UpdateDuration(dwDuration); LPTSTR pszTmp = CmFmtMsg(CMonitor::GetInstance(), IDMSG_CONNDISCONNECT, dwSeconds); SetDlgItemTextU(m_hWnd,IDC_CONNSTAT_DISCONNECT_DISPLAY,pszTmp); CmFree(pszTmp); } //+---------------------------------------------------------------------------- // // Function: CStatusDlg::UpdateDuration // // Synopsis: Update the connection duration // // Arguments: DWORD dwSeconds - connected duration // // Returns: Nothing // // History: fengsun Created Header 2/20/98 // //+---------------------------------------------------------------------------- void CStatusDlg::UpdateDuration(DWORD dwSeconds) { if (!IsWindowVisible(m_hWnd)) { return; } LPTSTR pszMsg; // Connect Duration pszMsg = CmFmtMsg(CMonitor::GetInstance(), IDMSG_CONNDUR, (WORD)((dwSeconds/60)/60), (WORD)((dwSeconds/60)%60), (WORD)(dwSeconds%60)); SetDlgItemTextU(m_hWnd,IDC_CONNSTAT_DURATION_DISPLAY,pszMsg); CmFree(pszMsg); } //+---------------------------------------------------------------------------- // // Function: CStatusDlg::UpdateStats // // Synopsis: Update the status dialog for Win9X // // Arguments: DWORD dwBaudRate - Baud rate // DWORD dwBytesRead - Total Bytes read // DWORD dwBytesWrite - Total bytes written // DWORD dwBytesReadPerSec - Byte read last second // DWORD dwBytesWritePerSec - Byte written last second // // Returns: Nothing // // History: fengsun Created Header 2/20/98 // //+---------------------------------------------------------------------------- void CStatusDlg::UpdateStats(DWORD dwBaudRate, DWORD dwBytesRead, DWORD dwBytesWrite, DWORD dwBytesReadPerSec, DWORD dwBytesWritePerSec) { // // Received // CHAR szFmtNum1[MAX_PATH]; CHAR szFmtNum2[MAX_PATH]; LPSTR pszMsg; FmtNum(dwBytesRead, szFmtNum1, sizeof(szFmtNum1)); if (dwBytesReadPerSec) { FmtNum(dwBytesReadPerSec, szFmtNum2, sizeof(szFmtNum2)); pszMsg = CmFmtMsgA(CMonitor::GetInstance(), IDMSG_CONNCNTRATE, szFmtNum1, szFmtNum2); } else { pszMsg = CmFmtMsgA(CMonitor::GetInstance(), IDMSG_CONNCNT, szFmtNum1); } SetDlgItemTextA(m_hWnd, IDC_CONNSTAT_RECEIVED_DISPLAY, pszMsg); CmFree(pszMsg); // // Sent // FmtNum(dwBytesWrite, szFmtNum1, sizeof(szFmtNum1)); if (dwBytesWritePerSec) { FmtNum(dwBytesWritePerSec, szFmtNum2, sizeof(szFmtNum2)); pszMsg = CmFmtMsgA(CMonitor::GetInstance(), IDMSG_CONNCNTRATE, szFmtNum1, szFmtNum2); } else { pszMsg = CmFmtMsgA(CMonitor::GetInstance(), IDMSG_CONNCNT, szFmtNum1); } SetDlgItemTextA(m_hWnd, IDC_CONNSTAT_SENT_DISPLAY, pszMsg); CmFree(pszMsg); if (dwBaudRate) { FmtNum(dwBaudRate, szFmtNum1, sizeof(szFmtNum1)); pszMsg = CmFmtMsgA(CMonitor::GetInstance(), IDMSG_CONNSPEED, szFmtNum1); SetDlgItemTextA(m_hWnd, IDC_CONNSTAT_SPEED_DISPLAY, pszMsg); CmFree(pszMsg); } } //+---------------------------------------------------------------------------- // // Function: CStatusDlg::GetRasMonitorWindow // // Synopsis: Find the RasMonitor window on NT, if present // The Status window is the owner of the RasMonitor // // Arguments: none // // Returns: HWND - The RasMonitor window handle or NULL // // History: fengsun Created Header 2/12/98 // //+---------------------------------------------------------------------------- HWND CStatusDlg::GetRasMonitorWindow() { // // RasMonitor window only exists on NT // if (!OS_NT4) { return NULL; } // // The RasMonitor window is the child window of desktop // however, the owner window is the status window // HWND hwnd = NULL; while (hwnd = FindWindowExU(NULL, hwnd, WC_DIALOG, NULL)) { if (GetParent(hwnd) == m_hWnd) { return hwnd; } } return NULL; } //+---------------------------------------------------------------------------- // // Function: CStatusDlg::KillRasMonitorWindow // // Synopsis: Close the RasMonitorDlg and any child dialog it might have // // Arguments: None // // Returns: Nothing // // History: fengsun Created Header 4/28/98 // //+---------------------------------------------------------------------------- void CStatusDlg::KillRasMonitorWindow() { HWND hwndRasMonitor = GetRasMonitorWindow(); if (hwndRasMonitor) { // // The current thread is the connection thread // MYDBGASSERT(GetWindowThreadProcessId(m_hWnd, NULL) == GetCurrentThreadId()); // // The RasMonitorDlg can pop up aother dialog, such as details. // Kill all the dialog in the RasMonitor thread // DWORD dwRasMonitorThread = GetWindowThreadProcessId(hwndRasMonitor, NULL); MYDBGASSERT(dwRasMonitorThread); MYDBGASSERT(dwRasMonitorThread != GetCurrentThreadId()); EnumThreadWindows(dwRasMonitorThread, KillRasMonitorWndProc, (LPARAM)this); } } //+---------------------------------------------------------------------------- // // Function: CStatusDlg::KillRasMonitorWndProc // // Synopsis: Kill all the window in the RasMonitorThread // // Arguments: HWND hwnd - Window handle belong to the RasMonitorThread // LPARAM lParam - pointer to CStatusDlg // // Returns: BOOL - TRUE to continue enumeration // // History: fengsun Created Header 4/28/98 // //+---------------------------------------------------------------------------- BOOL CALLBACK CStatusDlg::KillRasMonitorWndProc(HWND hwnd, LPARAM lParam) { // // SendMessage will block until the message returns, because we do not // want to exit the connection thread before RasMinotor thread ended. // CM sends a message from Connection thread to RasMonitor thread. // Be careful about possible deadlock situation // Cause Bug 166787 // SendMessageA(hwnd, WM_CLOSE, (WPARAM)0, (LPARAM)0); return TRUE; } //+---------------------------------------------------------------------------- // // Function: CStatusDlg::DismissStatusDlg // // Synopsis: Dismisses the status dialog. // // Arguments: None // // Returns: Nothing // // History: quintinb Created Header 4/28/98 // //+---------------------------------------------------------------------------- void CStatusDlg::DismissStatusDlg() { // // Since OnOK is protected and virtual we will just add a member function // to call it. We really just want to dismiss the dialog so it will be // hidden again. // OnOK(); } #ifdef DEBUG //+---------------------------------------------------------------------------- // // Function: CStatusDlg::AssertValid // // Synopsis: For debug purpose only, assert the object is valid // // Arguments: None // // Returns: Nothing // // History: Created Header 2/12/98 // //+---------------------------------------------------------------------------- void CStatusDlg::AssertValid() const { MYDBGASSERT(m_fDisplayStatus == TRUE || m_fDisplayStatus == FALSE); MYDBGASSERT(m_fStatusWindowVisible == TRUE || m_fStatusWindowVisible == FALSE); MYDBGASSERT(m_pConnection != NULL); } #endif