|
is it possible to drag-drop files between desktop and silverlight?
|
|
|
|
|
Hy Syed,
Your implementation of Silverlight Host Control lacks of a small but really important detail. There is no keyboard support...you cannot enter anything by keyboard inside the Silverlight application.
|
|
|
|
|
Clear, concise and it works.
|
|
|
|
|
Hi i am a developer from china. i have read your article,it is very cool. i follow your way to try to load a xap which implement by smoothstreaming, but as the result, load failed. please help me, thanks
<br />
namespace SilverlightApplication1<br />
{<br />
public partial class MainPage : UserControl<br />
{<br />
public MainPage()<br />
{<br />
InitializeComponent();<br />
smoothStreamingMediaElement1.SmoothStreamingSource = new Uri("http://streams.smooth.vertigo.com/elephantsdream/Elephants_Dream_1024-h264-st-aac.ism/manifest"); <br />
}<br />
<br />
}<br />
}<br />
|
|
|
|
|
I have the same problem. Does somebody give a hint why smooth streaming doesnt work when hosted in c++ app?
|
|
|
|
|
How would I go about creating a windowless XcpControlHost? I would like to use OleDraw to draw the control to a BITMAP instead of a window.
|
|
|
|
|
Please take a look at my old post "Host Silverlight in ATL"
you will find following block
STDMETHOD (Read)(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog)
{
HRESULT hr = E_INVALIDARG;
BSTR bstrValue = NULL;
if (_wcsicmp(pszPropName, L"Source") == 0)
{
bstrValue = SysAllocString(L"SilverlightTestApp.xap");
}
else if (_wcsicmp(pszPropName, L"Background") == 0)
{
bstrValue = SysAllocString(L"Gold");
}
else if (_wcsicmp(pszPropName, L"Windowless") == 0)
{
V_VT(pVar) = VT_BOOL;
V_BOOL(pVar) = VARIANT_FALSE;
hr = S_OK;
}
if (bstrValue != NULL)
{
V_VT(pVar) = VT_BSTR;
V_BSTR(pVar) = bstrValue;
hr = S_OK;
}
return hr;
}
use V_BOOL(pVar) = VARIANT_TRUE; to create the windowless.
Hope it will help...
Thanks,
-Syed
|
|
|
|
|
Thanks. I've changed that.
However, how do I modify CreateXcpControl to not require a HWND? I've tried to simply replace all the code in AttachControl with a single call to ActivateXcpControl. And then I create the control in a CoInitialized thread and start the windows message loop. However, when I call OleDraw all i get is blackness. Any ideas?
modified on Sunday, January 23, 2011 5:46 AM
|
|
|
|
|
Cheer, it really good article, when you will upload the code where we can send data from SilverLight to C++?
I really need it
Regards
|
|
|
|
|
|
Unfortunately the Invoke only seems to work within the context of the UI thread. Which makes its use rather limited. Has anyone come up with a better way to do this?
|
|
|
|
|
Thats true, it uses only UI thread...
|
|
|
|
|
Hello.
We have a complete IXcpControl implementation from "First Floor" (http://firstfloorsoftware.com/blog/hosting-silverlight-outside-the-browser-sourcecode/). There are no implemetation of two way communication, like you do. Did you have a C# port of your code? (Sorry for my english )
|
|
|
|
|
Thank you very much for your nice project.
can you tell me how I can invoke c++ method from silverlight?
any advice is welcome.
|
|
|
|
|
You need to do couple of things for callig C++ method from silverlight.
1- Create a class which implements an IDispatch Interface and your own interface e.g. IMyScriptableObject (which defines atleast one method in it).
interface IMyScriptableObject : IDispatch
{
void MethodInC++();
}
class CMyScriptableObject : IMyScriptableObject
{
//implement IDispatch
//implement IMyScriptableObject
};
2- instantiate CMyScriptableObject via new operator and pass its address to Silverlight (using C++ to silverlight communication). On Silverlight side, you can receive CMyScriptableObject into ScriptOject {ScriptObject is already defined in Silverlight}.
3- You are done!!! you using ScriptObject object, you can call MethodInC++()
Hope, it will help you out and give you an idea how to make this happen!
-Syed
|
|
|
|
|
Hi Syed,
Thank you very much for your advice.
I try to implement it as you said above. but I failed
I pass ScriptObject address as following.
CMyScriptableObject* obj=new CMyScriptableObject;
dispparams.rgvarg[0].vt = VT_INT;
dispparams.rgvarg[0].intVal = (int)obj;
and define a function at silverlight side as this
[ScriptableMember]
public string TestScriptObject(ScriptObject obj)
{
obj.Invoke("MethodInC++","ok");
}
Can you tell me where the mistake is made in the above code.
|
|
|
|
|
don't use VT_INT
use something like this...
dispparams.rgvarg[0].vt = VT_DISPATCH ;
dispparams.rgvarg[0].pdispVal = obj;
pass these params and check the return type in C++ side to make sure that function call is succesful. if return type is S_OK, its mean you are good to go! otherwise look at the exception or error info to investigate the issue.
NOTE: please write code when you are sure that silverlight control is loaded and you can see the "Communicator" object in C++ side then try to execute the above mention code.
Please let me know how it goes...
-Syed
|
|
|
|
|
Hi Syed,
I have modified the dispparams as you advised.
CMyScriptableObject* obj=new CMyScriptableObject;
dispparams.rgvarg[0].vt = VT_DISPATCH ;
dispparams.rgvarg[0].pdispVal =(IDispatch*) obj;
hr = pCommunicatorDispatch->Invoke(dispIDSetDataInTextBox, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &dispparams, &pVarResult,&pexcepinfo,NULL);
And now it returns S_OK.
I implement the IMyScriptableObject as following
// IMyScriptableObject type library's GUID
// {E1124082-5FCD-4a66-82A6-755E4D45A9FC}
DEFINE_GUID(CLSID_ScriptObject_TypeLib, 0xe1124082, 0x5fcd, 0x4a66, 0x82, 0xa6, 0x75, 0x5e, 0x4d, 0x45, 0xa9, 0xfc);
// IMyScriptableObject object's GUID
// {520F4CFD-61C6-4eed-8004-C26D514D3D19}
DEFINE_GUID(CLSID_IMyScriptableObject, 0x520f4cfd, 0x61c6, 0x4eed, 0x80, 0x4, 0xc2, 0x6d, 0x51, 0x4d, 0x3d, 0x19);
// IMyScriptableObject VTable's GUID
// {B6127C55-AC5F-4ba0-AFF6-7220C95EEF4D}
DEFINE_GUID(IID_IMyScriptableObject, 0xb6127c55, 0xac5f, 0x4ba0, 0xaf, 0xf6, 0x72, 0x20, 0xc9, 0x5e, 0xef, 0x4d);
// IMyScriptableObject's VTable
DECLARE_INTERFACE_ (IMyScriptableObject, IDispatch)
{
// IUnknown functions
STDMETHOD (QueryInterface) (REFIID, void **) PURE;
STDMETHOD_ (ULONG,AddRef) () PURE;
STDMETHOD_ (ULONG,Release) () PURE;
// IDispatch functions
STDMETHOD (GetTypeInfoCount)( UINT *) PURE;
STDMETHOD (GetTypeInfo) ( UINT, LCID, ITypeInfo **) PURE;
STDMETHOD (GetIDsOfNames) ( REFIID, LPOLESTR *, UINT, LCID, DISPID *) PURE;
STDMETHOD (Invoke) ( DISPID, REFIID, LCID, WORD, DISPPARAMS *, VARIANT *, EXCEPINFO *, UINT *) PURE;
// Extra functions
STDMETHOD (MethodInC) ( ) ;
};
DEFINE_GUID(IID_IDispatchEx, 0xa6ef9860, 0xc720, 0x11d0, 0x93, 0x37, 0x0, 0xa0, 0xc9, 0xd, 0xca, 0xa9);
class CMyScriptableObject : IMyScriptableObject
{
public:
static int m_dwRef;
static ITypeInfo* m_pTypeInfo;
static HRESULT LoadMyTypeInfo(void)
{
HRESULT hr;
ITypeLib* pTypeLib = NULL;
if (m_pTypeInfo)
return S_OK;
// Load type library.
hr = LoadRegTypeLib(CLSID_ScriptObject_TypeLib, 2, 0, LOCALE_USER_DEFAULT, &pTypeLib);
if (SUCCEEDED(hr))
{
// Get type information for interface of the object.
hr = pTypeLib->GetTypeInfoOfGuid(IID_IMyScriptableObject, &m_pTypeInfo);
pTypeLib->Release();
if (FAILED(hr))
m_pTypeInfo = NULL;
}
return hr;
}
STDMETHOD(QueryInterface)(REFIID riid, LPVOID* ppv)
{
*ppv = NULL;
if (IID_IUnknown == riid)
{
*ppv = (LPUNKNOWN)this;
AddRef();
return NOERROR;
}
else if (IID_IDispatch == riid)
{
*ppv = (IDispatch*)this;
AddRef();
return NOERROR;
}
else if (IID_IDispatchEx == riid)
{
*ppv = (IDispatch*)this;
AddRef();
return NOERROR;
}
else
{
return E_NOTIMPL;
}
}
STDMETHOD_(ULONG, AddRef)()
{
return ++m_dwRef;
}
STDMETHOD_(ULONG, Release)()
{
if (--m_dwRef == 0)
{
delete this;
return 0;
}
return m_dwRef;
}
// IDispatch method
STDMETHOD(GetTypeInfoCount)(UINT* pctinfo)
{
*pctinfo = 1;
return S_OK;
}
STDMETHOD(GetTypeInfo)(UINT iTInfo,
LCID lcid,
ITypeInfo** ppTInfo)
{
*ppTInfo = NULL;
if(iTInfo != 0)
return DISP_E_BADINDEX;
m_pTypeInfo->AddRef();
*ppTInfo = m_pTypeInfo;
return S_OK;
}
STDMETHOD(GetIDsOfNames)(REFIID riid,
LPOLESTR* rgszNames,
UINT cNames,
LCID lcid,
DISPID* rgDispId)
{
if(riid != IID_NULL)
return DISP_E_UNKNOWNINTERFACE;
if (!m_pTypeInfo)
{
register HRESULT hr;
if ((hr =LoadMyTypeInfo()))
return(hr);
}
return(DispGetIDsOfNames(m_pTypeInfo, rgszNames, cNames, rgDispId));
}
STDMETHOD(Invoke)(DISPID dispIdMember,
REFIID riid,
LCID lcid,
WORD wFlags,
DISPPARAMS __RPC_FAR *pDispParams,
VARIANT __RPC_FAR *pVarResult,
EXCEPINFO __RPC_FAR *pExcepInfo,
UINT __RPC_FAR *puArgErr)
{
return NOERROR;
}
STDMETHOD(MethodInC)()
{
MessageBox(NULL,"hello","ok",MB_OK);
return S_OK;
}
};
I put this file into your TestProject, but I don't know how to register typelib of IMyScriptableObject, so that it fails when GetIDsOfNames is invoked.
Actually I want to implement GetIDsOfNames like this,
STDMETHOD(GetIDsOfNames)(REFIID riid,
LPOLESTR* rgszNames,
UINT cNames,
LCID lcid,
DISPID* rgDispId)
{
if(riid != IID_NULL)
return DISP_E_UNKNOWNINTERFACE;
*rgDispId=1; //define MethodInC id 1
return S_OK;
}
but it doesn't work.
Do you have any advice?
Thank you again.
|
|
|
|
|
Lets start from scratch
1- Start from .idl file
Do you have something like this in your .idl file?
[
object,
uuid(FC9BCF84-19F3-4efd-BD08-85EC48488C52),
dual,
nonextensible,
helpstring("IMyScriptableObject Interface"),
pointer_default(unique)
]
interface IMyScriptableObject : IDispatch
{
[id(1), helpstring("method MethodInC++")] HRESULT MethodInC++([in] BSTR bstrMessage);
};
[
uuid(3F5A19B1-AB44-4f74-8498-069744B51A2D),
version(1.0),
helpstring("MyType Library")
]
library MyTypeLib
{
[
uuid(BE630C14-8D72-44b1-BAA4-C1E119809F03),
helpstring("CMyScriptableObject Class")
]
coclass CMyScriptableObject
{
[default] interface IMyScriptableObject;
};
};
2- CMyScriptableObject class
class CMyScriptableObject : public IMyScriptObject
{
public:
CMyScriptableObject();
virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv) ;
virtual ULONG __stdcall AddRef() ;
virtual ULONG __stdcall Release() ;
virtual HRESULT __stdcall GetTypeInfoCount(UINT* pctinfo);
virtual HRESULT __stdcall GetTypeInfo(UINT nInfo, LCID lcid, ITypeInfo** ppTypeInfo);
virtual HRESULT __stdcall GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames,
LCID lcid, DISPID* rgdispid);
virtual HRESULT __stdcall Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams,
VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr);
STDMETHOD(MethodInC++)(BSTR bstrData);
private:
HRESULT LoadTypeInfo(ITypeInfo ** ppTypeInfo, const CLSID& libid, const CLSID& iid, LCID lcid);
private:
long m_cRef;
LPTYPEINFO m_pTypeInfo;
};
CMyScriptableObject::CMyScriptableObject():m_cRef(1),
m_pTypeInfo(NULL)
{
}
HRESULT CMyScriptableObject::LoadTypeInfo( ITypeInfo ** ppTypeInfo, const CLSID& libid, const CLSID& iid, LCID lcid )
{
return NOERROR;
}
HRESULT __stdcall CMyScriptableObject::QueryInterface(const IID& iid, void** ppv)
{
if (iid == IID_IUnknown || iid == IID_IScriptObject || iid == IID_IDispatch)
{
*ppv = static_cast<IMyScriptableObject*>(this) ;
}
else
{
*ppv = NULL ;
return E_NOINTERFACE ;
}
reinterpret_cast<IUnknown*>(*ppv)->AddRef() ;
return S_OK ;
}
ULONG __stdcall CMyScriptableObject::AddRef()
{
return InterlockedIncrement(&m_cRef) ;
}
ULONG __stdcall CMyScriptableObject::Release()
{
if (InterlockedDecrement(&m_cRef) == 0)
{
delete this ;
return 0 ;
}
return m_cRef ;
}
HRESULT __stdcall CMyScriptableObject::GetTypeInfoCount(UINT* pctinfo)
{
*pctinfo = 1;
return S_OK;
}
HRESULT __stdcall CMyScriptableObject::GetTypeInfo( UINT nInfo, LCID lcid, ITypeInfo** ppTypeInfo )
{
return NOERROR;
}
HRESULT __stdcall CMyScriptableObject::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgdispid)
{
CComBSTR bstrName = *rgszNames;
if (bstrName == L"MethodInC++")
*rgdispid = 1;
return S_OK;
}
HRESULT __stdcall CMyScriptableObject::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult,
EXCEPINFO* pexcepinfo, UINT* puArgErr)
{
BSTR bstrResponse;
int nArgCount = pdispparams->cArgs;
switch(dispidMember)
{
case 1:
if(nArgCount == 1)
{
MethodInC++( pdispparams->rgvarg[0].bstrVal);
}
break;
default:
break;
}
return S_OK;
}
STDMETHODIMP CMyScriptableObject::MethodInC++(BSTR bstrData)
{
MessageBox(NULL, L"Wow! function is called", L"Wow! function is called", 0);
return S_OK;
}
Now other question is that where are you setting up your CMyScriptableObject? Make sure your silverlight control and silverlight page is loaded at that time. For safe side, create a button and write that code in its handler.
Make sure you are setting up the CMyScriptableObject successfully? your invoke call should be successfull, please check its return code.
Silverlight side:
public void BtnHandler()
{
// so is your object of ScriptObject type which was received from C++ CMyScriptObject
so.Invoke("MethodInC++", "Data passed from Silverlight side ");
}
If it doesn't work, I will upload another article for silverlight to C++ communication but most part of it is already covred in this message board.
Hope, it will help you out.
Good Luck!!!
-Syed
|
|
|
|
|
Hi Syed,
Thank you very much
Now it works!
Cheers!
|
|
|
|
|
Glad to hear that it is working!!!
Please don't forget to rate the article
-Syed
|
|
|
|
|
Hi,
With Silverlight 4, this is much easier and you don't need the web browser anymore.
Just create a COM object directly.
Cheers,
|
|
|
|
|
HI Ernest,
Can you please post a link here so I can take a look? or post a sample?
Thanks,
-Syed
|
|
|
|
|
You can have a look at Tim Heuer tutorial
http://www.silverlight.net/learn/videos/all/com-object-access-trusted-applications/
modified on Tuesday, May 25, 2010 1:52 AM
|
|
|
|
|
Thanks for sending the link but I think my approach is little different than launching the silverlight app out of browser. e.g. In my case, I am hosting the silverlight control in a C++ app and it can give us more control like loading the different assemblies synchronously and/or asynchronously through C++ host.
|
|
|
|
|