Working with Timers in Visual C++ by vkworld

Windows timers are mechanisms that let you set one or more timers to be triggered at a specific number of milliseconds. If you set a timer to be triggered at a 1,000 millisecond interval, it triggers every second. When a timer triggers, it sends a WM_TIMER message to your application. You can use the Class Wizard to add a function to your application to handle this timer message.

Timer events are placed only in the application event queue if that queue is empty and the application is idle. Windows does not place timer event messages in the application event queue if the application is already busy. If your application has been busy and has missed several timer event messages, Windows places only a single timer message in the event queue. Windows does not send your application all the timer event messages that occurred while your application was busy. It doesn’t matter how many timer messages your application may have missed; Windows still places only a single
timer message in your queue.

When you start or stop a timer, you specify a timer ID, which can be any integer value. Your application uses this timer ID to determine which timer event has triggered, as well as to start and stop timers.

Creating the Project and Application

To create the application, follow these steps:

1. Create a new project, named TimerEvent,  using the same AppWizard settings.
2. Choose SingleDocument
3. In the Step 6 , choose the base class as CFormView.
4. Select the Dialog from the Resources and the following controls as show in the Table.


TABLE CONTROL PROPERTY SETTINGS.

Object Property Setting
Static
Text
ID IDC_STATIC
Caption Current
Time:
Edit
Box
ID IDC_CURRTIME
Static
Text
ID IDC_STATIC
Caption User
Timer
Edit
Box
ID IDC_USERTIME
Static
Text
ID IDC_STATIC
Caption Task
Combo
Box
ID IDC_OPERATION
Button ID IDC_CANCEL
Caption Change
Usertime
Button ID IDC_EXIT
Caption Exit

Now, right click on the Combobox, go to properties window. Select the Tab DATA and enter the following data :

Lock
LogOff
ShutDown
Restart

 

Adding the Application Variables

You need to add a few variables to the controls. With the clock timer, you needed only a single variable for updating the clock display. Now you need to add a few other variables for the other controls, as listed in Table below. CONTROL VARIABLES:

Name
Category
Type

m_cCancel
Control
CButton

m_sCurrtime
Value
CString

m_cOperation
Control
CComboBox

m_sUsertime
Value
CString

m_cUTime
Control
CEdit

m_cExit
Control
CButton

Object
IDC_CANCEL IDC_CURRTIME IDC_OPERATION IDC_USERTIME IDC_USERTIME IDC_EXIT

 

After you add all the variables using the Class Wizard,

Adding the Timer IDs:

#ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif Add the following Code after this code in the TimerEventView.cpp:

#define  IDT_TIMER  WM_USER + 200 
int iHour,iMinute,iSecond;           
// Global Variables 
CString Label;               
BOOL Status=FALSE;

Add the following Variables in the TimerEventView.h in the public section

UINT Timeval;

Add the following function definitions in the TimerEventView.h .After this comment write the following code.

Protected:
//Generated message map functions
afx_msg UINT  StartTimer (UINT TimerDuration); 
// Start the Timer 
afx_msg BOOL StopTimer (UINT TimerVal);          
// Stop the Timer
afx_msg BOOL MyTask(CString strType);           
//Perform the Operation 
afx_msg void OnCheck();                                              
// Perform the Validation 
afx_msg void OnUnlock();                                        
// Unlock the System
Starting the Clock Timer:

To start the clock timer, you need to edit the OnInitUpdate function Add the new code:

void CShutEvtView::OnInitialUpdate()
{
CFormView::OnInitialUpdate();
GetParentFrame()->RecalcLayout();
ResizeParentToFit();
/*My Code Starts Here*/       
m_cUTime.SetFocus();
m_cCancel.EnableWindow(FALSE);
Timeval=StartTimer(1000);
SetWindowPos(&CWnd::wndTop, 670, 350, 0, 0, SWP_SHOWWINDOW|SWP_NOSIZE);
}

THE StartTimer FUNCTION:

UINT CTimerEventView::StartTimer (UINT TimerDuration)
{
UINT    TimerVal;
TimerVal = SetTimer (IDT_TIMER,TimerDuration, NULL);  // Starting the Timer
if (TimerVal == 0){
AfxMessageBox("Unable to obtain timer");
}
return TimerVal;
}// end StartTimer

THE StopTimer FUNCTION:

BOOL CTimerEventView::StopTimer (UINT TimerVal)
{
if (!KillTimer (TimerVal))        
{
return FALSE;
}
//    Place clean-up code following this point.
return TRUE;
} // end StopTimer

 

THE OnCancel FUNCTION:

void CTimerEventView::OnCancel()
{     
 m_cUTime.EnableWindow(TRUE);           
 //Enabling the Shutdown Time Edit Control           
 m_cExit.EnableWindow(TRUE);                                           //Enable Exit Button
m_cOperation.EnableWindow(TRUE);          
//Enable List Control
Status=TRUE;
}

THE OnExit FUNCTION:

void CTimerEventView::OnExit()
{
if(StopTimer(Timeval)==FALSE)
::MessageBox(NULL,”Error While
Killing the Timer”,”ShutEvt”,1);

::PostQuitMessage(1);

}

THE OnUnlock FUNCTION:

void CTimerEventView::OnUnlock()
{
WinExec("rundll32 user32.dll,LockWorkStation",1);  //Lock the System
}

THE OnCheck FUNCTION:
This functions is to validate the date entered by user

void CTimerEventView::OnCheck()
{
int iLHour,iLMinute;
CString tmpTime,subTime;
UpdateData();
tmpTime=m_sUserTime;
iLHour=tmpTime.Find(":",0);
subTime=tmpTime.Left(iLHour);
iHour=atoi(subTime);
if(iLHour==2 && iHour>=0 && iHour<=24)
{         
iLMinute=tmpTime.Find(":",iLHour);
subTime=tmpTime.Mid(iLHour+1);
subTime=subTime.Left(iLMinute);
iMinute=atoi(subTime);
if(iLMinute==2 && iMinute>=0 && iMinute<=60)
{

iSecond=atoi(tmpTime.Right(2));
if(iSecond>=0 && iSecond<=60)
{
	m_cUTime.EnableWindow(FALSE);          
	m_cCancel.EnableWindow(TRUE);
	m_cExit.EnableWindow(FALSE);
	m_cOperation.EnableWindow(FALSE);
}
else
::MessageBox(NULL,"Enter the Date in  HH:MM:SS nn OR nn Seconds Should be between 0 and 60","ShutEvt",1);
}
else
::MessageBox(NULL,"Enter the Date in HH:MM:SSnn OR nn Minutes Should be between 0 and 60","ShutEvt",1);
}
else
::MessageBox(NULL,"Enter the Date in HH:MM:SS nn OR nn Hour should be between 0 and 24","ShutEvt",1);

}

THE MyTask FUNCTION:

This function is to perform the task selected by user from the CComboBox

BOOL CTimerEventView::MyTask(CString strType)
{
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
// Stop the timer before shutdown
StopTimer(Timeval);
// Get a token for this process.
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
return( FALSE );
// Get the LUID for the shutdown privilege.
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
tkp.PrivilegeCount = 1;  //one privilege to set   
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// Get the shutdown privilege for this process.

AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
if (GetLastError() != ERROR_SUCCESS)
 return FALSE;

// Shut down the system and force all applications to close.
// if (!ExitWindowsEx(EWX_POWEROFF | EWX_POWEROFF | EWX_FORCE, 0))
if(strType=="LogOff")
{
  if(!ExitWindowsEx(EWX_LOGOFF | EWX_FORCE, 0))
   return FALSE;
}
else if(strType=="ShutDown")
{
  if(!ExitWindowsEx(EWX_SHUTDOWN|EWX_POWEROFF| EWX_FORCE, 0))
   return FALSE;
}
else if(strType=="Restart")
{
if(!ExitWindowsEx(EWX_REBOOT| EWX_FORCE, 0))
 return FALSE;
}
return TRUE;

}

THE OnSelchangeOperation FUNCTION:

Add this function through ClassWizard for the Comboxbox Control.(CBN_SELCHANGE)

void CTimerEventView::OnSelchangeOperation()
{
Status=FALSE;
int Selection=m_cOperation.GetCurSel();
OnCheck();
m_cOperation.GetLBText(Selection,Label);
}

Handling the Clock Timer Event

Now that you’ve started a timer, you need to add the code to handle the timer event message. You can do this by following these steps:

1. Using the Class Wizard, add a variable to the IDC_STATIC control of type CString named m_sCurrtime.

2. Using the Class Wizard, add a function to handle the WM_TIMER message for the CTimerEvent object.

3. Edit the OnTimer function, adding the following code:

THE OnTimer FUNCTION.

void CTimerEventView::OnTimer(UINT nIDEvent)
{
 CTime ct=CTime::GetCurrentTime();
 char *str=new char[10];

UpdateData();
m_sCurrtime.Format(“%d : %d : %d “,ct.GetHour(),ct.GetMinute(),ct.GetSecond());
UpdateData(FALSE);

if(iHour==ct.GetHour() && iMinute==ct.GetMinute() && iSecond==ct.GetSecond() && Label==”Lock” && Status==FALSE)
{
OnUnlock();
m_cUTime.EnableWindow(TRUE);
//Enabling the Shutdown Time Edit Control
m_cExit.EnableWindow(TRUE);
//Enable Exit Button
m_cOperation.EnableWindow(TRUE);
//Enable List Control
//StopTimer(Timeval);
Status=TRUE;
}
if(iHour==ct.GetHour() && iMinute==ct.GetMinute() && iSecond==ct.GetSecond() && Label==”LogOff” && Status==FALSE)
{
MyTask (“LogOff”);
}
if(iHour==ct.GetHour() && iMinute==ct.GetMinute() && iSecond==ct.GetSecond() && Label==”ShutDown” && Status==FALSE)
{
MyTask (“ShutDown”);
}
if(iHour==ct.GetHour() && iMinute==ct.GetMinute() && iSecond==ct.GetSecond() && Label==”Restart” && Status==FALSE)
{
MyTask (“Restart”);
}
delete [] str;
CFormView::OnTimer(nIDEvent);
}

Download the Sample Project here.