# STL Vector Problem

This topic is 4643 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Okay, I've used the STL vector alot and I've never had any problems until now. I can't figure out why this code isn't working. I use the debugger and when it gets the OnMouseMove() in the WM_MOUSEMOVE code block, it sets the m_bMouseHover to true (if the mouse is over it), but when it gets to WM_PAINT, its back to false.
#include "DevFuncs.h"
#include <vector>

LRESULT CALLBACK GuiInputProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam);
bool Frame();

class Widget
{
D3DXVECTOR2	m_Position;
UINT		m_nWidth, m_nHeight;
bool		m_bMouseHover;
public:
void Create(float fX, float fY, UINT nWidth, UINT nHeight)
{
m_Position		= D3DXVECTOR2(fX, fY);
m_nWidth		= nWidth;
m_nHeight		= nHeight;
m_bMouseHover	= false;
}

void Render(HDC hDC)
{
RECT Rect;
UINT nEdge = 0;
SetRect(&Rect, m_Position.x, m_Position.y, m_Position.x + m_nWidth, m_Position.y + m_nHeight);
if(m_bMouseHover)
nEdge = EDGE_SUNKEN;
else
nEdge = EDGE_RAISED;
DrawEdge(hDC, &Rect, nEdge, BF_RECT);
}

void OnMouseMove(WPARAM wParam, LPARAM lParam)
{
UINT nX = 0, nY = 0;
nX = LOWORD(lParam);
nY = HIWORD(lParam);
RECT Rect;
SetRect(&Rect, m_Position.x, m_Position.y, m_Position.x + m_nWidth, m_Position.y + m_nHeight);
if(nX > m_Position.x && nY > m_Position.y && nX < (m_Position.x + m_nWidth) && nY < (m_Position.y + m_nHeight))
m_bMouseHover = true;
else
m_bMouseHover = false;
}
};

std::vector<Widget*> g_Controls;

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
Widget* Ctrl1 = new Widget;
Ctrl1->Create(10, 10, 25, 25);
g_Controls.push_back(Ctrl1);

Widget* Ctrl2 = new Widget;
Ctrl2->Create(45, 35, 35, 30);
g_Controls.push_back(Ctrl2);

SetUpSystem(GuiInputProc);
StartLoop(Frame);
ShutDownSystem();
delete Ctrl2;
delete Ctrl1;
return 0;
}

bool Frame()
{
return true;
}

LRESULT CALLBACK GuiInputProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
switch(nMsg)
{
case WM_DESTROY:
case WM_CLOSE:
{
PostQuitMessage(0);
return 0;
}

case WM_PAINT:
{
PAINTSTRUCT Paint;
BeginPaint(hWnd, &Paint);

for(UINT nIndex = 0; nIndex < g_Controls.size(); ++nIndex)
{
Widget* pCtrl = g_Controls.at(nIndex);
pCtrl->Render(Paint.hdc);
}
EndPaint(hWnd, &Paint);
return 0;
}

case WM_MOUSEMOVE:
{
for(UINT nIndex = 0; nIndex < g_Controls.size(); ++nIndex)
{
Widget* pCtrl = g_Controls.at(nIndex);
pCtrl->OnMouseMove(wParam, lParam);
}
return 0;
}
}
return DefWindowProc(hWnd, nMsg, wParam, lParam);
}


Edit: I've also tried an iterator:
std::vector<Widget*>::iterator pItor = g_Controls.begin();
while(pItor != g_Controls.end())
{
Widget* pCtrl = ((Widget*)pItor);
pCtrl->Function();
++pItor;
}


But with the iterator it never even shows up (m_nWidth and m_nHeight are never assigned the values that they should be). The code in OnMouseMove() works fine (it sets it to true when I'm above it, and false when I'm not), but for some reason it doesn't seem to be keeping the value. Edit: With the current setup, all of the values are good (i.e. the width and height are correct), but the changes are only temporary. Thanks [Edited by - Programmer16 on June 9, 2005 3:03:21 PM]

##### Share on other sites
You have a vector of pointers. The elements will be stored as is -- not copies. But after insertion you delete the pointers. Hence, the pointers in the vector are invalid.

int* p = new int;std::vector v<int*>;v.push_back( p );delete p;// v[0] is now a pointer to invalid memory

Greetz,

Illco

##### Share on other sites
actually he's doing the delete at the end of main, before shutdown. that's fine.

##### Share on other sites
Quote:
 Original post by IllcoYou have a vector of pointers. The elements will be stored as is -- not copies. But after insertion you delete the pointers. Hence, the pointers in the vector are invalid.int* p = new int;std::vector v;v.push_back( p );delete p;// v[0] is now a pointer to invalid memoryGreetz, Illco

I delete them at the end of the program.
SetUpSystem() creates the window (and any other stuff like DirectX and such).
StartLoop() starts the message (using PeekMessage()).
ShutDownSystem() destroys the extra systems (like DirectX).

Edit: oops, beat to it.

##### Share on other sites
Ah, true good point. But this might be it: in a switch statement each case should be ended by break. Now for every message all cases get executed. Also, for messages your application handles you should return 0L from the WindowProc, instead of returning DefWindowProc.

Greetz,

Illco

##### Share on other sites
Quote:
 Original post by IllcoAh, true good point. But this might be it: in a switch statement each case should be ended by break. Now for every message all cases get executed. Also, for messages your application handles you should return 0L from the WindowProc, instead of returning DefWindowProc.Greetz, Illco

True, but 'return 0;' will work fine since it exits the function (with the window procedure you're supposed to return 0 if you handle the message).

I did double check and only the message's case is getting executed.

I should return 0L? I've always been told to return DefWindowProc() (and I've always seen it done this way). What about WM_NCCREATE? If I return 0L, won't the window not get created?

##### Share on other sites
Quote:
 Original post by IllcoAh, true good point. But this might be it: in a switch statement each case should be ended by break. Now for every message all cases get executed.
His return statements take care of that already.

I honestly can't find any problem with it, and I stared at it kinda hard. My best guess is that between OnMouseMove() getting called and m_bMouseHover getting set to true, and Render() getting called, OnMouseMove() gets called again, and sets m_bMouseHover back to false. But if he's doing breakpoints and watching everything, I don't see how that would happen.

##### Share on other sites
God, I need some serious spectacles. Sorry for bothering everyone; I give up.

##### Share on other sites
Okay, I am really sorry for bothing everybody. Its seems that there isn't anything wrong with my STL (as far as I know). I've never really used Win32 for graphics and I guess I'm only getting WM_PAINT message once. Does anybody know how I fix this?

Again, I'm really sorry!

##### Share on other sites
i know you have already found the problem but i just want to mention something

Quote:
 Original post by Programmer16Widget* pCtrl = ((Widget*)pItor);

This is not wright, setting a side the fact that C-style casts are bad for [grin], iterators are typically are user-defined types even if they really turn out to be plain pointers (rarely the case) you shouldn't make that assumption that they are. Also if you're imp's vector's iterators where plain pointers in this case it would have most likely been a "pointer to pointer to Widget" not a pointer to widget.

Normally if you wanted to work with the actual value instead of directly with an iterator you dereference the iterator and it returns (constant) reference to the element, i.e:

const foo& foo_ref = *my_const_itr;

Also prefer using the generic algorithms over explicit loop code on containers, in this case you could do:

#include <algorithm>  // for_each#include <functional> // mem_fun//...std::for_each(g_Controls.begin(), g_Controls.end(),               std::mem_fun(&Widget::Render));

##### Share on other sites
Quote:
Original post by snk_kid
i know you have already found the problem but i just want to mention something

Quote:
 Original post by Programmer16Widget* pCtrl = ((Widget*)pItor);

This is not wright, setting a side the fact that C-style casts are bad for [grin]

Indeed, this should be done like so:
Widget* pCtrl = &*pItor;

Widget** ppCtrl = &*pItor;
or:
Widget&* pCtrl = *pItor;
or:
Widget* pCtrl = *pItor;

Type and const-safe without any casts too!!! :-).

[Edited by - MaulingMonkey on June 9, 2005 5:07:32 PM]

##### Share on other sites
I thought I was doing that wrong, but it seems to work fine (I'm still going to change it, because I know that just because something works once doesn't mean it always will). Also, I wanted to use for_each(), but I didn't know what header it was in.

Edit: I can't get for_each() to work (I think its because I need to pass an HDC to it Render()).

Thanks guys!

##### Share on other sites
Quote:
 Original post by MaulingMonkeyIndeed, this should be done like so:Widget* pCtrl = &*pItor;

Ah but he has a vector of pointer to Widget [wink]

either:

Widget* pCtrl = *pItor;

or if he wants to actually modify the original value stored in the vec.

Widget*& pCtrl = *pItor;

Quote:
 Original post by Programmer16I didn't know what header it was in.

Handy reference here even if its not 100% correct.

##### Share on other sites
Quote:
 Original post by Programmer16Okay, I am really sorry for bothing everybody. Its seems that there isn't anything wrong with my STL (as far as I know). I've never really used Win32 for graphics and I guess I'm only getting WM_PAINT message once. Does anybody know how I fix this?

I believe the typical method is to use some form of a timer or loop to continually tell Windows to repaint your window (as in send you a WM_PAINT message), by using either UpdateWindow() or InvalidateRect().

An easy way to set up a timer would be with SetTimer(). This will send a WM_TIMER message to your window at the (approximately) appropriate times, at which point you'd call one of those two functions above. It's not the most accurate thing in the world time-wise, but it's good to get the basic functionality working. A better timing mechanism can be added later.

And as a couple of side notes, I can't believe I missed that iterator/pointer thingy, and I don't accept your apology for asking questions when the problem was elsewhere. You shouldn't be apologizing to begin with. [smile]

##### Share on other sites
Quote:
 Original post by Programmer16Edit: I can't get for_each() to work (I think its because I need to pass an HDC to it Render()).

Sorry only glanced at the code before [grin]

#include <algorithm>  // for_each#include <functional> // bind2nd, mem_funstd::for_each(g_Controls.begin(), g_Controls.end(),              std::bind2nd(std::mem_fun(&widget::render), Paint.hdc));

Its times like these C++ can do with a boost [grin].

##### Share on other sites
Original post by snk_kid
Quote:
 Original post by Programmer16Its times like these C++ can do with a boost [grin].

Edit:
Ok, does anybody know where I can find some boost tutorials? I read the documents, but it doesn't really have any examples (that I can find).

Thanks!

[Edited by - Programmer16 on June 9, 2005 5:51:27 PM]

##### Share on other sites
Original post by Programmer16
Quote:
Original post by snk_kid
Quote:
 Original post by Programmer16Its times like these C++ can do with a boost [grin].

Edit:
Ok, does anybody know where I can find some boost tutorials? I read the documents, but it doesn't really have any examples (that I can find).

Thanks!

Any specific part(s) of boost? I've found examples most of the time, just well hidden :-).

##### Share on other sites
Quote:
 Original post by MaulingMonkeyAny specific part(s) of boost? I've found examples most of the time, just well hidden :-).

Well, I've found some of them (hidden, as you said), but after actually trying to use it, boost seems to actually work like it shoud (so I've been able to figure it out for the most part).

Thanks for all of your help everybody!

##### Share on other sites
Quote:
Original post by snk_kid
Quote:
 Original post by MaulingMonkeyIndeed, this should be done like so:Widget* pCtrl = &*pItor;

Ah but he has a vector of pointer to Widget [wink]

TOTALLY need to learn to read here. I'll fix that :3.