home *** CD-ROM | disk | FTP | other *** search
/ Clickx 47 / Clickx 47.iso / assets / software / sswitchxp152.exe / source / SpeedswitchXP / SpeedswitchXPDlg.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2006-07-13  |  66.3 KB  |  2,363 lines

  1. /*
  2.    SpeedswitchXP V1.5
  3.    - Windows XP CPU Frequency Control for Notebooks -
  4.  
  5.    Copyright(c) 2002-2006 Christian Diefer
  6.  
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License version 2 as 
  9.    published by the Free Software Foundation.
  10.    
  11.    This program is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.    
  16.    You should have received a copy of the GNU General Public License
  17.    along with this program; if not, write to the Free Software
  18.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. */
  20.  
  21. #define _UNICODE
  22.  
  23. #include "stdafx.h"
  24. #include "AtlBase.h"
  25. #include "TOptions.h"
  26. #include "SpeedswitchXP.h"
  27. #include "SpeedswitchXPDlg.h"
  28. #include <wtsapi32.h>
  29. #include <stdarg.h>
  30. #include "speedswitch.h"
  31. #include "SpeedswitchXPOptions.h"
  32. #include "Hyperlink.h"
  33. #include "cpuid.h"
  34. #include "speed.h"
  35. #include "CPUData.h"
  36. #include "PowerCapabilities.h"
  37. #include "SystemInfo.h"
  38. #include "htspeed.h"
  39. #include <time.h>
  40. #include "TrayIconManager.h"
  41. #include "CPUSpeed.h"
  42.  
  43. #ifdef _DEBUG
  44. #define new DEBUG_NEW
  45. #endif
  46.  
  47. #define IDM_MAXPERF  300
  48. #define IDM_BATTOPT  301
  49. #define IDM_MAXBATT  302
  50. #define IDM_DYNAMIC  303
  51. #define IDM_SHOWMAIN 304
  52. #define IDM_SHUTDOWN 305
  53.  
  54. const UINT WM_TASKBARCREATED = ::RegisterWindowMessage( _T("TaskbarCreated") );
  55.  
  56. TOptions options;
  57. static UINT timerID = 1;
  58.  
  59. static TTrayIconManager trayMan;
  60.  
  61. HWND glb_hWnd;
  62.  
  63. // CAboutDlg-Dialogfeld fⁿr Anwendungsbefehl 'Info'
  64.  
  65. class CAboutDlg : public CDialog
  66. {
  67. public:
  68.     CAboutDlg();
  69.  
  70. // Dialogfelddaten
  71.     enum { IDD = IDD_ABOUTBOX };
  72.     CHyperLink    m_gplLink;
  73.     CHyperLink    m_homeLink;
  74.     CHyperLink    m_faqLink;
  75.  
  76.     protected:
  77.     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV-Unterstⁿtzung
  78.   virtual BOOL OnInitDialog();
  79.  
  80. // Implementierung
  81. protected:
  82.     DECLARE_MESSAGE_MAP()
  83. };
  84.  
  85. CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
  86. { }
  87.  
  88. void CAboutDlg::DoDataExchange(CDataExchange* pDX)
  89. {
  90.   CDialog::DoDataExchange(pDX);
  91.   DDX_Control(pDX, IDC_GPLLINK, m_gplLink);
  92.   DDX_Control(pDX, IDC_URLTEXT1, m_homeLink);
  93.   DDX_Control(pDX, IDC_URLTEXT4, m_faqLink);
  94. }
  95.  
  96. //////////////////
  97. // Initialize dialog: subclass static controls
  98. BOOL CAboutDlg::OnInitDialog() 
  99. {
  100.   m_gplLink.SetURL( _T("http://www.fsf.org/licenses/gpl.txt") );
  101.   m_gplLink.SetUnderline( TRUE );
  102.  
  103.   m_homeLink.SetURL( _T("http://www.diefer.de/speedswitchxp/index.html") );
  104.   m_homeLink.SetUnderline( TRUE );
  105.  
  106.   m_faqLink.SetURL( _T("http://www.diefer.de/speedswitchxp/faq.html") );
  107.   m_faqLink.SetUnderline( TRUE );
  108.  
  109.   return CDialog::OnInitDialog();
  110. }
  111.  
  112. BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
  113. END_MESSAGE_MAP()
  114.  
  115. // CSpeedswitchXPDlg Dialogfeld
  116.  
  117.  
  118. //**************************************************************
  119. // Constructor for main class
  120. //**************************************************************
  121. CSpeedswitchXPDlg::CSpeedswitchXPDlg(CWnd* pParent /*=NULL*/)
  122.     : CDialog(CSpeedswitchXPDlg::IDD, pParent)
  123.   , m_iACState(0)
  124.   , m_iDCState(0)
  125.   , m_szCPULoad(_T("---"))
  126.   , m_szCPUSpeed(_T("---"))
  127.   , m_szMaxCPUSpeed(_T(""))
  128. {
  129.   getRegKeys();   // read configuration from registry
  130.  
  131.   diagramOffset = 0;
  132.  
  133.   if( options.debugMode )
  134.     DeleteFile( _T("SpeedswitchXP.log") );
  135.  
  136.   log( _T("Constructor: Starting") );
  137.   m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  138.   iBattOpt = AfxGetApp()->LoadIcon(IDR_BATTOPT);
  139.   iMaxPerf = AfxGetApp()->LoadIcon(IDR_MAXPERF);
  140.   iMaxBatt = AfxGetApp()->LoadIcon(IDR_MAXBATT);
  141.   iDynamic = AfxGetApp()->LoadIcon(IDR_DYNAMIC);
  142.   iTrayBattery = AfxGetApp()->LoadIcon(IDI_TRAYBATT);
  143.   iBattCharge = AfxGetApp()->LoadIcon(IDI_CHARGEICON);
  144.  
  145.   cpuDataIcon = NULL;
  146.   loadIndex = 0;
  147.   speedIndex = 0;
  148.   tickCounterCPU = 0;
  149.   tickCounterCheck = 0;
  150.   batteryIconActive = FALSE;
  151.   batteryIconCharge = FALSE;
  152.   batteryValue = -2;
  153.   cpuDataIconActive = FALSE;
  154.   cpuIconVal1 = -2;
  155.   cpuIconVal2 = -2;
  156.   curSpeed = 0;
  157.   curLoad = 0;
  158.   forceShutdown = false;
  159.  
  160.   for( int i=0; i<1200; i++ )   // init history arrays
  161.     loadArr[i] = speedArr[i] = 0;
  162.  
  163.   trayIcon = FALSE;
  164.  
  165.   log( _T("Constructor: Creating dialog") );
  166.   Create( CSpeedswitchXPDlg::IDD, pParent );
  167.  
  168.   // compute diagram offsets
  169.   ((CWnd*)GetDlgItem(IDC_CPUFRAME))->GetWindowRect( &cpuFrame );
  170.   ((CWnd*)GetDlgItem(IDC_LEGENDFRAME))->GetWindowRect( &legendFrame );
  171.   ScreenToClient( &cpuFrame );
  172.   ScreenToClient( &legendFrame );
  173.   cpuFrame.DeflateRect( 1, 1 );
  174.   legendFrame.DeflateRect( 1, 1 );
  175.  
  176.   log( _T("Constructor: Complete") );
  177. }
  178.  
  179. void CSpeedswitchXPDlg::initStrings()
  180. {
  181.   CString s1;
  182.  
  183.   legend1.LoadStringW( IDS_MAIN21 );
  184.   legend2.LoadStringW( IDS_MAIN22 );
  185.   err.LoadStringW( IDS_MAINERR2 );
  186. }
  187.  
  188. void CSpeedswitchXPDlg::DoDataExchange(CDataExchange* pDX)
  189. {
  190.   CDialog::DoDataExchange(pDX);
  191.   DDX_CBIndex(pDX, IDC_COMBO1, m_iACState);
  192.   DDX_CBIndex(pDX, IDC_COMBO2, m_iDCState);
  193.   DDX_Text(pDX, IDC_EDIT1, m_szCPULoad);
  194.   DDX_Text(pDX, IDC_EDIT2, m_szCPUSpeed);
  195.   DDX_Text(pDX, IDC_EDIT3, m_szMaxCPUSpeed);
  196.   DDX_Control(pDX, IDC_COMBO3, m_cDisplayAC);
  197.   DDX_Control(pDX, IDC_COMBO7, m_cDisplayDC);
  198.   DDX_Control(pDX, IDC_COMBO4, m_cDiskAC);
  199.   DDX_Control(pDX, IDC_COMBO8, m_cDiskDC);
  200.   DDX_Control(pDX, IDC_COMBO5, m_cStandbyAC);
  201.   DDX_Control(pDX, IDC_COMBO9, m_cStandbyDC);
  202.   DDX_Control(pDX, IDC_COMBO6, m_cHibernationAC);
  203.   DDX_Control(pDX, IDC_COMBO10, m_cHibernationDC);
  204. }
  205.  
  206. BEGIN_MESSAGE_MAP(CSpeedswitchXPDlg, CDialog)
  207.   ON_WM_SYSCOMMAND()
  208.   ON_WM_PAINT()
  209.   ON_WM_QUERYDRAGICON()
  210.   ON_WM_CLOSE()
  211.   ON_WM_TIMER()
  212.   ON_WM_HSCROLL()
  213.   ON_MESSAGE(WM_ICONNOTIFY, OnIconNotify)
  214.   ON_MESSAGE(WM_POWERBROADCAST, OnPowerBroadCast)
  215.   ON_BN_CLICKED(IDC_CLOSE, OnBnClickedClose)
  216.   ON_BN_CLICKED(IDC_ABOUT, OnAbout)
  217.   ON_CBN_SELCHANGE(IDC_COMBO1, OnCbnSelchangeCombo1)
  218.   ON_CBN_SELCHANGE(IDC_COMBO2, OnCbnSelchangeCombo2)
  219.   ON_BN_CLICKED(IDC_OPTBUTTON, OnBnClickedOptbutton)
  220.   ON_COMMAND(IDM_MAXPERF, OnMaxPerfMenu)
  221.   ON_COMMAND(IDM_BATTOPT, OnBattOptMenu)
  222.   ON_COMMAND(IDM_MAXBATT, OnMaxBattMenu)
  223.   ON_COMMAND(IDM_DYNAMIC, OnDynamicMenu)
  224.   ON_COMMAND(IDM_SHOWMAIN, OnShowMainMenu)
  225.   ON_COMMAND(IDM_SHUTDOWN, OnSelectShutdown)
  226.   ON_BN_CLICKED(IDC_BUTTON2, OnBnClickedButton2)
  227.   ON_WM_SETCURSOR()
  228.   ON_CBN_SELCHANGE(IDC_COMBO3, OnCbnSelchangeDisplayAC)
  229.   ON_CBN_SELCHANGE(IDC_COMBO7, OnCbnSelchangeDisplayDC)
  230.   ON_CBN_SELCHANGE(IDC_COMBO4, OnCbnSelchangeDiskAC)
  231.   ON_CBN_SELCHANGE(IDC_COMBO8, OnCbnSelchangeDiskDC)
  232.   ON_CBN_SELCHANGE(IDC_COMBO5, OnCbnSelchangeStandbyAC)
  233.   ON_CBN_SELCHANGE(IDC_COMBO9, OnCbnSelchangeStandbyDC)
  234.   ON_CBN_SELCHANGE(IDC_COMBO6, OnCbnSelchangeHibAC)
  235.   ON_CBN_SELCHANGE(IDC_COMBO10, OnCbnSelchangeHibDC)
  236.   ON_BN_CLICKED(IDC_BUTTON3, OnBnClickedCPUData)
  237.   ON_REGISTERED_MESSAGE(WM_TASKBARCREATED, OnTaskBarCreated)
  238.   ON_BN_CLICKED(IDC_BUTTON4, OnBnClickedButton4)
  239. END_MESSAGE_MAP()
  240.  
  241.  
  242. // CSpeedswitchXPDlg Meldungshandler
  243.  
  244. //**************************************************************
  245. // redisplay tray icon(s)
  246. //**************************************************************
  247. LRESULT CSpeedswitchXPDlg::OnTaskBarCreated( WPARAM wp, LPARAM lp )
  248. {
  249.   displayTrayIcon( NIM_ADD );
  250.  
  251.   if( batteryIconActive )
  252.   {
  253.     batteryIconActive = batteryIconCharge = FALSE;
  254.     batteryDisplay( NULL );
  255.   }
  256.  
  257.   if( cpuDataIconActive )
  258.     displayCPUDataIcon( NIM_ADD );
  259.  
  260.   return 0;
  261. }
  262.  
  263. //**************************************************************
  264. // initialize dialog window
  265. //**************************************************************
  266. BOOL CSpeedswitchXPDlg::OnInitDialog()
  267. {
  268.   log( _T("InitDialog: Start") );
  269.   CDialog::OnInitDialog();
  270.  
  271.   initStrings();
  272.  
  273.   fillHibernationTimes( &m_cDisplayAC, NULL, -1, 0 );
  274.   fillHibernationTimes( &m_cDisplayDC, NULL, -1, 0 );
  275.   fillHibernationTimes( &m_cDiskAC, NULL, -1, 1 );
  276.   fillHibernationTimes( &m_cDiskDC, NULL, -1, 1 );
  277.   fillHibernationTimes( &m_cStandbyAC, NULL, -1, 2 );
  278.   fillHibernationTimes( &m_cStandbyDC, NULL, -1, 2 );
  279.  
  280.   fillPolicyStrings( (CComboBox*)GetDlgItem(IDC_COMBO1) );
  281.   fillPolicyStrings( (CComboBox*)GetDlgItem(IDC_COMBO2) );
  282.  
  283.     // Hinzufⁿgen des Menⁿbefehls "Info..." zum Systemmenⁿ.
  284.  
  285.     // IDM_ABOUTBOX muss sich im Bereich der Systembefehle befinden.
  286.     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
  287.     ASSERT(IDM_ABOUTBOX < 0xF000);
  288.  
  289.     CMenu* pSysMenu = GetSystemMenu(FALSE);
  290.     if (pSysMenu != NULL)
  291.     {
  292.         CString strAboutMenu;
  293.         strAboutMenu.LoadString(IDS_ABOUTBOX);
  294.         if (!strAboutMenu.IsEmpty())
  295.         {
  296.             pSysMenu->AppendMenu(MF_SEPARATOR);
  297.             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  298.         }
  299.     }
  300.  
  301.     // Symbol fⁿr dieses Dialogfeld festlegen. Wird automatisch erledigt
  302.     //  wenn das Hauptfenster der Anwendung kein Dialogfeld ist
  303.     SetIcon( m_hIcon, TRUE );            // Gro▀es Symbol verwenden
  304.     SetIcon( m_hIcon, FALSE );        // Kleines Symbol verwenden
  305.  
  306.   glb_hWnd = m_hWnd;
  307.  
  308.     // TODO: Hier zusΣtzliche Initialisierung einfⁿgen
  309.     OSVERSIONINFO ovi;
  310.  
  311.     ovi.dwOSVersionInfoSize = sizeof( ovi );
  312.  
  313.     if( GetVersionEx(&ovi) == 0 )
  314.         return FALSE;        // this should never happen !
  315.  
  316.   log( _T("Running on %s Version %d.%d Build %d (%s)"),
  317.        ovi.dwPlatformId==VER_PLATFORM_WIN32_NT 
  318.            ? _T("Windows NT")
  319.            : (ovi.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS
  320.            ? _T("Windows 9x") : _T("Windows 3.1 (?)")),
  321.        ovi.dwMajorVersion,
  322.        ovi.dwMinorVersion,
  323.        ovi.dwBuildNumber,
  324.        ovi.szCSDVersion );
  325.  
  326.     // not running on XP or higher => terminate
  327.     if( ovi.dwPlatformId!=VER_PLATFORM_WIN32_NT || ovi.dwBuildNumber<2600 )
  328.   {
  329.     log( _T("/aError") );
  330.     CString s1;
  331.     s1.LoadStringW( IDS_MAINERR1 );
  332.     MessageBox( s1, err, MB_OK|MB_ICONEXCLAMATION ); 
  333.     forceShutdown = true;
  334.     PostMessage( WM_CLOSE );
  335.     return FALSE;
  336.   }
  337.  
  338.   if( !initPowerValues() )    // set box contents on main window
  339.     return FALSE;
  340.  
  341.   UpdateData( FALSE );
  342.  
  343.   log( _T("InitDialog: Complete") );
  344.  
  345.     return TRUE;
  346. }
  347.  
  348. //**************************************************************
  349. // read keys from registry
  350. //**************************************************************
  351. void CSpeedswitchXPDlg::getRegKeys()
  352. {
  353.   if( !options.getRegKeys() )
  354.   {
  355.     CString s1;
  356.     s1.LoadStringW( IDS_MAINERR3 );
  357.     MessageBox( s1, err, MB_ICONEXCLAMATION|MB_OK );
  358.   }
  359. }
  360.  
  361. //**************************************************************
  362. // write keys to registry
  363. //**************************************************************
  364. void CSpeedswitchXPDlg::setRegKeys()
  365. {
  366.   if( !options.setRegKeys() )
  367.   {
  368.     CString s1;
  369.     s1.LoadStringW( IDS_MAINERR4 );
  370.     MessageBox( s1, err, MB_ICONEXCLAMATION|MB_OK );
  371.   }
  372. }
  373.  
  374. //**************************************************************
  375. // evaluate command line options (used here to indicate program 
  376. // start, thus displaying the tray icon)
  377. //**************************************************************
  378. void CSpeedswitchXPDlg::setCmdLine( TCHAR* cl )
  379. {
  380.   log( _T("setCmdLine: Start") );
  381.   displayTrayIcon( NIM_ADD );
  382.   trayIcon = TRUE;
  383.   minimizeToTray();
  384.   log( _T("setCmdLine: Complete") );
  385. }
  386.  
  387. //**************************************************************
  388. // evaluate commands from the system menu
  389. //**************************************************************
  390. void CSpeedswitchXPDlg::OnSysCommand(UINT nID, LPARAM lParam)
  391. {
  392.     if ((nID & 0xFFF0) == IDM_ABOUTBOX)
  393.     {
  394.         CAboutDlg dlgAbout;
  395.         dlgAbout.DoModal();
  396.     }
  397.     else
  398.     {
  399.         CDialog::OnSysCommand(nID, lParam);
  400.     }
  401. }
  402.  
  403. // Wenn Sie dem Dialogfeld eine SchaltflΣche "Minimieren" hinzufⁿgen, ben÷tigen Sie 
  404. //  den nachstehenden Code, um das Symbol zu zeichnen. Fⁿr MFC-Anwendungen, die das 
  405. //  Dokument/Ansicht-Modell verwenden, wird dies automatisch ausgefⁿhrt.
  406.  
  407. void CSpeedswitchXPDlg::OnPaint() 
  408. {
  409.     if (IsIconic())
  410.     {
  411.         CPaintDC dc( this ); // GerΣtekontext zum Zeichnen
  412.  
  413.         SendMessage( WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0 );
  414.  
  415.         // Symbol in Clientrechteck zentrieren
  416.         int cxIcon = GetSystemMetrics(SM_CXICON);
  417.         int cyIcon = GetSystemMetrics(SM_CYICON);
  418.         CRect rect;
  419.         GetClientRect(&rect);
  420.         int x = (rect.Width() - cxIcon + 1) / 2;
  421.         int y = (rect.Height() - cyIcon + 1) / 2;
  422.  
  423.         // Symbol zeichnen
  424.         dc.DrawIcon(x, y, m_hIcon);
  425.     }
  426.     else
  427.     {
  428.       drawDiagram();
  429.         CDialog::OnPaint();
  430.     }
  431. }
  432.  
  433. // Das System ruft diese Funktion auf, um den Cursor abzufragen, der angezeigt wird, wΣhrend der Benutzer
  434. //  das minimierte Fenster mit der Maus zieht.
  435. HCURSOR CSpeedswitchXPDlg::OnQueryDragIcon()
  436. {
  437.     return static_cast<HCURSOR>(m_hIcon);
  438. }
  439.  
  440. //**************************************************************
  441. // process events from the tray icon
  442. //**************************************************************
  443. LRESULT CSpeedswitchXPDlg::OnIconNotify( WPARAM w, LPARAM l )
  444. {
  445.   switch( l )
  446.   {
  447.     case WM_LBUTTONUP:
  448.           ShowWindow( SW_SHOW );
  449.           SetForegroundWindow();
  450.           break;
  451.  
  452.     case WM_RBUTTONUP:
  453.           {
  454.             CMenu menu;
  455.             menu.CreatePopupMenu();
  456.  
  457.             int cur = options.ac ? acThrottle : dcThrottle;
  458.  
  459.             for( int i=0; i<4; i++ )
  460.               menu.AppendMenuW( MF_STRING | (i==cur ? MF_CHECKED : 0),
  461.                                IDM_MAXPERF+i, 
  462.                                throttleString(i) );
  463.  
  464.             menu.AppendMenu( MF_SEPARATOR );
  465.             CString s1;
  466.             s1.LoadStringW( IDS_MAIN23 );
  467.             menu.AppendMenu( MF_STRING, IDM_SHOWMAIN, s1 );
  468.             SetMenuDefaultItem( menu, IDM_SHOWMAIN, FALSE );
  469.             menu.AppendMenu( MF_SEPARATOR );
  470.             s1.LoadStringW( IDS_MAIN24 );
  471.             menu.AppendMenu( MF_STRING, IDM_SHUTDOWN, s1 );
  472.  
  473.             POINT Point;
  474.             GetCursorPos( &Point );
  475.             SetForegroundWindow();
  476.  
  477.             menu.TrackPopupMenu( TPM_LEFTALIGN|TPM_BOTTOMALIGN|TPM_NONOTIFY,
  478.                                  Point.x,
  479.                                  Point.y,
  480.                                  this );
  481.             menu.Detach();
  482.           }
  483.           break;
  484.   }
  485.  
  486.   return 0;
  487. }
  488.  
  489. //**************************************************************
  490. // enter autostart string in the user's autostart registry area
  491. //**************************************************************
  492. void CSpeedswitchXPDlg::setAutoStartRegistry()
  493. {
  494.   LONG lReturn = 0;
  495.   TCHAR path[264];
  496.   CRegKey key;
  497.  
  498.   if( GetModuleFileName(NULL,path,255) == 0 )
  499.   {
  500.     CString s1;
  501.     s1.LoadStringW( IDS_MAINERR5 );
  502.     MessageBox( s1, err, MB_OK|MB_ICONEXCLAMATION );
  503.     return;
  504.   }
  505.  
  506.   lReturn = key.Create( HKEY_CURRENT_USER,
  507.                         _T("Software\\Microsoft\\Windows\\CurrentVersion\\Run\\") );
  508.  
  509.   if( lReturn == ERROR_SUCCESS )
  510.   {
  511.     if( key.SetValue(_T("SpeedswitchXP"),REG_SZ,path,(ULONG)((_tcslen(path)+1)*2)) != ERROR_SUCCESS )
  512.     {
  513.       CString s1;
  514.       s1.LoadStringW( IDS_MAINERR6 );
  515.       MessageBox( s1, err, MB_ICONEXCLAMATION|MB_OK );
  516.       key.Close();
  517.       return;
  518.     }
  519.   }
  520.   else
  521.   {
  522.     CString s1;
  523.     s1.LoadStringW( IDS_MAINERR6 );
  524.     MessageBox( s1, err, MB_ICONEXCLAMATION|MB_OK );
  525.   }
  526.  
  527.   key.Close();
  528. }
  529.  
  530. //**************************************************************
  531. // ... and delete it if the user asks for it
  532. //**************************************************************
  533. void CSpeedswitchXPDlg::deleteAutoStartRegistry()
  534. {
  535.   CRegKey key;
  536.   LONG result = key.Open( HKEY_CURRENT_USER,
  537.                           _T("Software\\Microsoft\\Windows\\CurrentVersion\\Run\\") );
  538.  
  539.   if( result == ERROR_SUCCESS )
  540.     key.DeleteValue( _T("SpeedswitchXP") );
  541.   else
  542.   {
  543.     CString s1;
  544.     s1.LoadStringW( IDS_MAINERR7 );
  545.     MessageBox( s1, err, MB_ICONERROR );
  546.   }
  547.  
  548.   key.Close();
  549. }
  550.  
  551. //**************************************************************
  552. // last method to be called during this class' lifetime
  553. //**************************************************************
  554. void CSpeedswitchXPDlg::PostNcDestroy()
  555. {
  556.     delete this;
  557. }
  558.  
  559. //**************************************************************
  560. // show the 'About' dialog
  561. //**************************************************************
  562. void CSpeedswitchXPDlg::OnAbout() 
  563. {
  564.     CAboutDlg dlgAbout;
  565.     dlgAbout.DoModal();    
  566. }
  567.  
  568. //**************************************************************
  569. // minimize to tray
  570. //**************************************************************
  571. void CSpeedswitchXPDlg::minimizeToTray()
  572. {
  573.   ShowWindow( SW_HIDE );
  574. }
  575.  
  576. //**************************************************************
  577. // handler for 'Close' button
  578. //**************************************************************
  579. void CSpeedswitchXPDlg::OnBnClickedClose()
  580. {
  581.   if( options.minimizeOnClose )
  582.   {
  583.     minimizeToTray();
  584.     return;
  585.   }
  586.  
  587.   OnClose();
  588. }
  589.  
  590. //**************************************************************
  591. // process the Close request
  592. //**************************************************************
  593. void CSpeedswitchXPDlg::OnClose()
  594. {
  595.   if( options.minimizeOnClose && !forceShutdown )
  596.   {
  597.     minimizeToTray();
  598.     return;
  599.   }
  600.  
  601.   forceShutdown = false;
  602.  
  603.   log( _T("--------------------------------") );
  604.   log( _T("Begin termination") );
  605.  
  606.   if( closeQuery() )
  607.   {
  608.     setRegKeys();
  609.  
  610.     if( activeTimer )
  611.     {
  612.       log( _T("/bKilling timer (%d)... "), timerID );
  613.       if( KillTimer(timerID) == 0 )
  614.         log( _T("/aError") );
  615.       else
  616.         log( _T("/aOk") );
  617.       tickCounterCPU = 0;
  618.       tickCounterCheck = 0;
  619.     }
  620.  
  621.     log( _T("/bClosing main window... ") );
  622.     DestroyWindow();
  623.     log( _T("/aOk") );
  624.  
  625.     if( options.reactivate )
  626.     {
  627.       log( _T("/bRestoring previous power scheme... ") );
  628.       SetActivePwrScheme( options.originalScheme, NULL, NULL );
  629.       log( _T("/aOk") );
  630.     }
  631.   }
  632. }
  633.  
  634. //**************************************************************
  635. // CloseQuery taken from I8kfanGUI; only used here to remove the
  636. // tray icon
  637. //**************************************************************
  638. bool CSpeedswitchXPDlg::closeQuery()
  639. {
  640.   if( trayIcon )
  641.   {
  642.     log( _T("removing tray icon...") );
  643.     NOTIFYICONDATA nid;
  644.     nid.cbSize = sizeof( NOTIFYICONDATA );
  645.     nid.hWnd = m_hWnd;
  646.     nid.uID = 700;
  647.     nid.uCallbackMessage = WM_ICONNOTIFY;
  648.     nid.hIcon = curIcon;
  649.     Shell_NotifyIcon( NIM_DELETE, &nid );
  650.   }
  651.  
  652.   if( batteryIconActive )
  653.     removeBatteryIcon();
  654.  
  655.   if( cpuDataIconActive )
  656.     removeCPUDataIcon();
  657.  
  658.   return true;
  659. }
  660.  
  661. //**************************************************************
  662. // display/modify/remove the tray icon
  663. //**************************************************************
  664. void CSpeedswitchXPDlg::displayTrayIcon( DWORD msg )
  665. {
  666.   NOTIFYICONDATA nid;
  667.   static TCHAR tp[128];
  668.  
  669.   nid.cbSize = sizeof( NOTIFYICONDATA );
  670.   nid.hWnd = m_hWnd;
  671.   nid.uID = 700;
  672.   nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
  673.   nid.uCallbackMessage = WM_ICONNOTIFY;
  674.  
  675.   CString s1;
  676.   s1.LoadStringW( IDS_MAIN25 );
  677.   wsprintf( tp, s1,
  678.                 throttleString(acThrottle),
  679.                 options.ac ? _T(" <-") : _T(""),
  680.                 throttleString(dcThrottle),
  681.                 options.ac ? _T("") : _T(" <-") );
  682.   
  683.   if( options.readCPUSpeed )
  684.   {
  685.     CString s1;
  686.     s1.LoadStringW( IDS_MAIN26 );
  687.     wsprintf( &tp[_tcslen(tp)],
  688.                 s1,
  689.                 m_szCPUSpeed );
  690.   }
  691.  
  692.   if( options.readCPULoad )
  693.   {
  694.     CString s1;
  695.     s1.LoadStringW( IDS_MAIN27 );
  696.     wsprintf( &tp[_tcslen(tp)],
  697.                 s1,
  698.                 m_szCPULoad );
  699.   }
  700.  
  701.   lstrcpy( nid.szTip, tp );
  702.   nid.hIcon = curIcon;
  703.  
  704.   Shell_NotifyIcon( msg, &nid );
  705. }
  706.  
  707. //**************************************************************
  708. // select the 'flag' icon corresponding to the current CPU policy
  709. //**************************************************************
  710. void CSpeedswitchXPDlg::setCPUIcon( int policy )
  711. {
  712.   switch( policy )
  713.   {
  714.     case PO_THROTTLE_NONE:      curIcon = iMaxPerf;
  715.                                 break;
  716.  
  717.     case PO_THROTTLE_ADAPTIVE:  curIcon = iDynamic;
  718.                                 break;
  719.         
  720.     case PO_THROTTLE_CONSTANT:  curIcon = iBattOpt;
  721.                                 break;
  722.  
  723.     case PO_THROTTLE_DEGRADE:   curIcon = iMaxBatt;
  724.                                 break;
  725.   }
  726. }
  727.  
  728. //**************************************************************
  729. // process AC policy change by user
  730. //**************************************************************
  731. void CSpeedswitchXPDlg::OnCbnSelchangeCombo1()
  732. {
  733.   int i = acThrottle;
  734.  
  735.   UpdateData();
  736. //  if( i != m_iACState )
  737.   {
  738.     log( _T("changing AC from %d to %d"), i, m_iACState );
  739.  
  740.     // Workaround for high load situations when switching from batt.opt/max.batt to
  741.     // dynamic switching: the CPU speed stays at lower speed for duration of high
  742.     // load 
  743.     // => take a short step to max.performance to reset XP's internal idle timer
  744.     if( options.ac )   // really on battery ?
  745.     {
  746.       if( i!=PO_THROTTLE_NONE && m_iACState==PO_THROTTLE_ADAPTIVE )
  747.         setState( TRUE, PO_THROTTLE_NONE );    // take a short step to 'Max.Performance'
  748.     }
  749.  
  750.     if( !setState(TRUE,m_iACState) )
  751.     {
  752.       log( _T("*** change failed ***") );
  753.       m_iACState = i;
  754.       UpdateData( FALSE );
  755.       CString s1;
  756.       s1.LoadStringW( IDS_MAINERR8 );
  757.       MessageBox( s1, err, MB_OK|MB_ICONEXCLAMATION );
  758.       return;
  759.     }
  760.  
  761.     if( options.ac )
  762.       setCPUIcon( m_iACState );
  763.  
  764.     displayTrayIcon( NIM_MODIFY );
  765.   }
  766. }
  767.  
  768. //**************************************************************
  769. // process DC policy change by user
  770. //**************************************************************
  771. void CSpeedswitchXPDlg::OnCbnSelchangeCombo2()
  772. {
  773.   int i = dcThrottle;
  774.  
  775.   UpdateData();
  776. //  if( i != m_iDCState )
  777.   {
  778.     log( _T("changing DC from %d to %d"), i, m_iDCState );
  779.  
  780.     // Workaround for high load situations when switching from batt.opt/max.batt to
  781.     // dynamic switching: the CPU speed stays at lower speed for duration of high
  782.     // load 
  783.     // => take a short step to max.performance to reset XP's internal idle timer
  784.     if( !options.ac )   // really on battery ?
  785.     {
  786.       if( i!=PO_THROTTLE_NONE && m_iDCState==PO_THROTTLE_ADAPTIVE )
  787.         setState( FALSE, PO_THROTTLE_NONE );    // take a short step to 'Max.Performance'
  788.     }
  789.  
  790.     if( !setState(FALSE,m_iDCState) )
  791.     {
  792.       log( _T("*** change failed ***") );
  793.       m_iDCState = i;
  794.       UpdateData( FALSE );
  795.       CString s1;
  796.       s1.LoadStringW( IDS_MAINERR8 );
  797.       MessageBox( s1, err, MB_OK|MB_ICONEXCLAMATION );
  798.       return;
  799.     }
  800.  
  801.     if( !options.ac )
  802.       setCPUIcon( m_iDCState );
  803.  
  804.     displayTrayIcon( NIM_MODIFY );
  805.   }
  806. }
  807.  
  808. //**************************************************************
  809. // process power status change event from system
  810. //**************************************************************
  811. LRESULT CSpeedswitchXPDlg::OnPowerBroadCast( WPARAM wp, LPARAM lp )
  812. {
  813.   if( wp == PBT_APMPOWERSTATUSCHANGE )
  814.   {
  815.     log( _T("Powerstatus change detected !") );
  816.     if( GetSystemPowerStatus(&pwrStatus) )
  817.     {
  818.       BOOL x = (pwrStatus.ACLineStatus!=0);
  819.    
  820.       if( x != options.ac )
  821.       {
  822.         log( _T("change from %s to %s"), options.ac?_T("AC"):_T("DC"), x?_T("AC"):_T("DC") );
  823.         options.ac = x;
  824.         setCPUIcon( options.ac ? acThrottle : dcThrottle );
  825.         displayTrayIcon( NIM_MODIFY );
  826.  
  827.         if( options.showBattery )
  828.           batteryDisplay( &pwrStatus );
  829.       }
  830.     }
  831.   }
  832.   else if( wp == PBT_APMRESUMESUSPEND )
  833.   {
  834.     log( _T("Returning from standby/hibernation !") );
  835.  
  836.     // switch to max performance for a short time and then back:
  837.     int aktuell = options.ac ? acThrottle : dcThrottle;
  838.  
  839.     setState( options.ac, PO_THROTTLE_NONE );
  840.     Sleep( 250 );                       // wait 1/2 second
  841.     setState( options.ac, aktuell );    // return to previous setting
  842.   }
  843.   else if( wp == PBT_APMRESUMESTANDBY )
  844.   {
  845.     log( _T("Returning from standby !") );
  846.  
  847.     // switch to max performance for a short time and then back:
  848.     int aktuell = options.ac ? acThrottle : dcThrottle;
  849.  
  850.     setState( options.ac, PO_THROTTLE_NONE );
  851.     Sleep( 250 );                       // wait 1/2 second
  852.     setState( options.ac, aktuell );    // return to previous setting
  853.   }
  854.   
  855.   return 0;
  856. }
  857.  
  858. //**************************************************************
  859. // handler for 'Options' button
  860. //**************************************************************
  861. void CSpeedswitchXPDlg::OnBnClickedOptbutton()
  862. {
  863.   CSpeedswitchXPOptions dlg;
  864.  
  865.   dlg.setVars( options );
  866.  
  867.     if( dlg.DoModal() == IDOK )
  868.   {
  869.     dlg.getVars( options );
  870.  
  871.     if( dlg.power || dlg.cpu )
  872.     {
  873.       log( _T("writing new power policies:%d %d"), dlg.power, dlg.cpu );
  874.       writePolicies( dlg.power, dlg.cpu );
  875.     }
  876.  
  877.     setRegKeys();
  878.  
  879.     if( options.autoStart )
  880.       setAutoStartRegistry();
  881.     else
  882.       deleteAutoStartRegistry();
  883.  
  884.     if( !options.readCPUSpeed )
  885.       m_szCPUSpeed = _T("---");
  886.  
  887.     if( !options.readCPULoad )
  888.       m_szCPULoad = _T("---");
  889.  
  890.     if( activeTimer 
  891.     && !(options.checkStatus || options.readCPUSpeed || options.readCPULoad || options.showBattery) )
  892.     {
  893.       log( _T("Killing existing timer") );
  894.       KillTimer( timerID );
  895.       activeTimer = FALSE;
  896.     }
  897.  
  898.     if( !activeTimer 
  899.     && (options.checkStatus || options.readCPUSpeed || options.readCPULoad || options.showBattery) )
  900.     {
  901.       log( _T("Creating new timer") );
  902.       SetTimer( timerID, 1000, NULL );
  903.       activeTimer = TRUE;
  904.     }
  905.  
  906.     displayTrayIcon( NIM_MODIFY );
  907.  
  908.     if( !GetSystemPowerStatus(&pwrStatus) )
  909.     {
  910.       CString s1;
  911.       s1.LoadStringW( IDS_MAINERR9 );
  912.       MessageBox( s1, err, MB_ICONEXCLAMATION|MB_OK );
  913.     }
  914.     else
  915.     {
  916.       // check battery options for changes:
  917.       // 1. battery option off & icon shown => remove icon
  918.       if( !options.showBattery && batteryIconActive )
  919.         removeBatteryIcon();
  920.       // 2. battery option on => show/update/remove icon
  921.       else if( options.showBattery )
  922.         batteryDisplay( &pwrStatus );
  923.     }
  924.  
  925.     if( !options.speedIcon && !options.loadIcon && cpuDataIconActive )
  926.       removeCPUDataIcon();
  927.     else if( options.speedIcon || options.loadIcon )
  928.       displayCPUDataIcon( cpuDataIconActive ? NIM_MODIFY : NIM_ADD );
  929.  
  930.     initPowerBoxes();
  931.          
  932.     UpdateData( FALSE );
  933.   }
  934. }
  935.  
  936.  
  937. //**************************************************************
  938. // handlers for tray icon menu
  939. //**************************************************************
  940. void CSpeedswitchXPDlg::OnMaxPerfMenu( void )
  941. { MenuSpeedHandler(PO_THROTTLE_NONE); }
  942.  
  943. void CSpeedswitchXPDlg::OnBattOptMenu( void )
  944. { MenuSpeedHandler(PO_THROTTLE_CONSTANT); }
  945.  
  946. void CSpeedswitchXPDlg::OnMaxBattMenu( void )
  947. { MenuSpeedHandler(PO_THROTTLE_DEGRADE); }
  948.  
  949. void CSpeedswitchXPDlg::OnDynamicMenu( void )
  950. { MenuSpeedHandler(PO_THROTTLE_ADAPTIVE); }
  951.  
  952. void CSpeedswitchXPDlg::OnShowMainMenu( void )
  953. { ShowWindow(SW_SHOW); }
  954.  
  955. void CSpeedswitchXPDlg::OnSelectShutdown( void )
  956. {
  957.   forceShutdown = true;
  958.   PostMessage( WM_CLOSE );
  959. }
  960.  
  961.  
  962. void CSpeedswitchXPDlg::MenuSpeedHandler( int throttle )
  963. {
  964.   if( options.ac )
  965.   {
  966.     UpdateData();
  967.     int x = m_iACState;
  968.     m_iACState = throttle;
  969.     UpdateData( FALSE );
  970.     m_iACState = x;
  971.     OnCbnSelchangeCombo1();
  972.   }
  973.   else
  974.   {
  975.     UpdateData();
  976.     int x = m_iDCState;
  977.     m_iDCState = throttle;
  978.     UpdateData( FALSE );
  979.     m_iDCState = x;
  980.     OnCbnSelchangeCombo2();
  981.   }
  982. }
  983.  
  984. //**************************************************************
  985. // perform user requested scrolling in the history diagram
  986. //**************************************************************
  987. void CSpeedswitchXPDlg::OnHScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar )
  988. {
  989.   if( pScrollBar != ((CScrollBar*)GetDlgItem(IDC_SCROLLBAR1)) )
  990.     return;
  991.  
  992.   int curpos = pScrollBar->GetScrollPos();
  993.   int newpos = curpos;
  994.  
  995.   switch( nSBCode )
  996.   {
  997.     case SB_THUMBPOSITION:
  998.     case SB_THUMBTRACK:
  999.            newpos = nPos;
  1000.            break;
  1001.  
  1002.     case SB_LEFT:
  1003.            newpos = 0;
  1004.            break;
  1005.  
  1006.     case SB_RIGHT:
  1007.            newpos = 90;
  1008.            break;
  1009.  
  1010.     case SB_LINELEFT:
  1011.     case SB_PAGELEFT:
  1012.            if( curpos > 0 )
  1013.              newpos = curpos-1;
  1014.            break;
  1015.  
  1016.     case SB_LINERIGHT:
  1017.     case SB_PAGERIGHT:
  1018.            if( curpos < 90 )
  1019.              newpos = curpos+1;
  1020.            break;
  1021.  
  1022.     case SB_ENDSCROLL:
  1023.            break;
  1024.   }
  1025.  
  1026.   if( newpos != curpos )
  1027.   {
  1028.     pScrollBar->SetScrollPos( newpos, TRUE );
  1029.     diagramOffset = (90-newpos) * 12;
  1030.     InvalidateRect( &cpuFrame, FALSE );
  1031.   }
  1032.  
  1033.   CDialog::OnHScroll( nSBCode, nPos, pScrollBar );
  1034. }
  1035.  
  1036. //**************************************************************
  1037. // perform timer dependend tasks (read CPU speed/load etc.)
  1038. //**************************************************************
  1039. void CSpeedswitchXPDlg::OnTimer( UINT nIDEvent ) 
  1040. {
  1041.     if( nIDEvent == timerID )
  1042.   {
  1043.     if( (options.readCPUSpeed || options.readCPULoad || options.showBattery) && (int)tickCounterCPU>=options.cpuInterval )
  1044.     {
  1045.       UpdateData();
  1046.  
  1047.       CString sp = m_szCPUSpeed;
  1048.       CString lo = m_szCPULoad;
  1049.  
  1050.       if( options.readCPUSpeed )
  1051.         readCPUSpeed();
  1052.       else
  1053.       {
  1054.         speedArr[speedIndex++] = 0;
  1055.         if( speedIndex >= 1200 )
  1056.           speedIndex = 0;
  1057.       }
  1058.  
  1059.       if( options.readCPULoad )
  1060.         readCPULoad();
  1061.       else
  1062.       {
  1063.         loadArr[loadIndex++] = 0;
  1064.         if( loadIndex >= 1200 )
  1065.           loadIndex = 0;
  1066.       }
  1067.  
  1068.       if( sp!=m_szCPUSpeed || lo!=m_szCPULoad )
  1069.       {
  1070.         displayTrayIcon( NIM_MODIFY );
  1071.  
  1072.         if( cpuDataIconActive )
  1073.           displayCPUDataIcon( NIM_MODIFY );
  1074.       }
  1075.  
  1076.       if( options.showBattery )
  1077.         batteryDisplay( NULL );
  1078.  
  1079.       tickCounterCPU = 0;
  1080.  
  1081.       UpdateData( FALSE );
  1082.  
  1083.       if( options.showDiagram )   // update history diagram
  1084.         InvalidateRect( &cpuFrame, FALSE );
  1085.     }
  1086.  
  1087.     if( (int)tickCounterCheck >= (options.checkInterval*60) ) 
  1088.     {
  1089.       UpdateData();
  1090.       
  1091.       checkProfile( 3 );
  1092.  
  1093.       tickCounterCheck = 0;
  1094.       UpdateData( FALSE );
  1095.     }
  1096.  
  1097.     tickCounterCPU++;
  1098.     tickCounterCheck++;
  1099.   }
  1100.  
  1101.     CDialog::OnTimer( nIDEvent );
  1102. }
  1103.  
  1104. //**************************************************************
  1105. // get the current CPU speed depending on the chosen method
  1106. //**************************************************************
  1107. void CSpeedswitchXPDlg::readCPUSpeed() 
  1108. {
  1109.   switch( options.speedMethod )
  1110.   {
  1111.     case 0: {
  1112.               DWORD speed;
  1113.               PROCESSOR_POWER_INFORMATION ppi;
  1114.               BOOL x = (CallNtPowerInformation(ProcessorInformation,
  1115.                                                NULL,
  1116.                                                0,
  1117.                                                &ppi,
  1118.                                                sizeof(ppi)) == ERROR_SUCCESS);
  1119.               if( x )
  1120.               {
  1121. /*
  1122.                 log( "curspeed:%d maxspeed:%d limit:%d Maxidlestate:%d Currentidlestate:%d",
  1123.                      ppi.CurrentMhz, 
  1124.                      ppi.MaxMhz, 
  1125.                      ppi.MhzLimit, 
  1126.                      ppi.MaxIdleState, 
  1127.                      ppi.CurrentIdleState );
  1128. */
  1129.                 speed = ppi.CurrentMhz;
  1130.                 m_szCPUSpeed.Format( _T("%d MHz"), speed );
  1131.               }
  1132.               else
  1133.               {
  1134.                 m_szCPUSpeed = _T("???");
  1135.                 speed = 0;
  1136.               }
  1137.  
  1138.               BYTE z = (BYTE)(speed / 100);
  1139.               if( speed%100 >= 90 )
  1140.                 z++;
  1141.  
  1142.               speedArr[speedIndex++] = z;
  1143.               if( speedIndex >= 1200 )
  1144.                 speedIndex = 0;
  1145.  
  1146.               curSpeed = speed;
  1147.             }
  1148.             break;
  1149.  
  1150.     case 1:
  1151.             {
  1152.               int x = cpuSpeedHT();
  1153.               if( x == 0 )
  1154.                 m_szCPUSpeed = _T("???");
  1155.               else
  1156.                 m_szCPUSpeed.Format( _T("%d MHz"), x );
  1157.  
  1158.               BYTE z = (BYTE)(x / 100);
  1159.               if( (x)%100 >= 90 )
  1160.                 z++;
  1161.  
  1162.               speedArr[speedIndex++] = z;
  1163.               if( speedIndex >= 1200 )
  1164.                 speedIndex = 0;
  1165.               
  1166.               curSpeed = x;
  1167.             }
  1168.             break;
  1169.  
  1170.     case 2:
  1171.             {
  1172.               CPUSpeed sp;
  1173.               int x = sp.CPUSpeedInMHz;
  1174.               if( x == 0 )
  1175.                 m_szCPUSpeed = _T("???");
  1176.               else
  1177.                 m_szCPUSpeed.Format( _T("%d MHz"), x );
  1178.  
  1179.               BYTE z = (BYTE)(x / 100);
  1180.               if( (x)%100 >= 90 )
  1181.                 z++;
  1182.  
  1183.               speedArr[speedIndex++] = z;
  1184.               if( speedIndex >= 1200 )
  1185.                 speedIndex = 0;
  1186.               
  1187.               curSpeed = x;
  1188.             }
  1189.             break;
  1190.   }
  1191. }
  1192.  
  1193. //**************************************************************
  1194. // read the current CPU load
  1195. //**************************************************************
  1196. void CSpeedswitchXPDlg::readCPULoad() 
  1197. {
  1198.   DWORD t = cpuUsageNT();
  1199.   static DWORD oldUsage = 0;
  1200.  
  1201.   if( t > 100 )
  1202.     t = oldUsage;
  1203.  
  1204.   m_szCPULoad.Format( _T("%d %%"), t );
  1205.  
  1206.   loadArr[loadIndex++] = (BYTE)t;
  1207.   if( loadIndex >= 1200 )
  1208.     loadIndex = 0;
  1209.  
  1210.   curLoad = t;
  1211. }
  1212.  
  1213. //**************************************************************
  1214. // draw the history diagram
  1215. //**************************************************************
  1216. void CSpeedswitchXPDlg::drawDiagram()
  1217. {
  1218.   CPaintDC dc( this );
  1219.   CBrush bBlackBrush( RGB(0,0,0) );                     // Schwarz als Pinsel
  1220.   CPen bRed( PS_SOLID, 1, RGB(255,0,0) );               // Rot
  1221.   CPen bYellow( PS_SOLID, 1, RGB(255,255,0) );          // Gelb
  1222.   CPen bWhite( PS_SOLID, 1, RGB(255,255,255) );         // Wei▀
  1223.   CPen bGreen( PS_SOLID,1,RGB(0,255,0) );               // Grⁿn
  1224.   CPen bMagenta( PS_SOLID, 1, RGB(255,0,255) );         // Magenta
  1225.   CPen bCyan( PS_SOLID, 1, RGB(0,255,255) );            // Cyan
  1226.   CPen bWhiteDotted( PS_DOT, 1, RGB(255,255,255) );     // Wei▀ gestrichelt fⁿr Skala
  1227.  
  1228. #define XBASE (cpuFrame.left)
  1229. #define YBASE (cpuFrame.top)
  1230.  
  1231.   // Bereich anschwΣrzen ;-)
  1232.   dc.SetBkMode( TRANSPARENT );
  1233.   dc.FillRect( &cpuFrame, &bBlackBrush );
  1234.  
  1235.   // gestrichelte Linien im Diagramm bei 25er-, 50er- und 75er-Skala zeichnen
  1236.   CPen* old = dc.SelectObject( &bWhiteDotted );
  1237.   dc.MoveTo( XBASE+1, YBASE+50 );
  1238.   dc.LineTo( XBASE+351, YBASE+50 );
  1239.   dc.MoveTo( XBASE+1, YBASE+50+25 );
  1240.   dc.LineTo( XBASE+351, YBASE+50+25 );
  1241.   dc.MoveTo( XBASE+1, YBASE+50-25 );
  1242.   dc.LineTo( XBASE+351, YBASE+50-25 );
  1243.  
  1244.   if( options.showDiagram )
  1245.   {
  1246.     int x = loadIndex-117-diagramOffset;
  1247.     int run = 0;
  1248.  
  1249.     if( options.readCPULoad )
  1250.     {
  1251.       dc.SelectObject( &bYellow );
  1252.    
  1253.       while( run <= 348 )
  1254.       {
  1255.         while( x < 0 )
  1256.           x = 1200+x;
  1257.  
  1258.         int a=loadArr[x];
  1259.         if( run == 0 )
  1260.           dc.MoveTo( XBASE+1+run+1, YBASE+100-a );
  1261.  
  1262.         dc.LineTo( XBASE+1+run+1, YBASE+100-a );
  1263.  
  1264.         x++;
  1265.         run += 3;
  1266.  
  1267.         if( x >= 1200 )
  1268.           x = 0;
  1269.       }
  1270.     }
  1271.  
  1272.     if( options.readCPUSpeed )
  1273.     {
  1274.       x = loadIndex-117-diagramOffset;
  1275.       run = 0;
  1276.  
  1277.       dc.SelectObject( &bRed );
  1278.    
  1279.       while( run <= 348 )
  1280.       {
  1281.         while( x < 0 )
  1282.           x = 1200+x;
  1283.  
  1284.         int a=speedArr[x] * options.freqScaling;
  1285.         if( a > 100 )
  1286.           a = 100;
  1287.  
  1288.         if( run == 0 )
  1289.           dc.MoveTo( XBASE+1+run+1, YBASE+100-a );
  1290.  
  1291.         dc.LineTo( XBASE+1+run+1, YBASE+100-a );
  1292.  
  1293.         x++;
  1294.         run += 3;
  1295.  
  1296.         if( x >= 1200 )
  1297.           x = 0;
  1298.       }
  1299.     }
  1300.   }
  1301.  
  1302.   dc.SelectObject( GetFont() );
  1303.   dc.SetBkMode( OPAQUE );
  1304.   dc.SetBkColor( RGB(0,0,0) );
  1305.  
  1306.   dc.SetTextColor( RGB(255,0,0) );
  1307.   dc.TextOut( legendFrame.left+10, legendFrame.top+25, legend1 );
  1308.  
  1309.   dc.SetTextColor( RGB(255,255,0) );
  1310.   dc.TextOut( legendFrame.left+10, legendFrame.top+45, legend2 );
  1311.  
  1312. #undef XBASE
  1313. #undef YBASE
  1314. }
  1315.  
  1316. //**************************************************************
  1317. // retrieve string for a particular windows error code
  1318. //**************************************************************
  1319. TCHAR* CSpeedswitchXPDlg::getWinErr( DWORD errcode )
  1320. {
  1321.   static TCHAR msg[256];
  1322.   
  1323.   FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM,
  1324.                  NULL,
  1325.                  errcode,
  1326.                  MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
  1327.                  msg,
  1328.                  255,
  1329.                  NULL );
  1330.  
  1331.   TCHAR* t = msg + _tcslen(msg) - 1;
  1332.  
  1333.   while( t > msg )
  1334.   {
  1335.     if( isspace(*t) )
  1336.       t--;
  1337.     else
  1338.       break;
  1339.   }
  1340.  
  1341.   t[1]='\0';
  1342.   return msg;  
  1343. }
  1344.  
  1345. //**************************************************************
  1346. // handler for 'Detect max speed' button
  1347. //**************************************************************
  1348. void CSpeedswitchXPDlg::OnBnClickedButton2()
  1349. {
  1350.   AfxGetApp()->DoWaitCursor(1);
  1351.  
  1352.   int aktuell = options.ac ? acThrottle : dcThrottle;
  1353.  
  1354.   // switch to max performance:
  1355.   setState( options.ac, PO_THROTTLE_NONE );
  1356.  
  1357.   // wait for 2 seconds to make sure switching took place (this causes 100% CPU load)
  1358.   time_t x = time(NULL) + 2;
  1359.   while( time(NULL) < x )     
  1360.     ;
  1361.  
  1362.   int f = cpuSpeedHT();
  1363.   options.maxSpeed = f;
  1364.  
  1365.   m_szMaxCPUSpeed.Format( _T("~%d MHz"), options.maxSpeed );
  1366.  
  1367.   setRegKeys();
  1368.  
  1369.   // switch back to original policy:
  1370.   setState( options.ac, aktuell );
  1371.  
  1372.   UpdateData( FALSE );
  1373.   AfxGetApp()->DoWaitCursor(-1);
  1374. }
  1375.  
  1376. //**************************************************************
  1377. // control battery icon display
  1378. //**************************************************************
  1379. void CSpeedswitchXPDlg::batteryDisplay( SYSTEM_POWER_STATUS* sps )
  1380. {
  1381.   if( sps == NULL )
  1382.   {
  1383.     if( !GetSystemPowerStatus(&pwrStatus) )
  1384.     {  
  1385.       options.showBattery = FALSE;
  1386.       setRegKeys();
  1387.       CString s1;
  1388.       s1.LoadStringW( IDS_MAINERR9 );
  1389.       MessageBox( s1, err, MB_ICONEXCLAMATION|MB_OK );
  1390.       return;
  1391.     }
  1392.  
  1393.     sps = &pwrStatus;
  1394.   }
  1395.  
  1396.   log( _T("AC-Status:%d batteryIcon:%d chargeIcon:%d method:%d chargeIndicator:%d batteryFlag:%d"),
  1397.        sps->ACLineStatus, batteryIconActive, batteryIconCharge, options.batteryMethod,
  1398.        options.chargeIndicator, sps->BatteryFlag );
  1399.  
  1400.   if( sps->ACLineStatus == 0 )    // running on battery
  1401.   {
  1402.     if( !batteryIconActive )
  1403.       showBatteryIcon( NIM_ADD, iTrayBattery, sps );
  1404.     else
  1405.       showBatteryIcon( NIM_MODIFY, iTrayBattery, sps );
  1406.   }
  1407.   else                            // running on AC
  1408.   {
  1409.     if( options.batteryMethod == 0 )    // show only on DC
  1410.     {
  1411.       if( !options.chargeIndicator && batteryIconActive )
  1412.         removeBatteryIcon();
  1413.       else if( options.chargeIndicator )    // show charging status
  1414.       {
  1415.         if( sps->BatteryFlag & 8 )   // it is charging
  1416.         {  
  1417.           if( !batteryIconActive )
  1418.             showBatteryIcon( NIM_ADD, iBattCharge, sps );
  1419.           else 
  1420.             showBatteryIcon( NIM_MODIFY, iBattCharge, sps );
  1421.         }
  1422.         else                          // not charging
  1423.         {
  1424.           if( batteryIconActive )
  1425.             removeBatteryIcon();
  1426.         }
  1427.       }
  1428.     }
  1429.     else        // show always
  1430.     {
  1431.       if( !options.chargeIndicator )      // no charge showing
  1432.       {
  1433.         if( !batteryIconActive )
  1434.           showBatteryIcon( NIM_ADD, iTrayBattery, sps );
  1435.         else
  1436.           showBatteryIcon( NIM_MODIFY, iTrayBattery, sps );
  1437.       }
  1438.       else        // show charging status
  1439.       {
  1440.         if( sps->BatteryFlag & 8 )     // now charging
  1441.         {
  1442.           if( !batteryIconActive )
  1443.             showBatteryIcon( NIM_ADD, iBattCharge, sps );
  1444.           else
  1445.             showBatteryIcon( NIM_MODIFY, iBattCharge, sps );
  1446.         }
  1447.         else                            // not charging now
  1448.         {
  1449.           if( !batteryIconActive )
  1450.             showBatteryIcon( NIM_ADD, iTrayBattery, sps );
  1451.           else
  1452.             showBatteryIcon( NIM_MODIFY, iTrayBattery, sps );
  1453.         }
  1454.       }
  1455.     }
  1456.   }
  1457. }
  1458.  
  1459. //**************************************************************
  1460. // remove battery icon from tray area
  1461. //**************************************************************
  1462. void CSpeedswitchXPDlg::removeBatteryIcon()
  1463. {
  1464.   NOTIFYICONDATA nid;
  1465.   nid.cbSize = sizeof( NOTIFYICONDATA );
  1466.   nid.hWnd = m_hWnd;
  1467.   nid.uID = 701;
  1468.   nid.uCallbackMessage = WM_ICONNOTIFY;
  1469.   nid.hIcon = modBatteryIcon;
  1470.   Shell_NotifyIcon( NIM_DELETE, &nid );
  1471.   DestroyIcon( modBatteryIcon );
  1472.   batteryIconActive = FALSE;
  1473.   batteryIconCharge = FALSE;
  1474.   batteryValue = -2;
  1475. }
  1476.  
  1477. // 10 digits (0-9) α 16 bytes: 2 bytes per row (16 pixels) * 8 rows = 16x8 matrix
  1478. // + 2 digits for a compressed '100' (special case for CPU usage)
  1479. // + 1 digit for '-' as unreported fan speed digits
  1480. static unsigned char digits[17][16] = 
  1481. {
  1482.   // digits 0-9:
  1483.   { 0xf0,0x0f,0xcf,0xf3,0xcf,0xf3,0xcf,0xf3,0xcf,0xf3,0xcf,0xf3,0xcf,0xf3,0xf0,0x0f },
  1484.   { 0xfc,0xff,0xf0,0xff,0xc0,0xff,0xfc,0xff,0xfc,0xff,0xfc,0xff,0xfc,0xff,0xc0,0x0f },
  1485.   { 0xf0,0x0f,0xcf,0xf3,0xff,0xf3,0xff,0xcf,0xff,0x3f,0xfc,0xff,0xf3,0xff,0xc0,0x03 },
  1486.   { 0xf0,0x0f,0xcf,0xf3,0xff,0xf3,0xff,0x0f,0xff,0xf3,0xff,0xf3,0xcf,0xf3,0xf0,0x0f },
  1487.   { 0xff,0x3f,0xfc,0x3f,0xf3,0x3f,0xcf,0x3f,0x00,0x03,0xff,0x3f,0xff,0x3f,0xf0,0x03 },
  1488.   { 0xc0,0x03,0xcf,0xff,0xcf,0xff,0xc0,0x0f,0xff,0xf3,0xff,0xf3,0xcf,0xf3,0xf0,0x0f },
  1489.   { 0xfc,0x0f,0xf3,0xff,0xcf,0xff,0xc0,0x0f,0xcf,0xf3,0xcf,0xf3,0xcf,0xf3,0xf0,0x0f },
  1490.   { 0xc0,0x0f,0xcf,0xcf,0xff,0x3f,0xff,0x3f,0xfc,0xff,0xfc,0xff,0xf3,0xff,0xf3,0xff },
  1491.   { 0xf0,0x0f,0xcf,0xf3,0xcf,0xf3,0xf0,0x0f,0xcf,0xf3,0xcf,0xf3,0xcf,0xf3,0xf0,0x0f },
  1492.   { 0xf0,0x0f,0xcf,0xf3,0xcf,0xf3,0xcf,0xf3,0xf0,0x03,0xff,0xf3,0xff,0xcf,0xf0,0x3f },
  1493.  
  1494.   // 2 additional digits for '100':
  1495.   { 0xf3,0xf0,0xc3,0xcf,0x03,0xcf,0xf3,0xcf,0xf3,0xcf,0xf3,0xcf,0xf3,0xcf,0x00,0x30 },
  1496.   { 0x3f,0x03,0xcc,0xfc,0xcc,0xfc,0xcc,0xfc,0xcc,0xfc,0xcc,0xfc,0xcc,0xfc,0x3f,0x03 },
  1497.  
  1498.   // 1 additional character for '-':
  1499.   { 0xff,0xff,0xff,0xff,0xff,0xff,0xc0,0x03,0xc0,0x03,0xff,0xff,0xff,0xff,0xff,0xff },
  1500.  
  1501.   // 4 additional characters for 'Sl' and 'Hi':
  1502.   { 0xf0,0x03,0xcf,0xff,0xcf,0xff,0xcf,0xff,0xf0,0x0f,0xff,0xf3,0xff,0xf3,0xc0,0x0f },
  1503.   { 0xcf,0xff,0xcf,0xff,0xcf,0xff,0xcf,0xff,0xcf,0xff,0xcf,0xff,0xcf,0xff,0xf0,0x0f },
  1504.   { 0xcf,0xf3,0xcf,0xf3,0xcf,0xf3,0xcf,0xf3,0xc0,0x03,0xcf,0xf3,0xcf,0xf3,0xcf,0xf3 },
  1505.   { 0xff,0xff,0xff,0xff,0xfc,0xff,0xff,0xff,0xfc,0xff,0xfc,0xff,0xfc,0xff,0xf0,0x3f }
  1506. };
  1507.  
  1508. // 10 digits (0-9) α 8 bytes: 1 byte per row (8 pixels) * 8 rows = 8x8 matrix
  1509. static unsigned char digits2[10][8] = 
  1510. {
  1511.   { 0x3c,0x42,0x42,0x42,0x42,0x42,0x42,0x3c },
  1512.   { 0x10,0x30,0x70,0x10,0x10,0x10,0x10,0x7c },
  1513.   { 0x3c,0x42,0x02,0x04,0x08,0x10,0x20,0x7e },
  1514.   { 0x3c,0x42,0x02,0x0c,0x02,0x02,0x42,0x3c },
  1515.   { 0x0c,0x1c,0x2c,0x4c,0xfe,0x0c,0x0c,0x3e },
  1516.   { 0x7e,0x40,0x40,0x7c,0x02,0x02,0x42,0x3c },
  1517.   { 0x1c,0x20,0x40,0x7c,0x42,0x42,0x42,0x3c },
  1518.   { 0x7c,0x44,0x08,0x08,0x10,0x10,0x20,0x20 },
  1519.   { 0x3c,0x42,0x42,0x3c,0x42,0x42,0x42,0x3c },
  1520.   { 0x3c,0x42,0x42,0x42,0x3e,0x02,0x04,0x38 }
  1521. };
  1522.  
  1523. //**************************************************************
  1524. // create battery icon and show/modify it
  1525. //**************************************************************
  1526. void CSpeedswitchXPDlg::showBatteryIcon( int msg, HICON icon, SYSTEM_POWER_STATUS* sps )
  1527. {
  1528.   int newval;
  1529.   int chargeLeft;
  1530.   int timeLeft;
  1531.   BOOL chargeIconNow = FALSE;
  1532.  
  1533.   chargeLeft = sps->BatteryLifePercent;
  1534.   if( chargeLeft<0 || chargeLeft>100 )
  1535.     chargeLeft = 999;
  1536.  
  1537.   if( sps->ACLineStatus == 0 )    // running on battery
  1538.   {
  1539.     timeLeft = sps->BatteryLifeTime;
  1540.     if( timeLeft < 0 )
  1541.       timeLeft = 999;
  1542.     else
  1543.       timeLeft /= 60;
  1544.   }
  1545.   else                            // on AC
  1546.     timeLeft = 999;
  1547.  
  1548.   if( icon == iBattCharge )
  1549.     chargeIconNow = TRUE;
  1550.  
  1551.   if( options.batteryIndicator==0 || chargeIconNow )     // show percentage
  1552.     newval = (chargeLeft==999 ? -3 : chargeLeft);
  1553.   else                                    // show time left
  1554.     newval = (timeLeft==999 ? -3 : timeLeft);
  1555.  
  1556.   CString s1, s2, s3;
  1557.   s1.LoadStringW( IDS_MAIN28 );
  1558.   s2.LoadStringW( IDS_MAIN30 );
  1559.   s3.LoadStringW( IDS_MAIN29 );
  1560.  
  1561.   if( msg==NIM_MODIFY && newval==batteryValue && batteryIconCharge==chargeIconNow )
  1562.   {
  1563.     NOTIFYICONDATA nid;
  1564.     static TCHAR tp[128];
  1565.  
  1566.     nid.cbSize = sizeof( NOTIFYICONDATA );
  1567.     nid.hWnd = m_hWnd;
  1568.     nid.uID = 701;
  1569.     nid.uFlags = NIF_TIP;
  1570.  
  1571.     CString temp;
  1572.     temp.Format( _T("%d%%"), chargeLeft );
  1573.  
  1574.     wsprintf( tp, s1,
  1575.               chargeLeft==999 ? s2 : temp );
  1576.  
  1577.     if( timeLeft != 999 )
  1578.     {
  1579.       CString s1;
  1580.       s1.LoadStringW( IDS_MAIN29 );
  1581.       wsprintf( &tp[_tcslen(tp)], s3, timeLeft );
  1582.     }
  1583.  
  1584.     lstrcpy( nid.szTip, tp );
  1585.  
  1586.     Shell_NotifyIcon( msg, &nid );
  1587.     return;
  1588.   }
  1589.  
  1590.   if( msg == NIM_MODIFY )
  1591.     DestroyIcon( modBatteryIcon );
  1592.  
  1593.   // create new icon:
  1594.   ICONINFO iconinfo;
  1595.   ICONINFO d2;
  1596.  
  1597.   GetIconInfo( icon, &d2 );
  1598.  
  1599.   iconinfo.hbmMask = d2.hbmMask;
  1600.   iconinfo.hbmColor = d2.hbmColor;
  1601.  
  1602.   CBitmap* mask = CBitmap::FromHandle( iconinfo.hbmMask );
  1603.   BITMAP maskMap;
  1604.   mask->GetBitmap( &maskMap );
  1605.   int size = maskMap.bmHeight * maskMap.bmWidthBytes;   // 128 Bytes (32x32 monochrom)
  1606.   log( _T("Bitmap size: %d"), size );
  1607.   mask->GetBitmapBits( size, bitmap );
  1608.  
  1609.   int num0 = (newval/100)%10;   // first decimal digit
  1610.   int num1 = (newval/10)%10;    // second decimal digit
  1611.   int num2 = newval%10;         // third decimal digit
  1612.   int j=0;
  1613.  
  1614.   if( newval == -3 )     // special value for deactivated ("--")
  1615.   {
  1616.     num0 = 0;
  1617.     num1 = 12;
  1618.     num2 = 12;
  1619.   }
  1620.  
  1621.   if( num0 != 0 )   // display three digits
  1622.   {
  1623.     for( int i=16; i<31; i+=2 )
  1624.     {
  1625.       for( int m=0; m<2; m++ )   // each loop = 1 icon row
  1626.       {
  1627.         bitmap[(i+m)*4] = 0xff ^ (digits2[num0][j]>>2);
  1628.         bitmap[(i+m)*4+1] = 0xff ^ (digits2[num0][j]<<6 | digits2[num1][j]>>4);
  1629.         bitmap[(i+m)*4+2] = 0xff ^ (digits2[num1][j]<<4 | digits2[num2][j]>>6); 
  1630.         bitmap[(i+m)*4+3] = 0xff ^ (digits2[num2][j]<<2);
  1631.       }
  1632.  
  1633.       j++;   // advance in digits2 array
  1634.     }
  1635.   }
  1636.   else              // only two digits
  1637.   {
  1638.     for( int i=16; i<=31; i+=2 )    // fill icon region
  1639.     {
  1640.       for( int m=0; m<2; m++ )   // each loop = 1 icon row
  1641.       {
  1642.         bitmap[(i+m)*4] = digits[num1][j];
  1643.         bitmap[(i+m)*4+1] = digits[num1][j+1];
  1644.         bitmap[(i+m)*4+2] = digits[num2][j];
  1645.         bitmap[(i+m)*4+3] = digits[num2][j+1];
  1646.       }
  1647.  
  1648.       j+=2;   // advance in digits array
  1649.     }
  1650.   }
  1651.  
  1652.   maskMap.bmBits = bitmap;
  1653.  
  1654.   CBitmap newMask;
  1655.   newMask.CreateBitmapIndirect( &maskMap );
  1656.  
  1657.   iconinfo.hbmMask = (HBITMAP)newMask.m_hObject;
  1658.   iconinfo.fIcon = TRUE;
  1659.  
  1660.   modBatteryIcon = ::CreateIconIndirect( &iconinfo );    
  1661.  
  1662.   NOTIFYICONDATA nid;
  1663.   static TCHAR tp[128];
  1664.  
  1665.   nid.cbSize = sizeof( NOTIFYICONDATA );
  1666.   nid.hWnd = m_hWnd;
  1667.   nid.uID = 701;
  1668.   nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
  1669.   nid.uCallbackMessage = WM_ICONNOTIFY;
  1670.  
  1671.   CString temp;
  1672.   temp.Format( _T("%d%%"), chargeLeft );
  1673.  
  1674.   wsprintf( tp, s1,
  1675.             chargeLeft==999 ? s2 : temp );
  1676.  
  1677.   if( timeLeft != 999 )
  1678.     wsprintf( &tp[_tcslen(tp)], s3, timeLeft );
  1679.  
  1680.   lstrcpy( nid.szTip, tp );
  1681.   nid.hIcon = modBatteryIcon;
  1682.  
  1683.   Shell_NotifyIcon( msg, &nid );
  1684.  
  1685.   batteryIconActive = TRUE;
  1686.   batteryIconCharge = chargeIconNow;
  1687.   batteryValue = newval;
  1688. }
  1689.  
  1690. //**************************************************************
  1691. // fill combo boxes on main window with current values
  1692. //**************************************************************
  1693. void CSpeedswitchXPDlg::initPowerBoxes()
  1694. {
  1695.   m_cDiskAC.SetCurSel( findDiskIndex(internalPolicy.user.SpindownTimeoutAc) );
  1696.   m_cDiskDC.SetCurSel( findDiskIndex(internalPolicy.user.SpindownTimeoutDc) );
  1697.   m_cDisplayAC.SetCurSel( findDefaultIndex(internalPolicy.user.VideoTimeoutAc) );
  1698.   m_cDisplayDC.SetCurSel( findDefaultIndex(internalPolicy.user.VideoTimeoutDc) );
  1699.  
  1700.   log( _T("ACAction: %d"), internalPolicy.user.IdleAc.Action );
  1701.   log( _T("ACIdletimeout:%d min"), internalPolicy.user.IdleTimeoutAc/60 );
  1702.   log( _T("ACHibtimeout:%d min"), internalPolicy.mach.DozeS4TimeoutAc );
  1703.  
  1704.   if( internalPolicy.user.IdleAc.Action == PowerActionHibernate )
  1705.   {
  1706.     m_cStandbyAC.SetCurSel( 15 );
  1707.     maxHibIndexAC = fillHibernationTimes( &m_cHibernationAC, hibernationTimesAC, 15, 3 );
  1708.     m_cHibernationAC.SetCurSel( 
  1709.                       findHibernationIndex(hibernationTimesAC,
  1710.                                            internalPolicy.user.IdleTimeoutAc,
  1711.                                            maxHibIndexAC) );
  1712.   }
  1713.   else
  1714.   {
  1715.     int sIdxAC = findDefaultIndex( internalPolicy.user.IdleTimeoutAc );
  1716.     m_cStandbyAC.SetCurSel( sIdxAC );
  1717.     maxHibIndexAC = fillHibernationTimes( &m_cHibernationAC, hibernationTimesAC, sIdxAC, 3 );
  1718.     int timeout = internalPolicy.mach.DozeS4TimeoutAc;
  1719.     if( timeout > 0 )
  1720.       timeout += internalPolicy.user.IdleTimeoutAc;
  1721.  
  1722.     m_cHibernationAC.SetCurSel( 
  1723.                       findHibernationIndex(hibernationTimesAC,
  1724.                                            timeout,
  1725.                                            maxHibIndexAC) );
  1726.   }
  1727.  
  1728.   log( _T("DCAction: %d"), internalPolicy.user.IdleDc.Action );
  1729.   log( _T("DCIdletimeout:%d min"), internalPolicy.user.IdleTimeoutDc/60 );
  1730.   log( _T("DCHibtimeout:%d min"), internalPolicy.mach.DozeS4TimeoutDc/60 );
  1731.  
  1732.   if( internalPolicy.user.IdleDc.Action == PowerActionHibernate )
  1733.   {
  1734.     m_cStandbyDC.SetCurSel( 15 );
  1735.     maxHibIndexDC = fillHibernationTimes( &m_cHibernationDC, hibernationTimesDC, 15, 3 );
  1736.     m_cHibernationDC.SetCurSel( 
  1737.                       findHibernationIndex(hibernationTimesDC,
  1738.                                            internalPolicy.user.IdleTimeoutDc,
  1739.                                            maxHibIndexDC) );
  1740.   }
  1741.   else
  1742.   {
  1743.     int sIdxDC = findDefaultIndex( internalPolicy.user.IdleTimeoutDc );
  1744.     m_cStandbyDC.SetCurSel( sIdxDC );
  1745.     maxHibIndexDC = fillHibernationTimes( &m_cHibernationDC, hibernationTimesDC, sIdxDC, 3 );
  1746.  
  1747.     int timeout = internalPolicy.mach.DozeS4TimeoutDc;
  1748.     if( timeout > 0 )
  1749.       timeout += internalPolicy.user.IdleTimeoutDc;
  1750.  
  1751.     m_cHibernationDC.SetCurSel( 
  1752.                       findHibernationIndex(hibernationTimesDC,
  1753.                                            timeout,
  1754.                                            maxHibIndexDC) );
  1755.  
  1756.   }
  1757. }
  1758.  
  1759. int CSpeedswitchXPDlg::findDefaultIndex( int val )
  1760. {
  1761.   for( int i=0; i<16; i++ )
  1762.     if( defaultTimes[i] == val )
  1763.       return i;
  1764.  
  1765.   return -1;    // return -1 as default if not found
  1766. }
  1767.  
  1768. int CSpeedswitchXPDlg::findDiskIndex( int val )
  1769. {
  1770.   for( int i=0; i<14; i++ )
  1771.     if( diskTimes[i] == val )
  1772.       return i;
  1773.  
  1774.   return -1;    // return -1 as default if not found
  1775. }
  1776.  
  1777. int CSpeedswitchXPDlg::findHibernationIndex( int* hibernation, int val, int maxIndex )
  1778. {
  1779.   for( int i=0; i<maxIndex; i++ )
  1780.     if( hibernation[i] == val )
  1781.       return i;
  1782.  
  1783.   return -1;    // return -1 as default if not found
  1784. }
  1785.  
  1786. //----------------------------------------------------------------
  1787. // what: 0=Display timeout
  1788. //       1=Disk timeout
  1789. //       2=Standby timeout
  1790. //       3=Hibernation timeout
  1791. //----------------------------------------------------------------
  1792. int CSpeedswitchXPDlg::fillHibernationTimes( CComboBox* box, int* hibernation, int idx, int what )
  1793. {
  1794.   int val;
  1795.   CString str, s1;
  1796.   int j=0;
  1797.  
  1798.   if( idx == 15 )
  1799.     idx = -1;   // start at 0
  1800.  
  1801.   box->ResetContent();
  1802.  
  1803.   for( int i=idx+1; i<17; i++ )
  1804.   {
  1805.     boolean nix = false;
  1806.  
  1807.     switch( i )
  1808.     {
  1809.       case 0: if( what == 1 )
  1810.                 nix = true;
  1811.               else
  1812.               {
  1813.                 val = 60;
  1814.                 s1.LoadStringW( IDS_MAIN39 );
  1815.                 str = s1;
  1816.               }
  1817.               break;
  1818.  
  1819.       case 1: if( what == 1 )
  1820.                 nix = true;
  1821.               else
  1822.               {
  1823.                 val = 120;
  1824.                 s1.LoadStringW( IDS_MAIN40 );
  1825.                 str = s1;
  1826.               }
  1827.               break;
  1828.  
  1829.       case 2: val = 180;
  1830.               s1.LoadStringW( IDS_MAIN41 );
  1831.               str = s1;
  1832.               break;
  1833.  
  1834.       case 3: val = 300;
  1835.               s1.LoadStringW( IDS_MAIN42 );
  1836.               str = s1;
  1837.               break;
  1838.  
  1839.       case 4: val = 600;
  1840.               s1.LoadStringW( IDS_MAIN43 );
  1841.               str = s1;
  1842.               break;
  1843.  
  1844.       case 5: val = 900;
  1845.               s1.LoadStringW( IDS_MAIN44 );
  1846.               str = s1;
  1847.               break;
  1848.  
  1849.       case 6: val = 1200;
  1850.               s1.LoadStringW( IDS_MAIN45 );
  1851.               str = s1;
  1852.               break;
  1853.  
  1854.       case 7: val = 1500;
  1855.               s1.LoadStringW( IDS_MAIN46 );
  1856.               str = s1;
  1857.               break;
  1858.  
  1859.       case 8: val = 1800;
  1860.               s1.LoadStringW( IDS_MAIN47 );
  1861.               str = s1;
  1862.               break;
  1863.  
  1864.       case 9: val = 2700;
  1865.               s1.LoadStringW( IDS_MAIN48 );
  1866.               str = s1;
  1867.               break;
  1868.  
  1869.       case 10:val = 3600;
  1870.               s1.LoadStringW( IDS_MAIN49 );
  1871.               str = s1;
  1872.               break;
  1873.  
  1874.       case 11:val = 3600*2;
  1875.               s1.LoadStringW( IDS_MAIN50 );
  1876.               str = s1;
  1877.               break;
  1878.  
  1879.       case 12:val = 3600*3;
  1880.               s1.LoadStringW( IDS_MAIN51 );
  1881.               str = s1;
  1882.               break;
  1883.  
  1884.       case 13:val = 3600*4;
  1885.               s1.LoadStringW( IDS_MAIN52 );
  1886.               str = s1;
  1887.               break;
  1888.  
  1889.       case 14:val = 3600*5;
  1890.               s1.LoadStringW( IDS_MAIN53 );
  1891.               str = s1;
  1892.               break;
  1893.  
  1894.       case 15:if( what != 3 )
  1895.                 nix = true;
  1896.               else
  1897.               {
  1898.                 val = 3600*6;
  1899.                 s1.LoadStringW( IDS_MAIN54 );
  1900.                 str = s1;
  1901.               }
  1902.               break;
  1903.  
  1904.       case 16:val = 0;
  1905.               s1.LoadStringW( IDS_MAIN55 );
  1906.               str = s1;
  1907.               break;
  1908.     }
  1909.  
  1910.     if( !nix )
  1911.     {
  1912.       if( hibernation != NULL )
  1913.         hibernation[j++] = val;
  1914.  
  1915.       box->AddString( str );
  1916.     }
  1917.     else
  1918.       nix = false;
  1919.   }
  1920.  
  1921.   return j;
  1922. }
  1923.  
  1924. //**************************************************************
  1925. // handlers for selecting values from power combo boxes on main 
  1926. // window
  1927. //**************************************************************
  1928. void CSpeedswitchXPDlg::OnCbnSelchangeDisplayAC()
  1929. {
  1930.   internalPolicy.user.VideoTimeoutAc = defaultTimes[m_cDisplayAC.GetCurSel()];
  1931.   writePolicies( true, false );
  1932. }
  1933.  
  1934. void CSpeedswitchXPDlg::OnCbnSelchangeDisplayDC()
  1935. {
  1936.   internalPolicy.user.VideoTimeoutDc = defaultTimes[m_cDisplayDC.GetCurSel()];
  1937.   writePolicies( true, false );
  1938. }
  1939.  
  1940. void CSpeedswitchXPDlg::OnCbnSelchangeDiskAC()
  1941. {
  1942.   internalPolicy.user.SpindownTimeoutAc = diskTimes[m_cDiskAC.GetCurSel()];
  1943.   writePolicies( true, false );
  1944. }
  1945.  
  1946. void CSpeedswitchXPDlg::OnCbnSelchangeDiskDC()
  1947. {
  1948.   internalPolicy.user.SpindownTimeoutDc = diskTimes[m_cDiskDC.GetCurSel()];
  1949.   writePolicies( true, false );
  1950. }
  1951.  
  1952. void CSpeedswitchXPDlg::OnCbnSelchangeHibAC()
  1953. {
  1954.   log( _T("------------------------------") );
  1955.   log( _T("Start of 'OnCbnSelchangeHibAC'") );
  1956.  
  1957.   int n = hibernationTimesAC[m_cHibernationAC.GetCurSel()];
  1958.  
  1959.   log( _T("new ACHib val: %d min"), n/60 );
  1960.   log( _T("current ACIdletimeout: %d min"), internalPolicy.user.IdleTimeoutAc/60 );
  1961.   log( _T("GUI AC Standby selection: %d min"), defaultTimes[m_cStandbyAC.GetCurSel()]/60 );
  1962.  
  1963.   if( n!=0 && internalPolicy.user.IdleAc.Action!=PowerActionHibernate )
  1964.     n -= internalPolicy.user.IdleTimeoutAc;
  1965.  
  1966.   if( defaultTimes[m_cStandbyAC.GetCurSel()] == 0 )
  1967.   {
  1968.     internalPolicy.user.IdleTimeoutAc = n;
  1969.     internalPolicy.mach.DozeS4TimeoutAc = 0;
  1970.     internalPolicy.user.IdleAc.Action = PowerActionHibernate;
  1971.   }
  1972.   else
  1973.     internalPolicy.mach.DozeS4TimeoutAc = n;
  1974.  
  1975.   log( _T("new ACIdletimeout: %d min"), internalPolicy.user.IdleTimeoutAc/60 );
  1976.   log( _T("new ACHibtimeout: %d min"), internalPolicy.mach.DozeS4TimeoutAc/60 );
  1977.  
  1978.   writePolicies( true, false );
  1979.   log( _T("End of 'OnCbnSelchangeHibAC'") );
  1980. }
  1981.  
  1982. void CSpeedswitchXPDlg::OnCbnSelchangeHibDC()
  1983. {
  1984.   log( _T("------------------------------") );
  1985.   log( _T("Start of 'OnCbnSelchangeHibDC'") );
  1986.  
  1987.   int n = hibernationTimesDC[m_cHibernationDC.GetCurSel()];
  1988.  
  1989.   log( _T("new DCHib val: %d min"), n/60 );
  1990.   log( _T("current DCIdletimeout: %d min"), internalPolicy.user.IdleTimeoutDc/60 );
  1991.   log( _T("GUI DC Standby selection: %d min"), defaultTimes[m_cStandbyDC.GetCurSel()]/60 );
  1992.  
  1993.   if( n!=0 && internalPolicy.user.IdleDc.Action!=PowerActionHibernate )
  1994.     n -= internalPolicy.user.IdleTimeoutDc;
  1995.  
  1996.   if( defaultTimes[m_cStandbyDC.GetCurSel()] == 0 )
  1997.   {
  1998.     internalPolicy.user.IdleTimeoutDc = n;
  1999.     internalPolicy.mach.DozeS4TimeoutDc = 0;
  2000.     internalPolicy.user.IdleDc.Action = PowerActionHibernate;
  2001.   }
  2002.   else
  2003.     internalPolicy.mach.DozeS4TimeoutDc = n;
  2004.  
  2005.   log( _T("new DCIdletimeout: %d min"), internalPolicy.user.IdleTimeoutDc/60 );
  2006.   log( _T("new DCHibtimeout: %d min"), internalPolicy.mach.DozeS4TimeoutDc/60 );
  2007.  
  2008.   writePolicies( true, false );
  2009.   log( _T("End of 'OnCbnSelchangeHibDC'") );
  2010. }
  2011.  
  2012. void CSpeedswitchXPDlg::OnCbnSelchangeStandbyAC()
  2013. {
  2014.   int last;
  2015.  
  2016.   if( internalPolicy.user.IdleAc.Action == PowerActionHibernate )
  2017.     last = internalPolicy.user.IdleTimeoutAc;
  2018.   else
  2019.   {
  2020.     last = internalPolicy.mach.DozeS4TimeoutAc;
  2021.     if( last != 0 )
  2022.       last += internalPolicy.user.IdleTimeoutAc;
  2023.   }
  2024.  
  2025.   int n = defaultTimes[m_cStandbyAC.GetCurSel()];
  2026.  
  2027.   internalPolicy.user.IdleTimeoutAc = n;
  2028.  
  2029.   maxHibIndexAC = fillHibernationTimes( &m_cHibernationAC, hibernationTimesAC, m_cStandbyAC.GetCurSel(), 3 );
  2030.   log( _T("Searching for %d (%d) (max:%d)"), last, last/60, maxHibIndexAC );
  2031.   int x = findHibernationIndex( hibernationTimesAC, last, maxHibIndexAC );
  2032.   log( _T("Found:%d"), x );
  2033.   if( x == -1 )
  2034.     x = 0;
  2035.  
  2036.   n = hibernationTimesAC[x];
  2037.   if( n != 0 )
  2038.     n -= internalPolicy.user.IdleTimeoutAc;
  2039.  
  2040.   internalPolicy.mach.DozeS4TimeoutAc = n;
  2041.  
  2042.   m_cHibernationAC.SetCurSel( x );
  2043.  
  2044.   if( internalPolicy.user.IdleTimeoutAc==0 && internalPolicy.mach.DozeS4TimeoutAc!=0 )
  2045.   {
  2046.     internalPolicy.user.IdleTimeoutAc = internalPolicy.mach.DozeS4TimeoutAc;
  2047.     internalPolicy.mach.DozeS4TimeoutAc = 0;
  2048.     internalPolicy.user.IdleAc.Action = PowerActionHibernate;
  2049.   }
  2050.   else
  2051.     internalPolicy.user.IdleAc.Action = PowerActionSleep;
  2052.  
  2053.   writePolicies( true, false );
  2054. }
  2055.  
  2056. void CSpeedswitchXPDlg::OnCbnSelchangeStandbyDC()
  2057. {
  2058.   int last;
  2059.  
  2060.   if( internalPolicy.user.IdleDc.Action == PowerActionHibernate )
  2061.     last = internalPolicy.user.IdleTimeoutDc;
  2062.   else
  2063.   {
  2064.     last = internalPolicy.mach.DozeS4TimeoutDc;
  2065.     if( last != 0 )
  2066.       last += internalPolicy.user.IdleTimeoutDc;
  2067.   }
  2068.  
  2069.   int n = defaultTimes[m_cStandbyDC.GetCurSel()];
  2070.  
  2071.   internalPolicy.user.IdleTimeoutDc = n;
  2072.  
  2073.   maxHibIndexDC = fillHibernationTimes( &m_cHibernationDC, hibernationTimesDC, m_cStandbyDC.GetCurSel(), 3 );
  2074.   int x = findHibernationIndex( hibernationTimesDC, last, maxHibIndexDC );
  2075.   if( x == -1 )
  2076.     x = 0;
  2077.  
  2078.   n = hibernationTimesDC[x];
  2079.   if( n != 0 )
  2080.     n -= internalPolicy.user.IdleTimeoutDc;
  2081.  
  2082.   internalPolicy.mach.DozeS4TimeoutDc = n;
  2083.  
  2084.   m_cHibernationDC.SetCurSel( x );
  2085.  
  2086.   if( internalPolicy.user.IdleTimeoutDc==0 && internalPolicy.mach.DozeS4TimeoutDc!=0 )
  2087.   {
  2088.     internalPolicy.user.IdleTimeoutDc = internalPolicy.mach.DozeS4TimeoutDc;
  2089.     internalPolicy.mach.DozeS4TimeoutDc = 0;
  2090.     internalPolicy.user.IdleDc.Action = PowerActionHibernate;
  2091.   }
  2092.   else
  2093.     internalPolicy.user.IdleDc.Action = PowerActionSleep;
  2094.  
  2095.   writePolicies( true, false );
  2096. }
  2097.  
  2098. //**************************************************************
  2099. // handler for 'System Info' button
  2100. //**************************************************************
  2101. void CSpeedswitchXPDlg::OnBnClickedCPUData()
  2102. {
  2103.   CSystemInfo si;
  2104.   si.setVars();
  2105.   si.DoModal();
  2106. }
  2107.  
  2108. //**************************************************************
  2109. // handler for hidden 'Update' button (only used during development)
  2110. //**************************************************************
  2111. void CSpeedswitchXPDlg::OnBnClickedButton4()
  2112. {
  2113.   initPowerValues();
  2114. }
  2115.  
  2116. //**************************************************************
  2117. // read current power and CPU policy from registry
  2118. //**************************************************************
  2119. BOOL CSpeedswitchXPDlg::initPowerValues()
  2120. {
  2121.   static TCHAR msg[1024];   // fⁿr diverse Fehlertexte
  2122.  
  2123.   if( !CanUserWritePwrScheme() )
  2124.   {
  2125.     DWORD x = GetLastError();
  2126.     CString s1;
  2127.     s1.LoadStringW( IDS_MAIN31 );
  2128.     wsprintf( msg, s1, x, getWinErr(x) );
  2129.     MessageBox( msg, err, MB_OK|MB_ICONEXCLAMATION );
  2130.     PostMessage( WM_CLOSE );
  2131.     return FALSE;
  2132.   }
  2133.  
  2134.   UINT origScheme;
  2135.   if( !GetActivePwrScheme(&origScheme) )
  2136.   {
  2137.     DWORD x = GetLastError();
  2138.     CString s1;
  2139.     s1.LoadStringW( IDS_MAIN32 );
  2140.     wsprintf( msg, s1, x, getWinErr(x) );
  2141.     MessageBox( msg, err, MB_OK|MB_ICONEXCLAMATION );
  2142.     PostMessage( WM_CLOSE );
  2143.     return FALSE;
  2144.   }
  2145.  
  2146.   log( _T("Current power scheme no: %d"), origScheme );
  2147.  
  2148.   options.originalScheme = origScheme;
  2149.   options.setRegKeys();
  2150.  
  2151.   int x = detectProfile();
  2152.  
  2153.   log( _T("profile detect rc: %d"), x );
  2154.  
  2155.   if( x == -2 )
  2156.   {
  2157.     int y = createProfile();
  2158.     if( y != 0 )
  2159.     {
  2160.       DWORD x = GetLastError();
  2161.       CString s1;
  2162.       s1.LoadStringW( IDS_MAIN33 );
  2163.       wsprintf( msg, s1, y, x, getWinErr(x) );
  2164.       MessageBox( msg, err, MB_OK|MB_ICONEXCLAMATION );
  2165.       PostMessage( WM_CLOSE );
  2166.       return FALSE;
  2167.     }
  2168.   }
  2169.   else if( x < 0 )
  2170.   {
  2171.     DWORD z = GetLastError();
  2172.     CString s1;
  2173.     s1.LoadStringW( IDS_MAIN34 );
  2174.     wsprintf( msg, s1, x, z, getWinErr(z) );
  2175.     MessageBox( msg, err, MB_OK|MB_ICONEXCLAMATION );
  2176.     PostMessage( WM_CLOSE );
  2177.     return FALSE;
  2178.   }
  2179.  
  2180.   if( !GetSystemPowerStatus(&pwrStatus) )
  2181.   {
  2182.     CString s1;
  2183.     s1.LoadStringW( IDS_MAIN35 );
  2184.     MessageBox( s1, err, MB_ICONEXCLAMATION|MB_OK );
  2185.   }
  2186.   else
  2187.     options.ac = (pwrStatus.ACLineStatus!=0);
  2188.  
  2189.   setCPUIcon( options.ac ? acThrottle : dcThrottle );
  2190.  
  2191.   if( options.showBattery )
  2192.     batteryDisplay( &pwrStatus );
  2193.  
  2194.   if( options.speedIcon || options.loadIcon )
  2195.     displayCPUDataIcon( NIM_ADD );
  2196.  
  2197.   m_iACState = acThrottle;
  2198.   m_iDCState = dcThrottle;
  2199.  
  2200.   if( options.autoStart )
  2201.     setAutoStartRegistry();
  2202.  
  2203.   ((CScrollBar*)GetDlgItem(IDC_SCROLLBAR1))->SetScrollRange( 0, 90, FALSE );
  2204.   ((CScrollBar*)GetDlgItem(IDC_SCROLLBAR1))->SetScrollPos( 90, TRUE );
  2205.  
  2206.   if( options.checkStatus || options.readCPUSpeed || options.readCPULoad || options.showBattery )
  2207.   {
  2208.     if( SetTimer(timerID,1000,NULL) == timerID )
  2209.       activeTimer = TRUE;
  2210.     else
  2211.     {
  2212.       CString s1;
  2213.       s1.LoadStringW( IDS_MAIN36 );
  2214.       MessageBox( s1, err, MB_ICONERROR|MB_OK );
  2215.       PostMessage( WM_CLOSE );
  2216.       return FALSE;
  2217.     }
  2218.   }
  2219.  
  2220.   cpuUsageNT();     // let it run once to initialize itself (?)
  2221.  
  2222.   if( options.maxSpeed <= 0 )
  2223.     m_szMaxCPUSpeed = _T("???");
  2224.   else
  2225.     m_szMaxCPUSpeed.Format( _T("~%d MHz"), options.maxSpeed );
  2226.  
  2227.   defaultTimes[0] = 60;                       // 1 min
  2228.   defaultTimes[1] = 120;                      // 2 min
  2229.   defaultTimes[2] = diskTimes[0] = 180;       // 3 min
  2230.   defaultTimes[3] = diskTimes[1] = 300;       // 5 min
  2231.   defaultTimes[4] = diskTimes[2] = 600;       // 10 min
  2232.   defaultTimes[5] = diskTimes[3] = 900;       // 15 min
  2233.   defaultTimes[6] = diskTimes[4] = 1200;      // 20 min
  2234.   defaultTimes[7] = diskTimes[5] = 1500;      // 25 min
  2235.   defaultTimes[8] = diskTimes[6] = 1800;      // 30 min
  2236.   defaultTimes[9] = diskTimes[7] = 2700;      // 45 min
  2237.   defaultTimes[10] = diskTimes[8] = 3600;     // 1 hr
  2238.   defaultTimes[11] = diskTimes[9] = 7200;     // 2 hrs
  2239.   defaultTimes[12] = diskTimes[10] = 10800;   // 3 hrs
  2240.   defaultTimes[13] = diskTimes[11] = 14400;   // 4 hrs
  2241.   defaultTimes[14] = diskTimes[12] = 18000;   // 5 hrs
  2242.   defaultTimes[15] = diskTimes[13] = 0;       // Never
  2243.  
  2244.   initPowerBoxes();
  2245.  
  2246.   return TRUE;
  2247. }
  2248.  
  2249. //**************************************************************
  2250. // show/modify the CPU data tray icon
  2251. //**************************************************************
  2252. void CSpeedswitchXPDlg::displayCPUDataIcon( int msg )
  2253. {
  2254.   NOTIFYICONDATA_CD nid;
  2255.   BOOL prev = FALSE;
  2256.   TCHAR tp[192];
  2257.   int val1, val2, val3;
  2258.  
  2259.   if( !options.speedIcon || !options.readCPUSpeed )
  2260.     val1 = -3;
  2261.   else
  2262.   {
  2263.     val1 = curSpeed/100;
  2264.  
  2265.     int t = curSpeed%100;
  2266.     if( t >= 90 )
  2267.       val1++;
  2268.   }
  2269.  
  2270.   val3 = val1;    // use val3 for tooltip only
  2271.   if( val3 != -3 )
  2272.     val3 = curSpeed;
  2273.  
  2274.   if( !options.loadIcon || !options.readCPULoad )
  2275.     val2 = -3;
  2276.   else
  2277.     val2 = curLoad;
  2278.  
  2279.   if( msg==NIM_MODIFY && cpuIconVal1==val1 && cpuIconVal2==val2 )
  2280.     return;
  2281.   
  2282.   nid.cbSize = sizeof( NOTIFYICONDATA );
  2283.   nid.hWnd = m_hWnd;
  2284.   nid.uID = 702;
  2285.   nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
  2286.   nid.uCallbackMessage = WM_ICONNOTIFY;
  2287.  
  2288.   *tp = '\0';
  2289.  
  2290.   if( val1 != -3 )
  2291.   {
  2292.     prev = true;
  2293.     CString s1;
  2294.     s1.LoadStringW( IDS_MAIN37 );
  2295.     wsprintf( tp, s1, val3 );
  2296.   }
  2297.  
  2298.   if( val2 != -3 )
  2299.   {
  2300.     if( prev )
  2301.       _tcscat_s( tp, _T("\n") );
  2302.  
  2303.     prev = true;
  2304.     CString s1;
  2305.     s1.LoadStringW( IDS_MAIN38 );
  2306.     wsprintf( &tp[_tcslen(tp)], s1, val2 );
  2307.   } 
  2308.  
  2309.   lstrcpy( nid.szTip, tp );
  2310.  
  2311.   DestroyIcon( cpuDataIcon );    // we're not going to waste resources, so destroy old icon resource !
  2312.  
  2313.   if( options.speedIcon && options.loadIcon )
  2314.     cpuDataIcon = trayMan.createIcon( true, val1, true, val2 );
  2315.   else if( options.speedIcon )
  2316.     cpuDataIcon = trayMan.createIcon( true, val1, false, 0 );
  2317.   else
  2318.     cpuDataIcon = trayMan.createIcon( true, val2, false, 0 );
  2319.  
  2320.   nid.hIcon = cpuDataIcon;
  2321.  
  2322.   if( msg==NIM_MODIFY && !cpuDataIconActive )
  2323.     msg = NIM_ADD;
  2324.  
  2325.   Shell_NotifyIcon( msg, (PNOTIFYICONDATA)&nid );
  2326.  
  2327.   cpuDataIconActive = TRUE;
  2328.   cpuIconVal1 = val1; 
  2329.   cpuIconVal2 = val2;
  2330. }
  2331.  
  2332. //**************************************************************
  2333. // remove the CPU data tray icon
  2334. //**************************************************************
  2335. void CSpeedswitchXPDlg::removeCPUDataIcon()
  2336. {
  2337.   NOTIFYICONDATA_CD nid;
  2338.   nid.cbSize = sizeof( NOTIFYICONDATA );
  2339.   nid.hWnd = m_hWnd;
  2340.   nid.uID = 702;
  2341.   nid.uCallbackMessage = WM_ICONNOTIFY;
  2342.   nid.hIcon = cpuDataIcon;
  2343.   Shell_NotifyIcon( NIM_DELETE, (PNOTIFYICONDATA)&nid );
  2344.   DestroyIcon( cpuDataIcon );
  2345.   cpuDataIconActive = FALSE;
  2346.   cpuIconVal1 = -2;
  2347.   cpuIconVal2 = -2;
  2348. }
  2349.  
  2350. //**************************************************************
  2351. //**************************************************************
  2352. void CSpeedswitchXPDlg::fillPolicyStrings( CComboBox* box )
  2353. {
  2354.   CString s1;
  2355.   
  2356.   box->ResetContent();
  2357.  
  2358.   s1.LoadStringW( IDS_MAIN56 ); box->AddString( s1 );
  2359.   s1.LoadStringW( IDS_MAIN57 ); box->AddString( s1 );
  2360.   s1.LoadStringW( IDS_MAIN58 ); box->AddString( s1 );
  2361.   s1.LoadStringW( IDS_MAIN59 ); box->AddString( s1 );
  2362. }
  2363.