|
I'm writing a program employing sprite animation. Each sprite holds its image in the form of a device-dependent bitmap (a HBITMAP) as well as other data that will allow it to be rendered. In order to render this bitmap onto a display surface, the bitmap needs to be selected into a memory DC first. My question: is it better to create a temporary memory DC every time the sprite needs to be rendered (then delete this DC after you've done rendering), or to create a permanent memory DC so that you don't have to create a DC everytime the sprite needs rendering. The "permanent DC" method would presumably be faster than the "temporary DC" method since you don't have to create the DC every time you render, but requires memory to hold the DC. How much speed improvement would having a permanent memory DC bring? and how much memory penalty?
(As an aside, I could make the sprite hold a DIB instead of a DDB and then render the DIB with DrawDibDraw, StretchDIBits, or SetDIBitsToDevice, which doesn't require a source DC. But would this method be significantly slower?)
Sorry for the long post. Any reply would be greatly appreciated.
Henry
|
|
|
|
|
I don't think memory is the issue here, but the notion of keeping permanent DC's is. If I dig way back to my Windows 3.0 days DC's were a scarce commodity, to be used and then released asap. Now we've come a long way since then, but nevertheless I don't think you want to grab a DC and hold it for a long period. One approach is that if you know you are about to draw a whole bunch of stuff grab the DC and whatever else you need at the start and let it go at the end. Or even look at caching a DC.
That said why don't you start with the simplest approach, see if it is too slow and then look at optimising it. Profile the code to see where the hotspots are. Getting a DC may be inconsequential.
Neville Franks, Author of ED for Windows. www.getsoft.com
|
|
|
|
|
Thanks for quick reply. Let me just clarify it a bit to be sure we're on the same page. Let's say I were to implement a Render function for the CSprite class. The CSprite class would have as its member m_hBM and m_hMemDC. Before Render is called, these two handles have been created elsewhere. The code has been simplified for illustration purposes.
// member variables
HBITMAP m_hBM; // holds the device-dependent bitmap
HDC m_hMemDC; // the memory DC to be used as the source DC in blitting operations. (See below)
// first method, using a permanent m_hMemDC, created elsewhere
BOOL CSprite::Render(HDC hDestDC, int left, int top, int width, int height)
{
HBITMAP hOldBM = (HBITMAP)::SelectObject(m_hMemDC, m_hBM);
::BitBlt(hDestDC, left, top, width, height, m_hMemDC, left, top, SRCCOPY);
::SelectObject(m_hMemDC, hOldBM);
}
// second method, using a temporary m_hMemDC, created each time Render is called
BOOL CSprite::Render(HDC hDestDC, int left, int top, int width, int height)
{
m_hMemDC = ::CreateCompatibleDC(hDestDC);
HBITMAP hOldBM = (HBITMAP)::SelectObject(m_hMemDC, m_hBM);
::BitBlt(hDestDC, left, top, width, height, m_hMemDC, left, top, SRCCOPY);
::SelectObject(m_hMemDC, hOldBM);
::DeleteDC(m_hMemDC);
}
Which method is better, in terms of either memory or speed?
Henry P.
http://www.allersoft.com
|
|
|
|
|
The first will be the fastest and is the best approach as long as you don't keep the HDC m_hMemDC; class member around for too long.
This is the approach I use in ED (see sig) whenever I need to update the display. I create a drawing object which does stuff like CreateCompatibleDC(), this is then used for all of the display update operations, then the class destructor releases the DC etc. when the drawing has finished.
Neville Franks, Author of ED for Windows. www.getsoft.com
|
|
|
|
|
You are safe to hold onto as many memory DCs as you would like. They are simply stored in memory, and the number of memory DCs are limited by the amount of memory on your system.
You should not hold onto Window DCs. In the Win9x OSs, there are only about eight window DCs that are available. So if you do not release the window DC, then unexpected things might start happening.
I am not sure of the limit in windows NT, however it is still not advisable to hold onto window DCs even in windows NT.
Yes it would be significantly slower to render a dib than a DDB. That is because the DDB is already formatted for the current device. In order to perform a bitblt you simply need to transfer an array of bits. A DIB needs to first be converted and color matched then transferred.
Good Luck.
Build a man a fire, and he will be warm for a day Light a man on fire, and he will be warm for the rest of his life!
|
|
|
|
|
Thanks a lot...That's what I thought.
If I understand it correctly, a DC is simply a data structure containing drawing attributes and handles to graphic objects (but not the objects themselves). As such, how much memory does a device context require?
Henry P.
http://www.allersoft.com
|
|
|
|
|
As mentioned earlier, you can keep as many memory DC's around as you like. I wouldn't think they would be terribly large. You might try looking on www.sysinternals.com[^] to see if they would know, or have a tool that could tell you.
Gary R. Wheeler
|
|
|
|
|
I have a class which i use as a base class for my other views.. it has a base class of CFormView.. i hope to convert this view into a .dll .. it currently is dependent on the resource.h because of the line:
enum { IDD = IDD_DISPLAY };
this is then used in the CFormView constructor.. the other option for the constructor is to pass it LPCTSTR lpszTemplateName which i guess is what i need to do? how could i get rid of this dependency, and how could i maybe make this view into a .dll?
thanks for any suggestions!
still a newb.. cut me some slack :P
-dz
|
|
|
|
|
One solution (assumes CYourFormView is your CFormView derived class):
1. Take out the "enum { IDD = IDD_DISPLAY };" from the CYourFormView.
2. Change the constructor of CYourFormView to accept a resource ID, and to not pass IDD into the CFormView constructor, but rather, pass in the value you get in CYourFormView's constructor.
3. In each .exe that uses CYourFormView, change the base initializer to pass in the appropriate resource ID to CYourFormView.
It could be something like this:
class CYourFormView : public CFormView
{
public:
CYourFormView( UINT p_uiTitleID );
CYourFormView( LPCTSTR p_pszTitle );
};
CYourFormView::CYourFormView( UINT p_uiTitleID ) :
CFormView( p_uiTitleID )
{
}
CYourFormView::CYourFormView( LPCTSTR p_pszTitle ) :
CFormView( p_pszTitle )
{
}
class CYourMoreSpecialFormView : public CYourFormView
{
public:
CYourMoreSpecialFormView();
enum { IDD = IDD_WHATEVER_YOU_WANT_IT_TO_BE };
};
CYourMoreSpecialFormView::CYourMoreSpecialFormView() :
CYourFormView( IDD )
{
}
I hope I have been clear enough. If not, I can try to explain better.
Chris Richardson
|
|
|
|
|
how can i know how many elements the vector has?
|
|
|
|
|
size_type size() const;
this is in all manuals and MSDN documentation.
Max.
|
|
|
|
|
|
Hi Folks,
can anybody tell me how the read a standard windows cfg file and access its sections and parameters ? Like
[My Section]
something = 1
I suppose there has to be a mfc class ???
Many Thanks
murphman
|
|
|
|
|
Look at GetProfileString, ReadProfileString, and related functions; they are Win32 API functions.
Max.
|
|
|
|
|
Great && Fast help ...
Regards
murphman
|
|
|
|
|
Hello All,
I am using one function, IDiscRecorder::GetPath(); Which returns the path for the CDRecorder, this function either gives OS Path, like \Device\CDRom0 or E:\. I am using this function which returns OS Path, and I want it to return the Drivetype its mapping to.
Is there anyway, someone can tell me, how can I find that what this OS path is mapping to. And I am doing it programmatically. So, it will be very helpful,if someone can suggest me how to get the drivetype with given OS path.
Thanks,
|
|
|
|
|
For drive-letter you can use GetDriveType (too obvious? ).
For the NT-only device specifications ("\Device\Xxx") I think you'd have to either get the drive-letter for that device or use some DDK function (AFAIK it's only the DDK that documents NT-only, non-Win32, functions).
|
|
|
|
|
I created a database, now I want to fill in the fields. The way I've seen is to do an AddNew with the recordset. But I have no records! Is it okay to do a SQL query (select * from Table) to retrieve a recordset object?
Appreciate your help,
ns
|
|
|
|
|
|
as far as i know, it`s ok to do that.
|
|
|
|
|
I've made an application to get meteo data from a server and to draw a graphic, it is possible to save it to a file. Well, when I download and draw a file, the first item of MRU files never works, neither if I try to open it with the 'File Open Dialog', but the another three items in MRU work fine. I suppose it assumes than the first item is the one loaded at screen but it's not true. What could be the problem?
|
|
|
|
|
I'm trying to use sendmessage to a button in a dialogbox. It seems its not working. I must have the parameters wrong or something. Any ideas.
Thanks
|
|
|
|
|
It should be defined something like this:
LRESULT SendMessage( UINT message, WPARAM wParam = 0, LPARAM lParam = 0 );
How are your parameters set up?
Nick Parker
The greatest lesson in life is to know that even fools are right sometimes. - Winston Churchill
|
|
|
|
|
Try this solution.
::SendMessage(m_Button.GetSafeHwnd(), Message, WPARAM, LPARAM)
Kuphryn
|
|
|
|
|
There's no way to know what's wrong unless you post your code.
--Mike--
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
|
|
|
|
|