Greetings all.
Here is the situation. I am writing an app that synchronizes data
between a PalmOS device and desktop PC. The PalmOS app was written using
Pumatech's Satellite Forms development environment. In order to
synchronize application data written using SatForms, you basically place
an ActiveX control (provided with the SDK) on a form. After "activating"
the control ("Enabled" property set to true) then it will fire an event
(HotSyncEvent) as soon as the user HotSyncs their Palm. Then, you can
call the various methods provided by the ActiveX control in order to
control the synchronization of data.
Now, of course this control was developed, and all documentation
written, with the intent that most developers using their software would
be using Visual Basic (version 6) to write their desktop synchronization
software. For me, VB is not an option. So, I tried to instead run the
"aximp" utility on the control, generating the runtime callable wrapper
(RCW DLL) for COM Interop and spewing/building C# code that implements a
class which inherits from System.Windows.Form.AxHost. This seemed to
work just fine.
Afterward, I went ahead and added the newly generated dotnet control
(the one implemented by "aximp" that inherits from AxHost) to a form and
made sure the control was "Enabled". I registered a HotSyncEvent (as
exposed by the control) handler and then executed a HotSync. The
HotSyncEvent never fired. At first I was baffled but then realized that
hosting the ActiveX control in a dotnet form may be somehow blocking
whatever interprocess communication methodology is used by the SatForms
HotSync conduit DLL to contact any running, active, SatForms ActiveX
controls.
So, I did some detective work, trying to see what IPC method was used. I
placed the SatForms ActiveX control in the ActiveX Test Control
Container, manually activated it, then started the Spy++ utility. After
some trial and error, I selected just the right window with the Spy++
utility on which to intercept windows messages. Sure enough, the
SatForms HotSync conduit DLL uses SendMessage() to send a "registered"
windows message to signal the event.
So, some side effect of the System.Windows.Forms.Form and/or
System.Windows.Forms.AxHost class implementations is stopping,
filtering, or otherwise not allowing this windows message to make it to
the actual window (handler) created by the actual ActiveX control. One
of my attempts to get around this was to use the "NativeWindow" class to
intercept this registered windows message with my top-level window (my
main form) and then use interop to call the Win32 SendMessage()
function. I hoped that the window handle in the "Handle" property field
of the AxHost class might refer to the actual window handle created by
the control. (code attached)
Woe is me, this didn't work. I was able to intercept the registered
windows message, but my attempt at sending it along was futile. Nothing
happened. As you can see, I am diligently trying to not have to
implement an ActiveX control container in a C/C++ application in order
to perform the relatively simple synchronization actions.
So, if a typical instance of this control in a control container (as
provided in a VB form, the ActiveX Control Test Container or, I assume,
any other appropriate C/C++ application) receives this windows message
just fine, what about the dotnet CLR or framework makes it so an
instance wrapped via an AxHost class doesn't get the message?
Also, does anyone know how I might be able to retrieve a handle to the
window created by the control so as to be able to send the notification
along? Do I have some fundamental misunderstanding of something here? Is
there any other information that might be useful on this topic that
you'd like to share with me?
I appreciate any and all help.
ATTACHED: [For reading -- you won't be able to build and run]
SyncEventForm.cs
----------------
Test program that demonstrates what I've been trying to accomplish as
far as embedding the SatForms ActiveX control in a form and handle the
HotSyncEvent exposed by the same control. Must be linked with
SFControl.dll (built from code file below).
SFControl.cs
------------
Ultimately generated by "aximp.exe", then marginally modified, this file
implements an ActiveX control wrapper (by inheriting from AxHost)
exposing it as a regular dotnet control. To build requires the other DLL
generated by "aximp.exe", I assume a runtime callable wrapper (RCW) to
the actual control COM object. Since this isn't included, nor is the
actual control (OCX), you can't build and run this example unless you
have Satellite Forms 5.2 and related files installed, then run aximp on
the control yourself.

Signature
Kendall Gifford
========================================
WEB: http://kendall.jedis.com/
EMAIL: [REPLY TO NEWSGROUP PLEASE]
========================================
Vadim Melnik - 08 Oct 2003 09:21 GMT
Hi Kendal,
> ...After "activating"
> the control ("Enabled" property set to true) then it will fire an event
> (HotSyncEvent) as soon as the user HotSyncs their Palm.
Could not it be a problem that AxHost class has Enabled property as well, so
it collide with ActiveX one, (at least I see Enabled and _Enabled properties
in SFControl.cs)? Try directly access ActiveX using AxHost.GetOcx() or via
private SFControl.ocx member and set Enabled property in such way.
> Also, does anyone know how I might be able to retrieve a handle to the
> window created by the control so as to be able to send the notification
> along? Do I have some fundamental misunderstanding of something here? Is
> there any other information that might be useful on this topic that
> you'd like to share with me?
It is not good idea, unless control explicitly exposes it internal window,
control might be windowless for example and without window at all. ActiveX
control and container interact using COM interfaces. But if you still need
window handle see IOleWindow::GetWindow. Hope it helps somehow.
..
Cheers,
Vadim.
Kendall Gifford - 09 Oct 2003 00:32 GMT
Hello.
>>...After "activating"
>>the control ("Enabled" property set to true) then it will fire an event
[quoted text clipped - 4 lines]
> in SFControl.cs)? Try directly access ActiveX using AxHost.GetOcx() or via
> private SFControl.ocx member and set Enabled property in such way.
I did check this as well, actually. You'll notice that the code in
SFControl.cs, as generated by aximp, overrides the AxHost's Enabled
property with the following:
...
public override bool Enabled {
get {
if ((this.ocx != null) && (this.PropsValid() == true)) {
return this.ocx.Enabled;
} else {
return base.Enabled;
}
}
set {
base.Enabled = value;
if ((this.ocx != null)) {
this.ocx.Enabled = value;
}
}
}
Thus, when getting or setting the Enabled property on an SFControl
object, you're accessing the property on the underlying ocx object. I
guess aximp is smart enough to detect that the underlying control has a
property with the same name as a property in the AxHost class.
I appreciate the help in trying to figure this out. I've pretty much
decided, however, to give in and just do this in C++ instead.

Signature
Kendall Gifford
========================================
WEB: http://kendall.jedis.com/
EMAIL: [REPLY TO NEWSGROUP PLEASE]
========================================