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.
Brilliant!
Now I have a docker button lunching the form:
1 2 3 4 5
private void btShowForm_Click(object sender, RoutedEventArgs e) { frmCorel frmC = new frmCorel(corelApp, this); frmC.Show(new WindowWrapper(WinGetHandle("CorelDRAW", hwnd))); }
Not using ShowDialog(), but using Show(). It's a way to make the new form a child of CorelDRAW application Windows form. As CorelDRAW is not an IWin32Window we need a wrapper to transform its handle in such a Window.. The process handler and Wrapper class in the next code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
IntPtr hwnd = IntPtr.Zero; public static IntPtr WinGetHandle(string wName, IntPtr hWnd) { foreach (Process pList in Process.GetProcesses()) { if (pList.MainWindowTitle.Contains(wName)) { hWnd = pList.MainWindowHandle; break; } } return hWnd; } public class WindowWrapper : System.Windows.Forms.IWin32Window { public WindowWrapper(IntPtr handle) { _hwnd = handle; } public IntPtr Handle { get { return _hwnd; } } private IntPtr _hwnd; }
Now, so launched form behaves exactly like a VBA form. It stays all the time on top of CorelDRAW application, even with focus or without and takes keys in its text boxes when it has focus... A kind of VBA form having SowModal property set to False.
You can test this, i dont have heavy files for test,
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
using System.Threading; namespace PageTest { public class PageActiveController2 { private Corel.Interop.VGCore.Application corelApp; public delegate void PageActiveEventHandler(Corel.Interop.VGCore.Page Page); private PageActiveEventHandler pageActive; private Corel.Interop.VGCore.Page prevPage; private bool running = false; private Thread Process; private int refreshTime = 0; public event PageActiveEventHandler PageActive { add { StartThread(); pageActive += value; } remove { StopThread(); pageActive -= value; } } public PageActiveController2(Corel.Interop.VGCore.Application corelApp,int refreshTime = 100) { this.corelApp = corelApp; this.refreshTime = refreshTime; } private void StartThread() { running = true; if (Process == null) { Process = new Thread(new ThreadStart(ThreadProcess)); } Process.IsBackground = true; Process.Start(); } private void StopThread() { running = false; if(Process != null) Process.Abort(); Process = null; } private void ThreadProcess() { while (running) { if (corelApp.ActivePage != prevPage) { prevPage = corelApp.ActivePage; if (pageActive != null && prevPage != null) pageActive(prevPage); } Thread.Sleep(refreshTime); } } } }
Usage exemple
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
using System; using System.Windows; using System.Windows.Controls; using corel = Corel.Interop.VGCore; namespace PageTest { public partial class DockerUI : UserControl { private corel.Application corelApp; PageActiveController2 pg2; public DockerUI(corel.Application app) { this.corelApp = app; InitializeComponent(); this.Unloaded += DockerUI_Unloaded; pg2 = new PageActiveController2(app,1500); pg2.PageActive+=pg2_PageActive; } void DockerUI_Unloaded(object sender, RoutedEventArgs e) { pg2.PageActive -= pg2_PageActive; } void updateMyUI(string[] data) { lba_pageName.Dispatcher.Invoke(new Action(() => {lba_pageName.Content = data[0];})); lba_numShapes.Dispatcher.Invoke(new Action(() => { lba_numShapes.Content = data[1]; })); } void pg2_PageActive(corel.Page Page) { updateMyUI(new string[2] { Page.Name, Page.Shapes.Count.ToString() }); } } }
Very interesting!
I gave it a try and I like it very much. I will play more tomorrow... I learned already a lot. So, if I will need to create a thread in order to catch the page change i must find an algorithm to define prevSizeWidth against Page.SizeWidth and so on.
Now, what I could observe that is need to be improved:
When you close CorelDRAW the ThreadProcess is still running and you receive an error at line 5 in the next code :
1 2 3 4 5 6 7 8 9 10 11 12 13
private void ThreadProcess() { while (running) { if (corelApp.ActivePage != prevPage) //error after Corel Application stop { prevPage = corelApp.ActivePage; if (pageActive != null && prevPage != null) pageActive(prevPage); } Thread.Sleep(refreshTime); } }
The unload event of the docker must stop it...
Another thing to be improved, at least understood (by me...) is the time to refresh the labels. I mean it takes more then one second. I tried to modify refreshTime from existing value of 100 to 10 but the necessary time to update has been increased instead of decreasing like I hopped...
"pg2.PageActive -= pg2_PageActive;" already exists in DockerUI_Unloaded method.
I also added "pg2.StopThread(); " but for nothing...
I tried to catch the error but also strange. It is a matter of 'unhandled' error... See the picture:
I tried a break point on the line 97 at the beginning of the stopThread method but it looks that this one is not called before ThreadProcess...
Even more. I put a breakpoint inside DockerUI_Unloaded method but error appears before that.. There I tried to use "pg2.running = false;" after making running variable public.