(Tagged messages in GFA Basic)

#: 99196 S12/GFA  (CIS:WINAPC)
    05-Aug-97  20:39:05
Sb: Editor Extension Tool
Fm: Dale Bryant 73134,1500
To: GFA Germany 75300,3224
Replies:   0

Is there a way to make the new Extension tool open the Gfa editor MAXIMIZED?
Thanks,
Dale Bryant


#: 99261 S12/GFA  (CIS:WINAPC)
    15-Aug-97  01:18:25
Sb: gfawhelp.zip
Fm: Dale Bryant 73134,1500
To: GFA Germany 75300,3224
Replies:   0

Hi Sven,
Have uploaded new, improved, GFAWHELP.ZIP. Please replace current file with the new version.  Please let me know if  any corrections need to be made.

Dale Bryant
adbryant@msm.com
73134.1500@compuserve.com


#: 99272 S12/GFA  (CIS:WINAPC)
    16-Aug-97  22:33:22
Sb: #99267-Color Conversion
Fm: GFA Germany 75300,3224
To: Owen Laurion 72547,170
Replies:   0

>>What command will convert an enumerated color (that is, a number from the 16-color palette) into an RGB number <<

a&=GetPaletteEntries(hPalette&, StartIndex&, NumEntries&, PaletteEntriesPointer%)

and

a&=SetPaletteEntries(hPalette&, StartIndex&, NumEntries&, PaletteEntriesPointer%)

or, if you read the system palette:
GetSystemPaletteEntries resp. SetSystemPaletteEntries

should do the work.

Yours

Sven Thomas
GFA Software


#: 99301 S12/GFA  (CIS:WINAPC)
    26-Aug-97  08:00:01
Sb: #99272-Color Conversion
Fm: Owen Laurion 72547,170
To: GFA Germany 75300,3224
Replies:   0

>>What command will convert an enumerated color (that is, a number from the 16-color palette) into an RGB number <<

<<a&=GetPaletteEntries(hPalette&, StartIndex&, NumEntries&, PaletteEntriesPointer%)
and
a&=SetPaletteEntries(hPalette&, StartIndex&, NumEntries&, PaletteEntriesPointer%)
or, if you read the system palette:
GetSystemPaletteEntries resp. SetSystemPaletteEntries
should do the work.
Yours
Sven Thomas
GFA Software>>

I'm not sure I understand how those would work. Could you give me an example? Say

FUNCTION samecolor(a%,b%)  //where a% is 1 to 16, b% is RGB
   ?
   RETURN TRUE //if both are the same color
   RETURN FALSE  //if they're different
ENDFUNC

Thank you,

Owen


#: 99317 S12/GFA  (CIS:WINAPC)
    28-Aug-97  09:19:11
Sb: #99301-Color Conversion
Fm: Sjouke Hamstra 100741,1036
To: Owen Laurion 72547,170
Replies:   0

Hi Owen,

The function would look like this;

FUNCTION samecolor(a%,b%)  //where a% is 1 to 16, b% is RGB
  LOCAL rgb%
  ~GetPaletteEntries(_PAL(WIN(WIN())), a%, 1, V:rgb%)
  IF b% = rgb%
    RETURN TRUE //if both are the same color
  ELSE
    RETURN FALSE  //if they're different
  ENDIF
ENDFUNC

Greetings,
Sjouke Hamstra
(09:12 28-Aug-97 using OzWinII)


#: 99333 S12/GFA  (CIS:WINAPC)
    30-Aug-97  11:33:08
Sb: #Windows 95 lpt1:
Fm: Steve Thornton 72337,2372
To: Bob Springett 100772,452
Replies:   1

Bob,

Your message #97943 to Sjouke Hamstra on 4/16/97 about removing the colon from OPEN "O",#1,"LPT1:" solved a big problem for me and several clients. While "LPT1:" worked fine in Win3.1, it would give error 57 every time in Win95. I searched documentation for Win95, read internet pages, reconfigured ports, etc., for hours before searching here which I should have done first! Anyway, removing the ":" is all that's required to print directly to the printer port in Windows 95. Now clients can print invoices again (print manager much too slow for that). Thanks!

Steve Thornton

Micromiser Software


#: 99340 S12/GFA  (CIS:WINAPC)
    01-Sep-97  13:08:05
Sb: #99329-#TAB ARRAY
Fm: Sjouke Hamstra 100741,1036
To: Dale Bryant 73134,1500 (X)
Replies:   1

Hi Dale,

>> Would you have a short example of setting up a TAB array and using 
TabedTextOut?  I have a examle but it doesn't work . <<

This should do the job:

DEFWRD "a-z"
OPENW #1,200,200,350,350,~15

Txt$ = "Column 1" + CHR$(9) + "Column 2" + CHR$(9) + "Test of TabbedTextOut"
DIM aTabs(2)

aTabs(0) = 0, aTabs(1) = 90, aTabs(2) = 160
XPos = 10, ypos = 10

ON MENU MESSAGE GOSUB HandleMessage
DO
  SLEEP
UNTIL MENU(1)=4
CLOSEW #1
END

PROCEDURE HandleMessage
  SWITCH MENU(1)
  CASE 1
  CASE 3
  CASE 21
    // TabbedTextOut(hdc,            /* handle of device context   */)
    // iStartXPos, iStartYPos,       /* starting coordinates       */
    // lpszTabbedText,               /* address of text            */
    // lstrlen(lpszTabbedText),      /* number of characters       */
    // sizeof(aTabs) / sizeof(int),  /* number of tabs in array    */
    // aTabs,                        /* array for tab positions    */
    // iStartXPos);                  /* x-coord. for tab expanding */
    ~TabbedTextOut(_DC(),XPos,ypos,Txt$,LEN(Txt$),3,V:aTabs(0),XPos)
    // show table:
    FOR i = 0 TO DIM?(aTabs()) - 1
      LINE XPos + aTabs(i),0,XPos + aTabs(i),_Y
    NEXT i

  ENDSWITCH
RETURN

Greetings,
Sjouke Hamstra
(10:22 30-Aug-97 using OzWinII)


#: 99361 S12/GFA  (CIS:WINAPC)
    04-Sep-97  04:35:01
Sb: GetPrivateProfileString?
Fm: James V. Schumacher 104166,2104
To: All
Replies:   0

Hi,

As I've mentioned in past, I'm using the routine below to access the GetPrivateProfileString API on both Win95 and Win3.1 systems.  

PROCEDURE MyGetPrivateProfileString(sectionName,entry,defltString,tmp,tmpLen&,PathOfProfile)
    IF gSysVers > 3.1 //Windows 95
      //sectionName = lpAppName
      //entryName = lpKeyName
      //defltstring = lpDefault
      //tmp = lpReturnedString
      //tmpLen = nSize
      //PathOfProfile = lpFileName
      LOCAL tmpLen% = tmpLen&
      RETVAL P:(lpf32)(L:sectionName,L:entry,L:defltString,L:tmp,L:tmpLen%,L:PathOfProfile,L:^GetProcAddress32W(hkernel32,"GetPrivateProfileStringA"),L:%111101,L:6)
    ELSE //Windows3.1
    RETVAL GetPrivateProfileString(sectionName,entry,defltString,tmp,tmpLen&,PathOfProfile)
    ENDIF
RETURN

I've discovered that occasionally a call to this routine on a Win95 system returns a blank when there is, in fact, data available.  As a result, I've had to place this routine inside a do loop to insure that it returns the data (i.e., until tmp$ <> "").  Just curious ... is this is a Windows API bug or something that I am doing wrong?

James


#: 99366 S12/GFA  (CIS:WINAPC)
    04-Sep-97  11:08:14
Sb: GetPrivateProfileString?
Fm: Sjouke Hamstra 100741,1036
To: All
Replies:   0

I noticed different post fixes where they all have to be long integers (%).


Greetings,
Sjouke Hamstra
(11:05 04-Sep-97 using OzWinII)


#: 99393 S12/GFA  (CIS:WINAPC)
    07-Sep-97  11:10:22
Sb: #99390-Metafile and DTP program
Fm: Sjouke Hamstra 100741,1036
To: Jeffrey Heywood 106161,1624
Replies:   0

Hi jeffrey,

It's very likely that the other application needs a placeable metafile format. This is a meta file that contains an additional header. If you have a copy of my book, please look at Chapter 7, Meta Files, which explains how to convert a normal metafile to a placeable one.

If this is not the case, you might also try to add the following lines:

CREATEMETA TheFile$

 MAPMODE MM_ANISOTROPIC
 ~SetWindowOrg(_DC(),0,0)      ' graphical origin
 ~SetWindowExt(_DC(),w,h)      ' scaling (0,0) -> (w,h)

LINE 0,0,300,200
LINE 300,0,0,200
CLOSEMETA

w and h should specify the width and height of the picture respectively.


Greetings,
Sjouke Hamstra
(11:00 07-Sep-97 using OzWinII)


#: 99409 S12/GFA  (CIS:WINAPC)
    09-Sep-97  22:04:10
Sb: #99366-#GetPrivateProfileString?
Fm: James V. Schumacher 104166,2104
To: Sjouke Hamstra 100741,1036 (X)
Replies:   1

Hi Sjouke,

I'm still having trouble with the 32 bit WOW version of GetPrivateProfileString.  I've managed, after a great deal of effort, to duplicate the odd behavior in the program below.  It get values from a file named "test.txt".  If "test.txt" does not yet exist, it outputs the value in defltString$ as tmp$.  Then it writes tmp$ into "test.txt" (creating the file if it doesn't exist).  The file is supposed to have entries from 1 to 1000 where the value assigned to the entries is 1 to 1000.

The strange thing is that when the program is run, with no "test.txt" file in existance, all entries except #154 (which may be different on your machine?) are filled.  #154 is left blank.  This is the same behavior I have observed in my larger application.  If you uncomment the IF statement before the GOSUB myGetPrivateProfileString() statement, delete the "test.txt" file, then rerun the program,  it will fill entry #154.  I've tried substituting DELAY statements and other statement for the IF statement but only the IF statement seems to make things work!   Also, I've noticed that as I make slight changes to the program (eg., in the location of statements), the entry #(s) that are blank change.   By the way, it does the above for both versions of the RETVAL statements in the myGET... and myWRITE... procedures (I tried your advice regarding the long integers).  Finally, if you uncomment the gSysVer = 3.1 statement, the program uses the Win3.1 version of GetPrivateProfileString instead of the WOW version and everything seems to work fine.  Unfortunately, I have filenames longer than 8 characters so I must use the 32bit WOW version.

What in the world is going on?  This bug is serious because it is corrupting my database files.  I can't resume shipping until this is fixed so any advice or suggestions you or anyone else might have would be greatly appreciated!

James

code follows:

*******************************************************************************

DLL #10,"KERNEL"
  DECL DWORD LoadLibraryEx32W(L,L,L) //lpLibFileName,0,0
  DECL BOOL FreeLibrary32W(L)        //hLibModule
  DECL DWORD GetProcAddress32W(L,L)
  DECL DWORD GetVDMPointer32W(L,L)   //lpAddress,fMode
ENDDLL
lpf32% = GetProcAddress(GetModuleHandle("kernel"),"CallProc32W")
hkernel32% = ^LoadLibraryEx32W("kernel32.dll",0,0)
'
TYPE tagOfStruct:
- BYTE cbytes
- BYTE fFixedDisk
- LONG nErrCode
- LONG reserved
- CHAR*128 szPathName$
ENDTYPE
tagOfStruct:OFStruct.
'
gAppPath$ = CHR$(_DRIVE) + ":" + DIR$(0) 'path to folder containing application
pathName$ = gAppPath$ + "\test.txt" + CHR$(0) //path to profile
'
ver% = GetVersion()
x$ = HEX$(ver%,4)
ver$ = STR$(VAL("$" + x$) MOD $100) + "." + STR$(VAL("$" + x$) \ $100)
gSysVers = VAL(ver$)
// gSysVers = 3.1  ' undelete comment to test 3.1 version
'
FOR i& = 1 TO 1000
  sectionName$ = "percentCorrect&"
  entry$ = STR$(i&)
  tmpLen& = 100
  defltString$ = STR$(i&)
  tmp$ = SPACE$(tmpLen& - 1)
  'IF defltString$ = "220" THEN BEEP  //delete comment to fill entry
  GOSUB MyGetPrivateProfileString(sectionName$,entry$,defltString$,tmpLen&,pathName$,tmp$)
  tmp$ = ZTRIM$(tmp$)
  GOSUB MyWritePrivateProfileString(sectionName$,entry$,tmp$,pathName$)
NEXT i&
'
GOSUB quit_Program

PROCEDURE MyGetPrivateProfileString(sectionName$,entryname$,defltString$,tmpLen&,pathOfProfile$,VAR tmpname$)
  IF RIGHT$(sectionName$,1) <> CHR$(0)
    sectionName$ = sectionName$ + CHR$(0)
  ENDIF
  IF RIGHT$(entryname$,1) <> CHR$(0)
    entryname$ = entryname$ + CHR$(0)
  ENDIF
  IF RIGHT$(defltString$,1) <> CHR$(0)
    defltString$ = defltString$ + CHR$(0)
  ENDIF
  IF RIGHT$(pathOfProfile$,1) <> CHR$(0)
    pathOfProfile$ = pathOfProfile$ + CHR$(0)
  ENDIF
  '
  'sectionName = V:sectionName$
  'entryname = V:entryname$
  'defltString = V:defltString$
  'PathOfProfile = V:pathOfProfile$
  'tmpname = V:tmpname$
  sectionName% = V:sectionName$
  entryname% = V:entryname$
  defltstring% = V:defltString$
  pathOfProfile% = V:pathOfProfile$
  tmpname% = V:tmpname$
  '
  IF gSysVers > 3.1 //Windows 95
    tmpLen% = tmpLen&
    RETVAL P:(lpf32%)(L:sectionName%,L:entryname%,L:defltstring%,L:tmpname%,L:tmpLen%,L:pathOfProfile%,L:^GetProcAddress32W(hkernel32%,"GetPrivateProfileStringA"),L:%111101,L:6)
    'RETVAL P:(lpf32%)(L:sectionName,L:entryname,L:defltString,L:tmpname,L:tmpLen%,L:PathOfProfile,L:^GetProcAddress32W(hkernel32%,"GetPrivateProfileStringA"),L:%111101,L:6)
  ELSE //Windows3.1
    RETVAL GetPrivateProfileString(sectionName%,entryname%,defltstring%,tmpname%,tmpLen&,pathOfProfile%)
    'RETVAL GetPrivateProfileString(sectionName,entryname,defltstring,tmpname,tmpLen&,pathOfProfile)
  ENDIF
RETURN

PROCEDURE MyWritePrivateProfileString(sectionName$,entryname$,tmpname$,pathOfProfile$)
  IF RIGHT$(sectionName$,1) <> CHR$(0)
    sectionName$ = sectionName$ + CHR$(0)
  ENDIF
  IF RIGHT$(entryname$,1) <> CHR$(0)
    entryname$ = entryname$ + CHR$(0)
  ENDIF
  IF RIGHT$(tmpname$,1) <> CHR$(0)
    tmpname$ = tmpname$ + CHR$(0)
  ENDIF
  IF RIGHT$(pathOfProfile$,1) <> CHR$(0)
    pathOfProfile$ = pathOfProfile$ + CHR$(0)
  ENDIF
  '
  ' sectionName = V:sectionName$
  ' entryname = V:entryname$
  ' tmpname = V:tmpname$
  ' PathOfProfile = V:pathOfProfile$
  sectionName% = V:sectionName$
  entryname% = V:entryname$
  tmpname% = V:tmpname$
  pathOfProfile% = V:pathOfProfile$
  '
  IF gSysVers > 3.1 //Windows 95
    RETVAL P:(lpf32%)(L:sectionName%,L:entryname%,L:tmpname%,L:pathOfProfile%,L:^GetProcAddress32W(hkernel32%,"WritePrivateProfileStringA"),L:%1111,L:4)
    'RETVAL P:(lpf32%)(L:sectionName,L:entryname,L:tmpname,L:PathOfProfile,L:^GetProcAddress32W(hkernel32%,"WritePrivateProfileStringA"),L:%1111,L:4)
    '
    DO
    UNTIL FN MyEXIST(pathOfProfile$) = TRUE
    '
  ELSE //Windows3.1
    'RETVAL WritePrivateProfileString(sectionName,entryname,tmpname,PathOfProfile)
    RETVAL WritePrivateProfileString(sectionName%,entryname%,tmpname%,pathOfProfile%)
    DO
    UNTIL FN MyEXIST(pathOfProfile$) = TRUE
  ENDIF
RETURN

FUNCTION MyEXIST(path$)
  //path$ may not be more than 127 characters or OpenFile will not work
  IF MID$(path$,LEN(path$) - 4,1) = "." //its a file
    IF gSysVers > 3.1 // Windows95
      GOSUB openfile(V:path$,*OFStruct.,OF_EXIST)
      IF _EAX = -1 //HFILE_ERROR file does not exists
        RETURN FALSE
      ELSE //file exists
        RETURN TRUE
      ENDIF
    ELSE // Windows3.1
      RETURN EXIST(path$) //leave as EXIST
    ENDIF
  ELSE //its a folder
    RETURN EXIST(path$ + "\NUL") //leave as EXIST
  ENDIF
ENDFUNC

PROCEDURE openfile(lpFilePath%,lpOFStruct%,uStyle) //access 32bit API per Sjouke Technique
  //FilePath$ may not be more than 127 characters
  RETVAL P:(lpf32%)(L:lpFilePath%,L:lpOFStruct%,L:uStyle,L:^GetProcAddress32W(hkernel32%,"OpenFile"),L:%110,L:3)
RETURN

PROCEDURE quit_Program
  FREEDLL 10 //KERNEL
  IF hkernel32 > 32 THEN ~^FreeLibrary32W(hkernel32)
  END
RETURN

********************************************************************************


#: 99411 S12/GFA  (CIS:WINAPC)
    10-Sep-97  15:19:02
Sb: #99409-GetPrivateProfileString?
Fm: Sjouke Hamstra 100741,1036
To: James V. Schumacher 104166,2104 (X)
Replies:   0

James,

I'm sorry, but all entries get filled when I use the code on my machine. Maybe others might try to run the code...

James, RETVAL is used to return values from callback procedures or DLL functions. RETVAL should not be used in normal procedures. You cannot trust values set with RETVAL, within a normal program. If you want to return a value use RETURN within a FUNCTION or a VAR variable as a parameter in procedure heading. So, replace RETVAL with:

~P:()()
void P:()()
var = P:()()

For instance:
PROCEDURE openfile(lpFilePath%,lpOFStruct%,uStyle) //access 32bit API per Sjouke Technique
  //FilePath$ may not be more than 127 characters
  RETVAL P:(lpf32%)(L:lpFilePath%,L:lpOFStruct%,L:uStyle,
          L:^GetProcAddress32W(hkernel32%,"OpenFile"),L:%110,L:3)
RETURN

use:

FUNCTION openfile(lpFilePath%,lpOFStruct%,uStyle) //access 32bit API per Sjouke Technique
  //FilePath$ may not be more than 127 characters
  RETURN  P:(lpf32%)(L:lpFilePath%,L:lpOFStruct%,L:uStyle,
          L:^GetProcAddress32W(hkernel32%,"OpenFile"),L:%110,L:3)
ENDFUNC

I doubt this mistake is the cause of your problems.

Another GFA related problem is string passing to API or DLL functions. When you pass the address of a (null terminated of course) string, obtain it as late as possible. Internally GFA can reorganize string memory any time, leaving pointers invalid. So when passing a string address use:

~P:()(L:V:str$,...)


There is something else that bothers me. A 16-bit application should try to avoid using long file names. Even 32-application stick to 8.3 filenames. Why should you need LFN?




 
Greetings,
Sjouke Hamstra
(12:54 10-Sep-97 using OzWinII)


#: 99485 S12/GFA  (CIS:WINAPC)
    25-Sep-97  12:14:06
Sb: #99465-#Keyboard Messages
Fm: Sjouke Hamstra 100741,1036
To: Bob Springett 100776,3023 (X)
Replies:   1

Hi Bob,

An application that processes keyboard input typically ignores all but the WM_CHAR message. It only processes the WM_KEYDOWN keystroke message for those that contain virtual-key codes for the cursor movement keys, shift keys (also called control keys), and function keys.

The MESS_KBD program merely demonstrates the relation between the WM_CHAR and WM_KEYDOWN message. The WM_KEYDOWN part should additional test for the function keys and leave all other keys to be processed by the WM_CHAR handler.




Greetings,
Sjouke Hamstra
(12:10 25-Sep-97 using OzWinII)


#: 99584 S12/GFA  (CIS:WINAPC)
    13-Oct-97  10:39:24
Sb: #99582-showcursor()
Fm: Sjouke Hamstra 100741,1036
To: James V. Schumacher 104166,2104
Replies:   0

>> Does anyone see anything wrong with this code snippet?

IF ShowCursor(TRUE) > 0
  DO
  UNTIL ShowCursor(FALSE) = 0 //hide it till cursorcount& = 0
ENDIF

Its purpose is to make sure that the display counter is zero (i.e., just showing the cursor) so that the next time a HIDEM call is made the cursor will disappear.  Problem is that although everything seems to work fine on W95 systems, the cursor is not showing up on my W3.1 test platform.  I suspect that is a sign of some other problem but I thought I'd just be sure that this code is ok first. <<

The cursor is hidden when the internal counter is -1 or less.

The cursor is a shared resource. A window that hides the cursor should show it before the cursor leaves its client area or before the window relinquishes control to another window. 

The initial setting of the cursor show level is zero; otherwise, it is -1. 

Make sure that any SHOWM has a corresponding HIDEM and your application is not responsible for a disappearing cursor. Other programs should do the same. This way a mouse is shown after creating a window, because the counter will be 0.

Actually, if a mouse exists, it will be there unless YOU hide it.


Greetings,
Sjouke Hamstra
(16:39 11-Oct-97 using OzWinII)


#: 99701 S12/GFA  (CIS:WINAPC)
    06-Nov-97  10:06:07
Sb: #99698-programmer's nightmare
Fm: Sjouke Hamstra 100741,1036
To: James V. Schumacher 104166,2104
Replies:   0

James,

I'm puzzled as you are. On the other hand there may be some other problem. I'm currently writing an article about events, to be published on the GFA web site. Frank Ostrowski the author of GFA notified me about problems with GETEVENT and its variants used locally in procedures. Only one global message loop is allowed. This message loop dispatches the messages to the appropriate procedures based upon the value in _hWnd. This is of importance, especially when you use dialog boxes. Using local message loops, either crashes the program or produces unwanted effects.

The most best way to go is by using CB for each window/dialog. the second best way is by handling messages for the window using MENU()-array and declaring CBs for dialog boxes, and less best way is by using MENU() for both windows and dialogs.

I have yet another tool I use to watch the messages obtained with GETEVENT and messages that are sent to callback procedures. I'll post it too you.

I'm not sure about the WM_ERASEBKGND, this is a result of BeginPaint. For your information, when the posted WM_PAINT message is dispatched (during execution of GETEVENT) to and received in the GFA window procedure, GFA uses BeginPaint/EndPaint to validate the update rectangle. This causes a WM_ERASEBKGND. The update rectangle is copied to MENU(7)-MENU(10). After the window procedure returns to GETEVENT, GFA clears the window with the color set with CLS. The window gets cleared twice! However, not in a compiled program. Windows in compiled programs are only cleared when CLS is used explicitly! Then the next line in your program is executed. Usually SWITCH MENU(1), or MENU(11), etc.

There are situations that WM_PAINT isn't posted but sent only (modal dialog boxes, like DLG OPEN/DLG SAVE, etc.). GFA obtains the message directly in the window procedure and updates (WM_ERASBKGND) and validates the update rectangle. This is message is not copied to MENU() and CLS is not executed. Are you in any way encountering a sent WM_PAINT? Any way try the WM_SPY.LST I'll send you. You'll find out immediately.

Greetings,
Sjouke Hamstra
(10:02 06-Nov-97 using OzWinII)


#: 99711 S12/GFA  (CIS:WINAPC)
    07-Nov-97  22:05:05
Sb: #changing sound volume
Fm: James V. Schumacher 104166,2104
To: ALL
Replies:   1

Hi,

 I want my program to store the original sound volume, change the volume to a level the user has set in his preference file, then just before exiting, return the sound to the original volume.  At the bottom of this post is a program that is supposed to get the sound volume, alter it, and then play a wave file. 

First, I get an error in the waveOutGetVolume() call.  It is error 11 which I think means invalid parameters.    Any idea what is wrong?

Second, if the FN setSoundVolume(100) routine is uncommented, the waveOutSetVolume() call seems to sets the sound volume to zero although a value of 100 is supposedly about midway to the maximum (255).  No error is returned.  Afterwords, you have to go to the control panel to regain sound on the computer.  Again, any idea what is wrong?

I'm basing this routine on Microsoft Knowledge document Q118377. Does anyone see the problem or is there a better way to adjust the sound volume? 

Thanks,

James

**************************************
OPENW #1
'
DLL #1, "MMSYSTEM.dll"
  DECL WORD sndPlaySound(l,w)
  DECL WORD waveOutSetVolume(w,w,w)   //device,volumeright,volumeleft
  DECL WORD waveOutGetVolume(w,l)  //device,bothvolumes
ENDDLL
'
waveerr& = ^waveOutGetVolume(0,bothVolumes%)
gOriginalSoundVolume& = LOWORD(bothVolumes%)
'
TEXT 10,10,"waveerr&"
TEXT 10,30,waveerr&
TEXT 10,50,"gOriginalSoundVolume&"
TEXT 10,70,gOriginalSoundVolume&
'
'gSoundVolume& = FN setSoundVolume(100)
'
SND_SYNC = &H0 //play synchronously
~^sndPlaySound("FANFARE.WAV",SND_SYNC)
'
FREEDLL 1
CLOSEW #1
'
FUNCTION setSoundVolume (sndLevel&)
  LOCAL osErr&
  osErr& = ^waveOutSetVolume(0,sndLevel&,sndLevel&)
  TEXT 10,130,"oserr&"
  TEXT 10,150,osErr&
  TEXT 10,170,"sndLevel&"
  TEXT 10,190,sndLevel&
  RETURN  sndLevel&
ENDFUNC
*******************************************************


#: 99712 S12/GFA  (CIS:WINAPC)
    08-Nov-97  02:23:04
Sb: #99711-changing sound volume
Fm: James V. Schumacher 104166,2104
To: James V. Schumacher 104166,2104 (X)
Replies:   0

Hi,

As I often do, I've solved "part" of my problem just after posting a question.  Turns out that ^waveOutGetVolume()function has to be passed a far pointer as follows:

waveerr& = ^waveOutGetVolume(0,V:bothVolumes%).

Now waveerr& = 0 and gOriginalSoundVolume& is non-zero.

However, I'm still confused as to the maximum and minimum values for the parameter passed to waveOutSetVolume as well as the output value from that function.   Values from  0 to 32767 seems to alter the volume between none and halfway to its maximum and the output value goes from 0 to 32767.   To go from there to the maximum volume, either input values must be from -32767 to -1 (which seems a strange way to denote increasing amplitude but then output values are then in agreement) or 32767 to 66634 (but a word integer is not supposed to be greater than 32767 and output values from -32767 to -1 are returned).  So, what is the correct way to specify the input value for this function?

James


#: 99719 S12/GFA  (CIS:WINAPC)
    09-Nov-97  16:54:12
Sb: #99712-changing sound volume
Fm: Sjouke Hamstra 100741,1036
To: James V. Schumacher 104166,2104
Replies:   0

Hi James,

You're aware of the following:

The low-order word contains the left channel volume setting, and the high-order word contains the right channel setting. A value of 0xFFFF represents full volume, and a value of 0x0000 is silence. 

You can set a word var to any value between 0 and $FFFF:

left&=$FFFF, right&=$FFFF

Now it's a matter of interpretation: If you print or use these vars in a calculation the vars are interpreted as signed. These values can be passed to functions that interprets them as unsigned words. 

dwVolume%=MAKELONG(right&,long&)

If you would like to use them as unsigned values be sure to add the conversion function CARD() or UWORD(). To check the return values of waveOutGetVolume:

right& = HIWORD(bothVolumes%)
PRINT CARD(right&)

or 

IF CARD(right%) = $FFFF, etc.







Greetings,
Sjouke Hamstra
(16:51 09-Nov-97 using OzWinII)


#: 99729 S12/GFA  (CIS:WINAPC)
    11-Nov-97  14:40:10
Sb: #99722-programmer's nightmare
Fm: Sjouke Hamstra 100741,1036
To: James V. Schumacher 104166,2104
Replies:   0

Hi James,

>> Thanks for the advice on message handling.  I'll try to reorganize my program to avoid possible problems although this will definitely make some things more difficult to do (and follow).  I'll also make sure to keep this in mind in future efforts. <<

The more I 'investigate' the more I tend to make use of the following structure:

Use CB to process WM_PAINTs
Use GETEVENT rather than SLEEP (returns immediately when compiled)
Use _winId to find out if a queued message is available for a window.

Something like this:
OPENW #1
CB WIN(1),0 TO -1,WndProc1()
DO
  GETEVENT
  IF _winId =1 THEN HandleWnd1
UNTIL ProgEnd!

PROCEDURE WndProc1(h&,m&,w&,l%)
SWITCH m&
CASE WM_PAINT
  BEGINPAINT h&,ps$
  ...
  ENDPAINT h&,ps$
  RETVAL 0 // prevents WM_PAINT to be copied to MENU(11)
ENDSWITCH
RETURN
  
In my article I explain how to add a dialog box, but I personally tend to use the API calls (I provide a method to use the GFR file in API calls). 

I asked GFA about my investigations and I hope to get some answers soon. 


Greetings,
Sjouke Hamstra
(11:26 11-Nov-97 using OzWinII)


#: 99747 S12/GFA  (CIS:WINAPC)
    17-Nov-97  22:43:07
Sb: #99728-changing sound volume
Fm: James V. Schumacher 104166,2104
To: Sjouke Hamstra 100741,1036 (X)
Replies:   0

Sjouke,

I can't recall whether I sent this.  If so, sorry for the duplication.  I seemed to have solved most of my problem with respect to controlling the sound volume.  The code below allows the volume to be increased above the initial setting when the program is first executed.  It also changes the value one finds on the multimedia control panel sound volume scroll bar when that is opened.  However,  there is a sound volume control on the right side of my task bar (at the bottom of my screen) that does not seem to be affected by the code below or by changes to the multimedia control panel scroll bar.  I don't know how the two are related.  Perhaps, the one on the task bar is created by my sound card software?

In any case, the DLL callout in my program is:

  DLL #5, "MMSYSTEM.dll"
    DECL WORD waveOutSetVolume(w,w,w)   //device,volumeright,volumeleft
    DECL WORD waveOutGetVolume(w,l)        //device,bothvolumes
  ENDDLL

 To store the current volume setting I use the following code: 

  waveerr& = ^waveOutGetVolume(0,V:bothVolumes%)
  gOriginalSoundVolume& = LOWORD(bothVolumes%)
  gSoundVolume& = gOriginalSoundVolume&

I use the left sound volume because it is never ignored in ^waveOutSetVolume calls.
The following code creates a scroll bar showing the current volume:

  minSoundVolume& = 0
  maxSoundVolume& = 100
  scrollBarLength& = 168
  scrollBarWidth& = 20
  pixelHeight& = WIND_GET(14)
  yPos& = WIND_GET(7) / 2 - pixelHeight& / 2
  soundVolumeScrollBarRect.left = WIND_GET(6) / 2 - scrollBarLength& / 2
  soundVolumeScrollBarRect.top = yPos&
  soundVolumeScrollBarRect.right = WIND_GET(6) / 2 + scrollBarLength& / 2
  soundVolumeScrollBarRect.bottom = yPos& + scrollBarWidth&
  Style& = SBS_HORZ
  CONTROL "",g_btnScrollSoundVolume&,"scrollbar",Style&,soundVolumeScrollBarRect.left,soundVolumeScrollBarRect.top,scrollBarLength&,scrollBarWidth&
  hScrollBar& = DLGITEM(-1,g_btnScrollSoundVolume&)
 ~SetScrollRange(hScrollBar&,SB_CTL,minSoundVolume&,maxSoundVolume&, TRUE)
 ~SetScrollPos(hScrollBar&,SB_CTL,100 * CARD(gSoundVolume&) / CARD($FFFF),TRUE)

Then I use this code in a CB statement to alter the values on the scroll bar and adjust the sound accordingly:

    SELECT WIN() // instead of _winId
    CASE g_overrideSoundVolumeWind&
      IF mess& = WM_HSCROLL
        changemade! = FALSE
        SELECT wparam&
        CASE SB_LINEUP //left arrow
          gSoundVolume = GetScrollPos(HIWORD(lparam%),SB_CTL)
          IF gSoundVolume > 0 THEN DEC gSoundVolume
          changemade! = TRUE
        CASE SB_LINEDOWN //right arrow
          gSoundVolume = GetScrollPos(HIWORD(lparam%),SB_CTL)
          IF gSoundVolume < 100 THEN INC gSoundVolume
          changemade! = TRUE
        CASE SB_PAGEUP //page left
          gSoundVolume = GetScrollPos(HIWORD(lparam%),SB_CTL)
          IF gSoundVolume > 0 THEN gSoundVolume = gSoundVolume - MIN(10,gSoundVolume - 0)
          changemade! = TRUE
        CASE SB_PAGEDOWN //page right
          gSoundVolume = GetScrollPos(HIWORD(lparam%),SB_CTL)
          IF gSoundVolume < 100 THEN gSoundVolume = gSoundVolume + MIN(10,100 - gSoundVolume)
          changemade! = TRUE
        CASE SB_ENDSCROLL //scroll button moved
          gSoundVolume = GetScrollPos(HIWORD(lparam%),SB_CTL)
          changemade! = TRUE
        ENDSELECT
        IF changemade! = TRUE
          gSoundVolume& = gSoundVolume
          ~SetScrollPos(HIWORD(lparam%),SB_CTL,gSoundVolume&,TRUE)
          gSoundVolume = gSoundVolume / 100 * CARD($FFFF)
          //to deal with silly windows way of doing it
          //where 0 is no sound
          //      32767 and -32767 are half volume
          //      -1 if full volume
          IF gSoundVolume > 32767.5
            gSoundVolume& = -32767.5 + (gSoundVolume - 32768.5)
          ELSE
            gSoundVolume& = gSoundVolume
          ENDIF
          gSoundVolume& = FN setSoundVolume(gSoundVolume&)
        ENDIF
      ENDIF
      // end 11/07/97 addition

FUNCTION setSoundVolume (sndLevel&)
  LOCAL osErr&
  osErr& = ^waveOutSetVolume(0,CARD(sndLevel&),CARD(sndLevel&)) //11/07/97
  RETURN  sndLevel&
ENDFUNC

Yours truly,

James


#: 99754 S12/GFA  (CIS:WINAPC)
    19-Nov-97  10:11:00
Sb: #99744-Task Bar Icons
Fm: Sjouke Hamstra 100741,1036
To: Andrew Risely 100667,1620
Replies:   0

>> Can this be done in 16bit applications and if so how. <<

The system allows you to add status or notification information to the taskbar. Because the taskbar is a shared resource, add information to it that is of a global nature only or that needs monitoring by the user while working with other applications.
  
The Shell_NotifyIcon function provides support for adding a status item in the taskbar. For more information about this function, see the documentation included in the Win32 SDK.

Additionally, you will need GFA32API to implement 32 bit function in your 16-bit application.


Greetings,
Sjouke Hamstra
(11:11 18-Nov-97 using OzWinII)


#: 99762 S12/GFA  (CIS:WINAPC)
    21-Nov-97  09:02:11
Sb: comdlg32
Fm: John Findlay 100130,1771
To: Yourself
Replies:   0

Hello,

Has anyone managed to display the Win95 file selector?

    	hkernel32% = ^LoadLibraryEx32W("kernel32.dll",0,0)
    	huser32%   = ^LoadLibraryEx32W("user32.dll",0,0)
    	hgdi32%    = ^LoadLibraryEx32W("gdi32.dll",0,0)
    	hcomdlg32% = ^LoadLibraryEx32W("comdlg32.dll",0,0)

Using the above code for kernel32, user32 and gdi32 one gets a negative value returned, but the call for comdlg32.dll returns a positive number! 

So, is it possible, or am I barking up the wrong tree?

Regards,

John


#: 99777 S12/GFA  (CIS:WINAPC)
    23-Nov-97  10:50:12
Sb: Leaving Compuserve
Fm: Sjouke Hamstra 100741,1036
To: [F] GFA 75300,3224
Replies:   0

To ALL,

Since the GFA mailing list works ok now, I will leave Compuserve in the near future and switch (have done already) to the mailing list.
For a description on how to subscribe to the mailing list, please take a look at

http:\\www.ourworld.compuserve.com\gfasoft\


My new mailing address is 

shamstra@zwcai.net

if you like, you can always post me mail directly to this address.




Greetings,
Sjouke Hamstra
(10:50 23-Nov-97 using OzWinII)


#: 99781 S12/GFA  (CIS:WINAPC)
    24-Nov-97  14:17:05
Sb: Listbox Bmp
Fm: Friedrich Rode 100602,702
To: all 100602,702
Replies:   0

Hello, to all !

Topic: Bmp into Listbox.
Has somebody a small example how it is represented Bmp's 
in a Listbox?

mfg Friedrich


#: 99784 S12/GFA  (CIS:WINAPC)
    24-Nov-97  19:08:13
Sb: #99776-comdlg32
Fm: John Findlay 100130,1771
To: Sjouke Hamstra 100741,1036
Replies:   0

Hi Sjouke,

>> I don't see any errors. Did you try to execute one of its functions? <<

Yes, GetOpenFileNameA(). As below;

ret% = P:(lpf32%)(L:V:opfn.,L:^GetProcAddress32W(hcomdlg32%,"GetOpenFileNameA"),L:%1,L:1)

Is the above call correct? The OPENFILENAME: structure is correctly filed in. I've used it with a call to the 16bit dll;  DECL DWORD GetOpenFileName(L) and it's O.K.


I thought that as the other calls to 32bit dlls return a negative number that perhaps

 ^LoadLibraryEx32W("comdlg32.dll",0,0)

should as well.
====================================================================


>> See also my mail to ALL. <<

Sorry to see you leave here Sjouke. Ill keep in touch with you with your new e-mail address.

Your help on this forum will be missed. Hows the new book coming on?


Regards,

John


#: 99800 S12/GFA  (CIS:WINAPC)
    28-Nov-97  09:56:00
Sb: #99781-Listbox Bmp
Fm: Sjouke Hamstra 100741,1036
To: Friedrich Rode 100602,702
Replies:   0

Hi Friedrich,

Provide the handle to 16 color bitmaps with LB_SETITEMDATA:

SENDMESSAGE hLb,LB_ADDSTRING,0,V:t$,n&
SENDMESSAGE hLb,LB_SETITEMDATA,n&,MAKELONG(0,hBmpCol(i))

the following procedure should be called in response to a WM_DRAWITEM message:

(DEFINT a-z)

PROCEDURE OwnerDrawBox(pdis)
  LOCAL tcol, bcol, oldtcol, oldbcol, hMemdc, hdc
  LOCAL Id&, hbr, x&, y&, rh&
  LOCAL t$=STRING$(100,0)
  LOCAL fOff  = 14            ' FIELDOFFSET({pdis}.rcItem)

  Id&   = {pdis}.itemID ' more convenient
  IF Id& != -1 THEN     ' no items present

    TTEXTMETRIC:tm.

    IF {pdis}.CtlType = ODT_LISTBOX
      SENDMESSAGE {pdis}.hWndItem,LB_GETTEXT,Id&,V:t$
    ELSE
      SENDMESSAGE {pdis}.hWndItem,CB_GETLBTEXT,Id&,V:t$
    ENDIF
    t$ = ZTRIM$(t$)

    hdc = {pdis}.hDC    ' more convenient

    IF {pdis}.itemState & ODS_SELECTED  ' selected?
      oldtcol = SetTextColor(hdc,SYSCOL(COLOR_HIGHLIGHTTEXT))
      oldbcol = SetBkColor(hdc,SYSCOL(COLOR_HIGHLIGHT))
    ENDIF

    ~GetTextMetrics(hdc,*tm.)
    x& = bmpW& + 6

    rh& = {pdis}.rcy2 - {pdis}.rcy1
    y& = {pdis}.rcy1 + (rh& - tm.tmHeight) / 2

    ~ExtTextOut(hdc, x&,y&, ETO_OPAQUE, pdis + fOff,t$, LEN(t$), 0)

    x& = {pdis}.rcx1 + 2
    y& = {pdis}.rcy1 + (rh& - bmpH&) / 2

    hMemdc = MEMDC(hdc)
    SETBMP hMemdc,{pdis}.itemData       ' contains hBmp
    BITBLT hMemdc,0,0,bmpW&,bmpH&,hdc,x&,y&,SRCCOPY
    FREEDC hMemdc

    IF {pdis}.itemState & ODS_SELECTED  ' selected?
      ~SetTextColor(hdc,oldtcol)
      ~SetBkColor(hdc,oldbcol)
    ENDIF

    ERASE tm.

  ENDIF

  IF {pdis}.itemState & ODS_FOCUS
    ~DrawFocusRect({pdis}.hDC,pdis + fOff)
  ENDIF

  RETVAL 1
RETURN

Greetings,
Sjouke Hamstra
(09:37 27-Nov-97 using OzWinII)


