jeudi 31 mai 2012

Clipper: Comment retrouver les paramètres en ligne de commande

Si vous utilisez Harbour pour compiler votre code Clipper, vous pourrez trouver le petit bout de code ci-dessous vraiment utile :-)

   IF int_ParamCount > 0
     FOR int_LoopCounter = 1 TO int_ParamCount
       ? arr_Parameters[int_LoopCounter] 
     NEXT
   ENDIF


J'ai trouvé cette information sur ce Thread.

Je n'ai jamais cru que je retournerais vers un aussi vieux langage... il était pourtant si bien pensé.
C'est poursuivant le développement de notre application que je m’aperçoit que ni Dot.Net ni Python ne sont vraiment révolutionnaires.
Tout ce que je trouvais vraiment bien dans ces environnements existe aussi dans mon bon vieux Clipper d'il y a 20 ans.
Je sais même:
  • Imprimer en réseau
  • Faire de l'OleAutomation avec Excell !!!
  • Imprimer des étiquettes codes barres
  • Faire des appels stored/proc

Vive Harbour Project!


dimanche 13 mai 2012

Ubuntu 12.04 - Mettre les boutons à droite!

Si comme moi vous avez l'habitude, depuis quelques décennies, d'avoir vos boutons minimiser/maximiser/fermer en haut à droite de vos fenêtres vous aurez envie de remettre de l'ordre dans la configuration par défaut de Gnome sous Ubuntu 12.04.

Voici comment faire:
  1. Ouvrir l'application Applications | Outils systèmes | éditeur de configuration
  2. Dans l'arbre, localiser la branche Apps | MetaCity | Général
  3. Dans la listes des valeurs affichée, changer la valeur de button_layout en :minimize,maximize,close
 Et la modification est instantanée.
NB: la valeur d'origine de cette clé est "close,minimize,maximize:"

mardi 8 mai 2012

Clipper: Imprimer des étiquettes Code Barre sur un imprimante QL-570

C'est possible grâce à la combinaison:
  1. du pac-SDK de Brother, 
  2. Technologie COM 
  3. Harbour (compilateur Clipper Open-Source)
Harbour est un compilateur Clipper Open Source.
Il utilise lui même un compilateur C pour générer un exécutable Win32.
Pour notre part, nous utilisons MSVC (Visual C++ 8.0) puisque nous intégrons aussi Mediator (pour remplacer DBF par une DB PostGreSql).

Le projet Harbour dispose de nombreuses contributions, entre autre une concernant l'impression en mode RAW (super pour piloter une imprimante HP depuis du code Clipper) mais aussi une autre contribution  relative aux appels OLE (comprenez, aussi "COM").

L'exemple TestOle.prg d'Harbour
Le projet Harbour contient la contribution:
c:\hb30\contrib\hbwin\tests\testole.prg
qui démontre l'usage de COM depuis un projet écrit CLIPPER et compilé avec Harbour.

Croyez le ou pas MAIS CA MARCHE DU TONNERRE!!!
Ouvrir une feuille Excel, Ouvrir un document Word ou OpenOffice, démarrer InternetExplorer et naviger vers la page du projet Harbour. De petits exemple mais franchement bluffant pour une technologique qui date quand même de 20 ans!

Le plus dur est encore d'arriver à compiler le PRG en exécutable.
Je vous propose le petit fichier Batch suivant qui effectue toutes les étapes nécessaires.

Ses particularités sont:
  1. D'utiliser MSVC comme compilateur (il ***faut absolument*** lancer le batch depuis une "Invite de Commande Visual Studio 2008")
  2. De linker les bonnes librairies OLE (cherchez après OleAut32.lib & Ole32.lib)
  3. Link les librairies Mediator (MedNtx). Vous n'en aurez probablement pas besoin, vous pouvez donc enlever les références à
    %MEDDIR%\harbour\lib\%HBBUILD%\vc80\medntx.lib
    %MEDDIR%\harbour\lib\%HBBUILD%\vc80\cmnnet32.lib
Voici le batch ZZD-TestOle.bat qui compile le projet TestOle.PRG

rem RUN IT BY using the Visual Studio C++ compiler COMMAND LINE (via start menu)
rem   http://www.microsoft.com/visualstudio/en-us/products/2008-editions/express

REM set HBDIR to the directory where HARBOUR is installed
SET HBDIR=c:\hb30
REM set MEDDIR to the directory where Mediator is installed
SET MEDDIR=c:\medcl
REM set HBBUILD to the name of the xHarbour build (for ex. build80)
SET HBBUILD=build3000

%HBDIR%\bin\harbour -m testole.prg /i%HBDIR%\include/i%MEDDIR%\xharbour\include /dHBCL 
if errorlevel 1 goto error_end

cl -c /w /TP /GA /Gs /Zl /nologo /I%HBDIR%\include /dHBCL testole.c 
if errorlevel 1 goto error_end

link /OUT:TestOle.exe /subsystem:CONSOLE testole.OBJ %HBDIR%\lib\win\msvc\hbwin.lib %HBDIR%\lib\win\msvc\hbdebug.lib %HBDIR%\lib\win\msvc\hbvm.lib %HBDIR%\lib\win\msvc\hbrtl.lib %HBDIR%\lib\win\msvc\rddntx.lib %HBDIR%\lib\win\msvc\hblang.lib %HBDIR%\lib\win\msvc\hbrdd.lib %HBDIR%\lib\win\msvc\hbmacro.lib %HBDIR%\lib\win\msvc\hbpp.lib %HBDIR%\lib\win\msvc\hbcommon.lib %HBDIR%\lib\win\msvc\gtwin.lib %HBDIR%\lib\win\msvc\hbsix.lib %HBDIR%\lib\win\msvc\rddfpt.lib winspool.lib wsock32.lib kernel32.lib user32.lib advapi32.lib OleAut32.lib Ole32.lib %MEDDIR%\harbour\lib\%HBBUILD%\vc80\medntx.lib %MEDDIR%\harbour\lib\%HBBUILD%\vc80\cmnnet32.lib
if errorlevel 1 goto error_end

goto end

:error_end
echo !!!!!!!!!!!!!! ERROR IN ZZD-testole.BAT !!!!!!!!!!!!!!!!!!!!

:end


Une fois compilé, il est facile de s'apercevoir que les appels OLE fonctionnent assez bien.
J'ai personnellement fait mes test sous Win 7 64 bits (programme compilé en 32 bits)

Impression d'étiquettes sur une QL-570
L'article "QL-570: utilitaires pour imprimer facilement des étiquettes" présentait un bout de code vbs permettant d'imprimer une étiquette via l'interface COM du b-pac SDK de Brother.


Fort de mes premiers résultats, j'ai ajouté une fonction CLIPPER dans le programme TestOle.PRG me permettant de faire les appels COM depuis Clipper.
Cette fonction  Exm_PrintPac mime le fonctionnement du VBS en utilisant les capacités COM de harbour.
 STATIC PROCEDURE Exm_PrintPac()
    IF ( oObjDoc := win_oleCreateObject( "bpac.Document" ) ) != NIL
      ? oObjDoc:Open( "C:\Program Files (x86)\Brother bPAC3 SDK\Templates\NamePlate1.lbx" )
      
      oComp := oObjDoc:GetObject("objCompany")
      oComp:Text := "Brother Industries, Ltd."
      
      oComp2 := oObjDoc:GetObject("objName")
      oComp2:Text := "myself, Dodo"
      
      && ObjDoc.SetMediaByName ObjDoc.Printer.GetMediaName(), True
      oPrinter := oObjDoc:Printer
      mediaName = oPrinter:GetMediaName()
      ? mediaName
      
      oObjDoc:SetMediaByName( mediaName, .T. )
       
      oObjDoc:StartPrint( "Brother QL-570", 0 ) && Nom du document dans le spooler
      oObjDoc:PrintOut( 1, 0 ) && 1= nbre de copies
      oObjDoc:EndPrint()
      oObjDoc:Close()
      
   ELSE
      ? "Error: bpac.document not available. [" + win_oleErrorText()+ "]"
   ENDIF

   RETURN

Et comme attendu... une fois appelée, cette fonction sort la bonne étiquette.

Merci OTC!
Notre société migre un logiciel vieux de 20 ans vers PostGreSql (grâce à la technologie RDD), Harbour et Mediator.
Mediator est un produit OTC qui nous fournit la technologie RDD dont nous avons besoin et nous permet d'utiliser une base de données relationnel PostGreSql (à la place des fichiers DBFs).
Médiator est un produit très aboutit et performant!
Notre logiciel est d'ores et déjà en test sur Win 7 64 bits dans un environnement multi-utilisateurs.


Pour la première fois de ma vie de développeur j'ai rencontré un service support à classer dans la catégorie  "exceptionnel".
OTC fournit un support de qualité, compétant et endurant! (notre cas ne fût certainement pas l'un des plus simples).
A chaque embûche j'y ai trouvé de l'aide, que cela soit un problème de migration ou de compilation.
Si je remercie OTC aujourd'hui c'est parce que la compilation de OleTest.PRG regroupe une grande partie des connaissance que OTC m'a prodigué ces derniers mois (quand je parle d'endurance, ce n'est pas pour rien).
Mes remerciements vont plus particulièrement à Miss Bozena Potempa du service Support.

lundi 7 mai 2012

QL-570: utilitaires pour imprimer facilement des étiquettes

Dans mon long processus de migration de Clipper vers Harbour, je suis face à un problème en apparence épineux... en effet, il me faut imprimer des étiquettes Code Barre sur notre QL-570 en réseaux.

P-Touch Template & ESC/P
Au cours de mes recherches, je me suis aperçu que la méthode ci-dessous n'est pas compatible avec les QL-570. Il existe cependant une alternative (voir autre point plus bas)

Au cours de mes recherches, j'ai trouvé le logiciel P-Touch (visiblement de Brother) accompagné de PTouch Template et PTouch ESC/P (permettant de piloter l'imprimante avec des séquences d'échappement).

Vous trouverez plus d'informations depuis la section développement du site de brother.

Je me suis personnellement penché plus attentivement sur la vidéo suivante:


C'est de bon présage :-)

P-Touch Editor et b-pac SDK
L'option ESC/P n'est visiblement pas applicable pour une QL-570. C'est bien dommage car cela semblait pourtant parfait.
Visiblement, cela serait causé par le fait qu'une QL-570 fonctionne uniquement en mode raster (comprenez par envoi de données point-à-point/sous forme d'image). Dans ce cas, il est bien évidement difficile de commander l'imprimante avec des séquences d'échappement.

Par contre, il est possible de contourner le problème à l'aide d'une interface COM.
Brother propose P-Touch Editor, un éditeur d'étiquette qui permet de préparer ses étiquettes et de nommer les différentes zones. Une fois sauvée, cette étiquette peut devenir un modèle (template pour les initiés).

Il est possible de se procurer séparément b-pac SDK. Ce dernier est une interface COM permettant de piloter l'impression de P-Touch editor (recharger le modèle, modifier le contenu des zones nommées, lancer l'impression).

Des exemples fournis avec le SDK, j'ai tiré  NamePrn.vbs, exemple qu'il m' fallut modifié pour le faire fonctionner.
Pour cause, le répertoire mentionné par sDataFolder n'était pas correct (le (x86) pour un Windows 64 bits). et j'ai également précisé le nom de l'imprimante dans StartPrint (le nom tel que connu par Windows dans le volet Configuration|imprimante).
Sinon cela fonctionne :-)

' b-PAC 3.0 Component Sample (Instant Name Plate)
' (C)Copyright Brother Industries, Ltd. 2009
'
'<SCRIPT LANGUAGE="VBScript">
 ' Data Folder
 Const sDataFolder = "C:\Program Files (x86)\Brother bPAC3 SDK\Templates\"
 DoPrint(sDataFolder & "NamePlate1.lbx")

 '*******************************************************************
 ' Print Module
 '*******************************************************************
 Sub DoPrint(strFilePath)
  Set ObjDoc = CreateObject("bpac.Document")
  MsgBox( strFilePath )
  bRet = ObjDoc.Open(strFilePath)
  If (bRet <> False) Then
    MsgBox("OPEN :-) ")
   ObjDoc.GetObject("objCompany").Text = "Brother Industries, Ltd."
   ObjDoc.GetObject("objName").Text = "John Smith"
   ObjDoc.SetMediaByName ObjDoc.Printer.GetMediaName(), True
   ObjDoc.StartPrint "Brother QL-570", 0
   ObjDoc.PrintOut 1, 0
   ObjDoc.EndPrint
   ObjDoc.Close
  End If
  
    MsgBox("Hello world")
  Set ObjDoc = Nothing
 End Sub


Ressources utiles