Rogue Wave Software logo banner

Click on the banner to return to the Class Reference home page.

©Copyright 1996 Rogue Wave Software

RWDDEstreambuf


RWDDEstreambufinherits fromRWCLIPstreambufinherits fromstreambuf

Synopsis

#include <rw/winstrea.h>
#include <iostream.h>
iostream str( new RWDDEstreambuf(CF_TEXT, TRUE, TRUE, TRUE) ) ;

Description

Class RWDDEstreambuf is a specialized streambuf that gets and puts sequences of characters to Microsoft Windows global memory that has been allocated with the GMEM_DDESHARE flag. It can be used to exchange data through the Windows Dynamic Data Exchange (DDE) facility.

The class has two modes of operation: dynamic and static. In dynamic mode, memory is allocated and reallocated on an as-needed basis. If too many characters are inserted into the internal buffer for its present size, then it will be resized and old characters copied over into any new memory as necessary. This is transparent to the user. It is expected that this mode would be used primarily by the DDE server. In static mode, the buffer streambuf is constructed from a specific piece of memory. No reallocations will be done. It is expected that this mode would be used primarily by the DDE client.

In dynamic mode, the RWDDEstreambuf "owns" any allocated memory until the member function str() is called, which "freezes" the buffer and returns an unlocked Windows handle to it. The effect of any further insertions is undefined. Until str() has been called, it is the responsibility of the RWDDEstreambuf destructor to free any allocated memory. After the call to str(), it becomes the user's responsibility.

In static mode, the user always has the responsibility for freeing the memory handle. However, because the constructor locks and dereferences the handle, you should not free the memory until either the destructor or str() has been called, either of which will unlock the handle.

Note that although the user may have the "responsibility" for freeing the memory, whether it is the client or the server that actually does the call to GlobalFree() will depend on the DDE "release" flag.

Persistence

None

Example

This is an example of how the class might be used by a DDE server.

#include <rw/winstrea.h>
#include <iostream.h>
#include <windows.h>
#include <dde.h>

BOOL
postToDDE(HWND hwndServer, HWND hwndClient) {
  RWDDEstreambuf* buf =
  new RWDDEstreambuf(CF_TEXT, TRUE, TRUE, TRUE);
  ostream ostr(buf);
  double d = 12.34;
  ostr << "Some text to be exchanged through the DDE.\n";
  ostr << "The double you requested is: " << d << endl;
  ostr.put(0);     // Include the terminating null
  // Lock the streambuf, get its handle:
  HANDLE hMem = buf->str();
  // Get an identifying atom:
  ATOM aItem = GlobalAddAtom("YourData");
  if(!PostMessage(hwndClient, WM_DDE_DATA, hwndServer,
                  MAKELONG(hMem, aItem))){
    // Whoops!  The message post failed, perhaps because
    // the client terminated.  Now we are responsible
    // for deallocating the memory:
   if( hMem != NULL )
   GlobalFree(hMem);
   GlobalDeleteAtom(aItem);
   return FALSE;
  }
  return TRUE;
}
 

The handle of the DDE server is passed in as parameter hwndServer, the handle of the client as parameter hwndClient. An ostream is created, using an RWDDEstreambuf as its associated streambuf. The results can be used much like any other ostream, such as cout, except that characters will be inserted into Windows global memory, from where they can be transferred through the DDE. Note the parameters used in the constructor. These should be studied below as they have important ramifications on how memory allocations are handled through the DDE. In particular, parameter fRelease, if TRUE, states that the client will be responsible for deallocating the memory when done. The defaults also specify fAckReq TRUE, meaning that the client will acknowledge receiving the message: you must be prepared to receive it.

Some text and a double is inserted into the ostream. Member function str() is then called which unlocks and returns a Windows HANDLE. Once we have called str(), we are responsible for this memory and must either free it when done, or pass on that responsibility to someone else. In this case, it will be passed on to the client.

An atom is then constructed to identify the data. The DDE data, along with its identifying atom, is then posted. If the post fails, then we have been unable to foist our responsbility for the global memory onto someone else and will have to free it (along with the atom) ourselves.

Public Constructors

RWDDEstreambuf(WORD cfFormat  = CF_TEXT,
               BOOL fResponse = TRUE
               BOOL fAckReq   = TRUE
               BOOL fRelease  = TRUE);
RWDDEstreambuf(HANDLE hMem);

Public Destructor

~RWDDEstreambuf();

Public Member Functions

Because RWDDEstreambuf inherits from streambuf, any of the latter's member functions can be used. Furthermore, RWDDEstreambuf has been designed to be analogous to streambuf. However, note that the return type of str() is a HANDLE, rather than a char*.

BOOL
ackReq() const;
WORD
format() const;
BOOL
release() const;
BOOL
response() const;
HANDLE
str();