Hear Yourself Type

Contents

The first prototype of KeyTick kept memory images of all its WAV files in a fixed-size portion of the DLL's shared memory area and played them as needed using the multimedia API function PlaySound(). The program used the SND ASYNC flag, indicating that PlaySound() should return immediately, but each call still took too long. The system's responsiveness to typing was noticeably slowed. That was unacceptable, so I defined a TThread descendant, TsndThread, to play sounds and modified the hook procedures to post a user-defined message directly to the thread. This change eliminated the slowdown.

The TSndThread object, defined in the module Sndthdu.pas, stores the sounds defined for KeyTick's ten events and responds to messages sent directly from a hook procedure by playing one of the sounds. The thread's ID is stored in the shared memory area used by the hook procedures. To request one of the ten sounds, a hook procedure uses the PostThreadMessage() API function to send a user-defined message to that thread ID, passing the sound number as the message's wParam.

Because the Execute() method of the Delphi TThread object is defined with the abstract keyword, every descendant must override the Execute() method with code that performs the thread's specific task. TSndThread's Execute() method makes an initial call to the API function PeekMessage() to force creation of a message queue, then settles down in a loop to receive and process messages. The Execute() method repeatedly calls the API function GetMessage(), which does not return until a message is received. If GetMessage() returns False, the thread has received a WM_QUIT message and should terminate. Otherwise, if the message is from the hook procedure[[otherwise the message is from the hook procedure or otherwise, and if the message is from the hook procedure?, the Execute() method plays the appropriate sound by calling the API function PlaySound() with the flags SND_MEMORY (sound is stored in memory), SND_ASYNC (return immediately), SND_NODEFAULT (do not play the default sound if this sound cannot be found), and SND_NOSTOP (do not stop a sound that is already playing). It passes all other messages to the API function DispatchMessage() for default handling.

Neil Rubenking served as vice president and president of the San Francisco PC User Group for three years when the IBM PC was brand new. He was present at the formation of the Association of Shareware Professionals, and served on its board of directors. In 1986, PC Magazine brought Neil on board to handle the torrent of Turbo Pascal tips submitted by readers. By 1990, he had become PC Magazine's technical editor, and a coast-to-coast telecommuter. His "User to User" column supplied readers with tips...
More »