Projects > KM-RW Project > KM-RWDlg-Impl_and_Play-Rec-Proc.h

Home | Projects | Links

 

KM-RW PROJECT

  

KM-RWDlg-Decl.h    KM-RWDlg-Impl_and_Play-Rec_Proc.h    KM-RWSettings.h    StoreStruct.h    cwfi.h

Download km-rw.exe (392 KB)        Download VC++ 8.0 Project (26.8 KB RAR Archive)        KM-RW Help


// CKMRWDlg dialog implementation (KM-RWDlg-Impl.h):

//================== CONSTRUCTION, INITIALIZATION & SUCH ============================================================

// This message is sent when app starts and finds out it is set up
// tostart playback automatically:

static UINT NEAR WM_KMRW_AUTOPLAY = RegisterWindowMessage("Automatic Playback");

// This one is sent at the end of each playback cycle when app
// is set up to play Journal more than once:

static UINT NEAR WM_KMRW_PLAYAGAIN = RegisterWindowMessage("Play Again");


BEGIN_MESSAGE_MAP(CKMRWDlg, CDialog)

ON_WM_PAINT()
ON_WM_QUERYDRAGICON()

ON_REGISTERED_MESSAGE(WM_KMRW_AUTOPLAY, AutoPlay)
ON_REGISTERED_MESSAGE(WM_KMRW_PLAYAGAIN, Play1Time)

ON_COMMAND(IDC_RECORD_BUTTON, DoRecord)
ON_COMMAND(IDC_PLAY_BUTTON, DoPlay)
ON_COMMAND(IDC_STOP_BUTTON, DoStop)
ON_COMMAND(IDC_PO_BUTTON, DoPSDialog)
ON_COMMAND(ID_INFO, DoHelpDlg)

END_MESSAGE_MAP()

//-------------------------------------------------------------------------------------------------------------------
// Wizard-created constructor:

CKMRWDlg::CKMRWDlg(CWnd* pParent /*=NULL*/)
: CDialog(CKMRWDlg::IDD, pParent), outstream(outstring,200)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
//-------------------------------------------------------------------------------------------------------------------
BOOL CKMRWDlg::OnInitDialog()
{
CDialog::OnInitDialog();

// Set the icon for this dialog.  The framework does this automatically
//  when the application's main window is not a dialog

SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon

// TODO: Add extra initialization here

//Get Controls:
recordBtn=(CButton *)GetDlgItem(IDC_RECORD_BUTTON);
playBtn=(CButton *)GetDlgItem(IDC_PLAY_BUTTON);
stopBtn=(CButton *)GetDlgItem(IDC_STOP_BUTTON);
outBox=(CListBox *)GetDlgItem(IDC_OUT_LIST);

//To make windows transparent:
lw.AddLayeredStyle(m_hWnd); // Modify the style
lw.SetTransparentPercentage(m_hWnd, 100); // Set the trasparency effect to __%

//Initialize the hook interface class:
cwfi.InitParent(this);

autoplay_in_progress=0;

//Load KMRW settings:
if(!settgs.LoadSettings()) {
WriteToBox("Failed to load settings from KMRWSettings.i44, defaults loaded.");
settgs.SaveSettings();
}

//Start AutoPlay if necessary:
if(settgs.PlayOnStartup) {PostMessage(WM_KMRW_AUTOPLAY);}

status=STOPPED;
UpdateUI();


return TRUE;  // return TRUE  unless you set the focus to a control
}
//-------------------------------------------------------------------------------------------------------------------
//This is wizard-created too:

void CKMRWDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting

SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;

// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
//-------------------------------------------------------------------------------------------------------------------
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.

HCURSOR CKMRWDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}

//====================== SOME OTHER UTILITIES =======================================================================
void CKMRWDlg::DoPSDialog(){
//Do the settings dialog:
PSDialog psd(this);
psd.DoModal();
//Save settings:
settgs.SaveSettings();
}
//-------------------------------------------------------------------------------------------------------------------
// This functionjust adds a string to the app's ListBox:

void CKMRWDlg::WriteToBox(CString strg){
outBox->AddString(strg);
//Seems like the only way known to humanity to scroll automatically:
outBox->SetCurSel(outBox->GetCurSel()+1);
}
//-------------------------------------------------------------------------------------------------------------------
//GLOBAL VERSION:

void WriteToBox(CString strg){
( (CKMRWDlg*)(AfxGetApp()->m_pMainWnd) )->WriteToBox(strg);
}

//==================== RECORDING FUNCTIONS ==========================================================================
// These functions start, maintain, pause and stop recording and playback:

void CKMRWDlg::DoRecord(){
ContinueRecording();
}
//-------------------------------------------------------------------------------------------------------------------
void CKMRWDlg::ContinueRecording(){
//if(status==RECORDING) return;
status=RECORDING;
UpdateUI();
PrevMessageTime=::GetCurrentTime();
// This will insert a callback hook that will record all events:
cwfi.HookupRecord();
}
//-------------------------------------------------------------------------------------------------------------------
void CKMRWDlg::PauseRecord(bool paused_by_user){
//remove hook first:
cwfi.UnhookRecord();
// Program will know if user paused recording by pressing <Ctrl+Break>,
// or system removed hook (in response to <Ctrl+Alt+Del> or I don't know what).

if(paused_by_user) status=REC_PAUSED_USER;
else status=REC_PAUSED_SYSTEM;
UpdateUI();

}
//-------------------------------------------------------------------------------------------------------------------
void CKMRWDlg::StopRecord(){
status=STOPPED;
WriteToBox("Recording Stopped.");
UpdateUI();
if(AfxMessageBox("Recording has been stopped, do you want to save Journal to file?",
MB_ICONQUESTION | MB_YESNO |MB_TASKMODAL)==IDYES){
SaveList();
}
//Every time recording or playback is stopped, Journal is discarded.
Journal.RemoveAll();
}

//================ PLAYBACK FUNCTIONS ===============================================================================
void CKMRWDlg::DoPlay(){ //PLAY FROM FILE
if(status==PLAYING) return;
if(status==PLAY_PAUSED_USER || status==PLAY_PAUSED_SYSTEM) {ContinuePlaying(); return;}

//Clear Journal:
Journal.RemoveAll();

//Load Journal:
if(!ReadList()) return;

//Start playback:
StartPlayingSession();
}
//-------------------------------------------------------------------------------------------------------------------
//This function called as a response to a WM_KMRW_AUTOPLAY message:

afx_msg LRESULT CKMRWDlg::AutoPlay(WPARAM wParam, LPARAM lParam){

//SHOW WARNING:
WriteToBox("             ATTENTION !!!");
WriteToBox("-------------------------------------------");
WriteToBox("KMRW is currently set up to start playback");
WriteToBox("automatically. Automatic playback will start");
WriteToBox("in 10 seconds. Once it starts, you can stop it");
WriteToBox("by pressing Ctrl+Break, and then clicking Stop");
WriteToBox("button. You can change this setting later.");
WriteToBox("-------------------------------------------");
WriteToBox("");

//Wait 10 seconds:
Sleep(10000);

autoplay_in_progress=1;

WriteToBox("Auto Playback Started");

//LOAD LIST WITHOUT FileDialog:
CString filepath=settgs.PlayFilePath;
if(filepath=="") return 0;
ifstream inf(filepath.GetString(),ios::binary);
CString status;
if(!inf) {
status=status+"Failed to open " +filepath+ " for reading";
WriteToBox(status);
return 0;
}
else {
Journal.RemoveAll();
StoreStruct tempsst;
while( inf.read((char*)&tempsst,sizeof(StoreStruct)) )
{ Journal.AddTail(tempsst); }
}

inf.close();

outstream.seekp(0);
outstream<<"Loaded "<<Journal.GetCount()<<" records from "<<filepath.GetString()<<ends;
WriteToBox(outstring);

//Start playback:
StartPlayingSession();

return 0;
}
//-------------------------------------------------------------------------------------------------------------------
void CKMRWDlg::StartPlayingSession(){
// Initializes Cycle count, the number of times whole Journal is played:
PlayCycleCount=1;
//START PLAYBACK:
Play1Time(0,0);
}
//-------------------------------------------------------------------------------------------------------------------
// This function is called in response to WM_KMRW_PLAYAGAIN message,
// which is sent when Journal has not been played the preset number of times yet:

afx_msg LRESULT CKMRWDlg::Play1Time(WPARAM wParam, LPARAM lParam){
// Initializes played event count
PlayEventCount=0;
tempss=&Journal.GetHead();
readPOS=Journal.GetHeadPosition();
ContinuePlaying();
return 0;
}
//-------------------------------------------------------------------------------------------------------------------
void CKMRWDlg::ContinuePlaying(){
status=PLAYING;
UpdateUI();
//This variable tells the callback if the next event is redy to be fed:
FeedNextMsg=true;
//Insert hook:
cwfi.HookupPlay();
}
//-------------------------------------------------------------------------------------------------------------------
void CKMRWDlg::PausePlay(bool paused_by_user){
// Remove hook first:
cwfi.UnhookPlay();
// Program will know if user paused playback by pressing <Ctrl+Break>,
// or system removed hook (in response to <Ctrl+Alt+Del> or I don't know what).

if(paused_by_user) status=PLAY_PAUSED_USER;
else status=PLAY_PAUSED_SYSTEM;

UpdateUI();
}
//-------------------------------------------------------------------------------------------------------------------
// This function is called when program is done playing Journal 1 time,
// i.e. at the end of the Journal.

void CKMRWDlg::StopPlay1Time(){
cwfi.UnhookPlay();

WriteToBox("Playback cycle ended.");
UpdateUI();

PlayCycleCount++;

//Play another cycle if needed:
if(PlayCycleCount <= settgs.PlayTimes) PostMessage(WM_KMRW_PLAYAGAIN);
else {
StopPlay();
//Close app if it was an automatic playback:
if(autoplay_in_progress) PostMessage(WM_CLOSE);
}
}
//-------------------------------------------------------------------------------------------------------------------
void CKMRWDlg::StopPlay(){

if(status==STOPPED) return;
status=STOPPED;
cwfi.UnhookPlay();
Journal.RemoveAll();
WriteToBox("Playback stopped.");
UpdateUI();
}

//====================== INTERRUPTION FUNCTIONS =====================================================================
// This function would respond to an interruption,
// determine who did it, and whether playback or
// recording was on at the time, to pause it appropriately
// and update UI.

void CKMRWDlg::InterruptionHandler(bool paused_by_user){
if(paused_by_user){WriteToBox("PAUSED BY USER");}
else {WriteToBox("PAUSED BY SYSTEM");}

if(status==RECORDING) PauseRecord(paused_by_user);
if(status==PLAYING) PausePlay(paused_by_user);
}
//-------------------------------------------------------------------------------------------------------------------
//To determine how to respond when <Stop> button is clicked:

void CKMRWDlg::DoStop(){
if(status==REC_PAUSED_USER || status==REC_PAUSED_SYSTEM || status==RECORDING) {StopRecord(); return;}
if(status==PLAY_PAUSED_USER || PLAY_PAUSED_SYSTEM || status==PLAYING) {StopPlay(); return;}
}

//================= UPDATE USER INTERFACE ===========================================================================
void CKMRWDlg::UpdateUI(){
if(status==STOPPED){ // STOPPED
ModifyStyleEx(WS_EX_TRANSPARENT,0);
recordBtn->SetWindowText("Record");
playBtn->SetWindowText("Play");
recordBtn->EnableWindow(1);
playBtn->EnableWindow(1);
stopBtn->EnableWindow(0);
this->SetWindowText("STOPPED - (KM-RW)");
lw.SetTransparentPercentage(m_hWnd, 100); // Set the trasparency effect to __%
}

else if(status==PLAYING){
ModifyStyleEx(0, WS_EX_TRANSPARENT);
recordBtn->SetWindowText("Record");
recordBtn->EnableWindow(0);
playBtn->EnableWindow(0);
stopBtn->EnableWindow(0);
SetWindowText("PLAYING-(KM-RW), <Ctrl+Break> to PAUSE");
lw.SetTransparentPercentage(m_hWnd, 35); // Set the trasparency effect to __%
}

else if(status==RECORDING){
ModifyStyleEx(0, WS_EX_TRANSPARENT);  
playBtn->SetWindowText("Play");
recordBtn->EnableWindow(0);
playBtn->EnableWindow(0);
stopBtn->EnableWindow(0);
SetWindowText("RECORDING - (KM-RW), <Ctrl+Break> to PAUSE");
lw.SetTransparentPercentage(m_hWnd, 35); // Set the trasparency effect to __%
}

else if(status==PLAY_PAUSED_USER){
ModifyStyleEx(WS_EX_TRANSPARENT,0);  
lw.SetTransparentPercentage(m_hWnd, 100); // Set the trasparency effect to __%
SetWindowText("PAUSED PLAYBACK - (KM-RW)");
recordBtn->SetWindowText("Record");
recordBtn->EnableWindow(0);
playBtn->SetWindowText("Continue Playback");
playBtn->EnableWindow(1);
stopBtn->EnableWindow(1);
}

else if(status==PLAY_PAUSED_SYSTEM){
ModifyStyleEx(WS_EX_TRANSPARENT,0);  
lw.SetTransparentPercentage(m_hWnd, 100); // Set the trasparency effect to __%
SetWindowText("PAUSED PLAYBACK - (KM-RW)");
recordBtn->SetWindowText("Record");
recordBtn->EnableWindow(0);
playBtn->SetWindowText("Continue Playback");
playBtn->EnableWindow(1);
stopBtn->EnableWindow(1);

}

else if(status==REC_PAUSED_USER){
ModifyStyleEx(WS_EX_TRANSPARENT,0);
lw.SetTransparentPercentage(m_hWnd, 100); // Set the trasparency effect to __%
SetWindowText("PAUSED RECORDING - (KM-RW)");
playBtn->SetWindowText("Play");
recordBtn->SetWindowText("Continue Recording");
recordBtn->EnableWindow(1);
playBtn->SetWindowText("Play");
playBtn->EnableWindow(0);
stopBtn->EnableWindow(1);

}

else if(status==REC_PAUSED_SYSTEM){
ModifyStyleEx(WS_EX_TRANSPARENT,0);
lw.SetTransparentPercentage(m_hWnd, 100); // Set the trasparency effect to __%
SetWindowText("PAUSED RECORDING - (KM-RW)");
playBtn->SetWindowText("Play");
recordBtn->SetWindowText("Continue Recording");
recordBtn->EnableWindow(1);
playBtn->EnableWindow(0);
playBtn->SetWindowText("Play");
stopBtn->EnableWindow(1);
}

else {
WriteToBox("This is not supposed to happen!");
WriteToBox("Please write to dev@intellimech.com");
WriteToBox("and say you have a KMRW status problem.");
}

this->UpdateWindow();
}

//===================== HELP DIALOG (DHTML) =========================================================================
//Runs the Help DHTML Dialog, when <Info> button is clicked, nothing fancy:

void CKMRWDlg::DoHelpDlg(){
CHelpDHTMLDialog infodlg(this);
infodlg.DoModal();
}

//===================== FILE PROCESSING =============================================================================
// Saves journal to disk:

bool CKMRWDlg::SaveList(){

CFileDialog fdlg(0,"i45","Journal.i45", OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_FILEMUSTEXIST,0,this);
fdlg.GetOFN().lpstrTitle="Save journal as:";
fdlg.GetOFN().lpstrFilter="KM-RW Journal Files (.i45)\0*.i45\0\0";

int result=fdlg.DoModal();
if(result!=IDOK) return 0;

CString filepath=fdlg.GetPathName();
if(filepath=="") return 0;

ofstream outf(filepath.GetString(), ios::binary);
CString status;
if(!outf) {
status=status+"Could not open "+filepath+ " for writing";
WriteToBox(status);
return 0;
}
else {
//Load the records:
POSITION currPOS=Journal.GetHeadPosition();
while(currPOS!=NULL) {
outf.write((char*)(&Journal.GetNext(currPOS)),sizeof(StoreStruct));
}

outf.close();

outstream.seekp(0);
outstream<<"Saved "<<Journal.GetCount()<<" records to "<<filepath.GetString()<<ends;
WriteToBox(outstring);
}

return 1;
}
//-------------------------------------------------------------------------------------------------------------------
// Loads Journal from disk:

bool CKMRWDlg::ReadList(){

CFileDialog fdlg(1,"i45", 0, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_FILEMUSTEXIST,0,this);
fdlg.GetOFN().lpstrTitle="Open journal:";
fdlg.GetOFN().lpstrFilter="KM-RW Journal Files (.i45)\0*.i45\0\0";

int result=fdlg.DoModal();
if(result!=IDOK) return 0;

CString filepath=fdlg.GetPathName();
if(filepath=="") return 0;
ifstream inf(filepath.GetString(),ios::binary);
CString status;
if(!inf) {
status=status+"Could not open "+filepath+ " for reading";
WriteToBox(status);
return 0;
}
else {
Journal.RemoveAll();

StoreStruct tempsst;

while( inf.read((char*)&tempsst,sizeof(StoreStruct)) )
{ Journal.AddTail(tempsst); }

inf.close();

outstream.seekp(0);
outstream<<"Loaded "<<Journal.GetCount()<<" records from "<<filepath.GetString()<<ends;
WriteToBox(outstring);
}
return 1;
}


#ifndef PL_REC_PROCS_H
#define PL_REC_PROCS_H

//-------------------------------------------------------------------------------------------------------------------
void CKMRWDlg::ProcessRecordHook(int code,WPARAM wparam,LPARAM lparam){
//Only processing HC_ACTION codes:
if(code!=HC_ACTION) return;

EVENTMSG * pMsg=(EVENTMSG *)lparam;
currMSG = *pMsg;

outstream.seekp(0);
outstream<<"             "<<Journal.GetCount()+1;

if(pMsg->message==WM_MOUSEMOVE) {outstream<<" Mouse Move: ";}
else if(pMsg->message==WM_LBUTTONDOWN) {outstream<<" Mouse Left Btn Down: ";}
else if(pMsg->message==WM_LBUTTONUP) {outstream<<" Mouse Left Btn Up: ";}
else if(pMsg->message==WM_RBUTTONDOWN) {outstream<<" Mouse Right Btn Down: ";}
else if(pMsg->message==WM_RBUTTONUP) {outstream<<" Mouse Right Btn Up: ";}
else if(pMsg->message==WM_MOUSEWHEEL) {outstream<<" Mouse Wheel: ";}
else if(pMsg->message==WM_MBUTTONDOWN) {outstream<<" Mouse Mid Btn Down: ";}
else if(pMsg->message==WM_MBUTTONUP) {outstream<<" Mouse Mid Btn Up: ";}

else if(pMsg->message==WM_KEYDOWN) {outstream<<" Keyboard key down: ";}
else if(pMsg->message==WM_KEYUP) {outstream<<" Keyboard key up: ";}
else if(pMsg->message==WM_SYSKEYDOWN) {outstream<<" Keyboard sys. key down: ";}
else if(pMsg->message==WM_SYSKEYUP) {outstream<<" Keyboard sys. key up: ";}
else {outstream<<" Unidentified event: ";}

currMSG.time=pMsg->time - PrevMessageTime;
PrevMessageTime=pMsg->time;

if(pMsg->hwnd) outstream<<pMsg->hwnd<<"  ";
outstream<<"("<<pMsg->paramL<<","<<pMsg->paramH<<")   +";
outstream<<currMSG.time;
outstream<<ends;

WriteToBox(outstring);



Journal.AddTail(StoreStruct(KMMSG, &currMSG));

}
//-------------------------------------------------------------------------------------------------------------------
LRESULT CALLBACK CKMRWDlg::ProcessPlayHook(int code,WPARAM wparam,LPARAM lparam){
//Process only HC_GETNEXT & HC_SKIP codes, call CallNextHookEx() on anything else.

//(*)System calls JournalPlaybackProc with HC_GETNEXT when a message is processed:
if(code==HC_GETNEXT){
//Stop playback when reached end of Journal:
if(readPOS==0) {StopPlay1Time(); return 0;}

//If Keyboard/Mouse message:
if(tempss->GetCommand()==KMMSG) {
//If ready to process next message (function was just called with HC_SKIP):
if(FeedNextMsg){
//Get next message from Journal, update POSITION pointer:
tempss=&Journal.GetNext(readPOS);
//Load message to lparam:
*(EVENTMSG *)lparam=tempss->GetMsg();
//Until system is ready to take another message:
FeedNextMsg=false;
}
//If not ready for next message, return 0;
else { *(EVENTMSG *)lparam=tempss->GetMsg(); return 0; }
}

//If not Keyboard/Mouse message:
else {  } //add code for extended messages

//DISPLAY MESSAGE INFO:

EVENTMSG * lparammsg=(EVENTMSG *)lparam;
outstream.seekp(0);
outstream<<"             "<<++PlayEventCount;

if(lparammsg->message==WM_MOUSEMOVE) {outstream<<" Mouse Move: ";}
else if(lparammsg->message==WM_LBUTTONDOWN) {outstream<<" Mouse Left Btn Down: ";}
else if(lparammsg->message==WM_LBUTTONUP) {outstream<<" Mouse Left Btn Up: ";}
else if(lparammsg->message==WM_RBUTTONDOWN) {outstream<<" Mouse Right Btn Down: ";}
else if(lparammsg->message==WM_RBUTTONUP) {outstream<<" Mouse Right Btn Up: ";}
else if(lparammsg->message==WM_MOUSEWHEEL) {outstream<<" Mouse Wheel: ";}

else if(lparammsg->message==WM_KEYDOWN) {outstream<<" Keyboard key down: ";}
else if(lparammsg->message==WM_KEYUP) {outstream<<" Keyboard key up: ";}
else if(lparammsg->message==WM_SYSKEYDOWN) {outstream<<" Keyboard sys. key down: ";}
else if(lparammsg->message==WM_SYSKEYUP) {outstream<<" Keyboard sys. key up: ";}
else if(lparammsg->message==WM_MBUTTONDOWN) {outstream<<" Mouse Mid Btn Down: ";}
else if(lparammsg->message==WM_MBUTTONUP) {outstream<<" Mouse Mid Btn Up: ";}
else {outstream<<" Unidentified message: ("<<lparammsg->message<<")  ";}

//if(lparammsg->hwnd) outstream<<lparammsg->hwnd<<"  ";
outstream<<"("<<lparammsg->paramL<<","<<lparammsg->paramH<<")   +";
outstream<<lparammsg->time;
outstream<<ends;

//Add info to list box:
WriteToBox(outstring);

//This return will make system wait fo lparammsg->time milliseconds:
return settgs.PlayAtRecSpeed ? lparammsg->time+1 : 20; // <- default delay is 20 ms.
//return lparammsg->time+1;
}

//(*)Framework passes this code when ready to accept next message:
else if(code==HC_SKIP) {
//Allow function to feed new message on next call:
FeedNextMsg=true;
return 0;
}

//(*)On any other code:
else return ::CallNextHookEx(cwfi.PlayHookHandle,code,wparam,lparam);

//return 0;
}

#endif


KM-RWDlg-Decl.h    KM-RWDlg-Impl_and_Play-Rec_Proc.h    KM-RWSettings.h    StoreStruct.h    cwfi.h

 Download km-rw.exe (392 KB)         Download VC++ 8.0 Project (26.8 KB RAR Archive)        KM-RW Help

 

Get WinRAR

 

 

Copyright © Yuri Bulankov 2004

 

Bugs/Comments: code@compilerabuse.com

Copyright (C) 2001-2006 Yuri Bulankov. All rights reserved.