frc691
Messages postés7Date d'inscriptionlundi 19 décembre 2005StatutMembreDernière intervention 2 juin 2009
-
26 mai 2009 à 17:55
frc691
Messages postés7Date d'inscriptionlundi 19 décembre 2005StatutMembreDernière intervention 2 juin 2009
-
2 juin 2009 à 17:42
Bonjour,
Au cours du traitement de fichiers de coordonnées x,y, j'en retire des polaires qui sont affichées dans un formulaire spécifique comprenant textes et graphiques. Mon but est de transformer, à la volée, ces formulaires en pages pdf par le biais de CuteWriter tout en agrémentant un fichier .sql pour la mise à jour d'une DB. En gros, le principe fonctionne et j'obtiens bien le résultat voulu, sauf que :
- le soft tourne parfois plusieurs fois sur la même entrée pendant l'impression et le .sql grossit de plusieurs doublons (j'en fais mon affaire !:),
- certains fichiers sont traités mais ne sont pas imprimés ! Car il me faut définir à chaque fois le nom du fichier destination (comme pour toute imprimante de type fichier),
Une petite précision : pour le traitement de 1 à 5 fichiers : tout va bien ! Au delà, c'est la pagaille. Pour info, j'ai en tout plus de 2000 fichiers à traiter ainsi en mode batch, par lots de 55 à près de 1000.
Voici mon code d'impression (l'impression se fait par des printer.... et se termine par printer.EndDoc) :
Private Declare Sub Sleep Lib "kernel32" (ByVal dwTime As Long)
Public Sub Imprime_Polaire()
Dim Ordre As String
'Impression du formulaire de Polaire sur PDF CutWriter / imprimante par défaut
frmImgPol.Imprimer 'Se termine par printer.enddoc
'Transmission du nom de fichier et validation
Sleep 500 'Temps de démarrage de la boîte de dialogue d'impression
Ordre = App.Path & "" & NomCatalogue & "\images-pol" & NomDat & ".pdf{ENTER}"
SendKeys Ordre, True
Sleep 20000 'Temps de traitement de l'impression en pdf
End Sub
J'ai tenté de nombreuses permutations et valeurs d'attente, sans résultat probant ! Si l'un de vous peut ne serait-ce que tenter de m'orienter vers une solution viable :je suis preneur !
Il doit sans doute y avoir qqch auquel je n'ai pas songé :-) mais là, je ne vois plus !!! J'ai vainement tenté la voie de tester la fermeture de la boîte de dialogue d'impression via vb6, peut-être est-ce pourtant une possibilité ?!
Si vous avez des idées...
Cordialement,
François
cs_Jack
Messages postés14006Date d'inscriptionsamedi 29 décembre 2001StatutModérateurDernière intervention28 août 201579 27 mai 2009 à 01:10
Salut
Manque de précision.
Tu parles de boucle de traitement, mais on ne vois que la procédure pour un seul.
Difficile de te dire pourquoi ça bugue.
De toute façon, l'utilisation de SendKeys est toujours hasardeuse puisqu'elle se base (dans ton cas) sur une temporisation.
Tout le monde aura remarqué que l'appel d'un programme n'a jamais la même durée, environnement oblige.
Donc, la seule solution est de te pencher sur la détection (par les APIs) d'une fenêtre par son nom (caption), ça te donnera un Handle.
Quand tu seras sûr d'avoir obtenu cette info, c'est que la fenêtre sera bien présente, alors, tu pourras sans crainte envoyer ton SendKeys.
Ensuite, après la validation, cela durera aussi un certains temps.
Pendant cette période, une (autre ?) fenêtre est surement ouverte --> même principe : retrouver son handle, puis attendre que ce handle disparaisse, tu seras alors sûr que la tâche est terminée et tu pourras penser en démarrer une autre.
frc691
Messages postés7Date d'inscriptionlundi 19 décembre 2005StatutMembreDernière intervention 2 juin 2009 27 mai 2009 à 18:49
Bonjour Jack,
Je te remercie pour ta réponse. Je vais de ce pas me pencher sur ce qui me semblait être la meilleure solution (Api's et Handles).
Effectivement, seule la procédure présentée me pose souci. Le reste du traitement fonctionne parfaitement. Il est en boucle et demande beaucoup de temps de traitement intermédiaire (soufflerie numérique) et plusieurs machines tournent sur le même traitement en cross-domain. Cette procédure dite d'impression est appelée par le serveur à la fin de chaque traitement, d'où cette présentation.
A te relire en cas de besoin :-),
Cordialement,
François
frc691
Messages postés7Date d'inscriptionlundi 19 décembre 2005StatutMembreDernière intervention 2 juin 2009 28 mai 2009 à 14:57
Bonjour !!!
Je ne connaissais pas ce outils et les conseille à tous (http://logiciel.codes-sources.com/logiciels/API-Guide-197.aspx et <WinID>) !
La solution que j'ai trouvée n'est pas à proprement parler très élégante (scrutation et non bufferisation), cependant elle fonctionne avec au moins 100 impressions successives, le tout, sans avoir - apparemment - de pb de pile, ni de mémoire.
Pour ceux que cela intéresse, la solution trouvée est la suivante :
Créer un module avec :
Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Boolean
Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hwnd As Long) As Long
Public HandlePrn As Long
Public HandlePrnOld As Long
Public NbImp As Integer
Public Function ChercheWindowsProc(ByVal hwnd As Long, ByVal lParam As Long) As Boolean
Dim sSave As String, Ret As Long
Ret = GetWindowTextLength(hwnd)
sSave = Space(Ret)
GetWindowText hwnd, sSave, Ret + 1
If (Trim(sSave) = "Enregistrer sous") Then
HandlePrn = hwnd
End If
'Continue l'énumeration.
ChercheWindowsProc = True
End Function
Et dans le code du formulaire (créer un bouton cmdImprim) :
Private Sub Form_Load()
HandlePrn = -1 // Handle de la nouvelle boite de dialogue d'impression.
HandlePrnOld = -1 // Handle de l'ancienne pour comparaison ultérieure.
NbImp = 0 // Nb de demande d'impressions.
End Sub
Private Sub cmdImprim_Click() // Lancement des impressions successives.
For NbImp = 0 To 100: Impression: Next NbImp
End Sub
Private Sub Impression()
Dim Ordre As String // Nom du fichier à enregistrer à intégrer dans la dialogbox.
'Impression de la page // pour exemple.
'Fonctionne très bien avec 198 contrôles à imprimer sur la même page comme avec une seule ligne graphique.
'Testé avec CuteWriter, SymantecFax et Phantom AutoCad.
Printer.Line (0, 0)-(1000, 1000)
Printer.EndDoc
'Attente d'un nouveau handle de fenêtre "Enregistrer sous"
While HandlePrn = HandlePrnOld
EnumWindows AddressOf ChercheWindowsProc, ByVal 0&
Wend
'Sauvegarde du nouveau handle pour comparaison ultérieure
HandlePrnOld = HandlePrn
'Envoi de la séquence de définition du nom de fichier
Ordre = App.Path; "\test"; CStr(NbImp); ".pdf{ENTER}"
SendKeys Ordre, True
End Sub
J'ai tenté de rendre la boîte de dialogue d'impression non-visible, mais cela ne fait pas gagner un temps fou (moins de 1%). Un constat : le serveur peut fonctionner tout seul, tout en faisant autre chose. Cependant, il vaut mieux ne pas changer de tâche ni surtout utiliser de commandes clavier (cela paraît évident !) pendant le traitement. Le gain de temps d'avec l'utilisation de Sleep paraît être de l'ordre de 30 à 65% selon les besoins externes et se défie de tous les temps de demandes extérieures. Cela me rapelle le vieux temps des noyaux temps réel en i8085 ! Sinon, la gestion d'erreur est relativement simple à assurer,
Pour Jack : Les choses ne sont pas si complexes quand l'on fut bien formé et avec plus de 20 ans de métier derrière soi ! Mais plus spécialisé dans les DB et les réseaux, j'avais un peu oublié ces fondements. Merci à toi.
Bien à vous tous,
François
Vous n’avez pas trouvé la réponse que vous recherchez ?
cs_Jack
Messages postés14006Date d'inscriptionsamedi 29 décembre 2001StatutModérateurDernière intervention28 août 201579 30 mai 2009 à 20:17
Re François
Impec.
Tu peux même pousser la recherche encore plus loin :
Après avoir trouvé le handle de la fenêtre "Enregistrer sous", tu peux rechercher l'objet "zone de texte" (classe "Edit") et le bouton (classe "Button") de validation : ce sont des Child de la forme.
Comme ça, même si la fenêtre perd le focus (obligatoire pour un SendKeys), tu pourras quand même poursuivre.
Exemple d'un truc que j'avais écrit il y a longtemps :
Public Function mChercheEditEtRemplit(ByVal ParentHwnd As Long, _
ByVal NomFichier As String) As Boolean
' Ecrit le nom du fichier à utiliser à une fentre de selection
' Renvoie True si Ok
Dim Temp As String
Dim r As Long
Dim sClasse As String
Dim mHwnd As Long
Dim Carré As RECT
' Cherche la ligne Edit (Nom du fichier)
Screen.MousePointer = vbHourglass
DoEvents
Call Sleep(250)
Screen.MousePointer = vbDefault
mHwnd = GetWindow(ParentHwnd, GW_CHILD)
Do While mHwnd <> 0
sClasse = String(256, "<")
r = GetClassName(mHwnd, sClasse, 256)
sClasse = Left$(sClasse, r)
If LCase(sClasse) = "edit" Then
Exit Do
End If
mHwnd = GetWindow(mHwnd, GW_HWNDNEXT)
DoEvents
Loop
If mHwnd = 0 Then Exit Function
' Envoie le nom du fichier
DoEvents
Temp = StrConv(NomFichier, vbFromUnicode, ByVal 1033)
Call SendMessage(mHwnd, WM_SETTEXT, ByVal 0&, ByVal StrPtr(Temp))
DoEvents
' Cherche le bouton Ouvrir et Clic
mHwnd = GetWindow(ParentHwnd, GW_CHILD)
Do While mHwnd <> 0
sClasse = String(256, "<")
r = GetClassName(mHwnd, sClasse, 256)
sClasse = Left$(sClasse, r)
If LCase(sClasse) = "button" Then
Temp = String(256, "<")
r = GetWindowText(mHwnd, Temp, 256)
Temp = Left$(Temp, r)
If LCase(Temp) Like "*ouvrir" Then
Call GetWindowRect(mHwnd, Carré)
With Carré
.Left = ((.Right - .Left) / 2) + .Left
.Top = ((.Bottom - .Top) / 2) + .Top
End With
Call SetCursorPos(Carré.Left, Carré.Top)
Call mouse_event(MOUSEEVENTF_LEFTDOWN Or MOUSEEVENTF_LEFTUP, 0, 0, 0, ByVal 0)
Exit Do
End If
End If
mHwnd = GetWindow(mHwnd, GW_HWNDNEXT)
DoEvents
Loop
If mHwnd = 0 Then Exit Function
mChercheEditEtRemplit = True
End Function
Vala
Jack, MVP VB NB : Je ne répondrai pas aux messages privés
<hr />
Le savoir est la seule matière qui s'accroit quand on la partage (Socrate)
frc691
Messages postés7Date d'inscriptionlundi 19 décembre 2005StatutMembreDernière intervention 2 juin 2009 2 juin 2009 à 17:42
Joli !
Voila une manière élégante de détourner le système. J'en prend bonne note. Cela me servira bientôt.
Cependant, comme ma tournure m'a déjà permis de batcher plus de 500 impressions pdf, j'en resterai là. Après tout, je ne devrai m'en servir que 2 fois / an !
Une petite chose : dans le msg précédent, je voulais parler d'interruption et non de bufférisation. Tout le monde aura bien sûr compris.
Par contre, si tu connaissais (ou qq'un) un - même vague - algorythme permettant de définir si 2 cylindres dans l'espace sont ou non sécants.... Plusieurs Profs de maths (enseignant en Lycée et MSpé) ont déjà "passé l'éponge". C'est à titre perso pour la reconstitution d'un trière de l'époque d'Alexandre le Grand (rien que 170 rames à faire mouvoir ensemble...) et nous avons besoin d'une simulation avant construction.
En tous les cas, merci pour tes avis qui furent d'un bon secours.
Cordialement,
François