[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 721
  • Last Modified:

345 Points ressource problem with LoadBitmap or LoadImage

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
ulischmidt
Asked:
ulischmidt
  • 9
  • 5
  • 4
  • +8
2 Solutions
 
jhanceCommented:
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
 
jkrCommented:
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
 
ulischmidtAuthor Commented:
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
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
jhanceCommented:
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
 
jhanceCommented:
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
 
waseemanisCommented:
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
 
waseemanisCommented:
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
 
migelCommented:
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
 
PacmanCommented:
>> 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
 
MichaelSCommented:
>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
 
BeyondWuCommented:
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
 
ulischmidtAuthor Commented:
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
 
MichaelSCommented:
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
 
ulischmidtAuthor Commented:
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
 
ulischmidtAuthor Commented:
AfxFindResourceHandle(str, RT_BITMAP) returns always a valid handle!

0
 
MichaelSCommented:
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
 
migelCommented:
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
 
ulischmidtAuthor Commented:
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
 
PacmanCommented:
> 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
 
ulischmidtAuthor Commented:
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
 
PacmanCommented:
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
 
MichaelSCommented:
>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
 
DanRollinsCommented:
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
 
DanRollinsCommented:
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
 
DanRollinsCommented:
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
 
ulischmidtAuthor Commented:
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
 
DanRollinsCommented:
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
 
ulischmidtAuthor Commented:
Dan

I'll check it out tomorrow!
0
 
FengYuanCommented:
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
 
ulischmidtAuthor Commented:
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
 
DanRollinsCommented:
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
 
FengYuanCommented:
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
 
PacmanCommented:
>> 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
 
Roshan DavisCommented:
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

Prep for the ITIL® Foundation Certification Exam

December’s Course of the Month is now available! Enroll to learn ITIL® Foundation best practices for delivering IT services effectively and efficiently.

  • 9
  • 5
  • 4
  • +8
Tackle projects and never again get stuck behind a technical roadblock.
Join Now