How to declare pointer to member function ?
Today while browsing at CP MFC forums, I find these two reply intresting for problem mentioned in title.
Aescleal replied:-
Member function pointers are really handy when you want to call the same member function on every element of a collection. It's either that or write a shim functor to do the call for you. So instead of:
class functor{
public:
void operator()( object &obj )
{ obj.A(); }
};
std::for_each( data.begin(), data.end(), functor() );
you can use:
std::for_each( data.begin(), data.end(), std::mem_fun_ref( &object::A ) );
The first form is a real pain in the neck before C++0x as you can't define a local class or use a lamda. Your functor has to be defined "somewhere else" which can lead to a bit of flow interruption when you're reading code (for me anyway, your experience probably differs).
SuperMan replied:-
Consider the class -
class A{
public: void One() {}
};
Declaring and initializing a member function pointer would be -
void (A::*pmfn)() = &A::One;
Calling the method using the function pointer would be -
A obj;(obj.*pmfn)();
OR
A* ptr = new A;(A->*pmfn)();
String Manipulation!
Today I found a interesting post at CP, which states
"I've given a string like this:"S R Tendulkar". I've to get the third part in the string ie "Tendulkar" and randomly rearrange or replace the characters between 'd' to 'r'. ie I've to display "SR Tendulkar" as "S R Tendalkur" or as "S R Tendelker". My string is a std::string. How to do this?"
Aescleal commented as following :-
std::transform takes a range over which you want to do something, a destination and what you want to do. So if you wanted to convert all vowels to the next in a sequence you could do something like:
std::pair<char, char> vowel_step =
{
std::pair<char, char> ( 'a', 'e' ),
std::pair<char, char> ( 'e', 'i' ),
std::pair<char, char> ( 'i', 'o' ),
std::pair<char, char> ( 'o', 'u' ),
std::pair<char, char> ( 'u', 'a' )
};
std::map<char, char> vowel_map( &vowel_step[ 0 ], &vowel_step[ 5 ] );
class vowel_transformer
{
public:
char operator()( char c )
{
std::map<char, char>::const_iterator iter( vowel_map.find( c ) );
if( iter != vowel_map.end() )
return iter->second;
return c;
}
};
std::string aesc( "aescleal" );
std::transform( aesc.begin(), aesc.end(), aesc.begin(), vowel_transformer() );
That should convert "aescleal" into "eiscliel". To get the effect you want define a class to do the tranformation on a per-character basis and work out the range you want to operate on.
IPC: Using Window Message
There are numerous ways to communicate between two applications, in this post will tell you the way to communicate between two different app using raw window message. This is most simpler and primitive way of IPC communication.
Step of achieving IPC using Window Message:-
- Create Dialog based application, implement way to set caption of dialog box window (will let you know in next step, requirement behind it). Use WIN32 Api SetWindowText to change window caption.
void CMFCTwoWayCommunicationDlg::OnBnClickedButtonSetcaption() { CString tmpString; GetDlgItemText(IDC_EDIT_CAPTION,tmpString); if (!tmpString.IsEmpty()) { SetWindowText(tmpString); } } - Use FindWindow Api to find window handle of remote process, use #32770 as classname (its dialog window class name) and caption set in step 1 to find remote window.
void CMFCTwoWayCommunicationDlg::OnBnClickedButtonFindwindow() { CString tmpString; GetDlgItemText(IDC_EDIT_WINDOWCAPTION,tmpString); m_pRemoteWnd = NULL; // this CWnd* pointer declared in class m_pRemoteWnd=FindWindow(L"#32770",tmpString); if (m_pRemoteWnd != NULL) { MessageBox(L"Remote Window Found"); } } - Now add Message Handller for WM_APP+1 for handlling external message.
ON_MESSAGE(WM_APP+1,&CMFCTwoWayCommunicationDlg::OnApplicationMessage) LRESULT CMFCTwoWayCommunicationDlg::OnApplicationMessage(WPARAM wParam, LPARAM lParam) { CString strMsg; strMsg.Format(L"Message Recv: %d",lParam); MessageBox(strMsg,L"MSG RECV from Remote Client"); return 0; } - Use PostMessage Api to post message to remote window using Window Handle retrieved in step 2.
void CMFCTwoWayCommunicationDlg::OnBnClickedButtonSendmsg() { int iMsgToSend = GetDlgItemInt(IDC_EDIT_SENDMSG); if(m_pRemoteWnd != NULL) { m_pRemoteWnd->PostMessageW(WM_APP+1,0,iMsgToSend); } }
Output:-
Now you must be wondering why PostMessage not SendMessage, because PostMessage lineup message in remote window message queue and return. Even if application doesn’t exist it will work without exception.
Download code :- MFCTwoWayCommunication
Using IComparer interface in Managed C++!
IComparer is an useful interface provided to programmer to sort collection according to programmer wish. IComparer has one virtual function which need to be overload by programmer to sort.
Class T<> virtual int Compare(T x, T y)
Here is mine custom implementation to sort array/list in desending way.
using namespace System::Collections::Generic;
ref class RevCompare:public IComparer<int>
{
public:
virtual int Compare(int x, int y)
{
if (x > y)
return -1;
else
if (x == y)
return 0;
else
return 1;
};
};
points to remember while implementing managed interface :-
- Put ref before class, otherwise it treat it as unmanaged class.
- implemented function should be preceded by virtual keyword, if not you will receive following error.
“error C3766: 'RevCompare' must provide an implementation for the interface method 'int System::Collections::Generic::IComparer<T>::Compare(int,int)'”
Code Snippet:-
using namespace System;
using namespace System::Collections::Generic;
ref class RevCompare:public IComparer<int>
{
public:
virtual int Compare(int x, int y)
{
if (x > y)
return -1;
else
if (x == y)
return 0;
else
return 1;
};
};
int main(array<System::String ^> ^args)
{
System::Collections::Generic::List<int> intList = gcnew List<int>();
intList.Add(7);
intList.Add(4);
intList.Add(3);
intList.Add(10);
intList.Add(19);
intList.Add(20);
intList.Add(12);
Console::WriteLine(L"Before Sorting");
List<int>::Enumerator^ enumIt = intList.GetEnumerator();
while(enumIt->MoveNext())
{
Console::WriteLine(L"{0}",enumIt->Current);
}
Console::WriteLine(L"After Sorting");
intList.Sort(gcnew RevCompare());
enumIt = intList.GetEnumerator();
while(enumIt->MoveNext())
{
Console::WriteLine(L"{0}",enumIt->Current);
}
return 0;
}
Output:-
Before Sorting
7
4
3
10
19
20
12
After Sorting
20
19
12
10
7
4
3
IPC: Using Memory Mapped Files!
There are many ways you can do inter-process communication in unmanaged world. One of them is data sharing using memory mapped files. Here how’s it work.
Server Application:-
- Create File Handle using CreateFileMapping.
- Use MapViewOfFile function to get starting address of shared memory address.
- Use Starting address pointer receieved in last step to update information you want to share.
- Once done,use UnmapViewOfFile to release shared memory.
- Use CloseHandle Api to close file Handle.
Client Application:-
- Open File Handle using OpenFileMapping.
- Use MapViewOfFile function to get starting address of shared memory address.
- Use Starting address pointer receieved in last step to update information you want to share.
- Once done,use UnmapViewOfFile to release shared memory.
- Use CloseHandle Api to close file Handle.
Code Snippet (Server Side):-
HANDLE m_hMemoryMappedFile=NULL;
TCHAR *m_pFileBuff = NULL;
m_hMemoryMappedFile = CreateFileMapping(INVALID_HANDLE_VALUE,
NULL,
PAGE_READWRITE,
0,
100,
L"SHARED_FILE_{E2128B79-1C09-4805-9330-1420E19D87E1}");
if(m_hMemoryMappedFile == NULL)
{
MessageBox(_T("CreateFileMapping fails"));
}
m_pFileBuff = (LPTSTR)MapViewOfFile(m_hMemoryMappedFile,
FILE_MAP_ALL_ACCESS,
0,
0,
100); // Buffersize 100
if(m_pFileBuff== NULL)
{
MessageBox(_T("MapViewOfFile fails"));
}
Code Snippet (Client Side):-
HANDLE m_hMemoryMappedFile=NULL;
TCHAR *m_pFileBuff = NULL;
m_hMemoryMappedFile = OpenFileMapping(FILE_MAP_ALL_ACCESS,
FALSE,
L"SHARED_FILE_{E2128B79-1C09-4805-9330-1420E19D87E1}");
if(m_hMemoryMappedFile == NULL)
{
MessageBox(_T("CreateFileMapping fails"));
}
m_pFileBuff = (LPTSTR)MapViewOfFile(m_hMemoryMappedFile,
FILE_MAP_ALL_ACCESS,
0,
0,
100);
if(m_pFileBuff== NULL)
{
MessageBox(_T("MapViewOfFile fails"));
}
Code Snippet (Data Sharing):-
Saving:-
SetDlgItemText(IDC_EDIT1,m_pFileBuff);
//Retrieving:-
GetDlgItemText(IDC_EDIT1,m_pFileBuff,100);
Code Snippet (On Close) :-
UnmapViewOfFile(m_pFileBuff);
CloseHandle(m_hMemoryMappedFile);
Preview:-
Plot4: Smart Device Game!
Out of hobby, I am making application(s) on window based smart devices. I opened Visual Studio 2008 (though I have VS2010 too, but I haven’t installed it’s fully) and selected smart device project targeting Mobile-Phone/Pocket-PC SDK. I am surprise to see almost same set of class I used for developing window application, however they are tear down version of same (removing memory intensive API’s or windows pc specific API’s).
All the programming design and architecture are similar to that of programming on window pc, however background implementation is different. So here is my first successful implemented mobile app, it’s a Game, yes it is . Players have to position four consecutive coins in horizontal, diagonal or vertical direction to win the game. Example:-
Here is little glimpse of my logic (it’s very beginner-ish ), there might be much better logic around, however I am not seasoned game programmer and I am open to any comments and improvements suggestion.
I have created a 9*8 matrix for holding falling coin. Matrix can have following values only:-
enum EPlayerCoin {eCoinEmpty,eCoinPlayerOne,eCoinPlayerTwo};
#define X_MAX 9
#define Y_MAX 8
EPlayerCoin m_eGameMatrix[X_MAX][Y_MAX];
Games start with matrix containing eEmptyCoin, one by one player chose a particular column to drop its coloured coin, this game would continue till all the places are filled or either of player come victories.
For every successful coin drop, app would checks it’s diagonally, horizontally and vertically in matrix for four consecutive coins for winning condition. Here is the logic :-
bool CChildView::CheckMatrixForResult(int a_iX, int a_iY)
{
EPlayerCoin eTmp = m_eGameMatrix[a_iX][a_iY];
int i=0,j=0;
bool bFlag = true;
#ifdef _DEBUG
CString strDebugMsg;
#endif
//Check LEFT to RIGHT in batch of 4
for(i=a_iX-3;i<=a_iX;i++)
{
#ifdef _DEBUG
strDebugMsg.Format(_T("PLT4(LEFT2RIGHT) StartI=[%d]\n"),i);
OutputDebugString(strDebugMsg);
#endif
//check for array break condition
if(i<0)
{
continue;
}
for(j=i;j<=i+3;j++)
{
#ifdef _DEBUG
strDebugMsg.Format(_T("m_eGameMatrix[%d][%d]\n"),j,a_iY);
OutputDebugString(strDebugMsg);
#endif
//check for array break condition
if(j>X_MAX)
{
bFlag = false;
break;
}
if( m_eGameMatrix[j][a_iY]!=eTmp)
{
bFlag = false;
break;
}
}
/// check for game winning condition!
if(bFlag== true)
{
#ifdef _DEBUG
OutputDebugString(_T("Game Won Right Left"));
#endif
// Game Won.
return true;
}
//Set flag condition to true
bFlag = true;
}
//Check UP AND Down in batch of 4
bFlag = true;
for(i=a_iY-3;i<=a_iY;i++)
{
#ifdef _DEBUG
strDebugMsg.Format(_T("PLT4(UP2DOWN) StartI=[%d]\n"),i);
OutputDebugString(strDebugMsg);
#endif
//check for array break condition
if(i<0)
{
continue;
}
for(j=i;j<=i+3;j++)
{
#ifdef _DEBUG
strDebugMsg.Format(_T("m_eGameMatrix[%d][%d]\n"),a_iY,j);
OutputDebugString(strDebugMsg);
#endif
//check for array break condition
if(j>Y_MAX)
{
bFlag = false;
break;
}
if( m_eGameMatrix[a_iX][j]!=eTmp)
{
bFlag = false;
break;
}
}
/// check for game winning condition!
if(bFlag== true)
{
#ifdef _DEBUG
OutputDebugString(_T("Game Won UP - DOWN"));
#endif
// Game Won.
return true;
}
//Set flag condition to true
bFlag = true;
}
//Check LEFT UP to RIGHT Bottom in batch of 4
bFlag = true;
for(i=a_iX-3,j=a_iY-3;i<=a_iX;i++,j++)
{
#ifdef _DEBUG
strDebugMsg.Format(_T("PLT4(UPLEFT_2_BOTTOMRIGHT) tartX,Y=[%d][%d]\n"),i,j);
OutputDebugString(strDebugMsg);
#endif
//check for array break condition
if((i<0)||(j<0))
{
continue;
}
for(int x=i,y=j;x<=i+3;x++,y++)
{
#ifdef _DEBUG
strDebugMsg.Format(_T("m_eGameMatrix[%d][%d]\n"),x,y);
OutputDebugString(strDebugMsg);
#endif
//check for array break condition
if(x>X_MAX)
{
bFlag = false;
break;
}
if(y>Y_MAX)
{
bFlag = false;
break;
}
if( m_eGameMatrix[x][y]!=eTmp)
{
bFlag = false;
break;
}
}
/// check for game winning condition!
if(bFlag== true)
{
#ifdef _DEBUG
OutputDebugString(_T("Game Won UpLeft - Bottom Right"));
#endif
// Game Won.
return true;
}
//Set flag condition to true
bFlag = true;
}
//Check LEFT Bottom to RIGHT UP in batch of 4
bFlag = true;
for(i=a_iX-3,j=a_iY+3;i<=a_iX;i++,j--)
{
#ifdef _DEBUG
strDebugMsg.Format(_T("PLT4BOTTOMLEFT_2_BOTTOMUP) StartX,Y=[%d][%d]\n"),i,j);
OutputDebugString(strDebugMsg);
#endif
//check for array break condition
if((i<0)||(j>Y_MAX))
{
continue;
}
for(int x=i,y=j;x<=i+3;x++,y--)
{
#ifdef _DEBUG
strDebugMsg.Format(_T("m_eGameMatrix[%d][%d]\n"),x,y);
OutputDebugString(strDebugMsg);
#endif
//check for array break condition
if(x>X_MAX)
{
bFlag = false;
break;
}
if(y<0)
{
bFlag = false;
break;
}
if( m_eGameMatrix[x][y]!=eTmp)
{
bFlag = false;
break;
}
}
/// check for game winning condition!
if(bFlag== true)
{
#ifdef _DEBUG
OutputDebugString(_T("Game Won BottomLeft - UpRight"));
#endif
// Game Won.
return true;
}
//Set flag condition to true
bFlag = true;
}
return false;
}
And here are the game files :-
These files are release as part of CPOL license, you must use it at your own risk! This is without any warranty and gurantee.
Using Conditioned Activity Group Activity in WF
Window workflow is quite easy to program and mantain, as you just need to convert you idea depicted as flowchart on paper to flowcharting like language on computer. It made programmer task easier, as it need to put more stress on coding business logic then actual language.
Now this post I am going to show you how to use CONDITIONAL activity, conditional activity is something like while look with switch case statement. I.e. The Conditioned Activity will loop itself repeatedly, until it exit condition is not satisfied just like while loop, and you can define cases/condition inside to execute any other activity.
Now put One Code activity (CA_EnterChoice) for collecting user response (add public integer variable Choice for collecting user response), and then add Conditioned Activity Group, put two CODE inside it. Your workflow would look something like this:-
Now add public Boolean Variable KeepRunning [Default value = TRUE] into source file, and configure our conditioned activity group like this:-
Now Configure code condition inside Conditioned activity group for there running condition, like this:-
Now add following code, in each code activity handler:-
private int _iChoice;
public int Choice
{
get { return _iChoice; }
set { _iChoice = value; }
}
private bool _KeepRunning = true;
public bool KeepRunning
{
get { return _KeepRunning; }
set { _KeepRunning = value; }
}
private void CA_EnterChoice_ExecuteCode(object sender, EventArgs e)
{
Console.WriteLine();
Console.WriteLine("*******ConditionalActivity Workflow***********");
Console.WriteLine("What do you want to do!");
Console.WriteLine("1. Greeting");
Console.WriteLine("2. Good Bye");
Console.WriteLine("Anything else: Exit");
Console.Write("Enter Choice");
switch (Console.ReadKey().Key)
{
case ConsoleKey.D1:
Choice = 1;
break;
case ConsoleKey.NumPad1:
Choice = 1;
break;
case ConsoleKey.D2:
Choice = 2;
break;
case ConsoleKey.NumPad2:
Choice = 2;
break;
default:
Choice = -1;
KeepRunning = false;
break;
}
// KeepRunning = false;
}
private void CA_ENDActivity_ExecuteCode(object sender, EventArgs e)
{
Console.WriteLine("Exiting the Conditional Activity");
}
private void CA_Greeting_ExecuteCode(object sender, EventArgs e)
{
Console.WriteLine();
Console.WriteLine("Enter your Name");
string sName = Console.ReadLine();
Console.WriteLine("Good Morning {0}, Have a nice day", sName);
KeepRunning = false;
}
private void CA_Goodbye_ExecuteCode(object sender, EventArgs e)
{
Console.WriteLine();
Console.WriteLine("Enter your Name");
string sName = Console.ReadLine();
Console.WriteLine("Good Bye {0}, Nice meeting you!", sName);
KeepRunning = false;
}
Output:-
[RUN1]
*******ConditionalActivity Workflow*********** What do you want to do! 1. Greeting 2. Good Bye Anything else: Exit Enter Choice1 Enter your Name VisualCpp Good Morning VisualCpp, Have a nice day
[RUN2]
*******ConditionalActivity Workflow*********** What do you want to do! 1. Greeting 2. Good Bye Anything else: Exit Enter Choice2 Enter your Name VisualCpp Good Bye VisualCpp, Nice meeting you!
Download :- WWFTest_combined.Zip, File contain all sample for WF till date






