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);
}