We currently have a Silverlight UI (which we are unable to change from at this stage) for our system, which has very limited drag drop capabilities. We are currently running out of browser with elevated trust. So in order to handle Silverlight's shortcomings I have created a c++ com library in order to handle Drag Drop events. This works perfectly well for incoming events from other applications, however I'm struggling to get the Drag operations, with our app as the source, working correctly. Most of the files to be dragged from the app will be virtual, which I have managed to get working however regardless of everything I've tried I have been unable to get the operation to be asynchronous, and the app locks up during the process.
I initially implemented only the IAsyncOperation (need backward compatibility to xp), which had no apparent affect. My DataObject is queried for the interface, gets the ref. A Call to GetAsyncMode is made, which returns VARIANT_TRUE, and a call to StartOperation is made. However all operations are done on the same thread (ui thread) and no async seems to be in affect.
I Subsequently tried implementing ICallFactory to return an AsyncIDataObject. Here explorer seems to check for the ICallFactory interface, calls the CreateCall on the call object and queries it to make sure it has the correct interfaces. Using the symbol servers I am able to see that it this occurs in the AsyncStubInvoke call stack. From here a call to StdStubBuffer_QueryInterface is made which is searching for the ICallFactory interface. This check fails and I unfortunately cannot see what object is being checked for this interface. After this fails the call seems to fall back to SyncStubInvoke after an operation not supported error (following from the Interface not supported error). All of this too seems to have no effect on the end result and the call is still apparently synchronous with the source app locking up.
My DragDrop class which exposes the com calls is CComMultiThreadModel. I have tried using my DataObject as a basic class not inheriting from CComObjectRootEx and a wrapper IDataObject class which is defined in the IDL as well and does inherit from CComObjectRootEx as is also CComMultiThreadModel. I have also tried having this class inherit from IDispatch as well as IUnknown.
Any feedback would be greatly appreciated.
Related
I have a C++ COM (multi-threaded apartment model) application that I build with Visual C++ 2019. I am playing with the COM-based Active Script interfaces and classes. I have a JavaScript ("JScript" really, CLSID {F414C260-6AC0-11CF-B6D1-00AA00BBBB58}) Active Script COM object created and set up. Everything works surprisingly well (for something that is falling into obscurity, unfortunately).
Is there an idiomatic approach to registering and calling event listeners where a script can use an API like like https://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener and where I can dispatch events from the script host (C++)? To clarify, I am well able to call IDispatch interface methods from scripts, I want to call script functions that were passed earlier with such methods to the program, from the program. GetScriptDispatch is something else -- it lets me call methods available in the global script namespace, but I need to call functions that I pass to a proxied (from the script) "addEventListener" method.
I depend on this functionality because I want to dispatch events. Basically I want addEventListener to be available on certain proxied (e.g. objects added to script namespace with AddNamedItem) objects and I need to call event listeners added through calls to that method, when certain events in the C++ application happen.
I have read something about IConnectionPoint, and the Active Script documentation briefly mentions "event sinks" a couple of times, without there being examples on how and for what these can be used for. There is also the IBindEventHandler interface, without much explanation again as to what to use it for.
I understand this is ancient stuff, but I like COM and Active Script interface has several implementations, which to me adds utility.
You need to create an object that implements events (see IConnectionPoint).
After starting the script you can call AddNamedItem. The script now knows the interface of you object. If it implements it can register to this events when the state changes to SCRIPTSTATE_CONNECTED.
If an event is fired, the script will receive the event and will execute the appropriate code section.
There are old samples:
Q168214 SAMPLE: MFCAXS (you might find it in the wayback engine)
And there is a sample here in code project
For ATL samples for Events look here
I am trying to call a WCFService from Windows phone 8 which connects and returns data fine when i use WCFTestClient but when I refreence the service using add reference and then try to access in code only the async methods are showing in intelesence. I have not delciared my methods as aync how can i ensure I can access my other methods as I calling a webservice does it need be aysnc.
// Constructor
public MainPage()
{
InitializeComponent();
// Sample code to localize the ApplicationBar
//BuildLocalizedApplicationBar();
IcuroServiceClient _db = new IcuroServiceClient();
var json =_db.GetPersonByIdAsync(1);
}
And if so How would I convert a method that is as simple as below to Aysnc ?. I am used to asmx services and new to WCF.
public string GetListByUserId(string userId)
{
List<curoList> myList = _db.GetAllListsByUserId(userId);
var json = JsonConvert.SerializeObject(myList, Newtonsoft.Json.Formatting.None);
return json;
}
Its grayed out here for me mate In my normal signature im returning a string but the asyncs dont look like their returning anything just void .
Windows phone is based literally and figuratively on the Silverlight motif of keeping all service calls async only. It is a two step process where one has to think backwards. Here are the steps
Provide a callback method whose job it is to handle the resulting data or error in an appropriate fashion.
Then make the call as one normally would (but calling the async version) to start the process off on a separate thread.
Be cognizant of not directly loading to the GUI in the callback method for the result is on a different thread; note that loading to VM properties is fine for the most part whereas the update to any GUI subscribed bindings will be done on the thread.
Hot to Resolve
In the example given before the call to to db.GetPersonByIdAsync(1) provide (find using intellisense) the async subscription method that has the call back.
It may be prefixed with either a Load method or a Begin call, for the PersonById.
In the editor, the providing of a method is usually done by intellisense which where one can tab an example into code. That is so one doesn't have to root out the parameters for the callback method.
Possible example, shows the how to do it:
client.GetPersonByIdAsyncCompleted += MyMethodToHandleResultforGetPerson; // var personId = e.Result;
client.GetPersonByIdAsync(1);
Why
When Silverlight was designed, having a program wait (even if its busy waiting) on any thread would slow down the browser experience. By requiring all database (service) calls to be asynchronous ensures that the developer can't slow down the browser, in particular by bad code. Loosely speaking that motif carried over to the windows phone where Silverlight was brought over as the main operations for the phone.
It took me awhile to get used to the process, but now that I have worked on Silverlight and Windows phone, I actually use the async motif in WPF even though I don't necessarily have too, it makes sense in terms of data processing and thread management.
It is not easier for the developer per-se for everyone learns in a synchronous hello world, but it is adapted for the needs of the target platform and once learned it becomes second nature.
I have written a simple dialog based MFC application using a thirdd party soft tree control. I am trying to write a automation client for the application. For this I wrote a singleton out-of-process COM Testing Agent for the dialog based application sample app. The Com server exposes a Run method to the automation client. This Run method access the gut of the mfc app and actually mimicks a click on the GUI. The problem i am facing is when the automation client tries to invoke Run method on the Com object it is able to invioke it but when the Run method crashes when it tries to access the control's methods such as getCaretInedx.
I have tried to cach the exception and log the message to a file but have not been able to do so.
My question is: Is there any limitation in the way a com object can access the application? Or am i missing anything to facilitate this.
Any help or pointer is greatly appreciated. Since this is my first in COM I have not been able to make much progress.
Thanks
Is your client's window actually being created? If not, the hwnd doesn't exist, which is probably why it crashes. Furthermore, your client may be hidden behind another window when it is started, and may exhibit different behavior than when the user called it through regular interaction.
In general, calling code that relies on or interacts with the UI from a COM server is fraught with peril, especially when that code is not written in the first place to behave like this. Most UI isn't that defensive about HWND's existing etc.
I have a program that (amongst other things) has a command line interface that lets the user enter strings, which will then be sent over the network. The problem is that I'm not sure how to connect the events, which are generated deep inside the GUI, to the network interface. Suppose for instance that my GUI class hierarchy looks like this:
GUI -> MainWindow -> CommandLineInterface -> EntryField
Each GUI object holds some other GUI objects and everything is private. Now the entryField object generates an event/signal that a message has been entered. At the moment I'm passing the signal up the class hierarchy so the CLI class would look something like this:
public:
sig::csignal<void, string> msgEntered;
And in the c'tor:
entryField.msgEntered.connect(sigc::mem_fun(this, &CLI::passUp));
The passUp function just emits the signal again for the owning class (MainWindow) to connect to until I can finally do this in the main loop:
gui.msgEntered.connect(sigc::mem_fun(networkInterface, &NetworkInterface::sendMSG));
Now this seems like a real bad solution. Every time I add something to the GUI I have to wire it up all through the class hierarchy. I do see several ways around this. I could make all objects public, which would allow me to just do this in the main loop:
gui.mainWindow.cli.entryField.msgEntered.connect(sigc::mem_fun(networkInterface, &NetworkInterface::sendMSG));
But that would go against the idea of encapsulation. I could also pass a reference to the network interface all over the GUI, but I would like to keep the GUI code as seperate as possible.
It feels like I'm missing something essential here. Is there a clean way to do this?
Note: I'm using GTK+/gtkmm/LibSigC++, but I'm not tagging it as such because I've had pretty much the same problem with Qt. It's really a general question.
The root problem is that you're treating the GUI like its a monolithic application, only the gui is connected to the rest of the logic via a bigger wire than usual.
You need to re-think the way the GUI interacts with the back-end server. Generally this means your GUI becomes a stand-alone application that does almost nothing and talks to the server without any direct coupling between the internals of the GUI (ie your signals and events) and the server's processing logic. ie, when you click a button you may want it to perform some action, in which case you need to call the server, but nearly all the other events need to only change the state inside the GUI and do nothing to the server - not until you're ready, or the user wants some response, or you have enough idle time to make the calls in the background.
The trick is to define an interface for the server totally independently of the GUI. You should be able to change GUIs later without modifying the server at all.
This means you will not be able to have the events sent automatically, you'll need to wire them up manually.
Try the Observer design pattern. Link includes sample code as of now.
The essential thing you are missing is that you can pass a reference without violating encapsulation if that reference is cast as an interface (abstract class) which your object implements.
Short of having some global pub/sub hub, you aren't going to get away from passing something up or down the hierarchy. Even if you abstract the listener to a generic interface or a controller, you still have to attach the controller to the UI event somehow.
With a pub/sub hub you add another layer of indirection, but there's still a duplication - the entryField still says 'publish message ready event' and the listener/controller/network interface says 'listen for message ready event', so there's a common event ID that both sides need to know about, and if you're not going to hard-code that in two places then it needs to be passed into both files (though as global it's not passed as an argument; which in itself isn't any great advantage).
I've used all four approaches - direct coupling, controller, listener and pub-sub - and in each successor you loosen the coupling a bit, but you don't ever get away from having some duplication, even if it's only the id of the published event.
It really comes down to variance. If you find you need to switch to a different implementation of the interface, then abstracting the concrete interface as a controller is worthwhile. If you find you need to have other logic observing the state, change it to an observer. If you need to decouple it between processes, or want to plug into a more general architecture, pub/sub can work, but it introduces a form of global state, and isn't as amenable to compile-time checking.
But if you don't need to vary the parts of the system independently it's probably not worth worrying about.
As this is a general question I’ll try to answer it even though I’m “only” a Java programmer. :)
I prefer to use interfaces (abstract classes or whatever the corresponding mechanism is in C++) on both sides of my programs. On one side there is the program core that contains the business logic. It can generate events that e.g. GUI classes can receive, e.g. (for your example) “stringReceived.” The core on the other hand implements a “UI listener” interface which contains methods like “stringEntered”.
This way the UI is completely decoupled from the business logic. By implementing the appropriate interfaces you can even introduce a network layer between your core and your UI.
[Edit] In the starter class for my applications there is almost always this kind of code:
Core core = new Core(); /* Core implements GUIListener */
GUI gui = new GUI(); /* GUI implements CoreListener */
core.addCoreListener(gui);
gui.addGUIListener(core);
[/Edit]
You can decouple ANY GUI and communicate easily with messages using templatious virtual packs. Check out this project also.
In my opinion, the CLI should be independant from GUI. In a MVC architecture, it should play the role of model.
I would put a controller which manages both EntryField and CLI: each time EntryField changes, CLI gets invoqued, all of this is managed by the controller.
I've got a bit of a problem with my application using MSHTML. I have everything working except for the odd keystroke missing behavior when typing fast as mentioned in the subject line. I think it may have to do with the method I use to sink the events?
The details: my application is a separate program written in C++ and MFC in Visual Studio 2005. The program attaches to a currently running (independent) instance of Internet Explorer and gets the pointer to the IWebBrowser2 interface and passes it to an object of type CCmdTarget:
class CHandler : public CCmdTarget
{
IWebBrowser2* m_pWebBrowser2;
DWORD m_dwBrowserCookie;
…
DECLARE_DISPATCH_MAP()
};
This class keeps track of what's happening in the browser. I sink the browser events with the following command:
LPUNKNOWN pUnkSink = GetIDispatch(FALSE);
retval = AfxConnectionAdvise((LPUNKNOWN)m_pWebBrowser2, DIID_DWebBrowserEvents2, pUnkSink, FALSE, &m_dwBrowserCookie);
If I comment out the AfxConnectionAdvise, then no keystrokes are missed but no more events. If I leave it in I sink the events but miss the occasional keystroke if typing fast.
I know there are a number of ways of connecting to the events (AtlAdvise, connection points), but this was the only one I could get working.
Any suggestions would be great!
If you're just looking for keystrokes, can't you subclass the control?
Underneath the covers all the various connection methods (AtlAdvise, AfxConnectionAdvise, etc) all use IConnectionPointContainer and IConnectionPoint — they're just saving you typing boilerplate COM goo.
I suspect this has to do with how you're connecting to the running instance of IE. How are you getting the IWebBrowser2 pointer? Are you being loaded into the IE process or are you a separate process? If you're running on a different thread than the IWebBrowser2's original thread (the IE Tab UI thread), are you doing proper COM marshalling?