by John Mertus - John_Mertus@Brown.EDU
Delphi programmers can use the CLIPBRD unit to copy and paste text and graphics to and from the Windows Clipboard. However this unit gives no method to copy and paste WAV sound files. Luckily, it is not very hard to implement the functions. There are various functions for inquiring about the clipboard, more information than what is presented can be found the the WIN32.HLP help file distributed with Delphi 2 and 3.
Brief Overview of the Clipboard's Innards
The clipboard is really just a list of global memory handles and formats; for example, a text is stored as a pointer to a null terminated string and has the attached format CF_TEXT, a bitmap file is stored as a global handle with format CF_BITMAP. These formats are predefined in the WINDOWS unit of Delphi. Formats are not restricted to these predefined ones, one can resister a custom format with the clipboard. Delphi does that with the CF_PICTURE format. In the case of WAV files, there is already a predefined format CF_WAVE.
Although there can only be one memory pointer with a given format, there may be multiple formats in the clipboard at the same time. Thus the clipboard can have text, bitmap and a sound in it all at once. It is important to understand that the clipboard itself does not understand these formats and does no checking to see if the data is in that format. To belabor the point, the clipboard does not know the structure of a bitmap, or the structure of a sound file. It just knows that a certain memory handle has a certain number(format) attached to it. It is up to application programs to understand the individual formats.
Lastly, it is the application that allocates the memory necessary to copy data to the clipboard. But after the data is sent, the clipboard owns the memory and will dispose it it when its done. An application program never disposes of the clipboard's predefined format memory handle!
Copying a sound file to the Clipboard
With this understanding, copying a sound to the clipboard is quite simple.
The following snipets of code show how to copy a WAV file, in this case called JUNK.WAV to the clipboard. First we must find how much memory to allocate.
fh := FileOpen('JUNK.WAV', fmOpenRead or fmShareDenyNone);
If (fh <= 0) Then Exit;
size := GetFileSize(fh, nil);
If (Size = -1) Then Exit;
A few comments about WAV files.
WAV files evolved over many years starting with the simple format of a header followed by data. Later it changed into a general purpose file, involving chunks of data which can contain information besides sound information. Many programs deal with a wave file as a header followed by data. This greatly simplifies the programming necessary to deal with these files and will work when there is only sound data in the file. However, the correct way of dealing with sound files is to open them as multi-media files using the mmioXXXX routines. The next sections, we will treat sound files as header followed by data; the very last section will show how to open the clipboard as a multi-media file.
Playing out the Clipboard.
A sound in the clipboard is nothing but a memory image of a WAV file. It is very simple to play out a WAV file memory image using playsound. The following code shows how this is done. First we check to see if there is a WAV format in the clipboard, this is done by using the IsClipboardFormatAvailable function.
Reading the Clipboard.
If one is confident or assumes the sound in the clipboard is a valid WAV file, then reading the clipboard can be done by just writing the memory out into a file. The only real trick involved is getting the size of the sound.
If IsClipboardFormatAvailable(CF_WAVE) Then
// once again see if format is there
If (OpenClipboard(Application.Handle)) Then
Begin
mh := GetClipBoardData(CF_WAVE);
// we should check for valid returns
fp := GlobalLock(mh);
// but this is just a demo
{ Find the Size of
the file }
wp := fp;
inc(wp,4);
// The 4 byte of a WAV
Move(wp^,SizeF,4);
// file gives the remaining size
SizeF := SizeF + 8;
// Add 8 to get total file size
{ Now create the file
}
fh := FileCreate(fname);
If (fh <= 0) Then
Begin
CloseClipBoard;
GlobalUnLock(mh)
Exit;
End;
FileWrite(fh, fp^,
SizeF); //
Just write it out
FileClose(fh);
GlobalUnlock(mh);
CloseClipBoard;
End;
Opening the Clipboard as an Multi-Media File
As said earlier, the best way to read a WAV file is through the multi-media interface. I will briefly describe a way of opening the clipboard as a multimedia file. Once the file is open, the usual mmioXXX routines can be called to process the data chunks.
First, the mmioOpen function uses a MMIOINFO structure. Depending upon the setting of this structure, mmioOpen can be told to use special I/O handlers, even user defined ones. Windows provides a predfined memory I/O handler which is what we will use.
To make the code more readable, assume that the clipboard has been opened and checked for CF_WAVE data; moreover, we will not check for invalid returns.
Being a good Neighbor
The clipboard is designed to exchange data between programs. The OpenClipboard and CloseClipboard functions are used to synchronize reading/writing to the clipboard. Thus, unlike a file, one should not keep the clipboard open for a long time. Open it, process the data, and close it quickly.
Unit and Demo Programs.
The URL http://www.cog.brown.edu/~mertus/components.html contains a ZIP file which contains a unit for copying and pasting waveform from the clipboard together with a small demonstration program.