Need some help with Clarion (6.4) hand code & resource file

It’s been over 20 years since I last seriously coded with Clarion. Time flies…

I’ve been digging out my cw version 6.4 from the dust for a long time now and am excited to try attaching a wav audio file as a resource and playing it from the resource.
I’ve done this a long time ago, but a large part of the old source code has been lost over the years.

I would like to ask if anyone has a working model of how to implement this?

The intention would be to use the following functions:
LoadResource
FindResourceA
SizeofResource
LockResource
PlaySoundA

I have created the resource.h file as follows:

#define SONG_WAVE 101

and resources.rc:

// resources.rc
#include “resource.h”

101 WAVE “sound.wav”

Unfortunately, despite all my experimentation, I haven’t been able to get the hand-coded program snippet to work.
I would like to ask if anyone could find a working code example of how to play a wav file directly from a resource?

Best regards,
-Ville Vahtera, Finland

These threads will probably help.

There is a code example in the last link.

Hi Ville,
This tip allows you to embed an Excel spreadsheet or any other type of document as a resource within the executable file.
When the program runs, the code will write the contents of the spreadsheet to a file on the hard drive.

WARNING: The document must be renamed to .BMP and then added to the project as an image. (Example: _accordions.html renamed to _accordions.html.bmp works fine as long as you set ResNameStr = _accordions_html_bmp, since the periods are replaced by underscores.)

After Global INCLUDEs:

INCLUDE('Winequ.clw')
FilName                 CSTRING(256)
GENERIC_WRITE           EQUATE(40000000H)
CREATE_ALWAYS           EQUATE(2)
FILE_ATTRIBUTE_NORMAL   EQUATE(80H)
hFile                   LONG
lpRes                   LONG !,Auto
cbRes                   LONG !,Auto
cbWri                   LONG

hRes                    LONG !UnSigned,Auto
hgMem                   LONG !UnSigned,Auto
ResTypeStr              CSTRING('IMAGE')
ResNameStr              CSTRING(200)

Inside the Global Map:

MODULE('Win32.lib')
    GetModuleHandle(*LPCSTR), HMODULE, PASCAL, RAW, NAME('GetModuleHandleA')
    FindResource(UNSIGNED, LONG, LONG), UNSIGNED, PASCAL, RAW, NAME('findResourceA')
    SizeOfResource(UNSIGNED, UNSIGNED), ULONG, PASCAL
    LoadResource(UNSIGNED, UNSIGNED), UNSIGNED, PASCAL, RAW
    LockResource(UNSIGNED), LONG, PASCAL
    FreeResource(UNSIGNED), BOOL, PASCAL, PROC
    CreateFile(*CSTRING, LONG, LONG, LONG, LONG, LONG, LONG), LONG, RAW, PASCAL, NAME('CreateFileA')
    WriteFile(LONG, LONG, LONG, LONG, LONG), LONG, RAW, PASCAL, NAME('WriteFile'), PROC
    CloseHandle(UNSIGNED), BOOL, PASCAL, PROC, NAME('CloseHandle')
    GetLastError(), ULONG, PASCAL
END

In a procedure:

ResNameStr = 'Prononcer_html_bmp'
FilName    = LONGPATH(PATH()) & '\Prononcer.html'
hRes       = FindResource(SYSTEM{Prop:AppInstance}, ADDRESS(ResNameStr), ADDRESS(ResTypeStr))
hgMem      = LoadResource(SYSTEM{Prop:AppInstance}, hRes)
lpRes      = LockResource(hgMem)
cbRes      = SizeOfResource(SYSTEM{Prop:AppInstance}, hRes)
hFile      = CreateFile(FilName, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0)
CLEAR(cbWri)
IF NOT WriteFile(hFile, lpRes, cbRes, ADDRESS(cbWri), 0) END
CloseHandle(hFile)
FreeResource(hgMem)

HTH

1 Like

Thank you for the great code! I did edit and use the </> button to format as Clarion code.

Note that LONGPATH() alone does return the Current Directory without Path(). A file name can be 260 in ANSI windows. It would be very rare to be 256 to 260 bytes. Revised code:

FilName      CSTRING(261)   !or use CSTRING(MAX_PATH+1) 
FilName    = LONGPATH() & '\Prononcer.html'   !was LongPath(Path())

__
One tip about LONGPATH() I keep in mind… is it does clear the current ERRORCODE(). This can mess up a Message() or Debug that shows error and path e.g. below will show a Blank Error():

IF ERRORCODE() THEN 
   Message('FileAAA access in folder '& LongPath() &' caused error '& Error())
END

Thanks everyone for your help.

It turned out that the real problem was in the resource file format itself.
Below is the resource (.rc) file and cw code:

(resorce.rc)
// .rc file entry
SOUND_WAVE WAVE “sound.wav”

cw code:
PROGRAM

lpRes LONG
hRes LONG
hgMem LONG
ResTypeStr CSTRING(‘WAVE’)
ResNameStr CSTRING(200)

MAP

MODULE('Win32.lib')
    FindResource(UNSIGNED, LONG, LONG), UNSIGNED, PASCAL, RAW, NAME('findResourceA')
    LoadResource(UNSIGNED, UNSIGNED), UNSIGNED, PASCAL, RAW
    LockResource(UNSIGNED), LONG, PASCAL
    FreeResource(UNSIGNED), BOOL, PASCAL, PROC
    PlaySoundA(UNSIGNED, UNSIGNED, UNSIGNED),BOOL,PASCAL,RAW
END
END

MyWindow WINDOW(‘Play sound from resource example’),AT(,138,42),COLOR(COLOR:White),CENTER,SYSTEM,GRAY
BUTTON(‘PLAY (WAV)’),AT(20,4,99,16),USE(?Play),TRN
BUTTON(‘EXIT’),AT(20,22,99,16),USE(?BtnExit),TRN
END

CODE
OPEN(MyWindow)

ACCEPT
CASE EVENT()
OF EVENT:Accepted
CASE ACCEPTED()
OF ?Play
IF ~lpRes
ResNameStr = ‘SOUND_WAVE’
hRes = FindResource(SYSTEM{Prop:AppInstance}, ADDRESS(ResNameStr), ADDRESS(ResTypeStr))
hgMem = LoadResource(SYSTEM{Prop:AppInstance}, hRes)
lpRes = LockResource(hgMem)
Ret# = PlaySoundA(lpRes, 0, 5h)
ELSE
Ret# = PlaySoundA(lpRes, 0, 5h)
END
OF ?BtnExit
BREAK
END
END
END

CLOSE(MyWindow)
Ret# = FreeResource(hgMem)
RETURN

-Ville