Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

API Sendmessage from VBA?

663 views
Skip to first unread message

Joe Minkwitz

unread,
Dec 29, 1998, 3:00:00 AM12/29/98
to
I have a public sub which uses the API Sendmessage command to send acad
commands to the command prompt
from vba. It ran fine untill recently, then took an unexpected dive. It
can't seem to find the handle for the AutoCAD
window that it's running in...imagine that. If anyone has any expirence
in this area, I would appreciate the help. I posted
the original, unedited, sub that I recieved from someone else in the
customer files.

thanks,
Josh


Tony Tanzillo

unread,
Dec 30, 1998, 3:00:00 AM12/30/98
to
Greg - You do realize that if the user does not
have the MDI document window maximized, that this
will not work?

You could also use EnumWindows() to get it.

Greg Toews wrote:
>
> I don't think there is anything wrong with the FindWindow function although
> I use a different approach. I think the code is missing one important thing
> and that is translating the string to the proper format.
>
> Perhaps the fact that you are calling the FindWindow function everytime you
> send a message is causing a problem. Also, did you do anything to the main
> AutoCAD window caption (ie. where it says "AutoCAD - [Drawing.dwg])? If this
> has been altered in your setup the findwindow function may not work anymore.
> Good Luck!
--
/*********************************************************/
/* Tony Tanzillo Design Automation Consulting */
/* Programming & Customization for AutoCAD & Compatibles */
/* ----------------------------------------------------- */
/* tony.t...@worldnet.att.net */
/* http://ourworld.compuserve.com/homepages/tonyt */
/*********************************************************/

Denis Gagné

unread,
Dec 30, 1998, 3:00:00 AM12/30/98
to
Tony ,

Could you give more details on what will not work?

The PostMessage api requires the MDI Client hwnd but I don't think the
SendMessage does. Maybe I'm missing something.

I got the idea of using the SendMessage api with the WM_COPYDATA parameter
at your website and the code I sent to this NG is very similar to the one
posted by Greg. I'm interested to know how it can be improved. Do you
suggest to get the MDI Client hwnd to maximize the window?

Denis

P.S.: A parameter of the EnumWindows() is the address of a function and the
AddressOf operator does not exist in vba. I sent a workaround a while ago
but it is not supported by Microsoft. I think the dvb file I sent at that
time enumerates windows but I'm not sure.


Tony Tanzillo a écrit dans le message
<368A3EA4...@worldnet.att.net>...


>Greg - You do realize that if the user does not
>have the MDI document window maximized, that this
>will not work?
>
>You could also use EnumWindows() to get it.
>

Joe Minkwitz

unread,
Dec 30, 1998, 3:00:00 AM12/30/98
to
Although the form has focus and acad is in the background, it is maximized. When
I use greg's version, I get a good caption,
but there is still a problem. If I set a watch on the line:
AcadWnd = FindWindow(vbNullString, "AutoCAD - [" + ThisDrawing.Name + "]")
and then run a quick watch on "AutoCAD - [" + ThisDrawing.Name + "]", it returns
the value:
<Object variable or with block variable not set>
If I set the watch on the following line of code, it returns the proper value.
But in any event the value of AcadWnd or in the other
version hWnd remains 0. So I always pass from if/then straight to else. If I
blow off the if/then statement and try sending directly to
Thisdrawing.Application.Caption, it sends it into the abyss. If you guys have
any ideas, :)

thanks,
Josh West / Minkwitz Design Services (Joe Minkwitz is the owner)

Tony Tanzillo

unread,
Dec 30, 1998, 3:00:00 AM12/30/98
to
Denis Gagné wrote:
>
> Tony ,
>
> Could you give more details on what will not work?
>

The call to FindWindow() will fail if the MDI
document window is not maximized, because in
that case, the drawing name is in the caption
of that window, rather than the main window.

Denis Gagné

unread,
Dec 30, 1998, 3:00:00 AM12/30/98
to
Tony,

At first glance, I did not notice the presence in the code of drawing Name
property. I always use the Caption property with FindWindow but also
noticed this property is not reliable. In some occasions, it can return the
autosave file name.

I'll change my code to rely on the Name property and assure that the MDI
Client window is maximized.

Thanks for the hint

Denis


Tony Tanzillo a écrit dans le message

<368A53B8...@worldnet.att.net>...

Joe Minkwitz

unread,
Dec 30, 1998, 3:00:00 AM12/30/98
to
If you use the name property, it only returns the value "AutoCAD", not the
actual drawing name.

Greg Toews

unread,
Dec 30, 1998, 3:00:00 AM12/30/98
to
Denis,

I think there are several problems with using the Name property. This method
fails if the caption varies from the basic "AutoCAD - [Drawing.dwg]"
formula.

1. If the child window is not maximized the caption changes (Tony brought
this one up)
2. If the drawing is read only then the caption changes
3. If you use a third party program such as those available from Manusoft
which alter the caption. One of those programs changes the caption to
"AutoCAD - "C:\Path\Drawing.dwg]"

The other method that you are using avoids more problems than the Name
method does so I'm not sure why you would want to switch.

A separate but similar issue is the whole problem with multiple instances of
AutoCAD. I use VB instead of VBA and I don't believe there is any way for my
standalone EXE to determine which instance of AutoCAD launched it. Even if
that problem is solved I believe the next problem would be how to pick which
instance of AutoCAD you are talking to via the Automation interface.

Greg

Denis Gagné wrote in message <76dras$fi...@adesknews2.autodesk.com>...

Greg Toews

unread,
Dec 30, 1998, 3:00:00 AM12/30/98
to
I think the watch problem is just something you have to deal with. Kind of
like in C when you are trying to watch a variable that has been optimized -
it is frustrating but there are ways around it.

If I understand - you are saying that you still do not get a window handle
and your code does not work? If this is the case then we need to know what
the caption of your main AutoCAD window is when this occurs. Does it say
"AutoCAD" or "AutoCAD - [Drawing.dwg]" or "AutoCAD - [Drawing.Dwg - Read
Only]" or "AutoCAD - [C:\Data\Drawing.dwg]" or some variation on these
themes or something else entirely?

Greg

Joe Minkwitz wrote in message <368A584D...@xta.com>...


>Although the form has focus and acad is in the background, it is maximized.
When
>I use greg's version, I get a good caption,
>but there is still a problem. If I set a watch on the line:
> AcadWnd = FindWindow(vbNullString, "AutoCAD - [" + ThisDrawing.Name +
"]")
>and then run a quick watch on "AutoCAD - [" + ThisDrawing.Name + "]", it
returns
>the value:
> <Object variable or with block variable not set>
>If I set the watch on the following line of code, it returns the proper
value.
>But in any event the value of AcadWnd or in the other
>version hWnd remains 0. So I always pass from if/then straight to else. If
I
>blow off the if/then statement and try sending directly to
>Thisdrawing.Application.Caption, it sends it into the abyss. If you guys
have
>any ideas, :)
>
>thanks,
>Josh West / Minkwitz Design Services (Joe Minkwitz is the owner)
>

>Denis Gagné wrote:
>
>> Tony ,
>>
>> Could you give more details on what will not work?
>>

>> The PostMessage api requires the MDI Client hwnd but I don't think the
>> SendMessage does. Maybe I'm missing something.
>>
>> I got the idea of using the SendMessage api with the WM_COPYDATA
parameter
>> at your website and the code I sent to this NG is very similar to the one
>> posted by Greg. I'm interested to know how it can be improved. Do you
>> suggest to get the MDI Client hwnd to maximize the window?
>>
>> Denis
>>
>> P.S.: A parameter of the EnumWindows() is the address of a function and
the
>> AddressOf operator does not exist in vba. I sent a workaround a while ago
>> but it is not supported by Microsoft. I think the dvb file I sent at that
>> time enumerates windows but I'm not sure.
>>

>> Tony Tanzillo a écrit dans le message

>> <368A3EA4...@worldnet.att.net>...
>> >Greg - You do realize that if the user does not
>> >have the MDI document window maximized, that this
>> >will not work?
>> >
>> >You could also use EnumWindows() to get it.
>> >

Denis Gagné

unread,
Dec 30, 1998, 3:00:00 AM12/30/98
to
>The other method that you are using avoids more problems than the Name
>method does so I'm not sure why you would want to switch.

I also realized this afterward and decided to stick to the
Application.Caption property. I think the only occasion it returned a false
value is within a beginSave reactor when an autosave was performed.


>A separate but similar issue is the whole problem with multiple instances
of
>AutoCAD. I use VB instead of VBA and I don't believe there is any way for
my
>standalone EXE to determine which instance of AutoCAD launched it. Even if
>that problem is solved I believe the next problem would be how to pick
which
>instance of AutoCAD you are talking to via the Automation interface.

I use the GetForegroundWindow, the GetNextWindow, the GetClassName and the
GetWindowText Win32 api functions to find to the top acad Window. Then I
revoke every acad object in the ROT until it matches the right caption.

If you launch your VB application from an AutoCAD toolbar or from an AutoCAD
menu command it will always connect to that session.

Denis


Joe Minkwitz

unread,
Dec 31, 1998, 3:00:00 AM12/31/98
to
The drawing caption is "AutoCAD - [Drawing.dwg]".
The property "ThisDrawing.Application.Name" returns the value "AutoCAD", and
the property "ThisDrawing.Application.Caption" should return "AutoCAD -
[Drawing.dwg]",
but instead, it is returning garbage. In any event, the value of the property
will not pass
into the variable with the statement "hWnd = Findwindow (vbnullstring,
ThisDrawing.Application.Caption)".
hWnd remains at 0. I've also tried using sendmessage directly with the property
without storing
it as a variable first, but it does'nt seem to acknowledge the property until
after the current line
of code has already passed????? This is a new one for me and it's got me
stumped.

Greg Toews

unread,
Dec 30, 1998, 3:00:00 AM12/30/98
to
I don't think there is anything wrong with the FindWindow function although
I use a different approach. I think the code is missing one important thing
and that is translating the string to the proper format.

Perhaps the fact that you are calling the FindWindow function everytime you
send a message is causing a problem. Also, did you do anything to the main
AutoCAD window caption (ie. where it says "AutoCAD - [Drawing.dwg])? If this
has been altered in your setup the findwindow function may not work anymore.
Good Luck!

Greg

My code requires the following definitions (note the slightly different
definition for the struct, the additional function and the global variable)

Private Type COPYDATASTRUCT
dwData As Long
cbData As Long
lpData As Long
End Type

Private Const WM_COPYDATA = &H4A

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal
lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA"
(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As
Any) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (hpvDest
As Any, hpvSource As Any, ByVal cbCopy As Long)
Dim AcadWnd As Long ; the window handle is a global variable

I only get the window handle once in the initialization event of the form

Private Sub UserForm_Initialize()


AcadWnd = FindWindow(vbNullString, "AutoCAD - [" + ThisDrawing.Name +
"]")

End Sub

The following is my code for sending the message:

Function SendMsg(s As String) As Boolean

Dim cds As COPYDATASTRUCT
Dim buf(1 To 255) As Byte
Dim i As Long

i = 0
If AcadWnd <> 0 Then
CopyMemory buf(1), ByVal s, Len(s)
cds.dwData = 1
cds.cbData = Len(s) + 1
cds.lpData = VarPtr(buf(1))
i = SendMessage(AcadWnd, WM_COPYDATA, 0, cds)
If i = 0 Then
MsgBox "Can't talk to AutoCAD!", vbCritical, "Message"
End If
Else
MsgBox "Can't find the AutoCAD Window!", vbCritical, "Message"
End If

End Function

Joe Minkwitz wrote in message <36894EC9...@xta.com>...

0 new messages