Boris Pekic - NG's archive

Boris Pekic - NG's archive

Postby Antonio Linares » Wed Aug 27, 2008 7:24 am

"Dear friends,

I hope these compiled messages will help...
From 01.June.2000 to 30.September.2002.

"Renewing time. Dedicated to all the friends around the world. This forum members shows that it doesn't matter where you are from, what is your skin color or what language are you speaking. The only thing that counts is friendship.

I am happy I can help all of you friends, to make your life much easier, searching the archive. See you next year, cheers! Regards from Belgrade, Yugoslavia"
regards, saludos

Antonio Linares
User avatar
Antonio Linares
Site Admin
Posts: 27219
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

32 bit stuff

Postby Antonio Linares » Wed Aug 27, 2008 7:25 am

32-bit operations


Has anyone had any luck in writing 32 bit entries to the registry ? If so, could you please post a working sample ?

Look in to this \source\classes\Reg32.prg source code. You will get the idea of how to proceed with it.


#Define HKEY_CURRENT_USER 2147483649

oReg := TReg32():New( HKEY_CURRENT_USER, "\Software\iCode" )

IF oReg:nError == 0

nOrd := oReg:Get("Order", 0)

IF oReg:nError == 0

nOrder := if( nOrd == -1, nOrder, nOrd)




It not work on Fwin++1.2, only on Fwin2.0


How can i get cGetFile in 32 bits

Here's the working V2. There is c code at the bottom that must be put in a 32bit dll. You can now get long filenames. ( V2.PRG ). you don't get an error message if no file is selected (cancel). ccepts a mask, default directory and caption for the file selection dialog.

It could be expanded but it is the basic model and I've also included a cGetFile() function which can be linked into your code where your existing code using cGetFile() should work.

Here's the ( LFN.ZIP ). It will contain the LFN.DLL for the cGetFile V2 posted above. You'll have to change the code in the V2.PRG to use LFN.DLL instead of MYDll.Dll ... You should be warned that using the LFN file get routine has a side effect. You have to remove the Null - Chr(0) - that is returned at the end of the filename.

If you don't and take the Right( alltrim(cFile), 3 ) for the file returned you will only get the last 2 characters AND a Null and not the filename extension you expect. ( LFNDIR.ZIP )


I am having a stupid problem with Crystal 32bits. I can call from 'CRPE32.DLL' the function PEOpenEngine' from one application as many time as I like, but if I have to run another application and open the Crystal report engine again with 'PEOpenEngine' it fails and of course I can't do anything more with crystal. If I comment out the call to 'PEOpenEngine' and then try to start report is shows a message that the report engine is not opened, but in the same moment from the first app I can run as many reports as I need. Has somebody noticed something ugly like this.

I ran a test program that looks something like


Local oCRW := CrystalReport():New()

oCrw:OpenReport( cReport,,.f.)

? "Ready"





I can run this once no problem. If I run another copy (copy the EXE) I get the following error KERNEL32.DLL

Cannot run multiple instances of a DLL under WIN32s. Don't know if it is possilbe to have two separate applications accessing the same 32 bit DLL?

I just gave a quick look today at your problem and maybe it isn't as serious as it may seem.

I did open to FW apps that use CR and launched a report in each of them. In the second one I do get the error mesage you say, but the CR errror number is 0. What I suspect is that it isn't really an error because I just changed the code to to return .T. (ie ! ::lError) is initialy ::lError is TRUE but a call to PEGetErrorCode() returns 0. So I was able to present the report in the second app without any more warinings or false messages.

How did you do that. Absolutely the same way as you describe I can reset the return value of ::lError so the program can continue but as soon as I run the report all the messages for 'Report Engine not Open' are coming and I cannot get the report on the screen. Would you send me your sample code so I can test it here. I will send you my sample just now.

Yes CRW v.6 32 bit works perfect. It looks very nice with the drill down, search in the report and so on. Even the old reports from CRW v.4 work fine. No more problems with the printers because the 16 bits drivers. When I am done with the latest functions in Tom's TCRW class I will post it here.


Where can I find about Win32 API or DLL32 functions?

Richard, Tehre are so many sources to find Win32 API function. You could use the Windows Api Viewer that comes with various Microsoft development tools (Like Visual Basic. for example). ... t_1n6t.htm although the source code examples are for VB, you can easily convert them toDLL32 calls


I'm really screw up with this one ! I want to use the function Peekmessage from USER32.DLL This is the MSN Info:


BOOL PeekMessage(

LPMSG lpMsg <>, // pointer to structure for message

HWND hWnd <>, // handle to window

UINT wMsgFilterMin <>, // first message

UINT wMsgFilterMax <>, // last message

UINT wRemoveMsg <> // removal flags


typedef struct tagMSG { HWND hwnd; UINT message;

WPARAM wParam; LPARAM lParam;

DWORD time; POINT pt;

} MSG;


I translate it this way with FIvewin:

STRUCt Ostruct

Member Hwnd AS LONG

Member Uint AS _INT

Member Wparam AS DWORD

Member Lparam AS LONG

Member Time AS LONG

Member Point AS LONG


DLL32 FUNCTION Peekit( Lpmsg AS PTR, Hwnd AS LONG, Mfirst AS _INT, Mlast AS _INT, Mrem AS _INT ) AS BOOL PASCAL ;

FROM "PeekMessageA" LIB "USER32.DLL"

I call the Function this way Peekit(Ostruct,GetdesktopWindow(),522,522,0) I always received a GPF and Drwatson says that I acces memory improperly ! Where is my mistake ?? Any help or Idea will be appreciated !

I've found that with 32bit dll's you should use LONG instead of _INT when creating your DLL32 Functions. I've also found that returning _INT instead of a BOOL works better (so you just test the return against 0=FALSE or 1=TRUE). ie:


FROM "PeekMessageA" LIB "USER32.DLL"

Thank 's for the information I'll give it a try this week and let you now how it goes ! What I ant to do it's to add MOUSE_WHEEL event to 16 bits application !

Sound cool. Let us know when you have it working.

It's working thank you for all the information you gave me !

I can now trap the WM_MOUSEWHEEL message but the problem is that I have to use

DLL32 GetmessageA to retrieve it because with PeekMessageA I can't chatch it BEFORE

the default WNDPROC of Fivewin !

But it's working, I sent a message to Antonio, to see if he can change the default process for queue message just adding a call to peekMessageA to retrieve the Wparam to get the wheel Rotation !

If I was able to catch all message BEFORE Fivewin do it I can gave support for WM_MOUSEWHEEL event to Fivewin user !

Without testing, I did notice a few things. Any time Windows sends back data, whether it's LPSTR, PTR or otherwise, you need to proceeed the parameter with @. Also, try using LPSTR for the structure that Windows is returning. Generally, you are only using PTR when numers are returned. In this case, Windows is essentially returning the cBuffer of the structure to you. And finally, try using LONG where UINT's are concerned. Using _INT is Okay for 16-Bit DLL's but not for 32-Bit (called from a 16-Bit application that is).


FROM "PeekMessageA" LIB "USER32.DLL"

It still may not work, but I would start with the things mentioned above. If you are still having problems, let me know and I will do some testing.

Oh, and one other thing call the function this way:

cBuffer := Ostruct:cBuffer

Peekit( @cBuffer, GetdesktopWindow(), 522, 522, 0 )

// Validation Etc

Ostruct:cBuffer := cBuffer

Thank's for all the information you gave me, MY Win32 API problem goes away with the detailed information you give me !


32-bit Parse Script:

small bug fixed for error 'Cannot Read Beyond End of File' - now setup is an installable exe - converts ASCII text to a variety of formats ( ACCESS, Excel, XML, HTML, dBASE ) - freeware, then click on <More...>, and then click on <Download>.


I need to use function GET_FLAG that is in CALC32.DLL (32 Bits) as I make to declare it?
int Get_Flag( short int * FlagFiscal )

AS LONG PASCAL FROM "Get_Flag" LIB "calc32.dll"

Debtor for the aid, but did not function. When I call the functioncontinues closing the program.
What more I can make?


Debtor for the aid, but did not function. When I call the function continues closing the program.
What more I can make?

do you have access to the source code for the CALC32.DLL? What is the Get_Flag( ) function supposed to do?

Does it run in 16bit? Reason I ask. There seems to be a bug in the 32bit DLL function. I have a program I need 32bit DLL action; unfortunately, it only works in 16bit. Antonio is aware of the problem.

The problem is alone with functions that receive parameters from the type shorts int? In these cases it is only giving error.
Use Fw2.2+Clipper 5.e + Blinker 5.1

I do not have access to the sources, and this function returns flag from a fiscal printer.
Already I perceived that the problem is occurring with all the functions of the DLL that wait a parameter of the type short int.
int Get_Flag( short int * FlagFiscal )
Already I tried to declare it the following forms of declaration and nothing.
AS LONG PASCAL FROM "Get_Flag" LIB "calc32.dll"
AS LONG PASCAL FROM "Get_Flag" LIB "calc32.dll"
AS LONG PASCAL FROM "Get_Flag" LIB "calc32.dll"
You can help me?

it seems that the 32bit thunk that Fivewin does is deficient as far as that type of pointer. Fivetech would have to fix their 32bit thunking in order to fix this problem.
Basically what would be required is to create a short int equivalent on the 16bit c side, convert it to a 32bit short int and then pass a pointer of it
on the stack when calling / thunking the 32bit function.

Maybe Vilian could try with
AS LONG PASCAL FROM "Get_Flag" LIB "calc32.dll"
and then convert cFlagFiscal to nFlagFiscal using BIN2I() function.

FiveWin simply uses the Windows standard thunking system that does all thatautomatically :-)
Maybe, the problem comes from the way the function is getting called.I guess something like this may be needed:
local nFlagFiscal := 0
MsgInfo( Get_Flag( @nFlagFiscal ) )
MsgInfo( nFlagFiscal )
AS LONG PASCAL FROM "Get_Flag" LIB "calc32.dll"
Notice the use of "@"

Thanks, it´s ok.


See the sample bellow in VisualBasil
Public Declare Function Bematech_FI_VendeItem Lib "BemaFi32.dll" (ByVal Codigo As String, ByVal Descricao As String, ByVal
Aliquota As String, ByVal TipoQuantidade As String, ByVal Quantidade As String, ByVal CasasDecimais As Integer, ByVal
ValorUnitario As String, ByVal TipoDesconto As String, ByVal Desconto As String) As Integer
Retorno = Bematech_FI_VendeItem("1", "Caneta", "II", "I", "10", 2, "0,25", "%", "0000")
It´s Ok
The same sample in FiveWin 2.2c don´t work.
DLL32 FUNCTION BmVendItem( Codigo AS LPSTR, Descricao AS LPSTR, Aliquota AS LPSTR, TpQte AS LPSTR,;
Quantid AS LPSTR, Decimal AS PTR , ValUnit AS LPSTR , TpDesc AS LPSTR,;
ValDesc AS LPSTR ) ;
AS LONG PASCAL FROM "Bematech_FI_VendeItem" LIB "BemaFi32.dll"
Retorno = BmVendItem("1", "Caneta", "II", "I", "10", 2, "0,25", "%", "0000")
LOCAL cVar01 := "1", cVar02 := "Caneta",cVar03 := "II",cVar04 := "I",cVar05 := "10",nVal := 2,;
cVar06 := "0,25",cVar07 := "%",cVar08 := "0000"
Retorno := BmVendItem(cVar01,cVar02,cVar03,cVar04,cVar05,nVal,cVar06, cVar07, cVar08)
DLL32 FUNCTION BmVendItem( Codigo AS STRING, Descricao AS STRING, Aliquota AS STRING, TpQte AS STRING,;
Quantid AS STRING, Decimal AS PTR , ValUnit AS STRING , TpDesc AS STRING,;
ValDesc AS STRING ) ;
AS LONG PASCAL FROM "Bematech_FI_VendeItem" LIB "BemaFi32.dll"
Retorno = BmVendItem("1", "Caneta", "II", "I", "10", 2, "0,25", "%", "0000")
LOCAL cVar01 := "1", cVar02 := "Caneta",cVar03 := "II",cVar04 := "I",cVar05 := "10",nVal := 2,;
cVar06 := "0,25",cVar07 := "%",cVar08 := "0000"
Retorno := BmVendItem(cVar01,cVar02,cVar03,cVar04,cVar05,nVal,cVar06, cVar07, cVar08)
What more I can make?

Decimal must be of LONG type not PTR.

Thanks, It´s ok.

regards, saludos

Antonio Linares
User avatar
Antonio Linares
Site Admin
Posts: 27219
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

3D Studio

Postby Antonio Linares » Wed Aug 27, 2008 7:27 am

3D Studio and FiveWin


I wonder if a VBX or DLL to manage 3DStudio files exist. Can anybody help me ?

Check They release DLL and ActiveX Controls.... dbcad can read dwg files, so all you have to do is to save 3dstudio files as dwg

regards, saludos

Antonio Linares
User avatar
Antonio Linares
Site Admin
Posts: 27219
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

3th Party Libraries

Postby Antonio Linares » Wed Aug 27, 2008 7:28 am

3th Party Libraries and FiveWin


what are 3rd part lib compatible with fivewin?

The most of the libraries designed for working under protected mode are compatibles with FiveWin.However some stuff is not compatible:

a.) Comm libraries like Telepathy are no compatible because coummunications interruptions under Windows are different from DOS, you will need instead to use a DLL library for such things.

b.) Graphical tools like Light-Lib, ProVision Windows and other don't work neither because Graphical interface is handled by Windows. Also Bussiness graphics tools like Flipper, TLib and others are notcompatible.Anyway, Windows is full of other wonderful stuff that will keep your mind off of your old DOS libs.

However you must also keep a can of Raid handy for all those bugs in Windows....

You're right !, and also have in hand (or in feet) a heavy industrial boots for squashing those anoying bugs called GPFs, you the ones that state Some module has caused a General Protection Fail in the module most-unknow address Random(number).GUINDOS: Graphic User Interface Naturally for DOS. (In Spanish GU sounds like W)


We used several libriaries in an old DOS and Windows applications. We need to locate some of the vendors for the libriaries we used. Purchase them, and turn them over to our client. Does anybody know how to get in touch with the following vendors, or principals.



Ninety5 fot funcky and for ninety5. For Silverware I do not know a URL.

Silverware is no longer produced, you may get an old copy from somewhere. Ninety5 is by Tomsoft and Funky is/was by dLesko Associates.


Using the toleauto class, I do the following
oFuncky := TOleAuto():New("Funcky")
However, this returns zero, which I suppose means failure Any ideas/people doing this?

Try this:
oFuncky := TOleAuto():New("Funcky.6")
Also see attached sample that uses FUNCky 6.0 IPADRESS.ZIP

also, be in mind that it only works with Harbour

Didn't toleauto use to work with regular Fivewin/Clipper? I can't distribute commercial apps with harbour yet.

The problem is about 16 bits. Funky6 is an ActiveX component (similar but not equal to an OLE automation server), that cannot be accessed from 16 bits apps.
If you need Funky6 from Clipper apps, you can use the .lib, that contains almost functions. Some time ago, I ask Dirk (the creator of
Funcky) about this and this was his answer:


Anybody have a font to create a postnet barcode for the US Post Officestandards.

Some years ago I downloaded a shareware library (I think from the OASIS ftp) called the Texas Laser Library. It was a library of printer functions specifically for HP compatible laser printers. It did include a postnet barcode function.
The function was a little buggy on some zip codes, so I write my own function using some of the drawing functions in the laser LIB.
It worked well for my purposes, but it was for an S87 app and was specific to HP compatible printers. If you're interested, I'll send you the source.


Can funcky 2,5 used with harbor ? Can 6,0 be used ?

> Can funcky 2,5 used with harbor ?
No, Funcky 2.5 is 16 bits. Harbour is 32 bits.
> Can 6,0 be used ?
Yes! I'm working on a FUNCky wrapper's for Harbour. OR you can use Jose's OLE class. See attached PRG as a sample. IPS.PRG

regards, saludos

Antonio Linares
User avatar
Antonio Linares
Site Admin
Posts: 27219
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

MS Access

Postby Antonio Linares » Wed Aug 27, 2008 7:28 am

MS Access


What is the best way or is it possible to access a Microsoft Access MDB database within fivewin?

ODBC 3.50 would work with FiveWin. Otherwise I do not know if it is possible at all.


I need make search in files ACCESS, How make ?

You need ODBC driver for Access version 3.51, version 4 do not work.

But, how or where obtain ODBC driver ?

Have you got 3.51 working ? Only 3.5 an prior versions were working before.


Is there an example for converting dbf-files into access-files?

you can always go to\~stanl\D2001.htm
there are free utilities, requires only a simple WaitRun() in your application

thank but we 're fouding anything to link our program code.

I am sorry, I do not understand what you wrote. If you are trying to insult me, you may write in Italian, I can get it translated.

Stan, I don't think he is trying to insult you. Just his english is worse than mine. :-) Probably he did mean: "thanks but we found nothing
to link to our program code". Maybe he did hope to find in your site a source code or a library while we all know that you have some external
EXEs that can be called from our FW apps.

Dear Stan,
I 'm not trying to insult you I explain my problem :
I must to compile the function dbf2access on my exe program and I cannot use a external program Because it crash my program .
I hope you understand me now . I was found the dbf2acc source code but it not run because there are not the ch files Can You help us ?
Best Regards and sorry if you think bad about me

1. I do not think bad about anybody
2. If you are referring to the original dbf2acc FiveWin Program I wrote, that used ODBC calls, it failed after Microsoft Access
Driver 3.5 or above ( which use threads)
3. If you cannot shell to an external exe without your program crashing, then you have some serious problems with that
program. I currently have FW programs compiled in 1.9.1 that shell out to Winbatch Scripts I have compiled which download
and convert DB2 data from an AS400 into multi-tabbed Excel Spreadsheet. I only added the WaitRun() function to he original
apps, and they have been running for 1 year now.

Can I have the new download URL ?

Is it easy to install Winbatch on a remote PC (W98-W2000-WXP)?
For now I use winexec and a VB-program. But to install VB on a user-PC is a task for its own.
You are never sure if your program executes. Therefore I would prefer a FW solution.
I bought Squealer
(The Industrial Demystification Tool Squealer can tell you in seconds which component is missing as well as well as generate a complete manifest of all of the components your application needs so you can easily compare it with a system that DOES work. )

I never use Winexec() always WaitRun(). What is so good about Winbatch being 32-bit is that if there is ever any problems, the calling FW app never crashes (my fingers are crossed - it never has crashed so far ).
I communicate between FW and all my WB extensions via an ini or by passing parameters ( Winbatch accepts 9 ).
To add a DBF2Access routine in FW, involves about 600 lines of code, in Winbatch about 13. So my average
Winbatch EXE is based upon about 400 lines, but can perform about 16 tasks ( dbf to Access, to Excel, to
HTML, Access to DBF, Custom 'explorer/html like' dialogs with animated GIF's or music to enjoy during long
processing, complete UDL creation and editing, links for reports.... the list goes on. But in the meantime, my
FW EXE is the same size. In fact I am working on a Winbatch 'launcher' that waits on the tray, and executes
FW programs, and actually tells them to accept parameters for additional Winbatch EXE's - in effect a 32-bit
shell for a 16-bit EXE that can shell to a 32-bit exe - and it works with as little as 32meg RAM.
I just completed an application soley in Winbatch with 99 lines of code. It
1. creates a temp Access Database, and links in a DBF
2. issues 17 queries on in-bound 800 number calls for resort Motels in North Carolina to Florida
3. These queries are inserted into 17 unique Excel Files, with custom headers and formating for each resort.
4. Each Excel Spreadsheet is attached to an auto-email
The entire process takes about 40 seconds on a 233mg NT with 128k Ram.
99 lines of code, under 2 hours to develop and test.
Like perhaps many reading this, I am getting old, I have a family to feed, a mortgage to pay, my eyesight is
poor, so I need to go with what works. But don't get me wrong, FiveWin works - so does Winbatch, with 99
lines of code.

Perhaps You not understand our problems I have many dbf and I want to converte in a MDB for use it on a WEB with a program made in asp
I think explained YOU well !!!!!! Thereis a dbf2acc routine in fivewin sintax ? Do you have this source ?


You mentioned that you must use DAO for passwords in Access, but that maynot be entirely true.
Access 2000 and Jet 4.0 permit extensive DML advances; I just wrote a scriptexample issuing SQL
CREATE VIEW [ ...... ]
permits writing portable code from Access to SQL Server or MSDE or otherANSI92 SQL data sources. What is interesting is that the 'views' cannot be seen i Access ( they do not appear as query objects ) but can be manipulated via Jet 4.0 and ADO/OLEDB.
In addition to CREATE VIEW [or CREATE PROCEDURE which is really awesome ]
you can GRANT and REVOKE or issue SELECTS with user permissions....
see. ... advsql.asp

Thanks for the info.


Does anybody have an example using Fivewin with Access? I need to change my database to Access and I don't know how to do.

There was something about FWACCESS a couple of years ago. I have the exe,hlp file and sample database but no source. It uses odbc.
I can send it to your e-mail if you wish.

FW16 can work with Access only with 3.5 or olders versions ODBC drivers . I'm reading data from Access tables so , it is the
same way like FW16+ODBC+SQL .

Have you done some tests using all MS Access versions? I recieved the FWACCESS.EXE that access a 16-bits driver from Access 2.0. And the others? What I have here is Access XP.

I made some tests with Access 2000 with no results because the ODBC driver was > 3.5
I didn't want to install an older one because if the customer reinstalls Office or upgrade it with a newest version, the ODBC driver could be
upgraded again. I had only to read some data from a small table, so I wrote a little Acces macro that exports that table to a DBF one and run it everytime the FW application starts.

I use SQLExpress and xBase++ and it works well.


A discussion took place last month about using MDB files in FW. Has anyone got a working example or sample code to do same?
I need to use a MDB file in my application which will be installed on a variety of customers machines, Win98/2000 and XP etc.. I am using comix within my own application and awaiting cdx support before I move to Harbour.
Any help would be appreciated.

Take a look to TesdODBC.Prg in your samples directory.


I have two problems regarding a MS Access database.
1) From time to time I need to copy an entire access table to a dbf.
I use oOdbc:Query("SELECT * FROM " + cTable) to create a temporary dbf then I read through it and append it to a dbf within the application. This is very slow (about 150 records per minute). There must be a better way :-(
2) I need to do a lookup on the access file similar to dbseek().
Should I use a sql command within oOdbc:Query()? If so, has anyone experience in doing this. Any sample code would be appreciated or can you suggest any reading material on sql formats.
Is any of this realistic in the commercial world, or should I be trying a different approach?

Hmm .. strange . I'm working with Access databases and I'm doing the same copy as you . But speed is very good . The only difference is that this my app. is writen with TRddOdbc , because TDbOdbcDirect wasn't and I'm using 3.5 version MS Access ODBC driver . I don't really know , but in earlier was problem with others ODBC versions with Access . Then I wrote this app. and tried to run with 4.0 version of MS Acces ODBC driver , then I got GPF . So it was needful to reinstall ODBC drivers . Maybe is problem with driver ? In this days I'm working with TDbOdbcDirect and MS SQL 7.0 and 2000 . With SQL there isn't problem ODBC drivers . I'm working with Clipper 5.3b , FW 2.0d and Blinker 5.1
> 2) I need to do a lookup on the access file similar to dbseek().
> Should I use a sql command within oOdbc:Query()? If so, has anyone
> experience in doing this. Any sample code would be appreciated or can you
> suggest any reading material on sql formats.
Yes , you can use more complex sql query - the same "select " - with "where " clause . Here is a small sample :
static function find_sql( cTable, cField, uVar )
local cLen := len( alltrim( uVar ) )
local cSql := "select " + cField + " from " + cTable + " where left( " +
cField + ", " + cLen + " )" = " + alltrim( uVar )
local oDbf := TDbOdbcDirect():new( cSql, oOdbc )
if oOdbc:IsError()
oOdbc:aErrors := {}
return( NIL )
return( oDbf )
That will return recordset where will be search results . It is needful to familiarize with SQL syntax . It is very powefull thing and it is very easy
to learn .
David , if you need help with TDbOdbcDirect , please wait some days . I'll send you a sample how to to work with tcbrowse and TDboDbcDirect .

I'm going to get some books on SQL.
The access speed may be the size of the memo fields, but I still find it too slow for serious commercial work.
Perhaps with more experience and trying different PC's, I'll increase the speed, although I used the TESTODBC as a jump start.
> David , if you need help with TDbOdbcDirect , please wait some days .I'll
> send you a sample how to to work with tcbrowse and TDboDbcDirect .
Many thanks for the offer, I look forward to seeing your samples.

Maybe the slow is MsAccess, just a thought. :-))

Please test the sample testodbc against on any mdb database. On my tests I
only needed 2 seconds to retrieve 2.200 records. (Pentium IV 1.3)

you should use
I do it daily with files of 25meg or more and it takes less than 4 seconds...

I'm only starting with ODBC and SQL
Can you expand your sample please?

I should have read your initial post more carefully. The TdbOdbcDirect call has built in support for converting a Table to a DBF.
However, Access has support for ISAM's built in, but with the syntax I suggested you would want to use the TOle class. In that case you would open the MDB with either the Jet OLEDB Provider, or as Access.Application-
then, asssuming
table name in Access is - Mytable
path for dbase filer is C:\dbfiles
name for dBase File is MyDbf
you would execute a single SQL Statement:
SELECT * INTO [dBase III;Database=c:\dbfiles].[MyDbf] FROM [MyTable]
the benefit here is that you could change dBase III to dBase IV, Excel 8.0, HTML or any other ISAM supported and get the appropriate output.
Now, using OLE ( or ADO ) instead of ODB, you can employ generic methods such as Seek(), Find() and Filter() to quickly get at data in Access. And, since these methods are generic, a simple change of Provider or database let's you re-use the code for Oracle, SQL Server, MySQL... etc...
I suggest you play around with Regedit to see the ISAM's available with your version of Access.
The initial learning curve with ADO can be cut in half if you download the MDAC SDK from Microsoft.


Is there a (simple) way to read/write information contained in a MS Access database?

There are so many questions about access to MS ACCESS that I think it is time for<?xml:namespace prefix = o ns ="urn:schemas-microsoft-com:office:office" />
FIVETECH to work on this and release a solution.
Because of the lack of a solution I use VB with the APOLLO database engine.
With APOLLO you can use dBase-files (CDX,NTX supported) within VB.
So I do my work the other way round. With VB I open my dbf-files and do the import-export to MS ACCESS.

That could get interesting. Just my own opinion but I do not think it is up to the developers to produce a solution, but only to
make the products 'compatible' - this done by the tOLE class, or the ODBC classe(s)..
FiveWin, at its core is still tied to the DBF structure. If you have a FW application and more and more customers want it to be
MSACCESS friendly, you have the simple choice of re-coding it in VB or Access Basic. On the other hand, if they want the
ability to Export Data from your system to manipulate, or you find it easier to use SQL and ACCESS ( as some sort of
middleware ) to produce rerports, queries, crosstabs, or conversions ( to Excel or other ISAM's ), you have a similar set of
1. code the demands into your existing app
2. shell out to 3rd party apps - the cheapest being VBScript which has excellent OLE capabilities and is free. MDAC is free and
you can create .MDB files without even having Access installed ( but you just cannot view them ).
Again, this is my opinion - but the bottom line is that it is not going to be done for free ( which I think a lot of people expect ).
Then there is a 3rd possibility. I have a legacy FW app that produces about 800meg of data files daily, statistics, billing,
reports, over 300 browse screens - but the demands for queries and conversions became so code laden, many of the newer
employees started linking to my DBF's with Access and performing their own queries - without causing major problems - so
that 3rd choice - fairly intelligent users, who can expand your basic product on their own ( therefore you never have to be told
you designed from obsolecence ).
P.S. - Winbatch just released 2 new FREE extender DLL's - one for Terminal Server, one for eHLLAPI ( for screen scraping and
3270 ermulation ).

In my opinion one of the great advantages of Fivewin-programs is that you can copy the application to a PC and your program will work. So if I would use one of your suggestions I think at least I would need a ODBC-driver installed and then this advantage would not be.
OT: ad) I do not think it is up to the developers to produce a solution I think the examples and solutions coming with fivewin and also form the 3rd party should be more standardized the way that they should work out of the box.
For example if you look at VB. You download a project open it and than you press F5 or the button "RUN" and all works. So you can test easily if this is a solution for you or not.
Ad) but the bottom line is that it is not going to be done for free ( which I think a lot of people expect
As I sell my software I do not expect free development-software.

Is it possible to use VBScript outside a ASP page? How?

First, to Enrico:
I said cheapest, that is all. Personally I use VBscript 'templates' to create my own OLE apps, which is not as cheap, I had to license a WB
compiler, but like Clipper, I have unlimited runtime.
Next, to Otto
I agree with your comments; while it is not possible for FW to 'do all things for all people', if there is compatibility it should be more clearly
stated. But then, such is the purpose of newsgroups, where users share knowledge.
However, where does such knowledge start and stop? Look at the recent post concerning obtaining a contact list from Outlook. I posted code ( in WB ) illustrating how one could use the Jet OLEDB 4.0 Provider to obtain the information in XML. Now, I first had to convert this code from VB/VBScript to WB, so I assumed that interested users could convert the WB code to tOle, but a user writes that he cannot, so could I do it for him?
That, my friend, would be the problem for developers - should they provide a means for users to use ODBC/ADO/OLE resources, or should they write the users programs for them? Simple economics provides the answer.
and to my firend Ignacio,
I know you work hard to provide the Interface ( not always the solution ) - or was we say in North Carolina - RTFM
R = Read
T = The
M = Manual
F = ( not a pleasant word )
... some people just are not ready.

It seems you have not upgrade your Fivewin version for a long time, did you? (maybe is time for it :-))
If not, please take some spare time to read carefully our FiveODBC documentation included on Fivewin.

FiveODBC, of course. In my opinion ODBC connections are really for kids, do not be afraid of SQL language is by far easier then Xbase.
You should read carefully all the FiveOdbc documentation.

I hadn't realised there was info on the FW disk (only used it once). However the demo wants an odbc.dll, any suggestions where to obtain this, MS Access is installed on my system.

regards, saludos

Antonio Linares
User avatar
Antonio Linares
Site Admin
Posts: 27219
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Acrobat Reader

Postby Antonio Linares » Wed Aug 27, 2008 7:29 am

Acrobat Reader


Mi goal is:

1) Open Acrobat Reader

2) Open a document

3) Print the document

4) Close Acrobat Reader

Any help?

I found a solution:


hWnd:=FindWindow(0,"Acrobat Reader");

if hWnd!=0



regards, saludos

Antonio Linares
User avatar
Antonio Linares
Site Admin
Posts: 27219
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain


Postby Antonio Linares » Wed Aug 27, 2008 7:29 am



It is nice when you have problems to work out.

I had to come up with a statistical summary against 700,000-1 million records kept in ACCESS by a Delphi App. They recorded phone calls and call duration in seconds. The data had to be read by a FiveWin App, then exported to Comma-Delimited file.

In FiveWin that would have meant exporting both ACCESS tables to DBFS, building indexes, creating relationships, creating a third database to hold the summaries, and writing a processing loop. So I came up with this [ Note: ANI is a phone number]


cSQL = "SELECT TrunkANI.ANI, Sum(TrunkANI.Calls) AS Call, Sum(Seconds)/60

AS Minutes INTO temp35 FROM TrunkANI WHERE (((TrunkANI.ANI)




Then I by-passed the slower ODBC drivers by using the newer OLEDB

cConn = "Provider=MicroSoft Jet OLEDB.4.0; Data


DB = ObjectOpen("ADODB.Connection")


RS = DB.Execute(cSQL)

And, theoretically, once the data is moved to ORACLE, all I have to do is change Provider= the rest stays the same. The query does take 10 minutes, but as far as I'm concerned - I am hooked on ADO - and y'all get this stuff up in Harbour, it will Rock!!!

Sounds great.

What version of Clipper/Harbour etc and FiveWin are you using? Obviously this will work with Oracle using ODBC and ADO. I wonder will it work with Oracle's proprietary middleware (SQL*Net, OCI etc.). You might get better performance this way.

Actually, this works with OLEDB, that's the Provider=, in ADO it is simply Driver=

We use MSORADB as our Provider for Oracle. I'm not an expert so I cannot comment on SQL *NET, but I do know that it permits a link between our LAN VB apps and Internet ASP's, therefore permitting both local and remote Data-Entry/Queries from just a about the same screens.

As for the version of FiveWin - 1.9.5, but I use a 32bit scripting language called Winbatch to accomplish this.

Although I am sure that Harbour as a 32bit Fivewin-enabled product may eventually replicate this - I had to have the results on the FTP site ASAP or risk a lawsuit.

Just today, I received word that the customer wanted an addtional field to calculate a commission - and the original ACCESS table has grown by 240,000 rows - I simply have to modify the SQL statement to get the desired results (it still takes 10 minutes), but while it is running, I am developing a generic metod to pass an unlimited number of databases/queries to the same script (which is currently 7 lines of code).


(George, if your read this, you'll love it)

I finally installed Office 2000, and can now begin to test many of the new ADO methods available. However, I was pleased to learn that most of them are contained in the MDAC 2.5 drivers. In particular, I was intersted in moving data from a TABLE to a comma-delimited text file which would be placed on an FTP site. I had been using DAO since I was required to both use a DAO Object to create and execute a query, then an Application Object to transfer the query to a text file.

Under ADO, I knew I could create a Recordset, but how to get this to a text file? I was also anxious to test the claim that an OLEDB provider was faster than DAO.

I (1) discovered how to do it (2) tested it and it was much faster.

first, set up your provider (I amd using ACCESS Tables), and create twoobjects

cConn = "Provider=MicroSoft.Jet.OLEDB.4.0; Data


DB = ObjectOpen("ADODB.Connection")

RS = ObjectOpen("ADODB.Recordset")


cSQL = "SELECT * FROM <Table>" // or use any query SQL expression

then create your recordset

RS = DB.Execute(cSQL)

Now, using either fopen(), or something to create an ASCII file

file://I am using Winbatch here, but you get the point

fle = FileOpen("test35.txt","WRITE")

file://I choose to put the 'field' names first

cRc = ""

FLDS = RS.Fields

nCount = FLDS.Count()

For i=0 to ( nCount-1 )

nField = RS.Fields(i)

cName= nField.Name

cRc = strcat(cRc,",",cName)


cRc = StrSub(cRc,2,-1)


Finally, I discovered that MDAC 2.5 permits you to use the GetStrin() method

cRest = RS.GetString()

FileWrite(fle,cRest )




This is so fast, I was amazed. In reality, getstring() takes five parameters, but I was able to get by with the default. By using a Recordset, you never create temporary queries or tables in your Database, you simply manipulate and export data. And, by using the Provider=, I am able to perform the same task with Oracle and SQL Server Tables.

P.S. - this is not something you can only do in Winbatch, it should be easily accomplished with the FiveWin OLE Class. Stan Littlefield

Of course I "read this". Your postings are always interesting. Yes, it looks great.

In relation to "read this" I just want to share the following. After spending two nights to get FWOle working with Excel I gave up and went to VB. I got it for a few hours as this was my very first experience with VB. However I needed to pass some start-up parameters to my VB application but did not know how to handle them in VB and I posted a message in one of the VB forums on the M$ news server and surprise - I got 2 replies for just a few minutes + a web link with a history with all the message and a search engine posted to my private email. It was such a good filling. Stan, tell me, does WinBatch need run time files when you distribute your software.

Winbatch is an 'interprative' language - but you have the ability to compile and distribute standalone EXES with no royalties. It is, more or less C/C++ DLLS and wrapper functions to the WINAPI. In the 'basic' library there are over 500 functions covering strings, binary and ASCII file management, OLE, Netware and NT functions. In addition, Wilson WindowWare makes avaialble for free 'extender' DLLS - covering areas like ADSI, FTP/SMTP, ODBC.

In itself, Winbatch does not have a datbase engine, but I saw possibilites to extend my stable FiveWin apps into areas like ODBC/OLE/ADO where I was having problems, but needed results.

Talk about support, two days after I requested that they consider a separate section in their NewsGroup for OLE/ODBC/DDE etc... they put it there. Most questions I post are answered within hours. Outside their newsgroup they have an extensive section of code snippets (really 'scripts', not code, although they have While...EndWhile, For...Next, Switch...EndSwitch, If..else..endif built into the language.

I know a lot of FiveWin users have purchased and are using Winbatch the same way I am, not as a replacement, but as an add-on. One user, who posted a script which showed how to perform 32-bit SMTP on WIN98 with FiveWin and Winbatch - wrote, "it is almost a crime, how ridiculously easy it is to accomplish something I have been trying for months to accomplish with FiveWin alone".

Two other points: (1) Winbatch has a dllcall() function similar to the DLL32 in FIveWin, but without the thunking; it is easy to pass structures with 32/64bit Longs.. (2) like Clipper's extend system,

Winbatch has an SDK, so you can write your own 32bit DLL's (they are limited to 100 functions each) which can be included in your scripts by simply writing

AddExtender( "<your DLL>" )

If you have tried any of my demoes like WBDEMO or DBF2ACC, you will see it is difficult to tell where FiveWin ends and Winbatch starts.

Right now, I am in the planning stages of using Winbatch OLE to populate multiple sheet Excel files with data from legacy DBFS. The Excel files are templates, with 1-3 main database sheets, a graph sheet, a summary sheet. In essence the Excel file functions as a standalone app for specific results (all sent as SQL queries, so there is no need to modify one line of my FiveWin code which produces the DBF's)

Stan you made a GREAT job with odbc and ADO/DAO.. i read that you are working on winbatch.... Did you have any working code on fivewin, using ado or dao via OLE connection?


The other week I posted some code that illustrated the RecordSet method getstring(), which converts a given RS

( where RS = SELECT.... FROM )

into a CSV file. At first, I didn't think that was very impressive, but in one of the applications I used it with, the end-users want the Recordset displayed by the browser (on an Intra-Net). Please note, before you read any farther, this will only work with IE version 4.0 or higher.

I thought about writing code to loop through the Recordset, and create an HTML page, with a simply table. That is when I discovered the Microsoft TDC (table display component). This OCX, which is called from an HTM page via a CSLID number, can autoformat a CSV into a DHTML web table. I discovered that by adding a piece of JavaScript code, the resulting file would display the Recordset in the Browser as 'pages', contains buttons to go back and forth, and can even sort by column headings. (see attached JPG). ( DHTML.ZIP )

The attached zip file contains RAO.TXT and the template TEMP.HTM to produce the paged display.

Be sure to modify the line in the HTM file


To indicate where you placed the RAO.TXT file. I call TEMP.HTM a template, because with very little effort you could probably

1. load it into a memvar

2. Modify or Set the DataURL

3. Modify/Set the sort and DATAFLD's

Obviously, this would be used only in places where users needed a list of names, or a log-file display, and it will work with any comma-delimited file, not just ones created with getstring().

What's the easy way to get all the possible methods, and variables from the TDC.OCX. Can you fix the column widths???

TDC is just something to know is out there; RDS is probably a better way to go, since it will also work with NutsScrape 4+;

The only TDC Method I am aware of is reset(); and I think the Column Size could be set within the

<TABLE> ... </TABLE> as COLSIZE= (just straight HTML)

We tested the TDC.OCX and it looks very good. The only problem is it appears that the brings all the data to the client. Have you come accross any types of OCX, or Active X controls which will provide browse capability but only send the number of rows required to be drawn on the screen. We currently do this with ASP but maybe there is something you have seen.

I'm not sure what you are exactly after. In the template I provided you could easily add


to the javascript, or since the original dataset is based upon an SQL query, put a WHERE clause there.

The example file is every Revenue Accounting Office for Telecom in the U.S. - I set it up as an example, but wanted to avoid getting in trouble with my company - in reality, we query this by state and include the phone numbers. I discovered that you could actually write a small ASP script to pass the Data Source to the HTM code without having to modify the template file.

What I am after is an OCX which is server based and only sends HTML code to the client for screen updates. Similar to what TBrowse did on the monitor of a PC. This OCX will send all data requested, and filter it on the client side not the server side. Dont get me wrong, I like this one but it may not work for all applications.

Are you talking about situations where users perform remote data-entry? Or situations where users request information ( i.e. "I want to buy a Car? What Kind of cars Do You have?") then can filter to what they are after and perhaps finally submit a request.

I think, as following the specifics of this particular thread, that we are talking about ADO and disconnected RecordSets. It sounds so easy, but I am still a little confused, the more I read into it. I have another example, I am working up whcih contains a 'Filter' window, I'll post it soon.


Access to Data Sources Through ADO

In the not so distant past, it was only the biggest websites which featured interactive forms, personalization, and search capability. Now it is becoming a requirement of any website. As websites have evolved from business novelty to business necessity, the architecture of these sites has become increasingly complex and therefore more costly, particularly in terms of the development cycles. Naturally enough, end users’ expectations follow hard on the heals of technological developments, and site visitors have are increasingly discerning in their requirements, expecting the functionality hitherto associated with traditional software from the websites they visit. Businesses are compelled to keep up to speed with their sites if they want to hold onto their traffic. And this means fast and efficient data access.

ADO is a series of ActiveX Data Objects, a technology that can access data stores such as relational databases or message stores, with speed, clarity and ease. It is an instance of Microsoft’s strategy for dealing with a huge variety of data sources - Universal Data Access (UDA) - and a higher level of model to that of OLEDB, which is a COM (Component Object Model - a set of object orientated interfaces). The upshot is that ADO is much easier to use, and because of the ActiveX component, ADO can be used from within any other language supporting COM - Visual Basic, VBA, Scripting languages, VC++ and VJ++, and allows data retrieval with sometimes as little as one line of code.

The ADO object model comprises three main objects, the Connection object, the RecordSet object and the Command object. These last two can be used without the user explicitly creating a Connection object, despite their hierarchical dependence upon it, and in these cases ADO creates the connection behind the scenes as and when it is needed.

The RecordSet object allows data to be marshalled between tiers easily and without the need for custom code. It is bested suited to updating records, or multiple fields in a record, and for complex data manipulation. The Command object calls complicated stored procedures, and is used for single commands, in particular those that require parameters. The Connection object, the workhorse of ADO, is used to establish a connection to a data source, and can be used to execute SQL statements, stored procedures, delete a record, or perform simple updates.

Each use of a Connection string to access the data source creates a new connection, so if you are going to be running several commands, or creating several record sets, then it is good practice to create a Connection Object directly. This you can use throughout your code without worrying about the number of connections you are creating. It’s faster, more efficient, and reusable.

Creating the Connection

Establishing a connection to a database is an expensive process, both in terms of the CPU processing time required to create the connection, and the memory used to maintain it. When establishing connections to a database (or instantiating objects with ASP) the first thing to consider is the impact they will have on the system’s resources. Used over enthusiastically, connections can be responsible for the crashing of an otherwise hardy server.

One way to alleviate this fairly disastrous side effect is through Connection pooling (enabled by default in IIS4 if you install the latest ODBC drivers and ADO 2.0), where connections that have been returned to the pool can be reused. A connection from the pool will be reused if all the connection details exactly match, irrespective of how the connection was made. Connection pooling decreases the wear and tear on the CPU and memory, since it reuses connection that has been established beforehand.

While ADO doesn’t require that connections be explicitly created, because using the RecordSet or Command objects implicitly creates them, there are instances where it is more efficient to do so. If, for example, you are creating several record sets, then calling an explicitly created Connection object means that it can be reused, and you do not need to worry about the number of connections that would otherwise be created.

The syntax for creating the Connection object depends upon your preference. You can call an object that has been implicitly created by ADO previously, or use a ConnectionString, comprising either Data Source Name (DSN) or individual parameter=value pairs detailing how the connect to the data source should be established:.

ConnectionString = "provider=SQLOLEDB; Data Source=DatabaseName; Initial Catalog=Pubs; User Id=sa; Password="


ConnectionString = "DSN=Pubs"

Once the connObj is created we need to open the connection with the following syntax:

connObj.Open ConnectionString,UserID,Password

The advantages of using a System DSN to connect to a data source, is that you only need to change code in one place in order for all the references to that code to be effected. Naming of the individual parameters, however, creates a direct connection, is slightly faster, and, of course, the code is clearer to read. You could also transfer the parameters in the ConnectionString to an include file, which would combine the advantages of both systems.

Retrieving Information

Since we are interested in retrieving information, the next step is to create a recordset. The three ADO objects can return a recordset, so the one you use depends entirely on what you need to do. In this example, we are going to display the information we collect in an HTML page. The most efficient way to do this is use the Connection object, which returns a recordset with a read-only forward-only cursor. The syntax would be:

Set rsObj = connObj.Execute (CommandText,RecordsEffected,Options)

CommandText is the SQL statement you send to the database, RecordsEffected returns the value of how many record(s) effected and Options indicates the type of statement you are sending, (0 unkown - default – driver must try to figure out what you are sending slows performance, 1 SQL statement, 2 Use to open a table, 4 Stored Procedure). In this example, we are sending a SQL statement and don’t need to know how many records where effected.

sql = "SELECT Name,Email FROM Demo"

Set rsObj = connObj.Execute (sql,,1)

Displaying Information

Now that we have a recordset (rsObj), a combination of ADO properties and VBScript will look through the recordset and collect the information. VBScript offers several tools to trawl collections, For-Next, For-Each, Do-While, and Do-Until. Which one you choose depends on what you want to do. In this case we'll use the Do-While Loop to iterate through a recordset. Let’s display the information in a table.

<table border="1" cellspacing="2" cellpadding="2">






Do While NOT rsObj.EOF



<td><%= rsObj.Fields("Name") %></td>

<td><%= rsObj.Fields("Email") %></td>



'Move to the next record





One great thing about ASP is that it allows you to mix HTML and VBScript on one page, which makes coding a lot easier. The draw back, however, is that forcing the ASP parser to switch between HTML and ASP slows performance. The code written here could have easily been written entirely in ASP in order to increase performance. However, for clarity I choose to break it up to make it easier to read. An extract looks like this:


Do While NOT rsObj.EOF

‘Chr(13) & Chr(10) is a carriage return and line feed

Response.Write("<tr>" & Chr(13) & Chr(10))

Response.Write("<td>" & rsObj.Fields("Name") & "</td>" & Chr(13) & Chr(10))

Response.Write("<td>" & rsObj.Fields("Email") & "</td>" & Chr(13) & Chr(10))

Response.Write("</tr>" & Chr(13) & Chr(10))



Tidying Up

The last step is to free-up memory resources by closing all-open objects and setting them to nothing. While in ADO.2 setting the connObj to nothing removes the connection from the pool, in ADO 2.1, the connection only becomes inactive and waits in the pool until, or if, it is needed. The final bit of code for this is:


Set rsObj = Nothing



About a month ago, I asked about interest in a FiveWin XML class.

Seems Microsoft made it easy with ADO (2.5) just set

adPersistXML = 1

then create an Ado Recordset where

RS = SELECT <something> from DATA_SOURCE


and later


can restore the RecordSet.

hope to post a very 'practical' demo in the near future. stan littlefield

and I just figured out how to put the XML file back into a Recordset, and Insert it into another table. This means that if I perform a QUERY on a 2 million row Oracle table, return a RecordSet of Say 800 rows (grouped,sorted, etc...) then save it as XML -

I can re-create the data in (1) another Oracle Table (2)ACCESS (3)Excel (4)DBF (5)Sybase or any other Client-Server with a OLE DB Provider option - all with once generic script. This, I found, is what is meant by a disconnected Recordset.


Unless you have ADO 2.5 and or MDAC 2.5, read no further.

I have put together a demo which illustrates a generic procedure to reconstruct a recordset from a .XML text file (created from the ADO 'stream'). The demo will

1. load the XML file as a Recordset

2. Create a new ACCESS Database

3. INSERT the Recordset into an new Table

4. Then do the same only this time creating a DBF

I am not going to post this, but will send a zip file with instructions in response to direct e-mail requests. stan littlefield

I'm definetely interested Stan. I've just finished creating new array (2 dim) and text file data drivers abstracted the data source for data in reports) where you can now do anything with those arrays or text files (comma delimited) just like you do with DBFs in GX. It is quite something. If a textfile is delimited, you can treat it just like a dbf where the different columns are accessed with a FieldGet() method the data array. So now, I'm looking for more data sources - I think the first should be Access and it looks like you have the ticket. Only one thing though - I'm going to have to write some type of parser that will create sql expressions from std expressions we use in clipper to obtain a scoped recordset.

I'm not sure where the convergence is between XML and GX, but the demo is on its way...

I have a 'freebie' - if you try and successfully yest the XML demo I will send you an EXE that will allow you to select any MDB file in the path, and a corresponding XML file will be output detailing the 'schema' of the MDB -i.e. all tables, links,views....

regards, saludos

Antonio Linares
User avatar
Antonio Linares
Site Admin
Posts: 27219
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Advantage DS

Postby Antonio Linares » Wed Aug 27, 2008 7:30 am

Adventage Database Server


is anybody using ADS in an novell net and running Windows NT on a workplace with Fivewin apps? I use ADS in Novell net with Win95/98-machines and have no problems with my FW apps. Since yesterday we have on one machine Windows NT and the DOS-version of my apps are running normal but the fivewin version cannot open the databases (DBFCMD-error). Any comment?

What protocol are you using to access the NT ?, FiveWin Apps should use TCP/IP, not IPX protocol in order to access ADS Data, ADS Client includes the DOS IP, a program that must be running on you client PC to access the ADS NT Server.

I disagree with René because ADS internally was writen around IPX so you will get best performance with IPX. ADS on NT has half the speed versus ADS on Novell. (God save Novell) I think the problem you experiment is caused by the absence of some DLL in the windows\system directory. Check your documentation and put all those dll.

Sorry to disagree with you this time, in our test under NT, ADS seems to be faster using TCP/IP than IPX, specially with Win98, those terminals (win98) doesn´t seem to work properly with IPX. (Tested with 150 concucurrent users on an Wan enviroment).

This is a subjective matter. IPX is horrible on WAN but god in LAN. The way you access the databases is other theme to see.


I am obtaining mistakes when I am going to use ADS with my application , I am going to describe my steps to create the program , if someone can help me , I would stay very thankful :

1) My environment :

ADS 5.1 Windows NT

RDD 5.0

Fivewin 2.0

Clipper 5.3b ( I use files CDX do Clipper 5.3b )

Blinker 5.1

Net Windows NT 4 Service pack 5 ( protocol unico TCP/IP in all estaçoes)

Terminals Windows NT Workstation and Windows 98

2) Link Script

# Blinker 5.10 Script










name FiveWin

description 'Windows Fivewin'

exetype Windows

code moveable discardable

date preload moveable

stacksize 12500

heapsize 2048

segment 'PLANKTON_TEXT' nondiscardable

segment 'EXTEND_TEXT' nondiscardable

segment 'OM_TEXT' nondiscardable

segment 'OSMEM_TEXT' nondiscardable

segment 'SORTOF_TEXT' nondiscardable

segment 'STACK_TEXT' nondiscardable



FILE __________, DBFCDXAX

SEARCH Five, FiveC, Objects


LIB WinApi, Clipper, Extend, DbfCdx, _Dbfcdx, Terminal , Barlib , Ctp


3) Alterations in the Program



#INCLUDE "DBFCDXAX.CH" / it is necessario ?

I use the following function for not link RDD default (DBFNTX) :




Must continue using ? I copied DLL AXCOMM16.DLL and ADSIP16.DLL in directory where the application is executed . I didn't find DLL AXSCOMM.DLL , it is the same that AXCOMM16 ?

4) Result :

I obtain the following message :



And the program generates a GPF when it executes.

1. solved the problem :

I can't use SEARCH , I Have to use LIB in the following script line :


if I uses SEARCH occurs a GPF.


When opening my files with ADS , one of the files doesn't have index , just a MEMO (FPT) , when the program is going opened him occurs the following mistake :


all of the files used for ads has to have one Index ?

EXACTLY !!! all the files must have an index in order to use ADS support, remember, an RDD is normally used for indexing support.

NO, NO, NO !!!!! You don't need and index to use ADS. I use ADS everyday with no index on some files.


Please I need a link script to use Advantage database server with Clipper 5.2e, FW 1.95 and Blinker 5.1.



























































































name Optowin

description 'Kill your memory'

exetype Windows 3.1

code moveable discardable preload

data preload moveable

stacksize 9500

heapsize 2048

segment 'PLANKTON_TEXT' nondiscardable

segment 'EXTEND_TEXT' nondiscardable

segment 'OM_TEXT' nondiscardable

segment 'OSMEM_TEXT' nondiscardable

segment 'SORTOF_TEXT' nondiscardable

segment 'STACK_TEXT' nondiscardable



Thanks for your response but the link script you post is for Clipper 5.3 and I need for 5.2e.


I want to try Advantage Xbase Server. Does anyone know where I can find it?


Does FiveWin work with Advantage?

Yes it does! Rene Flores uses it frequently. Rene?

Yes it works great, as it does with Dos clipper, we have been using it for some time now. My only grip is its expensive (in SA) which is making us look at alternative products

YES; no problems at all. You need a special link-script and in your app. these rows:




ADS works superb with FiveWin (faster than in DOS, super stable and great with data transactions), we have been using it for a long time ago (almost 4 years) in several projects with our apps with FW, we are testing actually with Xbase++ (in DOS mode) and seems to work good. Keep in touch, Extended Systems (the producers of ADS) are planning to create a Driver for Harbour and if it works as Harbour will do, boy, you will have a great DataServer.

there is already a ads rdd driver in harbour and it works good......

Are they writing their own DBFCDX, does anybody know? I would be much happier if I knew I could buy COMIX for Harbour and use that which I know is proven in what is such a critical part of the whole product

DBFCDX is actually working in harbour already before DBFNTX and it is part of harbour so there is no need to buy it separately.

My point is ...Did they re-write it from scratch?? and if so its bound to be buggy, and database handling has to be 100% perfect......... Look at Clipper5.2e DBFCDX which was buggy so CA when they released Clipper 5.3 licensed COMIX and used that in 5.3 as DBFCDX instead of their own buggy version. To me COMIX is king (for local /small network access) and that is what s/be in Harbour

Is COMIX still alive?<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> My version is from 1997.

yes, for 5.2 if you have Clipper 5.3, the DBFCDX in Clipper 5.3 is Comix.

I think Bruno is about done with the cdx driver for harbour. i don't know if it will support all the comix stuff <i hope so>

is it likely that one person can get right in a short time what has evolved and been developed by many over a long period of time....., what's the likelihood?


It's possible to know how can you work with Borland Control without Fivewin/3 error?

because i made a little aplication, and this crash when reopen some dialog with Borland Control , I renamed the Bwcc.dll to miBwcc.dll and load in the begining of the main program, and free on then end, but this not work correctly (FiveWin/3 error). The strange is that the aplication work fine in my pc where i develop this, but in other machine (same version and revision of windows 95) don't work, i copied the Bwcc.dll, ctl3d.dll..... but don't work, How do you do?

Avantage doesn´t use borland controls, they use modifications to TBTNBMP class to make the buttons look like borland's. Suggestion: stop using Borland controls, they only give headaches !!!


You can probably improve memory usage if you use ADS by upgrading your client to 5.5

Below is extract from Advantage upgrade doc

What's New in v5.5

a) The amount of DGROUP used by the DBFAXS.LIB library has been drastically reduced. Older versions of DBFAXS.LIB could use over 5K of DGROUP. Version 5.5 of DBFAXS.LIB will only use approximately 1.5K.


I'm using clipper 5.3 (DBFCDX) With Fivewin 2.3. I want to go to ADS 5.5 (Client) + 5.7.2 (Server)
With DBFCDX my application is very fact ( using OrdKeyNo and OrdKeyCount )
With DBFCDXAX my application is Sloooooooooow ( using Ax_KeyNo and Ax_KeyCount )
Why ?
May Ax_ function are not well implemented ?

Do you use the function Ax_driver() in your Skipper() function ? This really slows down the application.
I have no problems with Ax_KeyNo() and Ax_KeyCount()

no i do not use ax_driver() in the skipper function. I'm using WBrowse, is wbrowse use ax_driver ?
thanks for reply !

If you mean the class twBrowse() from wBrowse.prg; it does not use ax_driver().
My ads browses are fast and I also use client version 5.5. If you send me your sloooooow code I will take a look at it.

Thanks fo reply. I solve my problem not using ax_keyno().


I am using ADS and need to have Raw Save method without implicit locking and
unlocking. I need to control the locking and unlocking myself. Earlier Mr.
James Bott was kind enough to post a solution subclassing TData, using an
undocumented save method. I lost this posting and not able to relocate it.
I shall be glad if Mr. James Bott advises how to subclass TData so that I
can have a save method without locking or unlocking.

You don't have to subclass, just call the saveData() method instead of the save() method.

Thank You


I am using ADS. Though the error I am trying solve is an Advantage error, the source of the problem is the behaviour of Refresh() and Paint() methods. The error is Advantage DBFCDXAX/6619, which means that "The client comm layers was busy with one database operation when a second database operation was requested".
Our applications have sevaral browses and the users have choices to change 'orders', choose different filters, etc while viewing the browses. While the refresh operations are fast on LAN, the refresh operations take between 1 to 2 seconds on WAN (64 kbps connectivity thro permanent / ISDN). When a user over WAN initiates a filter or change of order, the refresh takes about a second and if he triggers another change (filter or order) before theearlier refresh finishes, the above error occurs.
In the DOS TBrowse, there is a vaiable TBrowse:stable. In such a case, we can check for :stable before changing the filter or order to avoid the above error. But either in TWBrowse or TSBrowse, I could not find any such vaiable and through my program I am not able to decided if the Refresh() andPaint() operations were completed.
If there is a way to query the browse object, to find out if the browse is stable ( or if the refresh or paint operations were completed ) it is
possible to hold up the second request for change of filter/order till the browse is stable.
Can Mr.Manuel Mercado or any other help please?

There are some issues on the website of advantage on this problem. The main problem is that ads supports multitasking, this can lead to error
6619 in some cases. This problem can also occur in normal network-conditions. I solved this problem by changing the adsipx16.dll and the adsip16.dll on every workstation to the versions that do not support multitasking. These are not the default .dll files; I got them from advantage.
Also, I have modified the errsysw.prg to support some other ADS errors. I also made a function that auto-copies the .dll files to the workstation if these are not present. If you are interested I can send you these files; send me an email.

I am very thankful for your reply. I have been struggling with this problem for quite sometime.
I shall be extremely thankful if you can kindly send the dlls and your modified errsysw.prg. I do hope this will avoid the errors we are facing.
Thanks in advance

Files have been sended to you. Succes.


If I do this "Set _3DLook On" with ADS and NT 4.0, the 3D controls are disabled but if ADS not linked seems OK on NT
4.0. How can I fix this?

My AP working fine on WinXP.Below:
RddRegister( "ADS", 1 )
RddSetDefault( "ADS" )
Set _3DLook ON
Set Resources to 'KIDS32.dll'
Return Nil
Exit Function Exit_Init()
Set 3dLook Off
Set Resources to
Return Nil

have you try using my ctl3d.lib?

Sorry to bother.
I forgot to copy the Ctl3D.Dll to my working directory ;-)))
Thank you for all your support.
Jose, I'll try your Ctl3D. OK? ;-)))


My apps hanging on tsbrowse right click mouse on Fw2.1c and ADS 6.0 client.
What should i do?

It's OK now. I Have to call AX_TagOrder() before TSBrowse. Strange......
Thanks anyway.


Did somebody use Advantage Local Server with Fivewin/Clipper? There are ACE functions ADSSetServerType and
ADSConnect, but how to use these ACE functions under Fivewin?

can not be used with 16bit clipper/fivewin applications. But can be used
with 32bit Harbour applications


I'm trying to implement the ADS local server and I seem to have too many #include files. I'm getting the following compiler error.
Fatal C3048 Preprocessor table overflow
I can't seem to find any help in the Norton Guides.
Using 5.2e

put these defines before all your include files
#define _VIDEO_CH // if you are not using videos in your prg.
#define _DDE_CH // if you are not using DDE's
#define _TREE_CH // if you are not using Trees
#define _DLL_CH // if you are not defining DLL functions
#define _OBJECTS_CH
and then
#include ""
now please try

Thank you - that worked well.


I am looking for a List of functions for the ADS library but can not find them. A Manual of functions to call? Can anybody help by
giving me the Address for the Page on the Web. Were the Functions are listed.
Thank you.
I have pick up some of the Functions. But don't know all the Par. to pass to the functions.

If you downloaded the ADS client for Clipper the there's a Norton Guides with all the functions documentation.
In other clients, such Delphi one, a HLP file is provided.

I am using the DLL for Harbour and Fivewin 2.3 is it the same as the ADS Client for Clipper?


I am finamy going to convert a program from Comix 3.0 single user to ADS client server.
I have already a client server Fortress. That should be working better for Comix users. But that application did'nt work fine because
of a problem with the ipx drivers. The clients were W98 WME and W2000. Fortress was fast to sell but when I contact them with a problem they never reacted. This happend several times.
I often use the CmFilter() in my application that has to be changed. Is there an equivalent in ADS. Is there a fast way to convert.
Sorry, I have more questions.
Is the server also able for later use with Harbour ?
I think ADS works also with IPX. Are there any problems known with this driver in collaboration with internet. Have they already a
TCP version and is this working stable.
Is the local server working in a client server situation while developping. I mean data on Pc1 and program on Pc2 ?
I know, many questions, but here is the place to ask so.

Yes your coADS code will work the same with Harbour.

I am finamy going to convert a program from Comix 3.0 single user to ADS client server. I have already a client server Fortress.
That should be working better for Comix users. But that application did'nt work fine because of a problem with the ipx drivers. The
clients were W98 WME and W2000.Fortress was fast to sell but when I contact them with a problem they never reacted. This
happend several times.
What a shame.
I often use the CmFilter() in my application that has to be changed. Is there an equivalent in ADS.Is there a fast way to convert.
I don´t remember but you can make a question in his news forum. Check for the link
Sorry, I have more questions. Is the server also able for later use with Harbour ?
I think ADS works also with IPX.
Yes. The only trouble you can have is with Windows Me and XP Home Edition because it cant be connected to a server, just peer to peer.
Are there any problems known with this driver in collaboration with internet.
No, I never got any problems but got some problems whit protocols and the like.
Have they already a TCP version and is this working stable.
Is the local server working in a client server situation while developping. I mean data on Pc1 and program on Pc2 ?
I never test the Local Server but I know many user of FW have done that.

We have installed over 500 ADS licenses during the las 5 years and let me tell you that is a superb product.
>I have already a client server Fortress. That should be working better for Comix users. But that >application did'nt work fine
because of a problem with the ipx drivers. The clients were W98 WME and >W2000.
ADS runs on both, IPX or TCP/IP, if your app is a Clipper FiveWin one, it will automatically detect the protocol and will work with any
problem.>Fortress was fast to sell but when I contact them with a problem they never reacted. This happend >several times.
ADS has a wonderful tech support team, a huge, enormous knowledge base with almost all the problems you can find solved, a
news group is also available and your questions are solved within the next 24 hours you posted them.>I often use the CmFilter() in
my application that has to be changed. Is there an equivalent in ADS.>Is there a fast way to convert.
ADS has one thing called Advantage Optimized Filters (AOFs), they are incredibly fast no matter how big is you database.

>Is theserver also able for later use with Harbour ?
Yes !!!!, you bet, the same server can be used with Clipper, Harbour, VisualBullshit, Delphi, or C.>I think ADS works also with IPX.
Are there any problems known with this driver in collaboration with >internet. Have they already a TCP version and is this working
As I told you before, ADS works great on both (IPX would be my choice, it's faster) but if you have TCP/IP installed it will work, and
also if you have IPX installed.
ADS has a plug-in called Advantage Internet Server (AIS), boy, this is a great tool, just put you ADS server in the internet running
AIS, and the same client program you use in your local area network will be using your remote data via internet, no matter where in
the world you are. this is cool

.>Is the local server working in a client server situation while developping. I mean data on Pc1 and >program on Pc2 ?
Nop, Local Server doesn't include client/server capabilities, it's only provided for you to test your programs.
>I know, many questions, but here is the place to ask so.
You can also go to : to get more technical help on this issue.

Local Server is for 32 bit only :-((
but if you have one PC like i have, use VMware to create virtual network and test your app from vmware's client OS (3.1,95,98,ME,2K,XP or even Linux). That's great! Good luck on your convertion.

I tested ADS for Win9x/Me in a stand alone PC, i conected two FW application to the server in the same machine this work, i testd transaction and work. I useed ADS 6.11 5 users Trial for win9x/me


I have installed the evaluation version of ADS 6.11 on my W2000 server. When I press CTRL ALT DEL on the server I see ADS is running
I made a small test program in FiveWin.
I found it strange that there is no point in the source code that points to the servermap were the data is stored.
The test program gives an error
"FIVEWIN veroorzaakte een algemene beschermingsfout in module herbs.exe op 0009:7DC2"
Can someone tell me what I forgot.
I can't find ideal settings for stack and heap. May be the problem is there.

I use this the check everything:
If ax_Loaded( "\\server\path\" )
rddSetDefault( "DBFCDXAX" )
ax_RightsCheck( .F. ) // by-pass NT rights checking. ("\path\" not even shared or users have no idea this path exist)
ax_AXSLocking( .F. ) // share locking to other apps
On your link:
<fivewin lib>

Thanks I think I just made my first connection to a dbf via Ads.
Every time I start the small test program my firewall tells me that"NTVDM.EXE" tries to connect to internet.
It begins with NT, so it could be a part of W2000.
Someone any idea what this is.

Remember that you can't run your program in a local drive (where are the server)


I am converting my first application from COMIX to ADS.
The orderDetail file has about 100.000 records and is indexed on 9 different indexes.
Only index 6 has a function --> StrZero(Coef,6,4)
I think StrZero() is known by Clipper and ADS.
All the others indexes consist of 1 to 3 character fields.
An important screen contains initially all de order details. The user can choose a period, client, clienttype and so on.
Every time I change something in the query I have to wait more than a minit. With comix this was only a few seconds with 3
simultan users.
Several times when asking some queries the program finisch without any error. All program screens simply disappears.
My stacksize is 10000
and the heapsize is 1024
I think I am doing something wrong but I cannot find it.

Are you opening and closing your files while you're doing your queries?
One of the things that ADS requires is that you should open your tables only once because it takes longer time to open the files
through ADS.

That depends on the contents of the query. When you query on the. When you choose a dealer the program first opens de
dealerfile. Returns the number (string) of the dealer to compare in the query. After choosing the dealer the dealer file is closed.
I try too change the concept today. Becauwe I always use a Is_Open_Dbf(file,index,...) I can change that to open all files at the
beginning and the Is_Open_Dbf() can be a select.
I Think that cannot be the cause because the Order detail file is also indexed on periode plus day. When I fill in the from-period
"20020515" 15 may 2002. The program just need that one index. It should go fast but it does not.
Anyway I will open all files at the beginning. I let you know the result.

The program is changed now. All files are opened at the beginning.
I still need 50 seconds for a simple query in 100000 records. Each record = 103 Bytes. So it is not a big one.

Are you using filters or scopes?
If you're using filters try using the ones from ADS.
If you think the problem is the strzero() index try changing that index by creating your own strzero(). However, I doubt it is the
strzero() function. I have indexes using local functions and my queries have woked fine with ADS.

> If you're using filters try using the ones from ADS.
I have changed CmFilter() from Comix into AofSetFilter()
For the complex queries I use filters because it is impossible to solve everything with scopes

I don´t agree with you. My experience is that ADS with Novell is rather fast.
And I don´t think that the right way is to open all database when you start the app. I can not imagine how you work in an event
driven environment without an oDbf-object (I use TData !) for every new dialog/window: so you must open the databases you need for
every dialog/window in a new area - or am I wrong?

Maybe I'm wrong but what I have learned from ADS it is that whenever a file is being open it takes much longer than any other driver.
In a local network environment this may not be the problem but in an wan evironment it is rather slow. Maybe in newer versions of
ADS this has been improved but I worked this with Novell ADS with version 4.0.
I agree with you that with an event driven environment files must be kept opening and closing. However, the less you keep opening
and closing the better. Also when you use the TPS with ADS you should not open any files or create any files during the transaction.

I am changing my application. That means that I am adding some new characterfields which contains expressions, so I can
index straight on that expression.
The result is very fast but it is a big change.
Maybe it is a good tip for everybody. When setting up an application build extrafields on which you can build simple indexes. It
is the cornerstone of fast applications.
I still have to change several child tables from AofSetFilter to Scopes. A simple orderdetail goes faster with scopes.
In a stand alone comix situation I could not see a difference but of course that is a stand alone situation.
Thanks to all who helped me in this beginner situation.

I think you were right from the beginning. I just remember that ADS does not support some expressions specially when you use
UDF's in your index expression. I just found this in the ADS NG for version 4.2. I think this is important to remember. I don't know if
with newer versions of ADS this can be supported.
In any case what I told you about the opening of files is also another important issue to consider.

Yes I found it. I used the function Asc() in an expression. Now it isalready working better.
Not all of the proplems are solved but ADS keeps me busy for just a fewhours and everything needs his time.
Thanks for your support.


I have ADS 6.11 , Clipper 53.b, FW 2.3 , Blinker 6.0 , TCP/IP
I made a small test program in FiveWin.
Function ax_Loaded( "\\server\path\" ) always return .F. !
during that the same in
DOS version is O.K. ( by ADSDOSIP.EXE )
"\\server\path\" is also O.K.
<fivewin lib>

never occured to me this situation. can you post that small program so we can test.

Do you have installed the comunication DLLs needed for a FiveWin app?
If so, where did you place them ?


My first Client server becoms a fact. Indeed it is going fast. But I stil have some problems.
When I keep pushing navigation buttons. PgDn of PgUp or when I am going fast through a table with scrollbars, the program crashes
without any error. The program simply disapear from the screen.
It happens with W2000 as a client and also with WME. It happens in a complex table with relations but also in a simple clientlist
that uses only 1 dbf without lookups and so on.

have some additional info on this error.
Now the program crashed but there was an error description
"ERRORDIAL (0) unrecoverable error 650 : Processor stack fault"
The word "Dial" in the error and the fact that the program tries to make a internet connection at startup makes me think that it has
something to do with the fact that the server is still a trial version.
I received a trial from ADS 2 weeks ago.

This error occurs when the errorsys does not have enough memory to show de dialog error but perhaps exist the error.log file
check these one.
On the other hand, are you using TCBROWSE? it have memory problems, use TSBROWSE instead.

here was no error log created.
I do'nt use TcBrowse()
Maybe I have to look also for an alternative error system that uses less memory.

It´s easy, make your own errorsys function displaying the error and quiting the program. Later put again the standard errorsys.

> On the other hand, are you using TCBROWSE? it have memory problems,
What memory problems?

Gustavo says that the reason I am getting a 650 is a memory fault. In this case it is not the result of using TcBrowse() because I do
not use it. I use TWBrowse and TsBrowse().
I think he means that the error system also need memory.
Interesting point is that some bugs does not result in an error-dialog but only consumes some memory. When that occurs in a loop
(maybe that is what happens in my problem situation - PGDN read several records and refresshes the screen in a loop) there is an
error from the point the program is runned out of error.
When typing this I also read Axel's answer. That is an interesting point I first go to test that.

The f*kng 5333.
¡¡Si habremos hablado por este tema!!, despues aparece A.L. promocionando no se que nuevo super browse, si le van a dar soporte como
se lo dieron al TCBrowse bien embromados vamos a estar. De no haber sido por el TSBrowse tuyo y de Manuel no se que sería de mi aplicación. Si puedes traduce esto al Ingles, que mi furia me lo impide.

sometimes Ive got the same error 650. I dont work with ADS. Maybe the reason was much traffic in the net. Dont know. But since I
link with Blinker 5.1 and increased the stacksize to 4096 I have no error 650.

stacksize: 9500
heapsize I increased to 4096

The problem is not solved but this time I have a log file
(b)ERRORSYS (0) Unrecoverable error 650: Processor stack fault
(b)ERRORSYS 0000
(b)ERRORSYS 0000
(b)ERRORSYS 0000
(b)ERRORSYS 0000
(b)ERRORSYS 0000
(b)ERRORSYS 0000
(b)ERRORSYS 0000
(b)ERRORSYS 0000
(b)ERRORSYS 0000
(b)ERRORSYS 0000
(b)ERRORSYS 0000
(b)ERRORSYS 0000
(b)ERRORSYS 0000
(b)ERRORSYS 0000
(b)ERRORSYS 0000
(b)ERRORSYS 0000
(b)ERRORSYS 0000
(b)ERRORSYS 0000
(b)ERRORSYS 0000
(b)ERRORSYS 0000
(b)ERRORSYS 0000
(b)ERRORSYS 0000
(b)ERRORSYS 0000
(b)MAIN 0101
MAIN 0158

The problem start in the line where you define the filter expression. If you are not putting any filter expression then the problem
is on TwBrowse so you will need to compile the TwBrowse with line numbers to check exactly in wich line is the error.

I have added some memory into the server. The server has now 256 MB.
It makes no difference. The problem stays.
I think the program always calls the setfilter method from TWBrowse() I have changed the program so that there was absolutely no
filter in the database.
The call to SetFilter always stays. I placed a simple Browse() after opening the file. I results in the same error.

I have a friend who had the some problem and he discovered that there is a problem in TWBrowse using NTX indexes. He moved to CDX
and solved the problem.

use already CDX.
I was using FW2.2 and I have just installed FW2.3. There is a difference now. The errorsys gives a ADS 6619 error
6619 Client comm layer was already busy with one database operation when a second database operation was requested.
So I found the nature of the error but the errorlist does not gives a solution.

I sugestt you to contact the ADS supplier. Some time ago I got these errors and was the dlls on the client side whith large databases.

Ads informed me that I have to make a ADS.INI wth contents
This does not help. Does anybody has know if there has to be a call to that INI from within FW.

As I know the .Ini does not apply to 16 bits applications.

My firewall software confirms that ADS tries to make an Internet connection when the fivewin programa starts up.
I have a full two user version installed.


Does someone use ADS server
W2000 + TCP/IP + Clipper 5.3b + adsdosip.exe ( DOS without FiveWin)
Changing compilation from 5.2e to 5.3 happened the work strongly slower.
Adsdosip.exe shows
transmission more quantity of packs with identical activities looking over the base.
The libraries Dbfaxs.lib are dated - 25.09.2001

ADS libs for 5.3 are not the same that the ones for 5.2., did you checked
you are using the right ones ?
On the other hand, what version of Clipper 5.3 are you using, service pack "a" or SP "b".

regards, saludos

Antonio Linares
User avatar
Antonio Linares
Site Admin
Posts: 27219
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

All text

Postby Antonio Linares » Wed Aug 27, 2008 7:31 am



Some days ago I bought the Alltext 4.5 vbx control (standard) and it works very well except for a detail... I doesn't know of how to print the content of the control. I am using Fivewin 1.9.5, Clipper 5.2e and Blinker 3.30

I don't know that specific control, but I guess you may try:

<oControl>:HardCopy( <nFactor> )


Can anyone tell me how can i save a five with the correct fonts in it ? I can't get the FontTableGet to work, and if i grabe the info in the ftext, it returns a none RTF format.

First in the dialog where you have defined the Alltext Vbx you have to change the property SelFtype to 13 and the you can use

oVbx:Ftext:= texto

where texto is the text you have previously stored in a memo field.

regards, saludos

Antonio Linares
User avatar
Antonio Linares
Site Admin
Posts: 27219
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

API functions

Postby Antonio Linares » Wed Aug 27, 2008 7:32 am

Windows API functions


Do you have any other function documentation about system calls ? Or is any public document on the internet where I can found this kind of information ? ... e/ControlP

This is another site for Windows api : ... /Download/


I am working on a Class for the Microsoft Crypto API for encrypting/decrypting data & files using microsofts implementation of MD5 and RC4 algorithms of RAS Data Security Inc. I need to be able to encrypt data at 128bit. I am having a problem with my first 32 bit DLL call. Does anyone have any ideas why this never returns a handle?

#include ""

#define PROV_RSA_FULL 1


Function Main()

local hCryptProv := 0

AcquireContext(@hCryptProv,'','',PROV_RSA_FULL, 0)


if hCryptProv > 0

ReleaseContext(hCryptProv, 0)


return nil

DLL32 Function AcquireContext( @hProv AS LONG ,;

cContainer AS LPSTR,;

cProvider AS LPSTR,;

nProvType AS DWORD,;

nFlags AS DWORD ) ;

AS BOOL PASCAL from "CryptAcquireContextA" LIB "ADVAPI32.DLL"

DLL32 Function ReleaseContext( hProv AS LONG,;

nFlags AS DWORD ) ;

AS BOOL PASCAL from "CryptReleaseContext" LIB "ADVAPI32.DLL"

Never messed with the Crypto API but [jump ahead, where you define AcquireContext)

Thanks for the suggestion. I forgot all about AS PTR as a type. That was it. BTW it still needs the @ though.

Now I have another problem. Here is the Encrypt Function description:

#include <wincrypt.h>

BOOL WINAPI CryptEncrypt(

HCRYPTKEY hKey, // in

HCRYPTHASH hHash, // in

BOOL Final, // in

DWORD dwFlags, // in

BYTE *pbData, // in/out

DWORD *pcbData, // in/out

DWORD cbBuffer // in




A handle to the key to use for the encryption. An application obtains this handle by using either the CryptGenKey or the CryptImportKey function. This key specifies the encryption algorithm that is used.


A handle to a hash object. This parameter is used only if a hash of the data is to be computed at the same time the encryption is being performed. See the "Remarks" section for more information. If no hash is to be done, this parameter must be zero.


The Boolean value that specifies whether this is the last section in a series being encrypted. This should be TRUE if this is the last or only block, and FALSE if it is not. See the "Remarks" section for more information.


The flag values. This parameter is reserved for future use and should always be zero.


The buffer holding the data to be encrypted. After the encryption has been performed, the encrypted data is placed back in this same buffer. The size of this buffer is specified by cbBuffer. The number of bytes of data to be encrypted is specified by pcbData. This parameter can be NULL if all you are doing is determining the number of bytes required for the returned data.


The address of the data length. Before calling this function, the caller should set this parameter to the number of bytes to be encrypted. Upon return, this address will contain the number of bytes of encrypted data. If the buffer specified by pbData is not large enough to hold the data, the function returns the ERROR_MORE_DATA error code (through GetLastError) and stores the required buffer size, in bytes, into the variable pointed to by pcbData. If pbData is NULL, then no error is returned, and the function stores the size of the data, in bytes, in the variable pointed to be pcbData. This lets an application determine the correct buffer size unambiguously. When a block cipher is used, this data length must be a multiple of the block size, unless this is the final section of data to be encrypted and the Final flag is TRUE.


The number of bytes in the pbData buffer. Note that, depending on the algorithm used, the encrypted text can be slightly larger than the original plaintext. In this case, the pbData buffer needs to be sized accordingly. As a rule, if a stream cipher is used the ciphertext will be the same size as the plaintext. If a block cipher is used, the ciphertext will be up to a "block length" larger than the plaintext.

Here is my code:

pbBuffer := space(dwBufferLen)

dwCount := fread(hSource,@pbBuffer,dwBlockLen)

Encrypt(hKey, 0, feof(hSource), 0, @pbBuffer, @dwCount, dwBufferLen)

DLL32 Function Encrypt( hKey AS LONG,;

hHash AS LONG,;

lFinal AS BOOL,;

nFlags AS DWORD,;

@cData AS LPSTR,;

@nLen AS DWORD,;

nSize AS DWORD ) ;

AS BOOL PASCAL from "CryptEncrypt" LIB "ADVAPI32.DLL"

I Get a GPF everytime I call this function. I have tried all sorts of ways of defining the function and no matter what I do I get a GPF. I have tried Padr() of the buffer. I have tried AS PTR for the @ variables. I haved Any ideas?

I'd be very intresting to see this work. Keep us posted ok?

I personally wouldn't even use CryptoApi since there are 2 keys that can break it - one at Microsoft and one at the NSA ( no such agency ). The prefered option is PGP - the choice of hackers.

Yea, except that most of the world is Microsoft based. If you want to install an app on any machine out there and know that the encryption will work stick with a standard. By the way they use RSA Data Security Inc.'s encryption which is the industry standard for encryption. I would rather go with the masses on this one than stand alone. I am being forced by our industry to prove data security and the best way is to use what microsoft has already done.

PGP works - you can download the source - and - export out of North America is now allowed.

Two things you can check:

a.- Find out if the strings have to be NULL terminated, ie, add a Chr(0) at the end

b.- Raise your heap and stack sizes in your link script. For example using Crystal or ODBC requires something like StackSize 17500 and HeapSize 4096. Of course, you'll have to play a little bit with the numbers. Good luck, since GPF when interacting with the WinAPI can be a nightmare finding. Hope you pull that stuff though before going nuts.

Here is a working example of using the Microsoft Crypto API to encrypt and decrypt a file. I will be working on this to create a class and improve its functionality. We need to encrypt/decrypt a buffer as well as a file and want to test for 128bit encryption. ( CRYPTO.PRG )


How do you create winapi.lib ? What lib it is to import ?

We do use Borland implib.exe

I know. But what dll to import ? Syntax ?

> I know. But what dll to import ?

Many of them. One for each used Windows API.

> Syntax ?

implib YourLib.lib WindowsAPI.dll


Did someone already use a tool to SPY Windows API (not windows message) ?
If so can you provide a URL or if it's a free tool you can send it by Email at

Sylvain, go to or ... there you will find many useful and free tools. gives a 'Cannot find server or DNS Error' Is this the correct URL ???

No, it's


I have FW 2.2c in Windows 98 & Outlook Express 5.5. I get a return code -1 using TESTMAIL.PRG (Class TMAIL).
On a system with Outlook 97 it works fine. In MAPI.C is loaded MAPI.DLL but on my system there is only MAPI32.DLL.

have the same problem. No need to search a mapi.dll. I took a MAPI.DLL from a Win95 CD but without success.

I have Windows 98 with Outlook 97 installed and it works fine ..... I think Mapi.dll is present as a result of Outlook 97. I have several apps that need the Mapi.dll ....... and all are working. I think the Mapi.dll is from Outlook 97 due to the date of the file
OOPS forgot to mention Outlook Express 5.5 is also present on my Windows 98 system.


If I have the name of a Windows API function, how will I know which dll it comes from?

It may seems like a "brute force" solution but it works:
Generate the DEF file for all DLLs on windows directories:
impdef.exe name.def name.dll (you may use a batch file to automatize it) and later on look for the name on the DEF files :-)

Most of the time it's indicated in the MSDN ! Wich function I can verify if I have the DLL name !

Thanks, found it it MSDN. They gave as requirement user32.lib, which I guessed meant user32.dll is the one, and I guessed right :).

Thanks, forgotten about that site.


I found API that are working well under all Windows operating system, If you are interested to received a program to test on your operating system and report the result here before I send the new gettasks.prg to Antonio. Send me an Email at I'll send it back by Email for test.

The message is:
It seems to be ok, but just a note. If you get the tasks from MS Word (Help, About...) there is lots more of DLLs and tasks.
Sorry, for sure I'm not following the idea.

The new API follow the same rules than the previous one to find the task, thetask must have a Window open in the Z order ! ;-)
The ultimate way to have the REAL result is with psapi.dll but it need a CALLBACK function and I'm not enough comfortable with C to do it ! ;-(
Wich operating system did you test ? I think it's Windows 98 because with Nt,W2k,XP and the 16 bit version of the program you'll have less task, but with the 32 bit version you have a complete list of task that have a Window in the Z order. I dind't want to change the way Gettasks() is working I just change the GetModuleFilename( GetWindowWord(hWnd,GWW_HINSTANCE) by something that is not loosing memory under NT,W2K and XP ! ;-)

After a Lot of request on my private Email asking me to publish the solution ASAP, I publish the source code for the new Gettasks.prg, just
compile it and add it to your link script to replace the Fivewin Function. Be aware that Antonio didn't review those modification and I didn't
received much feedback. But my inhouse test under 98,Nt,W2K,XP reveal NO PROBLEM AT ALL, that function won't work under 95 and lower version of Windows and for NT you need at least SP3,as stated in the MSDN library !. If you found a problem don't hesitate to report it here I'll take care of it as soon as possible, any comment and suggestion are ALWAYS wellcome ! ;-)
I tested it with Fivewin 2.3a in 16 and 32 bit and it's working very well !
Hope it will help the Fivewin community !;-)) GETTASKS.PRG

Nice work Sylvain.

Thank's Rene, your comment is always appreciated !
After reviewing the source there is a need to standardize the variable name ! ;-)
So here is the formatting correction ! ( The same name - GETTASKS.PRG )

Report for Win98SE:
Thanks for your nice job!

I would have preferred a more general working solution but nice work anyway!

I think that just adding a few IF that check the Windows version can do the trick with older operating system we can do what is in the original Gettasks() !

Right! Simple and effective!

Here you have it !, I tested it on Windows 3.11 and it's working the old fashion ! can you please test it under Windows 95 and if possible Windows ME (The same name - GETTASKS.PRG )

Enrico ask for a more generic solution there it is ! (The same name - GETTASKS.PRG )

It seem's that is a problem only With Windows 95 I'm searching the cause and will post the solution. In Windows 95 it follow the new technique but it must follow the older one !

This is the Final version also working on Windows 95, the only Windows version that isn't be tested is Windows ME. (The same name - GETTASKS.PRG )

Thank's to Enrico for his precious comment, this is the latest version of Gettask(), I removed the cTask:=space(200) from the loop and added a Task name buffer that will be initialized only ONCE if Needed ! ( no one is perfect ! ;-0 )
Sylvain Robert (The same name - GETTASKS.PRG )

This solved one of my major problem!
I never thought it gettask().
You are one of the best!

regards, saludos

Antonio Linares
User avatar
Antonio Linares
Site Admin
Posts: 27219
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain


Postby Antonio Linares » Wed Aug 27, 2008 7:32 am



Does someone have a Array2C() and a CtoArray() function that is real fast?

Patrick i use a marshall() / unmarshall() functions to convert Array->String <> String->Array .... this functions are very fast in my cases .... i found this functions on a socket sample files.....(very old sample files....) I dont remember the author but i can send them to you monday morning to check them out.

Look at the attachment. C2ARRAY() is Clipper and is fast enough. ARRAY2C() is C (source and OBJ attached). Let me know if that's what you need. ( ARAY2C1.ZIP )

Can it also store multidimansional arrays with multi type of variables? like 1,2,3,{"A","B","C"},{{1},{2},{3,4}}} and so on...

No, it handles character array only.

Look at the attachment. It's a ATOC and CTOA function fast as clipper do. BTW it works with any data type and multidimensional arrays. I hope it's what you need. ( ATOC.PRG )

Thanks, but this only works for small arrays. Because the macro can only be 256 characters long.


Is anybody has a function which can extract a unique (str) element on an array?

(Sorry for my english) Sort your Array first and scan it:
PRIVATE aArray:={{"Hi",1150},{"ABC",34},{"00",54}}
ASORT(aArray, {|x,y|x>y})
IF (nI:=ASCAN(aArray,{|uA|uA[1], cSearch))>0
I'm not sure about the sintaxis


i´ve got a strange problem browsing an array using tsbrowse or tcbrowse. compiling it as a standalone program it runs fine, but if i include
this module in a bigger application, i got the following error:
Error description: Error BASE/1449 Syntax error: &
[ 1] = C {|x| IF(PCount() > 0, oBrw:aArray[oBrw:nAt, 1] := x,
oBrw:aArray[oBrw:nAt, 1])}
The error occured in the line, the columns are added. I have no idea, why the same code worked standalone and failed in an application.
I changed the order in the link-file, but no result.
I attached my code and the error.log. I am using FW 1.95 and Ms-Link.I hope anyone can can help me.
// Modul : Rechnungsverwaltung //
#include ""
#include ""
//procedure main ()
// rechnung()
FUNCTION Rechnung ()

LOCAL oDlg, oBrw
LOCAL nNetto := 0.0, nBrutto := 0.0
LOCAL aData := {{"Artikel 1",0, 0, 8, 20},;
{"Artikel 2",0, 0, 7, 10}}

//Msginfo ("Testmodul Rechnung")
AEval( aData, {|x| nNetto += x[4], nBrutto += x[5]} )
DEFINE DIALOG oDlg FROM 100,50 TO 400, 500 PIXEL Title "Rechnungsliste"
oBrw:SetArray (aData)
TITLE "Artikel" ; // ERROR
FOOTER "Summe";
SIZE 120
RETURN (nil)
Size: 1,227,776 bytes
Max files handles permited: ( SetHandleCount() ) 255
Error ocurred at: 17.01.02, 19:51:14
Error description: Error BASE/1449 Syntax error: &
[ 1] = C {|x| IF(Pcount()>0, oBrw:aArray[oBrw:nAt, 1] :=x, oBrw:aArray[oBrw:nAt, 1])}

next curiosity, under the debugger the app runs fine, no error. without the debugger it crashes.

Aren't you using static variables in your program that are not visible to other prgs ?
Check that the statement: oBrw:SetArray() precedes columns definition. I suggest to put it inmediately after the browse definition/redefinition.
Have you tried with #include "" before #include ""?
In the command line that invokes MS-Link, check that SBrowse.lib precedes FiveWin libs.
Do you have the last version 4.0 of TSBrowse?
I strongly recommend you to use Blinker instead of Ms-Link. Let me know the result of your tests.

thanks for your tips. I am using the latest version of TsBrowse (4.0). I will check hints and report you.
> Have you tried with #include "" before #include ""
> In the command line that invokes MS-Link, check that SBrowse.lib precedes
> FiveWin libs.
I tried both, but no result :-((
Late last night I discovered a workaround, but its no solution of the problem. If i build all obj-files new, the app runs, building only the changed module, the app crashes. Very strange.

I found it, compiling the module with the /z
switch of clipper solves the problem.

Be careful because that switch suppresses shortcutting, therforesomething like this:
If a .and. b
both parts of the expression will be evaluated even if a returns FALSE.


I need help to browse an array. the array stucture is bellow(each array item has 3 value)

This is part of a program i use to browse arrays with TSBROWSE (Thank's to Manuel Mercado's great job) RC.PRG

Namy thanks

late but hopefully not too lat (had some problems with my DSL, could receive but not send), a snip of my programs.


I want to fill a multidimensional array with data from a dbf (to automatic create tsbrowse's)
When I hardcode the arry, it works the filling from the dbf is not yet working (any hints)
function NewLbx(oLbx,cType)
Local aTmp:={}
cType = upper(alltrim(cType))
// fill from dbf want work !!!!!!!!!!!!!!!!
FOR I = 1 TO 6
use lbxdata index lbxdata alias lbxtmp shared new
if !lbxtmp->(dbseek(cType))
msginfo("not found")
DO WHILE lbxtmp->type = cType
AADD(aTmp[1],alltrim(lbxtmp->head) )
AADD(aTmp[2],'"'+alltrim(lbxtmp->veld)+'"' )
AADD(aTmp[3],lbxtmp->size )
AADD(aTmp[4],lbxtmp->edit )
AADD(aTmp[5],alltrim(lbxtmp->index) )
AADD(aTmp[6],lbxtmp->centercell )
close lbxtmp
// fill will work
AADD(aTmp,{"Document","Document","Order","Klant","Toestand","Memo"} ) // 1. Hoofd
AADD(aTmp,{"Document","Datum","werkbest","Klant","toestand","memo"} ) // 2. Field
AADD(aTmp,{70,78,78,100,100,100} ) // 3. Size
AADD(aTmp,{.F.,.T.,.F.,.F.,.T.,.F.} ) // 4. Edit
AADD(aTmp,{"Factinfo","","","Factklant","",""} ) // 5. Indexen
AADD(aTmp,{0,0,0,0,0,0} ) // 6. Align Cell (0 L, 1 M, 2 R, 3 V)
FOR I = 1 TO len(atmp[1])
ALIGN DT_RIGHT,DT_CENTER,DT_RIGHT // cells, header, footer
oLbx:ACOLUMNS[I]:CHEADING := aTmp[1][i]
oLbx:SetData(I, FieldWBlock( aTmp[2][i], Select() ) )
....bla bla bla

You need to use detached locals.
Also it's better to pass the alias name to Select(), or the progam might end up looking for the field in the wrong table!
> FOR I = 1 TO len(atmp[1])
> ALIGN DT_RIGHT,DT_CENTER,DT_RIGHT // cells, header, footer
> oLbx:ACOLUMNS[I]:CHEADING := aTmp[1][i]
> //oLbx:SetData(I, FieldWBlock( aTmp[2][i], Select() ) )
oLbx:SetData( I, fillCol(i) )
> ....bla bla bla
> aTmp:={}
> return
Static Function fillCol( aLbx, I )
Return FieldWBlock( aTmp[2][i], Select( lbxtmp ) )

Function Dbf2Arr( cAlias )
Local nFields := (cAlias)->( FieldCount( ) )
Local aData := {}
Local aFields := {}
Local n := 0
(cAlias)->( DbGotop( ) )
While !(cAlias)->( Eof( ) )
aFields := {}
For n := 1 To nFields
AAdd( aFields, (cAlias)->( FieldGet( n ) )
If Len( aData ) < 4000
Aadd( aData, AClone( aFields ) )
Msginfo("Only first 4000 records grabbed")
(cAlias)->( DbSkip( ) )
If Empty( aData )
aData := { ARRAY( nFields ) }
Return( aData )


I want to save an array to disk and than restore it from disk!!!
It's a three dimension array [4,92,3]
Which function is OK to use and what the parameters to call them ?

I think Six RDD has this function.

At least you can save each single array item to a DBF (one item per record).

why don´t you save your array in a dbf and restore it from there?

Take a look in windows.prg. There are two functions asave() and aread(). ASave() translates an array to a string and ARead() does the opposite. I'm not sure if they can handle three dimensional arrays, but you may be able to modify the code to handle them.
If that doesn't work, let me know. I know I have another routine that Roger Donnay wrote years ago to save a load arrays. I will have to dig through my archives to find it.
You might also try Oasis at:

I have attached a zip file containing the 16-bit and 32-bit object code and
the source code for saving/restoring arrays. It will save and restore multi
dimensional arrays with no problems.
Works in FW and FWH. ASAVE.ZIP

regards, saludos

Antonio Linares
User avatar
Antonio Linares
Site Admin
Posts: 27219
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

AVI files

Postby Antonio Linares » Wed Aug 27, 2008 7:33 am



How can i play an avi video with a continous loop ? can i transform a animated gif in an avi video ? With what software ?

I have an answer to your first question.

> How can i play an avi video with a continous loop ?

cBuffer := SPACE(200)

DEFINE WINDOW oWnd FROM 1, 5 TO 20, 75

DEFINE TIMER oTimer INTERVAL 1000 ACTION Endloslauf() OF oWnd



FUNCTION ShowVideo()

mciSendStr( "OPEN AVIVIDEO!"+Upper(Alltrim(cFile))+" ALIAS VIDEO STYLE

POPUP", @cBuffer, oWnd:hWnd)

mciSendStr( "WINDOW VIDEO HANDLE "+Alltrim(str(oBmp:hWnd)), @cBuffer,


mciSendStr( "PLAY VIDEO FROM 0", @cBuffer, oWnd:hWnd)


FUNCTION Endloslauf()

LOCAL nLaenge, nPosition

mciSendStr( "STATUS VIDEO LENGTH", @cBuffer, oWnd:hWnd)

nLaenge := VAL( cBuffer )

mciSendStr( "STATUS VIDEO POSITION", @cBuffer, oWnd:hWnd)

nPosition := VAL( cBuffer )

IF nPosition >= nLaenge

mciSendStr( "PLAY VIDEO FROM 0", @cBuffer, oWnd:hWnd)




Does anyone know how to play one of the AVI files that shows the file copy using the VIDEO class using the system default color as the background color instead of the pink transparent color that shows now? I found a good way to display those "flying folder" avi files that are common in Win 9x. Convert the AVI to bitmaps and create a single bitmap resource with the frames appended end to end and end the name with the number of frames like FILECOPY25 . Then using the following code you can display any animation you want.

Function Animate(cResource)

local oDlg,lOk

DEFINE DIALOG oDlg FROM 10, 20 TO 18, 65 TITLE "Testing Animation"

@ 3.5, 2 BUTTON "&Ok" OF oDlg SIZE 35, 12 ACTION ( oDlg:End, lOk := .t. ) DEFAULT


return nil

Function Startup(oDlg,cResource)

local oTmr,oBmp,nFrames,nFrameWidth


oBmp:SetColor(GetSysColor( COLOR_BTNFACE ),GetSysColor( COLOR_BTNFACE ))

nFrames := val(right(cResource,2))

nFrameWidth := oBmp:nWidth()/nFrames

oBmp:lTransparent = .t.



INTERVAL 70 ACTION ( If( oBmp:nY < -oBmp:nWidth() + nFrameWidth*2,oBmp:nY := 0,;

oBmp:nY -= nFrameWidth ), oBmp:Refresh( .f. ) )


return nil

This works GREAT! No need to have AVI's or BMP's in your install directory or 25+ entries in your resource. It also solves the problem of the transparent color in the AVI. The trick was resizing the oBmp after the Activate because the SIZE x,y doesn't use pixel metrics before the paint.

Cool!! Group: attached is a bmp, try with Jeff's module. ( MOVING.ZIP )

How do we convert bitmaps into a single bitmap ? Do you mean we will have only one file intead of 25 ? nd AVI too BMPs, what tool do we need ?

You can use PSP tool to catch AVI file and save bitmaps file.

This is sort of a manual process we used

To convert the AVI to individual GIF's. We then went to PAINT and created a single BMP by pasting each GIF appended to the end. We then went to workshop and added a resource for the Single BMP. Kinda "Brute force" but it worked. Once you have build the BMP the rest is easy though.

regards, saludos

Antonio Linares
User avatar
Antonio Linares
Site Admin
Posts: 27219
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain


Postby Antonio Linares » Wed Aug 27, 2008 7:33 am



How can I print Barcodes in Fivewin 1.9.5 without a spezially True Type Font.

Try barlib.lib from Cayetano, attached you'll find it. ( BARLIB.LIB )


I purchased fivewin a few years ago and never could figure it out (it's me :-)). I just got a copy of BARLIB and want to try it in a Clipper to xBase++ program I'm working on. The barcode.prg's have #include "" in them. What I want to know before I re install fivewin just to get the header file is it the version I need ? The fivewin version I purchased is 1.9.2 and if not, how do I get the one I need :-)?

I guess you are using Cayetano Gomez BarLib, sorry, this only works with FiveWin, because it uses access to the Windows drawing api via the FiveWin Interface. If you want to use the BarLib with Xbase++, you may need FiveWin++ to make it work (personally I think Xbase++ is a good product for DOS 32 bits programming or for CGI programming, Windowing with it is a real nightmare !!!)


Did anyone know how to use BARLIB.LIB from Cayetano to print barcode

See sample anexed. ( SAMPLE1.PRG )

thanks!!!, but I do not have file, will you mind send me one.


Sono un nuovo utilizzatore di Fivewin, volevo sapere se esiste qualche libreria per i Barcode grazie a tutti (Translation?[Boris]: I am the new FW user, I need asistance using Barcode LIB, thanks to all)

I'm italian too, but please write in english (this is an english forum). It will be also more usefull for you because more people will understand your messages. About your answer, yes, you can use barcode; however you haven't to search for library functions; barcode are easily accessed trough barcode fonts. i attached here what I have about barcode fonts


You should look at Rene Pilon GX reports . he has a very powerful library for barcodes.

connect to

The barcode lib is from Cayetano and it's free.
3. Thanks for the info Ricardo, I did not know this.

Try this ( BARLIB1.ZIP )

Adolfo Lagos publish in the spanish forum this address where you can find free CodeBar fonts:


Does anyone know of a way to print barcodes via FiveWin?

In FiveWin\Samples is directory "Labels" . Here are many goods samples how to print labels with barcodes . If you want to print barcodes
with TPrinter or another printing method , then simply use one of needful barcode font . I'm using "3 of 9" ( Code 39 ) which is freeware .

There are two ways
1 use TTF FOnts with bars
2 use a library like BARLIB (its my choice)
I send you by private freeware TTF's and this library.

Hello Bingen ! If this "BarLib" is freeware , can you send me this ? I want to try this .

Ok I send you by email.
Bingen Ugaldebere

regards, saludos

Antonio Linares
User avatar
Antonio Linares
Site Admin
Posts: 27219
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain


Postby Antonio Linares » Wed Aug 27, 2008 7:34 am



It is easy to use a bitmap in a listbox.
Local Lbx2Bmp := {ReadBitMap(0,"Leeg.Bmp"),;
ReadBitMap(0,"Gevuld.Bmp") }
This can be used in a listbox.
At this way the program directory contains a lot of files. If possible I want to store all the files in a DLL or if possible in the exe.
Is this possible ?

Yes! You can add the bitmaps to a RES file (using Resource Workshop) and then add the RES file to the EXE (using Blinker's RC command).

How can I access that bitmap. Is there another function such like ReadBitmap()

You bet there's such a function: LoadBitmap(Getresources(),"bitmapname")

Yes, it's LoadBitmap().


Is possible to convert BMP to JPG in FiveWin?

Try NCONVERT.EXE. It's a command line driven utility that converts a huge number of graphic formats.


perhaps someone of you could help me:
I've just upgraded FW from v2.1 to v2.3 and as I recompile my progs, where I've coded MSGITEMS to show bitmaps in the
msgbar, I have those results:
".\bmps\Zot.bmp" TOOLTIP "About CSW..."
This doesn't work at all! The program crashes (Error.log attached)
"CSW" TOOLTIP "About CSW..."
This makes the exe work but the bitmaps are not properly shown in the bar
3. MSGITEM without BITMAP:
"CsW" TOOLTIP "About CSW..."
This works with no problem...:-(
Is this a bug in FW2.3 or there is something that escapes to me? Please help!

Please try with the file attached. TMSGITEM.ZIP
If you continue having errors please send us a little sample and a JPG showing the error.

This is a 2.2 error that curiously nobody noticed it before.
Many thanks for your feedback,

Thank you Ignacio, now it works!
I've patched the five.lib with the command TLIB FIVE +-TMSGITEM and it's allright.
But to patch fiveh.lib what do I've to use and what's the right commandline?

TLib FiveH.lib -+TMsgItem /0 /P32,,


I´m trying to put a bitmap on a MDI windows. To do that I was testing with the samples on the \fw22\samples directory, specifically with the TESTBMP3.PRG.
The program run fine until I put the MDI sentence on the define windows comannd:
DEFINE WINDOW oWnd FROM 0,0 TO 10,20 TITLE "Test Class TBitmap" // RUN
DEFINE WINDOW oWnd FROM 0,0 TO 10,20 TITLE "Test Class TBitmap" MDI // NOT RUN
How I can put the bitmap on the desk of my application like the example attached?.

Non MDI Window:
DEFINE WINDOW oWnd FROM 0,0 TO 10,20 TITLE "Test Class TBitmap"
@ 0,0 BITMAP oBmp FILENAME "..\bitmaps\Tutanka1.bmp" OF oWnd ;
MDI Window:
DEFINE WINDOW oWnd FROM 0,0 TO 10,20 TITLE "Test Class TBitmap" MDI
@ 0,0 BITMAP oBmp FILENAME "..\bitmaps\Tutanka1.bmp" OF oWnd:oWndClient ;

Now is running but not fine. Let me explain
@ 0,0 BITMAP oBmp FILENAME ..... // OK@ 40,40 BITMAP oBmp FILENAME ..... // NOT OK
The second example does not put the image on the position desired, continues with 0,0 (with clause pixel or without).
Also if I put the clause color on the command define windows like this:
DEFINE WINDOW oWin TITLE "Pruebas con BMP's" ;
the colors are ignored.


I am changing an application. The goal is to have a minimum number of files in the program directory.
One of the points is to include bitmaps in the dll of exe.
I have tried several things but it does not work
In the main prg I use
DEFINE BUTTON FILENAME LoadBitmap(GetResources(),"BROWSE") OF oBar;
MESSAGE "Lijst met rubrieken" ;
Tooltip "Lijst met rubrieken" ;
ACTION PropTab()
There is a bitmap with the name Browse in the dll. This does not work. There was no bitmap shown.
Then I tried to export the dll to a Rc and to a Res file
I added the line
Rc -K HwDev to the batch file after the rMake
This results in an error
HWDEV.RC(13) : error RW2002: File not found: DISCARDABLE
Does anybody have an idea. What am I doing wrong.

Hello, Willy!
Try following
MESSAGE "Lijst met rubrieken" ;
Tooltip "Lijst met rubrieken" ;
ACTION PropTab()
Resourse is your EXE file.

That does not solve the RC error
HWDEV.RC(13) : error RW2002: File not found: DISCARDABLE but I'vr tried to incorporate the bitmap in the dll and called it with
DEFINE BUTTON RESNAME "BROWSE" OF oBar; that works already fine

I have the same problem in listboxes.
Local aBmp := {LoadBitMap(Getresources(),"Leeg"),;
LoadBitMap(Getresources(),"Rood") }
Redefine ListBox oLBX1;
Fields ;
aBmp[Max(Q->Kleur,1)], Q->Txt2;
Headers "", "Dossiernaam";
Select Q->QId For aQ[1,1];
On Left DblClick (nRekNr := Q->(Recno()),EditJobFrm(oLbx1,Q->SetId) , QVisie(oCmb001:nAt,oLbx1,ocVan,ocTot,nRekNr) );
On Right Click EditJobFrm(oLbx1,Q->SetId);
Sizes 14, 500;
Id 101 Of oDlg
This does not work Someone an idea.


Does anyone know how to put a BMP into a dialog as a background ?

There have been several discussions about this in recent threads. Getting the bitmap on the dialog is not hard, but then you have the problem of making all the SAYs and checkbox and radio text display with transparent backgrounds. If you are willing to get into all this then review the recent threads and you will find your answers.

Unfortunately they seem not to be working. Or, at least, I was unable to obtain transparent checkbox and radio so far, even with that
suggestions... :-(

I have asked Patrick Mast how he did his dialogs (shown in another thread). Perhaps he has a simpler solution.
Don't forget we also need a transparent group too.

Let me be more clear. I don't need (until now) a transparent bitmap. I need a bitmap as a background in a dialog, where I can put my SAY's and GET's over it. If you have any suggestions, I'm waiting.

I understand what you want, but you cannot put any text including SAYs or other labels like are used with groups, checkboxes, or radios because the text is shown in a box and the box is the default dialog color. You need text with a transparent backgound so the bitmap will show through. FW itself cannot do this--you need third-party solutions.
Here is how to put a bitmap on a dialog:
function PutBmp(oDlg)
@ 0,0 BITMAP oBmp FILE "AGUA2.BMP" of oDlg ;
SIZE oDlg:nWidth(), oDlg:nHeight() ADJUST
return nil

I did it more simple.. I did NOT use transparant says.
Just be sure that the Say covers only ONE color on the bitmap. Than make the background of the Say in the same color as the area of the bitmap where the Say is on.
More samples: ... ancier.gif
I'm working on an English version of WinFakt! So you guys can try it yourself! ;-)

That's exactly what I need. Do you have any code example to show this?

redefine say oSay...
Where nRed,nGreen,nBlue are the colors of the area.
Of course, this will only work on dialogs with solid areas of color.


I am having trouble in my program where I am using LoadBitmap( GetResources(), "BMP_SYS_BRWSPOINTER" )
My problem is LoadBitmap is returning a NUMERIC value instead of a Handle Value
I can not find the problem that is causing this, has anyone had a simular problem

In Clipper, handles *are* numeric values. It's fine that LoadBitmap() returns a numeric value that is the handle to the loaded bitmap. What is
exactly your problem?

My problem is that any BitMaps that I use in a Browse to not show up in the browse
When I excute this code in my application
Test := LoadBitmap( GetResources(), "BMP_SYS_BRWSPOINTER" )
/* I get 9976 */
/* I get N */
And the browse does not display the Bitmaps
When I excute the same piece of code in one of the Fivewin examples I get this error
Error description: Error BASE/1132 Bound error: array access
Called from LOCKERRHAN(0)
Called from (b)INITHANDL$(0)
Called from TCBROWSE:PAINT(0)
Called from MSGALERT(0)
But the Bitmaps do appear in the browse (after I comment out this code) I expect that LoadBitmap should return a Poimter in memory to the BitMap and not just a straight numeric valve.
This thing driving me crazy.

the handle ( a numeric value ) is actually an address where your resource (bitmap) is loaded. in your process space.

I had similar problem.
Try to put the BMP "BMP_SYS_BRWSPOINTER" as file "B_SYS_BR.BMP" in your disk out of resources and...
hTest := ReadBitmap( 0, "B_SYS_BR.BMP" )

> When I excute this code in my application
> Test := LoadBitmap( GetResources(), "BMP_SYS_BRWSPOINTER" )
> MsgAlert(Test)
> /* I get 9976 */
> MsgAlert(ValType(Test))
> /* I get N */
This is correct. You are supposed to get a numeric value.
I am concerned at the length of your resource name. Try shortening it to 8 characters.
> And the browse does not display the Bitmaps.
Can we see your code. How are you specifying the browse?
> When I excute the same piece of code in one of the Fivewin examples I get
> this error
> Error description: Error BASE/1132 Bound error: array access
> Called from LOCKERRHAN(0)
> Called from (b)INITHANDL$(0)
> Called from TCBROWSE:DRAWLINE(0)
> Called from TCBROWSE:PAINT(0)
> Called from TCBROWSE:DISPLAY(0)
> Called from MSGALERT(0)
> But the Bitmaps do appear in the browse (after I comment out this code)
After you comment out what code?
> I expect that LoadBitmap should return a Poimter in memory to the BitMap and
> not just a straight numeric valve.
No, it is supposed to return a number.

The handle seems to be a valid one. Maybe the problem is elsewhere.

> But the Bitmaps do appear in the browse (after I comment out this code)
Which code?
> I expect that LoadBitmap should return a Poimter in memory to the BitMap and
> not just a straight numeric valve.
It's the same thing. As I said, an handle is nothing more than a numeric value.

Found it !!!!
When I define my window browse
DEFINE WINDOW ::oWindow MDICHILD FROM 0,0 TO oRect:nBottom-30 , oRect:nRight-10 ;
TITLE cTitle ;
The STYLE parameter did it !! ???
This is from some old code left in my objects
I removed it and my problem went away.
Thanks for all your help.


got this problem with win98. the bitmap which i define in a menu item seems disappearing slowly each time i move the mouse
to the item.
Any workaround? I'm using Fw2.1c, 5.3b and Blinker 6.0

Strange things with bitmaps start happening when your resource memory is low. Does the problem go away after a fresh reboot?
I am using FW2.1c Clipper 5.2e and Blinker 5.1 and I have never seen anything like that.

> low. Does the problem go away after a fresh reboot?
> I am using FW2.1c Clipper 5.2e and Blinker 5.1 and I have never seen
> anything like that.
I tested it in 5 computers and all the same results. Fading Bitmaps. Is it about stack size?

I don't know. Why don't you try changing the stack size to see if it solves the problem.
You could also create a small test program just with a sample menu. Then see if it still happens. If so, then I expect it is not stack but code, either
yours or FW or Clipper. Perhaps you could try it with Clipper 5.2e.

I tried it on 5.2e and it all the same, fading bitmaps on menu (win98). I also tried TFolder bitmap (by J.Lalin) and it has the same problem (fading bitmap). What could be wrong?

How about making a small test program that shows the problem and posting it here. I will try a test compile with my software and see if I get the same thing.

I solved the problem. And is very strange!
I compiled the program under win98 and fading bitmap disappeared!
But when i compile in Wint 4.0 SP6 and run in win98, then fading bitmap occurs. It's crazy and i don't know the cause of it.
I'll trim down the menu and post a sample. Tomorrow.

Have tried to F(ile)C(ompare) the two EXEs?

No not yet. I haven't had the time to do so, but it's not so important.

I would be looking for different versions of FW, Clipper, Blinker and any third-party libs you may be using.

FW2.1c, 5.3b, Blinker 6.0, Delphi button class, TFolder Bitmap class, TSBrowse 6, btnget class, ctrl3d fw2.1c library (does
not require ctr3d.dll), ADS 5.5 client.
I don't know which one is the culprit.


Does anybody know how to use oPrn:SayBitmap() with a bitmap stored in a Workshop DLL? Thanks for any help!

Just put the name of your bitmap resource as the third parameter.


This is a newbie question.
I am trying to draw a bitmap file on the main screen of a application with no success I have tried different samples found on the FW23 Sample directory but with no success. I am utilizing Clipper 5.3b Blinker 4.1 and FW2.3 with its latest patch. I am developing this application on a machine with XP.
Here is the code;
Static oWnd, oBmp, bSupervisor, tUserName
Function Main()
Local oMenu, oIco
Public dbDirectory, dbInDirectory
If file("System.Dbf")
Use System
Store System->DATA_DIR to dbDirectory
Store System->DATA_IN to dbInDirectory
Store "" to dbDirectory
Store "" to dbInDirectory
Set Century On
Set _3dlook On
Set Procedure to CommProc.Prg
tUserName := WNetGetUser()
oMenu := Buildmenu()
DEFINE WINDOW oWnd MENU oMenu MDI FROM 5,19 to 40, 120 TITLE "Commission Pay Program" +;
" - User logged in the system : " + tUserName ICON oIco
//@ 8, 22 IMAGe oBmp File "Icon\ams.bmp" of oWnd
//@ 5, 5 BITMAP oBmp FILENAME "Icon\ams.bmp" ADJUST SIZE 280, 200 OF oWnd
//ON CLICK ( oBmp:lStretch := ! oBmp:lStretch, oBmp:Refresh(.t. ) )
oBmp := DrawBitmap( oWnd, "Icon\ams.bmp",5,5)
Set message of oWnd to "Sales Commission Program Version 1.0" Keyboard Date
activate window oWnd valid( MsgYesNo( "Do you want to exit?") )
//ON RESIZE oBmp:Center()
I have some lines in comment where I have tried different options.

Bitmap on main window:
DEFINE BITMAP ::oBMP filename "logo.bmp" of ::oWnd
on paint drawBitmap( ::oWnd:hdc, ::oBMP:hBMPPal, nRow, nCol )

I tried the change but still the bitmap will not appear, I also change the bitmap just in case any additional help will be appreciated. Here how the code looks now; I didn't use the leading double colon because it gave me an error.
Function Main()
Local oMenu, oIco, oBmp
Public dbDirectory, dbInDirectory
SET _3dlook ON
tUserName := WNetGetUser()
DEFINE BITMAP oBmp FILENAME "logo.bmp" of oWnd
oMenu := BuildMenu()
DEFINE WINDOW oWnd MENU oMenu MDI FROM 5,19 to 40, 120 TITLE "Commission Pay Program" +;
" - User logged in the system : " + tUserName ICON oIco
SET MESSAGE OF oWnd TO "Sales Commission Program Version 1.0" Keyboard Date
ON PAINT DrawBitmap( oWnd:hdc, oBMP:hBMPPal, 10, 22 );
VALID( MsgYesNo( "Do you want to exit?") )
Return (Nil)

try the following, works on all windows flavours and harbour also.

I didn't notice that you are using a MDI window. Here is how to do it on a MDI window:
// Purpose: Draw a bitmap on a MDI Window.
#include ""
function main()
local oWnd, oBmp
local nRow:=0, nCol:=0
define window oWnd MDI
define bitmap oBmp file "backg.bmp" of oWnd
activate window oWnd;
on paint drawbitmap( oWnd:oWndClient:hdc, oBmp:hBMPPal, nRow, nCol)
return nil
Here is another way (untested by me):
MDI Window:
DEFINE WINDOW oWnd FROM 0,0 TO 10,20 ;
TITLE "Test Class TBitmap" MDI
@ 0,0 BITMAP oBmp FILENAME "..\bitmaps\Tutanka1.bmp" ;
OF oWnd:oWndClient SIZE 0,0 PIXEL SCROLL

Thanks James this worked out.


I want (depending on content current record) to place a bitmap in a dialog. I thought it would be "redefine bitmap resname 101 id 1091 of
fldetdlg when (fl:del=.T.) update". But this way it does not function. The bitmap is always visible.
Suggestion on how to do it, are welcome.

redefine bitmap resname 101 id 1091 of fldetdlg when fl:del update
Then when you change fl:del you'll need to issue a ftdetdlg:AEvalWhen().

In the mean time I got an even simpler solution, oBitmap:Show() & oBitmap:hide().
But thanks anyway.

regards, saludos

Antonio Linares
User avatar
Antonio Linares
Site Admin
Posts: 27219
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Browsing generally

Postby Antonio Linares » Wed Aug 27, 2008 7:35 am

Browsing - generaly


I have build some array and I wanted to display inside a window browse using TCColumn to add the individual column.






This work fine. But what happen is... my array consist to 15 element so I have try with a shortcut by doing this

FOR n := 1 TO 15



This do not work!

After some checking, I found that the header file for TCColumn, it is using a code block to pass in the data block. Which mean that the <n> is physically passed in without assigning any value. When it reaches the browse, only the last element is browse through the cell. I have also try this.

FOR n := 1 TO 15

bBlock := &( "{ | | oBrw:aArray[ oBrw:nAt,"+Str(n)+" ] }" )

oBrw:AddColumn( TCColumn():New( "Header", bBlock ))


This doesn't work either! It gives me a syntax error at block definition . I have also checked the bBlock code. It cannot eval a class into a code block. Can anyone help! Because if I hard code it, when there is any changes in the number of element and I have maintain the code again.

Try :

FOR n := 1 TO 15



If that doesn't work, look at your PPO file (compile with /p) and use the method call instead of the command and it should work no probs.

First, your method would not work with number. only work with string.Secondly, I do not think you understand my problem. When you issue the command below, all the code block will look like this:

FOR nSize := 1 TO Len( aSize )

oBrow:AddColumn( TCColumn():New( IF(.F., OemToAnsi( cTitle ), cTitle ) ;

{|x| IF(Pcount()>0, oBrow:aArray[oBrow:nAt, nSize] :=x, oBrow:aArray[oBrow:nAt, nSize])} ))

NEXT nSize

The problem is oBrow:aArray[ oBrow:nAt, nSize ] is in a code block. It is going to stay that way until it is eval. By that time nSize is the last number, so when you eval all the code block, the data will be showing thelast element only. nSize is the problem! Only if we can physically change nSize into the content before putting it into the code block, only can this problem be resolved. Otherwise there are no other method. Even if I change the nSize into string and use the <&>, the problem will still exist because the code block still store &nSize which refer to the same variable after the FOR..NEXT loop.

Try this one:

FOR nSize := 1 TO Len( aSize )

oBrow:AddColumn( TCColumn():New( IF(.F., ;

OemToAnsi( cTitle ), cTitle ) {|x| IF(Pcount()>0, oBrow:aArray[oBrow:nAt, &(nSize) ] :=x, ;

oBrow:aArray[oBrow:nAt, &(nSize) ])} ))

NEXT nSize

You need to use the detached locals technique, because nSize is called from ithin a code block, the value of nSize at run time will be Len(aSize) + 1 for all columns, certanly not what you wanted to. So you need a function to create that code block inside your For..Next loop:

FOR nSize := 1 TO Len( aSize )

oBrow:AddColumn( TCColumn():New( IF(.F., OemToAnsi( cTitle ), cTitle ) ;

YourCol( oBrow, nSize ) )

NEXT nSize

STATIC Function YourCol( oBrow, nSize )

RETURN {|x| If(Pcount()>0, oBrow:aArray[oBrow:nAt, nSize] :=x, oBrow:aArray[oBrow:nAt, nSize])} ))

This way nSize will retain its value (1, 2, 3, etc) for each column from your array. This is the only way to solve this problem in a For..Next loop to avoid coding each column separately.

Try this:

FOR n := 1 TO 15



PROCEDURE MyAddColumn(oBrow,n)



I've not tried it... but it should work.

I have been using this code, partly from old clipper, since four years and works fine: oLbx is a browse object, with redefine from resources or similar titulos: Array with the column titles anchos: Array with column sizes

aDatHist: Multidimensional array with the data for the columns. Each subarray has the a lenght of titulos or anchos

oLbx:SetArray( aDatHist )

FOR i=1 TO LEN(Titulos)

oLbx:AddColumn( TCColumn():New( Titulos[i], ABrowseBlock(oLbx:aArray,i,oLbx);

,,,, "LEFT", anchos[i], .F., .T.,,,, .F. ) )


This is the function you need:

FUNCTION ABrowseBlock(a, x, oLbUsr)

RETURN ( {|p| IF(PCOUNT() == 0, a[oLbUsr:nAt, x], a[oLbUsr:nAt, x] := p)} )

It really works

You have to use a "detached local." This means that n must be in its own codeblock then it will stay in scope. I don't have an example handy--check in your Clipper documentation for a description of "detached local."

Thank you very much. I have got it working already. The idea is the same by moving the code block outside the For..Next loop.


I use wbrowse and REDEFINE LISTBOX ... from a DBF. Now I want to put bitmap "Tick" or "Blank" in first column instead of "Y" or "N" . How do I do that ? I use v1.95

Very easy:

a) load your two bitmaps in a handler variable:

hBmp1 := LoadBitmap(GetResources(),"name_of_ the_bitmap")

hBmp2 := LoadBitmap(GetResources(),"name_of_the_other_bitmap")

b) and in the fields clause use the handler number instead of the field name:

REDEFINE LISTBOX.... FIELDS dbf->field, dbf->field2, IIF(deleted(),hBmp1,hBmp2),dbf->field3......


Is it possible to use a Combobox as a field of a TWbrowse if so how ?

If you mean when you edit the cells of the browse with lEditCol() - yes. Just have a look in WBrowse.prg in FW\SOURCE\CLASSES. In metod lEditCol.

Check the wdbu source code when you edit a logical field wdbu display a combobox to choose .T. or .F.


Anyone know how to overcome error "1513/Operation too complex: " when building a bLine for wbrowse? The line I am tring to compile is 1007 characters long and have 35 fields. bLine:=&("{|| {"+ cLine + "} }")

Not perfect, but you could do it like this as a last resort :

bLine:=&("{|| {MyBrwLine()} }")


RETURN {Field1, Field2, Field3.... Field35}


Please look at the .JPG: ( WIN3.JPG ) The Browse is outside of control's edge. WHY? What's the problem in my code? The Control is a LISTBOX with the follow mark check:


-Integral height

-Multi column

-Scroll bar always

The Objet in y code is a TWBrowse. What happen?


* Browse



FIELDSIZES 50,280,280,280 ;

HEADERS 'Letra','Nombres','Telefonos','Datos Adicionales' ON DBLCLICK DATTELF(OLBX,.F.) ID 413 OF ODLG

I have the same problem on some browses. Im using Visual Studio to create 16bit dlls...what are you using? Ive noticed that you can fool the listbox sometimes by setting the data is a trial and error thing. I would certainly be interested in a solution to this.

I use Borland Workshop. Yes, I try to change the data width settings. I'll try with several values. I will write here, about this, ok?

How do you create your browse control in Borland RW. To me it looks like you are using another style of control and may be this is the problem. I create a browse by clicking on the little key on the bottom of the tools then typing TWBrowse, then OK, then for the style of the new control in the properties dialog :


Only the first three parameters are coming by default. The rest is up to you. I have never had your problem.

Are you shure, the field sizes are OK? They seams too big for me. Try to reduce.

You must select customer control when add a new control( not ListBox ) to dialog and Class name is TWBrowse.

Seems to me that your mixing two different concepts. Actually it isn't your fault. The problems is the way the TWBrowse class is mapped into a command using the keyword LISTBOX. This tends to be confused with the Windows API ListBox - two different things. Make sure you're defining your browse as a Custom Control (ie the icon with the Key in the toolbar) and that you define it as "TWBrowse" - not as a standard ListBox. I'm sure that's your problem.


Still Now, I am using the clipper. So, I will try and learn for Fivewin. But, I have a problem Dos to Windows programing. Becasue, always I used the DBedit function of Clipper. So, I have a lot of problem to modified the our program. If you have a DBedit function of windows, Pls. inform me! I will purchse the function.

I can't see where is the problem. Fivewin has 2-3 ways to use a file browse on window....tcbrowse,twbrowse,listboxes.... and too many ways to edit the can edit them in the browse or you can call another window/dialog to do the modification... i find the convertions from dos to windows veeery veeery easy. :} Fivewin has everything u want about browse/edit....

dbEdit is obsolete even in plain old Clipper. Maybe the easiest way before digging into TWBrowse or TCBrowse classes, give a look at FiveWin's Browse() function. You won't be able to do fancy things but since you have the source code to it, you can learn from it.


I have a generic function to all my browses wich work with lCellStyle (very nice!!). I only have two kinds of columns: those only to show and those to show and edit. In the method bkeydown I call to my function tbrKey to trap the keys and do things with them. If you type inside a column that is only to show a dialog appear to search in that column. If you type inside a column that lets you edit, then in that cell start a get. The problem is that the character that start this get is missing. How I can start with this character and include it on the get? Keyboard() is no good solution because it generated GPFs.

Try something like



I want to blink some items on a browse. any idea?... i can imagine a way with bitmaps and a timer to change them but i guess is a very stupid way.... I have a window with a browse i browse a database file with my network users. online or not. now i have a form and i send messages from local user to another my system check with timer if the user has a message(s) waiting .... if yes i want to blink an item on the browse beside the userid column, so the user can see that he has a message waiting. now... the column can be a set of bitmaps who can change quickly so i have a blink effect, or a text blinking item....

Did something similar for a Message bar item, you have to use a timer and repaint the cells once black once white etc. This give the appearance of blinking.


I have a big problem for me. How can i create a action if i click on the headerfield of a browse like changing the index information of the field etc

Use the ACTION clause of the LISTBOX FIELDS command.

Do this :

oYour_Brw:aActions := {{|| Action_Col_1()}, {||



I have a browse in a windows with buttons: The F9 button do this sentence:


then the browse refresh and change the order but the cell lost the focus (look at the grey color): How I can get the focus on the cell again?.

Did you tried to ( order(case(indexord(),1,1,3,3,2,2,4,4,5,5,6,6,7,7,1)) , yourBrw:Setfocus() )?


a) i have a tcbrowse i am on 5th item on the browse (somewhere on the midle of my browse on the screen).now i refresh the browse with .t. my browse goes to the current record but this record goes to the top of my browse.... how can i refresh the browse with out lost the browse position? (if i delete the records i must go to the next or prev record..)

b) how can i disable the horizontal scroll bar on a browse that i create from source code? ( i try everything i can imagine... )

Play around with setting ::oBrowse:nRowPos manually


When doing a right-click on an element in the table, the cursorline isn't set to the line I clicked on. How can I do this ?

Do this :

oYour_Browse:bRClicked : = { |nRow, nCol, nFlags|

oYour_Brwse:LButtonDown(nRow, nCol, nFlags) }

which will change the highlited row to the new position when you click on the browse with the right mouse button .


As I make to magnify the height of the lines in one listbox (tbrowser). Very obliged for the attention.

You can't increase the height of the line of a list box and keep the size of the font without changes in the FW C source code. If you increase the size of the font, the height of the lines of the list box will increase automatically.


Is there a way to lock a column from being resized in the wbrowse class?

Just set ::lMChange to FALSE (this is also valid for TCBrowse)

Not for the whole browse just for a single column?

I think that can only be achieved with TCBrowse class, not with TWBrowse class since it isn't column based. To make it work under TCBrowse, when a column is frozen, it won't be allowed to be resized. Since you can only freeze columns from left to right, only contiguous columns could be flagged so as to avoid resizing. Check out TCBrowse:MouseMove().


Is there any way to speed up the Vscroll bar on a wbrowse when the DBF size is big (30,000 records) ? It is too slow when dragging the scollbar cursor up and down.

Yes! You have to modify TWBrowse class - Method VScroll. Substitute

::Skip( nLParam - ::oVScroll:GetPos() )


( ::cAlias ) -> ( CmxKeyGoTo( nLParam ) )

or the xxxKeyGoto() function provided by your RDD.

TWBROWSE is a general CLASS to work with DBF(s) , ARRAYS, Objects and is not posible to put a special code for manage CDX o NTX RDD(s) I thing that is better solution to use a codeblock with the best operation to jump over desired records like

::bJump = {|cAlias,nRecno|(cAlias ) -> ( CmxKeyGoTo( nRecno ) )}



Since Windows treats the 'thumbpos' of the veritcal scroll as an integer, you will always have problems once your database exceeds 32,367 records. You should consider

oBrw:blogiclen:= { || min( 32000,lastrec() ) }

when defining your browse, or consider changing the scrllbar class to accomodate large data files.


How to size a browse to just fit in a dialog without using a resource in a DLL. I already try GetCoors(), GetClientRect(), GetWndRect() and oWnd:CoorsUpdate()

? oWnd:nTop

? oWnd:nBottom

? oWnd:nLeft

? oWnd:nRight

from EMG, but the browse does not fit. It oversize the dialog.

Can you be more specific about your problem. It seams to me now, you have the same problem I as have. My question is: do you create browse from RESOURCE (.RC or .DLL) or you put it on the dialog with @ y,x commands? It is important. If I don't use resources, I can fit browse without problem, but if I use resources, then there are problems, browse doesn't fit always in the dialog! The difference arise when I change the system settings related to the font sizes! (Setup-display-settings-font size).


FUNC zAdjDialog( oDlg, oWndMain )

* Function..: Ajust and position Dialog in size of window parent

* Parameters: oDlg - your dialog

* oWinMain - window parent

LOCAL nMsgHeight:= 0

IF oWndMain:oMsgbar # NIL

nMsgHeight:= oWndMain:oMsgBar:Height()


oDlg:SetSize( ;

oWndMain:GetCliRect():nRight - ABS( oWndMain:GetCliRect():nLeft ), ;

oWndMain:GetCliRect():nBottom - ABS( oWndMain:GetCliRect():nTop ) +

nMsgHeight ;


oDlg:Move( oWndMain:nBottom - oWndMain:GetCliRect():nBottom - nMsgHeight ,0 )


FUNC zAdjControl( oCtrl, oWinDlg, nTop )

* Function..: Adjust control in window/dialog

* Parameters: oCtrl - your control

* oWinDlg - window/dialog parent

* nTop - Top of control

LOCAL nMsgHeight:= 0

IF EMPTY( nTop )

IF EMPTY( nTop:= ABS( oCtrl:nTop ) )

nTop:= 0



IF oWinDlg:oMsgbar # NIL

nMsgHeight:= oWinDlg:oMsgBar:Height()



oCtrl:SetSize( ;

oWinDlg:GetCliRect():nRight - ABS( oWinDlg:GetCliRect():nLeft ), ;

oWinDlg:GetCliRect():nBottom - nTop - nMsgHeight ;



oCtrl:SetSize( ;

oWinDlg:GetCliRect():nRight - ABS( oCtrl:nLeft ), ;

oWinDlg:GetCliRect():nBottom - nTop - nMsgHeight ;



Maybe you should consider DIALOG metrics (borders, title-bar, etc.) and subtract them from total size.


Can anyone provide a sample piece of code for finding a record in a browse.

At the moment I have a browse displaying customers in account order , when the user hits the find button , the index is changed and a get is placed below the browse for the user to type in the customers name , as each letter is typed the browse moves to the required record - but if the user makes a mistake and uses backspace the whole search messes up. Anyone got a better solution.

// sample of present code

REDEFINE GET oClient VAR cClient ID EditFndClnt UPDATE picture '@!' color(GETCOL)

oClient:bKeyDown := {|nKey|cClient+= chr(nKey),oBrowDlg:Update(),FndClnt(oCust,cClient,oLbx),;


oClient:bLostFocus := {||oClient:Hide(),cClient := " ",oClient:SetPos(0),;


lExit := TRUE,oBrowDlg:end()}

static function FndClnt(oCust,cClient,oLbx)




Try adapting the function attached.
/* DbSearch() performs an incremental search on a character field in a database indexed on that field and visualized with TWBrowse or TCBrowse. After one second since the last keystroke, the seek is restarted.



oBrw:bKeyChar := { | nKey | IF( DbSearch(nKey,oBrw), oBrw:Refresh(),) }

Note: You must define two public or static vars as follows:

PUBLIC cArgume := "", nSeconds := SECONDS() */

FUNCTION DbSearch(nKey,oBrw)

LOCAL cKey := UPPER( chr(nKey) ),;

nRecno := RECNO(),;

nLapso := SECONDS() - nSeconds,;


cArgume := IF(nLapso > 1 .OR. nLapso < 0,"",cArgume)

cArgAnt := cArgume

cArgume += cKey

IF !DBSEEK(cArgume)

cArgume := cArgAnt


nSeconds := SECONDS()



IF !(RECNO() = nRecno)


nSeconds := SECONDS()



nSeconds := SECONDS()


Have you tried my TSearch class? You can get a copy at my FiveWin page at: ... rogram.htm It is a popup search box with dynamic searching as you described, but the backspace works too. I call it from a buttonbar button on a browse. I think there is some example code in the zip file.


I have written a few (small but stable) Clipper 5.2e for DOS applications for various clients (I run a small Networking Company inSouth Africa). I have been approached by one of my my larger clients to write an application for them but the main criteria is that is runs under Windows 98. I have downloaded the demo version of Fivewin and would like to purchase the latest version and use this for my application. Before I do this, however, I need to know that I will be able produce the results (as I have never written any application for windows).

I therefore have been testing the samples etc. and tried to write an extremely simple bit of code just to scroll through a database (see below) but I am getting strange results and I'm not sure why.

In the code below the idea is to click on the '>>Next' and '<<Previous' buttons and display the two test fields. In DOS this would be a breeze but for some reason (in this example) each time I click on either '>>Next' or '<<Previous' the programs seems to keep a history of the records previously used and each time one of the buttons is pressed it seems as though my application displays each previosuly viewed record in quick succession and then stops at the correct record and displays it (it is definately scrolling through the database as I can see my HDD light flickering as I click on the aforementioned buttons). Is this a windows anomaly or do I just not understand the concept of using dialog boxes and button bars etc. Obviously the more records you view the longer it takes to print the results as it appears to start at the first results displayed and sroll through each previously displayed record before displaying the correct information. I have noticed, however, that it does not start at the first record in the database but at the first window displayed ie. if you are at the beginning of the file INVOICE.DBF and press the '<<Previous' button say 20 times and then the '>>Next' button it will quickly display the first record in the database 20 times and then display the next (and correct) record.

Try this:

@ 5,1 BUTTON '&<<Previous' OF ODLG SIZE 80, 23 ACTION ( DBSKIP( -1 ), ODLG:Update() )

@ 5,20 BUTTON 'Next&>>' OF ODLG SIZE 80, 23 ACTION ( DBSKIP(), ODLG:Update() )

@ 7,20 BUTTON 'En&d' OF ODLG SIZE 80, 23 ACTION EXIT()

@ 2,1 SAY 'Invoice Number ' + STRZERO(INVOICE->IVREF) UPDATE

@ 3,1 SAY 'Invoice Remark ' + INVOICE->IVDBREM UPDATE

Take a look at the \samples directory. You'll find several small examples about almost everything that you can do with Fivewin. That will speed up your learning curve.

I tried your code and it works perfectly fine for me. You may be interested in my "Introduction to FiveWin" article located on my web site (see below).

You should look into a resource editor. Borland's Workshop is very used by the FW community. It allows you to draw very nice screens including buttons, icons ... You will only have to REDEFINE the buttons, and the actions to be performed. FW is an excellent tool for clipper programmers.


I need a Filtered Browse better than the LISTBOX with the clause SELECT (so slow).

You can use a conditional index or the Tdbf class with the setscope() method.

use class tcbrowse and use method




not very fast, but resolve problem. you see example ( BRWSIP.PRG )


(alias())->( dbClearIndex() )


TO cNomeNtx ;

FOR cCondFor

IF USE COMIX3 try this

cKey := "0001"

PlanPazi->( cmxClrScope( 0 ) )

PlanPazi->( cmxClrScope( 1 ) )


PlanPazi->( cmxSetScope( 0, cKey ) )

PlanPazi->( cmxSetScope( 1, cKey ) )

PlanPazi->( dbGoTop() )

while PlanPazi->( ! eof() )


PlanPazi->( dbskip() )



Question (Probably posted many times) In table view, my numbers are proportionally and not nicely ailing. I need to set a global font for doing it, but How ? The Ng's are not clear for me (use negative number ?) Please, post the syntax.

Courier is not a proportional font. Try this.

DEFINE FONT oFont NAME "Courier" SIZE -0,10

If you are referring to TWBrowse, try setting oBrw:aJustify. It's an array containing a series of logical values, one for each column. True value means right alignment (good for numbers).


When adding a record to a browse, the browse repositions so that the new record is the only one displayed. Does anyone have some hints on having the record added to the bottom of the existing list without scrolling all other items out of view.

Try this







LOCAL nLastRecno:=0,cOldOrder:=( cAlias )->( OrdName() )

( cAlias )->( DBSETORDER( 0 ) )

( cAlias )->( DBGOBOTTOM() )

nLastRecno:=( cAlias )->( RECNO() )

( cAlias )->( ORDSETFOCUS( cOldOrder ) )

( cAlias )->( DBGOTO( nLastRecno ) )

RETURN nLastRecno

I sending a BrwBottom() Function Which is your want :-)

Function BrwBottom( oBrw )

local nSkipped

local nLines := oBrw:nRowCount()

local n

local bChange := oBrw:bChange

oBrw:bChange := NIL


oBrw:lHitBottom = .t.

oBrw:lHitTop = .f.

Eval( oBrw:bGoBottom )

nSkipped = oBrw:Skip( -( nLines - 1 ) )

oBrw:nRowPos = 1 - nSkipped


for n = 1 to -nSkipped

oBrw:DrawLine( n )

oBrw:Skip( 1 )




if oBrw:oVScroll != nil



oBrw:bChange := bChange

if oBrw:bChange != nil

Eval( oBrw:bChange )


Return nil


Anyone have a way to browse an array on resource bitmaps. i can't seem to get it at all <ok so i'm stupid>

Here is somewhat of an answer. To load the resource bitmaps:

aadd(aBmp, loadBitmap( getResources(), "CUSTOMER"))

Then use a standard listbox with an array. If the data isn't character, listbox automatically recognizes it as a bitmap.


Hi for all ! I have a problem with Dialog and Browse coordinates .Here is the source code

local oBut

local oDlg

local nHorRes := GetSysMetric( 0 )

local nVerRes := GetSysMetric( 1 )

// Dialog window with coordnates .

DEFINE DIALOG oDlg FROM 0, 0 to nVerRes - 100, ;

nHorRes - 50 PIXEL TITLE 'Browse dialog'

// Here I want to create column browse with less cooordinates

@ 0, 0 COLUMN BROWSE oBrw ALIAS GO SIZE oDlg:nRight - 10, ;

oDlg:nBottom - 50, nRow PIXEL OF oDlg



// At the bottom of dialog window I want to put some buttons .

@ oDlg:nBottom - 25, 10 BUTTON oBut PROMPT ' ... ' ;

SIZE 80, 12 PIXEL OF oDlg ACTION but_push1()


My problem is that Browse coordinates don't appears trully . I can't understandant in which way I can operate with Dialog widow and Browse control sizes . The sizes nVerRes and nHorRes work OK and Dialog window I create for size which I want . But the controls objects in Dialog box like Browse , Buttons and etc . did not understand oDlg:nTop ,oDlg:nBottom or etc. I will be thankfull for any help .

Try using oBrw:Move( etc. ) in ACTIVATE DIALOG's ON INIT clause.

Do the following and it will work well

a) Create all your controls without worrying about position and size in your window definition ie.

@ 0, 0 control ::oControl1 .......................... SIZE 0, 0 PIXEL

Use the pixel clause for all controls

b) Add a bDlgInit as follows: oDlg:bDlgInit := {|| ::PositionDlgControls()}

METHOD PositionDlgControls

::oControl1:Move(10, 10, 60, 18) // Top, Left, Width, Height

::oControl3:Move(32, 10, 60, 18)

::oControl4:Move(32, 10, 60, 18)

::oControl5:Move(32, 10, 60, 18)

::oControl6:Move(32, 10, 60, 18)

etc etc etc etc

return nil

This works very well as all your positionaing and sizing for all controls is done in one place, making it much easier to do You must NOT size and position your controls before the init of the dialog, other wise the coordinates are all weird and will confuse the hell out of you


The code below doesn´t work because when bskip is called after a couple of times the VAR Linha is NIL causing the error. Can someone help me solving this problem ? Code :

LOCAL nRegistos, Linha := 1

Nregistos := RegistosPara(mbrowse)

mbrowse:bgotop := { || DBGOTO(Nregistos[Linha := 1] ) }

mbrowse:bobottom := { || DBGOTO(Nregistos[Linha := LEN(Nregistos) ] ) }

mbrowse:bskip := { |nanda| ChavePara(nanda, Nregistos, @Linha) }

FUNCTION Chavepara(nanda,nregistos,linha)

LOCAL nandou

nandou :=0

* movimento dentro de gama aceitavel

IF Linha + nanda < 1

* passei topo do bloco !

nanda := - Linha + 1

ELSEIF linha + nanda > LEN(Nregistos)

* passei o fim do bloco !

nanda := LEN(Nregistos) - Linha


Linha += nanda

nandou := nanda

if nregistos[linha] > 0

DBGOTO(Nregistos[Linha] )



>mbrowse:bobottom := { || DBGOTO(Nregistos[Linha := > LEN(Nregistos) ] ) }

Isn't this supposed to be "bGoBottom"?

That´s right but but in the program that is correct. What I pretend to know is that if this is in fact a valid code just like it is in standard clipper. When buiding the array of records and display it the 1st time everything works weel, but when I move the browse cursor it immediatly gives an error. I´ve found out that the VAR Linha in the block

mbrowse:bskip := { |nanda| ChavePara(nanda, Nregistos, @Linha) }

is becoming NIL but I can´t find why. I can´t see where in this code the value is changed to NIL. Maybe you could give a clue.

I don't understand your using Linha:= as an array postion. This will return .T. or .F. not a number.

>>mbrowse:bgotop := { || DBGOTO(Nregistos[Linha := 1] ) }

If you want to go to the first record and set Linha to 1, then I would do it like this:

mbrowse:bgotop := { || (Linha:=1, DBGOTO(Nregistos[Linha] ) ) }

> > mbrowse:bgotop := { || DBGOTO(Nregistos[Linha := 1] ) }

> If you want to go to the first record and set Linha to 1, then I would do it

> like this:

> mbrowse:bgotop := { || (Linha:=1, DBGOTO(Nregistos[Linha] ) ) }

The two expressions are semantically equivalent.


I would like to shift the position of an item in wbrowse with drag & drop. Up to now I have used an indexed field with the row-number. I mark the line which I want to transfer with the left button, then I click the right mouse-button to select the line. Afterwards I again mark the space where I want to insert the line with the left mouse-button, and finish the change with a right click. But I think this is not the usual procedure. So I tried with



But bLButtonUp is only sending back the row in pixel. Can someone tell me how I know how to find the record-number of the line?

This might help, get text row from pixel row

METHOD nClickRow ( pnPixRow ) CLASS qBrowser


return browse row matching pixel row


return nWRow( ::oBrw:hWnd, ::oBrw:hDC, pnPixRow, If( ::oBrw:oFont != nil, ::oBrw:oFont:hFont, 0 ) )


WBrowse. How to make headers active ? Meaning, if I click a header then something can be executed (Mostly used for index order related to that column)

oBrowse:aActions:={ {|oBrw,nRow,nCol|MsgInfo("You pressed the 1st column")},;

{|oBrw,nRow,nCol|MsgInfo("You pressed the 2nd column")}}

Thanks for the hints. Yes it goes now. Any chance we put a bitmap on the headers ?

Take a look into CanalFive Grid, quite powerful and amazing way to make your data look sharp !!!! check at:


do you think that it is a bug or my fault?



if i put a scop on a dbf and if there is no record matching the scop then my wbrowse is empty, so all is ok (so the scop is "working") but if i add a record, then delete it my wbrowse show me the deleted record NOT Normal!! if i add a new record then the wbrowse show the new record (and no more the deleted one) any idea?

It is normal - after you delete the record - do a DBSkip(0) on the work area. The reason you still see the deleted record is because you have not moved from that record yet...

i see the deleted record even if i close the dialog and return after in it

I suppose SET DELETED is on?

yes sure!

the proof is that if there are two records matching the scop one record not deleted and one record deleted the only record that i see in the browse in the not deleted the strange thing is if the only record matching the scope is a deleted record, then it appears in the browse


Is there any way to create relation on browse with arrays? for example i have 2 arrays with this records

Array(a) Array(b)

{"Test1",100,200} {"Test1",1000,2000}

{"Test2",200,200} {"Test2",50,100}

i want to create relation with items Array(a)/First Item & Array(b)/First Item ...

b:nAt:=ascan(a[a:nAt,1],b) ???

I tried to replace TWBROWSE in an app I'm working on with TSBROWSE. When compiling, I get: (14) "Fatal C3048 Preprocessor table overflow". It works fine using TWBROWSE.
My includes are ordered as follows:
Any idea what to try other than reducing number of includes, which can't be done with the current form being displayed.

Whoops, I meant TCBROWSE, not TWBROWSE.

Try by including the folowing lines at the begining of your program:
#define _DDE_CH // if you don't use DDE in your program
#define _VIDEO_CH // if you don't use VIDEO in your program
#define _TREE_CH // if you don't use TREE in your program
#define _ODBC_CH // if you don't use ODBC in your program
#define _OBJECTS_CH
#include ""

We have the same problem. We compile the module with Clipper 5.2e and linked it with other modules compiled with Clipper 5.3b. It worked fine But with "#define" thing, we completely compiled our modules with 5.3b.
What causes these? Is there any other way? (like for example i'm using all those objects)

Guess you're using Clipper 5.3. Either copy and comment out some of the rarely used #includes at the top:
#include ""
#include ""
#include ""
#include ""
#include ""
#include ""
#include ""
or add stuff like the following BEFORE #includeING
#define _FOLDER_CH
#define _TREE_CH
and so forth.

Can you move some sections of code into separate PRGs? Like the tree for instance?
Alternately, you could move the tree into a separate file, preprocess it and put it back (and thus be able to remove the ch include).
I think if you can free up more RAM it would also help.

This is a single module from the others that handles user/group security system, and I'm using a tree to select from. Guess with a little work I could break it into another module. What do you mean on preprocessing it in another file and then putting it back.... I don't quite understand what you mean exactly. I'm willing to try anything to make it work.....

The ch files are used to translate a lot of the Clipper and Fivewin syntax to other more arcane functions and OOP calls. So, for instance all your tree syntax is translated into class syntax. You can get the preprocessor output by compiling with Clipper using the /P parameter.
clipper myapp /p
The output file will be the same name as the PRG but with a PPO extension.
Now if you have a stable section of code, like the tree, you can copy out the tree section from the PRG and paste it into a temp PRG file, preprocess it, then copy it back into the original PRG (I would leave the original code in but comment it out). Now you can also comment out the #include "" since this code has already been preprocessed.
This is not an elegant solution. If you need to change the code in the preprocessed section, you have to go through all this all over again. The
better solution is to move sections of code into other modules.
I don't know how you do things, but I have seen entire large applications written in 1 or 2 PRGs. This is when you are going to really get into
trouble with preprocessor overflows. My applications are more likely to be 50 PRGs. I program in OOP syntax which promotes the use of smaller PRGs. OOP also makes it is also easier to break your code down into smaller modules since you can pass entire objects around (containing lots of code).

Ok, I understand what your telling me now..... I'll look into that solution to see if I can break my prg down a little more. I do as you on breaking my code into modules. I typically have a module for each type of action in my prg and use a lot generic functions to handle actions used across many modules. I haven't used a lot of OOP for each module, though I know I should. This module is rather large because it does a lot, but I think I can break it down some.

Once you start using OOP you will quickly wonder how you ever did without it. There is an article on basic OOP on my website (see URL below).
To get you started thinking about it, imagine having a class for each business object somthing like this:
class TCustomer from TData
method new
method add
method edit
method browse
TData is my enhanced database class. After creating the above you can just do:

define button of oBar... action TCustomer():new():browse()

to get a child window browser. On that window you can have add, edit, delete buttons:
define button of oBar action ::add()
define button of oBar action ::edit()
define button of oBar action ::delete()
So simple!
And you can pass the entire object around:
oCustomer := TCustomer():new()
Then within the whatever() function you can call oCustomer:edit() or oCustomer:print(). You'll love it.

Thanks for the reply Manuel and Luis. I knew that was one thing to do, but in my old age it slipped my memory. What little is left. <G>


Hi FW users ! I want to make use possibilities of TcBrowse Seek and etc methods . But in FW\samples directory I did not found any sample with this . I'll be thankfull , if you can send me any sample how to exhaust oBrw:Seek , oBrw:ResetSeek and etc methods . And another question is about TcBrowse aActions data . How to make codeblocks for TcBrowse columns and then how to use them ?

Did you look at TestTcbr.prg? It shows quite clearly how to use the seek feature inside TCBrowse.

I'm searching how to select some rows with mouse or Shift+arrows or Ctrl+push in TcBrowse class . As I saw in ListBox class this
possibility is , but in TWbrowse and TcBrowse - no . Maybe is another solution to do this ? May thanks for ant advice ! With best regards !

Here is a message from my archives telling how to do this:
I tried it with arrays... And it works !!!
Then, I thought, if I can do it with arrays, I should be able to do it with a file in a TWBrowse. I did it !!!
By adding a new field to my database, I update that field when I select the record. When the field is updated, I also created a oLbx:Pane(IIF field = .T., RGB(red), RGB(blue))... Works even better... I can now go to the database and process all records with this field at .T.


I'm using oLBX:bChange := { || ShoInvRec() } to display some data in the dialog box that is associated with the current record in the browse.
I know it is evaluating this function for every record in the database. As I scroll down the list, I can see the associated data scrolling
through until it reaches the current record.
My question is how can I control the scope so that it evaluates only the current record? Or, can I incorporate the function in oLBX:bLine?

I do this
redefine get oG1 var cName id ........
redefine listbox oLbs fields DBF1->number, ....... on change SeekAnyData( )
function SeekAnyData( ) // Seek the key number into MyFile and display it in oG1
cName = MyFile->Name
return( Nil)

In only my third week of using Fivewin, I'm still Jimmy source code not Jimmy resource editor, but I think I follow what you are saying.
> redefine get oG1 var cName id ........
First define a Get object with the data I want to display.
redefine listbox oLbs fields DBF1->number, ....... on change SeekAnyData( )
Second, use the ON CHANGE clause to call the function.
> function SeekAnyData( ) // Seek the key number into MyFile and display it
> in oG1
> MyFile->(Dbseek(DBF->Number))
> cName = MyFile->Name
> oG1:Refresh()
> return( Nil)
Finally seek the key for the record, reinitialize the GET vars and then refresh the oGET.
I see what you're saying but why do we seek at all? I thought we were already positioned on the appropiate record.

I followed your suggestion, but my oGET:Refresh() doesn't seem to be working. I posted a new message with more detail.
Thanks in advance for any suggestions.

Try this:
redefine get ....... of oDlg UPDATE ......
Change oGet:Refresh( ) to oGet:Update( ) or oDlg:Update( )


I can't seem to get my GETs to be repainted as I scroll through my dbf. here's what I'm doing:
// first I load my memvars from the database
// then I do my GETs
@row,col get oGET VAR mITEMCODE pict ... of oWND
... more gets ....
// then I do my LBX
@row,col listbox oLBX ...
// to repaint the GETs, I use:
oLBX:bChange := {|| LoadGets() , oGET:Refresh() }
I'm certain that LoadGets() is initializing my memvars properly, but oGET:Refresh() doesn't seem to be working for me. I'm sure I must be leaving something out.

I use this in my code.
1. put your get object in an array
aObj := { oGet1, oGet2, oGet3 ... }
on your bChange,
oLbx:bChange := { || DoRefresh(aObj) }
2. create a function with parameter to hold aObj.
function DoRefresh(aObj)
local i
for i = 1 to len(aObj)
return nil
... or if you want more complex, use oGet:VarPut() to update the object b4 refreshing the obj.


I have a listbox (Wbrowse), i want to drag a line to an other line. Swap between line 3 and line 5.
I begin the drag on line 3 and drop on line 5. The start line is found with oLbx:nRowPos, but how can i identify the drop
line ?? I have the var nRow but is in pixel, or how can i convert the nRow in nRowPos ?

Use NWROW() function (look inside WBROWSE.PRG for a how to use sample).


I have an array wich is filled from a dbf off 9 fields depending on the configuration wich can be changed the record amount is 14. The stucture of the browse MUST be downwards the fieldget( 1....9 ) and as column the records.
i create a dialog and then the column browse and here is the problem.
@ 1, 2 COLUMN BROWSE .....
oBrw:SetArray( .............
Then i want to do something like this :
For n := 1 To Len( aArray )
Next n
This doesn't work :(
is there a method to work around this problem ?

Remember the array you will be browsing has to be a nested array, not a simpleone.
That is it must be like this
{ { field1, field2, fieldN } ,;
{ field1, field2, fieldN }... }
In which each subarray is the "record" to be browsed.
If you array is like this:
{ field1, field2, fieldN }
That's why nothing is browsed.

Your correct Luis, but the array is correct while when i define :
this works but i don't know how many cols there are since it is config dependable so i thought
For n := 1 To Len( aArray )
should do the trick but it won't
Thanks anyway for the responce

your trouble seems to come from the 'detached local'-problem. Please have a look to the following source. May be it helps.
STATIC gaStatArr := {;
{ "Line 1", 12345.67, 123 },;
{ "Line 2", 12345.67, 123 },;
{ "Line 3", 12345.67, 123 },;
{ "Line 4", 12345.67, 123 } ;
LOCAL aHeader := { "Header 1", "Header 2", "Header3" }
LOCAL aSize := { 20, 20, 40 }
LOCAL aPict := { "@!", "@E 999.99", "999" }
oBrow:SetArray( gaStatArr )
for n := 1 to len( aHeader )
oBrow:AddColumn( TCColumn():New( aHeader[ n ], MakeBlock( n, oBrow ), aPict[ n ],,, If( !.T., "LEFT", Upper( "RIGHT" ) ), aSize[ n ],
.F., .F.,,,, .F. ) )
STATIC FUNCTION MakeBlock( n, oBrw )
RETURN ( { | x | if( pcount() > 0, oBrw:aArray[ oBrw:nAt ][ n ] := x, oBrw:aArray[oBrw:nAt ][ n ] ) } )

Should've thought of that... Detlef hit the nail right in the head. You need to use detached locals to solve your problem.

Thanx Luis and Detlef for the responce, i tested it yesterday and it works like a charm :-)), Now i got it working like i wanted but the most important question remains why do we need to use detached locals for it why cant we do it like the first thought of mine in a loop.

Because the loop counter got a fixed value at the end of the loop. Such value is the FOR statement upper limit plus one.

You should get yourself hold of Rick Spence's "Clipper 5.2 Power Programmer's Guide" if you want more insight on Detached Locals and other Clipper's stuff. (Enrico's explanations is just fine)


In there are an " #translate VALID ...... " defined. Help needed please!
If this, the valid-clause of an GET or a DIALOG are not ok when the clause are in the form:
....VALID if(xy=z,.T.,.F.) or ...VALID if(xy->(dbseek(z)),.T.,(msginfo("Not OK"),.F.))
In this case, there are both results of the if() evaluated! If I disable this directive, all is OK.

I don't understand what you mean exactly
1- What version of tcbrowse are you using (ie if it's FW original, from which version; if it's the one I changed, what date is it from)?
2.- Can you post the whole line where you are using the VALID clause since the snippet isn't at all clear, because it seems you're using the VALID keyword twice
In any case the first valid should be simplified just as
VALID ( xy == z ) // the if() is redundant

Guenther refers to a #xtranslate statement in which comes from original FiveWin version since 1.9.5 ( or prior versions, I don't know ).
Inclusive the class you modified, comes with that statement, and more, TSBrowse also preserves it.
I actually haven't ever used such command. I left it there for compatibility.

I now realize what he meant.
I've never used it ever either, but certainly seems to be not very useful and quite obnoxious.


When I use the for to clause in a browse, the record pointer is always on the first record of the scope. I want to open such a browse but the last record should have focus.

did you try "GO BOTTOM" before opening the browse?

ON INIT ( oBrw:nLen := 1, oBrw:GoBottom() ) ;
ON PAINT ( oBrw:SetFocus() ) ;

Ok, I've just tried and that works fine


This change was brought on by a funny, which has now bugged me long enough.
When moving your mouse around the browse, it changes to a left-right cursor when you are on top of a column boundary. If your last column is defined narrow enough, it would do this somewhere inside the last column.
I've changed the mousemove method inside wbrowse to counter this behaviour.
METHOD MouseMove( nRow, nCol, nKeyFlags ) CLASS TWBrowse
local nColPos := 0
local aColSizes := ::GetColSizes()
if ::lDrag
return Super:MouseMove( nRow, nCol, nKeyFlags )
if ::lCaptured
::VertLine( nCol )
return 0
if ::lMChange .and. AScan( aColSizes,;
{ | nColumn | nColPos += nColumn,;
nCol >= nColPos - 1 .and. ;
nCol <= nColPos + 1 }, ::nColPos,Len(aColSizes) - 1 ) != 0
Super:MouseMove( nRow, nCol, nKeyFlags )
return 0


TwBrowse Release Candidate I (beta) Harbour compatible available from:

There is no source or no documentation with it. How should you expect us to test it? ;-)
WHY another browser? What is better in this browser?

Patrick, is the same browser, but 100% compatible with Harbour. In few days, Hernán will put in its Page, the Final version.


I use several 'redefine brose ....' and more or less by accident I found some strange things.
e.g. I had a browse which enabled about 40 lines, while at that time the databse only has about 15 records. Things like pageup/down (and similar went weird, if I clicked on the place of an empry row, a row (identical to another) would appear. And so on.
All this went away the moment I changed the height (in the resource) of the browse and increased the number of records.
is there some rule that a browse may not have more than X lines?

Not at all. It may have as many rows as needed.
Do you have deleted records ? If so, please remember that you have to set <oBrw>:bLogicLen to return the proper amount of
records (without the deletes ones).

> Do you have deleted records ?
it is in a test situation, it happens often that there are even more deleted than actual records. It would explain, that at a fresh start (only adding) all is fine.
>> set <oBrw>:bLogicLen
Also if all I do is " redefine browse obrw ....." and no special clauses whatsoever?


I have a question that I tried many way to keep a numeric value right in TWBrowse or TListbox but it didn't work. I need like PADL(n,w,d) function or Str(n,w,d) function. Thanks in advance for any help,

In TWBrowse, set the aJustify elements for the numerics to True, like so:
oBrow:aJustify := { .F., .F., .T., .F., .T. }
Those cells will now appear right-justified.

I use "align right" for that.


I try to use 2 TBrowse object and 2 alias from 1 file. I use cmxsetscope() for query database. When I click on left browse but right browse do not query correctly.
Clipper 5.2e, FW 2.0d
index expression is GROUP+CODE
'M ' 'CAR' 'CAR name'
'CAR' 'TOY' 'Toyota'
'M ' 'PEN' 'PEN brand'
'CAR' 'HON' 'Honda'
'PEN' 'CRO' 'Cross'
'PEN' 'PAR' 'Parker'
Procedure ConMCode()
local oDlg, oBrw1, oBrw2, oBtn, oSay
MAN->(cmxSetScope(0,'M '))
MAN->(cmxSetScope(1,'M '+chr(122)))
REDEFINE LISTBOX oBrw1 FIELDS MAN->cod_code, MAN->cod_desc ;
HEADERS 'Code', 'Description' ;
FIELDSIZES 50, 180 ;
ID 101 ;
ON DBLCLICK EditMan(.F.,oBrw1)
ON CHANGE oBrw2:UpStable() ;
REDEFINE LISTBOX oBrw2 FIELDS SUB->cod_code, SUB->cod_desc ;
HEADERS 'Code', 'Description' ;
FIELDSIZES 50, 180 ;
ID 102 ;
ON DBLCLICK EditSub(.F.,oBrw2)
Thanks in advance for your help,

The call to cmxSetScope() has to bee done inside the ON CHANGE clause
REDEFINE LISTBOX oBrw1 FIELDS MAN->cod_code, MAN->cod_desc ;
HEADERS 'Code', 'Description' ;
FIELDSIZES 50, 180 ;
ID 101 ;
ON DBLCLICK EditMan(.F.,oBrw1)
ON CHANGE ( SUB->(cmxSetScope(0,MAN->COD_CODE))
SUB->(cmxSetScope(1,MAN->COD_CODE+chr(122)) ) )
Activate Dialog oDlg On Init Eval( oBrw1:bChange )

I try to use this but it's still not work.
REDEFINE LISTBOX oBrw1 FIELDS MAN->cod_code, MAN->cod_desc ;
HEADERS 'Code', 'Description' ;
FIELDSIZES 50, 180 ;
ID 101 ;
ON DBLCLICK EditMan(.F.,oBrw1) ;
ON CHANGE ( SUB->(cmxSetScope(0,MAN->COD_CODE)) , ;
SUB->(cmxSetScope(1,MAN->COD_CODE+chr(122)) ) )

Does the second browse have a index on the COD_CODE field?

The second browse use the same index file.
Index file CCRCODE.NTX
Field name Type Width
The first browse key is 'M '+COD_CODE
The second browse key is COD_TYPE+COD_CODE * the COD_TYPE will relation to COD_CODE in first browse

I don't think cmxSetScope() works with the NTX RDD.

I'm sorry the index file is CCRCODE.CDX


I use Clipper 5.2e / FW2.0d / Comix / Blinker 4.10. I tried to browse 2 databases that has relation but it doesn't work. Pls see my sample below, I don't know what I do wrong. Thanks in advance for any idea,
#include ''
#include ''
#include ''
Static oDlg, oBrw1, oBrw2
Procedure Main
FIELDSIZES 60, 150 ;
ID 101 ;
OF oDlg
oBrw1:bChange := { || oBrw_Con( oBrw1, oBrw2 ) }
FIELDSIZES 60, 100 ;
ID 102 ;
OF oDlg
ACTIVATE DIALOG oDlg ON INIT Eval( oBrw1:bChange )
Function oBrw_Con( oBrw1 , oBrw2 )
Select TRN
Select TBL
return nil

Put a "SELECT TRN" before the REDEFINE for oBrw2, or specify the alias as in oBrw2:alias := "TRN"
oBrw2:alias is going to be TBL because that was the active table when the listbox was defined.

Thanks a lot, I've got it and work nice.. : >


Suppose I wish to browse a file. Not so much allow modifications. Just browse it. Any suggestions on the best way to do so.

I'm not sure this is "best", but TWBrowse is certainly "easy":
redefine listbox fields alias "Customer" id 101 of oDlg


I have a browse (redefine .... browse ....) and I would prefer it to have no scrollbars (neither hor. nor vertical). Using MS Visual Dev to generate the resource and have already set there to use no scrollbars. Yet they appear.
I managed to eliminate one with obj:lNoHScroll:=.T., alas there appears to be no obj:lnoVscroll.
Who knows how to fully eliminate them?

oBrowse:oHScroll:setRange( 0,0 )
oBrowse:oHScroll := nil
oBrowse:oVScroll:setRange( 0,0 )
oBrowse:oVScroll := nil

Tried both, no success. I also liiked into tcbrowse.prg but could not find a data field suggesting to be useble.
> Ps. Op ons laatste gesprek kom ik binnenkort terug, het was wat hectisch de
> laatste tijd !!
Okay no hurry, I completely overhauled my app since that time. Several independent browses into a dialog, sending SMS messages, 'intelligent' buttons, etc.

I use twBrowse() and the suggested statements works for me !
Maybe a :refresh() ?
FW2.3b + Clipper 5.3 + Blinker 6.0

That is the same as a listbox? Bit difficult in my case then, the browse is supposed to show entries from a database and putting that in an array would be a very tedious thing.

> That is the same as a listbox?
>Bit difficult in my case then, the browse is
> supposed to show entries from a database and putting that in an array would
> be a very tedious thing.
You can use arrays but you can also use databases. I do most of my database browses using TWBrowse which is defined as either @ 0,0 LISTBOX... or REDEFINE LISTBOX... Listbox doesn't have all the capabilities of TCBrowse, but often you don't need them.
I haven't used MS Visual Dev, but I know that in Workshop you must define a custom control as TWBrowse instead of using the standard "listbox" that Workshop has or you will have strange problems like you are experiencing.
Also in workshop you can disable the scrolling by editing the style. You take out these. WS_VSCROLL | WS_HSCROLL.

I changed it to a "Listbox" (I discovered that there were 2 helpitem on listbox, one for use as regular and one for use with a dbf). But the
scrollbar remains. Although (as far as I can see) the problem (scrolling going haywire) has disappeared, and I wanted to eliminate the bar as a
>>> custom control as TWBrowse instead of using the standard "listbox" that
In MSDev I can define a customer control, but then I get a runtime error.


I have an empty database with a character field len 20, and a browse to show that field in a dialog with a buttonbar. The first button in the bar, it's used to diaplay a dialog to add a record with data entered by the user. Now, the problem is that when i add the first record in the database, the browse doesn't show it after the refresh, but if i close and open the dialog with the browse again, it shows it normally. The curious thing is that when i add a register and there are other records in the database, there isn't any problem. I am using oBrw:Refresh() and i tried oBrw:UpStable and oBrw:BugUp() too, and any combination of those methods to refresh the browse after i add the record, but it doesn't help. This problem happens with arrays and databases, and it doesn't matter how many items or the size of each one. What can it be?
Note: i don't want to use tsbrowse's autoappend functionality, because i must do it with the buttonbar.

Check your alias...
define browse... alias cAlias
=> cAlias must be your database alias name


In a browse I can (in the column statement) define an "order indxname" which defines the actual index to use when the columnheader is double clicked.
This is nice, however I want (when the column header is clicked) to have the control.
Question is, "Is there a way to define an action when a certain column header is (double) clicked?"

I had the same necessity; for this reason I modified for my personal use the tcbrowse and tccolumn classes.
I attach them here, just to show you how I did. Search for ::bHeadclick inside both classes. I don't expect you can compile and use this code, probably it calls more functions from my personal library or other pieces of code. But you should to get some idea about how to do.
Since The NG do not allow me to send whole code inside one zip, search two zip files in following messages :-)


I will check them out, although I remember that in 1.9x there was a default
codeblcok which could be changed for such purposes.

regards, saludos

Antonio Linares
User avatar
Antonio Linares
Site Admin
Posts: 27219
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain


Return to Utilities / Utilidades

Who is online

Users browsing this forum: No registered users and 1 guest