|
Yes, you need to add code into the Invoke methods that looks at the dispid that's passed and maps that to the method you need to call. In addition, you need to unpack the parameter values from the struct pointed at by pDispParams.
Also, that thread needs to be in a window message dispatch loop - my understanding is that COM method calls are passed from other threads and processes into your thread using windows messages.
I know you can't/don't want to use ATL and I can totally understand that...but ATL does make this sort of thing REALLY easy
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
Hi Stuart,
thanks a lot for your reply. Do you know if there will be an example about the invoke theme? I didn't know how this function will/must be called and how my functions then will be called / how I can get a message from the COM server above this invoke functions.
I know and I heared also from other people that it will be easier to work with ATL. But in this project I can't use ATL.
|
|
|
|
|
OK - the Invoke method is called when an event is raised by the server. It will tell you which method it's calling using the dispidMember parameter. The parameters to the call will be in the structure pointed at by pdispparams. You can pass back a result in pvarResult.
So, you could implement your Invoke using a switch statement and parameter transformation like this:
STDMETHODIMP CSink::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
WORD wFlags, DISPPARAMS* pDispParams,
VARIANT* pVarResult, EXCEPINFO* pExcepInfo,
UINT* puArgErr)
{
if ((riid != IID_NULL))
return E_INVALIDARG;
HRESULT hr = S_OK;
switch (dispIdMember)
{
case 1:
if (pDispParams->cArgs != 1) return E_INVALIDARG;
if (V_VT(&pDispParams->rgvarg[0]) != VT_BOOL|VT_BYREF) return E_INVALIDARG;
OnConfigurationApply(V_BOOLREF(&pDispParams->rgvarg[0]));
break;
case 2:
break;
}
return hr;
}
HTH!
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
The problem I have before is that the Invoke Function will not be called. What must I do that this function will be called from the Server when an event is raised?
I can see that an event is raised from the server because an dialog will be opended. But the invoke function will not be called.
|
|
|
|
|
Your code all looks reasonable - I presume you've set a breakpoint in your Invoke method to see if it gets called?
I'd also set breakpoints on your AddRef, QueryInterface methods and see if they get called when you call the connection point's Advise method - that's how you tell the server about your event handler.
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
I set now also some breakpoints in the AddRef and QueryInterface Methods. These methods will be called. Only the Invoke function will not be called.
Do you know what I can do to test if I did something wrong or if the COM server works correct?
|
|
|
|
|
Suddenly realised what your problem could well be.
The server could be asking for your event handler's dispinterface methods by name - in which case you would need to implement GetIDsOfNames.
Or it could be asking for your class's type-information, in order to determine what methods and associated parameters are available. I think you need to investigate (with breakpoints) whether the othe r IDispatch methods are called. If they are, then as you don't implement them, the server will (as a result) decide not to call your IDispatch::Invoke method.
All these details, and the pain of implementation, are why I use ATL - I fully accept that you can't use ATL - I sympathize with your predicament!
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
I tried it now with the breakpoints. The functions QueryInterface / AddRef and Release (IUnknown) will be called. But all the four IDispatch methods (GetTypeInfoCount / GetTypeInfo / GetIDsOfNames / Invoke) will not be called. So now if I understood you correct, I must implement (call the method) GetIDsOfNames by myself?
I tried the implementation of the method GetIDsOfNames a little bit but my application crashed down anytime. Please give me a note if I understood you correctly that the solution must be to implement this function. If so, I must search for some better examples about that and try it again.
Thanks for your help.
|
|
|
|
|
Have a look more closely at what interfaces are being asked for in QueryInterface. The fact that your IDispatch methods aren't being called means that implementing GetIDsOfNames isn't going to help - you need to work out what the server's actually trying to access on your event handler object.
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
Stuart, thanks for your help. Now it seems to work. The problem was that the Connection (Advise) must be done before I open the programm. If I do this Advise after the program start I didn't get any events.
|
|
|
|
|
Hi ,
Is there any way to update the DOM(view source ) of IE browser by using
IHTMLDocument and IHTMLElement interface. I want to change page's title,tooltip in browser before displaying it in IE browser.
Thanks
Atul
|
|
|
|
|
Hi,
I am using following imports:
//Mircorsoft Office Objects
#import \
"C:\Program Files (x86)\Common Files\Microsoft Shared\OFFICE12\mso.dll"\
rename("DocumentProperties", "DocumentPropertiesXL")\
rename("RGB", "RBGXL")
//Microsoft VBA Objects
#import \
"C:\Program Files (x86)\Common Files\Microsoft Shared\VBA\VBA6\vbe6ext.olb"
//Excel Application Objects
using namespace Office;
#import "C:\Program Files (x86)\Microsoft Office\Office12\EXCEL.EXE"\
rename("DialogBox", "DialogBoxXL") rename("RGB", "RBGXL")\
rename("DocumentProperties", "DocumentPropertiesXL")\
rename("ReplaceText", "ReplaceTextXL")\
rename("CopyFile", "CopyFileXL")\
exclude("IFont", "IPicture") no_dual_interfaces
Excel::_ApplicationPtr XL;
Excel::_WorkbookPtr book;
Excel::_WorksheetPtr sheet;
By using for loop ,able to get all workbook names.Using following code iterating through item, getting all workbook names.
book = XL->Workbooks->Item[1];
In case of worksheet, i am not getting the name of worksheet.There is no such option as workbook.
Able to point to particular sheet, but name option is not there.
sheet = XL->Workbooks->Item[1]->Sheets->Item[1];
I want to retrieve whole list of worksheets present in workbook.
Googled but I didn't get any clue.
If there is any option, please give me clue.
Thanks in advance.
Gtag.
|
|
|
|
|
gtag wrote: Able to point to particular sheet, but name option is not there
Yes it is. This code compiles and builds and runs:
Excel::_WorkbookPtr wb = xl->Workbooks->Add();
Excel::_WorksheetPtr ws = wb->Worksheets->Item[1];
if (ws)
std::cout << ws->Name << std::endl;
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
Hi Stuart,
Thanks again.
But I am not getting name its failing at getting sheets from the workbook to which I am pointing.
Main aim is to get the workbook names and worksheets names opened by the user, might be 50 workbooks or any number.
Please check the code and let me know where I am doing wrong?
//MicroSoft Office Objects
#import \
"C:\Program Files\Common Files\Microsoft Shared\OFFICE11\mso.dll" \
rename("DocumentProperties", "DocumentPropertiesXL") \
rename("RGB", "RBGXL")
//Microsoft VBA Objects
#import \
"C:\Program Files\Common Files\Microsoft Shared\VBA\VBA6\vbe6ext.olb"
using namespace Office;
//Excel Application Objects
#import "C:\Program Files\Microsoft Office\OFFICE11\EXCEL.EXE" \
rename("DialogBox", "DialogBoxXL") rename("RGB", "RBGXL") \
rename("DocumentProperties", "DocumentPropertiesXL") \
rename("ReplaceText", "ReplaceTextXL") \
rename("CopyFile", "CopyFileXL") \
exclude("IFont", "IPicture") no_dual_interfaces
using namespace std;
#include <string>
int _tmain()
{
Excel::_ApplicationPtr XL;
Excel::WorkbooksPtr book;
Excel::WorksheetsPtr sheet;
string BookName;
string SheetName;
int BookCount;
int SheetCount;
string bookArray[20];
int count;
//A try block is used to trap any errors in communication
try
{
//Initialise COM interface
CoInitialize(NULL);
HRESULT hr = XL.GetActiveObject(L"Excel.Application");
if(SUCCEEDED(hr))
{
book = XL->Workbooks;
BookCount = book->Count;
for(int i=1;i<=BookCount;i++)
{
BookName = book->Item[i]->Name;
cout<<BookName<<endl;
SheetCount = book->Item[i]->Sheets->Count;
for(int j=1;j<SheetCount;j++)
{
sheet = book->Item[i]->GetWorksheets();
if(sheet)
{
Excel::_WorksheetPtr pSheet = sheet->Item[j];
SheetName = pSheet->Name;
cout<<SheetName<<endl;
}
}
}
}
}
catch(_com_error &error)
{
//cout << "COM error " << endl;
}
}
gtag
modified on Friday, October 2, 2009 12:24 PM
|
|
|
|
|
gtag wrote: Excel::WorksheetsPtr sheet;
Should be Excel::SheetsPtr sheet;
gtag wrote: Excel::_WorksheetPtr pSheet = sheet->Item[j];
Not all sheets are worksheets. This line can raise an exception as well if, for example, you have a chart sheet. So, you should use this code:
sheet = book->Item[i]->Sheets;
if(sheet)
{
try {
Excel::_WorksheetPtr pSheet = sheet->Item[j];
SheetName = pSheet->Name;
cout<<SheetName<<endl;
}
catch (_com_error&) { cout << "Sheet " << j << " is not a worksheet\n"; }
}
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
Hi stuart,
Thanks again.
I corrected, its working perfectly.
One more help I need, I just want to know , is there any documentation on excel for programming in C++ , I have checked msdn, codeproject, there are only basic things related to excel not at events level.
If there are any, please provide me the link where I get the info. Or if you have any such stuff on excel(writing excel events etc), please let me know.
Regards,
Gtag
|
|
|
|
|
I just use the help that comes with Excel (go into the VBA IDE by pressing Alt-F11 when in Excel and you can get help on the Excel object model).
If (as you're doing) you use #import, use of the Excel object model in C++ follows on pretty straight forwardly from using it in VBA, so you might be best off prototyping in VBA first, then moving to C++ once you know what you want to do.
I don't know of any links to Excel programming in C++. What I've picked up has been a) from knowing the Excel object model (the VBA experience!), and b) knowing how to create a connection point handler (see this post of mine[^] for a complete example of an Excel event handler).
It's really not difficult given those two things.
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
Thanks, brilliant answers; why did I never think of it? Will save me a load of time with a project I'm working on.
|
|
|
|
|
Hi,
I checked your post in C/C++ related to events.
Its really helpful.
Thank you once again.
Gtag
|
|
|
|
|
Hi stuart,
I have one more issue.
My application works fine for Office 2007.
For office 2003, AfterCalculate is not triggering.
Googled, in msdn got the clue that it is new in 2007 and its not available in 2003.
If you have any idea, please let me know.
Thanks in advance.
Regards,
gtag
|
|
|
|
|
Hi All,
I have a little tricky question for you all. Maybe (I hope so) someone can help me with my problem.
I work in Visual Studio 2005 with an C++ project. This project does not support ATL + MFC and it should not be changed, if it’s possible. Now I should call an function / get an information out of an COM (.exe) server that is still running.
Below you can see the code that was created by the MIDL Compiler / by the OLE/COM Object Viewer from my test_programm.exe(COM server).
In the code of the Test.idl file you can see the following:
dispinterface ICWOLEEvents {
properties:
methods:
[id(0x00000001)]
void OnConfigurationApply([in, out] VARIANT_BOOL* pAccept);
[id(0x00000002)]
void OnShowMessageDlg(
[in] IMsgDlg* pIMsg,
[out, retval] VARIANT_BOOL* Result);
};
The problem now I have is that I must call / work with the OnConfigurationApply and the OnShowMessageDlg functions in my C++ project. I’ve implemented the three (Test_h.h / Test_i.c / Test.idl) files in my project and I could recompile it without any error messages.
Now my questions are:
- How can I work with these two functions(OnConfigurationApply and the OnShowMessageDlg) in my C++ project?
- Is there anywhere an simple/complete c++ example project?
- Can someone explain me how I must start to work / get some information with these functions?
I’ve posted a few weeks a similar question. But now after my holiday I will post this question a little bit more detailed again.
Let me know if you need any more information about these files.
MANY MANY thanks for any hints.
Juergen
Test_h.h
.
.
.
MIDL_INTERFACE("6775FB91-B5BE-11D6-A996-0050BA24C7B9")
ICWOLEEvents : public IDispatch
{
};
.
.
.
Test_i.c
//Created with the MIDL Compiler
.
.
.
MIDL_DEFINE_GUID(IID, IID_ICWOLE2,0xF560F761,0x2948,0x11D7,0xA9,0xBF,0x00,0x50,0xBA,0x24,0xC7,0xB9);
MIDL_DEFINE_GUID(CLSID, CLSID_CWOLEv2,0xF560F763,0x2948,0x11D7,0xA9,0xBF,0x00,0x50,0xBA,0x24,0xC7,0xB9);
.
.
.
Test.idl
// Generated .IDL file (by the OLE/COM Object Viewer)
//
// typelib filename: test_programm.exe
[
uuid(90B4344B-90CD-4527-BC00-4F4D45C793D6),
version(2.13),
helpstring("CW CWOLE")
]
library CW_CWOLE
{
importlib("stdole2.tlb");
interface ICWOLE2;
dispinterface ICWOLEEvents;
.
.
.
.
.
[
uuid(6775FB91-B5BE-11D6-A996-0050BA24C7B9),
version(1.1),
helpstring("Event dispatch interface for CW CWOLE")
]
dispinterface ICWOLEEvents {
properties:
methods:
[id(0x00000001)]
void OnConfigurationApply([in, out] VARIANT_BOOL* pAccept);
[id(0x00000002)]
void OnShowMessageDlg(
[in] IMsgDlg* pIMsg,
[out, retval] VARIANT_BOOL* Result);
};
typedef [uuid(5CBBA151-1C47-4D6C-B14C-C527E333F812), version(1.2)]
enum {
ECS_DEFAULT = 0,
ECS_FRONT = 1,
ECS_LEFT = 2,
ECS_RIGHT = 3,
ECS_LEFTUP = 4,
ECS_RIGHTUP = 5,
ECS_TOP = 6,
ECS_BACK = 7,
ECS_BACKLEFTUP = 8,
ECS_BACKRIGHTUP = 9,
ECS_BOTTOM = 10
} ECamSetup;
typedef [uuid(9545E3CA-6401-4418-A040-DA3A89E2C792), version(1.3)]
enum {
EPM_PERSP = 0,
EPM_ORTHO = 1,
EPM_2D = 2
} EProjectionMode;
[
uuid(F560F763-2948-11D7-A9BF-0050BA24C7B9),
version(2.13),
helpstring("CWOLE2")
]
coclass CWOLEv2 {
[default] interface ICWOLE2;
[default, source] dispinterface ICWOLEEvents;
};
|
|
|
|
|
Is nobody out there who can help me? A link to a complete tutorial or anything else?
|
|
|
|
|
To implement a connection point handler (for that is what you need to do), you need to implement a COM object that can receive those events. This CodeProject article[^] seems to explain it quite nicely without using ATL or MFC.
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
Hi - thanks in advance for any enlightenment you can provide!!
I have a basic C# app running on XP SP2, using the Media Player 11 SDK download. Code looks like the following...
- The PROBLEM is that this runs OK for a WMA audio file, but throws for a WMV file on the line
drm.GetDRMProperty( strWMDRM_ActionAllowed_Playback,... with HRESULT 0xC00D002B, which is NS_E_INVALID_REQUEST
- so the QUESTIONs:
1) The IsDRM attribute that I can query on the WMA, which I found in the SDK drmexternals.h, Why is this not anywhere
in the SDK sample code, or elsewhere in the SDK includes? It is not documented in Microsoft's media attributes lists either.
2) Where can I get better info regarding audio vs video file attribute and DRM querying in C++ or C#?
3) How can I query WMV for playability and protection, as I have working for WMA?
code....
<pre>
// File attributes to be queried
public string strATTR_IsProtected = "Is_Protected";
// DRM properties to be queried
// This works for wma, but not wmv?? Do not see this in the DRM attribute list in Help.
public string strWMDRM_IsDRM = "IsDRM";
public string strWMDRM_ActionAllowed_Playback = "ActionAllowed.Play";
public string strWMDRM_DRMHeader_LicenseAcqURL = "DRMHeader.LAINFO";
private void OnPickAudioFileToPlay(object sender, EventArgs e)
{
OpenFileDialog openFileDlg = new OpenFileDialog();
openFileDlg.InitialDirectory = "c:\\";
openFileDlg.Filter = "WMA files (*.wma)|*.wma|MP3 files (*.mp3)|*.mp3|All files (*.*)|*.*";
openFileDlg.FilterIndex = 0;
openFileDlg.RestoreDirectory = true;
checkBoxFileProtected.Checked = false;
DialogResult dr = openFileDlg.ShowDialog();
if (DialogResult.OK == dr)
{
string file = openFileDlg.FileName;
// Get properties
// from wmsdkidl.h
// static const WCHAR g_wszWMProtected[] =L"Is_Protected";
IWMMetadataEditor editor;
IWMHeaderInfo3 hi3;
IWMDRMEditor drm;
bool bLocked = false;
uint iRes;
try
{
iRes = WMFSDKFunctions.WMCreateEditor(out editor);
bool bProtected = false;
string strDistributedBy = null;
editor.Open(file);
hi3 = (IWMHeaderInfo3)editor;
ushort wAttribValueLen = 4;
byte[] pbAttribValue = new Byte[wAttribValueLen];
WMT_ATTR_DATATYPE wAttribType;
ushort pwStreamNum = 0;
iRes = hi3.GetAttributeByName(
ref pwStreamNum,
strATTR_IsProtected,
out wAttribType,
pbAttribValue,
ref wAttribValueLen);
bProtected = BitConverter.ToBoolean(pbAttribValue, 0);
drm = (IWMDRMEditor)editor;
iRes = drm.GetDRMProperty(
strWMDRM_ActionAllowed_Playback,
out wAttribType,
pbAttribValue,
ref wAttribValueLen);
bLocked = (!BitConverter.ToBoolean(pbAttribValue, 0));
checkBoxFileProtected.Checked = bProtected;
checkBoxFileLocked.Checked = bLocked;
if (bLocked)
{
pbAttribValue = null;
iRes = drm.GetDRMProperty(
strWMDRM_DRMHeader_LicenseAcqURL,
out wAttribType,
pbAttribValue,
ref wAttribValueLen);
pbAttribValue = new byte[wAttribValueLen];
iRes = drm.GetDRMProperty(
strWMDRM_DRMHeader_LicenseAcqURL,
out wAttribType,
pbAttribValue,
ref wAttribValueLen);
if (2 < wAttribValueLen)
{
if ((0xFE == Convert.ToInt16(pbAttribValue[0])) &&
(0xFF == Convert.ToInt16(pbAttribValue[1])))
{
// UTF-16LE BOM+
if (4 <= wAttribValueLen)
{
for (int i = 0; i < pbAttribValue.Length - 2; i += 2)
{
strDistributedBy += Convert.ToString(BitConverter.ToChar(pbAttribValue, i));
}
}
}
else if ((0xFF == Convert.ToInt16(pbAttribValue[0])) &&
(0xFE == Convert.ToInt16(pbAttribValue[1])))
{
// UTF-16BE BOM+
if (4 <= wAttribValueLen)
{
for (int i = 0; i < pbAttribValue.Length - 2; i += 2)
{
strDistributedBy += Convert.ToString(BitConverter.ToChar(pbAttribValue, i));
}
}
}
else
{
for (int i = 0; i < pbAttribValue.Length - 2; i += 2)
{
strDistributedBy += Convert.ToString(BitConverter.ToChar(pbAttribValue, i));
}
}
}
}
textBoxDistributedBy.Text = strDistributedBy;
}
catch( System.Runtime.InteropServices.COMException ex)
{
Console.WriteLine( ex.Message );
return;
}
// Play file...
if (! bLocked)
{
textPlayAudioFile.Text = file;
axWindowsMediaPlayer1.URL = file;
}
}
} // END pick file to play
<\pre>
|
|
|
|
|
Hi,
I am trying to retrieve a shortcut's arguments but when I do so, I get some strange random/chinese symbols.
I've checked multiple times the code and I can't see any reason why this is happening.
I also use the IShellLinkW GetPath, but I have no problem with it.
here is the code I have :
[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct WIN32_FIND_DATAW
{
public int dwFileAttributes;
public FILETIME ftCreationTime;
public FILETIME ftLastAccessTime;
public FILETIME ftLastWriteTime;
public int nFileSizeHigh;
public int nFileSizeLow;
public int dwReserved0;
public int dwReserved1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string cFileName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
public string cAlternateFileName;
}
[ComImportAttribute()]
[GuidAttribute("000214F9-0000-0000-C000-000000000046")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
public interface IShellLinkW
{
void GetPath([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile,
int cchMaxPath,
out WIN32_FIND_DATAW pfd,
uint fFlags);
void GetArguments([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs,
int cchMaxPath);
}
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
Guid("0000010B-0000-0000- C000-000000000046")]
public interface IPersistFile
{
[PreserveSig]
void IsDirty();
void GetClassID(out Guid pClassID);
void Load([MarshalAs(UnmanagedType.LPWStr)] string pszFileName, uint dwMode);
}
[ComImport(), Guid("00021401-0000-0000-C000-000000000046")]
public class ShellLink
{
}
public class ShortcutTargetInfo
{
internal static string getArguments(string shortcutPath)
{
IShellLinkW linkW = (IShellLinkW)new ShellLink();
((IPersistFile)linkW).Load(shortcutPath, 0);
StringBuilder sb = new StringBuilder(260);
linkW.GetArguments(sb, sb.MaxCapacity);
Marshal.ReleaseComObject(linkW);
linkW = null;
return sb.ToString();
}
}
can anyone help me find the cause of this strange behavior.
|
|
|
|
|