|
Ack, I didn't even notice that Michael, thanks.
Tim Smith
I'm going to patent thought. I have yet to see any prior art.
|
|
|
|
|
try:
LPTSTR a; //TCHAR* a
...
delete[] a;
|
|
|
|
|
There are some ATL templates and macros that help catch COM events.
As IDispEventSimpleImpl, SINK_ENTRY_INFO etc.
But what I must to do if I do not know all events before a program start.
For example, there are Outlook::ItemsEvent for Outlook folders. I can catch any one. But I want catch all to one function. How can I register events dynamically?
Your ideas?
================================
My home is here!
|
|
|
|
|
Brigsoft wrote:
But what I must to do if I do not know all events before a program start.
Then you're in for a rough ride. COM events are either tied to a vtable entry (non-dispinterface source) or to a DISPID (dispinterace source). In both cases, the events are tied to an interface ID. You must know in advance what you're dealing with. Of course, one could devise a more dynamic homebrew event scheme - but alas, that's not the case here. COM events are as static as stone.
Brigsoft wrote:
But I want catch all to one function.
You can do this quite easily if the source interface is a dispinterface. Simply implement the dispinterface "manually" in a separate class like this:
template <typename T, typename SourceInterface, int ID>
class CSourceInterfaceImpl {
public:
HRESULT Init() {
...
}
void Finalize() {
}
STDMETHOD(GetIDsOfNames)(...) {
}
STDMETHOD(GetTypeInfo)(...) {
}
STDMETHOD(GetTypeInfoCount)(...) {
}
STDMETHOD(Invoke)(...) {
return static_cast<T>(this)->EventInvocation(
ID,
...
);
}
};
#define ID_FOR_EVENTS_X 1
#define ID_FOR_EVENTS_Y 2
#define ID_FOR_EVENTS_Z 3
class ATL_NO_VTABLE CMyCOMClass :
public ...,
public CSourceInterfaceImpl<CMyCOMClass, ISourceX, ID_FOR_EVENTS_X>,
public CSourceInterfaceImpl<CMyCOMClass, ISourceY, ID_FOR_EVENTS_Y>,
public CSourceInterfaceImpl<CMyCOMClass, ISourceZ, ID_FOR_EVENTS_Z>
{
...
HRESULT FinalConstruct() {
HRESULT hr;
hr = CSourceInterfaceImpl<CMyCOMClass, ISourceX, ID_FOR_EVENTS_X>::Init();
hr = CSourceInterfaceImpl<CMyCOMClass, ISourceY, ID_FOR_EVENTS_Y>::Init();
hr = CSourceInterfaceImpl<CMyCOMClass, ISourceZ, ID_FOR_EVENTS_Z>::Init();
}
void FinalRelease() {
CSourceInterfaceImpl<CMyCOMClass, ISourceX, ID_FOR_EVENTS_X>::Finalize();
CSourceInterfaceImpl<CMyCOMClass, ISourceY, ID_FOR_EVENTS_Y>::Finalize();
CSourceInterfaceImpl<CMyCOMClass, ISourceZ, ID_FOR_EVENTS_Z>::Finalize();
}
HRESULT EventInvocation(int nId, ... ) {
switch(nId) {
case ID_FOR_EVENTS_X:
break;
case ID_FOR_EVENTS_Y:
break;
case ID_FOR_EVENTS_Z:
break;
default:
ATLASSERT(false);
return E_NOTIMPL;
}
}
}
Caveat Emptor; I have not tried this in a compiler. As you can see, I've left a lot of implementation details out of the picture. But I think the "theory" is sound, and it achieves what you are requesting. Filling in the missing pieces should be trivial if you look up the functions I mention in MSDN and have at least some experience with COM/IDispatch.
Did I make any sense? Did I understand your problem (at all?)
--
Gott weiß ich will kein Engel sein.
|
|
|
|
|
Suppose i have got a struct with vectors inside
<code>
struct A
{
int a;
vector<int> b;
};
vector <A> b;
Is this safe or do i have to write a copy contructor ?
"Just looking for loopholes." W. C. Fields American actor, 1880-1946, explaining why he was reading the Bible on his deathbed.
|
|
|
|
|
Perfectly safe. The compiler will automatically generate a copy constructor using what's defined by the aggregated objects.
Generally, a copy constructor is only needed if the structure contains pointers, and aliasing them would be a bad ideatm.
Imagine this scenario:
struct S {
int* p;
S() { p = new int[10]; }
~S() { delete [] p; }
};
{
S a;
S b(a);
}
In cases like this it's necessary to write your own copy constructor which either a) makes a complete copy of the array inside the object being copied from, or b) you implement some reference counting mechanism. There are gigantic semantic differences between the two cases, as you may understand. It's basically a question of "by value" or "by reference". If I chose b), any modification to let's say a.p[0] would be visible in b.p[0] .
In your example, std::vector has a well defined copy constructor. By the way, std::vector implements "by value" semantics. Anyway, the C++ compiler will always automatically generate a copy constructor if, and only if, you omit one. The generated code would look something like this:
A::A(const A& other) : a(other.a), b(other.b) { } . And how a and b are copied is defined by their copy constructors.
--
Gott weiß ich will kein Engel sein.
|
|
|
|
|
I need to show more than two views in a sdi frame window.
My code like this:
<br />
RECT rc;<br />
GetClientRect(&rc);<br />
m_hWndClient = m_view.Create(m_hWnd,rc);<br />
m_view.ShowWindow(SW_SHOW);<br />
m_view.SetFocus();<br />
m_view2.ShowWindow(SW_HIDE);<br />
It can show m_view2,but not like default view.
How can I switch views correctly??
opening view with wild mind
|
|
|
|
|
You need to call Create() on m_view2. Then, in your code that switches the view, you need to hide m_view, show m_view2, and then set m_hWndClient to m_view2.
|
|
|
|
|
To add to what TFrancis said, after setting m_hWndClient , call UpdateLayout() to make sure the view is sized correctly to fit the client area of the frame.
--Mike--
Personal stuff:: Ericahist Updated Feb 6! | Homepage
Shareware stuff:: 1ClickPicGrabber | RightClick-Encrypt
CP stuff:: CP SearchBar v2.0.2 | C++ Forum FAQ
"That probably would've sounded more commanding if I wasn't wearing my yummy sushi pajamas."
-- Buffy
|
|
|
|
|
Hi!
I am starting from ground up. I am with simple Win32 Application and I want add ATL functionality in it by fooling wizard. I planned:
1)a cpp file that has the same name as the project .
2)an ATL object map (the map can be empty, but it must be present).
3)an IDL file with the same name as the project and this file must have a Library block.
Need feedback on 2 and 3.
|
|
|
|
|
What kind of feedback?
That's how to fool the wizard. The easiest way to get examples of (2) and (3) if that's what you need is to run the VC++ AppWizard and select ATL. That will generate you the appropriate files, and you can cut and paste from there.
I've done this before, and it works.
Steve S
|
|
|
|
|
Problem with (3) is with
the entire IDL file.As it should not compile. So What modifications should I do in the project settings when I add it to the project.
And working on Ur copy paste tip. What should be the type (EXE or DLL )of ATL WORKSPACE.
Thanx for all that feedback. And feedback always for learning.
|
|
|
|
|
The IDL file can be as simple as this;
import "oaidl.idl";
import "ocidl.idl";
[
uuid(FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF),
version(1.0),
helpstring("myapp library")
]
library MyApp
{
importlib("stdole32.tlb");
importlib("stdole2.tlb");
};
You don't even need to use a different UUID, since you're not going to be registering it.
Your 'dummy' can be either, I tend to use DLL out of habit, since I write in-proc servers quite often
Steve S
|
|
|
|
|
Hello Everyone
Could you tell me How to launch a console simply from a wtl project?(Only launch)
Thank you.
-Freehawk
|
|
|
|
|
I'm using a CTreeViewCtrl in my project. It works great except for one small problem. When I change the system UI appearance to something like "Plum" so that the background color changes the tree has problems. When you expand an item in the tree sometimes the newly visible items are drawn with a white background. Is there a workaround?
I'm using Win2000, VS .Net 2002, and WTL ver 7.0. I'm kinda in the middle of the project so I figured I'd finish it before switching over to WTL 7.1. Is this something that was fixed in 7.1 and I should just switch over to it?
|
|
|
|
|
Hi
I try to insert in ATL dialog my oneself ActiveX object (
ATL composite control) but wizard not found this one(in dialog box of wizard i not see it), althought when i insert it from Add to project -> Components & Control wizar i see one into list.Why???I can't use Add to project -> Components & Control wizard because of my ATL dialog allocated in ATL project without MFC support.
Thanks
|
|
|
|
|
Looks like your activex is not registered
Edward.
|
|
|
|
|
My interface member is a BSTR Sum.
<br />
{<br />
BSTR bBuff = 0;<br />
SysAllocStringLen(bBuff,20);<br />
m_Sum = _itow((Num1 + Num2),bBuff,10);<br />
return S_OK;<br />
}
It's cilent is a WIn32 Application. I just want to TextOut this BSTR.How to do it?
One more thing if I want to pass data from ATL server to Client, how to do it using methods. I am straightaway using Interface data member for it.
|
|
|
|
|
I'm guessing this is not a UNICODE build
If this isn't an option, then you can use various methods to convert the BSTR to a regular char 'string'.
There's an atlconv.h which you can include, then have code like this;
{
USES_CONVERSION;
TCHAR* p = W2T( bBuff );
TextOut(....);
}
Alternatively if your client uses MFC you can use
CString tmp( yourBSTR );
since CString has a conversion method.
Another alternative is to use WideCharToMultiByte to do the conversion. (It's what the conversion macros in atlconv.h use, I believe...)
Steve S
|
|
|
|
|
Thanx. that was a great help to me. I am using Win32 SDK. Is development in Win32SDK has more overhead then that of MFC?
I use WIn32SDK because I am able to understand the flow, while I tried MFC at times and it seems to be overwhelming.
|
|
|
|
|
Development can take longer using raw SDK. Depends how well you 'grok' the framework. I tend to use WTL rather than MFC, unless I have a particular need for MFC specific features, such as support for OLE compound documents.
In many cases, the framework obscures your view of what's happening, until you understand it, and then it accelerates development; class = code you don't have to write.
Lots of my test apps though are pure SDK, but short.
Steve S
|
|
|
|
|
Even eaiser:
::TextOutW(...)
No need for conversion at all
Edward
|
|
|
|
|
Continuing same discussion. What I want to do is to pass a BSTR from a ATL DLL to a Client? Now since Interface method can return only HRESULT. I will store the values in a Global Variable and use it in the client. Is there in Flaw on Design? I need feedback.
By the way I didn't see anything like TextOutW in MSDN. Please help
|
|
|
|
|
My fellow poster with no name is correct that you can use TextOutW. But unfortunately, if you run your client app on Win9x or WinME, then it won't work, as that doesn't implement TextOutW, which is why I didn't suggest it (you didn't say it was NT/2K/XP/03, so I assumed it could be any.
Many API calls that take strings or characters as parameters have two versions, an ANSI version, and a UNICODE (or wide character) version. Although you use TextOut, in reality you're using either TextOutA or TextOutW, depending on whether you're compiling with _UNICODE and UNICODE defined. If you examine some of the Windows header files, you'll see definitions for both A and W functions, and then a macro which defines the base name (without A or W) as one or the other.
If you've unintentionally screwed up a parameter list to CWnd::SetWindowText, for example, the compiler will often complain about 'SetWindowTextA' or 'SetWindowTextW', rather than SetWindowText, because it's getting the definition of what the word 'SetWindowText' should be from a windows header.
Any time you see a reference to a function that ends with W or A, try looking in MSDN for the name without that trailing letter.
MEANWHILE, back to your original question;
There is a BIG flaw in your design. In the case of an in-proc ATL DLL, the global would be addressable, but that sure isn't how it's supposed to be done.
Although the method can only return an HRESULT, you can pass pointers to things in, and have the method assign values indirectly (equivalent to VB's ByRef, rather than ByVal).
An example would be:
IDL Definition:
HRESULT GetMyName( [out, retval] BSTR* pName );
HRESULT CMyObj::GetMyName( BSTR* pName)
{
if (pName == NULL)
{
return E_POINTER; // Bad address passed in...
}
*pName = SysAllocString(L"Steve Spencer");
return S_OK;
}
Client code:
BSTR t = NULL; // Empty BSTR
if (SUCCEEDED(pObj->GetMyName( &t )))
{
// woohoo! We got a result...
}
else
{
// Handle your error gracefully...
}
This works because a BSTR is a pointer; you pass in the address of the pointer, and the server (your ATL DLL) fills in the value for the pointer (hence '*pName' instead of 'pName'). You also have to mark the parameter as [out] so that the marshalling code knows how to transfer data. It's marked as [retval] so that VB programmers can use your object and treat that interface method as returning a string. (BSTR means 'BASIC String')
Hope this helps
Steve S
|
|
|
|
|
I have found the best way!!!
CComBSTR some(CString("some"));
CString some1= some;
CComBSTR and CString are exellent together!!!
================================
My Home is here!
|
|
|
|
|