(Tagged messages in GFA Basic)

#: 98096 S12/GFA  (CIS:WINAPC)
    25-Apr-97  09:05:27
Sb: #98095-Calling 32 APIs
Fm: Sjouke Hamstra 100741,1036
To: James V. Schumacher 104166,2104
Replies:   0

Hi James,

 >>  Is there anyway to include the MoveFile() API in my  program other than
through GFA32API.DLL?  ... nothing personal Sjouke :)  <<

No, 32 bits functions located in 32 bits compiled code (that's why they're called 32-bits functions) can only be called by some new 16-bit functions in the Windows 95 16-bit kernel (Has it a 16 bit kernel? Yes it has, however the main part of the kernel is located in kernel32.dll). When MS released the kernel of W95 they decided to make it possible to call the 32 part from the 16-bit part, and moreover they decided to make this a general approach. So each 16-bit application can call each 32-bit dll, by using the WOW (Windows on Windows) found in the 16 bit part of the Windows 95 kernel.

Knowing this you should be able to analyze my code and adapt to your own situation. (And nothing personal, but I find my solution by putting the hole bunch in a separate DLL, a nice one ;-) )

Greetings, SH


#: 98146 S12/GFA  (CIS:WINAPC)
    29-Apr-97  22:06:03
Sb: #98096-#Calling 32 APIs
Fm: James V. Schumacher 104166,2104
To: Sjouke Hamstra 100741,1036 (X)
Replies:   2

Hi Sjouke (and John),

I tried to incorporate the pertinent code from the GFA32API.gfw and BASIS32.gfw examples into my program so that I could add MoveFile() to it directly.
 
Here's what I did.  First I declared the kernel routines:

    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)

Then I added the procedure below to the end of my application file:

    PROCEDURE MoveFile(lpExistPath, lpNewPath)
      RETVAL P:(lpf32)(L:lpExistPath,L:lpNewPath,L:^GetProcAddress32W(hkernel32,"MoveFileA"),L:%11,L:2)
    RETURN

Finally, this procedure is called by the application as follows:

    GOSUB MoveFile(V:existingPath$,V:newPath$)
    ~MessageBox(WIN(WIN()),"_EAX",STR$(_EAX),MB_OK) //return value
 
Unfortunately, this doesn't work.  No newPath$ file is created.  The return value is _EAX = 0 which I gather indicates a problem.  The values of lpf32, lpExistPath, lpNewPath and hkernel32 appear to be ok just prior to the P: statement.  Also, the existingPath$ file is present and newPath$ is a valid pathname.   The existingPath$ file is a "wav" file if that matters.  Do you have any suggestions?  Does this stuff HAVE to be in a separate DLL ala GFA32API.DLL to work?

James


#: 98158 S12/GFA  (CIS:WINAPC)
    30-Apr-97  09:20:16
Sb: #98146-Calling 32 APIs
Fm: Sjouke Hamstra 100741,1036
To: James V. Schumacher 104166,2104
Replies:   0

Hi James,

 >> Does this stuff HAVE to be in a separate DLL ala  GFA32API.DLL to work?
<<

Certainly not. I couldn't find a mistake in your code. There is only one thing; you cannot rely on _EAX when you return a value using RETVAL in an interpreted program. In most cases you won't have a problem (i.e. RETVAL = _EAX) however there are situations _EAX does not reflect the value passed with RETVAL. So the solution is as follows:

PRO A32Api(...)
 TRY
   _EAX = P:(lpf32%) ()
 CATCH
 _EAX = ERR
RET

Be aware that I put the P: call between TRY/CATCH to trap GFABasic errors; such as 'DLL function not found", ERR does not reflect an error occured in the win32 function itself. This is returnded by _EAX and it's value depends on the function. For instance a return value of HFILE_ERROR = -1.

To distinguish between a normal return value and a GFABasic error, there should be a messagebox added after the CATCH statement.

Greetings, SH


#: 98161 S12/GFA  (CIS:WINAPC)
    30-Apr-97  12:49:07
Sb: #98146-Calling 32 APIs
Fm: John Findlay 100130,1771
To: James V. Schumacher 104166,2104
Replies:   0

James, if you are incorporating the calls into your app you should use FUNCTION and RETURN.

This code works;

OPENW #1

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)
existingPath$ = "c:\temp1.gfw"  + CHR$(0)
newPath$      = "c:\temp4.gfw" + CHR$(0)

ret% = @MoveFile(V:existingPath$,V:newPath$)

IF ret% < -8000
  // ===================================================
  // GFA Function failed;
  // ===================================================
  PRINT ERR$(ret% + 10000)
ELSE IF ret% = FALSE
  // ===================================================
  // API Failed; get error with API32 GetLastError()
  // ===================================================
  ret% = @GetLastError()
  IF ret% =   2 THEN ~MessageBox(WIN(WIN()), "File not found!", "API File Error", MB_OK)
  IF ret% = 183 THEN ~MessageBox(WIN(WIN()), "File already exists!", "API File Error", MB_OK)
ENDIF

IF hkernel32% > 32 THEN ~^FreeLibrary32W(hkernel32%)
FREEDLL 10
KEYGET a%
CLOSEW #1
EDIT

FUNCTION MoveFile(lpszExisting%, lpszNew%)
  TRY
    RETURN P:(lpf32%)(L:lpszExisting%,L:lpszNew%,L:^GetProcAddress32W(hkernel32%,"MoveFileA"),L:%11,L:2)
  CATCH
  ~MessageBox(WIN(WIN()), "Error " + STR$(ERR), "GFA Function Error", MB_OK)
  RETURN ERR -10000
ENDFUNC
FUNCTION GetLastError()
  TRY
    RETURN P:(lpf32%)(L:^GetProcAddress32W(hkernel32%,"GetLastError"),L:%0,L:0)
  CATCH
  ~MessageBox(WIN(WIN()), "Error " + STR$(ERR), "GFA Function Error", MB_OK)
  RETURN ERR -10000
ENDFUNC



Regards,

John


#: 98155 S12/GFA  (CIS:WINAPC)
    30-Apr-97  07:22:01
Sb: #32bit OpenFile()?
Fm: James V. Schumacher 104166,2104
To: Sjouke Hamstra 100741,1036 (X)
Replies:   1

Sjouke and John,

In order to use MoveFile(), I needed to be able to delete the previous version of any file with a Windows95 filename (i.e., greater than 8 characters or having spaces in it).  This is the 32bitAPI code that I used:

    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)

    GOSUB openfile(V:newPath$,*OFStruct.,OF_DELETE)
 
    PROCEDURE openfile(lpFileName,lpOFStruct,uStyle)
  RETVAL P:(lpf32)(L:lpFileName,L:lpOFStruct,L:uStyle,L:^GetProcAddress32W(hkernel32,"OpenFile"),L:%110,L:3)
    RETURN

My OFStruct type is defined as follows:

  TYPE tagOfStruct:
  - BYTE cbytes
  - BYTE fFixedDisk
  - CARD nErrCode
  - LONG reserved
  - CHAR*128 szPathName$
  ENDTYPE
  tagOfStruct:OFStruct.

Although it appears to work fine, do you see any mistakes?

Also, I would like to use the OpenFile routine to check for the existance of Window95 files.  The following is what I tried:

      GOSUB openfile(V:wavePath$,*OFStruct.,OF_EXIST)
      ~MessageBox(WIN(WIN()),"_EAX",STR$(_EAX),MB_OK)

It didn't work.  _EAX =  -1 regardless of whether the file exists or not.
The documentation says it returns a handle (if the file exists) or HFILE_ERROR?  What is HFILE_ERROR?  Any idea what is wrong? 

Thanks!!!

James


#: 98156 S12/GFA  (CIS:WINAPC)
    30-Apr-97  09:20:13
Sb: #98155-32bit OpenFile()?
Fm: Sjouke Hamstra 100741,1036
To: James V. Schumacher 104166,2104
Replies:   0

Hi James,

 >> My OFStruct type is defined as follows:

  TYPE tagOfStruct:
   - BYTE cbytes
   - BYTE fFixedDisk
   - CARD nErrCode
   - LONG reserved
   - CHAR*128 szPathName$
   ENDTYPE
   tagOfStruct:OFStruct.  <<

The nErrCode element is wrong, it should be a long. All (U)INT types are 32- bits in WIN32.

Greetings, SH


#: 98171 S12/GFA  (CIS:WINAPC)
    01-May-97  02:24:07
Sb: #98161-Calling 32 APIs
Fm: James V. Schumacher 104166,2104
To: John Findlay 100130,1771
Replies:   0

>> James, if you are incorporating the calls into your app you should use FUNCTION and RETURN. <<

Hi John,

Haven't decided which approach is to use yet.  It may depend on the circumstances. Here is my current routine, incorporating some of your suggestions:

PROCEDURE MoveFile(lpOldPath,lpNewPath) //access 32bit API per Sjouke Technique
  TRY
    _EAX = P:(lpf32)(L:lpOldPath,L:lpNewPath,L:^GetProcAddress32W(hkernel32,"MoveFileA"),L:%11,L:2)
    IF _EAX = FALSE
      ret% = FN getlasterror()
      IF ret% = 2 THEN ~MessageBox(WIN(WIN()),"File Not Found!","API32 MoveFile Error",MB_OK)
      IF ret% = 183 THEN ~MessageBox(WIN(WIN()),"File Already Exists!","API32 MoveFile Error",MB_OK)
      RETVAL _EAX
    ELSE
      RETVAL _EAX
    ENDIF
  CATCH
  _EAX = ERR
  ~MessageBox(WIN(WIN()),"MoveFile Error " + STR$(ERR),"GFA Function Error",MB_OK)
RETURN

I may change to a function after thinking it over.  By the way, thanks for the GetLastError function P: statement!

Now I'm off to create P: statements for GetPrivateProfileString and WritePrivateProfileString.  I'll post them once they're working ... or if they're not. :)

James


#: 98170 S12/GFA  (CIS:WINAPC)
    01-May-97  02:24:02
Sb: #98156-32bit OpenFile()?
Fm: James V. Schumacher 104166,2104
To: Sjouke Hamstra 100741,1036 (X)
Replies:   0

>> The nErrCode element is wrong, it should be a long. All (U)INT types are 32- bits in WIN32. <<

I made the change.

Also, the reason my OpenFile call with OF_EXIST didn't work is that the file I was checking turned out to have a pathname longer than 128 characters (that's the MAX). I put a check elsewhere in my program to make sure that this doesn't happen.  Anyway, here's the routine I'm now using to check existance.

FUNCTION MyEXIST(path$)
  TRY
    IF MID$(path$,LEN(path$) - 3,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
  CATCH
  _EAX = ERR
  ~MessageBox(WIN(WIN()),"GFA BASIC MyEXIST ERROR",STR$(_EAX),MB_OK)
ENDFUNC

This stuff is neat!

James


#: 98176 S12/GFA  (CIS:WINAPC)
    01-May-97  09:25:16
Sb: #98160-WIN32API's
Fm: Sjouke Hamstra 100741,1036
To: John Findlay 100130,1771 (X)
Replies:   0

Hi John,

 >> I'm using the API32 @GetLastError(); see message to James. I have only
just  discovered the information for the return codes though. Hmmm!

Conflict between GFA error codes and API codes could be implemented by say, adding a value to either one.  <<

I won't like to see WIN32 API error trapping within the DLL functions. The DLL functions are _only_ interfaces to the WIN32 function itself. The GetLasterror() should be used within the application, not in the DLL, after the function have returend. The GFA32API.DLL provides access to the 32 bit function nothing more. To prevent tthe DLL procedures from crashing the system when a GFABasic error occurs I implemented the TRY/CATCH. However a GFABAsic error can only ocuur in either of two cases: 1. When lpf32% doesn't contain the correct address 2. The GetProcAddressW isn't declared properly.

Actually both errors won't show up once the DLL is compiled and TRY/CATCH may be left out. The first error will show up only once when the GFA32API is originally created. Now it has proved to contain the correct value, it will never result in an error. When GetProcAddress32W is incorrectly spelled it will be trapped during compiling. So, in the next version you can get rid of the TRY/CATCH.

Greetings, SH


#: 98187 S12/GFA  (CIS:WINAPC)
    01-May-97  20:28:17
Sb: Calling 32 APIs
Fm: James V. Schumacher 104166,2104
To: All
Replies:   0

All,

Here are the routines I'm using to replace the GetPrivateProfileString and WritePrivateProfileString Function calls:

PROCEDURE MyGetPrivateProfileString(sectionName,entry,defltString,tmp,tmpLen&,PathOfProfile)
  TRY
    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)
      IF _EAX = FALSE
        LOCAL ret% = FN GetLastError()
        ~MessageBox(WIN(WIN()),"ret%",STR$(ret%),MB_OK)
        RETVAL _EAX
      ELSE
        RETVAL _EAX
      ENDIF
    ELSE //Windows3.1
      RETVAL GetPrivateProfileString(sectionName,entry,defltString,tmp,tmpLen&,PathOfProfile)
    ENDIF
  CATCH
  _EAX = ERR
  ~MessageBox(WIN(WIN()),"GFA BASIC MyGetPrivateProfileString ERROR",STR$(_EAX),MB_OK)
RETURN

PROCEDURE MyWritePrivateProfileString(sectionName,entryName,tmp,PathOfProfile)
  TRY
    IF gSysVers > 3.1 //Windows 95
      //sectionName = lpAppName
      //entryName = lpKeyName
      //tmp = lpString
      //PathOfProfile = lpFileName
      RETVAL P:(lpf32)(L:sectionName,L:entryName,L:tmp,L:PathOfProfile,L:^GetProcAddress32W(hkernel32,"WritePrivateProfileStringA"),L:%1111,L:4)
      IF _EAX = FALSE
        LOCAL ret% = FN GetLastError()
        ~MessageBox(WIN(WIN()),"ret%",STR$(ret%),MB_OK)
        RETVAL _EAX
      ELSE
        RETVAL _EAX
      ENDIF
    ELSE //Windows3.1
      RETVAL WritePrivateProfileString(sectionName,entryName,tmp,PathOfProfile)
    ENDIF
  CATCH
  _EAX = ERR
  ~MessageBox(WIN(WIN()),"GFA BASIC MyWritePrivateProfileString ERROR",STR$(_EAX),MB_OK)
RETURN

FUNCTION GetLastError()
  TRY
    RETURN P:(lpf32)(L:^GetProcAddress32W(hkernel32,"GetLastError"),L:%0,L:0)
  CATCH
  _EAX = ERR
  ~MessageBox(WIN(WIN()),"GFA GetLastError ERROR",STR$(_EAX),MB_OK)
ENDFUNC

James


#: 98201 S12/GFA  (CIS:WINAPC)
    02-May-97  20:24:19
Sb: #98180-#Copying Files
Fm: John Findlay 100130,1771
To: Bob Springett 100776,3023 (X)
Replies:   1

>> I need to copy say up to 50 files from time to time, from a Windows program.  I have used SHELL and it seems to work with small numbers of files but as the number grows it fails. Is there an alternative to SHELL. <<

Bob,

As Sjouke is on holiday for a while I'll try to help out.

I've run this a number of times and it hasn't failed yet!

Regards,

John

// =======================================================
// To copy multiple files using WIN32API CopyFile().
//
// Make sure the paths are correct!
// =======================================================

DIR "e:\gfawin\demo\" TO "e:\dir.txt"

OPENW #1,0,0,_X,_Y,~15

@Init()

OPEN "I",#1,"e:\dir.txt"

WHILE !EOF( #1)

  LINE INPUT #1, ExistingFile$

  NewFile$      = "e:\upload\"      + ExistingFile$ + CHR$(0)
  ExistingFile$ = "e:\gfawin\demo\" + ExistingFile$ + CHR$(0)

  IF !@CopyFile(V:ExistingFile$, V:NewFile$, FALSE) // FALSE = Always
    PRINT @GetLastError()
  ELSE
    PRINT CHAR{V:ExistingFile$},CHAR{V:NewFile$}
  ENDIF
WEND
CLOSE #1
PRINT "END"

ON MENU MESSAGE GOSUB HandleMessage

IF hkernel32% > 32 THEN ~^FreeLibrary32W(hkernel32%)
FREEDLL 10

DO
  SLEEP
UNTIL MENU(1) = 4

CLOSEW #1
END
PROCEDURE HandleMessage
  SELECT _Mess
  CASE WM_PAINT

  ENDSELECT
RETURN
PROCEDURE Init()

  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)

RETURN
FUNCTION GetLastError()
  RETURN P:(lpf32%)(L:^GetProcAddress32W(hkernel32%,"GetLastError"),L:%0,L:0)
ENDFUNC
FUNCTION CopyFile(lpszExistingFile%, lpszNewFile%, fFailIfExists%)
  RETURN P:(lpf32%)(L:lpszExistingFile%, L:lpszNewFile%, L:fFailIfExists%, L:^GetProcAddress32W(hkernel32%,"CopyFileA"),L:%110,L:3)
ENDFUNC


#: 98200 S12/GFA  (CIS:WINAPC)
    02-May-97  19:47:25
Sb: #98187-Calling 32 APIs
Fm: John Findlay 100130,1771
To: James V. Schumacher 104166,2104
Replies:   0

Hello James,

I'll add those routines to the gfa32api.dll. Thanks!

I noticed that you are using 3.1 and win32 api's; I think you'll find it's not necessary!

Documented in 32API Reference;

## The GetPrivateProfileString function retrieves a string from the specified section in the given initialization file. This function is provided for compatibility with 16-bit Windows-based applications. New applications should store initiation information in the registry. ##

A couple points; if you are using a GFA FUNCTION you will need a RETURN just before the ENDFUNC. Introduce a GFA error in FUNCTION GetLastError() and see what happens after the call to ~MessageBox()!

FUNCTION GetLastError()
  TRY  // should be lpf32
    RETURN P:(lp32)(L:^GetProcAddress32W(hkernel32,"GetLastError"),L:%0,L:0)
  CATCH
   ~MessageBox(WIN(WIN()),"GFA GetLastError ERROR",STR$(ERR),MB_OK)
 // RETURN ERR
ENDFUNC

The other point is that, as Sjouke said, after you've ironed out problems in the development stage you shouldn't get a GFA error at run time with these 32bit calls.


Regards,


John


#: 98221 S12/GFA  (CIS:WINAPC)
    05-May-97  00:16:06
Sb: XL7 and GFA DLLs
Fm: Peter Heffernan 100327,1173
To: ALL
Replies:   0

I wrote and compiled a GFA programme to a DLL which is called from within Excel. This works fine with the 16 bit versions of Excel but my problem is; now I have several people upgrading to Excel 7 who now can't access my DLL functions.

Can anyone offer any advice?

Ta,
PeteHeff


#: 98257 S12/GFA  (CIS:WINAPC)
    06-May-97  15:00:22
Sb: #98222-#Number formatting
Fm: John Findlay 100130,1771
To: Bob Springett 100776,3023 (X)
Replies:   1

Bob,

>> Is there a way to right justify in these so that I can get something approaching the PRINT USING function. I have tried padding on the left using RSET with not much luck. <<

The code below is a bit messy but it's the only way I can think of. When using proportional fonts it gets tricky because GetTextExtent() is not perfectly accurate for all fonts.

// =============================================================
//
// =============================================================
OPENW #1,0,0,600,400,-1

FONT QUALITY PROOF_QUALITY
FONT PITCH DEFAULT_PITCH
FONT FAMILY FF_SWISS
FONT CHARSET ANSI_CHARSET
FONT WEIGHT FW_MEDIUM
FONT HEIGHT 16

FONT "courier"
FONT TO userfont&
SETFONT userfont&

@DemoDialog()

DO
  SLEEP
UNTIL MENU(1) = 4

CLOSEDIALOG #1
SETFONT SYSTEM_FONT
IF userfont& THEN FREEFONT userfont&
CLOSEW #1
EDIT

PROCEDURE DemoDialog()

  DLGBASE PIXEL

  DIALOG #1,10,30,380,200,"Test...", WS_SYSMENU | WS_CAPTION

    '------------------------------------------------
    '       text  ID    X   Y   W   H
    '------------------------------------------------

    EDITTEXT "", 100 , 10, 10, 356, 22, WS_BORDER
    EDITTEXT "", 101 , 10, 31, 356, 22, WS_BORDER
    EDITTEXT "", 102 , 10, 52, 356, 22, WS_BORDER
    EDITTEXT "", 103 , 10, 73, 356, 22, WS_BORDER
    EDITTEXT "", 104 , 10, 94, 356, 22, WS_BORDER
    EDITTEXT "", 105 , 10, 115, 356, 22, WS_BORDER
    EDITTEXT "", 106 , 10, 136, 356, 22, WS_BORDER

  ENDDIALOG

  SHOWDIALOG #1
  FOR t&=100 TO 106
    SENDMESSAGE DLG(1,t&),WM_SETFONT,userfont&,0
  NEXT t&

  @SetEditStringRight(DLG(1,100),"The first field", 356)
  @SetEditStringRight(DLG(1,101),"The second field", 356)
  @SetEditStringRight(DLG(1,102),"112", 356)
  @SetEditStringRight(DLG(1,103),"The fourth field", 356)
  @SetEditStringRight(DLG(1,104),"Another field", 356)
  @SetEditStringRight(DLG(1,105),"1234567890", 356)
  @SetEditStringRight(DLG(1,106),"WWWWWWwwwwwww", 356)

RETURN
PROCEDURE SetEditStringRight(item&, text$, fieldwidth&)
  LOCAL spwidth&, textwidth&

  spwidth& = LOWORD(GetTextExtent(_DC(1)," ",1))

  textwidth& = LOWORD(GetTextExtent(_DC(1),V:text$,LEN(text$)))

  _WIN$(item&) = SPACE$((fieldwidth& - textwidth&) / spwidth&) + text$
RETURN


Regards,


John


#: 98258 S12/GFA  (CIS:WINAPC)
    06-May-97  15:00:26
Sb: #98248-Calling 32 APIs
Fm: John Findlay 100130,1771
To: James V. Schumacher 104166,2104
Replies:   0

>> Needless to say, I'm puzzled. << So am I.

James, you must be doing something wrong. Make sure you've closed the file every time otherwise you could get funny results.

Also you could try CreateFile() instead of OpenFile().

Regards,


John


#: 98287 S12/GFA  (CIS:WINAPC)
    08-May-97  02:25:14
Sb: #98258-Calling 32 APIs
Fm: James V. Schumacher 104166,2104
To: John Findlay 100130,1771 (X)
Replies:   0

>> James, you must be doing something wrong. <<

John,

I was.   Turns out that I wasn't null terminating the pathname$ string.  Curiously, my test program worked without the null terminator but the lack of it resulted in bizarre behavior in my larger application.  This is the second (or is it third) time I've been burned by the absence of a null string.  I'm going to put it at the top of my list of things to check when things aren't working write.

James


#: 98295 S12/GFA  (CIS:WINAPC)
    08-May-97  15:31:17
Sb: 32bit Funktion
Fm: Friedrich Rode 100602,702
To: all 100602,702
Replies:   0

Message part 1
---------------------

To all GFA Basic programmers in Compuserver ;-)
from Roland Walter, E-Mail: R.WALTER@VLBERLIN.COMLINK.DE

I don't have Compuserve and had to ask Fritz
(real name Friedrich Rode, hi hi) to send this message
into the GFA Compuserve forum. Fritz also posted some of
my listings.
It is a problem... Sometimes I got a first idea how to
handle a problem (for example GFA Basic and Win32), the listing
seems to work at first time and lots of people get it.
2 days later I find out a problen and correct it -
but the old listings live and live and live and are not to kill.

James V. Schumacher (CIS:104166,2104) wrote about such a
problem I corrected some days later:

> Also, just as a warning to others, I've again encountered
> problems because I incorrectly declared some 32 bit routine
> parameter handles as WORD rather than LONG.
> Specifically, I found examples of FindFirstFile,
> FindNextFile and CloseFile being used in Roland Walters
> programs and implemented as he did in mine.  He declared the
> handles in those routines as WORD.  They worked as long as
> I was "RUN"ing them.  When compiled, however, they no longer
> worked.  Thanks to John's post in this thread, I realized
> that the reason is that the handle parameters must be
> declared as LONG rather than WORD.

This could be a very very old listing ;-) And the described
correction by James is all right of course!
Sorry for those problems. But momently I cannot
permanently post listings into compuserve. If there would
be an internet news group ... Internet I have.

For consolation I have to small thinks:

At first, a tip:
The function CallProc32W likes to have a bit mask, wich tells
the parameters to convert into 32 bit flat pointers. There is
a very simple way to get this value by the Windows Calculator.
An examle: If You have a 32 bit function with 4 parameters,
and parameter 1 and 3 are to convert, this would result
the binary value 1010. Use the Windows calculator, swich on
the "Bin" Radio Button, type in "1010" and after swich on
the "Hex" Radio Button. In this example You get the Value
"A". The result: Give CallProc32W the value "$A" as converting
parameter. Is there a better way?!

O.K. And now I want to give an example how to work with
long filenames with Interrupts (without 32 bit functions).
This is for fun and works good, but be warned:
Microsoft absolutely don't like Interrupts in Windows programs.
And it is a crasy idea - I know it.
The program will ONLY work under Windows 95 and NOT under
Windows NT because the used Interrupts don't exist under
Windows NT (is this correct?).
But the advantage is, that You don't need initialisations,
declarations and so on. Also there are no global variables
used. In other words: The functions are fully encapsulated.
Take the functions, copy them into Your listing and use them
as they would be built-in GFA Basic commands.
-----------------------------------------------------

' Long filenames in 16 Bit GFA Basic with Interrupts
'  Roland Walter, Schnhauser Allee 64, D-10437 Berlin, Apr. 1997
'
'This listing contains a set of functions around the long filenames.
'All functions ar fully encapsulated and don't need externals.
'So You can "blind" copy them into Your listing and use them as
'they would be internal GFA Basic commands.
'
'WARNING: The used Interrupts don't exist under Windows NT
'
'As example for the work with the functions there is a small code
'with DLG OPEN at the beginning of the list.
'If You want to create a new file (with DLG SAVE) use the following
'steps:
' 1.) The user gives a filename to the program by DLG Save
' 2.) Use CreateFile() to create a Zero-Byte-File with the wished
'     long filename (that's because You cannot get a short filename
'     from a not existing file).
' 3.) Get the short filename with GetShortName$()
' 4.) Use OPEN to open the file by the short filename
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
OFN_LONGNAMES%=$00200000 //New Flag for DLG OPEN/SAVE: get and show long names
'
OPENW #1
DIM Filter$(5)
Filter$(0)="Text files",Filter$(1)="*.txt",Filter$(2)="All files",Filter$(3)="*.*",Filter$(4)="",Dateiname$=""
DLG OPEN DLG(1),OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY|OFN_LONGNAMES% ,"Open...","","*.*",Filter$(),Dateiname$
IF Filename$<>""
  IF @IsWindows95()=TRUE THEN Filename$=@GetShortName$(Filename$)
ENDIF
ERASE Filter$()
'
DO
  GETEVENT
  IF MENU(11)=WM_PAINT
    PRINT AT(0,1) "Short name: "+Filename$+CHR$(13,10)+"Long name: "+@GetLongName$(Filename$)
  ENDIF
UNTIL MENU(1)=4
CLOSEW #1
END
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
> FUNCTION IsWindows95()                         //stellt fest, ob Windows 95 luft
  'Returns TRUE if the program is running under >= Windows 95.
  '(But it would be better to EXACTLY know that WIndows 95 is running...)
  $FUNC1%
  LOCAL Version&=(LOWORD(GetVersion()))
  'Remark: Under Windows 95 You get "3.95" as version info and NOT "4.0"
  //MESSAGE STR$(LOBYTE(Version&))+"."+STR$(HIBYTE(Version&)),"Debug: Windows Version",MB_OK,Dummy&
  IF LOBYTE(Version&)>2 AND HIBYTE(Version&)>94 OR LOBYTE(Version&)>3
    RETURN TRUE
  ELSE
    RETURN FALSE
  ENDIF
ENDFUNC
//
FUNCTION CreateFile(FilePath$)             //Create Zero-Byte-long file wih long or short name
  $FUNC1%
  LOCAL FileHandle&
  FilePath$=FilePath$+CHR$(0)
  ~INTR($21,_AX=$716C,_BX=2,_CX=$0,_DX=$10,_DS=HIWORD(V:FilePath$),_SI=LOWORD(V:FilePath$))
  IF BTST(_FL,0)=FALSE  //Carry-Flag not set
    FileHandle&=_AX
    ~INTR($21,_AH=$3E,_BX=FileHandle&)  //Close file
    RETURN TRUE
  ELSE
    RETURN FALSE
  ENDIF
ENDFUNC
//
FUNCTION GetShortName$(LongName$)  //get short name of a long name
  LOCAL ShortName$=STRING$(260,0)
  LongName$=LongName$+CHR$(0)
  ~INTR($21,_AX=$7160,_CL=1,_CH=0,_DS=HIWORD(V:LongName$),_SI=LOWORD(V:LongName$),_ES=HIWORD(V:ShortName$),_DI=LOWORD(V:ShortName$))
  IF BTST(_FL,0)=FALSE  //Carry-Flag not set
    RETURN CHAR{V:ShortName$}
  ELSE
    RETURN ""
  ENDIF
ENDFUNC
//
FUNCTION GetLongName$(ShortName$)  //get long name of a short name
  ShortName$=ShortName$+CHR$(0)
  LongName$=STRING$(260,0)
  ~INTR($21,_AX=$7160,_CL=2,_CH=0,_DS=HIWORD(V:ShortName$),_SI=LOWORD(V:ShortName$),_ES=HIWORD(V:LongName$),_DI=LOWORD(V:LongName$))
  IF BTST(_FL,0)=FALSE  //Carry-Flag not set
    RETURN CHAR{V:LongName$}
  ELSE
    RETURN ""
  ENDIF
ENDFUNC
//
FUNCTION MakeDirectory(NameDir$)       //create directory with short or long name
  $FUNC1%
  NameDir$=NameDir$+CHR$(0)
  ~INTR($21,_AX=$7139,_DS=HIWORD(V:NameDir$),_DL=LOWORD(V:NameDir$))
  IF BTST(_FL,0)=FALSE  //Carry-Flag not set
    RETURN 0
  ELSE
    RETURN _AX  'Error values see procedure "Info"
  ENDIF
ENDFUNC
//
FUNCTION RemoveDirectory(NameDir$)   //delete (empty) directory with short or long name
  $FUNC1%
  NameDir$=NameDir$+CHR$(0)
  ~INTR($21,_AX=$713A,_DS=HIWORD(V:NameDir$),_DL=LOWORD(V:NameDir$))
  IF BTST(_FL,0)=FALSE  //Carry-Flag not set
    RETURN 0
  ELSE
    RETURN _AX  'Error values see procedure "Info"
  ENDIF
ENDFUNC
//


#: 98296 S12/GFA  (CIS:WINAPC)
    08-May-97  15:33:22
Sb: 32bit Funktion
Fm: Friedrich Rode 100602,702
To: all 100602,702
Replies:   0

Message by Roland Walter
part 2
-----------------------------

PROCEDURE Info
  'Values for DOS interrupt extended error code (RETURN _AX):
  '00h (0)   no error
  '01h (1)   function number invalid
  '02h (2)   file not found
  '03h (3)   path not found
  '04h (4)   too many open files (no handles available)
  '05h (5)   access denied
  '06h (6)   invalid handle
  '07h (7)   memory control block destroyed
  '08h (8)   insufficient memory
  '09h (9)   memory block address invalid
  '0Ah (10)  environment invalid (usually >32K in length)
  '0Bh (11)  format invalid
  '0Ch (12)  access code invalid
  '0Dh (13)  data invalid
  '0Eh (14)  reserved
  '0Fh (15)  invalid drive
  '10h (16)  attempted to remove current directory
  '11h (17)  not same device
  '12h (18)  no more files

  '---DOS 3.0+ ---
  '13h (19)  disk write-protected
  '14h (20)  unknown unit
  '15h (21)  drive not ready
  '16h (22)  unknown command
  '17h (23)  data error (CRC)
  '18h (24)  bad request structure length
  '19h (25)  seek error
  '1Ah (26)  unknown media type (non-DOS disk)
  '1Bh (27)  sector not found
  '1Ch (28)  printer out of paper
  '1Dh (29)  write fault
  '1Eh (30)  read fault
  '1Fh (31)  general failure
  '20h (32)  sharing violation
  '21h (33)  lock violation
  '22h (34)  disk change invalid (ES:DI -> media ID structure)(see #1021)
  '23h (35)  FCB unavailable
  '24h (36)  sharing buffer overflow
  '25h (37)  (DOS 4.0+) code page mismatch

  '26h (38)  (DOS 4.0+) cannot complete file operation (out of input)
  '27h (39)  (DOS 4.0+) insufficient disk space
  '28h-31h   reserved
  '32h (50)  network request not supported
  '33h (51)  remote computer not listening
  '34h (52)  duplicate name on network
  '35h (53)  network name not found
  '36h (54)  network busy
  '37h (55)  network device no longer exists
  '38h (56)  network BIOS command limit exceeded
  '39h (57)  network adapter hardware error
  '3Ah (58)  incorrect response from network
  '3Bh (59)  unexpected network error
  '3Ch (60)  incompatible remote adapter
  '3Dh (61)  print queue full
  '3Eh (62)  queue not full
  '3Fh (63)  not enough space to print file
  '40h (64)  network name was deleted

  '41h (65)  network: Access denied
  '42h (66)  network device type incorrect
  '43h (67)  network name not found
  '44h (68)  network name limit exceeded
  '45h (69)  network BIOS session limit exceeded
  '46h (70)  temporarily paused
  '47h (71)  network request not accepted
  '48h (72)  network print/disk redirection paused
  '49h (73)  network software not installed
  '(LANtastic) invalid network version
  '4Ah (74)  unexpected adapter close
  '(LANtastic) account expired
  '4Bh (75)  (LANtastic) password expired
  '4Ch (76)  (LANtastic) login attempt invalid at this time
  '4Dh (77)  (LANtastic v3+) disk limit exceeded on network node
  '4Eh (78)  (LANtastic v3+) not logged in to network node

  '4Fh (79)  reserved
  '50h (80)  file exists
  '51h (81)  reserved
  '52h (82)  cannot make directory
  '53h (83)  fail on INT 24h
  '54h (84)  (DOS 3.3+) too many redirections
  '55h (85)  (DOS 3.3+) duplicate redirection
  '56h (86)  (DOS 3.3+) invalid password
  '57h (87)  (DOS 3.3+) invalid parameter
  '58h (88)  (DOS 3.3+) network write fault
  '59h (89)  (DOS 4.0+) function not supported on network
  '5Ah (90)  (DOS 4.0+) required system component not installed
  '64h (100) (MSCDEX) unknown error
  '65h (101) (MSCDEX) not ready
  '66h (102) (MSCDEX) EMS memory no longer valid
  '67h (103) (MSCDEX) not High Sierra or ISO-9660 format

  '68h (104) (MSCDEX) door open
  'B0h (176) (MS-DOS 7.0) volume is not locked
  'B1h (177) (MS-DOS 7.0) volume is locked in drive
  'B2h (178) (MS-DOS 7.0) volume is not removable
  'B4h (180) (MS-DOS 7.0) lock count has been exceeded
  'B5h (181) (MS-DOS 7.0) a valid eject request failed
RETURN


#: 98307 S12/GFA  (CIS:WINAPC)
    09-May-97  13:40:07
Sb: #98200-Calling 32 APIs
Fm: Sjouke Hamstra 100741,1036
To: John Findlay 100130,1771
Replies:   0

 >> The other point is that, as Sjouke said, after you've ironed out problems
in  the development stage you shouldn't get a GFA error at run time with these  32bit calls.  <<

That's correct. I have teherfor used DEFFN declarations for the 32-bit functions like this:

DEFFN GetLastError() = P:(lp32)(L:^GetProcAddress32W(hkernel32,"GetLastError"),L:%0,L:0)

Greetings, SH


#: 98305 S12/GFA  (CIS:WINAPC)
    09-May-97  13:40:04
Sb: #98257-Number formatting
Fm: Sjouke Hamstra 100741,1036
To: John Findlay 100130,1771
Replies:   0

Hi Bob,

I'm sorry but only multiline edit controls can be right-aligned or centered. Single-line edit controls are always left-aligned, regardless of the control style given. This is a Windows limitation.

It would be interesting why only half of the 180 multiline edit controls are actually created, but this would require extensive debugging.

You might consider a different approach. Globally: 1. create 180 static Rtext controls to display your info 2. create (initially invisible) one multiline control with the same dimensions 3. do your own tabbing by using GetNextDlgTabItem and mouse handling (Childwindowfrompoint) 4. when a RTEXT control is 'activated' hide it and show the edit control to allow for input 5. when info is input hide the edit control and copy the text to the static control.

I've done something similar, although in a quite different kind of application and it should work.

Greetings, SH


#: 98320 S12/GFA  (CIS:WINAPC)
    10-May-97  08:53:15
Sb: #98287-Calling 32 APIs
Fm: John Findlay 100130,1771
To: James V. Schumacher 104166,2104
Replies:   0

James,

>> Curiously, my test program worked without the null terminator but the lack of it resulted in bizarre behavior in my larger application. <<

Yes, I've done the same. When a string is created it will sometimes have a zero byte termination but it may not. Depends where in the programs memory it's allocated.

Regards,

John


#: 98366 S12/GFA  (CIS:WINAPC)
    12-May-97  10:38:13
Sb: #98320-Calling 32 APIs
Fm: Sjouke Hamstra 100741,1036
To: John Findlay 100130,1771
Replies:   0

>> Yes, I've done the same. When a string is created it will sometimes have a zero byte termination but it may not. Depends where in the programs memory it's allocated. <<

The GFABASIC interpreter pads the strings with zero bytes when they have an odd number of characters. So sometimes your string is zero terminated and sometimes not. When you pass the address of a string with an odd number of characters API calls don't fail. In compiled versions this is handled otherwise (I assume).



Greetings,
Sjouke Hamstra, GFABASIC Intermediary
(10:30 12-May-97 using OzWinII)


#: 98365 S12/GFA  (CIS:WINAPC)
    12-May-97  10:38:11
Sb: #98318-modal dialogbox
Fm: Sjouke Hamstra 100741,1036
To: thomas engel 70602,2575
Replies:   0

>> I guess I don't understand.  Isn't the File Open (common) dialog a modal dialog?  It behaves the way I describe. <<

Try the next small program:

OPENW #1
DO
  GETEVENT
  SWITCH MENU(1)
  CASE 1
    FILESELECT "","",f$
  ENDSWITCH
UNTIL MENU(1)=4
CLOSEW #1
END

Hit a key and the modal file selector dialog box is shown. Now activate another application and try to make the dialog box active by clicking in the client area of OPENW 1. the application isn't activated.

Greetings,
Sjouke Hamstra, GFABASIC Intermediary
(10:26 12-May-97 using OzWinII)


#: 98383 S12/GFA  (CIS:WINAPC)
    12-May-97  23:12:25
Sb: 32bit Funktion
Fm: James V. Schumacher 104166,2104
To: Friedrich Rode 100602,702
Replies:   0

Friedrich,

I tried posting to Roland Walter directly but for some reason Compuserve doesn't like the address I used.  Perhaps you can pass on my thanks to him (and you!) for posting the set of functions for long filenames.  I've already used the GetLongName$() function to insure that the path$ statement in the OpenFile() call doesn't exceed 127 characters!  I'm sure the other functions will be equally useful.

Also, I want Roland to know that I meant no criticism when I posted my observation regarding the parameter declarations in his FindFirstFile, FindNextFile and CloseFile examples.  His examples, despite the small problem, were *extremely* helpful.  I appreciate his generosity in making them available to people like me.

James Schumacher
CIS:104166,2104 or peuapeu@aol.com


#: 98447 S12/GFA  (CIS:WINAPC)
    15-May-97  09:49:05
Sb: #98367-#Assembler incorporation
Fm: Bob Springett 100776,3023
To: Sjouke Hamstra 100741,1036 (X)
Replies:   1

Sjouke,
I am trying to read pixel colour with POINT or RGBPOINT but I am not getting the results I think I ought to get. Below is the type of code I'm using. What am I doing wrong.
Regards 
Bob


FULLW #1
//************************** Make a blue rectangle ********************
DIM x&(4),y&(4)
DATA 0,0,200,0,200,200,0,200
FOR i& = 0 TO 3
  READ x&(i&),y&(i&)
NEXT i&
RGBCOLOR RGB(0,0,255)
FILLMODE ALTERNATE
POLYFILL 4,x&(),y&() OFFSET OFFX&,OFFY&
RESTORE
KEYGET a%
//************************** Make window for RGBPOINT results ***********
OPENW #2,400,0,400,100,0
FOR y& = 0 TO 10
  FOR x& = 0 TO 9
    c% = RGBPOINT(x&,y&)
    //************************** Print c% and  HEX representation of c% *************
    PRINT c%,HEX$(c%)//   LPRINT c%,HEX$(c%)
  NEXT x&
NEXT y&
'LPRINT CHR$(12)
KEYGET a%
CLOSE #2

Have tried also with a red square and with POINT and get 255 all the time.


#: 98457 S12/GFA  (CIS:WINAPC)
    15-May-97  17:07:04
Sb: #98447-#Assembler incorporation
Fm: Sjouke Hamstra 100741,1036
To: Bob Springett 100776,3023 (X)
Replies:   1

Hi Bob,

>> I am trying to read pixel colour with POINT or RGBPOINT but I am not getting the results I think I ought to get. Below is the type of code I'm using. What am I doing wrong. <<

RGBPOINT should return $FF0000. Remember GFABasic graphic commands use the actual GFA device context (you can read all about it on page 108 in my book). After window #2 is opened the actual DC is _DC(2). I suppose you want to read out the pixels from window #1. 

SETDC _DC(1)      // or WIN #1, read my book!
rgb%=RGBPOINT(x,y)
SETDC _DC(2)
PRINT HEX$(rgb%)

Greetings,
Sjouke Hamstra, GFABASIC Intermediary
(16:59 15-May-97 using OzWinII)


#: 98458 S12/GFA  (CIS:WINAPC)
    15-May-97  17:07:05
Sb: #98431-Colors
Fm: Sjouke Hamstra 100741,1036
To: Andrew Risely 100667,1620
Replies:   0

Hi Andrew,

>> What is happening.  The result is the same for 256 color settings.  My application is uses OPENW <<

I really don't know, it works fine with me. On my system the size of the palette is 256, and GETNEAREST returns index 155 (different on each system) and selects yellow as required. (Both compiled and interpreted.)

  CASE 21
    ~GetObject(_PAL(1),2,*n)
    ? n
    Idx = GETNEAREST(255,255,128)
    COLOR Idx
    ? Idx

Greetings,
Sjouke Hamstra, GFABASIC Intermediary
(17:04 15-May-97 using OzWinII)


#: 98503 S12/GFA  (CIS:WINAPC)
    19-May-97  12:21:28
Sb: #98501-Colors
Fm: Sjouke Hamstra 100741,1036
To: Andrew Risely 100667,1620
Replies:   0

Hi Andrew,

>>
  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 <<

I use this to synchronise files between hard disks. However, these are these functions are from the 32 bit kernel.  Are there equivalent 16bit functions, if so what are they. <<

These ARE 16-bit functions, located in the 16-bit kernel of Windows 95! Please try to figure out the things you don't understand and I'll explain them to you.

Greetings,
Sjouke Hamstra, GFABASIC Intermediary
(12:15 19-May-97 using OzWinII)


#: 98507 S12/GFA  (CIS:WINAPC)
    19-May-97  14:49:00
Sb: #Peek/Poke/Call/
Fm: Bob Springett 100776,3023
To: Sjouke Hamstra 100741,1036 (X)
Replies:   1

Sjouke,
What is the significance of the above error. Included is a small piece of code in which it appears at the pointer? to the data structure ORIENT which appears later. The code subsequently leads on to your printbmp routine on the disk with your book.
I am trying to change the orientation of the printer.
Regards
Bob
PS I can't seem to find anywhere any info which ties up exactly to this error.( I have seen it
once in your book somewhere)


GET 0,0,640,480,bmp&
prdc& = PrinterDC()              // get printer dc
IF prdc&                         // no error
  SETDC prdc&                    // change GFA DC
  {lppr%}.prorientation = 1//*** peek/poke/call address error here
  ret& = Escape(prdc&,GETSETPAPERORIENT,20,{lppr%}.prorientation,NULL)
  DEBUG ON
  xx& = GETDEVCAPS(HORZRES)


#: 98517 S12/GFA  (CIS:WINAPC)
    20-May-97  11:21:09
Sb: #98507-Peek/Poke/Call/
Fm: Sjouke Hamstra 100741,1036
To: Bob Springett 100776,3023 (X)
Replies:   0

Hi Bob,

It's more likely the error occurs in the following line:

>>   ret& = Escape(prdc&,GETSETPAPERORIENT,20,{lppr%}.prorientation,NULL) <<

The fourth parameter requires a pointer, where you pass it a value. Try passing it lppr%, which is the address of the TYPE var.

Greetings,
Sjouke Hamstra, GFABASIC Intermediary
(11:08 20-May-97 using OzWinII)


#: 98546 S12/GFA  (CIS:WINAPC)
    22-May-97  04:31:13
Sb: GetPrivateProfileString
Fm: James V. Schumacher 104166,2104
To: All
Replies:   0

Hi,

For those who might be planning to use the Win32 GetPrivateProfileString routine that I posted a while back, I would recommend the following.  Before you call the routine, you should define the variable I called tmplen& as the length in characters of the destination string plus one and set  tmp$ = SPACE$(tmpLen& - 1) + CHR$(0).  I found that if you define tmplen& as the destination string length and set tmp$ = SPACE(tmpLen&), you get bizarre results where the routine will sometimes work and sometimes not.   That's the same behaviour I was getting when I forgot the NULL character in those API parameters that explicitely call for it.

Microsoft.com documention says that if the supplied destination buffer is too small to hold the requested string, the string is truncated and followed by a null character, and the return value is equal to tmpLen& minus one.  That is why I defined tmplen& and tmp$ the way I did.

Now the routine appears to work properly ... every time.

So ... null characters bite me again!

:)

James


#: 98572 S12/GFA  (CIS:WINAPC)
    25-May-97  02:31:22
Sb: GFA Mailing List
Fm: GFA Germany 75300,3224
To: ALL
Replies:   0

Dear Forum Member,

we are proud to pronounce the first step of our upcoming Internet activities:

New! The GFA Mailing List, 
open to every GFA-User, and everyone who wants to get in touch with our Basic-World!

What are the discussion topics?
Everything around GFA products. We would especially like to discuss about:
 - Have you written a helpful listing? Tell it other programmers!
 - Problems with GFA products? We will help us together!
 - Support questions for GFA-BASIC

We will send GFA news flash as well to keep you informed (we do not start sending large advertising mails, but short information what is new and where you can read more. We want to invite, not to frighten you!). We will join the Mailing List, too, thus you'll not only have User-to-User communication, but GFA support as well.

To subscribe, go to http://ourworld.compuserve.com/homepages/gfasoft/subscrie.htm.
Otherwise send E-Mail to gfabasic@bero-online.ml.org directly and choose the subject "subscribe". You will then automatically be added to the mailing list with your Replying-E-Mail address.

You don't understand what we are offering here? Then read more about Mailing Lists at
http://ourworld.compuserve.com/homepages/gfasoft/mailinfe.htm

Attention! Subscribe only if you agree to our Rules for the GFA Mailing List!
You can find the rules online at 
http://ourworld.compuserve.com/homepages/gfasoft/mrules_e.htm

Why do we offer this list?
Our CIS forum discussions are great, but only CIS member have access to the forum and there are many GFA user that only have an Internet account. Thus we won't close the CIS forum or replace it with the list, but enhance the possibilities for getting User-to-User discussions.
The list can be joined by *every* person that has an E-Mail account. They don't have to have a CIS account to join the discussion they would otherwise found in our CIS forum only.
We will give the list a try and see how many GFA User will join. It takes some time, of course, because the people must first learn about the existance of the Mailing List.

To send messages to the list, send E-Mail to gfabasic@bero-online.ml.org. The E-Mail will automatically be forwarded to all members of the list.

If you have questions about the GFA Mailing List or problems with subscribing, drop us an E-Mail to gfa@bero-online.ml.org.

Yours truly

GFA Software
Administrator Online Resources


#: 98596 S12/GFA  (CIS:WINAPC)
    29-May-97  03:26:01
Sb: #CreatePolygonRgn()
Fm: James V. Schumacher 104166,2104
To: ALL
Replies:   1

Hi,

I want to paint a odd shaped polygon region to the screen. My code isn't working and the problem appears to be in the way that I'm passing the array of points to the API CreatePolygonRgn().  My test code follows:

OPENW #1
brushHandle& = GetStockObject(BLACK_BRUSH)
oldbrushHandle& = SelectObject(_DC(),brushHandle&)
//create a TYPE array with 4 points in it per Sjouke
TYPE POINT:
- WORD h
- WORD v
ENDTYPE
DIM shape$(4)
FOR i& = 0 TO 3
  shape$(i&) = STRING$(LEN(POINT:),0)
NEXT i&
{V:shape$(0)}.h = 30
{V:shape$(0)}.v = 30
{V:shape$(1)}.h = 60
{V:shape$(1)}.v = 30
{V:shape$(2)}.h = 30
{V:shape$(2)}.v = 60
{V:shape$(3)}.h = 60
{V:shape$(3)}.v = 60
//create regions
rgnHndl2& = CreatePolygonRgn(V:shape$(0),4,ALTERNATE)
rgnHndl& = CreateRectRgn(70,70,100,100) //to test the rest of the code
'
DO
  GETEVENT
  ~PaintRgn(_DC(),rgnHndl&)
  ~PaintRgn(_DC(),rgnHndl2&)
UNTIL MENU(1) = 4
'
~DeleteObject(oldbrushHandle&)
~DeleteObject(rgnHndl&)
~DeleteObject(rgnHndl2&)
CLOSEW #1

 Any suggestions on how I should pass the points to CreatePolygonRgn()?

James


#: 98597 S12/GFA  (CIS:WINAPC)
    29-May-97  08:58:01
Sb: #98596-CreatePolygonRgn()
Fm: Sjouke Hamstra 100741,1036
To: James V. Schumacher 104166,2104
Replies:   0

>>  Any suggestions on how I should pass the points to CreatePolygonRgn()? <<

The elements of a string array are not contiguous stored in memory. You should use a data type that is; for instance a long-integer array:

DIM shape%(4)
{V:shape%(0)}.h = 30
{V:shape%(0)}.v = 30
{V:shape%(1)}.h = 60
{V:shape%(1)}.v = 30
{V:shape%(2)}.h = 30
{V:shape%(2)}.v = 60
{V:shape%(3)}.h = 60
{V:shape%(3)}.v = 60
//create regions
rgnHndl2& = CreatePolygonRgn(V:shape%(0),4,ALTERNATE)

Greetings,
Sjouke Hamstra, GFABASIC Intermediary
(08:53 29-May-97 using OzWinII)


#: 98636 S12/GFA  (CIS:WINAPC)
    02-Jun-97  14:12:23
Sb: #98476-GRIDDY.DLL
Fm: Dave Barton 100355,1331
To: Sjouke Hamstra 100741,1036
Replies:   0

Message text written by Sjouke Hamstra
>For what I know it is a commercial product. Despite this I have some copies lying about on my HD. Please ask GFA directly.<

Hi Sjouke,

Thanks for your response. Sorry for the delayed reply, I have been interstate on business.
You may be right, but I know GFA included the GRIDDY.DLL on a previous GFW upgrade disk.

I only wanted it to take a look at Ingmar Brunken's ODBC library file. I will ask GFA directly.

In recent times there has been some interest expressed in the forum about using GFA with MS Access. We recently developed a nice simple little routine for directly adding records to an Access table from GFA using the DDEML.DLL. If anyone is interested, I would be happy to prepare and upload an example to the library and /or Dale might like to include it in the GFAHELP file (If he thinks it's good enough).

Kindest Regards,
Dave


#: 98637 S12/GFA  (CIS:WINAPC)
    02-Jun-97  14:12:27
Sb: #98502-GRIDDY.DLL
Fm: Dave Barton 100355,1331
To: Andrew Risely 100667,1620
Replies:   0

Message text written by Andrew Risely
>I obtained Griddy.dll, shipped directly from GFA on an upgrade disk.  I beleive it is listed as a commercial product, but the upgrade I got also listed the source code. <

Hi Andrew,

Thanks for your reply. Sorry for the delayed response, but I have been interstate on business.

You are right, GFA did include GRIDDY.DLL and source code on a previous upgrade disk. They also included a fairly detailed WRI file, which unfortunately is all I have left of the original upgrade.

I will ask GFA if they can supply a copy of the dll. Alternatively, if GFA can't help,  (Assuming there are no copyright restrictions) would you be willing to send me a copy of the dll you have? I only want this dll to try out a library example of ODBC from Ingmar Brunken.

Thanks & Regards,
Dave


#: 98664 S12/GFA  (CIS:WINAPC)
    04-Jun-97  10:59:23
Sb: Win95 PROGMAN?
Fm: Ingmar Brunken 100573,3013
To: ALL
Replies:   0

I'm trying to write a Win95 setup routine that installs the program icons in a window like PROGMAN.EXE does in Windows 3.11.

Only in Win95 the code doesn't work like it does in Windows 3.11 (no installation).

The example code is:

a$="[CreateGroup("Test",TEST.GRP)]
[ShowGroup("Test",1)]
[AddItem(test.exe,Test)]
[AddItem(notepad.exe info.txt,Info)]"
//
OPENW #14,0,0,_X/2,_Y/4,0
~SetWindowPos(WIN(14),-1,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE)
CB WIN(14),WM_DDE_FIRST  TO WM_DDE_LAST,ddecb
atom&=GlobalAddAtom("PROGMAN")
SENDMESSAGE -1,WM_DDE_INITIATE,WIN(14),MAKELONG(atom&,atom&)
 xeq(a$)   // La Programmmanager dies ausfhren!
 POSTMESSAGE pw&,WM_DDE_TERMINATE,WIN(14),0
~GlobalDeleteAtom(atom&)
CLOSEW #14
//...
PROCEDURE xeq(a$)
  'Copy command-string into shared memory:
  cmdmem&=GlobalAlloc(GMEM_DDESHARE,LEN(a$)+1)
  CHAR{GlobalLock(cmdmem&)} = a$
  ~GlobalUnlock(cmdmem&)
  POSTMESSAGE pw&,WM_DDE_EXECUTE,WIN(14),MAKELONG(cmdmem&,0)
  DO                      // wait for DDE to terminate
    PEEKEVENT
  UNTIL MENU(11)=0
  ~GlobalFree(cmdmem&)
RETURN

I'd appreciate any ideas.

Ingmar.


#: 98695 S12/GFA  (CIS:WINAPC)
    05-Jun-97  17:29:29
Sb: #98688-LOCK PIXELS?
Fm: Ingmar Brunken 100573,3013
To: Sjouke Hamstra 100741,1036
Replies:   0

Sjouke,

<<can you provide me with a small example?>>

Well, yes. Please find it below. I don't know if you'd still call it "small" but it is the shortest I've got. It shows a 3D-object animated by the mouse moves, and you can zoom it by pressing the left mouse button.

There is one line which I  especially highlighted. If you let it like it is, no error occurs when zooming to the object, even in spite the fact the lines are already outside the screen.  If you replace the line by MAX(..,7), you can zoom more close...and if you do so and move the mouse, an error will occur soon. This proofs that it depends on how far the lines are outside the screen. The exact measure of -_X...+2*_X if found out testing that behaviour and trying to fix the range. That's what I've got.


//3D-Animation by Ingmar P. Brunken, 1996
DEFLINE PS_SOLID,0
scrx&=_X
scry&=_Y
eingaben
'
OPENW #1,0,0,SYSMETRIC(0),SYSMETRIC(1),%1111110000
hm&=MEMDC(_DC(1))    // MemoryDeviceContext erzeugen
hb&=CREATEBMP(scrx&,scry&)   // Bitmap erzeugen
SETBMP hm&,hb&
'
flag2!=FALSE
flag3!=FALSE
IF flaginvers!=TRUE
  rl|=128
  gl|=128
  bl|=0
ELSE
  rl|=0
  gl|=0
  bl|=0
ENDIF
DO
  PEEKEVENT
  IF MOUSEK=1
    flag3!=TRUE
    IF flag2!=FALSE
      vy=MIN(vy*1.1,25000)
    ELSE
     //******************************************************************************************
      vy=MAX(vy*0.9,70)   //NO PROBLEM ****************************************************
      //vy=MAX(vy*0.9,7)  //try it and replace the line above and you'll soon get an ugly error!
     //******************************************************************************************
    ENDIF
  ELSE IF flag3!=TRUE
    flag2!=NOT flag2!
    flag3!=FALSE
  ENDIF
  IF MOUSEK=2 THEN beta=beta+2
  IF beta>360 THEN beta=0
  gamma=(MOUSEX/SYSMETRIC(0))*360
  alpha=(MOUSEY/SYSMETRIC(1)*360 )
  SETDC hm&
  darstellung
  BITBLT hm&,0,0,scrx&,scry&,_DC(1),0,0,SRCCOPY
  SETDC _DC(1)
LOOP UNTIL MENU(1)=4
FREEDC hm&
FREEBMP hb&
CLOSEW #1
END
'
PROCEDURE inits
  DIM x&(ep&),y&(ep&),z&(ep&)
  DIM bx&(ep&),by&(ep&)
  DIM k&(ad&,5)
  DIM l&(ad&)
RETURN
PROCEDURE lesen
  LOCAL i&,j&
  RESTORE eckpunktdaten
  FOR i&=1 TO ep&
    READ x&(i&),y&(i&),z&(i&)
    p1&=MIN(p1&,x&(i&))
    p2&=MAX(p2&,x&(i&))
    p3&=MIN(p3&,y&(i&))
    p4&=MAX(p4&,y&(i&))
  NEXT i&
  p1&=scrx&/(p2&-p1&)/2
  g=MIN(scry&/(p4&-p3&)/2,p1&)*vy/ob  'Objektgre abhngig von Entfernung und Brennweite
  RESTORE liniendaten
  FOR i&=1 TO ad&
    READ l&(i&)
    FOR j&=1 TO l&(i&)
      READ k&(i&,j&)
    NEXT j&
  NEXT i&
RETURN
PROCEDURE eingaben
  ep&=53
  ad&=22
  g=100  'Objektgre, wird aber beim Lesen noch auto eingestellt
  alpha=0
  beta=0
  gamma=0
  vx=1  'Rechts-Links-Verschiebung
  vy=350  'Entfernung
  vz=1  'Oben-Unten-Verschiebung
  ob=10  'Objektiv-Brennweite
  inits
  lesen
  optionen%=%0   'BIT                                  0          1
  '                             1      Hintergrund           wei     schwarz
  IF optionen% AND %10
    flaginvers!=TRUE  'Darstellungart einstellen TRUE=Hintergrund schwarz, FALSE=Hintergrund wei
  ELSE
    flaginvers!=FALSE
  ENDIF
RETURN
PROCEDURE darstellung
  @winkelberechnung(0)
  FOR i&=1 TO ep&
    x&=x&(i&),y&=y&(i&),z&=z&(i&)
    @punktabbildungen(0)
    bx&(i&)=bx&,by&(i&)=by&
  NEXT i&
  IF flaginvers!=TRUE
    GRAPHMODE R2_MERGEPEN,TRANSPARENT
    CLS 0
  ELSE
    GRAPHMODE R2_MASKPEN,TRANSPARENT
    CLS
  ENDIF
  RGBCOLOR RGB(rl|,gl|,bl|)
  FOR i&=1 TO ad&
    FOR j&=1 TO l&(i&)-1
      p1&=bx&(k&(i&,j&)),p2&=by&(k&(i&,j&)),p3&=bx&(k&(i&,j&+1)),p4&=by&(k&(i&,j&+1))
      PLOT p1&,p2&
      DRAW TO p3&,p4&
    NEXT j&
  NEXT i&
RETURN
PROCEDURE punktabbildungen(c1)
  x1=x&,y1=ca*y&-sa*z&,z1=sa*y&+ca*z&
  x2=cb*x1-sb*z1,y2=y1,z2=sb*x1+cb*z1
  x3=cc*x2-sc*y2,y3=sc*x2+cc*y2,z3=z2
  x4=x3+vx,y4=y3+vy,z4=z3+vz
  'Perspektiveberechnung
  u=-(x4+c1)/y4*g
  v=-z4/y4*g
  'Umrechnung auf Bildschirmkoordinaten
  bx&=_X/2+ob*u
  by&=_Y/2-ob*v
RETURN
PROCEDURE winkelberechnung(c1)
  gamma += c1
  ca=COS(alpha*PI/180),cb=COS(beta*PI/180),cc=COS(gamma*PI/180)
  sa=SIN(alpha*PI/180),sb=SIN(beta*PI/180),sc=SIN(gamma*PI/180)
  gamma -= c1
RETURN
eckpunktdaten:
DATA -65,-40,17,-65,40,17,65,40,17,65,-40,17,-60,-35,17
DATA -60,35,17,60,35,17,60,-35,17,-65,-40,-17,-65,40,-17
DATA 65,40,-17,65,-40,-17,-60,-35,-17,-60,35,-17,60,35,-17
DATA 60,-35,-17,-50,10,7,-50,20,7,-45,25,7,-20,25,7
DATA -15,20,7,-15,5,7,-20,0,7,-15,-5,7,-15,-20,7,-20,-25,7
DATA -45,-25,7,-50,-20,7,-50,-10,7,-35,-10,7,-35,-15,7
DATA -30,-15,7,-30,-5,7,-42,-5,7,-42,5,7,-30,5,7,-30,15,7
DATA -35,15,7,-35,10,7,-10,-5,7,-10,5,7,10,5,7,10,-5,7
DATA 15,-25,7,15,25,7,45,25,7,50,20,7,50,-20,7,45,-25,7
DATA 30,-15,7,30,15,7,35,15,7,35,-15,7
'53 Eckpunkte
liniendaten:
DATA 5,1,2,3,4,1
DATA 5,5,6,7,8,5
DATA 5,9,10,11,12,9
DATA 5,13,14,15,16,13
DATA 2,9,1
DATA 2,13,5
DATA 2,14,6
DATA 2,10,2
DATA 2,11,3
DATA 2,15,7
DATA 2,16,8
DATA 2,12,4
DATA 5,17,18,19,20,21
DATA 5,21,22,23,24,25
DATA 5,25,26,27,28,29
DATA 5,29,30,31,32,33
DATA 5,33,34,35,36,37
DATA 4,37,38,39,17
DATA 5,40,41,42,43,40
DATA 5,44,45,46,47,48
DATA 3,48,49,44
DATA 5,50,51,52,53,50
' 22 Datenzeilen fr Linien

//Greetings,
/Ingmar.


#: 98679 S12/GFA  (CIS:WINAPC)
    04-Jun-97  20:34:25
Sb: #freezing and GPFs!!!
Fm: James V. Schumacher 104166,2104
To: ALL
Replies:   1

Hi,

The following "may" be my problem.  I have a book titled  "Black Art Of Windows Game Programming" by Eric Lyons.  It says the following:

"Keep in mind one very important caution when using DeleteObject:  Never delete an object that is currently selected into a DC.  If you do, you can expect typical GDI-error results -- very bad things happen, often resulting in a crash of your (or some other) program.  Because of this, GDI "leaks" -- an accumulation of orphanced GDI objects -- are a common problem among novice (and expert!) GDI programmers."

and

"Remember that performing these operations in the wrong order -- first deleting the bitmap, then deleting the DC -- would probably cause GDI to crash at some point."

One of my routines does the following:

   GFAcurDChandle& = _DC()
   SETDC srcMDChandle&
   GET src.left,src.top,src.right -1, src.bottom-1,hbmp&
   SETDC destMDChandle&
   STRETCH dest.left,dest.top,hbmp&,destW&,destH&,copymode%
   FREEBMP hbmp&
   SETDC GFAcurDChandle&

srcMDChandle& or destMDChandle& are deleted much later.  Is my FREEBMP statement equivalent to deleting a selected bitmap before getting ride of  the MDC?

In another section of code I do the following:

   GFAcurDChandle& = _DC(WIN())
   SETDC gHandWorld&
   PUT gHandRect.left,gHandRect.top,handResHndl&
   FREEBMP handResHndl&
   SETDC GFAcurDChandle&

gHandWorld& is not free'd until much later.  Again, is my FREEBMP statement here the same as deleting the bitmap selected into the DC before deleting the DC?

Also, do I need a FREEDC GFAcurDChandle& statement at some point ... or would this be ill advised since _DC() and  _DC(WIN()) refer to the display context?

Finally, here's a third segment of code:

    hmono& = CreateBitmap(rect.right,rect.bottom,1,1,0)
    hnull& = SelectObject(gRewardWorldMask&(pictNum&),hmono&)
    SETDC gRewardWorldMask&(pictNum&)
       ... other statements
    FREEBMP hmono&
    SETDC gonScrnworld&

where MDC gRewardWorldMask&(pictNum&) is deleted later.  Is my FREEBMP hmono& possibly the problem.  Should I be deselecting it from the DC before I delete it  with a ~SelectObject(gRewardWorldMask&(pictNum&),hnull&) call?

Thanks,

James


#: 98689 S12/GFA  (CIS:WINAPC)
    05-Jun-97  09:31:23
Sb: #98679-freezing and GPFs!!!
Fm: Sjouke Hamstra 100741,1036
To: James V. Schumacher 104166,2104
Replies:   0

James, 

I think you located your problem. When using a memdc, you should indeed use FREEDC before FREEBMP, that is, if the the bitmap you refer to is selected in the memdc. You can do it otherwise, but then you must switch to SelectObject, rather than using SETBMP. The SelectObject function returns the previous selected bitmap, which you can restore before invoking FREEBMP. This way you make sure there is always a bitmap object selected in a memdc.

>> Finally, here's a third segment of code:

    hmono& = CreateBitmap(rect.right,rect.bottom,1,1,0)
    hnull& = SelectObject(gRewardWorldMask&(pictNum&),hmono&)
    SETDC gRewardWorldMask&(pictNum&)
       ... other statements
    FREEBMP hmono&
    SETDC gonScrnworld& <<
    
    I don't see any problems in the first two examples, but the last one is critical. You are deleting a bitmap that is currently selected into the gRewardWorldMask&(pictNum&) dc. So,

>> Should I be deselecting it from the DC before I delete it  with a ~SelectObject(gRewardWorldMask&(pictNum&),hnull&) call? <<

is exactly what you should do.

Greetings,
Sjouke Hamstra, GFABASIC Intermediary
(09:28 05-Jun-97 using OzWinII)


#: 98700 S12/GFA  (CIS:WINAPC)
    05-Jun-97  21:28:08
Sb: #98689-#freezing and GPFs!!!
Fm: James V. Schumacher 104166,2104
To: Sjouke Hamstra 100741,1036 (X)
Replies:   1

>>  I don't see any problems in the first two examples, but the last one is critical. <<

Hi Sjouke,

Unfortunately,  that particular section of code is never executed before the GPF that  I am currently trying to resolve.   It probably has something to do with the screen freezes I've had though!

 I've traced the current GPF down to the routine listed below.  If this routine is called, then the first time I run the code everything seems to work fine.  However, the second time I run the code, a GPF occurs at the same point (in a GET statement) later on.  If I then restart the computer, then once again, the first time I run the code ... no GPF, the second time ... GPF at the same point.   If I comment out the calls to the routine, then the code will run repeatedly without GPFs.  Do you see anything in particular wrong with the routine's coding.  This routine is supposed to paint the background of a window a specific color/pattern that is stored in resources.  The routine is called several times because it is in the WM_PAINT message section.

PROCEDURE PAINTPIXPAT(patResName$,lprect%)
    LOCAL hPatDIB&
    LOCAL hPatDDB&
    LOCAL hBrush&
    LOCAL hOldBrush&
    LOCAL hrsc&
    LOCAL pat%
    '
    hrsc& = FindResource(hAPPInst&,patResName$,RT_BITMAP)
    hPatDIB& = LoadResource(hAPPInst&,hrsc&)
    pat% = LockResource(hPatDIB&)
    'in DIB form ... must convert to DDB form
    IF hPatDIB&   //load ok?
      hDDB% = ^DIBTOBMP(hPatDIB&,1)
      hPatDDB& = LOWORD(hDDB%)
      hPatPal& = HIWORD(hDDB%)
    ENDIF
    ~UnlockResource(hPatDIB&)
    ~FreeResource(hPatDIB&)
    '
    oldPal& = SelectPalette(_DC(),hPatPal&,FALSE)
    ~RealizePalette(_DC())
    '
    hBrush& = CreatePatternBrush(hPatDDB&)
    hOldBrush& = SelectObject(_DC(),hBrush&)
    REALIZE WIN(WIN())
    PBOX {lprect%}.left,{lprect%}.top,{lprect%}.right,{lprect%}.bottom
    ~SelectObject(_DC(),hOldBrush&)
    ~DeleteObject(hOldBrush&)
    ~DeleteObject(hBrush&)
    ~SelectPalette(PrDC&,oldPal&,FALSE)
    ~DeleteObject(hPatPal&)
    FREEBMP hPatDDB&
RETURN

Thanks,

James


#: 98732 S12/GFA  (CIS:WINAPC)
    10-Jun-97  09:26:16
Sb: #98726-freezing and GPFs!!!
Fm: Sjouke Hamstra 100741,1036
To: James V. Schumacher 104166,2104
Replies:   0

>> Can I just assign an RGB color to a parameter and cause the window to use that color as the background? <<

No, you cannot. You can force GFA to redraw the background by providing a palette index with the CLS command. If you can make sure a specific color is located in a given palette entry you can do it that way. I have used another, more Windows-like way,  using a CB:

1. Create a brush using CreateSolidBrush(RGB(0,0,128))

2. Replace the class background brush with the brush:   ~SetClassWord(WIN(1),GCW_HBRBACKGROUND,hbrblue&)

3. Process the WM_PAINT message:
  CASE WM_PAINT
    BEGINPAINT hWnd,ps$
    ENDPAINT hWnd,ps$
    
This makes sure Windows uses the class brush for painting the window background.
    


Greetings,
Sjouke Hamstra, GFABASIC Intermediary
(09:22 10-Jun-97 using OzWinII)


#: 98729 S12/GFA  (CIS:WINAPC)
    10-Jun-97  09:09:02
Sb: #98718-Disk Volume Labels WIN95
Fm: Sjouke Hamstra 100741,1036
To: RAY FOLEY 71042,2233
Replies:   0

This is from the WIN32 SDK. If you have a copy of GFA32API, you must be able to add it to the kernel32 section by calling SetVolumeLabelA !

BOOL SetVolumeLabel(
    LPCTSTR  lpRootPathName,	// address of name of root directory for volume 
    LPCTSTR  lpVolumeName 	// name for the volume 
   );	

Parameters

lpRootPathName
Points to a null-terminated string specifying the root directory of a file system volume. This is the volume the function will label. If this parameter is NULL, the root of the current directory is used. 

lpVolumeName
Points to a string specifying a name for the volume. If this parameter is NULL, the function deletes the name of the specified volume. 

Return Value
If the function succeeds, the return value is TRUE.
If the function fails, the return value is FALSE. To get extended error information, call GetLastError. 

I didn't test it, but it should be this:

PROCEDURE SetVolumeLabel(lpRootPathName,lpVolumeName )
  $EXPORT SetVolumeLabel
  TRY
    RETVAL P:(lpf32)(L:lpRootPathName,L:lpVolumeName, L:^GetProcAddress32W(hkernel32,"SetVolumeLabelA"),L:%11,L:2)
  CATCH
  RETVAL ERR
RETURN

Let me know if it works.

Greetings,
Sjouke Hamstra, GFABASIC Intermediary
(09:40 09-Jun-97 using OzWinII)


#: 98741 S12/GFA  (CIS:WINAPC)
    11-Jun-97  06:50:13
Sb: #98732-freezing and GPFs!!!
Fm: James V. Schumacher 104166,2104
To: Sjouke Hamstra 100741,1036
Replies:   0

Hi Sjouke,

Thanks for your suggestion on how to color the background of  windows.  Unfortunately, it appears that my GPF is not caused by the routine I was using to do so.   I still get the GPF after eliminating all calls to the routine.   Too bad.

In trying to diagnose the GPF, I've "created" another error.  I want to describe it because it may or may not be related to the source of the GPF.

The  routine below is supposed to play an AVI.  I modified my program so that there are two ways to enter it from my splash window: press a key or click the mouse button.  Press a key and it runs correctly.  Click the mouse and it crashes at the MCI$(playCmd$,WIN(WIN())) statement.  In the latter case, the AVI output window flashes briefly, then I get this message from the CATCH:  "MMSYSTEM278  This is a driver specific error and the driver is closed.  Try the command again."

Below is the routine:

PROCEDURE displayVideoClipReward
  TRY
    fileName$ = "leaf^L.avi"
    aviFilePath$ = gAppPath$ + "\LTrewAVI\" + fileName$
    openCmd$ = "open " + aviFilePath$ + " TYPE AVIVideo alias videoclip"
    error$ = MCI$(openCmd$)
    playCmd$ = "PLAY videoclip from 1 NOTIFY"
    error$ = MCI$(playCmd$,WIN(WIN()))  // the error occurs here
    DO
      PEEKEVENT
    UNTIL _Mess = $3b9
    MCI "CLOSE all"  // closes all
  CATCH
  IF _EAX <> 0
    ~MessageBox(WIN(WIN()),mciErr$(_EAX),"mciErr$(_EAX)",MB_OK)
  ENDIF
RETURN

I've checked and filename$, gAppPath$ and WIN() are the same regardless of how the routine is entered.

The mouse click event is trapped by a CB declared thus:

CB -1,0 TO -1,onEventdoUserEvent

PROCEDURE onEventdoUserEvent(hwnd&,mess&,wparam&,lparam%)
  LOCAL pictsOK&
  LOCAL pos&
  SELECT WIN()
  CASE g_splashWind&
      IF mess& = WM_LBUTTONDOWN
       '
       //**** this is the code activated by a mouse click
        IF gActiveWind& = 0
          pictsOK& = FN arePICTsOKToDrill
          IF pictsOK& = TRUE
            gSessionStartTime% = GetTickCount()
            GOSUB initDrillWindow
            GOSUB endSplash
            gNeedNewReward& = TRUE
            GOSUB beginNewTrial
          ENDIF
         //****
         '
        ELSE
          GOSUB endSplash
        ENDIF
      ENDIF
    ENDIF
  ENDSELECT
RETURN

The key press event is trapped by the following code:

PROCEDURE dialogSplashWind
  LOCAL   pictsOK&
  SWITCH MENU(11)
  CASE WM_CHAR
   '
   //****code activated by key press
    IF  gActiveWind& = 0
      pictsOK& = FN arePICTsOKToDrill
      IF  pictsOK& = TRUE
        gSessionStartTime% = GetTickCount()
        GOSUB initDrillWindow
        GOSUB endSplash
        gNeedNewReward& = TRUE
        GOSUB beginNewTrial
      ENDIF
   //****
   '
    ELSE
      GOSUB endSplash
    ENDIF
  CASE WM_PAINT
    GOSUB refreshSplashWind
  ENDSWITCH
RETURN

PROCEDURE dialogSplashWind () above is reached through eventloop, below:

PROCEDURE eventloop
  DO
    PEEKEVENT
    GOSUB doBreak
    GOSUB doDialog
    GOSUB doMouse
    GOSUB doMenu
    GOSUB doTime
  LOOP
RETURN

where

PROCEDURE doDialog
  SELECT _winId  // WIN()
  CASE g_splashWind&
    GOSUB dialogSplashWind
  ENDSELECT
RETURN

Procedure doBreak is the only routine entered after the CB and before Procedure Dialog.  Procedure doBreak is as follows:

PROCEDURE doBreak
  'GFA test for "esc"-"shift" key combination
  IF ((WIN() = g_drillWind& AND gDisableContinueTrial& = FALSE) OR (WIN() = g_splashWind& AND gActiveWind& = 0)) AND gInit2Done& = TRUE
    IF ~GetKeyState(VK_SHIFT) > 0
      IF ~GetKeyState(VK_ESCAPE) > 0
        gDisableContinueTrial& = TRUE
        GOSUB displayPasswordWind
      ENDIF
    ENDIF
  ENDIF
RETURN

In other words, nothing happens in Procedure doBreak as a result of a mouse click or a single key press (and I'm not pressing the escape or shift key).

Thus, while there appears to be NO difference in the code that is activated after a mouse button or key press, I'm getting entirely different behavior.   Is there a problem with using a CB to detect a mouse click?  Otherwise, I see nothing that could cause this difference.  Do you?  Could this be an indication of a memory access error before the mouse button or key press that might cause a GPF later on?

Getting *really* frustrated ... sigh ... I thought I was so close to finishing this project ...

James


#: 98769 S12/GFA  (CIS:WINAPC)
    13-Jun-97  09:43:21
Sb: #98762-freezing and GPFs!!!
Fm: Sjouke Hamstra 100741,1036
To: James V. Schumacher 104166,2104 (X)
Replies:   0

>> Out  of curiosity, however, *why* is it bad to check for mouse clicks in a CB?  Should I be sure to avoid anything in a CB that I could do elsewhere? <<

It's not the check for a mouse message that's the problem, it's your message handling. CB -1,.. redirects ALL messages for ALL windows (including child windows) to the declared procedure. The check for WIN() is not correct, you must use the handle provided in the first parameter in the Window procedure. See CBPAL.LST in my book.
Greetings,
Sjouke Hamstra, GFABASIC Intermediary
(09:20 13-Jun-97 using OzWinII)


#: 98784 S12/GFA  (CIS:WINAPC)
    14-Jun-97  23:21:11
Sb: #98755-LOCK PIXELS?
Fm: James V. Schumacher 104166,2104
To: Sjouke Hamstra 100741,1036
Replies:   0

>>> If there are redundant function calls such that  the handle isn't  zero but the memory represented by the handle has already been released, will any of these functions (or others I haven't named) try to delete something in memory where the item the handle represented once was located? <<<
>>See my first answer. They might!<<

YES!!!!  Sjouke, I've fixed my GPF problem by making sure that I zeroed the handle after every ~FreeResource() call.  Even though everything seemed to be working without further problems, I also zeroed them after FREEFONT, as well as made sure that I deleted all palettes using myFREEBMP() rather than ~DeleteObject().

Here's my routine:

FUNCTION myFreeResource(hRes&)
  // do this because ~FreeResource() does not zero handle
  // which according to Sjouke might cause problems
  // if a deleted handle were later freed again
  // this was indeed causing GPFs
  ~FreeResource(hRes&)
  hRes& = 0
  RETURN hRes&
ENDFUNC

I would definitely recommend you point out this possible problem in future versions of your book.  Thanks for all your help!

James


#: 98821 S12/GFA  (CIS:WINAPC)
    17-Jun-97  17:53:07
Sb: #98786-Screensaver for WIN95
Fm: Dale Bryant 73134,1500
To: Jens Wachholz 106752,3253
Replies:   0

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

Sorry,Jens, I don't have any screen saver code at my fingertips. Will look for you and post it if I can find any that will do as you want.


#: 98812 S12/GFA  (CIS:WINAPC)
    17-Jun-97  00:50:11
Sb: #98729-#Disk Volume Labels WIN95
Fm: RAY FOLEY 71042,2233
To: Sjouke Hamstra 100741,1036 (X)
Replies:   1

Sjouke:

Thanks for the help on the SetVolumeLabel() Routine! I did find a few minor errors that gave an amature like me some fits but I got through them ok. Here is
the corrected code for anyone else who may need it.

PROCEDURE SetVolumeLabel(lpRootPathName%,lpVolumeName% )
  $EXPORT SetVolumeLabel
  TRY
    RETVAL P:(lpf32%)(L:lpRootPathName%,L:lpVolumeName%, L:^GetProcAddress32W(hkernel32%,"SetVolumeLabelA"),L:%11,L:2)
  CATCH
  RETVAL ERR
RETURN

Note the postfix of % on each of the passed values.

I also learned a little more about the WOW16 functions. How deep can we go into the 32 bit system without problems.
Do we need to wait still on the WIN95 version of GFA Basic?


                                                                                                                                 Ray


#: 98815 S12/GFA  (CIS:WINAPC)
    17-Jun-97  09:21:10
Sb: #98812-Disk Volume Labels WIN95
Fm: Sjouke Hamstra 100741,1036
To: RAY FOLEY 71042,2233
Replies:   0

>> Note the postfix of % on each of the passed values.

I also learned a little more about the WOW16 functions. How deep can we go into the 32 bit system without problems.
Do we need to wait still on the WIN95 version of GFA Basic? <<

The variables in GFA32API are long integer by default (DEFINT "a-z"). 
In principle you can call any WIN32 API function you like, by using the WOW functions.

Greetings,
Sjouke Hamstra, GFABASIC Intermediary
(09:18 17-Jun-97 using OzWinII)


#: 98869 S12/GFA  (CIS:WINAPC)
    21-Jun-97  11:22:22
Sb: #F10
Fm: Bob Springett 100776,3023
To: Sjouke Hamstra 100741,1036 (X)
Replies:   1

Sjouke,
I have had trouble getting F10 to respond to keyboard input in a program. Since, I have used the MESS_KBD.GFW from your book and get the same trouble, F1 to F9 and F11,F12 print their corresponding values but F10 no. Something is happening when F10 is pressed,
the cursor in the window containing the program text changes from an arrow to a text(hairline) cursor. Does Windows or GFA have an over riding interest in this function key.
Regards Bob


#: 98873 S12/GFA  (CIS:WINAPC)
    21-Jun-97  13:55:07
Sb: #98869-F10
Fm: Sjouke Hamstra 100741,1036
To: Bob Springett 100776,3023 (X)
Replies:   0

Hi Bob,

>> Does Windows or GFA have an over riding interest in this function key. <<

That's correct. It's a Windows key to activate the menu-bar. For the same reason the F10 implementation of GFA for MSDOS to RUN a program is changed to Shift-F10 in GFAWIN.

Greetings,
Sjouke Hamstra, GFABASIC Intermediary
(13:27 21-Jun-97 using OzWinII)


#: 98881 S12/GFA  (CIS:WINAPC)
    22-Jun-97  07:39:03
Sb: #98792-DLG3D
Fm: Bob Springett 100776,3023
To: Sjouke Hamstra 100741,1036
Replies:   0


Sjouke,
Could you tell me why the following piece of code(when DLG 3D ON is present) paints
itself on the screen and then repaints itself and if possible how to stop the repaint.
I have tried by elimination but the only thing that stops it is to eliminate the DLG 3D ON
which I would like to keep.
Regards Bob

DLG 3D ON
x& = 80
y& = 20
style% = WS_SYSMENU | WS_CAPTION | WS_VISIBLE
editstyle% = WS_BORDER '  ******************************************ES_MULTILINE******
DIALOG #0,0,0,640,480,"",style%
  i& = 1
  FOR countx& = 0 TO 8
    FOR county& = 0 TO 19
      CONTROL "",i&,"edit",editstyle%,x&,y&,48,16
      INC i&
      ADD y&,18
    NEXT county&
    y& = 20
    ADD  x&,50
  NEXT countx&
ENDDIALOG
SHOWDIALOG #0
DO
  GETEVENT
UNTIL MENU(1) = 4
DLG 3D OFF
END


#: 98912 S12/GFA  (CIS:WINAPC)
    25-Jun-97  10:09:08
Sb: #98905-Default Printer
Fm: Sjouke Hamstra 100741,1036
To: Andrew Risely 100667,1620 (X)
Replies:   0

Hi Andrew,

>> My goal is to have a section of my application automatically fax a report then revert back to the default printer for all other print jobs and other applications.  At the moment it seems to all be happening to quickly.

Am I going about this in the write way ? as win95 reports no changes in the default printer what ever I do. (except reboot or course) <<

Use the GetProfileString for the [devices] section in the WIN.INI to obtain the keywords for the printer (keyword=...).

~GetProfileString("devices",NULL,V:buf$,len(buf$)

Then search for the FAX driver, and use GetProfileString again to retrieve the entire string.

~GetProfileString("devices",V:buf$,V:buf2$,len(buf2$)

Use the information with the CreateDC() API. 

This should do the job.


Greetings,
Sjouke Hamstra, GFABASIC Intermediary
(09:57 25-Jun-97 using OzWinII)


#: 98926 S12/GFA  (CIS:WINAPC)
    26-Jun-97  21:17:26
Sb: #98905-#Default Printer
Fm: GFA Germany 75300,3224
To: Andrew Risely 100667,1620 (X)
Replies:   1

Andrew,

>>However, on the second attempt the correct printer is aquired. The result is the same whether I call DLG PRINT or not.<<
You should send WM_WININICHANGE to all Windows and force the system to re-load the WIN.INI with flushing the buffer (see WriteProfileString).

Regards


Sven Thomas
GFA Software


#: 98973 S12/GFA  (CIS:WINAPC)
    01-Jul-97  03:51:24
Sb: GFA Extension Tool 2.0
Fm: GFA Germany 75300,3224
To: ALL
Replies:   0

				GFA-Extension Tool 2.0

			Enhancement tool for GFA-BASIC



Make Programmer's life easier!

We are proud to announce the GFA-Extension Tool 2.0. It extends the GFA Editor with several new, powerful features. Try it, and you won't miss it any more!

Did you ever want to have long file names for your Source code files?
Do you ofen remark lines in the Editor while debugging your programs? Wouldn't it be easier to select a block and let the Editor automatically remark the whole block?

Here is the solution, the GFA-Extension Tool 2.0! It is fully configurable (you can switch on/off each feature separately) and runs with each Version of the GFA-BASIC Editor for Windows, even with the old ones (Version 4.31 or higher). And it is free-of-charge. Download it now, and simply install it as described in the documentation.

The GFA-Extension Tool 2.0 extends the GFA Editor with these features:

	- Debugger window is always on top and cannot be
	  overlapped by other windows
	- Supports long file names for loading and saving
	  GFW files and LST files within the GFA-Editor
	- Activation of the option "Ignore case" in the Find-
	  and Find-/Replace-Dialog
	- Several new hotkeys for different GFA-Editor functions
	- Run EXE option (executes the compiled EXE of the
	  currently loaded GFW file, if it exists;
	  otherwise the source code will be compiled first)
	- Syntax Error Check (remarks a line containing a
	  GFA Syntax Error, so you can leave the line)
	- Remark the current line
	  (Remark sign can be chosen from five styles)
	- Remark the currently selected block
	  (Remark sign can be chosen from five styles)
	- Remove the remark signs in the currently selected
	  block (only remark signs at the beginning of a line)



Download the GFA-Extension Tool 2.0 right now from the library!

You will find these versions:

GFAEXT2G.ZIP (60268 Bytes)	GFA-Extension Tool 2.0, with German documentation
GFAEXT2E.ZIP (58345 Bytes)	GFA-Extension Tool 2.0, with English documentation

(these files are available at http://ourworld.compuserve.com/homepages/gfasoft and ftp://ftp.bero-online.ml.org/pub/gfabasic/windows/extensions/exttool as well)

GFA-Extension Tool 2.0 requires GFA-BASIC for Windows Version 4.31 or higher. The long file name support additionally requires an operating system that can handle long file names, e.g. Windows95.




(c) 1997 by GFA Software Technologies, Inc./
GFA Systemtechnik GmbH


#: 98984 S12/GFA  (CIS:WINAPC)
    03-Jul-97  17:42:07
Sb: Dll Assiatance
Fm: Andrew Risely 100667,1620
To: SJ 100741,1036
Replies:   0

I am currently developing with Crystal Reports which provides a developers DLL engine, which I can call.

I have had moderate sucess in decoding the API use however, one command I cannot get to work, could you please check my definitions:-

C/Pascal Code supplied with developer pack:-

PEPrintReport is declared in CRPE.H as follows:

short FAR PASCAL PEPrintReport (char FAR *reportFilePath,
	BOOL toDefaultPrinter, BOOL toWindow, char FAR *title,
	int left, int top, int width, int height, DWORD style,
	HWND parentWindow);

The following table describes each argument:

Parameter	Description

reportFilePath	The name of the report to be printed. Include the path if the report is not in the current directory. The report name can be hardcoded and unchangeable at runtime, or you can pass a string variable or character array as the result of a user choice.

toDefaultPrinter	If toDefaultPrinter is set to TRUE (1), the report is sent to a printer. The toWindow argument should be set to FALSE.

toWindow		If toWindow is set to TRUE (1), the report is sent to a Preview window. The toDefaultPrinter argument should be set to FALSE.

title		The title that you want to appear in the window title bar. This argument can receive a string variable or a character array at runtime.

left		The position at which you want the left edge of the Preview window to appear if the report is being printed to a window.

top		The position at which you want the top edge of the Preview window to appear if the report is being printed to a window.

width		The width of your Preview window , in pixels, if the report is being printed to a window.

height		The height of your Preview window , in pixels, if the report is being printed to a window.

style		The style setting (as defined in WINDOWS.H). Style settings can be combined using the bitwise "OR" operator. These are standard Windows styles. Your options are:

Style	Decimal	Action

WS_MINIMIZE	536870912	Make a window that is minimized when it first appears.
WS_VISIBLE	268435456	Make a window that is visible when it first appears (for overlapping and popup windows.
WS_DISABLED	134217728	Make a window that is disabled when it first appears.
WS_CLIPSIBLINGS	67108864	Clip child windows with respect to one another.
WS_CLIPCHILDREN	33554432	Exclude the area occupied by child windows when drawing inside the parent widow.
WS_MAXIMIZE	16777216	Make a window of maximum size.
WS_CAPTION	12582912	Make a window that includes a title bar.
WS_BORDER	8388608	Make a window that includes a border.
WS_DLGFRAME	419304	Make a window that has a double border but no title.
WS_VSCROLL	2097152	Make a window that includes a vertical scroll bar.
WS_HSCROLL	1048576	Make a window that includes a horizontal scroll bar.
WS_SYSMENU	524288	Include the system menu box.
WS_THICKFRAME	262144	Include a thick frame that can be used to size the window.
WS_MINIMIZEBOX	131072	Include the minimize box.
WS_MAXIMIZEBOX	65536	Include the maximize box.
CW_USEDEFAULT	32768	Assign the child window the default horizontal and vertical position, and the default height and width.

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

MY ATTEMPT in GFA

DLL #1,"crpe.dll"
  DECL SHORT PEPrintReport(w,w,w,w,w,w,w,w,w,w)
ENDDLL

result&=^PEPrintReport("c:\crw\revenue.rpt"+CHR$(0),1,0,"Andrew"+CHR$(0),0,0,0,0,0,NULL)
ALERT 1,STR$(result&),1,"OK",a

Are the 'w' and 'l' in the decl statement correct. 

Tried   DECL SHORT PEPrintReport(l,w,w,l,w,w,w,w,w,w)

generates Peek/Poke Error Message? All other Dll seem to used 'l' to pass a string pointer to the function.  Also is there and difference in passing a BOOLEAN, as I can not find any examples of this anywhere.


Regards



Andrew


#: 98992 S12/GFA  (CIS:WINAPC)
    04-Jul-97  11:09:00
Sb: #98984-Dll Assiatance
Fm: Sjouke Hamstra 100741,1036
To: Andrew Risely 100667,1620
Replies:   0

Hi Andrew,

>> short FAR PASCAL PEPrintReport (char FAR *reportFilePath,
	BOOL toDefaultPrinter, BOOL toWindow, char FAR *title,
	int left, int top, int width, int height, DWORD style,
	HWND parentWindow); <<
        
Should be:

DECL SHORT PEPrintReport(l,w,w,l,w,w,w,w,l,w)

if it is a 16-bit DLL, otherwise all paramaters are LONG and the function should be called via the WOW functions or added to the GFA32API.DLL.


Greetings,
Sjouke Hamstra, GFABASIC Intermediary
(09:44 04-Jul-97 using OzWinII)


#: 98997 S12/GFA  (CIS:WINAPC)
    06-Jul-97  16:21:18
Sb: GFA-Extension Tool 2.0
Fm: GFA Germany 75300,3224
To: ALL
Replies:   0

Due to problems with uploads into the library, the GFA-Extension Tool 2.0 is not available until today.

We do the best to fix the problems and make the tool available as soon as possible. In the meantime you can download it from the WWW:
     http://ourworld.compuserve.com/homepages/gfasoft 
and from FTP
    ftp://ftp.bero-online.ml.org/pub/gfabasic/windows/extensions/exttool.

You will find these versions:

GFAEXT2G.ZIP (60268 Bytes)	GFA-Extension Tool 2.0, with German documentation
GFAEXT2E.ZIP (58345 Bytes)	GFA-Extension Tool 2.0, with English documentation

Additionally you can write private E-Mail to 75300,3224 and specify the version you want to have (one of the above). We will send it to you as file-attachment to an E-Mail.

Yours

Sven Thomas
GFA Software


