|
Anonymous wrote:
I would prefer a vector of real objects, if possible.
it's probably "failing" because the CBitmap destructor is being called. objects in vectors may be copied and destroyed many times as a result of adding, resizing, sorting, etc.. this is simply the way they work. so, your CBitmaps are being copied and destroyed (which releases the bitmap data) simply as a rsult of adding them to the vector.
that's why you need to use pointers to objects in vectors, if the objects have any kind of memory management or external resources.
-c
Alcohol is the anesthesia by which we endure the operation of life.
-- George Bernard Shaw
|
|
|
|
|
Thx for your help!
Chris Losinger wrote:
it's probably "failing" because the CBitmap destructor is being called.
I dont think so, ctor/dtor are empty:
_AFXWIN_INLINE CBitmap::CBitmap() { }<br />
_AFXWIN_INLINE CBitmap::~CBitmap() { }<br />
Im still suprised, a copy ctor would copy the data to another object.... so adding, resizing shouldn't be a problem. prolly not efficient, but I wonder why it has to fail with CBitmap.
Could it be that CBitmap is bad designed (missing ctor)? From the source it looks like a simple wrapper for a HBITMAP , I'm not that good in C++ and templates. I dont get why a CBitmap could not work with STL containers.
|
|
|
|
|
Anonymous wrote:
I dont think so, ctor/dtor are empty
CBitmap is derived from CGDIObject, which has a virtual destructor. that destructor looks like this:
_AFXWIN_INLINE CGdiObject::~CGdiObject()
{ DeleteObject(); }
so every time a CBitmap goes out of scope (which happens a lot when adding to a vector) it deletes the object it holds.
in general, anything that holds onto external resources (GDI objects, other objects, heap memory, etc) and that deletes them in the destructor needs special care when used in STL containers.
-c
Alcohol is the anesthesia by which we endure the operation of life.
-- George Bernard Shaw
|
|
|
|
|
Chris Losinger wrote:
_AFXWIN_INLINE CGdiObject::~CGdiObject() { DeleteObject(); }
oh thx!
so every time a CBitmap goes out of scope (which happens a lot when adding to a vector) it deletes the object it holds.
You can use reserve() for a vector. So the amount of copy ctors and assignments is very less (as long as the container does not need to shrink or relocated). Advantage, vectors are very fast to iterate, especially when holding real objects (extra indirection from pointers makes more cache breaks).
That's why I wanted to use a vector of CBitmap (actually it's a structure with a CBitmap). Also I wanted to get rid of manual cleanup code (delete *CBitmap).
Hmmm
|
|
|
|
|
Anonymous wrote:
You can use reserve() for a vector.
sure, but that won't fix the problem of CBitmaps deleting their contents.
you really need to use a CBitmap* (or a CBitmap* wrapped in an auto_ptr) if you're going to put it in any kind of container.
-c
Alcohol is the anesthesia by which we endure the operation of life.
-- George Bernard Shaw
|
|
|
|
|
Chris Losinger wrote:
sure, but that won't fix the problem of CBitmaps deleting their contents.
yes, and thanks for pointing this out.
May I ask what I don't understand:
Why is there no copy ctor in CBitmap?
A copy ctor would normaly copy the CBitmap object to another object
before the dtor is called. You can visualize this:
#include <stdio.h>
#include <vector>
class testme
{
public:
testme() {
value = 0;
printf("testme ctor (%d,0x%X)\n", value, (unsigned int) this);
}
testme(int t) {
value = t;
printf("testme ctor (%d,0x%X)\n", value, (unsigned int) this);
}
testme(const testme& ref) {
value = ref.value;
printf("testme copy ctor (%d,0x%X <- 0x%X)\n", value, (unsigned int) this, (unsigned int) &ref);
}
~testme() {
printf("testme dtor (%d, 0x%X)\n", value, (unsigned int) this);
}
testme& operator= (const testme &ref) {
value = ref.value;
printf("testme assigning %d,0x%X <- 0x%X\n", value, (unsigned int) this, (unsigned int) &ref);
return *this;
}
private:
int value;
};
int main()
{
std::vector<testme> v;
v.reserve(3);
testme test1(1);
testme test2(2);
testme test3(3);
printf("push_back\n");
v.push_back(test1);
v.push_back(test2);
v.push_back(test3);
printf("erase first\n");
v.erase(v.begin());
v.clear();
}
Output from above:
testme ctor (1,0xBFFFF55C)
testme ctor (2,0xBFFFF558)
testme ctor (3,0xBFFFF554)
push_back
testme copy ctor (1,0x804C340 <- 0xBFFFF55C)
testme copy ctor (2,0x804C344 <- 0xBFFFF558)
testme copy ctor (3,0x804C348 <- 0xBFFFF554)
erase first
testme assigning 2,0x804C340 <- 0x804C344
testme assigning 3,0x804C344 <- 0x804C348
testme dtor (3, 0x804C348)
testme dtor (2, 0x804C340)
testme dtor (3, 0x804C344)
testme dtor (3, 0xBFFFF554)
testme dtor (2, 0xBFFFF558)
testme dtor (1, 0xBFFFF55C)
|
|
|
|
|
Anonymous wrote:
Why is there no copy ctor in CBitmap?
i'm not actually sure, but speculation is fun. maybe it was to avoid the confusion of "who owns the HBITMAP now??". maybe it's just an oversight - i think CBitmap predate MS's STL awareness, so maybe they never thought there'd be a need.
Alcohol is the anesthesia by which we endure the operation of life.
-- George Bernard Shaw
|
|
|
|
|
Chris Losinger wrote:
who owns the HBITMAP now??
Hmm yes.... *thinking*
Question: Can I make a new HBITMAP from an existing HBITMAP, not just a copy of the handle? A real new HBITMAP so that the content (loaded image) is really duplicated? Perhaps I can use CreateBitmapIndirect(&m_hObject), but I'm not very good in Win32.
If it's possible I could theoretically derive a class from CBitmap, add a copy ctor and make STL containers happy.
Thanks again for your help.
|
|
|
|
|
Anonymous wrote:
Can I make a new HBITMAP from an existing HBITMAP, not just a copy of the handle?
yes, but it involves creating a new blank CBitmap a memory DC and a BitBlt - in other words, you have to draw the source onto the output. that's a pretty expensive operation, just to please STL.
take a look at auto_ptr. it will handle reference counting for you, and delete the contained object when there are no more references to it.
-c
Alcohol is the anesthesia by which we endure the operation of life.
-- George Bernard Shaw
|
|
|
|
|
thanks a lot for your patience! you convinced me.
PS: What I found on Google, short resume from our thread:
http://groups.google.com/groups?q=copy+constructor&hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=6i70hv%24iav%242%40news.LF.net&rnum=2
|
|
|
|
|
|
thx for reminding this!
e.g from 'Effective STL' Item 8: Never create containers of auto_ptrs
|
|
|
|
|
frankly, i never use auto_ptr at all, anywhere. i would just use a vector of CBitmap*s.
so, Anonymous, sorry about the bad auto_ptr advice - but i was trying to get you to use CBitmap * !
-c
Alcohol is the anesthesia by which we endure the operation of life.
-- George Bernard Shaw
|
|
|
|
|
Agreed, CBitmap*s is the way to go in this specific case.
I recently tried to use the MS auto_ptr and failed miserably because it doesn't implement reset(). Instead I used boost::scoped_ptr to very good effect. I plan to use it more in the future. Worth a look.
Neville Franks, Author of ED for Windows. www.getsoft.com
|
|
|
|
|
No, thanks for your help! I didn't like auto_ptr in the past and I will go back to my old code with CBitmap*
|
|
|
|
|
Probably the problem comes from HBITMAP , which is a handle and can't be simply "copied". If you simply copy the value of the HBITMAP , you would create a reference... which would become invalid if the original HBITMAP fades away.
I guess a CBitmap copy-ctor has to test 1. HBITMAP to be valid and 2. create a new handle by duplicating the original.
I don't know if this is possible with Win32. Perhaps not or CBitmap would already do it? Comments?
PS: Using auto_ptr of *CBitmap (rathern than CBitmap) seems to be a solution.
|
|
|
|
|
Hi,
Can anyone tell me how to make the enter key work like a tab key in a dialog box.
For instance, I have two edit controls, a Checkbox control and three command button controls and I pressing the enter key should setfocus to the next control according to the TAB order.
Is it possible to do this without using event handlers for each and every control?
Regards,
Seagull.
|
|
|
|
|
PreTranslateMessage
How low can you go ? (MS retrofuck)
|
|
|
|
|
|
Hi.
I am implemented a very simple MFC program without the powerful of ClassWizard.
I added a CListCtrl listbox. Everything works as designed except for a double-click message handler. I cannot get the program to respond when the user double-clicks the listbox. I have tried different messages, but all failed.
I would like to know, What message do you handler for double-click (left mouse button) on a CListCtrl that is not in a dialog box and was not implemented using ClassWizard.
Thanks,
Kuphryn
|
|
|
|
|
Your dialog box receives the LBN_DBLCLK notification message when you double-click. You can add a command handler ON_COMMAND(LBN_DBLCLK, ...) in your parent window.
How low can you go ? (MS retrofuck)
|
|
|
|
|
Okay. Thanks.
The program ignores all solutions yet. There is something weird going on here. I try adding a hander for LBN_DBLCLK and it only works outside of the CListCtrl box. I believe the program ignores everything inside of the list box.
Kuphryn
|
|
|
|
|
kuphryn wrote:
I believe the program ignores everything inside of the list box.
The notification is sent TO THE PARENT WINDOW, that's by design.
Otherwise, you need to derive your own class, and tweak things a bit (many CP articles are here to help your way out).
How low can you go ? (MS retrofuck)
|
|
|
|
|
You're confusing the list box and list control. CListCtrl is the latter, and sends an NM_DBLCLK message to its parent when the control is double-clicked.
--Mike--
"I'd rather you just give me a fish today, because even if you teach me how to fish, I won't do it. I'm lazy." -- Nish
Just released - 1ClickPicGrabber - Grab & organize pictures from your favorite web pages, with 1 click!
My really out-of-date homepage
Sonork-100.19012 Acid_Helm
|
|
|
|
|
Okay.
NM_DBLCLK does not work either.
I tested ON_NOTIFY and ON_NOTIFY_REFLECT using NM_DBLCLK and LBN_DBLCLK.
Kuphryn
|
|
|
|