|
HKEY_CLASSES_ROOT\*\Shell
nave
|
|
|
|
|
Hello everyone,
My general question is about Commercial Software Application. Are they (Commercial Software Applications) are also designed using the same Good Old Win32 APIs or they use a different approach?
Base on what I have learned on the last few days, I would say YES as long as they are supposed to use Windows Operating System. But I would like to hear your expert opinion on this, please.
Thank you,
Khoramdin
|
|
|
|
|
If they run on Windows then yes they use the same good ol' Windows APIs, directly or indirectly.
The Windows operating system is the only layer between application code and the hardware.
Even if you only use the generic C Runtime Library (CRT), the version of the CRT for Windows maps
all hardware-related stuff to Windows APIs.
Mark
|
|
|
|
|
Is there any way to deny focus to an application?
Trivial example: non-focused (MFC) application with a single button (might have to implement as label) that, when clicked, sends a Unicode string (example “\u8000”) to the application (e.g. excel, word, notepad) that does has the focus.
Behaviorally, with these 3 applications and the desired non-focused application on the desktop, the user could switch among the applications and send the string to each when the non-focused application is clicked.
|
|
|
|
|
dmailman wrote: when clicked, sends a Unicode string (example “\u8000”) to the application (e.g. excel, word, notepad) that does has the focus.
By the time the button is clicked, your app (and not Excel, Word, etc.) has focus. I recommend caching the currently active (non-self) main window every few mSec and targeting it when the user presses the button.
/ravi
|
|
|
|
|
What about handling the WM_MOUSEACTIVATE in the button's parent window and returning
MA_NOACTIVATE (I haven't tried it)?
Mark
|
|
|
|
|
Many thanks for all the suggestions...they were very clever.
I ended up using the WS_EX_NOACTIVATE style in creating the window, and that worked just fine.
thanks again.
|
|
|
|
|
Hello,
If I am not mistaken the Spy++ should be available when I have my Visual C++ window up and running.
unfortunatly, I am unable to see this options. I believe I should have it under "TOOL" option, but when I check this menu option I cannot see it!!!
Could you help out regarding SPY++?
Thank you for your time,
Khoramdin
|
|
|
|
|
Is it not in your menu group for VC ?
Christian Graus - C++ MVP
'Why don't we jump on a fad that hasn't already been widely discredited ?' - Dilbert
|
|
|
|
|
Christian,
I don't have a Menu Group which contains only two items:
1- Visual Studio Tools
2- Microsoft Visual C++ 2005 Express Edition
Khoramdin
|
|
|
|
|
Oh, you have the express edition. That's probably the problem
Christian Graus - C++ MVP
'Why don't we jump on a fad that hasn't already been widely discredited ?' - Dilbert
|
|
|
|
|
Hello,
What edition do I have to have in order to get the Spy++?
Khoramdin
|
|
|
|
|
Khoramdin wrote: What edition do I have to have in order to get the Spy++?
Any of the non-Express editions.
"Approved Workmen Are Not Ashamed" - 2 Timothy 2:15
"Judge not by the eye but by the heart." - Native American Proverb
|
|
|
|
|
The app is called spyxx.exe
You may be right I may be crazy -- Billy Joel --
Within you lies the power for good, use it!!!
|
|
|
|
|
Howdy y'all,
I am using Visual C++ 6.0 MFC. I am writing my first multi-threaded application. The worker thread calls a function in another class that uses automation to create an excel spreadsheet. If I call this function from my primary thread everything works okay, but if I call it from my secondary thread the creation of the spreadsheet fails. Any information on what is happening here would be much appreciated.
Buck
|
|
|
|
|
BuckBrown wrote: the spreadsheet fails
Please provide detailed error information
led mike
|
|
|
|
|
If I call the function from the primary thread -
void CTests::OpenWorksheet()
{
COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
// Start Excel and get the application object
if(!m_App.CreateDispatch("Excel.Application"))
{
AfxMessageBox("Couldn't start Excel and get application object.");
}
}
The call to m_App.CreateDispatch("Excel.Application")) begins to execute the following code -
BOOL COleDispatchDriver::CreateDispatch(LPCTSTR lpszProgID, COleException* pError)
{
ASSERT(m_lpDispatch == NULL);
// map prog id to CLSID
CLSID clsid;
SCODE sc = AfxGetClassIDFromString(lpszProgID, &clsid);
if (FAILED(sc))
{
if (pError != NULL)
pError->m_sc = sc;
return FALSE;
}
// create with CLSID
return CreateDispatch(clsid, pError);
}
As the function executes the values in my debug window are lpszProgID = 0x005902cc "Excel.Application", m_lpDispatch = 0x00000000, pError = 0x00000000 {COleException}, this = 0x00aa0158, &clsid = 0x0012ec4c {CLSID_Microsoft Office Excel Application}, sc = 0, and the CreateDispatch(clsid, pError) function returns a value of 1.
If I call m_App.CreateDispatch("Excel.Application") from the worker thread, the values are all the same but the call to CreateDispatch(clsid, pError) returns a value of 0.
If you want more detail, from the worker thread, the CreateDispatch(clsid, pError) function calls SCODE sc = CoCreateInstance(clsid, NULL, CLSCTX_ALL | CLSCTX_REMOTE_SERVER, IID_IUnknown, (LPLP)&lpUnknown); with values of CLSCTX_REMOTE_SERVER = 16, IID_IUnknown = {IID_IUnknown}, lpUnknown = 0x00000000, &lpUnknown = 0132fbbc. This call returns a value of -2147221008 into sc and then fails.
From the primary thread the value of lpUnknown is 0x0012ec28
From the secondary thread the value of lpUnknown is 0x0132fbbc
Other than this value everthing else is the same.
Thanks
|
|
|
|
|
BuckBrown wrote: This call returns a value of -2147221008 into sc and then fails.
Do you know that HRESULTS can be tested and represent specific errors?
Visual Studio 6 comes with a tool called "Error Lookup". Plug that number into it.
Here is a hint for you, COM must be initialized for each thread it is used in.
led mike
|
|
|
|
|
Thanks Mike,
No I didn't. First and foremost I am NOT a Windows programmer. I come from the UNIX world and everthing Microsoft seems back asswords to me. I have taught myself (with help from people like yourself) just enough MFC programming in the last couple of years to be dangerous, but it has been a real challenge because what experienced Windows programmers take for granted as kindergarten stuff is not really documented very well. I'll play with this angle for a while (it will probably take me a week) and let you know how it went.
Thanks again for getting me off the snide.
Buck
p.s. If you're wondering why a Windows hater is programming in it, it is because that was the compiler on my machine at work and it's the only one I have to develop applications with. I don't want to, I have to.
|
|
|
|
|
|
BuckBrown wrote: I am NOT a Windows programmer. I come from the UNIX world and everthing Microsoft seems back asswords to me. I have taught myself (with help from people like yourself) just enough MFC programming in the last couple of years to be dangerous, but it has been a real challenge because what experienced Windows programmers take for granted as kindergarten stuff is not really documented very well.
Ah, now that is useful information to aid in our communications! So the COM kernel of windows uses thread local storage for some of it's ?whatever? and therefore requires thread based intialization. Use the OleInitialize()[^] and matching uninitialize() to accomplish this in your thread callbacks when you want to use COM routines in a worker thread.
led mike
|
|
|
|
|
Hi,
Yes, not using the CoInitialize() function at the begining of the thread was the problem with not being able to create an Excel worksheet. Thank you all for your help. I didn't know anything at all about COM before, but now I guess I should bone up on it a little bit.
Buck
|
|
|
|
|
Did you initialize the apartment in the worker thread? You must ALWAYS call CoInitialize[Ex]() in a new thread before making ANY COM-calls...
Always take a look at the HRESULTs given by COM-functions. Then put the error code in the "Error Lookup"-tool that comes with Visual Studio (it's in the tools-menu). It can translate most common COM-errors.
Also, don't forget to call CoUninitialize() in your worker thread when it exits.
Good luck!
--
Verletzen zerfetzen zersetzen zerstören
Doch es darf nicht mir gehören
Ich muss zerstören
|
|
|
|
|
Hi,
Yes, not using the CoInitialize() function at the begining of the thread was the problem with not being able to create an Excel worksheet. Thank you all for your help. I didn't know anything at all about COM before, but now I gues I should bone up on it a little bit.
Buck
|
|
|
|
|
In addition to Joergen's reply, you have to marshal your interface into the new apartment.
Spawning a worker thread and not initializing COM by calling ::CoInitialize[Ex]() , is one of the top five mistakes when doing COM. Another one of the top five is using an interface gotten in the primary thread (apartment) without marshalling the interface. If you fail to do this you will get the RPC_E_WRONG_THREAD error.
Usually you marshal an interface by using ::CoMarshalThreadInterfaceInStream() and ::CoGetInterfaceAndReleaseStream() .
Have a look here[^].
I think that by about 95% certainty, the above is your problem.
"It's supposed to be hard, otherwise anybody could do it!" - selfquote
|
|
|
|