Solved

345 Points ressource problem with LoadBitmap or LoadImage

Posted on 2001-08-22
34
604 Views
Last Modified: 2013-11-20
Hi Experts!!

I've an very URGENT problem in my MFC App loading ressources from a ressource dll!!

It is a big job to do, because i've to load about 500 Bitmaps (very small ones, so all in all is about 8 MBytes), if i try to load Bitmap No. 399, CBitmap::LoadBitmap(..), ::LoadBitmap(..) and also ::LoadImage(..) returns Zero!! (I tested all versions!).
The Bitmap is definetely present! All following Bitmaps will do the same, all previous Bitmaps (0..398) do fine.

GetLastError returns 0 (All ok,...haha!#..)

So what's the problem????

I studied some lectures, all wrote there's no memory limit about ressources, or is?

I'd become trouble if i don't solve this problem, so
!PLEASE!

I give you all my 345 Points for solving the problem!!

greetings

Uli
0
Comment
Question by:ulischmidt
  • 9
  • 5
  • 4
  • +8
34 Comments
 
LVL 32

Expert Comment

by:jhance
Comment Utility
What version of Windows?

What size are the bitmaps?

I'm wondering if there is some sort of resource or memory limitation going on here.  The number 400 itself seems disconnected from any usual limit since it's not a power of 2 but perhaps 400 x bitmapsize is.

I'm scratching my head.....
0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
Try to load your resource dll in DevStudio as a resource ('Open...', select 'As Resource') - if DevStudio can display all bitmaps, there is no limitation involved...
0
 

Author Comment

by:ulischmidt
Comment Utility
Hi jhance
I use Win 98 II, the Bitmaps are all of different size.

Hi jkr
I tried already to open the ressource dll in Visual studio "as ressource"...all Bitmaps are there, alse 399 and above!
0
 
LVL 32

Expert Comment

by:jhance
Comment Utility
Well, if you had said this was NT or 2000 I'd say the chances of some sort of resource limit are remote.  But with Win98, all bets are off....

Just a quick calculation based on what you've said:

8 MB total / 500 bitmaps = 16 KB / bitmap

But 400 x 16 KB = 6,400,000 MB

anytime I see a "round" number like this I'm suspicious.  I'm not saying I KNOW of any such limitation but then I've never used more than a handful of bitmaps in an application.
0
 
LVL 32

Expert Comment

by:jhance
Comment Utility
Is it possible you've run out of SYSTEM RESOURCES on your Win98 system?  Check your System properties or run the Resource monitor program and see if you've run out of them.
0
 
LVL 2

Expert Comment

by:waseemanis
Comment Utility
Guys.. i guess you all missed the point here ...
The problem is with the loading Last bitmap. If it was a memory problem .. then the Load error would have been sporadic.
I think Uli needs to check his code .. rather than system prformance.
0
 
LVL 2

Expert Comment

by:waseemanis
Comment Utility
Hey Uli,
How about trying to load bitmap number 0 or 398 as number 399. I mean  how about trying to replace bitmap number 399 with one of the many already loaded.

This would atleast test the validity of the bitmap.
0
 
LVL 12

Expert Comment

by:migel
Comment Utility
Hi!
some words from MSDN:
"...
Windows 95 has a problem dealing with Win32 .exe or .dll files that contain resources whose size is 64K or larger. To retain Win16 compatibility, Windows 95 converts the 32-bit size into a 16-bit size and a shift count. When it does this conversion it rounds down instead of up, so some bytes can be lost. In addition, Win16 uses the same shift count for all resources, thus the shift required for a large resource can cause a small resource to be severely truncated, or even eliminated completely.
To avoid this problem, compute the scaling factor for the largest resource and pad all resources with zeroes so each is a multiple of the scaling factor. For example, a resource of size 0x100065 is converted to 0x8003 * 32, which loses 5 bytes. To save the 5 bytes, you must pad the resource with 27 zeroes so that it becomes size 0x100080 and is then converted to 0x8004 * 32. Note, any smaller resource must also be padded with zeroes so it is a multiple of the scaling factor, which in this case is 32.
..."
can you send your DLL for test it on vary paltform?
my Email is: migel.geo@yahoo.com
0
 
LVL 9

Expert Comment

by:Pacman
Comment Utility
>> I studied some lectures, all wrote there's no memory
>> limit about ressources, or is?

In my opinion nothing in windows is so limited as GDI resources.

Did you try to start with bitmap #399 and go on to #500 ?
Does it work?
0
 
LVL 6

Expert Comment

by:MichaelS
Comment Utility
>Did you try to start with bitmap #399 and go on to #500 ?
Does it work?

This is the question I also wanted to ask :)

BTW, it will be helpful if you show the code. Than we can look at it and stop guessing.
0
 
LVL 9

Expert Comment

by:BeyondWu
Comment Utility
I have ever encountered the same question, I use a loop to load bitmap and each bitmap is 8*8, when i reach some numbers, the windows will popup a messagebox say there no more memory.

ulischmidt, are you have the same question?

0
 

Author Comment

by:ulischmidt
Comment Utility
Hi Folks
First let me thank u for your answers.

The Bitmaps #399 and up are defenitely valid!
The resource monitor shows:
  System Resources: 43%
  User-Resources: 73%
  GDI-Resources: 43%

There's no message about no more memory.

Here' the function i load the bitmaps with:

CNoDoubleBitmapArray is a CTypedPtrArray<CPtrArray,CBitmap*> to store the Bitmaps
and to avoid to load same bitmaps more than 1 time.

CBitmap* CNoDoubleBitmapArray::LoadBitmap(LPCTSTR str)
{
    HBITMAP hbmp=(HBITMAP)::LoadImage(
                AfxFindResourceHandle(str, RT_BITMAP),
                str,
                IMAGE_BITMAP,
                0,
                0,
                LR_CREATEDIBSECTON);
    if(!hbmp)
    {
        DWORD err=GetlastError();
        return NULL;
    }

    CBitmap* pBmp=new CBitmap;
    pBmp->Attach(hbmp);
    if(!pBmp->m_hObject)
    {
        delete pBmp;pBmp=NULL;
        return NULL;
    }
   
    return Find(pBmp);//this function compares all
                      //existing Bitmaps in the array
                      //with this bitmap. If not found
                      //it will be added to the array
                      //and returned,
                      //otherwise it will be deleted. The
                      //found bitmap will be returned
                      //instead.
}

Before i used ::LoadImage, i used CBitmap->LoadImage(str).
I thought ::LoadImage will use less memory, because it loads the bitmaps not with the device colordepth, but with it's own (all Bitmaps are 256 Color), but this had no effect.
0
 
LVL 6

Expert Comment

by:MichaelS
Comment Utility
Can you call
AfxFindResourceHandle(str, RT_BITMAP)

before LoadImage and check the returned value?
               
Did you also tried to load bitmaps from 399 instead loading from 0?
0
 

Author Comment

by:ulischmidt
Comment Utility
Hi again:

Sorry : the limit Bitmap is #398!

More Info:
GetLastError() return always 0!

I started with Bitmap #398, all ok, then it loads the bitmaps, so they're ok!
But this doesn't solve the problem....

The first 12 Bitmaps have the size 800x600 and the following Bitmaps have the size 40x50 to 80x50 (different sizes).
0
 

Author Comment

by:ulischmidt
Comment Utility
AfxFindResourceHandle(str, RT_BITMAP) returns always a valid handle!

0
 
LVL 6

Expert Comment

by:MichaelS
Comment Utility
Ok, than other question, can you do the same but only from bitmap #500 to bitmap #0. May be than we can see something
0
 
LVL 12

Expert Comment

by:migel
Comment Utility
Hi!
if you just try load only #399 bitmap is it valid?
if it isn`t valid try recreate it in the resource editor or place dummy bitmap instead it (and never load it) may be there is some kind of alignment problem.
0
Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 

Author Comment

by:ulischmidt
Comment Utility
Again:

The Bitmap #398 and up does NOT differ from Bitmaps before.
There are many Bitmaps loaded before with the same size as Bitmap #398 and above!

MichaelS
Other resource dlls with less bitmaps load complete, others with morte Bitmaps have the same problem! Is there maybe a max number of Bitmaps, or resources in all?
0
 
LVL 9

Expert Comment

by:Pacman
Comment Utility
> Ok, than other question, can you do the same but only
> from bitmap #500 to bitmap #0. May be than we
> can see something

Yes this would be really interesting !
0
 

Author Comment

by:ulischmidt
Comment Utility
I tested the same app under Win NT, THERE IT WORKS!

So what's the problem with Win 98 II???
How can i solve it???
0
 
LVL 9

Expert Comment

by:Pacman
Comment Utility
The next interesting thing would be:
* Let it run from 7 to 500 (so some of the big bitmaps are included)

* Let it run from 20 to 500

how far does it go ?
do you get always 398 valid bitmaps or does the number change ?
0
 
LVL 6

Expert Comment

by:MichaelS
Comment Utility
>Is there maybe a max number of Bitmaps, or resources in all?

It's hard to say. There is some limitations. For example number of handles are limited, number of controls limited. May be CTypedPtrArray has some problems or so, it's more easy to find out when source code is available. In your case we can just guess and ask you to make some test out of which may be some things will gets cleared. It still not clear is than "magic" number (398) produces some problems or the problem is just in amount of data. May be you have something wrong in "Find" function. Thant's why we asking you to make some tests. Try to disable some parts of code and see what happens. In such a way you can find a part where problem is.

Try to disable Find function, try to use for example Icons instead of bitmaps or just some integers, or better try to debug it. Put a breakpoint on LoadImage, make something like:
static int i = 0;

if(i++ == 398)
    __asm int 3;

HBITMAP hbmp=(HBITMAP)::LoadImage(
               AfxFindResourceHandle(str, RT_BITMAP),
               str,
               IMAGE_BITMAP,
               0,
               0,
               LR_CREATEDIBSECTON);
   

0
 
LVL 49

Expert Comment

by:DanRollins
Comment Utility
There are three ways that

   CNoDoubleBitmapArray::LoadBitmap(LPCTSTR str)

can return 0.
1) ::LoadImage(...) fails
2) pBmp->Attach(hbmp) fails
3) CNoDoubleBitmapArray::Find() fails

Which one is failing?  Put a TRACE("XXX failed") at each juncture -- before returning NULL.

-- Dan
0
 
LVL 49

Expert Comment

by:DanRollins
Comment Utility
You have at least two other errors:

LR_CREATEDIBSECTON // no such constant

DWORD err=GetlastError(); //no such function

If you cook the code that you paste here, it makes it harder for use to help you.

-- Dan
0
 
LVL 49

Accepted Solution

by:
DanRollins earned 150 total points
Comment Utility
You care calling the undocumented AfxFindResourceHandle fn.  Is this needed?  Why not just pass in the handle of the target resource DLL?

The problem might lie in MFC's GDI object handle-mapping technique in the Attach() fn.  I see nothing in the MFC code that could fail except a call to AfxEnableMemoryTracking.

One thing to try:  Call AfxEnableMemoryTracking(FALSE) before doing the Attach().

Instead of pBmp->Attach(), you could try simply saving the HBITMAPs for each object, then Attach to a CBitmap when needed.

-- Dan
0
 

Author Comment

by:ulischmidt
Comment Utility
The Problem isn't the code, especially not AfxGetResourceHandle()...b'cause it works in all other cases, and as i posted before, under Win NT it works fine.
The only function, which is failing, is ::GetImage, or ::GetBitmap, so it seems, that the total count of handles under Windows 9x is limited.
I now run my project under Win NT and have no more trouble...(i hope so :-)...
the only thing under WinNT is, that LoadImage loads the Bitmaps not in device color depth (all Bitmaps have 256 color depth), so it loads all in theirs...that's nice, but...i later mask the bitmaps and only under WIN NT, the masking doesn't work properly then. Under Win 9x this does fine...
I changed it back to pBmp->LoadBitmap(str) and all works very very fine!

So if anybody solves the problem under Win9x, i give him or her the points as promised, even if i solved it with Win NT.
0
 
LVL 49

Expert Comment

by:DanRollins
Comment Utility
Please try:

HINSTANCE hInstRes= Xxxxx; // the handle of the DLL

HBITMAP hbmp=(HBITMAP)::LoadImage(
              hInstRes,
              str,
              IMAGE_BITMAP,
              0,
              0,
              LR_CREATEDIBSECTION);

By doing this, you eliminate many ways that your call to ::LoadImage() could fail under Win9x.  You might also be able to squeeze useful information out of the GetLastError() fn when it does fail.

-- Dan
0
 

Author Comment

by:ulischmidt
Comment Utility
Dan

I'll check it out tomorrow!
0
 
LVL 5

Expert Comment

by:FengYuan
Comment Utility
1) Try DanRollns' method, use DIB section instead of DDB. DIB section uses less system resource, because its pixel array is allocated from user mode virtual memory space.

2) Load the bitmaps as DIB, which does not use any GDI resource at all. Here is the code:

const BITMAPINFO * LoadDIB(HMODULE hModule, LPCTSTR pBitmapName)
{
     HRSRC   hRes = FindResource(hModule, pBitmapName, RT_BITMAP);

     if ( hRes==NULL )
          return NULL;

     HGLOBAL hGlb = LoadResource(hModule, hRes);

     if ( hGlb==NULL )
          return NULL;

     return LockResource(hGlb);
}

DIB can then be displayed using StretchDIBits.

3) If you're serious about GDI programming, read my book.

www.fengyuan.com
0
 

Author Comment

by:ulischmidt
Comment Utility
Hi Guys

Thanks a lot for all your comments!

Now i found a way to use about 250 Bitmaps less,..so it works fine for the first time without the need to use Windows NT....i had to do this, b'cause tomorrow i have to deliver the software!
I've to check out Dan Rollins' and Feng Yuan's methods for future projects!
The limitations is a very interesting thing, b'cause i never found these in the online help....(Greetings to Bill!) .. this is a thing where real life goes!

Please wish me luck for tomorrow!

Uli
0
 
LVL 49

Expert Comment

by:DanRollins
Comment Utility
good luck!

I think that we have not yet established that "Win9x limit" to be a fact.  But I am also pragmatic and when under a deadline, will go with the "fix that works" even if I have not uncovered the underlying cause.

-- Dan
0
 
LVL 5

Assisted Solution

by:FengYuan
FengYuan earned 150 total points
Comment Utility
Win9X GDI uses a 64-KB heap and a 32-bit 2MB heap.

Check Matt Pietrek's book on Windows 95, also use the MSVC HeapWalker program to walk GDI heaps.

www.fengyuan.com
0
 
LVL 9

Expert Comment

by:Pacman
Comment Utility
>> 3) If you're serious about GDI programming,
>> read my book.

I can recommend it. It's the best what I've found on GDI.
Also the "digging in the system" part is very interesting.

Pacman
0
 
LVL 23

Expert Comment

by:Roshan Davis
Comment Utility
No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this question is:

Answered by: DanRollins, FengYuan (points to be split)

Please leave any comments here within the next seven days.

PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!

Roshan Davis
EE Cleanup Volunteer
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

Introduction: Load and Save to file, Document-View interaction inside the SDI. Continuing from the second article about sudoku.   Open the project in visual studio. From the class view select CSudokuDoc and double click to open the header …
If you use Adobe Reader X it is possible you can't open OLE PDF documents in the standard. The reason is the 'save box mode' in adobe reader X. Many people think the protected Mode of adobe reader x is only to stop the write access. But this fe…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

6 Experts available now in Live!

Get 1:1 Help Now