I have a loop with these two lines and it works.
I was told that I would run out of brushes doing it this way.
Is this wrong to do it this way?? :tdown :thumbu
Thanks
invoke nrandom,0ffffffh
invoke SelectObject,hDC,rv(CreateSolidBrush,eax) :naughty:
if you look at the docs for SelectObject, you will find that it returns the handle for the object that is being replaced
you can use that handle to delete it with DeleteObject
http://msdn.microsoft.com/en-us/library/dd162957%28v=vs.85%29.aspx
http://msdn.microsoft.com/en-us/library/dd183539%28v=vs.85%29.aspx
Not tested, but this should do the job:
invoke nrandom, 0ffffffh
invoke CreateSolidBrush, eax
push eax ; will be arg for DeleteObject
invoke SelectObject, hDC, eax
push eax ; save previous object
... draw ...
pop eax
invoke SelectObject, hDC, eax ; select previous object
call DeleteObject ; the arg is already on the stack
My program works fine, I don't care about saving the old brush, just want to know if my way will run out of brushes.(someone said this without any reason why or how)
I have read SelectObject API and have always used it like jj2007 says.
When I execute SelectObject over and over without saving the old brush does creating a new brush each time
use up different brushes each time somewhere in memory??
xroot,
you are producing a so called 'handle leak' - that is simply a bug and it is a question of time, that your program stop working.
Just test it. Create an endless loop, with an invoke Sleep, 1 to prevent problems with your Office suite, and let it run some days. Then report to us what happened.
just add one more line...
invoke nrandom,0ffffffh
invoke SelectObject,hDC,rv(CreateSolidBrush,eax)
invoke DeleteObject,eax
deleting unused objects reduces your use of system resources :U
Dave,
that's almost as evil as jmp DefWindowProc :green2
Thanks, qWord
That is what I wanted to know I will change my code
and again thanks.
http://en.wikipedia.org/wiki/Handle_leak
xroot,
> I don't care about saving the old brush
You need to care if you don't want the memory leak. The high level logic is you select an object AND save the old one. Do what you need with the selected object then delete it and restore the old one.
In pseudo code,
SelectObject newobj
mov hOldObj, eax
; perform what you want with the object.
DeleteObject newobj
SelectObject hOldObj
The problem with doing the following,
invoke SelectObject,hDC,rv(CreateSolidBrush,eax)
is you don't save the old brush so every time you call the function you waste more memory.
i am playing with something similar - but i am selecting a font, rather than a brush
just a guess, here - it probably takes longer to delete an object than it does to restore the original handle
my thinking is that selecting a font or brush for a DC simply involves placing the object handle in a table that describes the DC
whereas, deleting an object requires more time to free the resources
in my case, i create the font in a routine that allows the user to select fonts
that handle is then stored in a global variable, where it remains unaltered until the user selects a different font
no need to repeatedly create and delete that object
in the paint routine, i select the font object, saving the original (replaced) font handle on the stack
once the paint routine is done, i restore the orignal font with another SelectObject call
i.e., the only time an object is deleted is if the user selects a new font - i delete the old one
your case is a little different, in that you are randomly creating a different object with each pass
it seems you should delete an object, whether it is the original one, or the one you created
however, it seems to be a little more efficient to delete the original object than the one you created
because it requires an additional system call to delete the one you created
Hutch's pseudo-code
SelectObject newobj
mov hOldObj, eax
; perform what you want with the object.
DeleteObject newobj
SelectObject hOldObj
Dave's pseudo-code
SelectObject newobj
DeleteObject oldobj
; perform what you want with the new object.
the only problem i see is that you might be trying to delete a system-created object
i read something about that on MSDN, but i don't remember what it was - lol - old age
(as i recall, it was either "don't do it" or "the attempt is ignored")
you might want to thoroughly review the SelectObject and DeleteObject documentation to see what the details are
EDIT:
ok - i found a note in the documentation for SelectObject...
QuoteThis function returns the previously selected object of the specified type. An application should always
replace a new object with the original, default object after it has finished drawing with the new object.
unfortunately, they do not explain why or what happens if you don't :(
your hair may fall out, i guess :P
what you probably want is something like this
invoke nrandom,0ffffffh
invoke SelectObject,hDC,rv(CreateSolidBrush,eax) ;create the first brush outside the loop
push eax ;save the original handle
top_of_loop:
;paint something
;delete the created handle
;nrandom
;create solid brush
;select object
;count and branch to top_of_loop
;delete the last object
;reselect the original one
Dave,
There is an easy way to see what happens, put the call in the WM_PAINT for a Window with a looped function and load Task Manager. Start the window and watch it leak like a sieve.
Effectively the OS maintains a "current object" for as many types of objects as are available, for your process it is available until you alter that state by selecting your own object, if you don't restore it in the documented way you don't recover the memory used for your new object.
switching to GDI+ avoids these annoying SelctObject()-hell :lol
Quote from: dedndave on June 20, 2011, 02:37:17 PM
the only problem i see is that you might be trying to delete a system-created object
i read something about that on MSDN, but i don't remember what it was - lol - old age
(as i recall, it was either "don't do it" or "the attempt is ignored")
You can try but it will be gracefully ignored. This is for lazy programmers like you and me who do not want an extra check if the object is sys or private :bg
Quote
EDIT:
ok - i found a note in the documentation for SelectObject...
QuoteThis function returns the previously selected object of the specified type. An application should always
replace a new object with the original, default object after it has finished drawing with the new object.
unfortunately, they do not explain why or what happens if you don't :(
your hair may fall out, i guess :P
Actually, it is a non-trivial question. I tried DeleteObject on a font that was still selected, and it returns sometimes 1, sometimes 0 but in any case "The operation was completed successfully". Hmm... dig further and you find this:
"Do not delete a drawing object (pen or brush) while it is still selected into a DC."
You see? Fonts are not mentioned, hehe! :green2
I seem to recall a post here recently that explained why you should always replace a new object with the original but I can't recall who posted it or find the post.
It depends probably on the type of handle. If what you get is a pointer to a resource that Windows has to create and maintain, then deleting the object the handle points to is an invitation for an access violation. If instead you get an entry to some global structure that Windows maintains anyway - like fonts -, you might get away with "deleting" the pointer to the font table because the fonts are still around after you marked the reference as bad via DeleteObject.
Having said that: After a while my deleted fonts stop working...
I think the point was for your last SelectObject call to always restore the default.
:bg
many of you guys missed out on the sheer fun of writing Win16 code. Software multitasking meant that all of Windows was one running program and if your app made a mess of memory, it took out the entire operating system. On the bright side, Win16 used to boot a lot faster than the 32 bit versions. Win32 at least restricts the messups to the running process so if you make a mess of memory you trash your own app, not everything else as well.
The test for a memory leak with GDI objects is reasonably simple, put the output in a loop and run task manager, if you have got it wrong you will see memory usage continually going up.
Magic rule is "Observe the SelectObject/DeleteObject rules" or watch it go BANG !
"Bang" - i think that'll be the name for my next project :P
I don't understand why you need to delete your drawing objects and brushes after drawing. I always thought of it as borrowing art supplies from the system, then giving them back after the program is done, or when you want to get some supplies off hand due to memory concerns.