# Showing images with C++



## qepto (Aug 25, 2004)

Hello, I'm trying to write a slideshow program with Visual C++ 6.0 Enterprise Edition. My Operating system is Windows Millenium. I'm working out of a book called SAMS teach yourself game programming and when I run the code from the cd it works fine. I can't see where the difference is between my code and that on the cd.
The problem is this:

I've written a bitmap class file which contains three constructors plus the default. The first constructor is supposed to take a device context and the name of the file as parameters. I don't know why but this way of displaying a bit map doesn't work at all. here's the code for the bitmap:

```
BOOL Bitmap::Create(HDC hDC, LPTSTR szFileName)
{
  // Free any previous bitmap info
  Free();

  // Open the bitmap file
  HANDLE hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  if (hFile == INVALID_HANDLE_VALUE)
    return FALSE;

  // Read the bitmap file header
  BITMAPFILEHEADER  bmfHeader;
  DWORD             dwBytesRead;
  BOOL bOK = ReadFile(hFile, &bmfHeader, sizeof(BITMAPFILEHEADER),
    &dwBytesRead, NULL);
  if ((!bOK) || (dwBytesRead != sizeof(BITMAPFILEHEADER)) ||
    (bmfHeader.bfType != 0x4D42))
  {
    CloseHandle(hFile);
    return FALSE;
  }

  BITMAPINFO* pBitmapInfo = (BITMAPINFO*)(new BITMAPINFO_256);
  if (pBitmapInfo != NULL)
  {
    // Read the bitmap info header
    bOK = ReadFile(hFile, pBitmapInfo, sizeof(BITMAPINFOHEADER),
      &dwBytesRead, NULL);
    if ((!bOK) || (dwBytesRead != sizeof(BITMAPINFOHEADER)))
    {
      CloseHandle(hFile);
      Free();
      return FALSE;
    }

    // Store the width and height of the bitmap
    m_iWidth = (int)pBitmapInfo->bmiHeader.biWidth;
    m_iHeight = (int)pBitmapInfo->bmiHeader.biHeight;

    // Skip (forward or backward) to the color info, if necessary
    if (pBitmapInfo->bmiHeader.biSize != sizeof(BITMAPINFOHEADER))
      SetFilePointer(hFile, pBitmapInfo->bmiHeader.biSize - sizeof
        (BITMAPINFOHEADER), NULL, FILE_CURRENT);

    // Read the color info
    bOK = ReadFile(hFile, pBitmapInfo->bmiColors,
      pBitmapInfo->bmiHeader.biClrUsed * sizeof(RGBQUAD), &dwBytesRead,
      NULL);

    // Get a handle to the bitmap and copy the image bits
    PBYTE pBitmapBits;
    m_hBitmap = CreateDIBSection(hDC, pBitmapInfo, DIB_RGB_COLORS,
      (PVOID*)&pBitmapBits, NULL, 0);
    if ((m_hBitmap != NULL) && (pBitmapBits != NULL))
    {
      SetFilePointer(hFile, bmfHeader.bfOffBits, NULL, FILE_BEGIN);
      bOK = ReadFile(hFile, pBitmapBits, pBitmapInfo->bmiHeader.biSizeImage,
        &dwBytesRead, NULL);
      if (bOK)
        return TRUE;
    }
  }

  // Something went wrong, so cleanup everything
  Free();
  return FALSE;
}
```
The second contructor displays the bitmap using a device context, resource id and an instance handle. It shows the image but the left edge of the bitmap is shifted to the right and the image wraps around. The code for this is:

```
BOOL Bitmap::Create(HDC hDC, UINT uiResID, HINSTANCE hInstance)
{
  // Free any previous DIB info
  Free();

  // Find the bitmap resource
  HRSRC hResInfo = FindResource(hInstance, MAKEINTRESOURCE(uiResID), RT_BITMAP);
  if (hResInfo == NULL)
    return FALSE;

  // Load the bitmap resource
  HGLOBAL hMemBitmap = LoadResource(hInstance, hResInfo);
  if (hMemBitmap == NULL)
    return FALSE;

  // Lock the resource and access the entire bitmap image
  PBYTE pBitmapImage = (BYTE*)LockResource(hMemBitmap);
  if (pBitmapImage == NULL)
  {
    FreeResource(hMemBitmap);
    return FALSE;
  }

  // Store the width and height of the bitmap
  BITMAPINFO* pBitmapInfo = (BITMAPINFO*)pBitmapImage;
  m_iWidth = (int)pBitmapInfo->bmiHeader.biWidth;
  m_iHeight = (int)pBitmapInfo->bmiHeader.biHeight;

  // Get a handle to the bitmap and copy the image bits
  PBYTE pBitmapBits;
  m_hBitmap = CreateDIBSection(hDC, pBitmapInfo, DIB_RGB_COLORS,
    (PVOID*)&pBitmapBits, NULL, 0);
  if ((m_hBitmap != NULL) && (pBitmapBits != NULL))
  {
    const PBYTE pTempBits = pBitmapImage + pBitmapInfo->bmiHeader.biSize +
      pBitmapInfo->bmiHeader.biClrUsed * sizeof(RGBQUAD);
    CopyMemory(pBitmapBits, pTempBits, pBitmapInfo->bmiHeader.biSizeImage);

    // Unlock and free the bitmap graphics object
    UnlockResource(hMemBitmap);
    FreeResource(hMemBitmap);
    return TRUE;
  }

  // Something went wrong, so cleanup everything
  UnlockResource(hMemBitmap);
  FreeResource(hMemBitmap);
  Free();
  return FALSE;
}
```
I've been trying to work out why this doesn't work for ages. Any help would be greatly appreciated. Thanks for reading


----------



## clr (Aug 24, 2004)

cant help ya with the programming, sory, but what u do need to do is get Windows XP pro atleast. ME is just not gonna cut it, especially trying to use VC++


----------



## qepto (Aug 25, 2004)

what exactly do you mean windows Me isn't going to cut when programming with vc++ ?


----------



## Shadow2531 (Apr 30, 2001)

It's not just VC++, it's others too. Depending on what you are doing, a program etc. might not compile unless you have Win2K, WinXP etc. So it is very possible that it's an OS problem.

However, we have not determined that this is an OS problem yet.

I do not have VC++. I have GCC MinGW so I do not know if everything will work for me, but if you want, you can zip up all your project files and upload it somewhere so I and others can download and mess with it. We need everything so we can be on the same level as you. That means, cpp files resource files, any pics, icons etc. that go with the project.


----------



## qepto (Aug 25, 2004)

okay I've uploaded the files to www.geocities.com/qepto/prog.zip

thanks for looking even if you can't help.


----------



## Shadow2531 (Apr 30, 2001)

O.K. downloaded it. I'll check it out soon.

On a side note, keep this thread for reference, as you might end up doing that part later.


----------



## qepto (Aug 25, 2004)

it was because I found that thread when searching for the answer to my problem on google that I posted here


----------



## Shadow2531 (Apr 30, 2001)

The program successfully compiled, but I got the following warnings.

In file included from SLIDESHOW.cpp:9:
Slideshow.h:6:9: warning: #pragma once is obsolete
In file included from Slideshow.h:13,
from SLIDESHOW.cpp:9:
GameEngine.h:6:9: warning: #pragma once is obsolete
In file included from Slideshow.h:14,
from SLIDESHOW.cpp:9:
Bitmap.h:6:9: warning: #pragma once is obsolete
SLIDESHOW.cpp: In function `void GameActivate(HWND__*)':
SLIDESHOW.cpp:58: warning: unused parameter `HWND__*hWindow'
SLIDESHOW.cpp: In function `void GameDeactivate(HWND__*)':
SLIDESHOW.cpp:62: warning: unused parameter `HWND__*hWindow'
In file included from BITMAP.Cpp:9:
Bitmap.h:6:9: warning: #pragma once is obsolete
BITMAP.Cpp: In member function `BOOL Bitmap::Create(HDC__*, unsigned int,
HINSTANCE__*)':
BITMAP.Cpp:169: warning: statement with no effect
BITMAP.Cpp:175: warning: statement with no effect
In file included from GAMEENGINE.cpp:9:
GameEngine.h:6:9: warning: #pragma once is obsolete
GAMEENGINE.cpp: In function `int WinMain(HINSTANCE__*, HINSTANCE__*, CHAR*,
int)':
GAMEENGINE.cpp:21: warning: unused parameter `HINSTANCE__*hPrevInstance'
GAMEENGINE.cpp:21: warning: unused parameter `CHAR*szCmdLine'

You can ignore the unused paramater warnings, but the rest you should investigate.

unlockResource() is also obsolete, so that could be the problem with line 169 and 175 errors in bitmap.cpp. Just comment them out.


Also, don't use pragma. Do it like this in your header files.

#ifndef GAMEENGINE_H
#define GAMEENGINE_H

code goes here

#endif
(blank line)

When I run the program, I just get a window named slideshow with nothing in it for about a minute. Then I get a green background. Is that what you get?


----------



## Shadow2531 (Apr 30, 2001)

got it working.

Before you check out any of the suggestions above, fix your slideshow.rc file.

The bitmap section should look like the following instead of what you have.

IDB_IMAGE1 BITMAP DISCARDABLE "image1.bmp"
IDB_IMAGE2 BITMAP DISCARDABLE "image2.bmp"
IDB_IMAGE3 BITMAP DISCARDABLE "image3.bmp" 
IDB_IMAGE4 BITMAP DISCARDABLE "image4.bmp"
IDB_IMAGE5 BITMAP DISCARDABLE "image5.bmp"
IDB_IMAGE6 BITMAP DISCARDABLE "image6.bmp"

That should do the trick.

Then you can fix the things I listed above if you want

or

You can download the modified files and the exe here.


----------



## qepto (Aug 25, 2004)

It's really weird. When I run your program it runs fine. However, when I replaced my non working files with the ones that you have I don't get any images at all other than the solid color image. Maybe it's the compiler that I'm using. What do you have to type in on a command line compiler to compile and link the files together?


----------



## Shadow2531 (Apr 30, 2001)

I use the windows version of gcc 3.3. It's called MinGW. It's free too. http://www.mingw.org

I use a specially compiled distro of it though.

To get it, goto http://www.nuwen.net , goto the c++ page and in the MinGW Distribution section of the page is the link to download it. View the readme for how to install it.

In the batch file are the commands I used.

windres -i slideshow.rc -o icons

g++ -Wall -W slideshow.cpp bitmap.cpp gameengine.cpp icons -o myslide -mwindows -s

upx -qqq --best myslide.exe

The first one makes an object file of all the pics/icons so you can include that file. The second does the compiling and linking. The third is the upx exe compressor that comes with that distro.

-Wall and -W turn on almost all warnings. -mwindows tells the compiler not to create a console window. -s strips the debug info form the exe to make it smaller.

Your compiler might be case sensitive one some of those files and if you have your pic named image1.bmp and the rc file points to image1.bmp, it might not include it.

Although MinGW is great, you'll want to keep using the VC++ for when you directX stuff as you'll have to convert a bunch of libraries to make them work with MinGW.


----------

