Example 13: Xprint a table opened with NeoDBPro

Topics related to David de Argentina's NeoThinBasic plug-in.

Moderator: Neosoft Support

Post Reply
David de Argentina
Posts: 1596
Joined: Mon Apr 04, 2005 4:13 pm
Location: Buenos Aires, Argentina
Contact:

Example 13: Xprint a table opened with NeoDBPro

Post by David de Argentina »

This sample shows how to Open a Access Database using NeoBookDBPro, show a table, and ListPrint all table using XPrint.
You can see how to thinBasic executes NeoBook actions (Call the function that change the record of the table) and get the record field values

For any reason i don't know, program does not work on debug mode.
Both plugins (NeoThinBasic.nbp & NeoBookDBPro.nbr) must not be compiled into the exe.

Perhaps Dave can tell me the reason of this abnormal behavior....

Download link:

https://app.box.com/s/xb916k0g7c18coibjmgs

Enjoy !
Neosoft Support
NeoSoft Team
Posts: 5628
Joined: Thu Mar 31, 2005 10:48 pm
Location: Oregon, USA
Contact:

Re: Example 13: Xprint a table opened with NeoDBPro

Post by Neosoft Support »

For any reason i don't know, program does not work on debug mode.
When I run this sample from NeoBook (test mode) I get an access violation error after the print dialog appears. However, the compiled version works. I have no idea why that would happen, but it may be that the memory overwrite that causes the AV error is still occurring but for some reason doesn't trigger an error message.
NeoSoft Support
David de Argentina
Posts: 1596
Joined: Mon Apr 04, 2005 4:13 pm
Location: Buenos Aires, Argentina
Contact:

Re: Example 13: Xprint a table opened with NeoDBPro

Post by David de Argentina »

Hi Dave,

I had detected the problem.

The NeoBook application "loads" the plugin into memory.

As the plugin creates a kind of "bubble" between NeoBook and thinBasic, both, NeoBook runtime and thinBasic runtime (the thinCore.dll) need to refer to the same instance of the plugin, in order to work properly.

On Debug Mode, NeoBook uses the installed plugin into the whole NeoBook enviroment.
Sometimes, the plugin is not in the same folder of the application.

On Execution time, NeoBook Runtime uses the plugin placed into the same folder of the application.

The solution is uninstall the plugin installed into the NeoBook enviroment and reinstall the NeoThinBasic.nbp one located on the same folder of the application.

Reinstalling the plugin located on the same folder of the program, does the program runs fine in Debug Mode.

Perhaps if you add into the Menu Options -> Install Plugins an option like

"if exists, use the plugin located on the Pub Folder for Debug Mode"

To avoid this error

Thanks !
David de Argentina
David de Argentina
Posts: 1596
Joined: Mon Apr 04, 2005 4:13 pm
Location: Buenos Aires, Argentina
Contact:

Re: Example 13: Xprint a table opened with NeoDBPro

Post by David de Argentina »

Sample updated.

Now, all columns are well formated and Left/Center/Right aligned.

Replace the Biblio.tBasic file with this one:

Code: Select all

uses "XPRINT"
uses "UI"

Declare SUB PlayScript Lib "NeoThinBasic.nbp" (BYVAL Script as string)
Declare SUB SetVariable Lib "NeoThinBasic.nbp" (BYVAL Variable as String, BYVAL sValue as String)
Declare FUNCTION GetVariable Lib "NeoThinBasic.nbp" (ByRef VarName AS STRING) as String
Declare FUNCTION GetObjectHandle Lib "NeoThinBasic.nbp" (ByRef sname AS STRING) AS LONG

%ID_Report = 2000       
%ID_List = 2001
%ID_Close = 2002
%Rows_Per_Page = 50

Global hDlg, page as long
Dim dx_offset(6), dw(6), dh(6) as long
Dim dText(6), dValue(6), dPad(6)  as string
dim ClientWidth, ClientHeight     as long
dim SizeWidth, SizeHeight         as long
dim ppiX, ppiY                    as long
dim mLeft, mTop, mRight, mBottom  as long
dim Quality           as long
dim Orientation       as long
dim DC                as dword
dim CurrentPrinter    as string

Function TBMain ()
  DIALOG NEW pixels, 0, "", 0, 0, 100, 40, %WS_SYSMENU, 0 TO hDlg
  DIALOG SHOW modeless hDlg, call dlgCallback
end function

callback function dlgCallback() as long    
  SELECT CASE cbMsg
    case %WM_INITDIALOG
      Dialog SHOW STATE hDlg, %SW_HIDE
    CASE %WM_COMMAND
      SELECT CASE cbctl
        CASE %ID_Report
        CASE %ID_List
          Print_List
        CASE %ID_CLOSE
          dialog end
    END SELECT           
  END SELECT
End Function


Sub Print_List ()
Local sAction, sVar as string
Local i, j, dy, counter, records, bcolor as long
local d1,d2,d3,d4,d5,d6 as string
local nwidth, R_offset as long

xprint_attach "choose", "thinBasic sample spool file"
  
CurrentPrinter = xprint$
if CurrentPrinter <> "" then
  'xprint_set(%XPRINT_set_orientation, 2)
  'xprint_scale(1, 1, 1000, 1000)
       
  xprint_get(%XPRINT_GET_DC , DC)
  xprint_get(%XPRINT_GET_CLIENT       , ClientWidth, ClientHeight)
  xprint_get(%XPRINT_GET_SIZE         , SizeWidth  , SizeHeight  )
  xprint_get(%XPRINT_GET_ppi          , ppiX       , ppiY        )
  xprint_get(%XPRINT_GET_MARGIN       , mLeft, mTop, mRight, mBottom)
  xprint_get(%XPRINT_GET_orientation  , Orientation)
  xprint_get(%XPRINT_GET_quality      , Quality)
  
  ' Grid titles
  records = val(GetVariable("Biblio.Titles.$RecCount"))
  counter = 0
  Page = 1
  List_GetInfo
  List_Titles


  for j = 1 to records

    ' calculate rows x page
    counter = counter + 1
    if counter >= %Rows_Per_Page then
      counter = 1
      Page = Page + 1 
      xprint_formfeed         
      List_Titles
    End if

    For i = 1 to 6 'Columns
      List_GetInfo
 
      dy = 400 + ((counter-1)*60) ' offset of the row

      if j/2 = j\2 then
        bColor = RGB(255,255,255)
      else
        bColor = RGB(245,245,245)
      end if

      XPRINT_box( dx_Offset(i), dy, dx_Offset(i)+dw(i), dy+60, 0, RGB(0,0,0),bColor)

      ' print the field
      xprint_font "Courier New", 8, 0
      xprint_color rgb(0, 0, 0)
      Select case dPad(i)

        case = "L"  ' Left align
          xprint_set(%xprint_set_pos, dx_Offset(i), dy+10)

        Case = "C"  ' Center align
          nwidth = XPRINT_GetTextWidth(dValue(i))
          R_offset = ( dw(i) - nwidth ) \ 2
          xprint_set(%xprint_set_pos, dx_Offset(i)+R_offset , dy+10) 

        Case = "R"  ' Right align
          nwidth = XPRINT_GetTextWidth(dValue(i))
          R_offset = dw(i) - nwidth - 10
          xprint_set(%xprint_set_pos, dx_Offset(i)+R_offset , dy+10) 

      end Select

      xprint dValue(i)

    Next i
    ' change the record
    sAction = "Gosub " & $DQ & "GoNext" & $DQ
    PlayScript sAction
  Next j
   
  xprint_formfeed
  xprint_close
else
  msgbox 0, "No printer selected."
end if
End Sub  

Sub List_Titles ()
Local i, dy as long
local nwidth, R_offset as long

  xprint_box(0, 0, SizeWidth, ClientHeight, 0)

  ' Main tittle
  xprint_font "Arial", 24, 0
  xprint_set(%xprint_set_pos  , 100, 100)
  xprint "List of Table Titles of Biblio.mdb - Page: " & str$(Page)

  for i = 1 to 6
    dy = 300
    XPRINT_box( dx_Offset(i), dy, dx_Offset(i)+dw(i), dy+100, 0, RGB(0,0,0), RGB(255,245,245))
    xprint_font "Arial", 9, 0
    xprint_color rgb(185, 28, 15)

    Select case dPad(i)

      case = "L"  ' Left align
        xprint_set(%xprint_set_pos, dx_Offset(i), dy+30)

      Case = "C"  ' Center align
        nwidth = XPRINT_GetTextWidth(dText(i))
        R_offset = ( dw(i) - nwidth ) \ 2
        xprint_set(%xprint_set_pos, dx_Offset(i)+R_offset , dy+30) 

      Case = "R"  ' Right align
        nwidth = XPRINT_GetTextWidth(dText(i))
        R_offset = dw(i) - nwidth - 10
        xprint_set(%xprint_set_pos, dx_Offset(i)+R_offset , dy+30) 

    end Select
    xprint dText(i)
  Next i
End sub

Sub List_GetInfo ()

  ' dw = width of the column
  ' dx_Offset = start point x of the column
  ' dText = Header Title
  ' dPad = could be: L for Left align, C for Center Align, R for Right Align

  ' First Column: ISBN -> width: 10%  
  dw(1) = (ClientWidth-200) \ 10
  dx_Offset(1) = 100
  dText(1) = " ISBN"
  dPad(1) = "L"

  ' Second Column: Title -> width: 50%  
  dw(2) = (ClientWidth-200) \ 2
  dx_Offset(2) = dx_Offset(1)+dw(1)
  dText(2) = "  Title"
  dPad(2) = "L"

  ' Third Column: PubID -> width: 5%  
  dw(3) = (ClientWidth-200) \ 20
  dx_Offset(3) = dx_Offset(2)+dw(2)
  dText(3) = "Pub ID"
  dPad(3) = "C"

  ' Fourth Column: Price -> width: 10%  
  dw(4) = (ClientWidth-200) \ 10
  dx_Offset(4) = dx_Offset(3)+dw(3)
  dText(4) = " Price"
  dPad(4) = "R"

  ' Fiveth Column: Pages -> width: 5%  
  dw(5) = (ClientWidth-200) \ 20
  dx_Offset(5) = dx_Offset(4)+dw(4)
  dText(5) = "Pag"
  dPad(5) = "R"

  ' Sixth Column: Year -> width: 10%  
  dw(6) = (ClientWidth-200) \ 10
  dx_Offset(6) = dx_Offset(5)+dw(5)
  dText(6) = " Year"
  dPad(6) = "C"

  'Get the Fields value
  dValue(1) = GetVariable("Biblio.Titles.ISBN")
  dValue(2) = " " & GetVariable("Biblio.Titles.Title")
  dValue(3) = GetVariable("Biblio.Titles.PubID")
  dValue(4) = format$(val(GetVariable("Biblio.Titles.Price")),"0.00")
  dValue(5) = GetVariable("Biblio.Titles.Pages")
  dValue(6) = GetVariable("Biblio.Titles.Year Published")

End sub
Enjoy !
Neosoft Support
NeoSoft Team
Posts: 5628
Joined: Thu Mar 31, 2005 10:48 pm
Location: Oregon, USA
Contact:

Re: Example 13: Xprint a table opened with NeoDBPro

Post by Neosoft Support »

Normally, you shouldn't need to have more than one copy of the plug-in and other DLLs on your hard drive. In design/test mode, the NeoBook pub will load the plug-in from the same folder where NeoBook itself loads the plug-in. After compiling, the plug-in will be extracted and loaded from the temp folder.

Are you using nbAddFile to include all of the dlls required by your plug-in in your nbRegisterPlugIn proc? In theory this is supposed to eliminate the need to manually deal with all those extra files.
NeoSoft Support
David de Argentina
Posts: 1596
Joined: Mon Apr 04, 2005 4:13 pm
Location: Buenos Aires, Argentina
Contact:

Re: Example 13: Xprint a table opened with NeoDBPro

Post by David de Argentina »

Hi Dave,

Perhaps i didn't explain well...

When you open NeoBook, you can see into the splash window, all plugins that are loading...
This plugins could be located on any place of the hard disk...

The thinBasic side needs to connect with the plugin, using:
Declare Function Myfunction Lib "neothinbasic.nbp" Alias "MyFunction" (ByVal var1 as long.... etc)

If the Lib (in this case, the plugin) is not located on the same folder of the Neobook program, i need to change the Lib definition to the folder were the plugin is located (tempdir, or any folder)

If i need install the whole program (Neo program + ThinBasic program + plugins + another files) into another machine, i need know were the plugins is located.

Is for this reason i suggest to the plugin users, do not compile the needed files into the exe, to prevent extract this in another folders.

On debug time, NeoBook uses the plugin loaded at splash screen, from the folder that is informed when the plugin were added.(probablely saved into the registry)

This plugin is used to the Neo program to launch the thinBasic program.

when thinBasic program is being executed, and find the line:
Declare Function Myfunction Lib "neothinbasic.nbp" Alias "MyFunction" (ByVal var1 as long.... etc)
thinBasic program uses the neothinbasic.nbp that is found into the same folder...
There are 2 instances of the neothinbasic.nbp into memory... and we get the Access Violation error message.


You said:

".. the NeoBook pub will load the plug-in from the same folder where NeoBook itself loads the plug-in."

This is the problem. NeoBook load a plugin from the registry load location and thinBasic load the plugin from [Pubdir]

In the mean time, problem is solved.
If another plugin user reports the same problem, i can tell how to bypass the error

I think if you add an option for adding plugins that set something like:

"If exists an equal named plugin into the pub folder, unload the loaded at (neobook) startup plugin and use the plugin into the pub folder for debug time"

The problem will be bypassed.

On the other hand, i don't need use nbAddFile because plugin can load the exported functions of the thinCore.dll library, using the standart declarations of the include file.

it is pretty confusing... isn't it ?

Thanks !
David de Argentina
Neosoft Support
NeoSoft Team
Posts: 5628
Joined: Thu Mar 31, 2005 10:48 pm
Location: Oregon, USA
Contact:

Re: Example 13: Xprint a table opened with NeoDBPro

Post by Neosoft Support »

This is confusing.
when thinBasic program is being executed, and find the line:
Declare Function Myfunction Lib "neothinbasic.nbp" Alias "MyFunction" (ByVal var1 as long.... etc)
thinBasic program uses the neothinbasic.nbp that is found into the same folder...
Your plug-in can determine where it was loaded from using the GetModuleFileName function. For example:

function GetModuleName: string;
var szFileName: array[0..MAX_PATH] of Char;
begin
FillChar(szFileName, SizeOf(szFileName), #0);
GetModuleFileName(hInstance, szFileName, MAX_PATH);
Result := szFileName;
end;

Would this be helpful in sorting out this problem?

I think it would be simpler for users if they didn't have to treat this plug-in differently than all the others.
NeoSoft Support
User avatar
dec
Posts: 1663
Joined: Wed Nov 16, 2005 12:48 am
Location: Spain
Contact:

Re: Example 13: Xprint a table opened with NeoDBPro

Post by dec »

Hello,

I don't know if this can help, but... when one of my plugins requires some DLL's I put these (the installer copy) into the plugin installation folder, and, for the user convenience, also into the plugin samples directory. In this way the plugin can load the appropiate files when needed, because always can found into the plugin directory the appropiate files, and also the plugin samples can be play without problems, since can count with their own DLL's copies.

This mean that the user can install and play the plugin samples without problems in designtime, and, on the other hand, the help file remember to the users that the plugin requires certain DLL's which must be copied aside of the publication executable to avoiding runtime problems. Anyway (in runtime) the plugin must raise the appropiate error if the requires files cannot be found.
.
Enhance your NeoBook applications!
.
58 plugins, 1131 actions and 233 samples
.
NeoPlugins website: www.neoplugins.com
.
David de Argentina
Posts: 1596
Joined: Mon Apr 04, 2005 4:13 pm
Location: Buenos Aires, Argentina
Contact:

Re: Example 13: Xprint a table opened with NeoDBPro

Post by David de Argentina »

Thanks Dave & dec.

Dave: one more time, you have reason :lol:

In my test, i can get the hinstance of the plugin doing:

Code: Select all

DIM zFileName AS ASCIIZ * 400
GetModuleFileName GetModuleHandle(BYCOPY "NeoThinBasic.nbp" + $NUL), zFileName, 400
msgbox TRIM$(zFileName)
Ok, first problem solved.

Now, i trying to compile the plugin within the executable.

When program runs, NeoBook runtime does this actions
* Extracts the plugin from the executable
* Save into the [TempDir]folder with a random name (like FG21AC97.nbp)

As this time, I don't have idea what is the name of the plugin.

I tryed:

Code: Select all

DIM zFileName AS ASCIIZ * 400
GetModuleFileName GetModuleHandle(BYCOPY $NUL), zFileName, 400
msgbox rtrim$(zFilename)
Doing this, i get the fullpath and name of the executable, not the plugin.

Are there another way to get the hinstance of the plugin ?

Thanks in advance,
David de Argentina
User avatar
HPW
Posts: 2571
Joined: Fri Apr 01, 2005 11:24 pm
Location: Germany
Contact:

Re: Example 13: Xprint a table opened with NeoDBPro

Post by HPW »

In delphi I use:

Code: Select all

GetModuleFilename(hinstance, @Buffer[0], BufferSize);
In Delphi hinstance is a global variable.

http://my.safaribooksonline.com/book/pr ... -hinstance

Regards
Hans-Peter
David de Argentina
Posts: 1596
Joined: Mon Apr 04, 2005 4:13 pm
Location: Buenos Aires, Argentina
Contact:

Re: Example 13: Xprint a table opened with NeoDBPro

Post by David de Argentina »

Thanks Hans-Peter,

Following some stuff over the net, I'm trying to catch the hInstance via de LIBMAIN entrance function

Now, this function is:

Code: Select all

FUNCTION LIBMAIN(BYVAL hInstance AS DWORD, _
                 BYVAL Reason    AS LONG, _
                 BYVAL Reserved  AS LONG) AS LONG
   SELECT CASE Reason
      CASE %DLL_PROCESS_ATTACH
			if len(DLLLocation) = 0 then
			  DIM zFileName AS ASCIIZ * 400
           GetModuleFileName hInstance, zFileName, 400
			  DLLLocation = rtrim$(zFilename)
           msgbox "hinstance: " & rtrim$(zFilename)
			end if  
			
        FUNCTION = %True
        EXIT FUNCTION
      CASE %DLL_PROCESS_DETACH
        FUNCTION = %True
        EXIT FUNCTION
      CASE %DLL_THREAD_ATTACH
        FUNCTION = %True
        EXIT FUNCTION
      CASE %DLL_THREAD_DETACH
        FUNCTION = %True
        EXIT FUNCTION
    END SELECT 			  
END FUNCTION
On debug time (when Neobook load the plugin from the saved location from the registry) all works fine.

On execution time, Attach process is executed 2 times:
First time, returns the correct plugin fullpath & name, something like "[PubDir]DC83FA31.nbp"
Second time, returns the saved location for the plugin loaded by NeoBook itself, similar debug time

You can see i'm trying to bypass more than one pass for the code with "if len(DLLLocation) = 0 then", but process is executed twice, and lost the real plugin location.

Any ideas ?
David de Argentina
David de Argentina
Posts: 1596
Joined: Mon Apr 04, 2005 4:13 pm
Location: Buenos Aires, Argentina
Contact:

Re: Example 13: Xprint a table opened with NeoDBPro

Post by David de Argentina »

Problem solved.

Now, the plugin works fine in Debug Time and Execution Time.
PUB can be compiled with the plugin embedded within the executable.

Next week i will release an update of the plugin, with this changes and a new function for encrypt .tbasic files and execute them

Thanks !
David de Argentina
Neosoft Support
NeoSoft Team
Posts: 5628
Joined: Thu Mar 31, 2005 10:48 pm
Location: Oregon, USA
Contact:

Re: Example 13: Xprint a table opened with NeoDBPro

Post by Neosoft Support »

I'm glad you were able to figure it out! I think this will be much easier for users to manage.
NeoSoft Support
David de Argentina
Posts: 1596
Joined: Mon Apr 04, 2005 4:13 pm
Location: Buenos Aires, Argentina
Contact:

Re: Example 13: Xprint a table opened with NeoDBPro

Post by David de Argentina »

Plugin Updated.

Actual Version is 1.06

see:
http://neosoftware.com/community/viewto ... 34&t=20219

Thanks !
Post Reply