• Articles
  • How I Learned A Vital Borland C++ Coding
Published by
Mar 23, 2016

How I Learned A Vital Borland C++ Coding Technique I Couldn't Learn Alone

Score: 3.6/5 (200 votes)
*****
INTRODUCTION

Back in the late 1990s I was having trouble with a Borland Turbo C++ version 3.1
programming issue to make a Windows form auto-calculate after tabbing out of a numerical text box. In the early 1990s when I coded MS-DOS based procedural C application development, I could call Borland's technical support line and they would help me out free of charge. By the time I had this particular problem though, everything had changed for the worse. They had a 900 number I had to call for technical support. It was very expensive - $5USD per minute. Ouch! Their technical support people wouldn't even speak to me until I gave them my credit card number and they had authorized it. I sent them one fax about my problem and another and then another after that, because they kept losing them. Not only did they not solve my problem, but they also had the nerve to charge my credit card $92USD just for the time they spent running around trying to find my faxes. I was absolutely livid - this was the high watermark of aggravation for me.

THE ISSUE I HAD

The custom software work I did typically involved invoicing or order entry. The Windows form had to automatically recalculate the extended prices as well as totals. I knew how to do this with my old MS-DOS based programs. However, I was having a real tough time making this work in the object oriented (OOP) Windows environment. I knew the calculation had to be fired after the operator tabbed out of a numerical text box on the Windows form. I went online spending many hours researching this issue to no avail.

Nearing the end of my rope, I found an online newsgroup for Borland C++ programmers. I saw a post from a coder who was inquiring about a problem he had that was different from mine. I thought there might be a possibility that he could help me out with my problem since he was using Borland C++ version 4.5 software - a newer version than mine. He kindly sent me the code that showed how to fire an event in a Borland C++ version 4.5 Windows form after tabbing out of a text box. I studied it and was able to adapt it for my older Borland Turbo C++ version 3.1 compiler - thank goodness!

THE BORLAND C++ CODE THAT SOLVED IT

I honestly don't know what I would have done next had it not been for his help. It was imperative that I knew how to implement this programming technique. I knew from my days in the MS-DOS based programming world that customers would expect an invoice screen to automatically recalculate after numerical additions and/or changes had been made. Here are some code snippets that facilitate this operation from an actual Borland C++ 5.02 program I made:



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102

// declare the class.
//
// class TCbookDlg
// ~~~~~ ~~~~~~~~~~~~

 class TCbookDlg : public TDialog {

  public:

   TCbookDlg(TWindow* parent, TResId resId, TCbookStruct& transfer);
   TEdit *Edit1,*Edit2,*Edit3,*Edit4,*Edit5,*Edit6,*Edit7,*Edit8;
   TEdit *Edit9,*Edit10,*Edit11,*Edit12,*Edit13,*Edit14,*Edit15;

   // WMTab is the event to process specific math calculations
   // upon receiving the WM_GETDLGCODE message.
   LRESULT WMTab(WPARAM, LPARAM);  
   // WMChar is the event to process specific programming upon
   // receiving inputed keystrokes in the text box.
   LRESULT WMChar(WPARAM, LPARAM);     

  protected:

   // declare member functions of the TCbookDlg class.
   void  CmOk();
   void  Choose();
   void  Delete();
   void  Mchk();
   void  PrnReg();
   void  BalForw();
   void  PrnEnv();
   void  New();
   void  SVendor();
   void  SPaymentDate();
   void  SCheckNo();
   void  Reset();

  private:

   // declare objects of the TCbookDlg class.
   TPrinter* Printer;
   TListBox* ListBox;
   TComboBox* ComboBox;
   TComboBox* ComboBox2;
   TComboBox* ComboBox3;
   TComboBox* ComboBox4;
   TComboBox* ComboBox5;
   TComboBox* ComboBoxV;
   TComboBox* ComboBox6;
   TButtonGadget* G1;
   TButtonGadget* G2;
   TButtonGadgetEnabler* Ge1;
   TButtonGadgetEnabler* Ge2;
   void  SetupWindow();
   // declare the character arrays.
   char  Pdate[MAXDAT];
   char  Pnumber[MAXINVNO];
   char  Paid_amount[MAXSELL];
   char  Pdescr[MAXNOTE2];
   char  Paid_amount_discount[MAXSELL];
   char  Pnetdebit[MAXSELL];
   char  Pcheck[MAXSELL];
   char  Vendor[MAXCOMPANY2];
   char  ExpCode[MAXPAIDDISCOUNTSUMODE];
   char  TranType[MAXSELL];
   char  TranPaid[MAXANS];
   char  Void[MAXANS];
   char  Pcredit[MAXSELL];
   char  Sdt[MAXDAT];
   char  Edt[MAXDAT];
   char  BalUpdated_amount[MAXSELL];
   char  CutOffDate[MAXDAT];
   char  CheckMemo[MAXNOTE];
   char  Paiddate[MAXDAT];
   char  TranCleared[MAXANS];
   char  Rcount[MAXPASS];

  DECLARE_RESPONSE_TABLE(TCbookDlg);

 };

 // connect the TCbookDlg class member functions to their corresponding
 // identifiers as set in the resource file (not included here).
 DEFINE_RESPONSE_TABLE1(TCbookDlg, TDialog)
  EV_COMMAND(IDOK, CmOk),
  EV_COMMAND(IDC_PDELETE, Delete),
  EV_COMMAND(IDC_MCHECK, Mchk),
  EV_COMMAND(IDC_PRNREG, PrnReg),
  EV_COMMAND(IDC_BALFORW, BalForw),
  EV_COMMAND(IDC_PRNENV, PrnEnv),
  EV_COMMAND(IDC_CNEW, New),
  EV_COMMAND(IDC_RESET, Reset),
  EV_COMMAND(IDC_SVENDOR, SVendor),
  EV_COMMAND(IDC_SDATE, SPaymentDate),
  EV_COMMAND(IDC_SCHECKNO, SCheckNo),
  EV_LBN_SELCHANGE(IDC_LISTBOX, Choose),
  // WM_GETDLGCODE fires this event (WMTab) in the class TCbookDlg.
  EV_MESSAGE(WM_GETDLGCODE, WMTab),  
  // WM_CHAR fires this event (WMChar) in the class TCbookDlg.
  EV_MESSAGE(WM_CHAR, WMChar),       
 END_RESPONSE_TABLE;




This programming runs when the operator inputs keystrokes (numbers) into the text box. It screens out non-numeric characters or characters that aren't periods and sets the text box to a numerical zero making the operator start over with valid input.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

LRESULT
TEdAmt::WMChar(WPARAM cmd, LPARAM cmd2)
{
int  a;

DefaultProcessing();

for(a=0; a<MAXSELL; a++) Amount[a]=32;
GetSubText(Amount, 0, MAXSELL-1);

flag_variable = 1;

for(a=0; a<MAXSELL-1; a++) {
	if( ( Amount[a]<46 || Amount[a]>57 ) && Amount[a]>32 ) {
	Amount[a]=48;
	Amount[MAXSELL-1]=0;
	SetText(Amount);
	SetSelection(0, MAXSELL-1);
	}
}

return TRUE;

}




This code runs when the operator tabs out of a numerical based text box that accepts a dollar amount



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

LRESULT
TEdAmt::WMTab(WPARAM cmd, LPARAM cmd2)
{
// declare local variables used in the formatting and math processing.
int   r,f,z,a,y;

if ( cmd == VK_TAB && flag_variable == 1 ) {

y=0;
if ( Amount[0]<=57 && Amount[1]<=57 && Amount[2]<=57 && Amount[3]<=57 && Amount[4]<=57 && Amount[5]<=57 && Amount[6]<=57 && Amount[7]<=57 && Amount[8]<=57 && Amount[9]<=57 ) y=1;

	if ( y == 1 ) {

		r=0;
		do {
			if(Amount[9]<46 || Amount[9]>57) {
			for(f=9; f>0; f--) Amount[f]=Amount[f-1];
			Amount[0]=32;
			}
		r++;
		} while(r<10);

		r=0;
		if ( Amount[7]!=46 && Amount[8]!=46 && Amount[9]!=46 ) {
			for(f=0; f<9; f++) Amount[f]=Amount[f+1];
			Amount[9]=46;
			for(f=0; f<9; f++) Amount[f]=Amount[f+1];
			Amount[9]=48;
			for(f=0; f<9; f++) Amount[f]=Amount[f+1];
			Amount[9]=48;
			r=1;
		}

		if ( Amount[9]==46 && r==0 ) {
			for(f=0; f<9; f++) Amount[f]=Amount[f+1];
			Amount[9]=48;
			for(f=0; f<9; f++) Amount[f]=Amount[f+1];
			Amount[9]=48;
			r=1;
		}

		if ( Amount[8]==46 && r==0 ) {
			for(f=0; f<9; f++) Amount[f]=Amount[f+1];
			Amount[9]=48;
		}

		z=0;
		if ( ( Amount[0]<48 || Amount[0]>57 ) && Amount[0]>32 ) z=1;
		if ( ( Amount[1]<48 || Amount[1]>57 ) && Amount[1]>32 ) z=1;
		if ( ( Amount[2]<48 || Amount[2]>57 ) && Amount[2]>32 ) z=1;
		if ( ( Amount[3]<48 || Amount[3]>57 ) && Amount[3]>32 ) z=1;
		if ( ( Amount[4]<48 || Amount[4]>57 ) && Amount[4]>32 ) z=1;
		if ( ( Amount[5]<48 || Amount[5]>57 ) && Amount[5]>32 ) z=1;
		if ( ( Amount[6]<48 || Amount[6]>57 ) && Amount[6]>32 ) z=1;
		if ( Amount[7]!=46 ) z=1;
		if ( ( Amount[8]<48 || Amount[8]>57 ) && Amount[8]>32 ) z=1;
		if ( ( Amount[9]<48 || Amount[9]>57 ) && Amount[9]>32 ) z=1;

		if(z==0) {
		r=0;
			do {
			r++;
			} while(Amount[r]==32 && r<10);
		if(r<10) Amount[r-1]='$';
		}

		if ( z>0 ) {
		for(a=0; a<MAXSELL; a++) Amount[a]=32;
		Amount[6]=48;
		Amount[7]=46;
		Amount[8]=48;
		Amount[9]=48;
		}

Amount[MAXSELL-1]=0;
SetText(Amount);

flag_variable = 0;

Parent->SendMessage(WM_GETDLGCODE, 0, 0);

	}

}

DefaultProcessing();

//return TRUE;

}




This is fired after the WM_GETDLGCODE message reaches the parent window. The math will be performed and the text box will be updated with the calculated result.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85

LRESULT
TCbookDlg::WMTab(WPARAM cmd, LPARAM cmd2)
{
  int        a,r;
  long int   paidsum,paiddiscountsum,convert_to_integer[10];
  char       Updated_amount[MAXSELL];
  ldiv_t     n;

  streambuf  *inn = cin.rdbuf();

  ifpstream  ivfile;

  for(a=0; a<MAXSELL; a++) Paid_amount[a]=32;
  for(a=0; a<MAXSELL; a++) Paid_amount_discount[a]=32;

  GetDlgItemText(IDC_PAID_AMOUNT, Paid_amount, MAXSELL);
  GetDlgItemText(IDC_PAID_AMOUNT_DISCOUNT, Paid_amount_discount, MAXSELL);

  for(a=0; a<MAXSELL-1; a++) {
  convert_to_integer[a]=0;
  if(Paid_amount[a]==48) convert_to_integer[a]=0;
  if(Paid_amount[a]==49) convert_to_integer[a]=1;
  if(Paid_amount[a]==50) convert_to_integer[a]=2;
  if(Paid_amount[a]==51) convert_to_integer[a]=3;
  if(Paid_amount[a]==52) convert_to_integer[a]=4;
  if(Paid_amount[a]==53) convert_to_integer[a]=5;
  if(Paid_amount[a]==54) convert_to_integer[a]=6;
  if(Paid_amount[a]==55) convert_to_integer[a]=7;
  if(Paid_amount[a]==56) convert_to_integer[a]=8;
  if(Paid_amount[a]==57) convert_to_integer[a]=9;
  }
  paidsum = convert_to_integer[0]*100000000 + convert_to_integer[1]*10000000 + convert_to_integer[2]*1000000 + convert_to_integer[3]*100000 + convert_to_integer[4]*10000 + convert_to_integer[5]*1000 + convert_to_integer[6]*100 + convert_to_integer[8]*10 + convert_to_integer[9]*1;

	  for(a=0; a<MAXSELL-1; a++) {
	  convert_to_integer[a]=0;
	  if(Paid_amount_discount[a]==48) convert_to_integer[a]=0;
	  if(Paid_amount_discount[a]==49) convert_to_integer[a]=1;
	  if(Paid_amount_discount[a]==50) convert_to_integer[a]=2;
	  if(Paid_amount_discount[a]==51) convert_to_integer[a]=3;
	  if(Paid_amount_discount[a]==52) convert_to_integer[a]=4;
	  if(Paid_amount_discount[a]==53) convert_to_integer[a]=5;
	  if(Paid_amount_discount[a]==54) convert_to_integer[a]=6;
	  if(Paid_amount_discount[a]==55) convert_to_integer[a]=7;
	  if(Paid_amount_discount[a]==56) convert_to_integer[a]=8;
	  if(Paid_amount_discount[a]==57) convert_to_integer[a]=9;
	  }
	  paiddiscountsum = convert_to_integer[0]*100000000 + convert_to_integer[1]*10000000 + 	convert_to_integer[2]*1000000 + convert_to_integer[3]*100000 + convert_to_integer[4]*10000 + 	convert_to_integer[5]*1000 + convert_to_integer[6]*100 + convert_to_integer[8]*10 + 	convert_to_integer[9]*1;

	  paidsum = paidsum - paiddiscountsum;

		  for(a=0; a<MAXSELL-1; a++) Updated_amount[a]=32;
		  Updated_amount[9]=48;
		  Updated_amount[8]=48;
		  Updated_amount[7]=46;
		  Updated_amount[6]=48;
		  r=9;
		  do {
		  n=ldiv(paidsum,10L);
		  paidsum=n.quot;
		  if(n.rem==0) Updated_amount[r]=48;
		  if(n.rem==1) Updated_amount[r]=49;
		  if(n.rem==2) Updated_amount[r]=50;
		  if(n.rem==3) Updated_amount[r]=51;
		  if(n.rem==4) Updated_amount[r]=52;
		  if(n.rem==5) Updated_amount[r]=53;
		  if(n.rem==6) Updated_amount[r]=54;
		  if(n.rem==7) Updated_amount[r]=55;
		  if(n.rem==8) Updated_amount[r]=56;
		  if(n.rem==9) Updated_amount[r]=57;
		  r--;
		  if(r==7) r--;
		  } while(paidsum>0);

			  r=0;
			  do {
			  r++;
			  } while(Updated_amount[r]==32 && r<MAXSELL-1);
			  Updated_amount[r-1]='$';

			  Updated_amount[MAXSELL-1]=0;
			  Edit6->SetText(Updated_amount);

}




CONCLUSION

Just when you think all is lost, you will find an educational resource or a kind soul online to help you out. If you can't resolve it on your own, the internet is filled with nice people who are ready to give you a helping hand. It is by far the best available resource. What with the problem I had, the internet could not have arrived soon enough to save me from the cost prohibitive (and not always useful) world of paid technical support. Thankfully, that option has gone the way of the typewriter.