(Tagged messages in GFA Basic)

#: 91967 S12/GFA  (CIS:WINAPC)
    16-Jul-96  14:22:07
Sb: ODBC
Fm: Ophir 100430,2465
To: GFA
Replies:   0

To GFA

ODBC

What about support for Microsoft Open Data Base Connectivity (ODBC).
I just spent 3 days writing GFA basic code using the ODBC API.

It will be a great help if you will include some sort of GFA commands to interface ODBC, 
 as this will give GFA programmers access to SQL, ACCESS, DBASE, PARADOX, ORACLE, 
  SYBASE, and many more formats.

Ophir


#: 92368 S12/GFA  (CIS:WINAPC)
    31-Jul-96  18:13:10
Sb: #92328-Listboxes
Fm: Ophir 100430,2465
To: Andrew Risely 100667,1620 (X)
Replies:   0

Dear Andrew

I don't use the basic file commands, I find the API commands faster and more reliable.
e.g
filh& = _lopen("andrew.dat",OF_SHARE_EXCLUSIVE | OF_READWRITE)
~_lclose(filh&) 

I don't use the basic field commands, I use structures instead.  
e.g
  TYPE TABLET:
  - CHAR*50 company_name$
  - CHAR*50 department_name$
  - CHAR*50 contact_name$
  - CHAR*25 street_name$
  ENDTYPE

Regards Ophir Daniel

Listboxes
---------

//You have to invalidate the rect after LB_SETCURSEL to redraw the control
//Try this example:

$ABIG LisBoxCont$()
DIM LisBoxCont$(5000)//(max_string_length*max_number_of_strings)
DIALOG #0,(SYSMETRIC(0) / 2) - 300,(SYSMETRIC(1) / 2) - 200,600,400,"Click Right Mouse",0
  CB DLG(0),WM_DRAWITEM,ListBoxString()
  DLG FILL 0,RGB(192,192,192)
  LISTBOX "",10,10,10,575,360,LBS_OWNERDRAWFIXED | WS_BORDER | WS_VSCROLL
ENDDIALOG
FOR dummy& = 0 TO 180
  LisBoxCont$(dummy&) = "This is string number: " + STR$(dummy&)
  ~SendMessage(DLG(0,10),LB_ADDSTRING,dummy&,0)//fill listbox with dummy strings
NEXT dummy&
~SendMessage(DLG(0,10),LB_SETCURSEL,16,0)//
SHOWDIALOG #0
DO
  PEEKEVENT
  IF MOUSEK = 2
    ~SendMessage(DLG(0,10),LB_SETCURSEL,RANDOM(180),0)//
    //You have to invalidate the rect to redraw the control
    ~InvalidateRect((DLG(0,10) ),0,0)
  ENDIF
UNTIL MENU(1) = 4
stl$ = LisBoxCont$(SendMessage(DLG(0,10),LB_GETCURSEL,0,0))
CLOSEDIALOG #0
ERASE LisBoxCont$()
PROCEDURE ListBoxString(LB_h&,LB_m&,LB_w&,LB_l%)
  IF {LB_l% + 8} & ODS_SELECTED
    temp_brush& = CreateSolidBrush(SYSCOL(COLOR_HIGHLIGHT))
    ~FillRect(WORD{LB_l% + 12},LB_l% + 14,temp_brush&)
    ~DeleteObject(temp_brush&)
    ~SetTextColor(WORD{LB_l% + 12},SYSCOL(COLOR_HIGHLIGHTTEXT))
  ELSE
    temp_brush& = CreateSolidBrush(SYSCOL(COLOR_WINDOW))
    ~FillRect(WORD{LB_l% + 12},LB_l% + 14,temp_brush&)
    ~DeleteObject(temp_brush&)
    ~SetTextColor(WORD{LB_l% + 12},SYSCOL(COLOR_WINDOWTEXT))
  ENDIF
  ~SetBkMode(WORD{LB_l% + 12},TRANSPARENT)
  stl$ = LisBoxCont$(WORD{LB_l% + 4})
  ~DrawText(WORD{LB_l% + 12},stl$,LEN(stl$),LB_l% + 14,DT_LEFT)
  RETVAL TRUE
RETURN


#: 93171 S12/GFA  (CIS:WINAPC)
    28-Aug-96  15:51:21
Sb: #93057-Edit-Box: Cursor?
Fm: Sjouke Hamstra 100741,1036
To: Ingmar Brunken 100573,3013
Replies:   0

Hi Ingmar,

Be my guest:

 >> 1. How to find the cursor position in the edit text of an Edit Box?  <<

  SENDMESSAGE hEd,EM_LINEFROMCHAR,-1,0,y
  SENDMESSAGE hEd,EM_LINEINDEX,-1,0,LineOffset  ' in chars
  SENDMESSAGE hEd,EM_GETSEL,0,0,sel%
  SelBegin = LOWORD(sel%)
  SelEnd   = HIWORD(sel%)               ' Hiword contains caret position
  x = SelEnd - LineOffset

 >> 2. How to place the cursor at a user defined position in the edit text?
<<

SENDMESSAGE hEd,EM_SETSEL,0,MAKELONG(pos,pos)   ' in chars!!

 >> 3. If 2. is not possible, if there is a possibility to place the cursor
last  instead of first position?  <<

A small trick can do the job:

l&=LEN(_WIN$(hED))
SENDMESSAGE hEd,EM_SETSEL,0,MAKELONG(l&,l&)   ' in chars!!

Greetings, SH


#: 93126 S12/GFA  (CIS:WINAPC)
    27-Aug-96  21:20:19
Sb: #Cursor in EditBox
Fm: Friedrich Rode 100602,702
To: Ingmar Brunken 100573,3013 (X)
Replies:   1

We all are of it dependent in any way, that us at questions is helped.
I finds your suggestion of a Commen Library very well. That this 
forum isn't very much active often hangs on the language barrier. 
My English is also very badly. I like to try nevertheless to 
contribute my part to this. Which routines have you imagined?Who 
manages the whole and where/how is they filed in the forum?

Now for the question:
>> 1. How to find the cursor position in the edit text of an Edit Box? <<

//  if a WM_KEYDOWN or WM_CHAR message arrives

PROCEDURE getcaretpos 
  caretpos_y% = SendMessage(id_edit&,EM_LINEFROMCHAR,$FFFF,0)
  ADD caretpos_y%,1
  getsel% = SendMessage(id_edit&,EM_GETSEL,0,0)
  wstart% = LOWORD(getsel%) + 1
  lineindex% = SendMessage(id_edit&,EM_LINEINDEX,$FFFF,0)
  caretpos_x% = wstart% - lineindex%
  getcaretpos% = MAKELONG(caretpos_x% ,caretpos_y%)

//***The position can be displayed in the Titlebar (for test)

  _WIN$(WIN(1)) = STR$(caretpos_x% ) + "    " + STR$(caretpos_y% )
RETURN

>> 2. How to place the cursor at a user defined position in the edit text? <<

PROCEDURE setcaretpos(x%,y%)
  // x%=caretpos x
  // y%=caretpos y
  // count lines
  lines% = SendMessage(id_edit&,EM_GETLINECOUNT,0,0)
  // if y% exist
  IF y% <= lines%
    sel% = SendMessage(id_edit&,EM_LINEINDEX,y% - 1,0)
    sel% = sel% + x% - 1
    ~SendMessage(id_edit&,EM_SETSEL,0,MAKELONG(sel%,sel%))
  ELSE
    BEEP
  ENDIF
RETURN

I hope that helps you.
regards,Friedrich


#: 93185 S12/GFA  (CIS:WINAPC)
    28-Aug-96  18:14:11
Sb: #93160-"OpenHelp (Keyword)"
Fm: Dale Bryant 73134,1500
To: Ingmar Brunken 100573,3013
Replies:   0

Standard opening:       ~WinHelp(WIN(0),"TEST.HLP",HELP_INDEX,0)
(works, but doesn't link to a keyword or even the keyword window)

>Additonal question: Does anybody know how to start the keyword window instead of standard title window when opening helpfile?<

	Just change the HELP_INDEX 0 to the context nuber of the page you want displayed in your help file. 

    ~WinHelp(WIN(0),"bcopy.hlp",HELP_CONTEXT,6)

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


#: 93232 S12/GFA  (CIS:WINAPC)
    30-Aug-96  09:00:07
Sb: #93205-ROTATE BMP
Fm: Sjouke Hamstra 100741,1036
To: James V. Schumacher 104166,2104 (X)
Replies:   0

Hi James,

You might give this a try. This uses cosq() and sinq() which are almost 5
times faster as the cos and sin functions. This doesn't use your trick of
rotating each quadrant at once. However, it rotates without 'fuzzing'.

DEFWRD "a-z"
OPENW #1
PRINT

' Create a bmp:
COLOR 1,8
TEXT 10,10,"GFABASIC"
width = TXTLEN("GFABASIC")
height = WIND_GET(14)
GET 10,10,10 + width,10 + height,hbmp        ' dimension of graph
width *= 5
height *= 5
STRETCH 10,10,hbmp, width,height
FREEBMP hbmp

' Rotate and transform a retctangle:
Rotate(10,10,width,height,270,200,100)

DO
  SLEEP
UNTIL MENU(1)=4
CLOSEW #1
END

PROCEDURE Rotate(x1,y1,w,h,Deg,x2,y2)
  LOCAL i,j,xr,yr

  FOR i = 0 TO w  - 1
    FOR j = 0 TO h  - 1
      xr = i * COSQ(Deg) - j * SINQ(Deg)
      yr = j * COSQ(Deg) - i * SINQ(Deg)
      PSET x2 + xr,y2 + yr,POINT(x1 + i,y1 + j)
    NEXT j
  NEXT i
RETURN

Greetings, SH


#: 93280 S12/GFA  (CIS:WINAPC)
    01-Sep-96  18:36:25
Sb: #93059-ODBC
Fm: Ophir 100430,2465
To: Ingmar Brunken 100573,3013
Replies:   0

//ODBC code
//you need the odbc disks that come with visual c or basic
//Regards Ophir
@iniodbc
@inigrid
~@@GridInit(_INSTANCE)  //Register With DLL
OPENW #1,10,10,_X - 20,_Y - 20,~15
SETFONT OEM_FIXED_FONT
CONTROL "&Grid",100,"griddy",WS_BORDER | WS_TABSTOP,0,0,620,480
LISTBOX "",101,20,20,420,280
hGrid& = GetDlgItem(WIN(1),100)
listtab& = GetDlgItem(WIN(1),101)
~ShowWindow(hGrid&,0)
env% = 0
hdbc% = 0
hstmt% = 0
cb& = 0
cursorname$ = SPACE$(100)
pcbCurso% = 0
pcrow% = 0
pccol& = 0
~^SQLAllocEnv(*env%)
~^SQLAllocConnect(env%,*hdbc%)
pcbConnStrOut& = 0
szConnStrOut$ = SPACE$(1350)
~^SQLDriverConnect(hdbc%,WIN(1),"DSN=Dan",0,V:szConnStrOut$,1350,*pcbConnStrOut&,1)
_WIN$(WIN(1)) = LEFT$(szConnStrOut$,pcbConnStrOut&)
//~^SQLConnect(hdbc%,"Dan",-3,"",-3,"",-3),"SQLConnect"
tabhstmt% = 0
~^SQLAllocStmt(hdbc%,*tabhstmt%)
~^SQLTables(tabhstmt%,0,0,0,0,0,0,0,0)
DO
  EXIT IF ^SQLFetch(tabhstmt%) != 0
  dbbufl$ = SPACE$(255),pcbvalue& = 0
  ~^SQLGetData(tabhstmt%,3,1,V:dbbufl$,254,V:pcbvalue&)
  ~SendMessage(listtab&,LB_ADDSTRING,0,LEFT$(dbbufl$,pcbvalue&))
LOOP
~SendMessage(listtab&,LB_SETCURSEL,0,0)
~^SQLFreeStmt(tabhstmt%,1)
DO
  PEEKEVENT
UNTIL MENU(1) = 4
tabtous$ = SPACE$(255)
tabtous$ = LEFT$(tabtous$,SendMessage(listtab&,LB_GETTEXT,SendMessage(listtab&,LB_GETCURSEL,0,0),V:tabtous$))
~ShowWindow(listtab&,0)
//
~^SQLAllocStmt(hdbc%,*hstmt%)
SQL$ = "SELECT * FROM " + tabtous$ + " WHERE(DEC>=296)"// AND WEIGHT<201) ORDER BY 1,2,3,4"
~^SQLExecDirect(hstmt%,V:SQL$,LEN(SQL$))
//~^SQLRowCount(hstmt%,*pcrow%)
pccol& = 0
~^SQLNumResultCols(hstmt%,*pccol&)
t = 1
~^GridSetColCnt(hGrid&,pccol&)
DO
  EXIT IF  ^SQLFetch(hstmt%) != 0
  ~^GridSetRowCnt(hGrid&,t)
  ~^GridSetTextN(hGrid&,0,t,STR$(t))
  FOR xdbf& = 1 TO pccol&
    IF t = 1
      szColName$ = SPACE$(256),pcbColName& = 0,pfSqlType& = 0,pcbColDef& = 0, pibScale& = 0, pfNullable& = 0
      ~^SQLDescribeCol(hstmt%,xdbf&,V:szColName$,255,*pcbColName&,*pfSqlType&,*pcbColDef&, *pibScale&, *pfNullable&)
      ~^GridSetTextN(hGrid&,xdbf&,0,LEFT$(szColName$,pcbColName&))
    ENDIF
    dbbufl$ = SPACE$(255),pcbvalue& = 0
    ~^SQLGetData(hstmt%,xdbf&,1,V:dbbufl$,254,V:pcbvalue&)
    ~^GridSetWidth(hGrid&,xdbf&,TXTLEN("  " + LEFT$(dbbufl$,pcbvalue&)))
    agdb$ = LEFT$(dbbufl$,pcbvalue&) + CHR$(0)
    ~^GridSetText(hGrid&,xdbf&,t,V:agdb$)//,LEN(agdb$) - 1)
  NEXT xdbf&
  t ++
LOOP
~ShowWindow(hGrid&,SW_SHOWMAXIMIZED)
~^SQLFreeStmt(hstmt%,1)
~^SQLDisConnect(hdbc%)
~^SQLFreeConnect(hdbc%)
~^SQLFreeEnv(env%)
//~^SQLCreateDataSource(WIN(1),"shiri")
//~^SQLManageDataSources(WIN(1))
DO
  PEEKEVENT
UNTIL MENU(1) = 4
CLOSEW #1
~@@GridExit(_INSTANCE)
FREEDLL 1
FREEDLL 2
FREEDLL 5
PROCEDURE inigrid
  DLL #19,"griddy.dll"
    DECL INT  GridInit(w)
    DECL INT  GridExit(w)
    DECL INT  GridSetText(w,w,w,l)
    DECL INT  GridSetTextL(w,w,w,l,w)
    DECL INT  GridSetTextN(w,w,w,l)
    DECL INT  GridSetTextNL(w,w,w,l,w)
    DECL INT  GridSetWidth(w,w,w)
    DECL INT  GridSetHeight(w,w,w)
    DECL INT  GridSetAlign(w,w)
    DECL INT  GridSetColCnt(w,w)
    DECL INT  GridSetRowCnt(w,w)
    DECL LONG GridActivate(w,w,w)
    DECL INT  GridGetTextSt(w,w,w,l)
    DECL INT  GridGetTextC(w,w,w,l,w)
  ENDDLL
RETURN
PROCEDURE iniodbc
  DLL #1,"odbcinst.dll"
    DECL BYTE SQLInstallODBC(w,l,l,l)
    DECL BYTE SQLCreateDataSource(w,l)
    DECL BYTE SQLManageDataSources(w)
  ENDDLL
  DLL #2,"odbc.dll"
    DECL SHORT SQLAllocEnv(l)
    DECL SHORT SQLFreeEnv(l)
    DECL SHORT SQLAllocConnect(l,l)
    DECL SHORT SQLFreeConnect(l)
    DECL SHORT SQLDriverConnect(l,w,l,w,l,w,l,w)
    DECL SHORT SQLConnect(l,l,w,l,w,l,w)
    DECL SHORT SQLDisConnect(l)
    DECL SHORT SQLAllocStmt(l,l)
    DECL SHORT SQLFreeStmt(l,w)
    DECL SHORT SQLGetCursorName(l,l,w,l)
    DECL SHORT SQLExecDirect(l,l,l)
    DECL SHORT SQLFetch(l)
    DECL SHORT SQLRowCount(l,l)
    DECL SHORT SQLNumResultCols(l,l)
    DECL SHORT SQLBindCol(l,w,w,l,l,l)
    DECL SHORT SQLGetData(l,w,w,l,l,l)
    DECL SHORT SQLPrimaryKeys(l,l,w,l,w,l,w)
    DECL SHORT SQLTables(l,l,w,l,w,l,w,l,w)
    DECL SHORT SQLDescribeCol(l,w,l,w,l,l,l,l,l)
  ENDDLL
RETURN


#: 93292 S12/GFA  (CIS:WINAPC)
    02-Sep-96  19:05:13
Sb: #32 bit Dialoge
Fm: Friedrich Rode 100602,702
To: all
Replies:   1

// The program 'rundll32.exe' makes possible the call of 32 bit programs
// and Dll's. The examples introduced in the demo program show the call
// of system programs. Everybody can try which possibilities still insist.
// It would be nice if these examples then is published too.
// Comments and suggestions are always welcome.
//
// Many fun, Friedrich Rode
//
// (Is a contribution for the CommonLibraryProject)
// -------------------------------------------------------------
// Das Programm 'rundll32.exe' ermglicht den Aufruf von 32 Bit
// Programmen und Dll's. Die im Demoprogramm vorgestellten Beispiele
// zeigen den Aufruf von Systemprogrammen. Jeder kann selber versuchen
// welche Mglichkeiten noch bestehen. Es wre nett wenn diese Beispiele
// dann auch verffentlicht werden.
// Kommentare und Vorschlge sind immer willkommen.
//
// Viel Spa, Friedrich Rode
//
// (Ist ein Beitrag fr das CommonLibraryProject)
//
// program -----------------------------------------------------
@init   // Initialize variables and dialogue structure
//         Initialisiere Variablen und Dialog Struktur

DO                      // message loop         // Nachrichtenschleife
  GETEVENT              // exist message?       // Nachricht da?
  SELECT _Mess          // ID of the last message //ID der letzten Message.
  CASE WM_COMMAND       // Button pushed        // Button gedrckt
    SWITCH _wParam      // ID Button
    CASE 101            // if ID=101
      @startsysfile(1)  // goto procedure       // gehe zu Procedure
    CASE 102            // and so on            // u.s.w
      @startsysfile(2)
    CASE 103
      @startsysfile(3)
    CASE 104
      @startsysfile(4)
    CASE 105
      @startsysfile(5)
    CASE 106
      @startsysfile(6)
    CASE 107
      @startsysfile(7)
    CASE 108
      @startsysfile(8)
    CASE 109
      @startsysfile(9)
    CASE 110
      @startsysfile(10)
    CASE 111
      @startsysfile(11)
    CASE 112
      @startsysfile(12)
    CASE 113
      //Checks whether Shell32.dll exists
      //berprfe ob shell32.dll existiert
      IF EXIST(windir$ + "\system\shell32.dll") THEN found| = 1
      //Checks whether rundll32.exe exists
      //berprfe ob run32.exe existiert
      IF EXIST(windir$ + "\rundll32.exe") AND found| = 1
        // if found, starts FormatDialog
        // wenn gefunden, starten FormatDialog
        EXEC windir$ + "\rundll32.exe shell32.dll,SHFormatDrive",""
        found| = 0
      ELSE // if not found    // wenn nicht gefunden
        // starts message     // starte message
        found| = 0
        MESSAGE sysfile$(0),"Warning",MB_ICONEXCLAMATION | MB_OK,n&
      ENDIF
    CASE 114
      //Checks whether diskcopy.dll exists
      //berprfe ob diskcopy.dll existiert
      IF EXIST (windir$ + "\system\diskcopy.dll") THEN found| = 1
      //Checks whether rundll32.exe exists
      //berprfe ob run32.dll existiert
      IF EXIST(windir$ + "\rundll32.exe") AND found| = 1
        // if found, starts DiskCopyDialog
        // wenn gefunden, starten DiskCopyDialog
        EXEC windir$ + "\rundll32.exe Diskcopy.dll,DiskCopyRunDll" , ""
        found| = 0
      ELSE // if not found    // wenn nicht gefunden
        // starts message     // starte message
        found| = 0
        MESSAGE sysfile$(0),"Warning",MB_ICONEXCLAMATION | MB_OK,n&
      ENDIF
    ENDSWITCH
  ENDSELECT
LOOP UNTIL MENU(1) = 4 // exit loop if Menu(1)=4
ERASE sysfile$() // array destroy       // array lschen
CLOSEDIALOG  #1  // close dialog        // Dialog zu

PROCEDURE init
  DIM sysfile$(14)
  sysfile$(0) = "      Can not find SysFile      " // Messagetext
  // Names of .cpl files (WinDir)  German version Win95
  // Namen der .cpl files in der deutschen Win95 Version
  sysfile$(1) = "appwiz"        // Software
  sysfile$(2) = "desk"          // Display
  sysfile$(3) = "intl"          // Regional
  sysfile$(4) = "joy"           // Joystick
  sysfile$(5) = "main"          // Mouse
  sysfile$(6) = "mlcfg32"       // Exchange
  sysfile$(7) = "mmsys"         // Multimedia
  sysfile$(8) = "modem"         // Modem
  sysfile$(9) = "netcpl"        // Network
  sysfile$(10) = "password"     // Password
  sysfile$(11) = "sysdm"        // System
  sysfile$(12) = "timedate"     // Time and Date
  sysfile$(13) = "FormatDisk"   // Format Disk
  sysfile$(14) = "DiskCopy"     // Diskcopy

  buffer$ = SPACE$(255) // creates Buffer for 255 characters
  //                    // erstelle Buffer fr 255 Zeichen
  tchars& = GetWindowsDirectory(V:buffer$,255)  // read the name of the WinDir
  windir$ = LEFT$(buffer$,tchars&)              // Name der WinDir auslesen

  BaseUnits% = GetDialogBaseUnits() // Height of the system font
  basey& = INT(HIWORD(BaseUnits%))  // Schrifthhe des System Font

  // make Dialog   // Dialog erstellen
  DLGBASE UNIT
  DIALOG #1,90,60,152,125,"System Dialogs",DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU,basey&,"helv"
    PUSHBUTTON "Software", 101, 10, 13, 70, 10, WS_CHILD | WS_VISIBLE | WS_TABSTOP
    PUSHBUTTON "Display", 102, 10, 26, 70, 10, WS_CHILD | WS_VISIBLE | WS_TABSTOP
    PUSHBUTTON "Regional", 103, 10, 39, 70, 10, WS_CHILD | WS_VISIBLE | WS_TABSTOP
    PUSHBUTTON "JoyStick", 104, 10, 52, 70, 10, WS_CHILD | WS_VISIBLE | WS_TABSTOP
    PUSHBUTTON "Mouse", 105, 10, 65, 70, 10, WS_CHILD | WS_VISIBLE | WS_TABSTOP
    PUSHBUTTON "Exchange", 106, 10, 78, 70, 10, WS_CHILD | WS_VISIBLE | WS_TABSTOP
    PUSHBUTTON "Multimedia", 107, 10, 91, 70, 10, WS_CHILD | WS_VISIBLE | WS_TABSTOP
    PUSHBUTTON "Modem", 108, 90, 13, 70, 10, WS_CHILD | WS_VISIBLE | WS_TABSTOP
    PUSHBUTTON "NetWork", 109, 90, 26, 70, 10, WS_CHILD | WS_VISIBLE | WS_TABSTOP
    PUSHBUTTON "PassWord", 110, 90, 39, 70, 10, WS_CHILD | WS_VISIBLE | WS_TABSTOP
    PUSHBUTTON "System", 111, 90, 52, 70, 10, WS_CHILD | WS_VISIBLE | WS_TABSTOP
    PUSHBUTTON "Date / Time", 112, 90, 65, 70, 10, WS_CHILD | WS_VISIBLE | WS_TABSTOP
    PUSHBUTTON "FormatDisk", 113, 90, 78, 70, 10, WS_CHILD | WS_VISIBLE | WS_TABSTOP
    PUSHBUTTON "DiskCopy", 114, 90, 91, 70, 10, WS_CHILD | WS_VISIBLE | WS_TABSTOP
  ENDDIALOG

  SHOWDIALOG #1 // show Dialog  // Dialog anzeigen
  DLG FILL 1,RGB(192,192,192)   // fill Dialog
RETURN

PROCEDURE startsysfile(sysfile|)
  // LOCAL Variables only valid in this Procedure
  // LOCAL Variablen nur in dieser Procedur gltig
  LOCAL found| = 0,found1| = 0,found2| = 0
  //Checks whether .cpl file exists
  //berprfe ob .cpl Files existiert
  path$ = windir$ + "\system\" + sysfile$(sysfile|) + ".cpl"
  IF EXIST (path$) THEN found| = 1
  //Checks whether Shell32.dll exists
  //berprfe ob shell32.dll existiert
  IF EXIST(windir$ + "\system\shell32.dll") THEN found1| = 1
  //Checks whether rundll32.exe exists
  //berprfe ob run32.dll existiert
  IF EXIST(windir$ + "\rundll32.exe") THEN found2| = 1
  // if found
  // wenn gefunden
  IF found| = 1 AND found1| = 1 AND found2| = 1
    // starts .cpl file
    // starte .cpl file
    EXEC windir$ + "\rundll32.exe shell32.dll,Control_RunDLL " + sysfile$(sysfile|) + ".cpl " , ""
  ELSE // if not found    // wenn nicht gefunden
    // starts message     // starte message
    MESSAGE sysfile$(0),"Warning",MB_ICONEXCLAMATION | MB_OK,n&
  ENDIF
RETURN


#: 93346 S12/GFA  (CIS:WINAPC)
    03-Sep-96  22:50:12
Sb: #rundll32
Fm: Friedrich Rode 100602,702
To: Sjouke Hamstra 100741,1036 (X)
Replies:   1

Sjouke!

>>Or now I'm thinking about it, does it mean: "calling a 32 bit
 DLL from a 16 bit application".<<

I think that it is so, a 16 bit application can call a 32 bit DLL. 
Otherwise the demo would not function also. Load the program into a 
Hexeditor, you see then the functions and DLL's this one can be 
invoked. ( but the syntax ???? ) In a PC - journal it was to be read, 
that it is not documented functions.

As example was: ' rundll32.exe shell32.dll,SHFormatDrive ' ,
and for not registered files: 
' rundll32.exe shell32.dll, Open As_RunDLL name.lst ' 
(but the last didn't work)

Unfortunately I have no other documents.  The demo-idea is from a 
VB program (CIS:MsBasic File: IE3BTNS.ZIP // I have uploaded both 
in the GFA Forum.).
-----------------------------------------------------------------

Another possibility comes also of VB 3.0. The 16 bit Kernel.dll, 
this one delivered with Win95, is expands around the WOW16 functions.
A 32 bits Library  loaded and any functions call with their help be 
possible. ?????? What is in VB possible, must be also possible in GFA ??

Unfortunately, the conversion is too difficult for me !

Here is the C-declaration of the WOW functions :

DWORD FAR PASCAL LoadLibraryEx32W(LPCSTR lpszLibFile, DWORD hFile, 
DWORD dwFlags)
DWORD FAR PASCAL GetProcAddress32W(DWORD hModule, LPCSTR lpszProc)
DWORD FAR PASCAL CallProc32W(DWORD param1, DWORD param2,...,
LPVOID lpProcAddress32,DWORD fAddressConvert,DWORD nParams)
BOOL FAR PASCAL FreeLibrary32W(DWORD hInst)

In the Internet (http://www.pcintern.de) you can download the VB-Demo :
" 32 Bit in Visual Basic 3.0 " month 7/96.If you are interested,you 
can get a written copy of the article of me (journal "PC-Intern" 
in german)
-------------------------------------------------------------------

>>Unfortunately I ran into a callback problem when I tried to convert 
the MARK95 program to GFA.<<

Is OK, I can wait!

Greetings, Friedrich


#: 93557 S12/GFA  (CIS:WINAPC)
    11-Sep-96  10:26:02
Sb: #93548-EXIST for folders
Fm: Sjouke Hamstra 100741,1036
To: James V. Schumacher 104166,2104
Replies:   0

James,

GFA recommends the following two options, found in the Help file under
FGATTR:

IF FGATTR("\TESTDIR") = 16

or:

IF EXIST("\TESTDIR\NUL") - the reserved filename nul is "existing" in all
directories-.

I never used it.


#: 93605 S12/GFA  (CIS:WINAPC)
    12-Sep-96  16:42:03
Sb: #93584-EXIST for folders
Fm: Sjouke Hamstra 100741,1036
To: James V. Schumacher 104166,2104
Replies:   0

James,

Sometimes you are a pain in the a.. ;). Whenever will you be statisfied? :) To be honest I think I'm a perfectionist as well, and ofcourse don't hestitate to ask!

I don't think there is an answer to your question. Almost all applications (GFA as well)  developed under 16 bit Windows, use the C file I/O functions. These functions use the underlying MSDOS I/O functions. To maintain compatibility between the enhanced Windows 95 VFAT and 16 bit FAT Windows 95 contains two FAT tables. 16 bit applications have only acces to the MSDOS compatible FAT table, because they use 16 bit MSDOS interrupts. If you are using long filenames you have a problem. If you insist on using long filenames, the only way out, as I see it, is to obtain the short 16 bit compatible filename from Windows 95. An example can be found in FILESE95 in the Library.

I ran into this problem as well. I therefor was very intrested in the thread on RUNDLL32 last week. If it would be possible to call a function within the 32 bit Kernel, you could use GetShortPathName() to obtain the 16-bit filename alias from a Windows 95 long filename...

Greetings, SH


#: 93607 S12/GFA  (CIS:WINAPC)
    12-Sep-96  16:42:05
Sb: #93571-Creating logical bitmap
Fm: Sjouke Hamstra 100741,1036
To: Jeffrey Heywood 106161,1624
Replies:   0

Jeffrey,

I called Marko Software immediatly: they have NOT received any order from
you!

Try this:

OPENW #1,50,50,500,400,-1
PRINT AT(0,20);"Click left - Click right to end"
DIALOG #0,170,105,300,200,"GFA Basic",$10000000
  //CONTROL "",100,"button",$10000000,40,10,160,140
  PUSHBUTTON "",100,40,10,160,140,BS_OWNERDRAW
  //CONTROL "ok",101,"button",$10000000,210,90,64,32
ENDDIALOG
@MemDcBmp(BMP&)
_WIN$(DLGITEM(0,100)) = STR$(BMP&)

DISABLEW 1
SHOWDIALOG #0
DO
  ON MENU
  IF MOUSEK = 1
    @MemDcBmp(BMP&)
    _WIN$(DLGITEM(0,100)) = STR$(BMP&)
  ENDIF
LOOP UNTIL MOUSEK = 2
ENABLEW 1
FREEBMP BMP&
CLOSEDIALOG #0
CLOSEW #1
END

PROCEDURE MemDcBmp(VAR Hbmp&)
  LOCAL dc& = MEMDC(_DC(1))
  FREEBMP Hbmp&
  Hbmp& = CREATEBMP(50,50)
  SETBMP dc&,Hbmp&
  SETDC dc&
  //***********************************************//
  // How do I use MEMDC to get the following
  // graphic drawn in memory...
  FOR X& = 1 TO 100
    COLOR RAND(15)
    LINE RAND(50),RAND(50),RAND(50),RAND(50)
  NEXT X&
  //**********************************************//
  SETDC _DC(1)
  FREEDC dc&
RETURN


#: 93581 S12/GFA  (CIS:WINAPC)
    12-Sep-96  02:02:18
Sb: #matchcase default
Fm: James V. Schumacher 104166,2104
To: Sjouke Hamstra 100741,1036 (X)
Replies:   1

Sjouke,

I'm talking about the "Find" item under the GFA Basic Editor "Edit" menu column.  In the dialog box that it opens, I can't find anything that controls the default for the "match case" check box.

James


#: 93721 S12/GFA  (CIS:WINAPC)
    17-Sep-96  10:13:09
Sb: #93358-ODBC
Fm: Ingmar Brunken 100573,3013
To: JERRY M. ALLEN 76721,1510
Replies:   0

>>Could you tell us more about this book.  Who publishes it, and where it's available from.
Thanks!<<

I'm not sure if this book is useful for you: It's a GERMAN book. (Maybe you understand German texts, so you'll find the data below.)

Te book is published by Addison-Wesley.
Author is Gnter Born.
Title: "Referenzhandbuch Dateiformate"

Ingmar.

Ingmar.


#: 93742 S12/GFA  (CIS:WINAPC)
    17-Sep-96  20:33:22
Sb: Colored StaticText
Fm: Friedrich Rode 100602,702
To: Ingmar Brunken 100573,3013
Replies:   0

Hi, Ingmar

>>Using "CreateWindow" and "DIALOG..." I tried to add graphics text to these windows and failed, because SETFONT commands are not accepted, means SETFONT doesn't change the font. Using "OPENW" instead, after opening defined as child by "SetParent", makes "SETFONT" working, but now I've got problems parsing the windows command in one central procedure:
"WM_PAINT" now is not recognized.<<

I have loaded the file: " C_Static.zip " into the forum.
If you immediately need the code, let me know.
--------------------------------------------------------------------
This demo shall show the use of colored StaticControls
with colored Text.

-- 5 Border styles -- raised/inset colored text -- SS_LEFT
-- SS_CENTER -- any fonts possible -- normal/italic/underline
fontstyle -- 16 fore/backcolors

This is reached by SubClassing of the StaticControl.

You perhaps are helped with it.

Many fun, Friedrich


#: 93772 S12/GFA  (CIS:WINAPC)
    18-Sep-96  20:12:11
Sb: Bmp DLL's
Fm: Friedrich Rode 100602,702
To: all
Replies:   0

Hi,
I have uploaded the file "Readbmp.zip".

Here is the possibility, different picture formats to load 
it with two DLL. For example: JPG / BMP / CUT / IMG / MSP / 
PCX / PIC / RAS / TGA / TIF  
These formats is to load with only one DLL-Call .
Other formats like GIF must be only translated. This applies 
also to additional functions like Dither, Scale or Print.
This everything is possibly by two Visual-Basic-DLL.
(file.dll and vbjpeg.dll)
The original program is enclosed. This GFA Demo shows the DLL 
call and the declarations.

Many fun, Friedrich Rode


#: 93798 S12/GFA  (CIS:WINAPC)
    19-Sep-96  14:23:30
Sb: #93792-SHELL
Fm: thomas engel 70602,2575
To: Sjouke Hamstra 100741,1036
Replies:   0

SH,

Yes, that's it.  The code below will now access "RegCreateKey" but I get an "INVALID_PARAMETER" error when I try to set the key.

*********************************************************************************
//Declare the shell library
DLL #1, "shell"
  DECL LONG RegCreateKey(w,l,l)
  DECL LONG RegSetValue(w,l,w,l,l)
  DECL LONG RegQueryValue(w,l,l,l)
ENDDLL

//Define some global constants
HKEY_CLASSES_ROOT = 1                                         //constant definition
REG_SZ = 1                                                                 //constant definition
hkey& = 0                                                                    //key handle definition

//Define some return value error codes
ERROR_SUCCESS = 0
ERROR_BADDB = 1
ERROR_BADKEY = 2
ERROR_CANTOPEN = 3
ERROR_CANTREAD = 4
ERROR_CANTWRITE = 5
ERROR_OUTOFMEMORY = 6
ERROR_INVALID_PARAMETER = 7
ERROR_ACCESS_DENIED = 8

//Define a key and a key value
key$ = "My" + CHR$(0)                                          //specify the key (no spaces allowed)
valuekey$ = "Application" + CHR$(0)                    //specify the key value

//Create the registration database entry
RegResult1% = ^RegCreateKey(HKEY_CLASSES_ROOT,V:key$,V:hkey&)
PRINT RegResult1%                         //Return should be zero
PRINT hkey&                                     //print the handle to the key (to be sure it's not zero!)
PRINT "-------"

//Set the registration database value
set$ = ""                                           //a NULL string sets the value
len& = LEN(valuekey$)
RegResult2% = ^RegSetValue(hkey&,"",REG_SZ,V:valuekey$,0)
PRINT RegResult2%
PRINT "-------"

//Wait a while to read the screen
PAUSE 30
CLOSEW #1

//Clean up and end
FREEDLL 1
END


#: 93916 S12/GFA  (CIS:WINAPC)
    23-Sep-96  16:14:11
Sb: #93826-PAINT-Problem
Fm: Ingmar Brunken 100573,3013
To: Ingmar Brunken 100573,3013
Replies:   0

I solved my "WM_PAINT"-problem in between. The sollution is: A callback routine.

Bacause nobody did answer I guess many others did not know how to "paint/draw/plot" things in a dialog. In fact, it's very easy now and seems to work wonderful (yet...). How easy now to mix windows controls with own drawings such as palettes, text examples etc. (cause TEXT and RGBCOLOR is supported also!). May my example be of use for others, too: 

Ingmar.
//Example: How to "DRAW, COLOR and TEXT" a regular dialog
// by Ingmar Brunken, CIS 100573,3013
//Example code
PARENTW #1
FULLW #1
DIM w(20,20),wmode|(20,20,5)
hWndMain&=WIN(1)
@grafmodify(spa,rei,w(),wmode|())
CLOSEW #1
END
PROCEDURE grafmodify(spa,rei VAR w(),wmode|())
  ' EIngabe: Grafikparameter spa(Spaltenzahl),rei(Reihenzahl),w() Werte dazu
  ' Ausgabe: Usergewnschte Grafikparameter in wmode|(spa,rei,mode)
  ' mit mode = 1: Darstellungsart entsprechend gz_mode| der PROC grafzeichnen()
  ' =2-4: R,G,B-Werte bei Farbdarstellung
  ' =5: Fllmuster-Nr. bei Fllmusterdarstellung
  ' Globals: Keine.
  LOCAL i&,j&
   DIALOG #3,(SYSMETRIC(0)-602)/2,(SYSMETRIC(1)-391)/2+25,602,391,"Local Graphics Control Panel",DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
    CONTROL "Objekt:",100,"static",$10000002,10,40,80,20
    CONTROL "Verbindung:",101,"static",$10000002,10,75,80,20
    CONTROL "",102,"combobox",$200302,95,35,185,135
    CONTROL "",103,"combobox",$50000002,95,70,185,95
    CONTROL "Darstellung",104,"button",$10000007,5,5,280,105
    CONTROL "Farbe",105,"button",$10000003,295,80,60,25
    CONTROL "R:",106,"static",$10000002,450,25,15,20
    CONTROL "",107,"edit",$10800000,470,20,35,25
    CONTROL "G:",108,"static",$10000002,450,55,15,20
    CONTROL "",109,"edit",$10800000,470,50,35,25
    CONTROL "B:",110,"static",$10000002,450,85,15,20
    CONTROL "",111,"edit",$10800000,470,80,35,25
    CONTROL "Farbe / Fllmuster",112,"button",$10000007,290,5,220,105
    CONTROL "",113,"static",$10000007,520,40,60,60
    CONTROL "Beispiel",114,"button",$10000007,515,5,70,105
    CONTROL "Setzen",115,"button",$10000007,5,110,580,150
    CONTROL "nach Hhe",116,"button",$10000003,355,80,90,25
    CONTROL "Quadrant:",117,"static",$10000002,140,270,70,20
    CONTROL "Titelfarbe:",118,"static",$10000002,275,275,95,20
    CONTROL "Y",119,"static",$10000001,150,290,55,15
    CONTROL "Textfarbe:",120,"static",$10000002,275,300,95,20
    CONTROL "Z",121,"static",$10000001,210,290,55,15
    CONTROL "Linienfarbe:",122,"static",$10000002,280,325,90,20
    CONTROL "",123,"static",$10000007,90,310,55,35
    CONTROL "",124,"static",$10000007,375,275,205,20
    CONTROL "",125,"static",$10000007,150,310,55,35
    CONTROL "",126,"static",$10000007,375,300,205,20
    CONTROL "",127,"static",$10000007,210,310,55,35
    CONTROL "",128,"static",$10000007,375,325,205,20
    CONTROL "X",129,"static",$10000001,90,290,55,15
    CONTROL "Layout",130,"button",$10000007,5,260,580,95
    CONTROL "",131,"static",$10000007,25,310,55,35
    CONTROL "Hintergrund",132,"static",$10000001,10,290,80,20  
   CB DLG(3),WM_PAINT,grafmdfy_paint()   //THIS CALLBACK IS THE CLUE!
 ENDDIALOG
  DISABLEW hWndMain&
  SHOWDIALOG #3
  ~PostMessage(DLG(3),WM_PAINT,0,0)
  DO
    GETEVENT
  LOOP UNTIL MENU(1)=4
  ENABLEW hWndMain&
  CLOSEDIALOG #3
RETURN
PROCEDURE grafmdfy_paint(h&,m&,w&,l%)
  LOCAL ps$
  TRY
    'SWITCH m&
    'CASE WM_PAINT
    '~BringWindowToTop(h&)
    '~SetActiveWindow(h&)
    BEGINPAINT h&,ps$
    IF spa=0 OR rei=0
      spa=14
      rei=5
    ENDIF
    DEFFILL 0
    DEFLINE PS_SOLID,1
    ' Farbe/Fllmuster
    FOR i&=1 TO 3
      FOR j&=1 TO 8
        RGBCOLOR RGB((i&-1)*127.5,(j& MOD 3)*127.5,INT(j&/3)*127.5)
        PBOX 296+(j&-1)*19,25+(i&-1)*19,295+j&*19,24+i&*19
        COLOR GETNEAREST(0,0,0)
        BOX 296+(j&-1)*19,25+(i&-1)*19,295+j&*19,24+i&*19
        COLOR GETNEAREST(255,255,255)
        LINE 295+j&*19,25+(i&-1)*19,295+j&*19,25+i&*19
        LINE 296+(j&-1)*19,24+i&*19,295+j&*19,24+i&*19
      NEXT j&
    NEXT i&
    'Setzen
    FOR i&=1 TO spa
      FOR j&=rei DOWNTO 1
        RGBCOLOR RGB(0,0,255)
        PBOX 41+38*(i&-1),142+(j&-1)*20,40+i&*38,141+j&*20
        COLOR GETNEAREST(0,0,0)
        BOX 41+38*(i&-1),142+(j&-1)*20,40+i&*38,141+j&*20
        COLOR GETNEAREST(255,255,255)
        LINE 40+38*i&,142+(j&-1)*20,40+i&*38,142+j&*20
        LINE 41+38*(i&-1),141+j&*20,41+i&*38,141+j&*20
        GRAPHMODE R2_COPYPEN,TRANSPARENT
        DRAWTEXT 41+38*(i&-1),144+(j&-1)*20,40+i&*38,144+j&*20,STR$(wmode|(i&,j&,1)),DT_CENTER
        GRAPHMODE R2_COPYPEN,OPAQUE
      NEXT j&
    NEXT i&
    'Beispiel
    RGBCOLOR RGB(r&,g&,b&)
    PBOX 521,41,578,98
    RGBCOLOR RGB(255,255,255)
    GRAPHMODE R2_COPYPEN,TRANSPARENT
    DRAWTEXT 521,61,578,98,STR$(gz_mode|),DT_CENTER
    ' Beschriftung
    COLOR GETNEAREST(0,0,0)
    TEXT 41+(spa*38-40)/2,142+rei*20,"X-Achse"
    FOR i&=1 TO spa
      TEXT 41+38*(i&-1)+(38-LEN(STR$(i&))*8)/2,126,STR$(i&)
    NEXT i&
    TEXT 15,135+(rei*20)/2,"Z"
    FOR j&=1 TO rei
      TEXT 37-LEN(STR$(rei-j&+1))*8,145+20*(j&-1),STR$(rei-j&+1)
    NEXT j&
    'Layout
    RGBCOLOR RGB(255,0,0)
    TEXT 377,276,"Titelfarbe"
    TEXT 377,301,"Textfarbe"
    LINE 376,335,580,335
    GRAPHMODE R2_COPYPEN,OPAQUE
    PBOX 25,311,78,343 'Hintergrund
    PBOX 90,311,143,343 'x-Quadr
    PBOX 150,311,203,343 'y-Quadr
    PBOX 210,311,263,343 'z-Quadr
    ENDPAINT h&,ps$
    RETVAL 0         // schaltet internes Redraw des Basic ab
    'ENDSWITCH
  CATCH
RETURN


#: 93958 S12/GFA  (CIS:WINAPC)
    24-Sep-96  20:47:31
Sb: OutLineFont
Fm: Friedrich Rode 100602,702
To: James V. Schumacher 104166,2104 (X)
Replies:   0

Hi, James

>> Question 2: is there any way to get outlined or shadowed 
letters.  I use these in several places in my Mac program 
(all I have to do is declare the style as OUTLINE or SHADOW).  
Is there a PC equivalent style?<<

Load down the "c_static.zip" from the library or use the 
following code:

Greetings, Friedrich

Code:

TITLEW #1,"Outline und Shadowtext Demo"
OPENW #1,0,0,_X,_Y,16

hdc& = GetDC(WIN(1))
@initmenu

DO
  GETEVENT
  SELECT _Mess
  CASE WM_PAINT       //Hat im ursprnglichen Beispiel gefehlt....
    IF Modus| = 1
      @shadow
    ELSE IF Modus| = 2
      @outline
    ENDIF
  CASE WM_COMMAND
    SWITCH _wParam
    CASE 100
      ende| = 1
    CASE 200
      Modus| = 2   //wg. WM_PAINT ergnzt
      CLS
      @neuerfont
      @outline
    CASE 300
      Modus| = 1  //wg. WM_PAINT ergnzt
      CLS
      @neuerfont
      @shadow
    ENDSWITCH
  ENDSELECT
UNTIL ende| = 1
FREEFONT font&
CLOSEW #1

PROCEDURE neuerfont
  DLG FONT 1,hdc&,CF_BOTH | CF_EFFECTS,0,0,0,""
  '                     // Gleich danach die Auswahl eines Fonts
  FONT TO font&         // Den eben ausgewhlten Font erzeugen
  RFONT NAME neuerfont% // Seinen Namen bestimmen und die
  '                     // Auszeichnung CHAR{_EBX} (DLG FONT .....,"")
  n$ = CHAR{neuerfont%} + " - " + CHAR{_EBX}
  SETFONT font&         // Font aktivieren
RETURN
'
PROCEDURE outline
  text$ = n$ + "  Outline - Font"
  x% = _X / 2 - (TXTLEN(text$) / 2)          //mittige Darstellung
  y% = _Y / 2
  GRAPHMODE R2_COPYPEN,TRANSPARENT
  textspace% = 2                       // Buchstabenabstand
  ~SetTextCharacterExtra(hdc&,textspace%)
  COLOR 0                            // Outlinefarbe
  TEXT x% + 1,y%,text$
  TEXT x%,y% + 1,text$
  TEXT x%,y% - 1,text$
  TEXT x% - 1,y%,text$
  TEXT x% - 1,y% - 1,text$
  TEXT x% + 1,y% + 1,text$
  TEXT x% - 1,y% + 1,text$
  TEXT x% + 1,y% - 1,text$
  IF _ECX = 0                  // wenn Textcolor=schwarz
    COLOR 255                // unschalten auf wei sonst keine
  ELSE                       // Outline-darstellung
    RGBCOLOR _ECX
  ENDIF
  TEXT x%,y%,text$
  FREEFONT font&             // Font freigeben
RETURN
'
PROCEDURE shadow
  text$ = n$ + "  Shadow - Font"
  x% = _X / 2 - (TXTLEN(text$) / 2)     // mittige Darstellung
  y% = _Y / 2
  tiefe% = 2                              // Schattentiefe
  RGBCOLOR RGB(192,192,192)             // Schattenfarbe
  TEXT x%,y%,text$
  GRAPHMODE R2_COPYPEN,TRANSPARENT
  RGBCOLOR _ECX                         // Schriftfarbe
  TEXT x% - tiefe%,y% - tiefe%,text$
  FREEFONT font&
RETURN
'
PROCEDURE initmenu
  bar& = CreateMenu()               // Menuleiste
  ~AppendMenu(bar&,MF_STRING,100,"Ende")
  ~AppendMenu(bar&,MF_STRING,200,"Outline-Font")
  ~AppendMenu(bar&,MF_STRING,300,"Shadow-Font")
  ~SetMenu(WIN(1),bar&)
RETURN


#: 93986 S12/GFA  (CIS:WINAPC)
    25-Sep-96  10:19:10
Sb: #93958-OutLineFont
Fm: Sjouke Hamstra 100741,1036
To: Friedrich Rode 100602,702
Replies:   0

Hi Friedrich,

I'm impressed by your outline solution. Keep the good work up.

Greetings, SH


#: 94084 S12/GFA  (CIS:WINAPC)
    27-Sep-96  09:32:27
Sb: #94038-#PAINT-Problem
Fm: Sjouke Hamstra 100741,1036
To: Ingmar Brunken 100573,3013 (X)
Replies:   1

Ingmar,

To force a redraw use InvalidateRect(DLG(3),0,0).

Greetings, SH


#: 94140 S12/GFA  (CIS:WINAPC)
    30-Sep-96  03:11:18
Sb: WM_ERASEBKGND
Fm: thomas engel 70602,2575
To: GFA Germany 75300,3224
Replies:   0

GFA,

Can I trap the WM_ERASEBKGND in a call back for an OWNERDRAW button?  I dont want the background to be erased.  Some code snippets follow.  Do I need to subclass the control?

TGE

************************************************************
//To create the button I use
  'First button
  tlbr_but1& = CreateWindow("BUTTON","",tlbr_but_prm%,tlbr_but_xinc&,tlbr_but_yinc&,tlbr_but_w&,tlbr_but_w&,WIN(0),101,_INSTANCE,0)
  _WIN$(tlbr_but1&) = STR$(bmp1u&) + "," + STR$(bmp1d&)



//To trap for the message I use
  CASE WM_ERASEBKGND /* background about to be erased
    IF Hwnd& = tlbr_but1&  /* don't erase the main window background (i.e., the toolbar region)
      RETVAL 0
    ENDIF
//But nothing happens


#: 94248 S12/GFA  (CIS:WINAPC)
    03-Oct-96  12:09:19
Sb: #94238-How To Create Directory?
Fm: Andrew Risely 100667,1620
To: James V. Schumacher 104166,2104
Replies:   0

It is often wise to create a MakeDir procedure complete with a TRY CATCH routine just incase the directory exists.  This way the error can be trapped.

e.g

Procedure MakeDir

TRY
  MKDIR your dir. name
CATCH
 Alert ,1"Directory Already Exists !,1,"OK",a

RETURN


#: 94306 S12/GFA  (CIS:WINAPC)
    05-Oct-96  16:38:09
Sb: #93887-WM_PAINT
Fm: Ingmar Brunken 100573,3013
To: James V. Schumacher 104166,2104 (X)
Replies:   0

James,

although I'm no expert yet especially in windows programming it seems to me your code is not correct: You select WIN() which just returns the actual window and NOT necessarily the window your message came from. To find the message source you should try "SELECT _hWnd" or "SELECT MENU(15)" as described below. You also could try "IF WM_PAINT AND _hWnd=g_drillWordColorWind&" instead. Please e-mail if this hint doesn't work.

Greetings, Ingmar.



//
  DO
    PEEKEVENT
    GOSUB doDialog
  LOOP

  PROCEDURE doDialog      'which window did event occur in
  SELECT WIN()                      //*** THIS DOESN'T MEAN THE MESSAGE CAME FROM WIN() BUT THE ACTUAL WINDOW IS WIN()
      ///*** IF YOU WANT TO FIND THE ORIGIN OF THE MESSAGE USE _hWnd OR MENU(15) LIKE: "SELECT _hWnd"
      CASE g_drillWordColorWind&
      GOSUB dialogDrillWordColorWind
  ENDSELECT
  RETURN

  PROCEDURE dialogDrillWordColorWind
    SELECT MENU(11) //message
    CASE WM_PAINT
      ... ***the location drawing the unnessarily refreshed items***
    ENDSELECT
  RETURN


#: 94314 S12/GFA  (CIS:WINAPC)
    06-Oct-96  04:21:12
Sb: Compile/Link Questions
Fm: bdd 102703,2110
To: James V. Schumacher 104166,2104 (X)
Replies:   0

Here's further linker info related to my recent post,


***********************
UNEXPANDED command line 
***********************
gfalnk @options.lnk  test.obj, hello.exe, nul,glib.lib,options.def


Reason for external options.lnk file is the limited space on the dos command line.
"@" is a macro symbol which tells the the compiler to get command line info from file.
"OPTIONS.LNK" is a macro file referenced by @ 


Expanding the macro file would yield the following command line,
which must fit on a single line. This could be written without the macor file, if desired.

**********************
EXPANDED command line
**********************
gfalnk /REO /A:32 /nol /packc:38000 /f /DEL /CO /RC: ~gfa.res ~GFA.obj test.obj, hello.exe, nul, glib.lib,options.def


I prefer to use my own macro file OPTIONS.LNK file and the automatic .DEF file "~gfa.def" created by GEN.
This  saves space on the command line and keeps the file names that I am likely to edit all in a single bat file.
OPTIONS.LNK can be created by editing the ~gfa.lnk file generated by GEN.
 

THE ABOVE COMMAND LINE links the most recently compiled gfa file, " ~GFA.obj " with 
	any list of other object files (if any) "test.obj," to form the executable 
	"hello.exe" If you have are just compiling a single GFA file, "test.obj" would of course 
	be left out.

Replace nul with a hello.map if desired.

Use no commas within a list of obj files or within a group of lib files. The first comma should be after the last .obj file.

GLIB.LIB is an essential library for all gfa programs, and must be included.
 
"OPTIONS.DEF" is an optional parameter which names a file holding the directives
		listed on page 39. It is essential for a windows program.


GOLINK:

"gfalnk %1 %2 @~gfa.lnk"   .....This is the text in GOLINK.BAT 

"%1" and   "%2" are not documented anywhere, I have no idea what they do. 

Linker seems to work fine without them.


***********************
NEW PROBLEM
*********************

How does one create a linkable object file with GEN ?
This is not a current problem, but I am curious....

Someday I'm sure I'll want to do it.


#: 94436 S12/GFA  (CIS:WINAPC)
    10-Oct-96  08:06:03
Sb: #R/G/B in DLG COLOR
Fm: Ingmar Brunken 100573,3013
To: ALL
Replies:   1

// Contribution for GFAWHELP.HLP
//
// DLGCOL2.GFW: Modified DLGCOLOR.GFW
// by Ingmar Brunken, CIS 100573,3013
//
// This demo shows - in addition to the "simple" version -
// how to "translate" the col%-value back to r/g/b-values,
// this is important e.g. if you want to paint a color run
// or to edit these values in an own dialog box afterwards
//
OPENW #1
col%=RGB(0,0,0)
DIM a%(15)
// DLG COLOR 1,0,a%(),col%
DLG COLOR WIN(1),CC_FULLOPEN,a%(),col%
r&=MOD(col%,256)
g&=INT(MOD(col%,65536)/256)
b&=INT(MOD(col%,65536*256)/65536)
DO
  SLEEP
  IF _Mess=WM_PAINT
    DEFLINE PS_INSIDEFRAME,99
    RGBCOLOR RGB(r&,g&,b&)
    BOX 0,0,100,100
  ENDIF
UNTIL MENU(1)=4
CLOSEW #1


// Regards, Ingmar.


#: 94503 S12/GFA  (CIS:WINAPC)
    11-Oct-96  20:47:03
Sb: #94492-#PBOX in DC problem
Fm: Dale Bryant 73134,1500
To: James V. Schumacher 104166,2104 (X)
Replies:   1

James, did you mean the box was not drawn. It seems to be with this very slight modification.

OPENW #1
hBmp& = CREATEBMP(_X,_Y)
mdc& = MEMDC(_DC(1))
SETBMP mdc&,hBmp&
SETDC mdc& //set to offscreen MDC
CLS //to get white background
RGBCOLOR RGB(120,120,200) //pick a color
COLOR RGB(192,192,192)
PBOX 10,10,_X-10,_Y-10
LINE 10,10,_X-10,_Y-10
SETDC _DC(1) //set back to onscreen window
REALIZE 1  //make sure colors are ok
~BitBlt(_DC(1),0,0,_X,_Y,mdc&,0,0,SRCCOPY)
KEYGET a%
FREEDC mdc&
FREEBMP (hBmp&)
CLOSEW #1

Dale Bryant
73134.1500@compuserve.com


#: 94511 S12/GFA  (CIS:WINAPC)
    12-Oct-96  06:47:12
Sb: #94503-PBOX in DC problem
Fm: James V. Schumacher 104166,2104
To: Dale Bryant 73134,1500 (X)
Replies:   0

Dale,

>> did you mean the box was not drawn <<

The problem is that the second PBOX call wasn't drawing a filled box.  It seems that a DEFFILL 0 statement is required to get a filled box in the offscreen mdc&.  I.E., this works

OPENW #1
'test onscreen mdc ... no DEFFILL and it works
RGBCOLOR RGB(20,120,200)
PBOX 0,0,_X,_Y
KEYGET a%
CLS //to get white background
DELAY 1
'test offscreen mdc
hBmp& = CREATEBMP(_X,_Y)
mdc& = MEMDC(_DC(1))
SETBMP mdc&,hBmp&
SETDC mdc& //set to offscreen MDC
CLS //to get white background
RGBCOLOR RGB(20,120,200)
DEFFILL 0         //DEFFILL required to get filled box in offscreen mdc&
PBOX 0,0,_X,_Y
LINE 0,0,_X,_X
SETDC _DC(1) //set back to onscreen window
REALIZE 1  //make sure colors are ok
~BitBlt(_DC(1),0,0,_X,_Y,mdc&,0,0,SRCCOPY)
KEYGET a%
FREEDC mdc&
FREEBMP (hBmp&)
CLOSEW #1

Makes me suspect that there is something different about the offscreen mdc from the onscreen mdc, even though they are supposed (I think)  to be equivalent.

James


#: 94507 S12/GFA  (CIS:WINAPC)
    11-Oct-96  23:40:26
Sb: changing sound volume
Fm: James V. Schumacher 104166,2104
To: ALL 75300,3224
Replies:   0

Hello,

I'm trying to use the MMSYSTEM.DLL routines waveOutGetVolume() and waveOutSetVolume() to change the volume of the sound output by my application.  As a test I tried the following code

DLL #1, "MMSYSTEM.dll"
  DECL WORD PlaySound(l,w,l)
  DECL WORD waveOutSetVolume(w,w,w)   //device,volumeright,volumeleft
  DECL WORD waveOutGetVolume(w,l)  //device,bothvolumes
ENDDLL
waveerr& = ^waveOutGetVolume(0,bothVolumes%)
soundVolume& = LOWORD(bothVolumes%)

but I get waveerr& = 11 in the call to waveOutGetVolume() and soundvolume=0 when it isn't.  I don't have any literature that says what  error 11 means.  The driver is installed because I play a sound using the ^PlaySound() routine immediately after this code.   I'm basing this on Microsoft Knowledge document Q118377 if that helps.  Any idea what is wrong?

Thanks,

James


#: 94540 S12/GFA  (CIS:WINAPC)
    14-Oct-96  07:59:02
Sb: #94477-CHILDREN.GFW
Fm: Sjouke Hamstra 100741,1036
To: Andrew Risely 100667,1620 (X)
Replies:   0

 >> Sounds like a job for Sjouke Hamstra !!!  <<

Actually, this is simple ;), you should add the the WS_CLIPSIBLINGS style to
the dialogbox.

SETWINDOWSTYLE DLG(0),WS_CLIPSIBLINGS | WS_CHILD | WS_BORDER

However, you better save the current window styles first and OR them with the
new ones. In this case you only want to add the WS_CHILD style, thus replace
SETWINDOWSTYLE with the following lines:

style% = GetWindowLong(DLG(0),GWL_STYLE)
SETWINDOWSTYLE DLG(0),style% | WS_CHILD

Greetings,
SH


#: 94570 S12/GFA  (CIS:WINAPC)
    14-Oct-96  19:28:18
Sb: new upload
Fm: Friedrich Rode 100602,702
To: all 100602,702
Replies:   0

I have uploaded 2 programs, Programmer is Roland Walter

1.) gfa32fnc.zip	The 16 bit Kernel.dll, this one delivered with 
		Win95, is expands around the WOW16 functions.
		A 32 bits Library  loaded and functions call with 
		their help be possible.
2.) tool1.zip	New Controls (Win95)
		Progressbar / Trackbar / UpDown Control

Unfortunately, is the description and the help file only in German.

Greetings, Friedrich


#: 94583 S12/GFA  (CIS:WINAPC)
    15-Oct-96  01:26:06
Sb: #94542-shell.dll
Fm: thomas engel 70602,2575
To: Sjouke Hamstra 100741,1036 (X)
Replies:   0

SH,

Here's the code to save on time.

TGE

*******************************************************
//Sample code to access the SHELL.DLL and the registration database.  The registration database contains
//information on associated filename extensions, software versions, OLE servers, etc.
//Released to the Public Domain by Thomas G. Engel 70602.2575  September 19,1996.

//Run the program REGEDIT /V to delete the key that this program creates

//Declare the shell library
DLL #1, "shell"
  DECL LONG RegCreateKey(l,l,l)
  DECL LONG RegSetValue(l,l,l,l,l)
  DECL LONG RegQueryValue(l,l,l,l)
  DECL LONG RegOpenKey(l,l,l)
  DECL LONG RegCloseKey(l)
ENDDLL

//Define some global constants
HKEY_CLASSES_ROOT = 1
REG_SZ = 1

//Define some return value error codes
ERROR_SUCCESS = 0
ERROR_BADDB = 1
ERROR_BADKEY = 2
ERROR_CANTOPEN = 3
ERROR_CANTREAD = 4
ERROR_CANTWRITE = 5
ERROR_OUTOFMEMORY = 6
ERROR_INVALID_PARAMETER = 7
ERROR_ACCESS_DENIED = 8

//-----------------------------------------------------------------------Create a key and value
//Define a key and a key value
key$ = "MyApplication" + CHR$(0)  //no spaces allowed in key
keyval$ = "Application 1.0" + CHR$(0)

//Get the handle of the key that will be added
Ret% = ^RegCreateKey(HKEY_CLASSES_ROOT,V:key$,V:hkey%)
//PRINT Ret%  //all the return values should be zero, see the global constants above
//PRINT hkey%
//PRINT "-------"

//Set the registration database value
Ret% = ^RegSetValue(hkey%,"",REG_SZ,V:keyval$,0)
//PRINT Ret%
//PRINT "-------"

//Close the key to save it
Ret% = ^RegCloseKey(hkey%)
//PRINT Ret%
//PRINT "-------"

//Print information to the user
PRINT "The following key has been created"
PRINT ZTRIM$(key$) + " = " + ZTRIM$(keyval$)
PRINT
PRINT "Press any key to continue"
KEYGET a%
CLS

//-----------------------------------------------------------------------Query a key and get its value
//Open the key back up
Ret% = ^RegOpenKey(HKEY_CLASSES_ROOT,V:key$,V:hkey%)
//PRINT Ret%
//PRINT hkey%
//PRINT "-------"

//Get the value of the key
bffr$ = SPACE$(128)           //Dimension a string buffer
sze& = LEN(bffr$)  //get the size of the buffer
Ret% = ^RegQueryValue(hkey%,"",V:bffr$,V:sze&)
//PRINT Ret%
PRINT "The registration database confirms the following key"
PRINT ZTRIM$(key$) + " = " +  ZTRIM$(bffr$)
PRINT
PRINT "Press any key to continue"
KEYGET a%

//Close the key to save it
Ret% = ^RegCloseKey(hkey%)
//PRINT Ret%
//PRINT "-------"

//-----------------------------------------------------------------------Pause for a moment to read the screen, then exit
CLOSEW #1
FREEDLL 1
END


#: 94670 S12/GFA  (CIS:WINAPC)
    16-Oct-96  12:31:09
Sb: #94491-Listbox ScrollBar mess&?
Fm: Sjouke Hamstra 100741,1036
To: James V. Schumacher 104166,2104
Replies:   0

James,

Just a thought.

Subclass the listbox, handle WS_VSCROLL by first calling CallDefWindProc()
and then get the first visible entry by sending LB_GETTOPINDEX. Specify the
index returned to the other listbox by sending LB_SETTOPINDEX.

Something like this:

SWITCH m
CASE WM_VSCROLL
  RETVAL CallWindowProc(lpLbWndProc%,h,m,w,l%)
  Idx=SendMessage(hLb1,LB_GETTOPINDEX,0,0)
  ~SendMessage(hLb2,LB_SETTOPINDEX,Idx,0)
ENDSWITCH

Hope this helps, Greetings,
SH


#: 94654 S12/GFA  (CIS:WINAPC)
    16-Oct-96  01:02:22
Sb: #94625-#Dirs & files in ListBox
Fm: James V. Schumacher 104166,2104
To: Marco A. Kummer 100341,411 (X)
Replies:   1

Marco,

Here are two examples.  I'm sure they can be improved but maybe they'll help.

  //#1 load all filenames in a directory into a hidden listbox, then get the n&-th filename. 
  idFileLB& = 441 //use a unique #
  style% = WS_CHILDWINDOW
  dirPath$ = //place a null terminated pathname here  (e.g., "c:\Windows" +CHR$(0) ) 
  hFileLB& = CreateWindow("LISTBOX","",style%,0,0,_X,_Y,WIN(WIN()),idFileLB&,_INSTANCE,0)
  'load listbox with filenames
  f! = DlgDirList(WIN(WIN()),V:dirPath$,idFileLB&,0,0)
  fileName$ = SPACE$(128)
  ~SendMessage(hFileLB&,LB_GETTEXT,n& - 1,V:fileName$)
  fileName$ = ZTRIM$(fileName$)
  'now close listbox
  ~DestroyWindow(hFileLB&)

  '#2 load all sub-directory names in a directory into a visible listbox
  '      then search for desiredDirName$ and highlight it if its present
  '      lbleft&,lbtop&,lbwidth& and lbheight& are listbox dimensions
  idDirLB& = 589 //use a unique #
  style% = WS_CHILDWINDOW | WS_VISIBLE | WS_BORDER | WS_VSCROLL
  hDirLB& = CreateWindow("LISTBOX","",style%,lbleft&,lbtop&,lbwidth&,lbheight&,WIN(WIN()),idDirLB&,_INSTANCE,0)
  'load listbox with directory names
  dirPath$ = //place a null terminated pathname here  (e.g., "c:\Windows" +CHR$(0) ) 
  f! = DlgDirList(WIN(WIN()),V:dirPath$,idDirLB&,0,$8010)
  'highlight desiredDirName$ if present
  searchName$ = "[" + desiredDirName$ + "]" + CHR$(0)  //note [  ] characters!
  indexPos& = SendMessage(DLGITEM(-1,idDirLB&),LB_SELECTSTRING,-1,searchName$)
  ' close listbox with   ~DestroyWindow(hDirLB& )   when done using it

James


#: 94713 S12/GFA  (CIS:WINAPC)
    17-Oct-96  08:41:27
Sb: #94705-VK_RETURN in EDITBOX
Fm: Sjouke Hamstra 100741,1036
To: James V. Schumacher 104166,2104
Replies:   0

 >> Does it pass another message or am I going to have to subclass each and
every  edit field that needs this feature ... yuck!   <<

It depends where you need the VK_RETURN for, otherwise you need only to write one callback procedure and subclass each EDIT to this callback. There is however a better solution: superclassing.

This differs from subclassing a window class, which causes messages meant for the window procedure to be sent to the class function. The class function then passes the message to the original window procedure. Superclassing creates a new window class. The new window class uses the window procedure from an existing class to give the new class the functionality of the existing class. The superclass is based on some other window class, known as the base class. Frequently the base class is a Windows-supplied control class, but it can be any window class.

Greetings, SH


#: 94719 S12/GFA  (CIS:WINAPC)
    17-Oct-96  17:22:12
Sb: VK_RETURN
Fm: Friedrich Rode 100602,702
To: James V. Schumacher 104166,2104
Replies:   0

James,

In a Dlg you can take this code...

PROCEDURE DlgMsg()
  LOCAL m& = _Mess,w&=_wParam,l%=_lParam,hwnd&=_hWnd
  LOCAL id& = GetWindowWord(hwnd&,GWW_ID)
  SWITCH m&
    CASE WM_KEYUP
    // in a Dlg you take the WM_KEYUP Message
    IF id& = 100 // ID EditControl
      SWITCH w&
      CASE VK_RETURN
      //.... your code
    ENDIF
    ENDSWITCH
  ENDSWITCH
RETURN 	

Greetings, Friedrich


#: 94784 S12/GFA  (CIS:WINAPC)
    21-Oct-96  10:03:07
Sb: #94755-Font Point/Cell Size
Fm: Sjouke Hamstra 100741,1036
To: thomas engel 70602,2575
Replies:   0

Thomas,

I'm sorry but the your suggestion is not correct.

 >> FONT TO screenfont&
    SETFONT screenfont&
    RFONT NAME p%
    RFONT HEIGHT lfHeight&   <<

This is not the way to retrieve the font height of screenfont& selected in
the current DC. RFONT returns the contents of the internal GFA LOGFONT
structure set by you or the user (using DLG FONT). Selcting the this font
into a DC causes Windows to search for the best mathing available font. The
attributes of this font might be different from the values you supplied in
the LOGFONT structure. You can only obtain the correct values using
WINDGET(14) or GetTextMetrics().

Greetings,
SH


#: 94812 S12/GFA  (CIS:WINAPC)
    22-Oct-96  09:32:10
Sb: #94802-Popup Menus
Fm: Sjouke Hamstra 100741,1036
To: Andrew Risely 100667,1620 (X)
Replies:   0

Andrew,

 >> Is there a method of implementing menus which popup as part of the main
menus.   <<

Help yourself:

  DIM menu$(50)
  FOR i& = 0 TO 50
    READ menu$(i&)
    EXIT IF menu$(i&) = "**"
  NEXT i&
  MENU menu$()

  ' Create a POPUP menu for Open
  hPop& = CreatePopupMenu()              ' add second submenu
  FOR i& = 0 TO 20
    READ a$,Id&
    EXIT IF a$ = "**"
    flag& = MF_STRING
    IF a$ = "~" THEN flag& = MF_SEPARATOR
    ~AppendMenu(hPop&,flag&,Id&,a$)
  NEXT i&

  ' Add popup to submenu #1 'Edit' (counting starts at 0)
  hSub& = GetSubMenu(GetMenu(WIN(WIN())),0)
  ~ModifyMenu(hSub&,2,MF_STRING | MF_BYCOMMAND | MF_POPUP,hPop&,menu$(2))

  ' Menu data
  DATA &File, &New, &Open, &Save,-, E&xit,
  DATA &Info, &About...,
  DATA ,,**

  ' Popup data for Xxx
  DATA &Bitmap,111
  DATA &Icon,112
  DATA Cursor,113
  DATA **,0

Greetings,
SH


#: 94879 S12/GFA  (CIS:WINAPC)
    24-Oct-96  20:52:16
Sb: #94856- LBS_DISABLENOSCROLL
Fm: GFA Germany 75300,3224
To: James V. Schumacher 104166,2104 (X)
Replies:   0

James,

LBS_DISABLENOSCROLL is a Windows v3.1 const. Because of backward compatibility GFA does not define these constants, i.e. you must do it yourself.
And that's the reason, why the Basic want it to make a variable.
The Windows constants are declared in the SDK file WINDOWS.H.
The value of LBS_DISABLENOSCROLL is $1000.

Best regards

Sven, GFA Software


#: 94907 S12/GFA  (CIS:WINAPC)
    26-Oct-96  02:11:18
Sb: StretchBlt and Palettes
Fm: James V. Schumacher 104166,2104
To: Sjouke (and All?) 73500,3224
Replies:   0

Oh yes, regarding my problem with ~StretchBlt ( ) changing the palette if the source and destination rects are different sizes, here is my workaround:

  GFAcurDChandle& = _DC(WIN())   // save DC of current WINDOW
  SETDC destMDCHandle&
  SETDC srcMDCHandle&
  GET {srcRectadr%}.left,{srcRectadr%}.top,{srcRectadr%}.right,{srcRectadr%}.bottom,hbmp&
  SETDC destMDCHandle&
  STRETCH {destRectadr%}.left,{destRectadr%}.top,hbmp&,destW&,destH&,copyMode%
  SETDC GFAcurDChandle&

This seems to work but I would still like to know if there is a way to make ~StretchBlt( ) work correctly.  Otherwise, that command is virtually useless.

James

James


#: 94916 S12/GFA  (CIS:WINAPC)
    26-Oct-96  12:16:06
Sb: #94907-StretchBlt and Palettes
Fm: Sjouke Hamstra 100741,1036
To: James V. Schumacher 104166,2104
Replies:   0

Hi James,

Regarding the STRETCH and PUT commands of GFA.

The bitmaps used with these commands may not be selected into a memdc at the
time you invoke these commands. Suppose you created a MEMDC and a CREATEBMP,
and you STRETCH the bmp loaded using LOADBMP into the memdc as follows:

SETDC memdc
STRETCH 0,0,Loadbmp&,2*w,2*h,SRCCOPY

the bmp created using CREATEBMP selected into memdc contains the stretched
bitmap now. When you now want to STRETCH or PUT it to the client area of the
window you won't get a thing. Before using the new memory bitmap you must
first delete the memdc:

SETDC memdc
STRETCH 0,0,Loadbmp&,2*w,2*h,SRCCOPY
SETDC _DC(1)
FREEDC memdc

Now everything will work ok.

You might want to use or adapt the CopyBmp function I provided in my book
(Chapter 9, A memory DC and bitmaps). The returned bitmap can be used with
the GFA commands.

Greetings,
SH


#: 95171 S12/GFA  (CIS:WINAPC)
    05-Nov-96  21:36:20
Sb: #94880-Uploads to the lib
Fm: Dale Bryant 73134,1500
To: GFA Germany 75300,3224
Replies:   0

I sent BCOPY4.ZIP but have not seen it yet. It has a couple of DLL's I thought some of the members might be interested in. Will send it again if  you are interested.


#: 95122 S12/GFA  (CIS:WINAPC)
    03-Nov-96  11:08:10
Sb: #95102-#GetPrivateProfileString?
Fm: Sjouke Hamstra 100741,1036
To: James V. Schumacher 104166,2104 (X)
Replies:   1

Hi James,

Sending code I can test is always best. I found your error within 1 minute.
You forgot to add a nulbyte to the path$:

path$ = CHR$(_DRIVE) + ":" + DIR$(0) + "\test.TXT" + CHR$(0)

and

GetPrivateProfileString(V:section$,V:entry$,V:deflt$,V:tmp$,len&,V:path$)

You see?

Greetings,
SH


#: 95163 S12/GFA  (CIS:WINAPC)
    05-Nov-96  10:02:18
Sb: #95159-Standard Scaleable Font?
Fm: Sjouke Hamstra 100741,1036
To: James V. Schumacher 104166,2104 (X)
Replies:   0

Hi James,

 >> Right now, I'm using "Arial" but I worry  that it may not be present on
some people's computers.  <<

Don't worry, users may have deleted it, but the chance is rare.

Do you have Win31.HLP? Look in the Overviews, Fonts section and read all you
need to know.

The following table lists the 13 core TrueType fonts distributed with Windows
version 3.1. (Windows 3.1 may include additional TrueType fonts that
supplement this core set.)

Font family	Font name	Type

Arial	Arial	Sans serif, variable pitch
	Arial Bold	Sans serif, variable pitch
	Arial Italic	Sans serif, variable pitch
	Arial Bold Italic	Sans serif, variable pitch
Courier New	Courier New	Serif, fixed pitch
	Courier New Bold	Serif, fixed pitch
	Courier New Italic	Serif, fixed pitch
	Courier New Bold Italic	Serif, fixed pitch
Symbol+	Symbol	N/A
Times New Roman	Times New Roman	Serif, variable pitch
	Times New Roman Bold	Serif, variable pitch
	Times New Roman Italic	Serif, variable pitch

Times New Roman Bold Italic	Serif, variable pitch

You best specify a font family! If GDI can't find it it takes the best match,
otherwise it takes the system font (stupid user...).

Greetings,
SH


#: 95343 S12/GFA  (CIS:WINAPC)
    12-Nov-96  09:31:16
Sb: #95302-Uploads to the lib
Fm: Ingmar Brunken 100573,3013
To: Andrew Risely 100667,1620
Replies:   0

Andrew,

<<How can you implement the query to check for Win 95 over that of Win 3.11 when compiled.
>>

FUNCTION getwinver()          // get Windows version
  version& = GetVersion()
  wver = ((version& MOD 256) * 100) + version& \ 256
  RETURN wver
ENDFUNC

Greetings, Ingmar.


#: 95461 S12/GFA  (CIS:WINAPC)
    17-Nov-96  12:21:08
Sb: Uploads to the lib
Fm: Dave Barton 100355,1331
To: Andrew Risely 100667,1620
Replies:   0

<<How can you implement the query to check for Win 95 over that of Win 3.11 when compiled.>>

Hello Andrew,

I know your question has already been answered. Ingmar's solution works fine, if you only need
to know if you dealing with 16 or 32 versions.  I do a lot of hardware & comms interfacing, so most
of my programs need to determin which variant of Windows 3.xx they are working with.

The GetVersion() function does not return information about the sub version, so I make use of
Microsoft's VER.DLL to extract more detail from Windows USER.EXE file.

Here is my suggestion for a GetWinVer() function. I hope you find it usefull.

Kindest Regards - Dave

/* Start of Code */
@Definitions()
/* Next 4 lines are a lazy way to trap WM_PAINT after window creation */
OPENW #1
DO
  PEEKEVENT
UNTIL _Mess = WM_PAINT
/* Now it is possible to use a simple print statement */
PRINT " You Are Running Windows ";@GetWinVer()
/* Use right mouse button or system menu to finish */
DO
  PEEKEVENT
UNTIL MENU(1) = 4 OR MOUSEK = 2
FREEDLL 1
CLOSEW #1
'
FUNCTION GetWinVer()
  LOCAL n&=144,VerNr, VerSize%, hFileInfo%, FileName$,Buffer$,zb$ = CHR$(0)
  Buffer$ = SPACE$(n&) + zb$        /* Buffer for windows system directory */
  n& = GetSystemDirectory(V:Buffer$,n&)
  FileName$ = LEFT$(Buffer$,n&) + "\USER.EXE" + zb$     /* Pathname for Windows User.exe */
  VerSize% = ^GetFileVersionInfoSize(V:FileName$,V:hFileInfo%)
  IF VerSize% > 0                           /* Any other result would be nonsense, but test anyway */
    /* Make the buffer 100 bytes longer to avoid DLL bug which causes memory protection error */
    VerSize% += 100
    Buffer$ = SPACE$(VerSize%) + zb$    /* Buffer for User.Exe information */
    ~^GetFileVersionInfo(V:FileName$, hFileInfo%, VerSize%, V:Buffer$)
    /* Get Microsoft's product version number from the buffer */
    VerNr = VAL(MID$(Buffer$, ADD(INSTR(Buffer$, "FileVersion"),12), 4))
    /* If it is Windows 3.00, 3.10 or 3.11 that is all the information there is */
    IF VerNr >= 4       /* If it is Windows 4 there is a bit more detail, should you want it */
      VerNr = VAL(MID$(Buffer$, ADD(INSTR(Buffer$, "FileVersion"),17), 3)) / 10
    ENDIF
  ENDIF
  RETURN VerNr
ENDFUNC
'
PROCEDURE Definitions()
  /* Open DLL & declare the two functions we need */
  DLL #1,"VER.DLL"
    DECL BOOL GetFileVersionInfo(l,l,l,l)
    DECL LONG GetFileVersionInfoSize(l,l)
  ENDDLL
RETURN
/* End of Code */


#: 95599 S12/GFA  (CIS:WINAPC)
    24-Nov-96  10:15:27
Sb: #95591-Learning dlls
Fm: Sjouke Hamstra 100741,1036
To: Andrew Risely 100667,1620
Replies:   0

Andrew,

This should do:

DEFWRD "a-z"
$LIBRARY AName

PROCEDURE LIBMAIN(hInst,DSeg,HpSz,lpCmd%)
  RETVAL 1
RETURN

PROCEDURE WEP(SysExit)
  // SysExit = 1 - ExitWindows
  // SysExit = 0 - DLL released
RETURN

PROCEDURE AProc(lpStr%)
  $EXPORT MYPROC
  LOCAL tmp$=CHAR{lpStr%}       ' be sure to pass a zere-terminated string

  // ....your code

  ' Actually it is not allowed to return a string, GFA can and will
  ' rearrange the string space after each string operation.
  ' When you IMMEDIATELY after returning from the DLL save
  ' the string to string in the application GFA does not get a chance
  ' to move the tmp$ around.
  tmp$ = tmp$ + CHR$(0)
  RETVAL V:tmp$
RETURN

------------------------------------------------------------
Now pay attention!!
Is there another trick to return a string? Yes there is!!!
------------------------------------------------------------

In LIBMAIN define a TYPE:

TYPE TString:
  - CHAR*255 a$
ENDTYPE

In AProc use the type-var to return the string:

PROCEDURE AProc(lpStr%)
  $EXPORT MYPROC
  LOCAL tmp$=CHAR{lpStr%}       ' be sure to pass a zere-terminated string

  ERASE Ret.
  DIM TString:Ret.

  // your code

  Ret.a$ = tmp$ + CHR$(0)
  RETVAL V:Ret.

RETURN

Now I leave it you folks why this is 'more' legitimate than the other method.
Send your answers to ... and win the price ... ;=)

Greetings,
SH


#: 95957 S12/GFA  (CIS:WINAPC)
    13-Dec-96  10:46:24
Sb: #95950-Timer events
Fm: Sjouke Hamstra 100741,1036
To: Dale Bryant 73134,1500
Replies:   0

Hi Dale,

 >> Sjouke, is there a better way of monitoring more than one TIMER event
than by  checking MNEU(12) in a call back?  <<

Actually you can't use MENU() in a callback at all!! The MENU() array is
updated after the callback is executed. So responding to a WM_TIMER in a
callback is fairly simple: you check the message parameter of to the
callback.

CB -1,0 TO -1, WndProc()

PROCEDURE WndProc(hWnd,Mess,wParam,lParam%)

SWITCH Mess
CASE WM_TIMER
  ...
ENDSWITCH


#: 95986 S12/GFA  (CIS:WINAPC)
    15-Dec-96  12:08:17
Sb: #95973-Timer events
Fm: Sjouke Hamstra 100741,1036
To: Dale Bryant 73134,1500 (X)
Replies:   0

Hi Dale,

Yes there is another way. You should set up a timer callback procedure.

_CB(0) = TimerProcWin1(wwwl)     // (hwnd, msg, idTimer, dwTime) ~SetTimer(hwnd, ID_MYTIMER, 5000, _CB(0))

PROCEDURE TimerProcWin1(hwnd, msg, idTimer, dwTime)
  ....
  RETVAL 1
RETURN

Greetings, SH


#: 96029 S12/GFA  (CIS:WINAPC)
    17-Dec-96  21:46:14
Sb: Program name
Fm: Friedrich Rode 100602,702
To: Marco A. Kummer 100341,411
Replies:   0

Marko,
>>Does anybody know if / how a GFA program can find out by what filename it was launched? For example if I had a compiled program called TEST.EXE, I could access that information in a string in the program.<<

use in compiled program :

buf$ = STRING$(255,0)     // 144 * nullbyte
~GetModuleFileName(_INSTANCE,V:buf$,255)
module$ = UPPER$(CHAR{V:buf$})

Greetings, Friedrich


#: 96073 S12/GFA  (CIS:WINAPC)
    20-Dec-96  15:01:13
Sb: #96063-calender routine
Fm: Sjouke Hamstra 100741,1036
To: Friedrich Rode 100602,702
Replies:   0

Hi friedirch,

Ok I opened my 1989 drawer:

FUNCTION DayFromdate$()
  ' Constructs a string specifying the day and the date
  ' formatted as Day dd Month 19nn
  ' (c) 19-07-89 S.A. Hamstra
  LOCAL day$,i

  RESTORE DayFromDate
  DIM day$(6), m(12),m$(12)
  FOR i = 1 TO 12
    READ m(i),m$(i)
  NEXT i
  FOR i = 0 TO 6
    READ day$(i)
  NEXT i

  day = VAL(LEFT$(DATE$,2))
  month = VAL(MID$(DATE$,4,2))
  year = VAL(RIGHT$(DATE$,2))

  i = (day + m(month) + (year MOD 7) + (year \ 4)) MOD 7
  day$ = day$(i) + " " + STR$(day) + " " + m$(month) + " 19" + STR$(year)

  ERASE day$(), m(),m$()

  RETURN day$

  DayFromDate:
  DATA 1,Jan,4,Feb,4,Mar,0,Apr,2,May,5,Jun
  DATA 0,Jul,3,Aug,6,Sep,1,Oct,4,Nov,6,Dec
  DATA Sat,Sun,Mon,Tue,Wed,Thu,Fri
ENDFUNC


#: 96188 S12/GFA  (CIS:WINAPC)
    28-Dec-96  11:35:12
Sb: #96160-Directory Selection
Fm: Peter Gammenthaler 101725,2705
To: Dave Barton 100355,1331
Replies:   0

//  Hi Dave
//  I know this is a long listing for just a fileselection, but maybe it will help.

//  Regards
//  Peter Gammenthaler

SHOWM
DLGBASE PIXEL
DLG 3DON
a$ = "c:\" + CHR$(0)  // If your drive is C
DIALOG #0,100,100,400,200,"List",WS_SYSMENU | WS_MINIMIZEBOX,-12,"Arial"
  CONTROL "",139,"listbox",$10a00040,10,10,155,134
  CONTROL "",140,"static",$1000000b,170,10,200,20
ENDDIALOG
SHOWDIALOG #0
@vvv //show content
DO
  GETEVENT //PEEKEVENT
  IF MOUSEK = 1 THEN takefind
LOOP UNTIL  MENU(1) = 4
CLOSEDIALOG  #0
PROCEDURE vvv
  a& = DlgDirList(DLG(0),V:a$,139,1,$0000 | $0001 | $0002 | $0004 | $0010 | $0020 | $2000 | $4000 | $8000)
RETURN
PROCEDURE takefind
  emptystr$ = SPACE$(16)
  BMOVE V:emptystr$,V:puffer$,16
  id& = SendMessage(DLGITEM(0,139),LB_GETCURSEL,0,0)
  VOID SendMessage(DLGITEM(0,139),LB_GETTEXT,id&,V:puffer$)
  tk$ = CHAR{V:puffer$}
  IF INSTR(tk$,"[") THEN @select // If a directory was selected
  _WIN$(DLGITEM(0,140)) =   tk$ + "                         "
RETURN
PROCEDURE select
  IF MID$(tk$,1,2) = "[-" AND MID$(tk$,4,2) = "-]"
    drive$ = MID$(tk$,3,1) + ":\"
    path$ = ""
  ELSE   IF MID$(tk$,1,1) = "[" AND MID$(tk$,2,1) <> "-"
    path$ = MID$(tk$,2,LEN(tk$) - 2)
    drive$ = ""
  ENDIF
  a$ = drive$ + path$  + CHR$(0)
  @vvv
RETURN


#: 96227 S12/GFA  (CIS:WINAPC)
    30-Dec-96  23:18:27
Sb: #96193-Directory Selection
Fm: Dave Barton 100355,1331
To: Peter Gammenthaler 101725,2705
Replies:   0

Hi Peter,

Many thanks for the code sample. It was not exactly what I was looking for, but it was a very usefull guide for me to work from.

For your information (and any other members of this forum) the following is my version of the Directory Selection Function. It works OK for both WIN 3.x & 95 filenames.

Thanks again for your help, it was much appreciated.

Kindest Regards
Dave


/* Demo Of Drive / Directory Selection Dialog
DLG 3D ON
TITLEW #1,"Press Right Mouse Button To Display Dialog"
OPENW #1
zb$ = CHR$(0),cr$ = CHR$(13)
DO
  PEEKEVENT
  IF MOUSEK = 2
    PRINT @GetDir$()
  ENDIF
UNTIL MENU(1) = 4
CLOSEW #1
DLG 3D OFF
/* Function To Return User Selected Drive & Directory For A Predifined File Name
FUNCTION GetDir$()
  LOCAL Done!,LbStyle%,Msg$,Choice$,Buffer$,a$,Path$ = "c:\"
  Msg$ = "Select A Directory Or Drive" + cr$ + "By Clicking On Your Choice" + cr$       /* User Info Message
  Msg$ = Msg$ + "In The Left Hand Window" + cr$ + "With Mouse Pointer." + cr$
  Msg$ = Msg$ + "When Required Path Is" + cr$ + "Displayed In The Window Above" + cr$ + "Select The 'OK' Button"
  Buffer$ = SPACE$(64) + zb$                                                /* Create A Good Sized Buffer
  a$ = Path$ + zb$                                                                   /* Null Terminated Copy Of Path String
  LbStyle% = LBS_HASSTRINGS | LBS_STANDARD | LBS_SORT | WS_TABSTOP | WS_BORDER | WS_VSCROLL | WS_CHILD
  DIALOG #20,100,100,400,250,"Select Directory For File",DS_MODALFRAME,-13,"Arial"  /* Create Selection Dialog
    CONTROL "",900,"listbox",LbStyle%,10,25,160,200
    CONTROL "",901,"edit",$10800080,180,25,205,20
    CONTROL "&OK",IDOK,"button",$50010000,185,190,90,28
    CONTROL "&Cancel",IDCANCEL,"button",$50010000,290,190,90,28
    CONTROL "Directories && Drives",886,"static",$10000001,10,4,160,20
    CONTROL "Selected Path",887,"static",$10000001,180,4,205,20
    CONTROL "",888,"static",$10000008,180,55,205,125
    CONTROL Msg$,889,"static",$10000001,185,60,195,115
  ENDDIALOG
  ~DlgDirList(DLG(20),V:a$,900,901,$0010 | $2000 | $4000 | $8000)    /* Only Drives & Directories In The Listbox
  SENDMESSAGE (DLGITEM(20,901)),WM_USER + 31,TRUE,0           /* Non-Editable Edit Box
  SHOWDIALOG #20                                                                 /* Display Selection Dialog
  DISABLEW WIN(1)                                                                  /* Reduces Possibilty Of Dialog Hiding Behind Window
  DO
    PEEKEVENT                                                                         /* I Am Not Sure Why But Sjouke recomends GETEVENT.
    /* Messaging Detection Used Only Functions Correctly With Mouse Selection
    /* Not Suitable For Keyboard Selection
    IF MENU(12) = 900 AND HIWORD(MENU(13)) = LBN_SELCHANGE      /* Listbox Selection Has Changed
      ~DlgDirSelect(DLG(20),V:Buffer$,900)                                 /* Put Selection Into Our Buffer
      Choice$ = CHAR{V:Buffer$}                                                 /* Transfer text from buffer to manipulation variable
      IF MID$(Choice$,2,1) = ":"                                                   /* Drive selected
        Path$ = Choice$ + "\"                                                        /* Restore Root Directory Backslash
      ELSE IF LEFT$(Choice$,2) = ".."                                         /* Next Directory Up Selected
        Path$ = LEFT$(Path$,SUB(RINSTR(Path$,"\"),1))             /* Strip last sub-directory from the path
        IF LEN(Path$) < 3                                                             /* If it is the root directory
          Path$ = Path$ + "\"                                                         /* Restore Root Directory Backslash
        ENDIF
      ELSE                                                                                   /* Next Directory Down Selected
        Choice$ = LEFT$(Choice$,SUB(LEN(Choice$),1))            /* Strip Returned Trailing Backslash
        IF LEN(Path$) > 3                                                             /* If Not the Root Directory
          Path$ = Path$ + "\"                                                        /* Add Backslash to existing path
        ENDIF
        Path$ = Path$ + Choice$                                                 /* Add Next Sub-Directory to existing path
      ENDIF
      a$ = Path$ + zb$                                                                /* Update Copy Of Path String
      ~DlgDirList(DLG(20),V:a$,900,901,$0010 | $2000 | $4000 | $8000)     /* Update Listbox & Display Selected Path
    ELSE IF MENU(6) = IDOK                                                    /* OK Button / Enter Key Selected
      Done! = TRUE                                                                    /* Set Function Termination Flag
    ELSE IF MENU(6) = IDCANCEL                                            /* Cancel Button / Esc Key Selected
      Path$ = "SELECTION CANCELLED"                                  /* Working Version Returns Null String
      Done! = TRUE                                                                    /* Set Function Termination Flag
    ENDIF
  UNTIL Done!                                                                          /* Terminate Dlg Proc When Flag Set
  ENABLEW WIN(1)                                                                 /* Make Main Window Active Again
  CLOSEDIALOG  #20                                                              /* Close The Dialog Box
  RETURN Path$                                                                      /* Return User's Selection
ENDFUNC


#: 96356 S12/GFA  (CIS:WINAPC)
    07-Jan-97  02:07:02
Sb: #Transparent BITBLT?
Fm: James V. Schumacher 104166,2104
To: Glynn Carey 106630,1060
Replies:   1

Hi Glynn,

I've been forced to conclude that you MUST use masks in Windows.   What I do is load my Macintosh bitmaps, which have white backgrounds, into an offscreen sprite memory device context (MDC).  Then, I use the code below to create a mask (where everything that is not white is black) for that bitmap in another offscreen MDC.  

        '
        'make mask
        hmono& = CreateBitmap(rect.right,rect.bottom,1,1,0)
        hnull& = SelectObject(maskMDC&,hmono&)
        SETDC maskMDC&
        DEFFILL 0
        PUT 0,0,pictureResHndl&
        FREEBMP hmono&

Then I use the following code (which is SLOW) to pixel by pixel change the white background in the spriteMDC to black.  Alternately, you could load a bitmap that already has a black background into the spriteMDC but I don't have that luxury because given my users.

      'add black background to spriteMDC&
      SETDC spriteMDC&
      // if pixel is white make black
      whtindex& = GETNEAREST(255,255,255)
      blkindex& = GETNEAREST(0,0,0)
      FOR i& = 0 TO width&
        FOR j& = 0 TO height&
          c% = POINT(i&,j&)
          IF c% = whtindex& THEN PSET i&,j&,blkindex&
        NEXT j&
      NEXT i&
      SETDC onScreenMDC&

Then, when I want to display the sprite I copy (using the STRETCH command) the mask, and then the sprite, into an offscrnMDC containing the background.  You must copy the mask with copymode% = SRCAND and the sprite with copymode% = SRCPAINT.  Then I copy from that offscrnMDC to the screen using copymode% = SRCCOPY.  This results in reasonably flicker free performance.

Sorry that I didn't find a better answer.  Just another way that the Mac has a superior OS. :)

James


#: 95536 S12/GFA  (CIS:WINAPC)
    21-Nov-96  11:06:12
Sb: #95526-Palette Purgatory
Fm: Sjouke Hamstra 100741,1036
To: Friedrich Rode 100602,702
Replies:   0

Hi Friedrich and others,

Palette maintanance is quite tricky as you might have noticed. I'll try to
explain.

There is only one system palette, which is a table of RGB colors ( always 16
or 256 entries depending on your VGA card) used by the system to display
anything you see on the screen. To display bitmaps correctly you need a
logical palette that should be mapped to system palette before drawing it
onto the screen. How do the system palette and logical palettes relate to
each other?
Windows reserves 20 colors from the system palette for its own use, this
means you should not change them (for instance with SetSystemPalettUse()).
Windows makes the rest of the entries (236) available to an application.
These 236 table entries are changed when you select and realize a logical
palette. Now, be aware, Windows determines itself where it puts the colors
from an applications logical palette. You can not tell Windows where to put a
particular color in its system palette.

Because of this Windows introduced logical palettes which are maintained by
the application. To illustrate the process, suppose you want to create and
use a palette with 256 grades of blue.
First create the logical palette:

  DIM PalEntries%(256)
  {V:PalEntries%(0)}.palVersion    = $0300
  {V:PalEntries%(0)}.palNumEntries = 256
  FOR i = 1 TO 256
    {V:PalEntries%(i)}.peRed = 0
    {V:PalEntries%(i)}.peGreen = 0
    {V:PalEntries%(i)}.peBlue = i
    {V:PalEntries%(i)}.peFlags = 0
  NEXT i
  hPal = CreatePalette(V:PalEntries%(0))
  ~SelectPalette(_DC(n),hPal,0)
  ~RealizePalette(_DC(n))

If you paid attention you might say: not all of these blue colors can't be
used, because Windows allows only 236 colors to be modified! And then you're
partly correct.
However when you select and realize this palette in a DC you HAVE all these
blue shades available at the locations you put them. That is if you select
COLOR 10 you get the color at index 10 of your palette (here: blue shade with
its component set to 10). Also when you use COLOR 255 you get pure blue not
white!!!

How does Windows do that?
After you have obtained a handle to a palette (hPal above) you must select it
into a DC and realize it, either as a foreground or a background palette.
Selecting and realizing a palette always come in a pair. This what Windows
does:

"Each color in the logical palette is color-matched to every color in the
system palette. The closest match is tracked. If an exact match is found, the
color is matched and the entry in the system palette is marked as used. If no
exact match exists, the Palette Manager looks for an entry that is unused. If
one is found, the logical color is set in the system palette at that entry,
and the entry is marked as used. A color in the system palette has thus been
changed. If there are no unused entries left in the system palette (the
palette is full), the logical color is mapped to the system palette entry
with the closest color match. Notice that the color could be mapped to a
color in the system palette that was set by the same logical palette."

Now back to the blue shade palette. Do you see what Windows does with the 20
blue shades that could NOT be mapped to a free slot in the system palette? It
maps those 20 blue shades to the closest color already in the system palette!
For instance it will almost certainly match the pure blue (entry 255 in the
logical palette) to pure blue in the reserved colors.

Windows acts as described above for foreground palettes (last parameter in
Selectpalette() is zero). If a background palette is being realized Windows
(last parameter in Selectpalette() is nonzero) maps the colors to the colors
in the sytem palette without adding new colors. If there are still entries in
the system palette that are marked as unused, the background palette can set
them. The foreground palette only has priority, not exclusivity.

The result of all this is demonstrated in the (first version) of my
LoadDib.GFW I posted in the  message to James (could you please check it out
as well?)

For animation the technique described is not suitable. You need, as you
stated yourself, the same logical palette for each bitmap. This is why I
wrote a new LoadImage function; it loads and converts bitmaps to a given
palette. To provide the bitmaps with the best possible colors it's most
convenient to load a bitmap with a rainbow palette. Now I'm still polishing
the LoadImage function and rainbow palette, because I noted some problems.
However to get the best result I need comments!!

Greetings,
SH


#: 96553 S12/GFA  (CIS:WINAPC)
    18-Jan-97  13:26:16
Sb: #96547-sndPlaySound file?
Fm: Dave Barton 100355,1331
To: James V. Schumacher 104166,2104
Replies:   0

Hello Again James,

Understand your frustration, PC's are a bit of a love / hate relationship for most of us.

To play simple waveform audio with 'sndPlaySound()' use the following:

OPENW #1
DLL #1,"MMSYSTEM.dll"
  DECL WORD sndPlaySound(l,w)   ' <- 2nd parameter is a WORD flag
ENDDLL
File$ = "C:\WINDOWS\MEDIA\CHORD.WAV" + CHR$(0) ' <- Replace with your filename
/* The filename must exist or the function will never return
SND_SYNC = &H0
SND_NODEFAULT = &H2
/* SND_FILENAME = &H20000         NOT A VALID FLAG FOR  sndPlaySound()
Done! = ^sndPlaySound(V:File$,SND_SYNC | SND_NODEFAULT)
FREEDLL 1
CLOSEW #1

>>One Microsoft knowledgebase document says sndPlaySound only works with Windows95 and NT but some of you are suggesting it works with Win3.1.   Another document and some of the VB books imply  that PlaySound ( ) works with Win3.1 but Sjouke (who I trust) makes me doubt that.<<

The sndPlaySound() function first appeared in the MultiMedia add-on for Windows 3.0, which was later incorporated into Windows 3.1 as a standard Windows component.

The PlaySound()  function  first appeared in the WIN32s (even Microsoft's own people are unclear on what precisly WIN32s is, but it was released to developers as a pre-cursor to the the release of the SDK's & DDK's for Windows 95 & NT3.51), and will not function (excuse the pun) in a 16 bit environment.

I think you are definitely right to trust  Sjouke, I have never know him to answer any question that he hasn't properly researched.

>>Final Question: does wavemix.dll work with both 3.1 and 95?  The documentation implies it does but before I switch over to using (in desperation!), can this be confirmed?<<

YES, the DLL header information clearly states 'Expected Windows Version: 3.10'.

Hope this reduces your blood pressure a little. :)

Regards, Dave


#: 96613 S12/GFA  (CIS:WINAPC)
    20-Jan-97  22:52:01
Sb: #96553-sndPlaySound file?
Fm: James V. Schumacher 104166,2104
To: Dave Barton 100355,1331 (X)
Replies:   0

Dave,

Thank you for trying to reduce my blood pressure ... it has been going up!  You are correct that specifying sndPlaySound(l,w) makes a sound in a file play.

HOWEVER, I've discovered that sndPlaySound only plays a sound in a resource, if the parameter list is (l,l).  Below is an example that illustrates this.

OPENW #1
path$ = CHR$(_DRIVE) + ":" + DIR$(0)
path$ = path$ + "\Waveres.dll"
hInst& = LoadLibrary(path$)
hrsc1& = FindResource(hInst&,"FANFARE","WAVE")
hwave1& = LoadResource(hInst&,hrsc1&)
wave1% = LockResource(hwave1&)
DLL #1,"MMSYSTEM.dll"
  DECL WORD sndPlaySound(l,l)  // does not play sound if l,w
ENDDLL
SND_SYNC = &H0 //play synchronously
SND_MEMORY = &H4 // use in memory waveform
f! = ^sndPlaySound(hwave1&,SND_MEMORY OR SND_SYNC)
~^sndPlaySound(NULL,SND_MEMORY OR SND_SYNC)
~FreeResource(hwave1&)
~FreeLibrary(hInst&)
FREEDLL 1
CLOSEW #1

If you'd like, I can send you the .dll.  Any ideas? ... because I need a solution that works with both forms of wav storage.  Oh Oh, pressures going up again!  I guess I better get busy testing Wavemix.dll.

James


#: 96670 S12/GFA  (CIS:WINAPC)
    22-Jan-97  12:01:00
Sb: #96636-MEMDC / BITBLT
Fm: Sjouke Hamstra 100741,1036
To: Friedrich Rode 100602,702
Replies:   0

Hi Friedrich,

A few suggestions.

The memdc has the DEFAULT_PALETTE selected, using COLOR implies the selection of an index color, which isn't the same as your windows palette color index. (You changed it by using LOADBMP.) Drawing in an offscreen bitmap requires the bitmap's palette to be selected... Sometimes it is easier to create an OPENW outside the physical screen and use it for LOADBMP and off-screen drawing. However, remember the palettes of the off screen window isn't the same as the on-screen window... Try to figure this out first and then ask me again.

BEGINPAINT generates a dc for the window which is set as the actual GFABasic dc, so _DC() reflects the current dc for the static control between BEGINPAINT and ENDPAINT. So skip GetDC().

Before using BITBLT you must select the bitmap into the memdc using SETBMP, see my BMPCOPY function in the BMP.DLL. As long as the bitmap is selected in the memdc it can't be used by PUT. Usually I create a local memdc and release it after I used it, this way the bitmap is freed.

Greetings, SH


#: 96707 S12/GFA  (CIS:WINAPC)
    23-Jan-97  15:05:15
Sb: #96680-Why GFA... Its better!
Fm: Sjouke Hamstra 100741,1036
To: James V. Schumacher 104166,2104
Replies:   0

Hi James,

That's quite an answer you gave me. I have to disapoint you concerning graphic manipulation and sound tools. There are a lot of third party DLLs and books on these topics, and they are easy to use from GFA. My main interest lies in GFABasic and its (lack of) capabilities. GFABasic omits some functions which I will try to provide with my BMP.DLL and/or in the Developement packs. I always concentrate on GFABasic and its interaction with Windows, and try to shine some light on items that aren't obvious or clear. The $20 is fixed, because I'll distribute it by e-mail only.

However, in my new book about Windows 95/NT I'll discuss some of these things because a lot of new functions are implemented in Windows 32 bit.

About the new BMP.DLL, I encountered a lot(!!) of problems with implementing the IMAGE control, the rest is finished. I'm still trying to locate the bugs. Some of the problems are due to the interpreter and some to the Windows palette manager. For instance an IMAGE control can't be placed in a dialog box because it is an overlapped window without palette awarness. Windows won't send palette messages to dialog boxes. Another problem has to do with the GFABasic window palettes, they seem to be locked or something and can be re-realized only after re-selecting or unrealizing. This is not according the documentation, I have to find out what's going on. And these are not the only problems... And as you might know programming isn't difficult, its locating the bugs that takes the time.

Greetings, SH


#: 96684 S12/GFA  (CIS:WINAPC)
    22-Jan-97  21:45:02
Sb: WAVEMIX (almost!)
Fm: James V. Schumacher 104166,2104
To: All
Replies:   0

Dave Barton (and anyone else who is multimedia),

Here is my first attempt at using WAVEMIX.DLL in GFABASIC.  It almost works in that, with both resources or files, it starts playing the sound ... but then it quits prematurely after a fraction of a second ... the sound should take several seconds.  Any idea why?

OPENW #1
path$ = CHR$(_DRIVE) + ":" + DIR$(0)
path$ = path$ + "\Waveres.dll"
hInst& = LoadLibrary(path$)
'
DLL #1,"Wavemix.dll"
  DECL WORD WaveMixGetInfo(l)
  DECL WORD WaveMixInit()
  DECL WORD WaveMixConfigureInit(l)
  DECL WORD WaveMixActivate(w,w)
  DECL LONG WaveMixOpenWave(w,l,w,l)
  DECL WORD WaveMixOpenChannel(w,w,l)
  DECL WORD WaveMixPlay(l)
  DECL WORD WaveMixFlushChannel(w,w,l)
  DECL WORD WaveMixCloseChannel(w,w,l)
  DECL WORD WaveMixFreeWave(w,l)
  DECL WORD WaveMixCloseSession(w)
  DECL WORD WaveMixPump()
ENDDLL
'
'*****BEGIN WAVEMIX GLOBAL PARAMETERS*****
'flags for WaveMixOpenWave()
gWMIXFile = &H1
gWMIXResource = &H2
gWMIXMemory = &H4
'flags for WaveMixOpenChannel()
gWMIXOpenSingle = 0 //open single channel specified by iChannel
gWMIXOpenAll = 1 //opens all the channels, iChannel ignored
gWMIXOpenCount = 2 //open iChannel Channels
'flags for WaveMixFlushChannel() & WaveMixCloseChannel()
gWMIXAll = &H1 //stops sound on all channels, iChannel ignored
gWMIXNoRemix = &H2
'
TYPE MIXPLAYPARAMS:
- WORD wSizeMixPlayParams
- WORD hMixSession
- WORD iChannel
- LONG lpMixWave
- WORD hWndNotify //window handle to notify if problems
- LONG dwFlagsMixPlayParams
- WORD wLoops  // number of loops -- &HFFFF means loop forever
ENDTYPE
'flag values for MIXPLAYPARAMS
gWMIXQueueWave& = &H0
gWMIXClearQueue& = &H1
gWMIXUselruchannel& = &H2
gWMIXHighPriority& = &H4
gWMIXWait& = &H8
MIXPLAYPARAMS:MixPlayParam.
'
TYPE WAVEMIXINFO:
- WORD wSizeWaveMixInfo
- CHAR *1 bVersionMajor$
- CHAR *1 bVersionMinor$
- CHAR *12 szDate$ // Mmm dd yyyy
- LONG dwFormats // see waveOutGetDevCaps requires synch device
ENDTYPE
'
TYPE MIXCONFIG:
- WORD wSizeMixConfig
- LONG dwFlagsMixConfig
- WORD wChannels //1 is MONO, 2 is stereo
- WORD wSamplingRate // 11,22,44 = 11025,22050,44100 Hz
ENDTYPE
'flag for MIXCONFIG
gWMIXChannels& = &H1
gWMIXSamplingRate& = &H2
MIXCONFIG:WaveMixConfig.
'
gMaxWaves = 7 // 0-7 (WaveMix supports up to 8)
DIM WMIXpointer(gMaxWaves) //pointers to identify WAVEMIX sounds
'*****END WAVEMIX GLOBAL PARAMETERS*****
'
'get handle to the mix session
hMixSession& = ^WaveMixInit()
'
index& = 0 //pointer number to use for sound
'
'do one or the other
'WMIXpointer(index&) = ^WaveMixOpenWave(hMixSession&,"Fanfare.wav",0,gWMIXFile) //from file
WMIXpointer(index&) = ^WaveMixOpenWave(hMixSession&,"FANFARE",hInst&,gWMIXResource) //from resource
'
'attempt to access all the wave channels
ret& = ^WaveMixOpenChannel(hMixSession&,0,gWMIXAll)
'
'Start mixing!
ret& = ^WaveMixActivate(hMixSession&,TRUE)
'
MixPlayParam.wSizeMixPlayParams = LEN(MixPlayParam.)
MixPlayParam.hMixSession = hMixSession&
MixPlayParam.iChannel = index& //channel number
MixPlayParam.lpMixWave = WMIXpointer(index&)
MixPlayParam.hWndNotify = 0 // could use WIN(WIN())?
MixPlayParam.dwFlagsMixPlayParams = gWMIXHighPriority&
MixPlayParam.wLoops = 0 //play it once only
'
'add the selected wave to the mix and play it
ret& = ^WaveMixPlay(*MixPlayParam.)
'
DELAY 3 //give sound enough time to finish
'
'clean up
ret& = ^WaveMixCloseChannel(hMixSession&,0,gWMIXAll)
WMIXpointer(index&) = ^WaveMixFreeWave(hMixSession&,WMIXpointer(index&))
ret& = ^WaveMixCloseSession(hMixSession&)
~FreeLibrary(hInst&)
FREEDLL 1
CLOSEW #1

James


#: 96796 S12/GFA  (CIS:WINAPC)
    27-Jan-97  23:52:24
Sb: Mask&Sprite Hint
Fm: James V. Schumacher 104166,2104
To: James V. Schumacher 104166,2104 (X)
Replies:   0

Hi,

I found a faster way to produce sprites with black backgrounds (needed for transparent bitmaps and animations) than the method I posted the other day (which was to change white pixels to black pixels, one by one).  Now, instead, I make sure that the bitmap that I want to turn into a sprite has white around the boundary.  Then I do the following:

      'make the mask
      hMask& = MEMDC(_DC())
      hmono& = CreateBitmap(pictWidth&,pictHeight&,1,1,0)
      hnull& = SelectObject(hMask&,hmono&)
      SETDC hMask&
      PUT 0,0,pictureH&
      SETDC gonScrnworld&
      '
      'add black background to picture
      hPictWithBlkBck& = MEMDC(_DC())
      hbmptemp& = CREATEBMP(pictWidth&,pictHeight&)
      SETBMP hPictWithBlkBck&,hbmptemp&
      SETDC hPictWithBlkBck&
      PUT 0,0,pictureH&
      whtindex& = RGB(255,255,255)
      DEFFILL 0
      COLOR 0
      ~ExtFloodFill(_DC(),0,0,whtindex&,FLOODFILLSURFACE)
      SETDC gonScrnworld&

The trade off is that the anything white on the inside of the bitmap will remain white.  Depending on your application, this may or may not be desirable.

James


#: 96800 S12/GFA  (CIS:WINAPC)
    28-Jan-97  02:14:11
Sb: WAVEMIX (yes!)
Fm: James V. Schumacher 104166,2104
To: ALL
Replies:   0

Hi,

It appears that the reason the sound in my WAVEMIX test program was stopping prematurely is that events need to be processed while the sound is playing.  I substituted a FOR/NEXT loop, with a PEEKEVENT call in it, for the delay and the sound played as it should.  Hopefully, there aren't many calls besides DELAY that stop WAVEMIX in this manner.  At least DELAY can be replaced with a routine that processes events.  Now to see if the rest of the WAVEMIX features work!!

James


#: 96801 S12/GFA  (CIS:WINAPC)
    28-Jan-97  02:14:14
Sb: sndPlaySound( ) AS!!!
Fm: James V. Schumacher 104166,2104
To: Sjouke Hamstra 100741,1036 (X)
Replies:   0

Sjouke,

I found the example in your book on the use of AS in the DLL declaration statement.  Using AS, the following DLL declaration seems to solve my problem!

DLL #1 "MMSYSTEM.DLL"
    DECL WORD sndPlaySoundFILE(l,w) AS 2   //use for sounds in files
    DECL WORD sndPlaySoundRES(l,l) AS 2  //use for resources
ENDDLL

I've only tested this on my Win96 system.  Is it safe to assume that it will also work on a Win3.1 system?  Also, will the ordinal value of sndPlaySound() in MMSYSTEM.DLL be 2 (I found it by trial and error) on all Windows3.1 and Windows95 computers?

Thanks for pointing me in the right direction ... and for writing your book in the first place!

James


#: 96821 S12/GFA  (CIS:WINAPC)
    29-Jan-97  09:44:01
Sb: #96801-sndPlaySound( ) AS!!!
Fm: Sjouke Hamstra 100741,1036
To: James V. Schumacher 104166,2104
Replies:   0

Hi James,

As I stated before, you may not change the type of the parameters of a DLL function. The parameters are passed via the stack and the sndPlaySound function expects a long integer and a word integer on the stack. Your sndPlaySoundFILE places two longs on the stack. In this particular case you're just lucky sndPlaySound doesn't crash. If you're interested why I'll explain.

The ordinal value of a DLL function can be found by Quick Viewing the DLL. The ordinal value isn't changed in newer MMSYSTEM.DLLs. However MS recommends the use of the name rather than its ordinal value, they don't guarantee ordinal values in future releases of DLLs.

Greetings, SH


