IPXC_Document::WriteToFile + default progress  SOLVED

PDF-XChange Editor SDK for Developers

Moderators: TrackerSupp-Daniel, Tracker Support, Paul - Tracker Supp, Vasyl-Tracker Dev Team, Chris - Tracker Supp, Sean - Tracker, Ivan - Tracker Software, Tracker Supp-Stefan

Forum rules
DO NOT post your license/serial key, or your activation code - these forums, and all posts within, are public and we will be forced to immediately deactivate your license.

When experiencing some errors, use the IAUX_Inst::FormatHRESULT method to see their description and include it in your post along with the error code.
Post Reply
zarkogajic
User
Posts: 1370
Joined: Thu Sep 05, 2019 12:35 pm

IPXC_Document::WriteToFile + default progress

Post by zarkogajic »

Hi Support,

I cannot get the progress bar to display when using IPXC_Document::WriteToFile(IPXV_Inst::DefaultProgressMon) upon saving a bigger file.

Any other way of saving needed for the default progress dialog to show up?

p.s.
Saving does take more time than default's progress "show me" timer.

-žarko
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: IPXC_Document::WriteToFile + default progress

Post by Sasha - Tracker Dev Team »

Hello zarkogajic,

Saving can take more time but the progress itself inside of the method can be shorter. Meaning that it's not used for some parts of the code that also can take some time. Thus the time between start and stop is not enough for it to show up.

Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
zarkogajic
User
Posts: 1370
Joined: Thu Sep 05, 2019 12:35 pm

Re: IPXC_Document::WriteToFile + default progress

Post by zarkogajic »

Hi Alex,

If I open the *same file* in EU Editor and do a SaveAs - the progress *is* displayed.

p.s.
As stated I'm using Inst.DefaultProgressMon - so I'm not controlling its Start/Stop ...

-žarko
zarkogajic
User
Posts: 1370
Joined: Thu Sep 05, 2019 12:35 pm

Re: IPXC_Document::WriteToFile + default progress

Post by zarkogajic »

Hi Alex,

I know this is probably not related, but in here:

https://forum.pdf-xchange.com/viewtopic.php?f=66&t=34323&p=142349&hilit=progress#p142327

you said that default progress dialog will be displayed only if the operation (op.openDoc in that case) is executed in a separate thread (via AsyncDoAndWaitForFinish).

Since there's no "op.saveDoc" I'm running WriteToFile in the main thread - and no progress is being displayed.

I've event tried running (and waiting for it to finish) WriteToFile in a separate thread (not PDFX's threading model) - still default progress dialog is not being displayed.

My code:

cDoc.WriteToFile('c:\pdf.pdf', Inst.DefaultProgressMon, 0)

Is there a way to force the display of the default progress dialog (if the "show timer" really fires after Stop) at the moment Start is called?

p.s.
Yes, I can and have implemented my own wrapper for IProgressMon and yes, when I use it with WriteToFile, methods (SetDuration, SetPos, Start/Stop ...) are being called and I can update my own progress bars - but to have the same user experience - I'd like to show the standard progress dialog used by PDFX....

-žarko
zarkogajic
User
Posts: 1370
Joined: Thu Sep 05, 2019 12:35 pm

Re: IPXC_Document::WriteToFile + default progress

Post by zarkogajic »

HI Support,

Here's another observation:

I've wrapped Inst.DefaultProgressMon (re: https://forum.pdf-xchange.com/viewtopic.php?f=66&t=35245&p=146480&hilit=IProgressMon#p146480).

As said in previous posts, when I simply use "cDoc.WriteToFile('c:\pdf.pdf', *MyDefaultProgressMonWrap*, 0)" - the progress dialog does not get displayed - and I'm 100 certain saving part takes longer than the timer to fire for the dialog to get displayed.

What I then did, is to add "Application.DoEvents()" inside "put_Pos" implementation, where my implementation just calls the DefaultProgressMon's put_Pos.

With calls to Application.DoEvent() - yes, the dialog does appear (after timer event). Unfortunately, no text, status text, etc - only the progress moves until saving finishes.

So, my guess is that while you are saving the document, messages (SW_SHOW (?)) are not being received (i.e. are waiting in the message loop) by DlgProgress (that is unless I do Application.DoEvents).

-žarko
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: IPXC_Document::WriteToFile + default progress

Post by Sasha - Tracker Dev Team »

Hello zarkogajic,

You are calling the WriteTOFile method from the main thread - how do you expect a progress to show up?

Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
zarkogajic
User
Posts: 1370
Joined: Thu Sep 05, 2019 12:35 pm

Re: IPXC_Document::WriteToFile + default progress

Post by zarkogajic »

Alex,

I'm not expecting anything :)

I'm asking and test-fail-trying...

Note that I have tried calling WriteToFile from a different thread but the dialog still did not show up.

Is your answer: "for the progress dialog to show up, WriteToFile must be called from a different thread"?

-žarko
User avatar
Vasyl-Tracker Dev Team
Site Admin
Posts: 2353
Joined: Thu Jun 30, 2005 4:11 pm
Location: Canada

Re: IPXC_Document::WriteToFile + default progress

Post by Vasyl-Tracker Dev Team »

Hi žarko.

Can you provide a simple example project to demonstrate the problem?

Cheers.
Vasyl Yaremyn
Tracker Software Products
Project Developer

Please archive any files posted to a ZIP, 7z or RAR file or they will be removed and not posted.
zarkogajic
User
Posts: 1370
Joined: Thu Sep 05, 2019 12:35 pm

Re: IPXC_Document::WriteToFile + default progress

Post by zarkogajic »

Hi Vasyl,

I have a 10K pages PDF that when opened/saved in PXV_Control -> the progress dialog does come up - so the saving part does take enough time for dialog's "show" timer to fire ....

I'm trying this in C# / Full Demo :

Code: Select all

string fileName = @"D:\pdfx\PDFEditorSDKExamples-master\CSharp\10Kpages.pdf";

PDFXEdit.IPXC_Document cDoc = pxcInst.OpenDocumentFromFile(fileName, null);
MessageBox.Show("opened 10K");

cDoc.WriteToFile(fileName, pdfCtl.Inst.DefaultProgressMon);
MessageBox.Show("saved 10K");
Since this is all in main thread - no progress dialog gets displayed - and from what Alex said - that's to expect.

If I try the saving part as:

Code: Select all

Task t = Task.Run(() => cDoc.WriteToFile(fileName, null))
t.Wait();
MessageBox.Show("saved 10K in separate thread");
The exception is raised "Unable to cast COM object of type 'System.__ComObject' to interface type 'PDFXEdit.IPXC_Document"..

What I really wanted to test is:

Code: Select all

Task t = Task.Run(() => cDoc.WriteToFile(fileName, pdfCtl.Inst.DefaultProgressMon));
t.Wait();
MessageBox.Show("saved 10K in separate thread WITH progress");
But this fails with "Bad variable type."

-> so it seems I cannot do a test case in C# where I call saving from a separate thread (?).

Further, I wanted to wrap Inst.DefaultProgressMon into my class and inject my implementation, but that also seems not to be possible with C# :(

Code: Select all

public partial class MyProgressDialog : PDFXEdit.IProgressMon
{
readonly IProgressMon InstDefaultProgressMon;
readonly Form TheForm;

public MyProgressDialog(IPXV_Inst inst, Form frm)
{
	TheForm = frm;
	InstDefaultProgressMon = inst.DefaultProgressMon;

	inst.ProgressMon = this;
}

public void SetText(string sText)
{
	InstDefaultProgressMon.SetText(sText);
}

public void SetTitle(string sTitle)
{
	InstDefaultProgressMon.SetTitle(sTitle);
}

public void SetStatusText(string sStatusText)
{
	InstDefaultProgressMon.SetStatusText(sStatusText);
}

public void SetButtonTitle(string sButtonTitle)
{
	InstDefaultProgressMon.SetButtonTitle(sButtonTitle);
}

public void SetStyle(uint nStyle, uint nStyleMask)
{
	InstDefaultProgressMon.SetStyle(nStyle, nStyleMask);
}

public void Start()
{
	InstDefaultProgressMon.Start();
}

public void Stop()
{
	InstDefaultProgressMon.Stop();
}

public double Duration { get => InstDefaultProgressMon.Duration; set => InstDefaultProgressMon.Duration = value; }
public double Pos
{
	get => InstDefaultProgressMon.Pos;
	set
	{
		InstDefaultProgressMon.Pos = value;
		TheForm.Text = Pos.ToString();
	}
}
public uint Style { get => InstDefaultProgressMon.Style; set => InstDefaultProgressMon.Style = value; }

public bool Canceled => InstDefaultProgressMon.Canceled;

public IFlag CancelFlag => InstDefaultProgressMon.CancelFlag;
}
Having:

Code: Select all

private void MainFrm_Show(object sender, EventArgs e)
{
	MyProgressDialog mypd = new MyProgressDialog(pdfCtl.Inst, this);
}

So, I have a general "no-go" with c#. I'll do a Delphi sample...

-žarko
zarkogajic
User
Posts: 1370
Joined: Thu Sep 05, 2019 12:35 pm

Re: IPXC_Document::WriteToFile + default progress

Post by zarkogajic »

Hi Vasyl,

So, what I am trying to have is: displayed default progress monitor's dialog when calling

Code: Select all

IPXC_Document::WriteToFile("pdf.pdf", Inst.ProgressMon, 0)
Whatever I try I cannot get it to display. And I've tried a lot of things (some info in my previous posts in this topic)...

I've now created a test custom IOperation just to do the saving part inside its Do() method. When called via AsyncDoAndWaitForFinish the dialog does finally come up - but it appears "empty" (no title, no status text):

image.png

The problem I have with this approach is that I *cannot* use AsyncDoAndWaitForFinish - since the saving part already needs to happen in a separate thread (another custom IOperation executed via AsyncDo) and "Wrong thread" exception is throw.

p.s.
To remove confusion with the previous post: my working code is Delphi.


-žarko
User avatar
Vasyl-Tracker Dev Team
Site Admin
Posts: 2353
Joined: Thu Jun 30, 2005 4:11 pm
Location: Canada

Re: IPXC_Document::WriteToFile + default progress

Post by Vasyl-Tracker Dev Team »

Hi žarko.

When you using this from the separate thread:

IPXC_Document::WriteToFile("pdf.pdf", Inst.ProgressMon, 0)

- it shows the progress dialog in the main thread (thread where the pdfCtl lives) but title and status text are empty because the WriteToFile function is from CoreAPI level that is separated from the UI-layer. To solve your problem you just need to use progress.SetTitle, progress.SetText to set the proper text before calling the WriteToFile.

According to the:

"The exception is raised "Unable to cast COM object of type 'System.__ComObject' to interface ...."

- that occurs in case when you trying to use SDK-objects in another thread, using the .NET - we will try to fix that issue in the near future.

HTH.
Vasyl Yaremyn
Tracker Software Products
Project Developer

Please archive any files posted to a ZIP, 7z or RAR file or they will be removed and not posted.
zarkogajic
User
Posts: 1370
Joined: Thu Sep 05, 2019 12:35 pm

Re: IPXC_Document::WriteToFile + default progress  SOLVED

Post by zarkogajic »

Hi Vasyl,

Thanks for confirming. All clear.

Let me sum up conclusions here for future users:

Task: have a default progress dialog show up when saving a big (takes time to save) document via IPXC_Document::WriteToFile.

Having

IPXC_Document : cDoc;
IPXV_Inst : Inst;

WriteToFile in MAIN THREAD:

1. Not using pProgress: IProgressMon parameter:

cDoc.WriteToFile('pdf.pdf', nil, 0)

=> The progress dialog does not show - as expected -> pProgress is null.

All below cases *are* using some kind of IProgressMon implementation...

2. Using Inst.DefaultProgressMon for pProgress: IProgressMon parameter:

cDoc.WriteToFile('pdf.pdf', Inst.DefaultProgressMon, 0)

=> The progress dialog does not show. More info below!

WriteToFile in DIFFERENT THREAD:

1. Using own threading mechanism (Task.Run in C#, VB.Net; TTask.Run in Delphi) - saving in a different thread (using Inst.DefaultProgressMon) with Task.Wait.

=> The progress dialog does not show.

2. Using PDFX's AsyncDoAndWaitForFinish with a custom IOperation implementation having the WriteToFile in the Do() method (using Inst.DefaultProgressMon)

=> The progress dialog DOES show!

Title, Text, Status text are empty. Need to set those manually via SetTitle, SetText , ... methods before executing WriteToFile.

DISPLAYING THE DEFAULT PROGRESS DIALOG IN THE MAIN THREAD
Even though it might seem this is a no go - there is a solution to display the default progress dialog even if WriteToFile is called from the main thread.

1. Wrap the implementation of Inst.DefaultProgressMon in a custom class
2. Set this class instance for Inst.ProgressMon
2.1. The custom class IProgressMon implementation calls Inst.DefaultProgressMon's methods
3. Inside the implementation of Pos setter:
3.1. Update some non visible element in your app's some window (a non visible label, for example) or some progress bar or something
3.2 Call Application.DoEvents (or similar)
3.3. Call DefaultProgressMon.Set_Pos(nPos))
4. Before the call to WriteToFile make sure to set Text, StatusText etc .. or the dialog window will show only the progress bar.

=> The progress dialog window does come up :)

p.s.
Use on as-is-bases-donot-blame-me-if-it-doesnot-work-for-you. :)

This approach works for me (even though slightly more complex stuff happening in my IProgressMon implementation)

-žarko
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

IPXC_Document::WriteToFile + default progress

Post by Sasha - Tracker Dev Team »

:)
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
Post Reply