|
A normal window (CFrameWnd) does not pop up after it was
minimized when clicked on its icon. But it is poped up
if right clicked on the minimized icon and selected
'Restored' or 'maximized' menu.
What would have gone wrong?
|
|
|
|
|
Hi all. I'm trying to write a string class ( we want to move away from MFC as we want to develop a cross platform product ), and I am starting by deriving from the standard string class. My header looks like this:
#include <string>
using namespace std;
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CGString : public virtual string
{
public:
CGString();
virtual ~CGString();
};
My problem is, I want to do this:
CGString s;
s = "dfdsfs";
printf(s);
And it's telling me = is not defined for this input type, and that it cannot convert from CGString to char*. I'm not sure *why* I need to provide the operator= again, but that's cool. I want to know how I can make my variable return a char*, in essence to cast itself to it's data member ? I know I can use .GetBuffer() or whatever, but I don't want to, if I can avoid it.
Thanks for helping...
Christian
The content of this post is not necessarily the opinion of my yadda yadda yadda.
To understand recursion, we must first understand recursion.
|
|
|
|
|
A derived class does not inherit operator = from its base class. That's Just The Way It Istm.
As for your second part, I think you are asking about writing a conversion operator for the class, right? You could do something like this:
CGString::operator const char* ()
{
return c_str();
}
--Mike--
http://home.inreach.com/mdunn/
"Didn't I tell you? I've got a brain the size of a planet."
--Marvin the paranoid android
|
|
|
|
|
Wow - cool. Thanks, that's my thing learned for the day....
Christian
The content of this post is not necessarily the opinion of my yadda yadda yadda.
To understand recursion, we must first understand recursion.
|
|
|
|
|
Actually, think long and hard about deriving from the standard classes in most cases.
std::string doesn't have a virtual destructor, thus if someone does this:
std::string *p = new CGString;
delete p;
You're off into weird and undefined territory. Declaring your destructor virtual won't help.
What's wrong with std::string that you need to change it? And why not just write some utility functions that accept a std::string to do what changes you need?
|
|
|
|
|
Oh. I didn't realise that, I assumed that the destructor would be virtual to allow for people to expand on the standard class. An assumption I make after mainly extending MFC classes, I guess.
The idea is that we have a product now which we want to port to Mac & Linux, and so we want to replace MFC classes like CString with something that will work in any C++ environment. Specifically I want to be able to replace any instance of CString in our existing code with CGString and have it work which means adding functions that simply call existing functions that have different names to the same functionality in CString, and adding those that are missing, like MakeLower ( which we use ALL the time for name comparison on files ) and Format. I personally don't like the idea of external functions, because I want a string to remain an object that knows how to do what I want it to, not something that is subject to external code for what I consider basic functionality.
I suppose that means I need to write the whole thing from scratch then ?
Christian
The content of this post is not necessarily the opinion of my yadda yadda yadda.
To understand recursion, we must first understand recursion.
|
|
|
|
|
I take it you mean you want to create a class with the same interface as CString, which is portable.
You can mostly achieve this by using a std::string as a member of CGString class, then set up forwarding functions that call members in string, or alternatively you can use private inheritance of std::string. This will make it so that you can't assign a CGString pointer to a a std::string pointer.
However, it won't be possible to completely duplicate CStrings functionality for a variety of reasons, especially if you provide a virtual destructor.
If you look at CString, you'll also see that it doesn't provide a virtual destructor. The reason is simple:
You can cast a CString to a char* and use it as if it were an array of characters. It does this by making the array pointer the first member in the class, thus a pointer to the CString is also a pointer to it's first member. In classes that have vtables though, the pointer to the class is also the pointer to the vtable, which would not work.
This isn't exactly good behavior though, so you might just want to say "You can't do that in my CGString", which would be fine unless you have existing code which expects that.
As far as external functions go, I think you're stuck in "everything has to be an object" mentality. Look at the standard C++ library. It provides all kinds of functions called algorithms that work on generic objects. These algorithms aren't part of the objects themselves, and it's still object oriented. You don't have to make everything a member for it to be OO. This is the biggest mistake most people make when using C++, too much encapsulation.
The things you mention are easily accomplished with external functions and std::string. You want to make lower, just use:
std::string s("ThIs Is A mIxEd CaSe StRiNg");
std::transform(s.begin(), s.end(), s.begin(), std::tolower);
Format is indeed handy, but it's simple enough to create your own format function that does the same thing using sprintf.
|
|
|
|
|
>I take it you mean you want to create a class with the same interface as CString, which is portable.
Yes.
>You can mostly achieve this by using a std::string as a member of CGString class, then set up forwarding functions that call members in string,
Yes, that is what I do where possible - no point reinventing the wheel, and that was the point of inheriting string.
>or alternatively you can use private inheritance of std::string. This will make it so that you can't assign a
CGString pointer to a a std::string pointer.
Hmm... If I provide interfaces to *all* of string, then I *could* do that.... Any down side ?
>However, it won't be possible to completely duplicate CStrings functionality for a variety of reasons, especially if you provide a virtual destructor.
Actually, given that string's destructor will always be called, I removed my destructor, forgetting that I will be given one anyhow by my compiler. Some thought needed there, methinks.
>If you look at CString, you'll also see that it doesn't provide a virtual destructor. The reason is simple:
>You can cast a CString to a char* and use it as if it were an array of characters. It does this by making the array pointer the first member in the class, thus a pointer to the CString is also a pointer to it's first member. In classes that have vtables though, the pointer to the class is also the pointer to the vtable, which would not work.
So I can't cast to char* in my class for this reason then ?
>This isn't exactly good behavior though, so you might just want to say "You can't do that in my CGString", which would be fine unless you have existing code which expects that.
I doubt we have code that expects it, but this could be hairy, none of us there now were there for the early to mid stage of thge project.
>As far as external functions go, I think you're stuck in "everything has to be an object" mentality. Look at the standard C++ library. It provides all kinds of functions called algorithms that work on generic objects. These algorithms aren't part of the objects themselves, and it's still object oriented. You don't have to make everything a member for it to be OO. This is the biggest mistake most people make when using C++, too much encapsulation.
Fair enough. Although I understand what you're saying in general, surely you'd agree 'format' and 'makelower' are not terribly generic ?
>The things you mention are easily accomplished with external functions and std::string. You want to make lower, just use:
>std::string s("ThIs Is A mIxEd CaSe StRiNg");
>std::transform(s.begin(), s.end(), s.begin(), std::tolower);
I s'pose, but s.MakeLower sees to me easier to read and easier to use.
>Format is indeed handy, but it's simple enough to create your own format function that does the same thing using sprintf.
Funny you mention that, because I've done this:
CGString& CGString::Format(const char* pChar, ...)
{
if (strlen(pChar)<2)
return *this;
va_list argList;
va_start(argList, pChar);
char* pReturn = new char [400];
memset(pReturn,0,400);
sprintf(pReturn,pChar,argList);
va_end(argList);
this->assign(pReturn);
return *this;
}
as a starting point ( I wanted to get it to work *at all* before cleaning it up, for starters I need to allocate a correct size to the char * that receives the data instead of an arbitrary value ) and it compiles, runs and returns garbage in the sections of a string that is formated, but correct data for the section that was in the format string. For example:
int i = 27;
CGString g;
g.Format("test me %d",i);
would leave g equalling "test me *insert big number here". Can you see what I've done wrong ?
Thanks for all the help & advice. I admit to being far more up on MFC than standard C++ right now, which is half the reason I put my hand up for this class, to study a bit and redress the balance.
Christian
The content of this post is not necessarily the opinion of my yadda yadda yadda.
To understand recursion, we must first understand recursion.
|
|
|
|
|
Before embarking upon your journey, Grasshopper, one should always see if someone else has gone there first.
Joe O'leary has made a CString replaceable class at:
http://home.earthlink.net/~jmoleary/projects.htm
Also, I think there may be literally hundreds of them out there.
In your code, you need to pass argList by value, instead of by pointer. va_list is a typedef for a pointer to argument, you need to pass the actual arguments.
sprintf(pReturn,pChar,*argList);
|
|
|
|
|
Thanks for the link, I will study it as well as searching for some more examples.
Interestingly, dereferencing argList doesn't change the result of my code: the int is properly formatted, but the string is garbage and the float is 0.00.
Christian
The content of this post is not necessarily the opinion of my yadda yadda yadda.
To understand recursion, we must first understand recursion.
|
|
|
|
|
What you might want to do is just use a stringstream internally.
CGString& CGString::Format(const char*pFormat, ...)
{
istringstream is;
// loop on variable arguments
is << arg;
*this = is.str();
}
|
|
|
|
|
But... given that I inherit from string virtually and my class has no member data, doesn't that just mean I need to call the base destructor anyhow ? My derived class has nothing extra to destruct.
Christian
The content of this post is not necessarily the opinion of my yadda yadda yadda.
To understand recursion, we must first understand recursion.
|
|
|
|
|
Actually, your class does have member data. The vtable for the virtual destructor.
If you don't use a virtual destructor, and you have no other member data, it might work, but it's still undefined and could very well be non-portable.
|
|
|
|
|
Hi,
I used a third party ActiveX control in my program.
There is a popup menu when I right click on the control after my program start, which I don't like.
How can I disable this feature?
Anyone can help? website? newsgroup?
thanks a lot,
larry
|
|
|
|
|
the easiest way would be to talk to the providers of the 3rd party control - they may have interfaces that they use to query the host site about such things. eg the IE (Micro$oft) control talks to the host via a host provided IDocHostUIHandler interface to enable and disable the menu.
or they might implement a method for you and send you the completed control (maybe do it for nothing - if they consider useful enough)
Holy Handgrenade of Antioch instructions
|
|
|
|
|
thanks for your help,
is anyway you know to stop the right click?
i.e.
RECT rect;
if (mouse above rect)
disable right click;
thanks again,
larry
|
|
|
|
|
Does anybody know of an example or code as to how to create a desktop icon and its label. I would like to extend this to a bitmap. That is have a bitmap displayed with a label.
|
|
|
|
|
Do you want to create the icon, or just the shortcut ? Under what circumstances do you want to label the bitmap ( i.e. in Explorer ? )
Christian
The content of this post is not necessarily the opinion of my yadda yadda yadda.
To understand recursion, we must first understand recursion.
|
|
|
|
|
I would like to know how the desktop icon and its label is created, so I can display a bitmap with its own label on a view.
|
|
|
|
|
I'm writing a GUI editor which can also create buttons on the fly, and I'm trying to change the buttons' text (foreground) color. I'm having trouble adding the BS_OWNERDRAW style - I keep getting a "Debug Assertion Failed" message. Even if I 'Ignore' this message, I still don't get the WM_DRAWITEM message. How do I fix this?
Help will be greatly appreciated.
|
|
|
|
|
Does anyboby know how to add context menu to the CRichEditView? I tried to override CRichEditView::GetContextMenu(), but that did not help.
Any ideas?
Thanks in advance.
Nikolay.
|
|
|
|
|
try this
HMENU CCmView::GetContextMenu(WORD, LPOLEOBJECT, CHARRANGE* )
{
menu.DestroyMenu();
menu.LoadMenu(IDR_MENU_POPUP);
HMENU hMenu=menu.GetSubMenu(0)->GetSafeHmenu();
return hMenu;
}
design your menu as you would any other popup menu - if you are always using the same menu then you could load the menu at the view creation and delete it when the view is destroyed
Holy Handgrenade of Antioch instructions
|
|
|
|
|
How do you create a ToolBar in a Dialog Box Window????
Help me...
I tried to do this: it doesn't work..
object.Create (WS_CHILD | WS_VISIBLE,CRect(200,100,250,250),this,IDR_TOOLBAR1);
where the object is devied from a CToolBar class.
Help....
|
|
|
|
|
I took a quick look (very quick ) here at CP, but didn't see any relevant articles. Check out the CodeGuru dialogs section - there's a "toolbars and status bars" subsection with a few articles on this topic.
--Mike--
http://home.inreach.com/mdunn/
"Didn't I tell you? I've got a brain the size of a planet."
--Marvin the paranoid android
|
|
|
|
|
You can't do it - toolbars are not supported in dialogs, and need to be simulated.
Christian
The content of this post is not necessarily the opinion of my yadda yadda yadda.
To understand recursion, we must first understand recursion.
|
|
|
|
|