I would like to handle a button clicked event in a native c++ class. I have tried creating a 'handler' object derived from Object to handle the event and then calling a c++ method. For example I tried the following code:
ref class GButtonHandler sealed : public Object
{
public:
void Button_Click(Object^ sender, RoutedEventArgs^ e)
{
}
GTextBlockHandler(GButtonImpl * pButtonImpl, Button ^ button)
{
button->Click += ref new RoutedEventHandler(this, >extBlockHandler::Button_Click);
}
};
Thinking that I could squirrel away the pButtonImpl pointer and then use it to call a native function in the Button_Clicked function. However on compiling this code, I get the error:
error C3986: '{ctor}': signature of public member contains native type 'GButtonImpl'
So it seems that it does not like me passing in native classes into an ref object. Is there a way to do this?
Note that I am completely new to developing Metro style apps, so bear with me!
Ok, it all makes sense to me now. For anyone else who is interested, the reason you cannot have WinRT Objects with public functions that have native C++ arguments is that these objects would then not be consumable by non C++ code. However, the (obvious?) solution is to make the constructor private and have the class that creates the Object declared as a 'friend' class (duh!). Then all is well, the compiler is happy, and I am happy.
Thanks to all who took the time to read this.
The correct answer is to use internal rather than public for the constructor. This tells the compiler that it will only be available in the current project, and won't be available to external projects (i.e. a library written in another language).
Related
I have developed any button application using createDialogParam and DialogProc. first i declared DialoProc method as static in order to make every thing work fine and it worked but now the situation is that there are so many variables(Not globally declared) and functions which i have to use inside DialogProc function and now i want to make it Non static because making it static makes me not implement few more things.
If i don't declare it static it gives error
m_hwndPreview = CreateDialogParam( g_hInst,MAKEINTRESOURCE(IDD_MAINDIALOG), m_hwndParent,(DLGPROC)DialogProc, (LPARAM)this); //('type cast' cannot convert from 'overloaded-function'
//to 'DLGPROC')
Is there any solution to make dialogProc function without declaring it static ???
It must be a static function because Windows calls it from C code, not C++ code. But there are several ways your static function can retrieve a 'this' pointer that you saved somewhere, then use that pointer to call a class member function. Every GUI library available for Windows solves this problem: Consider using one.
In my constructor of a class, I call a virtual member. Whether this should or should not be done is out of scope for my question.
WORKS (can call in my constructor):
protected void DoSomething();
protected virtual void DoSomething();
DOES NOT WORK
protected override void DoSomething();
The DOES NOT WORK part is located in the same library, the derived class has the same visibility, etc. As soon as I override the (virtual or abstract) DoSomething defined in class A in my Class B, I get a MissingMethodException as soon as the method is executed.
Does anyone have an idea why?
After lots of debugging, trying, etc, it seems that a class I used inside the method derived from an interface with this definition:
public interface IMyInterface<out TValueInterface>
It seems you cannot use covariant type parameters, otherwise you will get this exception.
For more information, see this blog post.
I think it's because you created the project with the beta 1 of the SDK.
Try again in a new project and you won't encounter the problem :-p !
I trying to hook several Visual Studio events. Unfortunately I am failing in the first step. The event handlers are never called.
So my question is what I am doing wrong?
Here a little excerpt of my code.
// here are some attributes
[ProvideAutoLoad(VSConstants.UICONTEXT.SolutionExists_string)]
public sealed class VSPackage : Package {
EnvDTE80.DTE2 dte_;
EnvDTE.DocumentEvents documentEvents_;
EnvDTE.WindowEvents windowEvents_;
public VSPackage2Package() {
Trace.WriteLine("I am get called.");
}
protected override void Initialize() {
Trace.WriteLine("I am get called too.");
dte_ = (EnvDTE80.DTE2) System.Runtime.InteropServices.Marshal.
GetActiveObject("VisualStudio.DTE.10.0");
windowEvents_ = dte_.Events.WindowEvents;
documentEvents_ = dte_.Events.DocumentEvents;
windowEvents_.WindowCreated +=
new EnvDTE._dispWindowEvents_WindowCreatedEventHandler(
windowEvents_WindowCreated);
documentEvents_.DocumentOpened +=
new EnvDTE._dispDocumentEvents_DocumentOpenedEventHandler(
documentEvents__DocumentOpened);
Trace.WriteLine("Everything fine until here.");
}
void documentEvents__DocumentOpened(EnvDTE.Document document) {
Trace.WriteLine("Never called");
}
void windowEvents_WindowCreated(EnvDTE.Window window) {
Trace.WriteLine("Never called");
}
}
Edit:
I get it working, looking at other sample code, I figured out that they sometimes getting the DTE object differently. Changing
dte_ = (EnvDTE80.DTE2) System.Runtime.InteropServices.Marshal.
GetActiveObject("VisualStudio.DTE.10.0");
to
dte_ = GetService(typeof(EnvDTE.DTE)) as EnvDTE80.DTE2;
and now everything is fine.
It should work.
I'm pretty sure that if you do the same from an Addin it would work. Packages can be painfull sometimes.
In fact, when a package is loaded the shell (DTE) may not be fully loaded yet. Try to register your events when it is.
To do so, use the OnShellPropertyChange event and the Zombie state to know when to register.
http://social.msdn.microsoft.com/forums/en-US/vsx/thread/3097a0e1-68e3-47ea-a4ba-8511571b2487/
Read the following, I think it answers your question. Note : The GetService method is the same as calling GetGlobalService.
1. ServiceProvider.GlobalProvider
This new static property on the
ServiceProvider class allows access to
the global service provider from any
code, as long as it is called from the
main UI thread. This property is
closely related to the
Package.GetGlobalService static method
which was available in previous
versions of the MPF. The problem with
Package.GetGlobalService was that it
would fail if a package had not yet
been initialized. This led to subtle
ordering bugs in code that used the
MPF libraries without initializing a
package of their own. Sometimes they
would work only because another
package had already initialized the
global ServiceProvider on their
behalf. If that other package was
uninstalled, or perhaps moved to a
different version of the MPF, that
static would no longer be initialized
causing Package.GetGlobalService to
fail.
Now, in MPF 10, you can call
ServiceProvider.GlobalProvider at any
time as long as you are calling from
the UI thread. For compatibility, this
mechanism will still use the
ServiceProvider created by the first
Package to be sited but, in the case
where no Package has yet been
initialized, MPF 10.0 now has the
ability to obtain the global provider
from the registered COM message
filter. Package.GetGlobalService() is
also hooked up to this new mechanism.
Make sure you are not boxing and unboxing your DTE object. I found this was the issue for me.
See my solution here: http://social.msdn.microsoft.com/Forums/en-US/vsx/thread/eb1e8fd1-32ad-498c-98e9-25ee3da71004
I am trying to use the OpcRcw.da.dll. If I interop this dll inside a test console project everything works, but if I build dll project to do my interop gymnastic and ref my library into my console project I am getting this error:
COM object that has been separated from its underlying RCW cannot be used.
What need to be done to a class lib project to not kill the RCW ref?
This can happen for a few reasons, the big ones I know of are below.
Event Handlers Without Strong References to the Delegate
A caller subscribes to an event on the com object without keeping a strong reference to the callback delegate. Here is an example of how to do this correctly and how to not do it:
The reason for this is a strong reference needs to be kept to the delegate, if it goes out of scope, the wrapper will release the reference count for the interface and bad things will happen.
public class SomeClass
{
private Interop.ComObjectWrapper comObject;
private event ComEventHandler comEventHandler;
public SomeClass()
{
comObject = new Interop.ComObjectWrapper();
// NO - BAD!
comObject.SomeEvent += new ComEventHandler(EventCallback);
// YES - GOOD!
comEventHandler = new ComEventHandler(EventCallback);
comObject.SomeEvent += comEventHandler
}
public void EventCallback()
{
// DO WORK
}
}
Calls to a disposed Runtime Callable Wrapper
The wrapper has been disposed and calls are being made after it has been disposed. A common way this can happen is if a control is using an activex control or COM object and the controls Dispose() is called out of order.
A form gets Close() called.
System.Windows.Forms.Close() will call Dispose()
Your forms virtual Dispose() will be called which hopefully calls base.Dispose() somewhere. Systems.Windows.Forms.Dispose() will release all COM objects and event syncs on the form, even from child controls.
If the control that owns a com object is explicitly disposed after base.Dispose() and if it calls any methods on it's COM object, these will now fail and you will get the error “COM object that has been separated from its underlying RCW cannot be used”.
Debugging Steps
A good way to debug this issue is to do the following:
Write a class that inherits from the Interop class (otherwise known as the runtime callable wrapper or RCW).
Override DetachEventSink
Override Dispose
Call your new class instead of calling the interop class directly
Add breakpoint to DetachEventSink and Dispose
See who is calling these methods out of order
One other thing
This isn't related to this issue but while we are on the topic, unless you know otherwise, always remember to check that the thread your COM objects are being used from are marked STA. You can do this by breaking in the debugger and checking the value returned from:
Thread.CurrentThread.GetApartmentState();
It's somewhat hard to tell what your actual application is doing, but it sounds like you may be instantiating the COM object and then attempting to access it from another thread, perhaps in a Timer.Elapsed event. If your application is multithreaded, you need to instantiate the COM object within each thread you will be using it in.
Is it possible to pass a pointer to an object into a DLL, initialize it, and then use the initialized pointer in the main application? If so how? Are there any good articles on the subject, perhaps a tutorial?
I have read this article http://msdn.microsoft.com/en-us/library/ms235460.aspx But that did not seem to get me any where. Maybe I am misinterpreting it...
Yes, this is fine, but assuming your DLL has dynamically allocated the data being pointed to by the buffer, you must be careful about how you free it. There are a few ways to deal with this:
The DLL documents a method by which one should free the data (i.e., CoTaskFree)
The DLL exposes a function that should be called to later free the data
The DLL and the caller are using a common DLL-based runtime; this allows the caller to use the C++ delete operator
Yes.
Assuming you are using Microsoft Visual Studio as your development environment you can export a class rather directly from a dll. Add a define to your dll project something like BUILDING_THE_DLL and the following code snippit will export a c++ class wholesale from the dll.
#ifdef BUILDING_THE_DLL
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT __declspec(dllimport)
#endif
class EXPORT DllClass
{
....
};
This is a highly coupled solution and only works if you build the application and its dll using the same development environment, and rebuild both whenever the class definition changes in any way. this method is heavilly used by the MFC library.
To achieve a greater independence between the dll and app, one typically defines a relatively immutable interface and uses that to make builds more independent, and possibly use different build environments.
An implementation in your dll would look something like this:
struct IMyInterface {
virtual void Destroy() =0;
virtual void Method() = 0;
};
class MoDllObject : public IMyInterface
{
// implementation
};
bool EXPORT DllGetInterface(IMyInterface** ppOut)
{
*ppOut = new MyDllObject();
return true;
}