OberonPlace.com Forums  

Go Back   OberonPlace.com Forums > Developer Forums > VBA > CorelDRAW/Corel DESIGNER VBA

Reply
 
Thread Tools Search this Thread Display Modes
  #1  
Old 06-05-2003, 17:00
bbolte
Guest
 
Posts: n/a
Default takes Draw a long time to start a new document!

corel is sitting on a dual PIII 450 with 256mb ram with win2k server as the OS. there is plenty of swap disk space available. i'm calling Draw from a COM with this call inside a sub called "StartCorel":

Code:
Application.CreateDocument
sometimes, it only takes about 5 seconds or so for Corel to launch and create a new document. most of the time though (prolly 2 out of 3 times), it takes around a minute, sometimes longer. any ideas on why or what i should look at? very perplexing... :?
Reply With Quote
  #2  
Old 06-05-2003, 22:43
Alex's Avatar
Alex Alex is offline
Administrator
 
Join Date: Nov 2002
Posts: 1,940
Blog Entries: 4
Default Re: takes Draw a long time to start a new document!

I'm just curious if you use Draw 10 or 11? There were a couple issues fixed in CorelDRAW 11 related to unexpected freezes when calling COM methods from out-of-process.

There was a discussion on this issue long time ago on the CdrVBA mailing list (gosh, I need to transfer those messages from Yahoo to this forum ).

Here is a brief recap of the thread (dated around November 2001):

Quote:
Originally Posted by Craig Tucker
Is anyone experiencing Coreldrw "sleeping"?
Occasionally, processes to coreldrw seem to be hung - if I hover (not click/activate) over Corel on the desktop, the application starts to work, processing the dll request.
Is there anything I can do in a dll to "WAKE UP" or immediately activate Coreldrw?
Quote:
Originally Posted by Alex
I have notice that as well, however the actual cause of this behavior is unknown so far. When you do the call from out-of-process (VB-to-CorelDRAW for example), Windows COM subsystem needs to synchronize the two processes to make sure CorelDRAW is not busy with anything else and can process the request from VB. In this case a special message is posted to CorelDRAW's message queue. When CorelDRAW processes this message, it is guaranteed that it doesn't do anything else and the COM can make the call to CorelDRAW with the VB request.

Unfortunately sometimes the posted message doesn't get through to CorelDRAW's message pump until another "regular" message (such as mouse, keyboard, screen painting, system timer, etc) arrives. At this time, VB request is processed and finally that normal message is processed as well. The reason why a message from COM doesn't get to CorelDRAW's message queue is unknown so far...

As for the work-around, the easiest way would be to force CorelDRAW to process its message queue to post some dummy message to it. I did the following in the past and seemed to help:

Have another thread or process post a neutral message such as WM_NULL to Draw's message queue. Here is how you can do this from VB. In your main VB program, launch another EXE that would post a WM_NULL message to CorelDRAW every now and then. Here is how I did it. Here are the sources of the two EXEs.

//////////// Main.exe ///////////////////

Code:
Option Explicit

Private Declare Function CreateEvent Lib "kernel32" _
    Alias "CreateEventA" (ByVal Attr As Long, _
    ByVal bManualReset As Long, ByVal bInitialState As Long, _
    ByVal lpName As String) As Long
Private Declare Function SetEvent Lib "kernel32" _
    (ByVal hEvent As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" _
    (ByVal hObject As Long) As Long
Private Declare Function WaitForSingleObject Lib "kernel32" _
    (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long

Sub Main()
    Dim i As Long
    Dim draw As New CorelDRAW.Application
    Dim hEvent As Long
    ' Create interprocess communication object
    ' (to let Poster.exe know when to exit)
    hEvent = CreateEvent(0, 0, 0, "MySyncEvent")
    If hEvent Then
        ' Start the helper program to post a message to CorelDRAW
        Shell App.Path & "\Poster.exe"
    End If
    ' Do some stuff in CorelDRAW
    For i = 0 To 100
        draw.ActiveLayer.CreateRectangle 0, 0, 2, 2
    Next i
    If hEvent Then
        ' Signal the event and let Poster.exe quit
        SetEvent hEvent
        CloseHandle hEvent
    End If
End Sub
//////////// Poster.exe /////////////////
Code:
Option Explicit

Private Declare Function CloseHandle Lib "kernel32" _
    (ByVal hObject As Long) As Long
Private Declare Function PostMessage Lib "user32" _
    Alias "PostMessageA" (ByVal hwnd As Long, _
    ByVal wMsg As Long, ByVal wParam As Long, _
    ByVal lParam As Long) As Long
Private Declare Function WaitForSingleObject Lib "kernel32" _
    (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function OpenEvent Lib "kernel32" _
    Alias "OpenEventA" (ByVal dwDesiredAccess As Long, _
    ByVal bInheritHandle As Long, ByVal lpName As String) As Long

Private Const WM_NULL As Long = 0

Sub Main()
    Dim draw As New CorelDRAW.Application
    Dim hEvent As Long, hDrawWnd As Long, Status As Long
    hEvent = OpenEvent(&H100002, 0, "MySyncEvent")
    hDrawWnd = draw.AppWindow.Handle
    Do
        ' if status in not zero, then we raised the event.
        ' Quit the application.
        ' Post the message every 0.5 seconds (500 milliseconds)
        Status = WaitForSingleObject(hEvent, 500)
        PostMessage hDrawWnd, WM_NULL, 0, 0
    Loop While Status <> 0
    CloseHandle hEvent
End Sub
If you program in C++ you can implement the Poster.exe as a separate thread within your application, so you don't have to create a new process. Unfortunately VB is not thread-safe and it will crash if you try to start another thread...

I hope this helps.
Quote:
Originally Posted by Craig Tucker
I have implemented the Corel wakeup code but am running into timing issues... Under normal circumstances, I can process an image in less than 5 seconds... Now processing time is up over 15 seconds. Here's what I think I'm going to do: Corel sleeping doesn't occur very often and my application checks every 3 seconds for completion, 12 times. If no image has been created (timeout-most likely Corel sleeping) I'm going to call the wakeup routine... Any suggestions?

The culprit seems to be here: Status = WaitForSingleObject(hEvent, 500)
This takes a while to get a result back of 0.

Thanks Much,
Craig...

BTW, Here's wakeup routine...

Code:
Private Sub WakeUpCorel()
    Dim i As Long
    Dim draw As New CorelDRAW.Application
    Dim mDoc As CorelDRAW.Document
    Dim hEvent As Long
    hEvent = CreateEvent(0, 0, 0, "MySyncEvent")
    If hEvent Then
        Shell Me.tcCorelDummyAppPath & "\DummyApp.Exe"
    End If
    Set mDoc = draw.CreateDocument()
    For i = 0 To 10
        mDoc.ActiveLayer.CreateRectangle 0, 0, 2, 2
    Next i
    If hEvent Then
        SetEvent hEvent
        CloseHandle hEvent
    End If
    mDoc.Dirty = False
    mDoc.Close
    Set draw = Nothing
End Sub
Quote:
Originally Posted by Alex
I'm not sure if you know how those events work in Win32 API. I'll try to explain more in case it helps.

First let's take the original code of the two applications that I showed earlier (see above)

Your main program creates a global event object with MySyncEvent name. This object is used to let the helper application know when the main program finished execution. A Win32 event can have two states: signalled or cleared. CreateEvent creates an event object and by default sets it to cleared status (one of those zeros in call to CreateEvent function). The event remains in cleared state until Main.exe calls SetEvent function which signals the object. When the object is signaled, this lets Poster.exe know that Main.exe is finished and there's no need to post all those dummy messages to CorelDRAW.

When Poster.exe is launched it uses WaitForSingleObject to see if the event was signalled. Normally you would have a loop that checks if the event is signaled or not and then check again until it is. However the problem with this approach is that the application is constantly running and eats up CPU pretty fast. WaitForSingleObject just stops the program until the event is signaled or the timeout occurs. By default, it waits for 0.5 seconds and exits. If the return value is not zero, that means that the event was signaled and we should quit the program, otherwise we just post a message and wait for another 0.5 seconds.

By doing this, Poster.exe sleeps most of the time and posts a message to CorelDRAW's message queue twice a second. You can adjust the timeout interval to set how frequently the dummy messages should be sent to Draw. WaitForSingleObject will return 0 only when Main.exe finishes and calls SetEvent method to signal the event object. In response to this, Poster.exe quits as well.

You can implement a more robust "sensing" technology. For example, create two event objects. One will be used to signal when Main.exe finishes executing as in the previous example. However the second one could be used to indicate when every CorelDRAW command is executed. Poster.exe will check the state of that second event and, if it is not signaled within some time interval (let's say, 2 seconds) it means that some command is "stuck". I guess I'll try to create another program for you that would illustrate this approach...

' ==================== Main.exe ==========================
Code:
Option Explicit

Private Declare Function CreateEvent _
    Lib "kernel32" Alias "CreateEventA" _
    (ByVal Attr As Long, ByVal bManualReset As Long, _
    ByVal bInitialState As Long, _
    ByVal lpName As String) As Long
Private Declare Function SetEvent Lib "kernel32" _
    (ByVal hEvent As Long) As Long
Private Declare Function CloseHandle _
    Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function WaitForSingleObject _
    Lib "kernel32" (ByVal hHandle As Long, _
    ByVal dwMilliseconds As Long) As Long

Sub Start()
    Dim i As Long
    Dim draw As New coreldraw.Application
    Dim hSyncEvent As Long, hFreezeEvent As Long
    ' Create thread communication objects
    hSyncEvent = CreateEvent(0, 0, 0, "MySyncEvent")
    hFreezeEvent = CreateEvent(0, 0, 0, "MyFreezeEvent")
    If hSyncEvent <> 0 And hFreezeEvent <> 0 Then
        Shell App.Path & "\Poster.exe"
    End If
    draw.Optimization = True
    For i = 1 To 500
        draw.ActiveLayer.CreateRectangle 0, 0, 2, 2
        ' Signal the completion of the operation
        SetEvent hFreezeEvent
    Next i
    draw.Optimization = False
    If hFreezeEvent Then
        SetEvent hFreezeEvent
        CloseHandle hFreezeEvent
    End If
    If hSyncEvent Then
        ' Signal the event and let the Poster.exe quit
        SetEvent hSyncEvent
        CloseHandle hSyncEvent
    End If
End Sub
' ====================== Poster.exe =================
Code:
Option Explicit

Private Declare Function CloseHandle _
    Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function PostMessage _
    Lib "user32" Alias "PostMessageA" _
    (ByVal hWnd As Long, ByVal wMsg As Long, _
    ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function WaitForSingleObject _
    Lib "kernel32" (ByVal hHandle As Long, _
    ByVal dwMilliseconds As Long) As Long
Private Declare Function OpenEvent Lib "kernel32" _
    Alias "OpenEventA" (ByVal dwDesiredAccess As Long, _
    ByVal bInheritHandle As Long, _
    ByVal lpName As String) As Long

Private Const WM_NULL As Long = 0

Sub Main()
    Dim hSyncEvent As Long, hFreezeEvent As Long
    Dim Draw As New coreldraw.Application
    Dim hDrawWnd As Long
    Dim Status As Long
    hDrawWnd = Draw.AppWindow.Handle
    hSyncEvent = OpenEvent(&H100002, 0, "MySyncEvent")
    hFreezeEvent = OpenEvent(&H100002, 0, "MyFreezeEvent")
    Do
        ' Check if FreezeEvent is raised.
        ' If it times out, it means that CorelDRAW froze
        ' Give 2 seconds for a CorelDRAW command to execute
        Status = WaitForSingleObject(hFreezeEvent, 2000)
        If Status <> 0 Then
            ' OK, Draw is frozen.
            ' Let's try to resurrect it by posting
            ' the dummy message to its message queue
            PostMessage hDrawWnd, WM_NULL, 0, 0
        End If
        ' Check to see if hSyncEvent was signaled.
        ' If it was, quit the application
        ' Timeout is set to 0, so just check and
        ' return immediately
        Status = WaitForSingleObject(hSyncEvent, 0)
    Loop While Status <> 0
    CloseHandle hSyncEvent
    CloseHandle hFreezeEvent
End Sub
Here MySyncEvent is used to indicate when Main.exe is finished, so the Poster.exe can quit also. hSyncEvent is the main communication object between Main.exe and Poster.exe. It gets signaled after every CorelDRAW command. If the object is not signaled within 2 seconds, Poster.exe will post a message to CorelDRAW trying to wake it up.

It is not necessary to signal the event after every Draw OM command. You can spread the SetEvent command within some intervals that you believe should be able to execute within 2 seconds or so. For example, try to set the event after every fifth CreateRectangle command or so.

Another problem here could be that launching the Poster.exe with Shell command from Main.exe could take several seconds (on my machine it takes as much as 10 seconds sometimes). So this could be the source of your 12 seconds vs 3 seconds processing time. To resolve this issue, make Poster.exe a completely independent program and do not exit it when Main.exe quits (remove the hSyncEvent). You might want to create the Event objects in Poster.exe and open them in Main.exe, so Poster.exe owns the event objects. Well, it may seem a little confusing, but I guess you've go the idea...

Let me know if something is still not clear :-)
I hope it shed some light on the problem for you.
Reply With Quote
  #3  
Old 07-05-2003, 09:26
bbolte
Guest
 
Posts: n/a
Default

interesting. would it be better to just upgrade to 11 - as we are using 10?
Reply With Quote
  #4  
Old 07-05-2003, 09:47
bbolte
Guest
 
Posts: n/a
Default

we moved this to a much faster computer to do some further testing - a win2k workstation - not a server. now this code to shut down corel isn't shutting it down

Code:
Private Sub StopCorel() 
    '// close the the document 
    With Application.ActiveDocument 
        .Dirty = False 
        .Close 
    End With 
    '// check to make sure no other documents open 
    '// if not close corel draw 
    If Application.Documents.Count = 0 Then 
        Application.Quit 
    End If 
End Sub
now what? this is a 1.8 ghz machine with a gig of ram. why would it not shut down? subsequent runnings of the com start doing what we discussed in the other post - sometimes using the same corel process and sometimes starting new ones... hmmm? maybe corel 11 is needed.
Reply With Quote
  #5  
Old 08-05-2003, 08:08
bbolte
Guest
 
Posts: n/a
Default

here is how i was able to get the process to terminate. i changed my close corel sub procedure to use WMI:

Code:
Private Sub StopCorel()
    '// close the the document
    With Application.ActiveDocument
        .Dirty = False
        .Close
    End With
    '// check to make sure no other documents open
    '// if not close corel draw
    If coreldraw.Application.Documents.Count = 0 Then
        IsProcessRunning ".", "coreldrw.exe"
    End If
End Sub

Private Sub IsProcessRunning(strServer As String, strProcess As String)
    Dim Process As Variant, strObject As SWbemServices

    Set strObject = GetObject("winmgmts://" & strServer)

    ' Call always gets only one Win32_ComputerSystem object
    For Each Process In strObject.InstancesOf("Win32_Process")
        If UCase(Process.Name) = UCase(strProcess) Then
            '// quit corel
            Process.Terminate
            Exit Sub
        End If
    Next
End Sub
works pretty groovy.
Reply With Quote
  #6  
Old 14-05-2003, 09:09
bbolte
Guest
 
Posts: n/a
Default

CorelDraw 11 fixed the "sleep" issue, if anyone is interested. thanks Alex.
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Creating new document problems ddonnahoe Code Critique 2 20-11-2004 17:11
Printing Raw Prn Files Mark Code Critique 2 16-09-2004 16:15
Corel Draw 9 Active Document korner CorelDRAW/Corel DESIGNER VBA 2 17-04-2004 01:46
is application running? Seelenquell CorelDRAW/Corel DESIGNER VBA 18 10-02-2004 09:40
CorelDRAW curves to Adobe Photoshop paths converter d-signer CorelDRAW/Corel DESIGNER VBA 8 15-01-2004 00:32


All times are GMT -5. The time now is 21:00.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright © 2011, Oberonplace.com