// ================================================ ====================================
// Title:
// Seteventdata and geteventdata solutions in WINXP
// Author:
// Norains
// Date:
// Tuesday 16-March-2010
// Environment:
// Windows XP
// ================================================ ====================================
If you are familiar with Wince development and often use seteventdata and geteventdata to transmit data between processes, when you want to port the code to WINXP, you will encounter a very embarrassing problem: win32 API does not have these two functions at all! Of course, if you use the. NET Framework, this is not a problem. We will not discuss it here.
Back to the origin, let's look at the functions of these two functions. We can think that seteventdata associates the DWORD value with the event handle, while geteventdata extracts the associated data. The data can be shared among different processes.
Is this a bit similar to the memory ing file? Since Win32 API does not have this function, we will create it manually!
Since the event handle is associated with numeric values, we can use STL: map for storage from the simplicity of the algorithm, which can greatly reduce our workload. On the other hand, because some information in the ing file can only be obtained through createevent, we can only use the class method to overload these functions. For ease of description, this class is declared as cmuf.
Let's start from scratch and look at the overloaded createevent function. Some of the key points are listed in the Code using annotations for ease of viewing.
Handle cmuf: createevent (lpsecurity_attributes lpeventattributes, bool bmanualreset, bool binitialstate, lpctstr lpname) <br/>{< br/> bool Bres = false; </P> <p> // call the native API function to create an event. <br/> handle hevent =: createevent (lpeventattributes, bmanualreset, binitialstate, lpname); <br/> If (hevent = NULL) <br/>{< br/> // If creation fails, jump to exit <br/> goto exit; <br/>}</P> <p> // first, determine whether the event has been created to facilitate subsequent data processing .. <Br/> bool bisexisting = (getlasterror () = error_already_exists); </P> <p> If (bisexisting = false) <br/>{< br/> // This is a new event <br/> tstring strmemfile; </P> <p> // determine whether the class is only used internally. The so-called internal use refers to an event without a name. It cannot be obtained by opening it again except by using a handle. <Br/> If (lpname! = NULL) <br/>{< br/> // because the memory ing file and event name are in the same namespace, the names of the two cannot be the same. Therefore, the name of the memory ing file to be created is "Event _ prefix + event name. <Br/> strmemfile = text ("Event _"); <br/> strmemfile + = lpname; <br/>}< br/> else <br/> {<br/> // if the event is used internally, the memory ing file is also used internally. Therefore, the name of the memory ing file is determined using the name of the program handle + event name. <Br/> tstringstream stream; <br/> stream <getmodulehandle (null) <text ("_") <pevent; <br/> strmemfile = stream. STR (); <br/>}</P> <p> // call initmemfile to create a memory ing file <br/> memfile; <br/> If (initmemfile (strmemfile, sizeof (DWORD), memfile) = false) <br/>{< br/> goto exit; <br/>}</P> <p> // ms_mpeventhandletoname and ms_mpeventnametofile are static members of the class. They are used to store the ing between events and ing files. <Br/> If (lpname! = NULL) <br/>{< br/> ms_mpeventhandletoname.insert (STD: make_pair (hevent, lpname); <br/> ms_mpeventnametofile.insert (STD: make_pair (lpname, memfile); <br/>}< br/> else <br/>{< br/> // because the event used internally has no name, therefore, the combination name is used as the identifier <br/> ms_mpeventhandletoname.insert (STD: make_pair (hevent, strmemfile); <br/> ms_mpeventnametofile.insert (STD: make_pair, memfile); <br/>}</P> <p >}< br/> else <br/>{< br/> // The system determines that the event named after this name has been created. Therefore, we first search for the corresponding records of our database. <Br/> STD: Map <pandle, tstring >:: iterator itername = STD: find_if (partition (), ms_mpeventhandletoname.end (), functor: value_equal <pandle, tstring> (lpname); <br/> If (itername = ms_mpeventhandletoname.end () <br/>{< br/> assert (false ); </P> <p> goto exit; <br/>}</P> <p> STD: Map <tstring, memfile> :: iterator iterfile = ms_mpeventnametofile.find (itername-> second); <br/> If (iterfile = ms_mpeventnametofile.end () <br/>{< br/> assert (false ); </P> <p> goto exit; <br/>}</P> <p> // if the corresponding record is found, add 1 <br/> interlockedincrement (reinterpret_cast <long *> (& iterfile-> second. dwcount); </P> <p> // even if the event named by this name has been used before, the handles are different during the Second Creation, therefore, we must save it <br/> ms_mpeventhandletoname.insert (STD: make_pair (hevent, lpname); <br/>}</P> <p> Bres = true; </P> <p> Exit: </P> <p> If (Bres = false) <br/>{< br/> closehandle (hevent ); <br/>}</P> <p> return hevent; </P> <p >}< br/> <br/>
This function has two static member variables, which are declared in the header file as follows:
Class cmuf <br/>{< br/> PRIVATE: <br/> struct memfile <br/>{< br/> handle hfilemap; <br/> handle pmapbuf; <br/> DWORD dwbufsize; <br/> DWORD dwcount; <br/>}; </P> <p> static STD: Map <pandle, tstring> ms_mpeventhandletoname; <br/> static STD: Map <tstring, memfile> ms_mpeventnametofile; </P> <p >}; </P> <p> <br/>
The initmemfile function is called as follows:
Bool cmuf: initmemfile (const tstring & strmapname, DWORD dwsize, memfile & memfile) <br/>{</P> <p> // create a ing file <br/> handle hfilemap = createfilemapping (invalid_handle_value, null, page_readwrite, 0, dwsize, strmapname. c_str (); <br/> If (hfilemap = NULL) <br/>{< br/> assert (hfilemap! = NULL); <br/> return false; <br/>}</P> <p> // obtain the allocated memory space from the ing file handle <br/> void * pmapbuf = mapviewoffile (hfilemap, file_map_all_access, 0, 0, 0); <br/> If (pmapbuf = NULL) <br/> {<br/> assert (false); <br/> closehandle (hfilemap ); <br/> return false; <br/>}</P> <p> // set the value in the memory to 0 <br/> DWORD dwdata = 0; <br/> memcpy (pmapbuf, & dwdata, dwsize); </P> <p> // Save the value to the struct <br/> memfile. hfilemap = hfilemap; <br/> memfile. pmapbuf = pmapbuf; <br/> memfile. dwbufsize = dwsize; <br/> memfile. dwcount = 1; </P> <p> return true; <br/>}< br/> <br/>
Corresponds to the creaetevent. Let's look at the closehandle function:
Bool cmuf: closehandle (handle hobject) <br/>{< br/> If (hobject = NULL) <br/>{< br/> return false; <br/>}</P> <p> // check whether the closed handle exists in the record. <br/> STD: Map <pandle, tstring>: iterator itername = ms_mpeventhandletoname.find (hobject); <br/> If (itername! = Ms_mpeventhandletoname.end () <br/>{</P> <p> STD: Map <tstring, memfile >:: iterator iterfile = ms_mpeventnametofile.find (itername-> second ); <br/> If (iterfile! = Ms_mpeventnametofile.end () <br/>{< br/> // find the record, minus one <br/> interlockeddecrement (reinterpret_cast <long *> (& iterfile-> second. dwcount); </P> <p> If (iterfile-> second. dwcount = 0) <br/>{< br/> // If the count is zero, delete the ing file. </P> <p> unmapviewoffile (iterfile-> second. pmapbuf); <br/>: closehandle (iterfile-> second. hfilemap); <br/> ms_mpeventnametofile.erase (iterfile); <br/>}</P> <p> ms_mpeventhandletoname.era Se (itername); <br/>}</P> <p> // call the API function to disable it. <Br/> return: closehandle (hobject); <br/>}< br/> <br/>
Creating and disabling is so simple and not complex. Before proceeding to the current role, let's take a look at the weapon that all the protagonists will use, that is, the getmemfile function, to obtain the memory ing file information related to the event handle.
The function is short and simple:
Bool cmuf: getmemfile (handle hevent, memfile & memfile) <br/>{< br/> If (hevent = NULL) <br/>{< br/> return false; <br/>}</P> <p> // search for the name based on the handle <br/> STD :: map <pandle, tstring >:: iterator iterevent = ms_mpeventhandletoname.find (hevent); <br/> If (iterevent = ms_mpeventhandletoname.end ()) <br/>{< br/> return false; <br/>}</P> <p> // find the ing file information based on the name. <br/> STD :: map <tstring, memfile >:: iterator itermem = ms_mpeve Ntnametofile. find (iterevent-> second); <br/> If (itermem = ms_mpeventnametofile.end () <br/>{< br/> return false; <br/>}</P> <p> // Save the information in the record file to the output variable cache. <Br/> memfile = itermem-> second; </P> <p> return true; <br/>}< br/> <br/>
With this getmemfile function, seteventdata and geteventdata are simple. It can even be said that it looks very thin and seems to be different from the halo of the main character in this article. However, all we need is functionality. :)
Let's make the two protagonists of this article Debut:
Bool cmuf: seteventdata (handle hevent, DWORD dwdata) <br/>{< br/> memfile; <br/> If (getmemfile (hevent, memfile) = false | memfile. pmapbuf = NULL) <br/>{< br/> return false; <br/>}</P> <p> // copy the value to the memory. <br/> memcpy (memfile. pmapbuf, & dwdata, memfile. dwbufsize); </P> <p> return true; <br/>}</P> <p> DWORD cmuf: geteventdata (handle hevent) <br/>{< br/> memfile; <br/> If (getmemfile (hevent, memfile) = false | memfile. pmapbuf = NULL) <br/>{< br/> return 0; <br/>}</P> <p> // obtain DWORD data from the memory <br/> DWORD dwval = 0; <br/> memcpy (& dwval, memfile. pmapbuf, memfile. dwbufsize); </P> <p> return dwval; <br/>}< br/> <br/>
OK. That's all we need to do.
Finally, let's take a look at how to call the functions listed in our article. Because these functions are declared as static and the access permission is public, we can directly add cmuf: prefix for access, such as cmuf: seteventdata.
Of course, if your code is organized as a class, it is simpler and can be directly inherited from cmuf.