Hello,
I just created a docker in visual studio.
I have attached something with Page.Properties that displays in docker.
but how can i refresh docker when user change page in coreldraw.
I have find document.pagechange or pageactivate event but don't know how to use.
please guide me.
I' m a little disappointed...
When docker remained activated in corel it is loaded before the first new document and my intention to fill some text boxes with identification parameters (name, page width, page height, measuring unit, etc) does not have (yet) the object and without receiving an error, the docker appearance misses all controls. I finally understood that and adapted the code for this situation:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
public partial class DockerUI : UserControl { private corel.Application corelApp; private int i = 0; bool noDocument = false; public DockerUI(corel.Application app) { this.corelApp = app; InitializeComponent(); if (corelApp.Documents.Count < 1) { this.txtTest.Text = "No document..."; noDocument = true; } else { foreach (corel.Document doc in this.corelApp.Documents) { i = ++i; this.txtTest.Text = "Try init - " + doc.Name + " - " + i; doc.PageChange += UpdateDockerFieldsPagChg; } UpdateDockerFields(); } this.Unloaded += UnsubscribeEvents; } void UnsubscribeEvents(object sender, RoutedEventArgs e) { if (noDocument==false) { foreach (corel.Document doc in this.corelApp.Documents) { doc.PageChange -= UpdateDockerFieldsPagChg; } } else {MessageBox.Show( noDocument.ToString()); } }
I tried to programmatically wait for some seconds but it looks that the document is waiting the docker loading as long it takes... I consider now the help of VBA and refresh the docker when documentNew event will occur.
Can somebody help me to set debugger to stop on the line having errors? For I don't know what reason it doesn't do that on the docker load event...
But I am disappointed because of something else...
After solving this situation of 'no any document' opened in corel, it works well but only for some times. For instance if I have three opened documents and activating the docker everything works as expected for for about six to twenty times and page change event is lost...
I do not know if or how to upload here the project. I do not see any such an option. So, I will post the code, maybe somebody will be patient enough to try it...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
public partial class DockerUI : UserControl { private corel.Application corelApp; private int i = 0; bool noDocument = false; public DockerUI(corel.Application app) { this.corelApp = app; InitializeComponent(); if (corelApp.Documents.Count < 1) { this.txtTest.Text = "No document..."; noDocument = true; } else { foreach (corel.Document doc in this.corelApp.Documents) { i = ++i; this.txtTest.Text = "Try init - " + doc.Name + " - " + i; doc.PageChange += UpdateDockerFieldsPagChg; } UpdateDockerFields(); } this.Unloaded += UnsubscribeEvents; } void UpdateDockerFieldsPagChg(corel.Page page) { UpdateDockerFields(); this.txtTest.Text = "OK pageChange... - "+corelApp.ActiveDocument.Name + " - " + page.Name; //MessageBox.Show(page.Name); } void UpdateDockerFields() { this.corelApp.ActiveDocument.Unit = this.corelApp.ActiveDocument.Rulers.HUnits; this.txtName.Text = this.corelApp.ActiveDocument.Name; this.txtPagHeight.Text = this.corelApp.ActivePage.SizeHeight.ToString(); this.txtPagWidth.Text = this.corelApp.ActivePage.SizeWidth.ToString(); this.txtMU.Text = UM(this.corelApp.ActiveDocument.Unit.ToString()); this.txtMU_.Text = UM(this.corelApp.ActiveDocument.Unit.ToString()); } private string UM(string um) { switch (um) { case "cdrInch": return "Inch"; case "cdrMillimeter": return "mm"; case "cdrCentimeter": return "cm"; case "cdrPixel": return "pixel"; case "cdrMeter": return "m"; default: return "strange..."; } } void UnsubscribeEvents(object sender, RoutedEventArgs e) { if (noDocument==false) { //this.corelApp.WindowActivate -= UpdateDockerFieldsWinAct; // this.corelApp.DocumentNew -= UpdateDockerFieldsDocNew; foreach (corel.Document doc in this.corelApp.Documents) { doc.PageChange -= UpdateDockerFieldsPagChg; } } else {MessageBox.Show( noDocument.ToString()); } } private void btShowForm_Click(object sender, RoutedEventArgs e) { //frmCorel frmC = new frmCorel(corelApp); //frmC.ShowDialog(); } }
And Xaml part of the main Grid:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
<Grid Margin="0,0,0,0"> <StackPanel> <Label Content="Active Document Name" HorizontalAlignment="Center" Margin="5,5,0,5" /> <TextBox Name="txtName" HorizontalAlignment="Center" Margin="5,5,0,5" /> <DockPanel> <Label DockPanel.Dock="Left" Content="Page Width: " Width="80"/> <TextBox DockPanel.Dock="Left" Name="txtPagWidth" Width="40" Margin="5,0,50,0"/> <TextBox DockPanel.Dock="Left" Name="txtMU" Width="40" Margin="5,0,10,0"/> </DockPanel> <DockPanel> <Label DockPanel.Dock="Left" Content="Page Height:" Width="80"/> <TextBox DockPanel.Dock="Left" Name="txtPagHeight" Width="40" Margin="5,0,50,0"/> <TextBox DockPanel.Dock="Left" Name="txtMU_" Margin="5,0,10,0" Width="40"/> </DockPanel> <Button Name="btShowForm" Content="Show Form" Width="70" Click="btShowForm_Click" Margin="10"/> <TextBox Name="txtTest" /> </StackPanel> </Grid>
Do you face the same problem? If yes, any idea to make it work?
Is it possible to catch the handler of event to be subscribed check it from time to time...? In this way I will also avoid unsubscribing on docker unload event if I will check the handler before subscription.
Thanks!
I did it but even on Loaded event things go in exactly the same way... It looks that the new document appears only after the docker is loaded. At least, in this case the debugger is stopped on the line where ActiveDocument object is null.
For the sake of programming I am plying now on the next scenario:
I placed in VBA on GlobalMacroStorage_DocumentNew event the next code (for the docker guid...):
1 2 3 4 5 6
Private Sub GlobalMacroStorage_DocumentNew(ByVal Doc As Document, ByVal FromTemplate As Boolean, ByVal Template As String, ByVal IncludeGraphics As Boolean) If Application.FrameWork.IsDockerVisible("f3f09ab3-a8b6-4400-9152-62ffbe93ecb5") Then Application.FrameWork.HideDocker "f3f09ab3-a8b6-4400-9152-62ffbe93ecb5" Application.FrameWork.ShowDocker "f3f09ab3-a8b6-4400-9152-62ffbe93ecb5" End If End Sub
It does its job. When the new document appears (after the docker loading) VBA event is refreshing the docker. Of course, I must find a way to stop it acting for all new documents, but I suppose (in VBA) will not be so difficult.
I am trying now to do that programmatically from C#. In VBA, in order to be able to write code in VBA module you need a reference to 'Microsoft Visual Basic for Applications Extensibility 5.3'. I did the same in C# I opened it and I used:
using vBE = Microsoft.Vbe.Interop;
Now I have vBE having all the necessary methods but I do not know how to instantiate a variable in order to use it for my purpose. I mean corelApp has been initialized in the main constructor connected to the 'app' argument. I am a beginner in C# and I am struggling to find the way... Any help on that issue will be much appreciated...
What about the strange behavior of loosing event subscription? Does that happens in your installation, too? If yes, did you have enough patience to test it on three open documents for more then 20 times...?
Your code works in terms of macro accessing and probably running them. I did not test macros running...
Even in VBA you can run existing macros but you cannot access, modify, create code without a reference to 'Microsoft Visual Basic for Applications Extensibility 5.3'. So I added such a reference in my C# project. It brought VBIDE in the References folder. Clicking on it you will see 'Microsoft.Vbe.Interop' and see its methods. Only here you have the necessary methods to access VBA code...
In VBA (corel, Excel, etc.) it adds that methods to Application. I have no idea how I can do that in C#... Do you? That's why I tried to directly access 'Microsoft.Vbe.Interop' but I also do not know how to initialize that...
I found the referenced file on the path: C:\Program Files (x86)\Common Files\Microsoft Shared\VBA\VBA6\VBE6EXT.OLB
If in your case it is somewhere else use, please, the next VBA code to find it:
1 2 3 4 5 6 7 8
Dim VBP As VBProject, R As Reference Set VBP = Application.VBE.ActiveVBProject For Each R In VBP.References If R.Name = "VBIDE" Then Debug.Print R.Description Debug.Print R.FullPath End If Next
Do not forget the reference to 'Microsoft Visual Basic for Applications Extensibility 5.3' !
So, a way to use this extensibility file will give us the possibility to write code in VBA modules.
And a way to keep Corel events in an event-handler variable will give us the possibility to check it before event itself subscribing or in case of other events firing and re-subscribing in case of null, when corel looses it... I'm afraid that not the C# code is the problem but corel X8 itsesf has this strange instable behavior. But I am not sure, of course...
I found a way to add all VBE interface methods to application VBE...
No after some tests I am almost sure that unsubscribing of pagheChange event is a Corel problem... I created a bool variable made true when subscribing and false when unsubscribing. So nothing from inside code unsubscribe the event. Corel itself looks to be guilty for this instability...
That's why the necessity of obtaining the event handler following it and resubscribing in case of null is even bigger if you really need this events working smooth...
Can anybody help on this issue? At least with a piece of idea or a link somewhere to debate it...
Thanks in advance!
I succeeded to show a form looking exactly like one in VBA. I mean to be all the time on top of CorelDRAW application window even with or without focus. Being able to receive text in its own text boxes. I used form.Show() but I succeeded to define it like a child of Corel application window...
What is strange regarding events would be the next described behavior:
- If pageChange event is subscribed from the docker itself class it is unstable. It works (updates some text boxes on the docker) for maximum twenty times. Most of the time less...
- If pageChange event is subscribed from a Windows form updating text boxes on that form it is more stable and works for much more times. It looks it is a maximum times allowed by corel and it never worked more then 582 times. I had enough patience to press the arrow increasing page dimensions and counting the pressing number in another text box...
Now I am a little confused... I do not know if this different corel behavior is connected or not with the class of subscribing or with the interface having the text boxes to be updated.
I am trying to fill the same text boxes of the docker from the form code but I can not...
How should I do docker text boxes updating from a different class?
I was trying :
1 2 3 4
DockerUI dockUI = new DockerUI(corelApp); MessageBox.Show(dockUI.txtTest.Text); dockUI.txtTest.Text = "test"; MessageBox.Show(dockUI.txtTest.Text);
First MessageBox returns the value on the text box in the moment of DockerUI class instantiation and the second one returns 'test', but the text in the docker text box is not updated at all...
I tried to make the docker class static in order to use it without instantiating but I did not have success neither... Can anybody help me on that issue?