Sign in to follow this  
gretty

[win32/c++] Displaying Bitmap causes crash

Recommended Posts

Hello I have made a simple win32 application that converts temperatures. Problem: I am displaying a bitmap image in a static control that is scaled using StretchBlt(). But when the application runs it goes into an infinite loop, doesn't display the bitmap & crashes. I believe the problem is either to do with the static window where the bitmap is loaded to OR in the painting area. To make it easy to find where the problem occurs, I think its in the Windows Proceedure function in either: - WM_CREATE - WM_PAINT
#include <windows.h>
#include <cstdlib>
#include <string>
#include <stdio.h>
#include "converter.h"

using namespace std;

const char g_szClassName[] = "myWindowClass";
static HINSTANCE gInstance;
HBITMAP header = NULL;
bool convert = false;

// Functions List //
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
bool isEqual(double cel, double fahr);
double findFahren(double cel);
double findCel(double fahr);


int WINAPI WinMain(HINSTANCE gInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;

    //Step 1: Registering the Window Class
    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.style         = 0;
    wc.lpfnWndProc   = WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = gInstance;
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(LTGRAY_BRUSH);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = g_szClassName;
    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

    // if registration of main class fails
    if(!RegisterClassEx(&wc))
    {
        MessageBox(NULL, "Window Registration Failed!", "Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    // Step 2: Creating the Window
    hwnd = CreateWindowEx(
        0,
        g_szClassName,
        "Temperature Converter",
        WS_OVERLAPPEDWINDOW | WS_VISIBLE | SS_GRAYFRAME,
        CW_USEDEFAULT, CW_USEDEFAULT, 410, 200,
        NULL, NULL, gInstance, NULL);

    if(hwnd == NULL)
    {
        MessageBox(NULL, "Window Creation Failed!", "Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    // Step 3: The Message Loop
    while(GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return Msg.wParam;
}

// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    HWND btnConvert, fldCelcius, fldFaren, cbFtc, cbCtf;
    // Labels
    HWND stBgd, stBox, lbCelcius, lbFaren;
    
    switch(msg)
    {
        case WM_CREATE:
        {
             //load bitmap
             header = LoadBitmap(GetModuleHandle(NULL),MAKEINTRESOURCE(IDB_HEADER));
             //if fails
             if (header == NULL) {
                 MessageBox(hwnd,"Failed to load bitmap","Error",MB_OK);
             }   
     
            // Create labels, buttons, edits etc.
            stBgd = CreateWindowEx(
                           0,
                           "Static",
                           "",
                           WS_BORDER | WS_VISIBLE | WS_CHILD,
                           2,2,
                           390,160,
                           hwnd,NULL,
                           gInstance,
                           NULL);
                           
            // Window to load & display bitmap header
            stBox = CreateWindowEx(
                      0,
                      "Static",
                      "",
                      WS_BORDER | WS_CHILD | WS_VISIBLE | SS_BITMAP,
                      10,10,
                      350,147,
                      hwnd,
                      (HMENU)IDT_TEXT,
                      gInstance,
                      NULL);
                           
            fldCelcius = CreateWindowEx(
                           0,
                           "EDIT",
                           "0",
                           WS_BORDER | WS_VISIBLE | WS_CHILD | ES_NUMBER,
                           20,80,
                           100,20,
                           hwnd,(HMENU)ID_CELCIUS,
                           gInstance,
                           NULL);
                           
            // Label
            lbCelcius = CreateWindowEx(
                         0,
                         "STATIC",
                         "Celcius",
                         WS_VISIBLE | WS_CHILD,
                         122,80,
                         60,20,
                         hwnd, NULL,
                         gInstance,
                         NULL);
                               
             btnConvert = CreateWindowEx(
                          0,
                          "BUTTON",
                          "Convert",
                          WS_BORDER | WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
                          200,120,
                          100,20,
                          hwnd,(HMENU)ID_CONVERT,
                          gInstance,
                          NULL);
                          
             cbFtc = CreateWindowEx(
                          0,
                          "BUTTON",
                          "F-C",
                          WS_BORDER | WS_VISIBLE | WS_CHILD | BS_AUTOCHECKBOX | BST_UNCHECKED,
                          80,120,
                          50,20,
                          hwnd,(HMENU)ID_CEL,
                          gInstance,
                          NULL);
                          
             cbCtf = CreateWindowEx(
                          0,
                          "BUTTON",
                          "C-F",
                          WS_BORDER | WS_VISIBLE | WS_CHILD | BS_AUTOCHECKBOX | BST_CHECKED,
                          20,120,
                          50,20,
                          hwnd,(HMENU)ID_FAHR,
                          gInstance,
                          NULL);
                          
             fldFaren = CreateWindowEx(
                          0,
                          "EDIT",
                          "0",
                          WS_BORDER | WS_CHILD | WS_VISIBLE | ES_NUMBER, // only take numbers
                          200,80,
                          100,20,
                          hwnd,(HMENU)ID_FAHREN,
                          gInstance,
                          NULL);
                          
             // Label
             lbFaren = CreateWindowEx(
                        0,
                        "STATIC",
                        "Fahrenheit",
                        WS_VISIBLE | WS_CHILD,
                        302,80,
                        80, 20,
                        hwnd, NULL,
                        gInstance,
                        NULL);
                              
        }  
        break;
        case WM_COMMAND:

             switch(LOWORD(wParam)) {
                      
                    case ID_CONVERT:
                    {
                         BOOL cSuccess;
                         BOOL fSuccess;
                         double celcius = GetDlgItemInt(hwnd,ID_CELCIUS,&cSuccess,true);
                         double fahrenheit = GetDlgItemInt(hwnd,ID_FAHREN,&fSuccess,true);
                         // if either GetDlgItemInt fails
                         if (!cSuccess | !fSuccess) {
                            MessageBox(hwnd,"Get numbers from text fields failed",
                                       "Error!",MB_OK);
                         }

                         if (!isEqual(celcius,fahrenheit)) {
                             if (convert) {
                                 celcius = findCel(fahrenheit);
                                 SetDlgItemInt(hwnd,ID_CELCIUS,(int)celcius,true);  
                             }
                             else {
                                 fahrenheit = findFahren(celcius);
                                 SetDlgItemInt(hwnd,ID_FAHREN,(int)fahrenheit,true);
                             }
                         } 
                    } 
                    break;         
                    default:
                    break;                
             }        
             
             switch (HIWORD(wParam)) { 
                    
                    case BN_CLICKED:
                    {
                         if (LOWORD(wParam) == ID_CEL) {
                             if (SendDlgItemMessage(hwnd,ID_CEL,BM_GETCHECK,0,0) == BST_CHECKED) {
                                 convert = true;
                                 SendDlgItemMessage(hwnd,ID_FAHR,BM_SETCHECK,BST_UNCHECKED,0);                                         
                             }                                                        
                         }
                         if (LOWORD(wParam) == ID_FAHR) {
                             if (SendDlgItemMessage(hwnd,ID_FAHR,BM_GETCHECK,0,0) == BST_CHECKED) {
                                 convert = false;
                                 SendDlgItemMessage(hwnd,ID_CEL,BM_SETCHECK,BST_UNCHECKED,0);                                                 
                             }
                         }
                    }
                    break;
                    default:
                    break;
             }    
        break;
        case WM_PAINT:
        {
            BITMAP bm;
			PAINTSTRUCT ps;

            // To paint outside the update rectangle while processing 
            // WM_PAINT messages, you can make this call: 
            //InvalidateRect(hwnd,NULL,TRUE);
            
			HDC hdc = BeginPaint(GetDlgItem(hwnd,IDT_TEXT), &ps);

			HDC hdcMem = CreateCompatibleDC(hdc);
			HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem,header);

			GetObject(header, sizeof(bm), &bm);

			//BitBlt(hdc, 0, 0,346, 148, hdcMem, 0, 0, SRCCOPY);
			
            //SCALE Bitmap
			StretchBlt(hdc,0,0,(int)(bm.bmWidth/7),(int)(bm.bmHeight/7),hdcMem,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);
             
			SelectObject(hdcMem, hbmOld);
			DeleteDC(hdcMem);

			EndPaint(hwnd, &ps);
        }
        break;
        case WM_CLOSE:
            DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
             DeleteObject(header);
            PostQuitMessage(0);
        break;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}


bool isEqual(double cel, double fahr) 
{
     double result = (5.0 / 9.0) * (fahr - 32);
     
     // return if celcius equals fahr converted to celcius
     return (cel == result); 
}

double findFahren(double cel) {
    
    return ((9.0 / 5.0) * cel) + 32;
}

double findCel(double fahr) {
    
    return (5.0 / 9.0) * (fahr - 32);
}


[Edited by - gretty on December 28, 2009 1:07:28 AM]

Share this post


Link to post
Share on other sites
Give us some hints :)

What information does the crash give you? Accessing an invalid memory location? If so, what location? What line does the crash point to?

Also, try putting your code in [source] .. [/source] tags.

Share this post


Link to post
Share on other sites
That is not the correct way to use SS_BITMAP. Currently, you are trying to render the bitmap in the static control from within the parent window's WM_PAINT, for which you should not do. That BeginPaint call you have there is probably why it is crashing, since you pass it a window handle that is not the one receiving the current WM_PAINT message.

In general, the static control renders the bitmap for you and you shouldn't have to paint it yourself. See below for proper use of SS_BITMAP.

winmain.cpp

#include<windows.h>

static HINSTANCE basead = 0;
LRESULT CALLBACK StdWndProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam);

int WINAPI WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int)
{
basead = instance;

WNDCLASS wc;
ZeroMemory(&wc, sizeof(wc));
wc.style = 0;
wc.lpfnWndProc = StdWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = instance;
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = 0;
wc.lpszClassName = TEXT("MAINWINDOW");
if(!RegisterClass(&wc)) return -1;

HWND window = CreateWindowEx(0, TEXT("MAINWINDOW"), 0, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, instance, 0);
if(!window) return -1;
ShowWindow(window, SW_SHOW);
UpdateWindow(window);

MSG msg;
while(GetMessage(&msg, 0, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}

LRESULT CALLBACK StdWndProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
{
switch(message) {
case(WM_CREATE) : {
HWND stbox = CreateWindowEx(0, TEXT("STATIC"), TEXT("IDRES_STBOX"), WS_BORDER | WS_CHILD | WS_VISIBLE | SS_BITMAP, 10, 10, 350, 147, window, 0, basead, 0);
if(!stbox) return -1;
break;
}
case(WM_DESTROY) : {
PostQuitMessage(0);
break;
}
default :
return DefWindowProc(window, message, wparam, lparam);
}
return 0;
}



stdres.rc

#include<windows.h>

IDRES_STBOX BITMAP "stbox.bmp"

Share this post


Link to post
Share on other sites
Quote:
Original post by mattd
Give us some hints :)

What information does the crash give you? Accessing an invalid memory location? If so, what location? What line does the crash point to?

Also, try putting your code in [source] .. [/source] tags.


I am very new to win32 so I dont know whats wrong or where But I believe the problems would be occuring in lines:

- 89 to 118 (line 89 is "header = LoadBitmap....")
OR
- 257 to 279 (line 257 is "BITMAP bm;")

To explain what I am trying to do:
- I am trying to display a scaled bitmap in the window called stBox using StretchBlt(), although I have never done this so I dont know whats going wrong & why.

Share this post


Link to post
Share on other sites
Also to add to my previous post, if you need to stretch the image, you can use
SS_REALSIZECONTROL with MoveWindow to control how the image is stretched. You don't need to call StretchBlt since the static control is supposed to draw and stretch the bitmap for you.

Share this post


Link to post
Share on other sites
Quote:
Original post by yadango
That is not the correct way to use SS_BITMAP. Currently, you are trying to render the bitmap in the static control from within the parent window's WM_PAINT, for which you should not do. That BeginPaint call you have there is probably why it is crashing, since you pass it a window handle that is not the one receiving the current WM_PAINT message.

In general, the static control renders the bitmap for you and you shouldn't have to paint it yourself. See below for proper use of SS_BITMAP.


Thanks for ur reply :) I have compiled your code but it does not show the bitmap?

I understand what you are saying tho. If I load a bitmap to the main client window using the conventional method, is there a way to control its depth? What I mean is I want the bitmap to appear infront of a static rectangular control.

Presently if I load & display a bitmap on the main client window, it is displayed behind my controls(gray rectangle, edit boxes etc) so thats why I tried to load a bitmap to a window in order to control its depth & make it appear infront of other controls.

So to sum up, is there a way to make a bitmap appear above/infront of a control?

Share this post


Link to post
Share on other sites
Quote:
Original post by gretty
Quote:
Original post by mattd
Give us some hints :)

What information does the crash give you? Accessing an invalid memory location? If so, what location? What line does the crash point to?

Also, try putting your code in [source] .. [/source] tags.


I am very new to win32 so I dont know whats wrong or where But I believe the problems would be occuring in lines:

- 89 to 118 (line 89 is "header = LoadBitmap....")
OR
- 257 to 279 (line 257 is "BITMAP bm;")

To explain what I am trying to do:
- I am trying to display a scaled bitmap in the window called stBox using StretchBlt(), although I have never done this so I dont know whats going wrong & why.

With a little hacking (defining values for the resource identifiers), I got your program to compile and run fine on my machine. One thing I did change was to use a built-in system bitmap instead of one from a resource file with LoadBitmap. Are you sure your call to LoadBitmap is working OK?

Do you know how to use a debugger? (Are you using Visual C++?) You should run your program in a debugger, and see the exact line that it crashes on.

What happens if you comment out the WM_PAINT handler - does it still crash then? Take note of what yadango posted above about how you don't actually do the painting yourself, and the possible reason for your crash.

EDIT: Looks like you got/are getting this bit sorted, so the above might not apply anymore.


As an aside, your code for handling WM_COMMAND is a little strange; the two switches could be merged into one. Also, you should prefer to use radio buttons for the C->F / F->C selection, so you don't need to code that mutual-exclusion code there in the first place :)

Share this post


Link to post
Share on other sites
Thanks for all the help.

I have made some sucess, I have drawn the bitmap but its being displayed behind other controls.

Any adviced on how to make it appear infront of other controls?

A side note, maybe its just me but using Yadango's code, I cant get the bitmap to appear? it just shows the border of the window.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this