|
I've created a Connection Page (in the Data Source Object of my OLE DB Provider) to be displayed by the Data Link core component.
Now I'm trying to add a tab control on the page using CreateWindow with the WC_TABCONTROL class (being registered through InitCommonControlsEx(...).
But I can't get the Instance Handle needed by CreateWindow,
because
hInst = (HINSTANCE)::GetWindowLong(hwndParent, GWL_HINSTANCE);
always returns 0x0000000.
(I've received the hwndParent through the IPropertyPage::Activate Method, that's being called by the Data Link core component)
How can I get that Instance Handle? Or is there another way of using a tab control on my property page?
|
|
|
|
|
We recently upgraded to Windows 2000 and I am having a little trouble with DCOM. I have an application which runs on one of my workstations as a server to applications on another workstation and a colleague's workstation. It works fine between my two computers but when my colleague tries to invoke it he gets a permission denied message.
The server application has a user interface, so we specified it to run under the INTERACTIVE identity. Also I set up custom launch and access permissions so that my colleague is allowed to launch and access, and I made him an administrator on my machine for good measure. This worked fine under NT 4 but apparently it is not good enough under Win2k. What am I missing?
READIN writin rhythmetic
|
|
|
|
|
"Invalid Number of Parameters"
This isn't my best day... I get some very strange bugs...
I use MS Visual Studio .NET typelib wizard to create a class for CanvasShapes Word object. I obtain the object, then I call one simple method of it. Simple textbook thing.
And I get the error message: "Invalid Number of Parameters"! Not during compilation, but during runtime!!!
W_Shapes sh = wdoc.get_Shapes();
W_CanvasShapes csh = sh.AddCanvas(0,0,500,500, covOptional);
csh.AddLine(0,0,100,200);
Produces the error!
What is going on here?
|
|
|
|
|
Hi!
I try to do very simple thing:
- Start Word from Visual C++/MFC OLE automation
- Get Shapes object
- Use AddCurve to add Beizer curve
When I run the application, I get error message:
The specified value is out of range.
I tried to do all sorts of things, to pass different types to as COleSafeArray elements, change the value of vertices... nothing works!
When I use AddLine, everything works without a glitch.
////////////////
_Shapes sh = wdoc.GetShapes();
COleSafeArray saRet;
DWORD numElements[2];
numElements[0] = 2;
numElements[1] = 2;
short sngArray[2][2];
sngArray[0][0] = 91;
sngArray[0][1] = 92;
sngArray[1][0] = 93; //50;
sngArray[1][1] = 94; //50;
/*sngArray[2][0] = 0; //100;
sngArray[2][1] = 0;
sngArray[3][0] = 0; //300;
sngArray[3][1] = 0;*/
long index[2];
// Create a double safe array
saRet.Create(VT_R4,2,numElements);
// Fill the array with data.
for (int iRow = 0; iRow < 2; iRow++) {
for (int iCol = 0; iCol < 2; iCol++) {
index[0]=iRow;
index[1]=iCol;
float d = sngArray[iRow][iCol];
// saRet.PutElement(index, COleVariant(d));
saRet.PutElement(index, &d);
}
}
sh.AddCurve(saRet, covOptional);
/////////////////
|
|
|
|
|
PS
Alternativelly, if you have any Visual C++/MFC code that uses AddCurve and works - it would be great! I could not findy anything on either google or yahoo... depressing!
|
|
|
|
|
You should specify more points, because MSDN says: "Note that you must always specify 3n + 1 points, where n is the number of segments in the curve".
With best wishes,
Vita
|
|
|
|
|
Thanks, but that isn't a problem - when I specify either 4 or 7 points, it sitll does not work. Ie, this code fails the same way:
COleSafeArray saRet;
DWORD numElements[2];
numElements[0] = 7;
numElements[1] = 2;
short sngArray[7][2];
sngArray[0][0] = 0;
sngArray[0][1] = 0;
sngArray[1][0] = 100; //50;
sngArray[1][1] = 200; //50;
sngArray[2][0] = 0; //100;
sngArray[2][1] = 0;
sngArray[3][0] = 0; //300;
sngArray[3][1] = 0;
sngArray[4][0] = 0; //300;
sngArray[4][1] = 0;
sngArray[5][0] = 0; //300;
sngArray[5][1] = 0;
sngArray[6][0] = 0; //300;
sngArray[6][1] = 0;
long index[2];
// Create a double safe array
saRet.Create(VT_R4,2,numElements);
// Fill the array with data.
for (int iRow = 0; iRow < 7; iRow++) {
for (int iCol = 0; iCol < 2; iCol++) {
index[0]=iRow;
index[1]=iCol;
float d = sngArray[iRow][iCol];
saRet.PutElement(index, &d);
}
}
|
|
|
|
|
If the problem does not associated with the dimension of the array, hence it happens by "covOptional" in "sh.AddCurve(saRet, covOptional)". How you specify this value? COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR)?
With best wishes,
Vita
|
|
|
|
|
Yes, exactly as:
covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR)
how should I specify it otherwise?!
|
|
|
|
|
I can't beleive that I wasted so much time with this... and still I did not get it to work! What a day...
|
|
|
|
|
Hi All,
My MFC based EXE COM server have to be automatically installed end registered by Install Shield Express, but MFC based executable COM doesn't generate appropriate Register/Unregister routines.
How it's can be implemented?
Thanks, Oleg.
|
|
|
|
|
The convention for an EXE is that passing the parameter /regserver will register the server, while passing /unregserver will unregister it.
The Wizard-generated MFC code will have produced an override of CWinApp::InitInstance which creates a CCommandLineInfo which is then passed to CWinApp::ParseCommandLine . When this returns it then calls CWinApp::ProcessShellCommand .
You can hook into this by deriving your own class from CCommandLineInfo , overriding ParseParam , and performing the necessary registration steps in response to the appropriate command line. You should exit (by returning FALSE from InitInstance ) after processing a registration flag.
You can use AfxOleRegisterTypeLib to register your type library and COleObjectFactoryEx::UpdateRegistryAll to register all the known classes.
Stability. What an interesting concept. -- Chris Maunder
|
|
|
|
|
Thanks Mike,
I've found the simpliest solution.
enum eRegistration{eNothing, eRegisterServer, eUNRegisterServer};
eRegistration process_program_arguments(LPSTR m_lpCmdLine);
...
App::InitInstance()
{
...
if (cmdInfo.m_bRunEmbedded || cmdInfo.m_bRunAutomated)
return TRUE;
if (cmdInfo.m_nShellCommand == CCommandLineInfo::AppUnregister)
{
m_server.UpdateRegistry(OAT_DISPATCH_OBJECT);
COleObjectFactory::UpdateRegistryAll(FALSE);
}
else
{
m_server.UpdateRegistry(OAT_DISPATCH_OBJECT);
COleObjectFactory::UpdateRegistryAll();
}
if (!ProcessShellCommand(cmdInfo)) // Dispatch commands specified on the command line
return FALSE;
if(process_program_arguments(m_lpCmdLine))
return FALSE;
...
...
}
eRegistration process_program_arguments(LPSTR lpCmdLine)
{
char* lpProgArg = _strdup( lpCmdLine );
char seps[] = " -/"; // program arguments separators
char Register[] = "regserver";
char UNRegister[] = "unregserver";
eRegistration ret = eNothing;
char *token = strtok( lpProgArg, seps );
while( token != NULL )
{
if ( !strcmp(token,Register) )
{
ret = eRegisterServer;
}
if ( !strcmp(token,UNRegister) )
{
ret = eUNRegisterServer;
}
token = strtok( NULL, seps );
}
free( lpProgArg );
return(ret);
}
In StdAfx.cpp
#include <afxctl.h>
That's it.
Thanks for hint.
Oleg
|
|
|
|
|
hello!
I am learning the MS COM/DCOM architecture.
I ve developed a few simple client/server programs and I ve obtained always the same result: I think client cannot get the object.
I ve used C++ with Microsift Visual C++ 6.0.
To make the server I ve followed the next steps:
1- create an ATL COM AppWizard Project.
2- EXE Server.
3- New ATL object (simple object)
4- Add methods to Interface
5- Code the methods.
6- Build the project
it shows me:
Compiling resources...
Compiling...
Linking...
Performing registration
Server registration done!
..and client is something like this:
const IID IID_IHelloObj = {0x389A6DD0,0xC789,0x463F,{0x87,0xD5,0x8C,0x3A,0x51,0xDC,0xB4,0xDF}};
const CLSID CLSID_HelloObj = {0x1635DA5A,0xD02E,0x4049,{0xB9,0x21,0x07,0xE1,0x81,0x55,0xB2,0x0E}};
void main()
{
HRESULT hr;
IHelloObj *IHello;
int num; // to test the service
hr = CoInitialize(0);
if(SUCCEEDED(hr))
{
hr = CoCreateInstance(CLSID_HelloObj,
NULL, CLSCTX_INPROC_SERVER,
IID_IHelloObj,
(void**)&IHello);
if(SUCCEEDED(hr))
{
hr=IHello->GetNumber(&num);
hr=IHello->Release();
}
else
cout << "error";
}
CoUninitialize();
}
This is all what i ve done.
Must i do more things to run the service?
What can be the cause of the error?
Thanks in advance!!!
|
|
|
|
|
0. What value is in hr, and when? This will tell you more about what's going wrong.
1. Are you sure you're using the correct interface IDs and class IDs?
2. Have you tried using CLSIDFromProgID to get your clsid instead?
Steve S
|
|
|
|
|
hello,
0.
com_error error(hr) (first, construct a _com_server)
HRESULT_FACILITY(hr) returns 4
HRESULT_SEVERITY(hr) returns 1
error.ErrorMessage() returns "Class not registered"
1.
I think so ... I get the IID and the CLSID from the _i.c file in the External Dependencies of the server project.
2. No, i haven´t. I dont know how to get the ProgID (the first parameter).
I search it in some documentation and i find something like:
hr = CLSIDFromProgID(OLESTR("Project_name.Object_name"),&pClsid);
but it does not run (error.ErrorMessage() returns "class String is not valid")
3. I ve tried to initialize as MTA instead with
CoInitializeEx(NULL, COINIT_MULTITHREADED) but i dont know what header files must i include. Is CoInitializeEx supported in Visual C++ 6.0 or is a .NET function???
A lot of thanks!!
|
|
|
|
|
You initialized client as single threaded apartment. It won't work if you don't have message queue.
Try to initialize as MTA instead:
CoInitializeEx(NULL, COINIT_MULTITHREADED)
Edward
|
|
|
|
|
Hello,
Finally, i ve used the CLSIDFromProgID function (CLSIDFromProgID(OLESTR("HelloServer.HelloObj.1"),&pClsid)) but the result is the same:
"Class not registered"
I ve sawn the windows register and i think there are all the data related with the registration:
LocalServer32 - path of the EXE server (HelloServer.exe)
ProgID - project_name.object_name.method (HelloServer.HelloObj.1)
Typelib - a String {FF638 ....)
VersionIndepentProgID - HelloServer.HelloObj
Apart from this, I ve tried to initialize as MTA instead with
CoInitializeEx(NULL, COINIT_MULTITHREADED) but the builder does not find this function and i dont know what header files must i include.
thank you very much.
|
|
|
|
|
Because you have made the EXE server, you cannot use the CLSCTX_INPROC_SERVER constant in calling of the CoCreateInstance. You should use the CLSCTX_LOCAL_SERVER or better CLSCTX_SERVER instead.
With best wishes,
Vita
|
|
|
|
|
Ohh, thanks for your help!
...but now i have got another problem :
HRESULT says "interface not compatible"
i ve tried it with CoCreateInstanceEx instead CoCreateInstance but the result is the same. Could be the MIDL definition the cause of the problem?
Code is something like this:
IHelloObj *iHello; // point to teh interface remoto
// other variables ans COM inicialitation
//mutli_qi strcuture
MULTI_QI qi = {&IID_IHelloObj, NULL, S_OK};
//server info
COSERVERINFO csi;
csi.pwszName = _bstr_t("localhost");
...
hr = CoCreateInstanceEx(CLSID_HelloObj,NULL,CLSCTX_SERVER,&csi,
1,&qi);
// here hr and qi.hr are not succeeded
if(SUCCEEDED(hr) && SUCCEEDED(qi.hr))
{
// get the interface
// call to remote methods
...
A lot of thanks!!
|
|
|
|
|
Hi All,
I am new to office automation and I need to perform a simple task. Basically I have to duplicate an Ms word application.
What I do is instantiate ms word through a dialog based application using
_Application app
if(!app.CreateDispatch("word.Application"))
{
AfxMessageBox("Couldn't start Word and get Application object.");
return;
}
Now I create another instance of word
_Application newapp
and copy the old instance to the new one.
newapp = app;
But how do I make the new instance refect the changes? Like show the old word's documents and stuff.
Kind of basic question but I have been stuck for hours.
Thanks for help
Regards,
Zahid
|
|
|
|
|
You don't. At least, not by doing what you're doing. That's like saying that I've overwritten your email address in my address-book with someone else's address, why aren't you them?
You can use automation to enumerate the open documents, and then open them in the second copy, but that's about it. You can force the first instance to save all changes, and then get the second one to reload, but why?
What's so special about the first instance of Word you have that means you want another one 'just like it'...?
Steve S
|
|
|
|
|
Thanks for suggestion
So I can't do it? Thats depressing since I not only needed the documents but also what buttons like BOLD, ITALIC were pressed or was the word in Print Preview mode or normal mode etc.
Actually my actual goal is that I want to transfer the word to another machine with its state intact. I figured that if I could do it on one machine then doing it on multiple would be easy.
So there is no other method available other than saving the document in a file and reloading it??? We can't copy the object's attributes and paste them to another object somehow?
Thanks.
Regards,
Zahid
|
|
|
|
|
No you can't.
That's a qualified "no". If you're doing it for disaster recovery purposes, then it might well be worth spending the time writing a clone routine that for a given document replicates it's content, cursor position etc to another instance on a separate machine. You could query every property and set them on another instance, but it would take a very long time in two senses.
Firstly, this would introduce a noticeable delay to the user (for noticeable, read unacceptable). Secondly, it's going to take a long time to cover all the properties.
Steve S
|
|
|
|
|
i am having trouble making a shape(be it rectangle or a circle) that is clickable and draggable. im using visual c++ 6.0 help me pls. thanks
|
|
|
|
|