This is my first windows app. I basically have my whole program written except for fixing a few lil problems and writing the code for 2 of my buttons. Could someone help me with the "Hex to Decimal" button code? or give some kind of example? my professor helped with the add button and i did the others, but i cant figure out this one :(

// hexcalcDlg.cpp : implementation file
//

#include "stdafx.h"
#include "hexcalc.h"
#include "hexcalcDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CHexcalcDlg dialog

CHexcalcDlg::CHexcalcDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CHexcalcDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CHexcalcDlg)
	m_op1 = _T("");
	m_op2 = _T("");
	m_result = _T("");
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CHexcalcDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CHexcalcDlg)
	DDX_Text(pDX, IDC_OP1, m_op1);
	DDV_MaxChars(pDX, m_op1, 10);
	DDX_Text(pDX, IDC_OP2, m_op2);
	DDV_MaxChars(pDX, m_op2, 10);
	DDX_Text(pDX, IDC_RESULT, m_result);
	DDV_MaxChars(pDX, m_result, 10);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CHexcalcDlg, CDialog)
	//{{AFX_MSG_MAP(CHexcalcDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_ADD, OnAdd)
	ON_BN_CLICKED(IDC_CLEAR, OnClear)
	ON_BN_CLICKED(IDC_DECTOHEX, OnDectohex)
	ON_BN_CLICKED(IDC_DIVIDE, OnDivide)
	ON_BN_CLICKED(IDC_HEXTODEC, OnHextodec)
	ON_BN_CLICKED(IDC_MULTIPLY, OnMultiply)
	ON_BN_CLICKED(IDC_SUBTRACT, OnSubtract)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CHexcalcDlg message handlers

BOOL CHexcalcDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CHexcalcDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CHexcalcDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CHexcalcDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CHexcalcDlg::OnAdd() 
{
	// TODO: Add your control notification handler code here
	GetDlgItemText(IDC_OP1, m_op1);
	GetDlgItemText(IDC_OP2, m_op2);
	int op1 = atoi((LPCTSTR) m_op1);
	int op2 = atoi((LPCTSTR) m_op2);
	int result = op1 + op2;
	m_result.Format("%d", result);
	SetDlgItemText(IDC_RESULT, m_result);

}

void CHexcalcDlg::OnClear() 
{
	// TODO: Add your control notification handler code here
	m_op1 = _T("");
	SetDlgItemText(IDC_OP1, m_op1);
	m_op2 = _T("");
	SetDlgItemText(IDC_OP2, m_op2);
	m_result = _T("");
	SetDlgItemText(IDC_RESULT, m_result);
}

void CHexcalcDlg::OnDectohex() 
{
	// TODO: Add your control notification handler code here
	
}

void CHexcalcDlg::OnDivide() 
{
	// TODO: Add your control notification handler code here
	GetDlgItemText(IDC_OP1, m_op1);
	GetDlgItemText(IDC_OP2, m_op2);
	int op1 = atoi((LPCTSTR) m_op1);
	int op2 = atoi((LPCTSTR) m_op2);
	if(op2 == 0)
	{
		AfxMessageBox("operand 2 is zero!");
		m_result = "unknown";
	}
	else
	{
		int result = op1 / op2;
		m_result.Format("%d", result);
	}
	SetDlgItemText(IDC_RESULT, m_result);
}


void CHexcalcDlg::OnHextodec() 
{
	// TODO: Add your control notification handler code here
	
}

void CHexcalcDlg::OnMultiply() 
{
	// TODO: Add your control notification handler code here
	GetDlgItemText(IDC_OP1, m_op1);
	GetDlgItemText(IDC_OP2, m_op2);
	int op1 = atoi((LPCTSTR) m_op1);
	int op2 = atoi((LPCTSTR) m_op2);
	int result = op1 * op2;
	m_result.Format("%d", result);
	SetDlgItemText(IDC_RESULT, m_result);	
}

void CHexcalcDlg::OnSubtract() 
{
	// TODO: Add your control notification handler code here
	GetDlgItemText(IDC_OP1, m_op1);
	GetDlgItemText(IDC_OP2, m_op2);
	int op1 = atoi((LPCTSTR) m_op1);
	int op2 = atoi((LPCTSTR) m_op2);
	int result = op1 - op2;
	m_result.Format("%d", result);
	SetDlgItemText(IDC_RESULT, m_result);	
}
void CHexcalcDlg::ConvertDecToHex(CString& str_out, int number_in) 
{
	int index = 4;
	str_out = "     ";
	char chr;
	while(number_in > 0);
	{
		int remainder = number_in % 16;
		number_in /= 16;
		switch(remainder)
		{
		case 0:
			chr = '0';
			break;
		case 1:
			chr = '1';
			break;
		case 2:
			chr = '2';
			break;
		case 3:
			chr = '3';
			break;
		case 4:
			chr = '4';
			break;
		case 5:
			chr = '5';
			break;
		case 6:
			chr = '6';
			break;
		case 7:
			chr = '7';
			break;
		case 8:
			chr = '8';
			break;
		case 9:
			chr = '9';
			break;
		case 10:
			chr = 'A';
			break;
		case 11:
			chr = 'B';
			break;
		case 12:
			chr = 'C';
			break;
		case 13:
			chr = 'D';
			break;
		case 14:
			chr = 'E';
			break;
		case 15:
			chr = 'F';
			break;
		default:
			AfxMessageBox("Invalid number");
		}
	str_out.SetAt(index, chr);
	index --;
	}
}

int CHexcalcDlg::ConvertHexToDec(CString str) 
{
	int value;
	int number = 0;
	int col = 1;
	int length = str.GetLength();
	for (int i = 0; i < length; i++)
	{
		char chr = str[length - 1 -i];
		switch(chr)
		{
		case '0':
			value = 0;
			break;
		case '1':
			value = 1;
			break;
		case '2':
			value = 2;
			break;
		case '3':
			value = 3;
			break;
		case '4':
			value = 4;
			break;
		case '5':
			value = 5;
			break;
		case '6':
			value = 6;
			break;
		case '7':
			value = 7;
			break;
		case '8':
			value = 8;
			break;
		case '9':
			value = 9;
			break;
		case 'A':
		case 'a':
			value = 10;
			break;
		case 'B':
		case 'b':
			value = 11;
			break;
		case 'C':
		case 'c':
			value = 12;
			break;
		case 'D':
		case 'd':
			value = 13;
			break;
		case 'E':
		case 'e':
			value = 14;
			break;
		case 'F':
		case 'f':
			value = 15;
			break;
		default:
			AfxMessageBox("Invalid character");
		}
		number += value * col;
		col *= 16;
	}
	return number;
}

oh the button should take the hex number entered into op1 and convert it, and display it in the result text window. thx for any help.

I'm not at my own computer so I can't test the code, but the idea is to steer you in the right direction anyway. If you have the pro version of VC++ have a look at the disassembled code. You'll see why I let the switch statements fall through the way I do. In any event, trace through step by step and you'll see the logic.

The switch statements you constructed are not wrong, it's just they generate a little more code than necessary.

int CHexcalcDlg::ConvertHexToDec(CString str) 
{
	int number = 0;
	int length = str.GetLength();
 
	for (int i = 0; i < length; i++)
	{
		number <<= 4;			 // Shift bits left 4 times (Number * 16)
		char value = str[i] & 0x5f;
 
		switch(value)	 // Get character and convert to uppercase
		{
		case '0':
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
		 Number += int (value) & 15;
		 break;
 
		case 'A':
		case 'B':
		case 'C':
		case 'D':
		case 'E':
		case 'F':
		 Number += int (value & 15) + 9;
		 break;
 
		default:
			AfxMessageBox("Invalid character");
		}
	}
	return number;
}
[B]#include[/B] <stdio.h>
[B]#include[/B] <stdlib.h>

[B]int[/B] [B]main[/B]([B]void[/B])
{
   [B]const[/B] [B]char[/B] text[] = "3E8";
   [B]int[/B] value = [B]strtol[/B](text, NULL, 16);
   [B]printf[/B]("%s = %d\n", text, value);
   [B]return[/B] 0;
}

/* my output
3E8 = 1000
*/

i need help bad...can someone please tell me what im doing wrong here?

void CHexcalcDlg::OnHextodec() 
{
	// TODO: Add your control notification handler code here
	GetDlgItemText(IDC_OP1, m_op1);
	m_result = ConvertHexToDec(m_op1);
	SetDlgItemText(IDC_RESULT, m_result);
}

i cant figure it out. when i run the program and try to convert something it gives me weird characters :/

ConvertHexToDec returns an int try SetDlgItemInt instead.

void CHexcalcDlg::OnHextodec() 
{
	// TODO: Add your control notification handler code here
	GetDlgItemText(IDC_OP1, m_op1);
	SetDlgItemInt(IDC_RESULT, ConvertHexToDec(m_op1) , TRUE);
}

Please note, I removed mResult getting the result of ConvertHexToDec since all you really do is display the answer and converting the int to string and displaying the string is sort of a hassle.

when i try that i get the error...
C:\Documents and Settings\owner\My Documents\C++\hexcalc\hexcalcDlg.cpp(244) : error C2664: 'SetDlgItemInt' : cannot convert parameter 2 from 'class CString' to 'unsigned int'
No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called

I'm not much of an MFC coder myself and can't test ATM, but try this:

void CHexcalcDlg::OnHextodec()
{
// TODO: Add your control notification handler code here
GetDlgItemText(IDC_OP1, m_op1);
SetDlgItemInt(IDC_RESULT, (UINT)ConvertHexToDec(m_op1) , TRUE);
}

oh thanks! that seems to have worked. now i just have to fix the rest of my little problems and i'll be good to go.

now having trouble with the DecToHex button :/ this is what i tried:

void CHexcalcDlg::OnDectohex() 
{
	// TODO: Add your control notification handler code here
	GetDlgItemText(IDC_OP1, m_op1);
	ConvertDecToHex(m_result, atoi((LPCTSTR) m_op1));
	SetDlgItemText(IDC_RESULT, m_result);
}

when i run it the program freezes though :sad: can someone point out my mistake to me please?

Try this, i think atoi() might be the problem if your dealing with unicode strings.

[left]void CHexcalcDlg::OnDectohex() 
{
// TODO: Add your control notification handler code here
GetDlgItemText(IDC_OP1, m_op1);
ConvertDecToHex(m_result, _ttoi((LPCTSTR) m_op1));
SetDlgItemText(IDC_RESULT, m_result);
} [/left]

it still freezes, i don't know what else to try :(...but i know something has to be wrong with that line...

Since the only function that is liable to freeze is ConvertDectoHex (the other functions are standard API), you need to go into that function and find the exact line that is causing the problem.

Edit:

After reviewing the function one thing I notice. You are passing in m_result to the function but why is it intializing the parameter? Why not just delcare str_out as a local CString and return it? If you are passing it by reference and intialzing the paramater str_out, it's not really nessisary to pass it at all.

I just read what you said and got confused...maybe its a little too late for me to be trying to figure this stuff out. I think i should take a break and start back on it tomorrow. Thanks for all your help though.

sorry to confuse you, its hard to explain let me show you:

void CHexcalcDlg::ConvertDecToHex(CString& str_out, int number_in) 
{
	int index = 4;
	str_out = "	 ";
	char chr;
	while(number_in > 0);

see the line:

str_out = "	 ";

That means whatever you pass in to str_out will be set to 5 spaces, so why pass it in at all? ;)

Instead I'm suggesting something along the lines of:

void CHexcalcDlg::ConvertDecToHex(int number_in) 
{
    int index = 4;
    CString str_out = "	 ";
    char chr;
    while(number_in > 0);

Anyways -- since it's freezing and not crashing and we have logically concluded that the cause of the freeze is the ConvertDectoHex function, looking at that function the only real thing that could cause a freeze is the loop. It's probally infinite.

the statment:
number_in /= 16;

the result of the division is the largest integer (in magnitude, disregarding the sign) that is less than the exact value the division operation would yield, therefore, it will always be greater than 0 (unless a number 0 or less is passed in) casuing an infinite loop. To be sure, test it by passing in a 0 to the ConvertDecToHex function and see if it no longer freezes.

well i talked to the professor about it too. and thats how he said to do it :/ so i dont know. i was just going by what he said.

he told me to make sure i set it to exactly 5 spaces.

i've updated my post on that response, check it out. The spaces thing was a typo, it wasn't the intent of my focus. The point is you are passing in a value to str_out then immedietly deleting that value by changing it to 5 blank spaces. This means that you don't really need to pass anything in for that parameter becuase it will always just be set to 5 spaces. I was suggesting removing it as a parameter and delclaring it locally (as shown in my post).

Let me know how testing goes with the division and the loop.

CString CHexcalcDlg::ConvertDecToHex(int number_in)
{
return ltostr(number_in,16);
}

rewrote the whole function give that a try.
don't forget

#include <stdlib.h>

Note: I updated the signature/prototype. It now returns "CString" and onyl has 1 parameter. You may want to reflect these changes in the corresponding header file.

Usage is also different try:

[left]void CHexcalcDlg::OnDectohex() [/left]
{
	// TODO: Add your control notification handler code here
	GetDlgItemText(IDC_OP1, m_op1);
SetDlgItemText(IDC_RESULT, (LPTCSTR)ConvertDecToHex(_ttoi((LPCTSTR) m_op1)));
}
[left]

[/left]

i tried that, including the <stdlib.h> and everything. and i get the error that ltostr is an undeclared identifier.

is that the only other thing i need to include. i'm still getting the same error.

i'm still stuck on this program. It still freezes when I do the decimal to hex button. Could i just be putting the wrong things in the parenthesis for the function ConvertDecToHex(CString& str_out, int number_in)? I've tried everything that has been suggested for me and also everything that I could think of myself, but still no luck :(

This article has been dead for over six months. Start a new discussion instead.