? on printing interaction

Started by Paul D. Elliott, September 11, 2006, 02:11:09 PM

Previous topic - Next topic

Paul D. Elliott

I've got a simple maintenance form with buttons to save/delete/print and
so on.  most work except I've hit a snag with the Print. I'm using XPrint to
choose a printer and do the printing. so far no problems. I use the
KillFocus routine on the key field to see if I need to add or change the
fields. I exit that routine if the current field is one of my buttons. It works
except if I actually pick a printer & print. then the print comes out but for
some reason the program immediately takes the KillFocus routine and
goes into change mode for the fields. If I put a MSGBOX at the end of the
print routine, it works without a problem.  at the end of the print routine,
I set focus back to the key field.

Any clue as to where or how I'm getting an extra TAB or RETURN or something
to cause an exit to the key field? I can post more of this program if
needed.

Thanks




FUNCTION SKUMAINT_BTNPRINT_BN_CLICKED ( _
                                     ControlIndex     AS LONG,  _  ' index in Control Array
                                     hWndForm         AS DWORD, _  ' handle of Form
                                     hWndControl      AS DWORD, _  ' handle of Control
                                     idButtonControl  AS LONG   _  ' identifier of button
                                     ) AS LONG
 DIM rtc AS LONG
 DIM cnt AS LONG
 DIM txt AS STRING
 DIM pg AS LONG
 DIM cost AS CURRENCY
 DIM sku AS STRING
   cnt = trm_count(hndl_SKU)
   IF cnt < 1 THEN
       MSGBOX "nothing to print"
       GOTO dun
   END IF
   XPRINT ATTACH CHOOSE
   txt = XPRINT$
   IF txt = "" THEN
       GOTO dun
   END IF
   XPRINT SET ORIENTATION 2
   
   sku = SKURec.SKU
   
   pg = 1
   txt = FF_CONTROL_GETTEXT(HWND_SKUMAINT_LBLNOW)    
   XPRINT txt & SPACE$(20) & "SKU Listing" & SPACE$(20) & "Page" & STR$(pg)
   XPRINT
   XPRINT "SKU" & SPACE$(20) & "Description" & SPACE$(32)&  "COO  HTS            ECCN         License      Cost"
   XPRINT
   
   SKUstr = trm_getfirst(hndl_SKU, 1)
lp:
   LSET SKURec = SKUstr
   txt = TRIM$(SKURec.Cost)
   cost = VAL(txt)
   XPRINT SKURec.SKU & "   " & SKURec.Descr;
   XPRINT SPACE$(3) & SKURec.COO & "   " & SKURec.HTS & "   " & SKURec.ECCN & "   " & SKURec.License & "   " & FORMAT$(cost, "####0.00")
   SKUstr = trm_getnext(hndl_SKU)
   rtc = trm_result(hndl_SKU)
   IF rtc = 0 THEN GOTO lp
   XPRINT
   XPRINT "Total " & STR$(cnt)
   XPRINT CLOSE
dun:    
   SKUstr = trm_getfirst(hndl_SKU, 1)
   rtc = trm_result(hndl_SKU)
   txt = FF_CONTROL_GETTEXT(HWND_SKUMAINT_TSKU)
   txt = TRIM$(txt)
   IF txt <> "" THEN
       txt = LEFT$(txt & SPACE$(20), 20)
       SKUstr = trm_getequal(hndl_SKU, 1, sku)
       rtc = trm_result(hndl_SKU)
   END IF
   'IF rtc <> 0 THEN
       'MSGBOX "at end of PRINT dun rtc =" & STR$(rtc)
   'END IF    
   LSET SKURec = SKUstr        
   ' FF_CONTROL_ENABLE HWND_SKUMAINT_TSKU
   SETFOCUS HWND_SKUMAINT_TSKU
   SLEEP 1000
END FUNCTION

TechSupport

Hi Paul,

Can you post the code you are using for the KillFocus? This certainly looks like a sequence of messages problem. I expect that your KillFocus is firing as soon as you press the BTNPRINT command button. That makes sense because the BTNPRINT is now gaining keyboard focus. The KillFocus may be getting interrupted by the modal print choose dialog ???? I am not sure. Maybe you can email me the application or a sample. I could then get you an answer much faster.

Paul D. Elliott

Since the original posting, I've added a global switch which gets set when
the print routine gets called. it fixes the problem but is slightly ugly. I'd
much rather do it right. it gets set as the last line of the Print function.

WHen I get it all working then I'll clean up the code and eliminate a lot of
duplicate and testing code.

I've sent a copy of the source & data files.

Thanks for any help.



FUNCTION SKUMAINT_TSKU_EN_KILLFOCUS ( _
                                   ControlIndex   AS LONG,  _  ' index in Control Array
                                   hWndForm       AS DWORD, _  ' handle of Form
                                   hWndControl    AS DWORD, _  ' handle of Control
                                   idTextControl  AS LONG   _  ' identifier of text control
                                   ) AS LONG
 DIM rtc AS LONG
 DIM sku AS STRING
 DIM nxt AS DWORD
 DIM txt AS STRING
 DIM cost AS CURRENCY
 
   nxt = GETFOCUS
   IF nxt = HWND_SKUMAINT_BTNNEXT OR nxt = HWND_SKUMAINT_BTNPREV OR nxt = HWND_SKUMAINT_BTNEXIT THEN
       EXIT FUNCTION
   END IF
   IF nxt = HWND_SKUMAINT_BTNSAVE OR nxt = HWND_SKUMAINT_BTNCANCEL THEN ' OR nxt = HWND_SKUMAINT_BTNDELETE THEN
       EXIT FUNCTION
   END IF    
   IF nxt = HWND_SKUMAINT_BTNPRINT THEN
       EXIT FUNCTION
   END IF    
   IF justprinted = 1 THEN
       justprinted = 0
       EXIT FUNCTION
   END IF    
       
   sku = FF_CONTROL_GETTEXT(HWND_SKUMAINT_TSKU)
   
   'IF sku = lastSKU AND moved = 0 THEN
   '    EXIT FUNCTION
   'END IF    
   
   moved = 0
   sku = LEFT$(TRIM$(sku) + SPACE$(20), 20)
   IF LEFT$(sku, 1) = " " THEN
       SETFOCUS HWND_SKUMAINT_TSKU
       EXIT FUNCTION
   END IF
   SKUstr = trm_getequal(hndl_SKU, 1, sku)
   rtc = trm_result(hndl_SKU)
   IF rtc <> 0 THEN
       addchg = 1
       SKUstr = SPACE$(117)
       LSET SKURec = " "
       SKURec.SKU = sku
       SKURec.UnitsPerBox = "00001"
       SKURec.TotalWght = "00001.000"
       SKURec.Cost = "00001.00"
       FF_CONTROL_SETTEXT HWND_SKUMAINT_FRAME2, "** ADD  **"
   ELSE
       addchg = 2
       LSET SKURec = SKUstr
       FF_CONTROL_SETTEXT HWND_SKUMAINT_FRAME2, "Change"
   END IF
 
   FF_CONTROL_SETTEXT HWND_SKUMAINT_TDESCR, TRIM$(SKURec.Descr)
   FF_CONTROL_SETTEXT HWND_SKUMAINT_TCOO, TRIM$(SKURec.COO)
   FF_CONTROL_SETTEXT HWND_SKUMAINT_THTS, TRIM$(SKURec.HTS)
   FF_CONTROL_SETTEXT HWND_SKUMAINT_TECCN, TRIM$(SKURec.ECCN)
   FF_CONTROL_SETTEXT HWND_SKUMAINT_TLICENSE, TRIM$(SKURec.License)
   txt = TRIM$(SKURec.Cost)
   cost = VAL(txt)
   FF_CONTROL_SETTEXT HWND_SKUMAINT_TCOST, FORMAT$(cost, "0.00")
   
   FF_CONTROL_DISABLE HWND_SKUMAINT_TSKU
END FUNCTION


TechSupport

Hi Paul,

I got your email - thanks. It certainly helped a lot. I am still not 100% sure why the KillFocus is firing but my best guess is the sequence of events that occur when the print selecting dialog occurs and then when a subsequent print dialog happens there appears to be a focus change when your application momentarily regains focus.

Your global flag solution does indeed seem to work. My advice: If it works, stick with it  :)

Paul D. Elliott

Ok but I was getting confused.

I know the KillFocus fired but at the beginning of that routine, I checked
which field had focus and if it was one of my buttons then I immediately
exited the KillFocus. Is there any reason that the KillFocus should fire
twice? Or should I exit it with a certain value ( to show that it was
handled or some such ) ? For that matter, should I exit all these funtions
with a return code to show that it was handled and that there is no need to
pass the message back up the queue to the form?

On the Print routine, if I Cancelled out of the Printer Selection then
everything worked without any extra flags. it also worked fine when I
put a MsgBox down towards the end ( the one in the If rtc <> 0  but
I commented out the If & EndIf statements ).

I'll just continue to clean up the rest of the code and allow for multiple
pages and such.

Thanks for taking the time to check on it.

Paul D. Elliott

Anybody got any ideas on what should be the return code of these
routines to signify that the message has been taken care of and that it
doesn't need to be passed up the queue to the form?

Just trying to figure out why the KillFocus event fires again after I've
clicked the Print button. Watching the program running thru the PB debugger ( without actually tracing the code step-by-step ) shows that
the KillFocus gets run again after the Print routine gets done. I've done
a Trace file but there is a ton of overhead from routines that I know
nothing about ( presumably the underlying routines supplied by FF ).

As I've said, I do have a work around but will need to do tests on the
client's computers to make sure that it always works. I would like to
find out why it's doing it and fix it the right way.

Thanks.

TechSupport

This is odd because on another computer of mine everything works as you originally intended. :?  The select printer dialog appears and then I print. At no time does the program enter "Change" mode. Weird. I will keep looking to see what might be the cause.

One thought: On my 'problem' computer, a second print dialog appears for my selected printer prior to the actual print occurring. It could be that when this dialog appears it is not an owned window of the application and then the application loses focus causing the KillFocus to fire again for the application. I will try to trace the messages on the problem computer when I get home.

Paul D. Elliott

I'm running W2K with an Epson Color 740 inkjet printer. I get a status
window showing how many pages left to print when I do the Xprint Close.
Sometimes the print can hog the CPU. I don't have access to any laserjets to test to see if it's just a problem with the Epson. Most likely
the client will only be printing on laserjets and never really see the problem I had. This is the first time I'm using PB's XPrint. Before I used
DDoc but am switching from Delphi over to PowerBASIC.

If I feel like getting a headache then I'll try the debugger again and maybe
add some Trace Print statements so that I can clearly see what's going on.
But I haven't had to resort to the debugger yet because all the problems
were little things that I could fix once I figured out what the compiler
was doing and a few simple prints or msgbox showed me my errors.

Paul D. Elliott

It might have something to do with the program losing focus when the
XPrint Close happens. With my printer, a Status program pops up and
displays how much of the print is complete and stays there until printing
is done. then control returns to my program. at that point, the main field
fires a KillFocus event. If I disable the Status program then I don't get
the extra KillFocus and the program works as it should.

Also the KillFocus event is getting fired if while my program is running I
switch to another program and back. NOT GOOD. Plus it doesn't seem
right. Will KillFocus get fired for EVERY field?

Do I need to put in some check to see if the program loses focus?

I think I need some help from those who know. How do you handle a
simple maintenance program? If you have a simple field that is the key
field, when & how do you check for a record existing or if it is a new
record and display what's on file and allow the user to update?
There is also a requirement that the user must be able to browse
thru the data ( preferrably in the same screen layout that does the
updates ... sometimes way too much data for any kind of a grid ).

Any thoughts?

TechSupport

Hi Paul,

In these types of applications, I have a separate set of buttons that the user must click in order to initiate an Edit, Add, or Delete. However, in your situation you can fix the problem by dealing with the application losing and gaining focus. It is actually quite simple - try the following:

(1) Create a global variable:

Global gAppHasFocus As Long


(2) Add the following code:

Function SKUMAINT_WM_NCACTIVATE ( _
                               hWndForm  As Dword, _  ' handle of Form
                               fActive   As Long   _  ' true if active state
                               ) As Long

  gAppHasFocus = fActive
     
End Function


(3) Add the following code to your KLLFOCUS handler:

   If gAppHasFocus = %FALSE Then
      Exit Function
   End If


Please let me know if you have success with this approach. It seems to be working for me.

Paul D. Elliott

Thanks. That is working so far. KillFocus also fires if the app is minimized
but generally the users never do that so for the moment I'll ignore it.

Having buttons for edit/add/delete might be a way to go. I'll have to
think about it a little bit. I would have to disable all the detail entry
fields. a couple questions. Do you do any checking of the data file before a
button is pressed ( as in the KillFocus to display the details of the record )? When editing the details, do you have other buttons for
Save/Cancel?  It's just that the users are used to seeing details for the
items as they can browse thru the data file.

Once again, THANKS.

TechSupport

Hi Paul,

You can still show all of the details. Keep the SKU text field enabled so the user can manually input a SKU number. Underneath the SKU text field (or to the right of it), place three CommandButtons: "ADD", "EDIT", "DELETE". You can place logic in each of those button's BN_CLICKED message handlers to act on the SKU number (e.g. if a SKU of 12345 is entered and the "ADD" button is clicked, then in the BN_CLICKED of the "ADD" button you would search the database to see if the SKU already exists. If it does, then retrieve the data, display it, and then enter EDIT mode. If the data does not exist then enter ADD mode).

When you enter ADD or EDIT modes then you would call a function to enable the various data input textboxes (i.e. Description field, ECCN, etc...). I would also use that function to enable/disable the CommandButtons that are relevent to the current state (e.g. only enable the SAVE button when the person is currently Adding or Editing).

When the user finishes entering/adding their data then they need to press the SAVE button to store the changes to the disk file. You would also do your data validation in that message handler.

Paul D. Elliott

Okay, that cleans up & simplifies some of my code. But I left out the
Add button figuring why have the user make a choice when the program
could do it for them and seeing that the Edit button still had to figure out
if it was supposed to be an Add. Took all the Tabstops from the buttons
except the Edit. Eventually I should change the background color of the
detail fields when they are disabled to make it easier to see the data.

I think I'll make this change to the main data entry program.

Once again, THANKS for all your help.