PDA

View Full Version : BIG Problem with Callback Functions


SonG0han
06-21-2004, 09:31 AM
k.. again now :|
this is a shortened version

i want to have 2 bars to show the unzip/install progress. one for current file and one for overall. but in the help it says for callback the "string" gives you the current filename and path but bevore every file it gives you "item x of y". thats missing in the helpfile ;)
if i try to remove this it does not work or if i try to set text to a paragraph i get an error at calling the callback function. is it a bug that you cant set paragraphs and labels in a callabackfuntion?

this is on show (old parts are partially commented)

-- SHOW DEBUG
Debug.SetTraceMode(true);
Debug.ShowWindow(true);
-- SHOW PROGRESS START
Page.StartTimer(350);
Progress.SetText("FILE", "Preparing Installation... Please wait...");
-- Get Contents of ZIP
tblZIP = Zip.GetContents(_SourceFolder.."\\DATA\\setup.zip", true);
-- Count Items of ZIP
ZipCount = Table.Count(tblZIP);
-- Set Overall Bar Range to ZIP Itemcount
Progress.SetRange("OVERALL", 0, ZipCount);
-- SHOW PROGRESS Finish --
Page.StopTimer();
Progress.SetText("FILE", "");
Progress.SetCurrentPos("FILE", 0);
-- SHOW PROGRESS END --

DEBUG = Dialog.Message("DEBUG", "ZipCount: "..ZipCount, MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);
StringCheck = 0;

-- Set Overall to 0
nOVERALL = 1;
-- Unzip and show details
Zip.Extract(_SourceFolder.."\\DATA\\setup.zip", {"*.*"}, FINALPATH, true, true, "", ZIP_OVERWRITE_ALWAYS, UnzipStatus);



Thats the Callback function for unzipping

function UnzipStatus (String, Percent)
--DEBUG = Dialog.Message("DEBUG", "String: "..String.."@ "..Percent.."%", MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);
--DEBUG = Dialog.Message("DEBUG", "Percent: "..Percent, MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);
-- Show Current Filename in Details-Box
--StringCheck = String.Find(String, FINALPATH, 1, false); FEHLER !?!?
--DEBUG = Dialog.Message("DEBUG", "StringCheck: "..StringCheck, MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);
if StringCheck >= 0 then
--sCurString = String.SplitPath(String);
--sDETAILS = Paragraph.GetText("parDetails");
--snewDETAILS = sDETAILS .. "\r\nExtracted: "..sCurString.Filename..sCurString.Extension
--Paragraph.SetText("parDetails", snewDETAILS);
end
--DEBUG = Dialog.Message("DEBUG", "Filename: "..sCurString, MB_OK, MB_ICONINFORMATION, MB_DEFBUTTON1);

-- Increase File Bar (Percent)
if StringCheck >= 0 and Percent < 100 then
Progress.SetCurrentPos("FILE", Percent);
--return true;
end
-- Increase Overall Bar after each File
if StringCheck >= 0 and Percent == 100 then
nOVERALL = nOVERALL + 1;
Progress.SetCurrentPos("OVERALL", nOVERALL);
Progress.SetCurrentPos("FILE", 0);
--return true;
end
-- Stop when Overall = zip contents count
if nOVERALL == ZipCount then
return false;
else
return true;
end
end

SonG0han
06-30-2004, 05:38 AM
anyone who can help me please? :rolleyes

SRJ
06-30-2004, 10:34 PM
Howdy,

Here's your solution.. I wrote some routines that will strip out the X and Y from the "Item X of Y" filename that the Zip.Add routine passes to the callback routine. Now... you don't need to get rid of the "Item X of Y" line as that helps us know what file we're at.

Here's the code:


function StripZipCallbackFilename(tmpStr)
if String.Compare(String.Left(tmpStr,4), "Item") == 0 then
local cFile = String.Mid(tmpStr,6,String.Find(tmpStr," ",7,false)-6);
local tFiles = String.Mid(tmpStr,String.Length(cFile)+10,String.F ind(tmpStr," ",-1));
return cFile, tFiles;
end
end

function CallbackFunction(Filename,Percent)
local CurrentFile, TotalFiles= StripZipCallbackFilename(Filename);
if CurrentFile ~= nil then
if not Finished then
Progress.SetRange("OVERALL", 0, tFiles);
end
Progress.SetCurrentPos("OVERALL", cFile);
Window.SetText(Application.GetWndHandle(),"Test Harness - "..Math.Floor(String.ToNumber(CurrentFile)/String.ToNumber(TotalFiles)*100).."% Completed");
if cFile == tFile then
Finished = true;
end
end
Progress.SetCurrentPos("FILE", Percent);
end


Your main code should be something like this...


Progress.SetRange("FILE",0,100);
Progress.SetCurrentPos("FILE", 0);
Zip.Add("zipfile.zip",{"C:\\*.*"},...etc...,false, CallbackFunction);


Here's how it works... Everytime the call back function is called by Zip.Add, it takes the Filename string that is passed and sends it to StripZipCallbackFilename for parsing. This function does nothing if the Filename string isn't the "Item X of Y" string. If it is, it reads the X value and then the Y value. Both these values are passed back to CurrentFile and TotalFiles.

Now, something you really need to note (which I didn't and it caused me all sorts of grief) is that the routine will return null values and null values cannot be printed like strings. So if you try to print a null string you'll get an error.

I've also included the code to change your Window title so that it displays the overall percentage.

Happy programming....
SRJ.

SonG0han
07-01-2004, 04:40 AM
thanks, i will try that! :D

but is it "normal" that you get an error if you try to write text into an paragraph or input field via a callback function?
i want to make a "setup" where you can see "extracting FILENAME..." in the multiline inputfield and below are the 2 bars for extracting.

if i disable the settext feature it works but if i enable it i get "error on call" :huh

SRJ
07-05-2004, 05:46 AM
Apologies for the delayed response...

It's NOT normal to get an error when trying to print text in a Callback function. I simply had a numpty moment where I completely forgot about how computer systems handle null strings. The best way to think of null strings is that they can be anything. For that reason the results, at best, can be unpredictable, at worse, BSOD causing! Consequently, its best to ensure your code deals with the times when any string, regardless of whether its in a callback function or not, is a null. :yes

Your error appears to be related to a null string. You will need to modify my parsing function slightly if you want to also just parse the filename you're currently working on. It's not difficult though...


function StripZipCallbackFilename(tmpStr)
if String.Compare(String.Left(tmpStr,4), "Item") == 0 then
local cFile = String.Mid(tmpStr,6,String.Find(tmpStr," ",7,false)-6);
local tFiles = String.Mid(tmpStr,String.Length(cFile)+10,String. Find(tmpStr," ",-1));
return cFile, tFiles;
else -- If we actually have a filename then let's use it!
if String.Compare(String.Left(tmpStr, 12), "Please Wait.") ~= 0 or String.Compare(String.Left(tmpStr, 20), "Processing Item List") ~= 0 then
local cFile = tmpStr;
local tFiles = null;
return cFile, tFiles;
end


Now I might have the character positions slightly wrong (ie. 12 and 20) but you shoudl be able to get the idea. Now you can check for when tFiles is Null but cFile isn't then you must have a new Current File and you can then display this to the screen (or whatever output device you're using).

Code would be something like this:


if (CurrentFile ~= nil) and (TotalFiles ~= nil) then
Progress.SetText("TEST","Current File: "..CurrentFile);
end;


Let me know if that clears things up...

SRJ.

SRJ
07-05-2004, 05:48 AM
oops,

the code should be this (ie. TotaFiles should be equal to nil (ie a null!!!)).. .apologies! ;) :


if (CurrentFile ~= nil) and (TotalFiles == nil) then
Progress.SetText("TEST","Current File: "..CurrentFile);
end;


SRJ.

SonG0han
07-05-2004, 10:54 AM
thank you. i will try that in the next days and hope it works now :) :yes

but one last thing: if anyone of you know something about databases i would be very happy if you could take a look at this: http://www.indigorose.com/forums/showthread.php?t=7085&page=3 :rolleyes

regards