• 文章
  • 我如何学会一项重要的 Borland C++ 编程技巧
发布
2016年3月23日

我如何学会一项我无法独自学会的重要 Borland C++ 编程技巧

评分:3.6/5(202 票)
*****
引言

早在 1990 年代末,我使用 Borland Turbo C++ 3.1 版本时遇到了一个难题。
我想解决一个编程问题,就是让一个 Windows 表单在用户按 Tab 键离开一个数字文本框后自动进行计算。在 1990 年代初,当我用基于 MS-DOS 的过程式 C 语言进行应用程序开发时,我可以拨打 Borland 的技术支持热线,他们会免费帮助我。但到我遇到这个特定问题时,一切都变得糟糕了。他们设立了一个 900 号码,我必须打电话寻求技术支持。费用非常昂贵——每分钟 5 美元。天哪!他们的技术支持人员甚至在我提供信用卡号并获得授权之前都不肯和我说话。我给他们发了一份关于我问题的传真,然后又发了一份,再后来又发了一份,因为他们总是弄丢。他们不仅没有解决我的问题,还厚颜无耻地从我的信用卡里扣了 92 美元,仅仅因为他们花时间到处找我的传真。我气得火冒三丈——这对我来说真是忍无可忍的顶点。

我遇到的问题

我做的定制软件工作通常涉及发票或订单录入。Windows 表单必须能自动重新计算扩展价格和总计。我知道如何在我以前的基于 MS-DOS 的程序中实现这一点。然而,在面向对象(OOP)的 Windows 环境中,我遇到了很大的困难。我知道这个计算必须在操作员按 Tab 键离开 Windows 表单上的一个数字文本框后触发。我花了很多时间在网上研究这个问题,但都无济于事。

就在我快要绝望的时候,我找到了一个 Borland C++ 程序员的在线新闻组。我看到一个程序员发帖询问一个与我不同的问题。我想他或许能帮我解决我的问题,因为他用的是 Borland C++ 4.5 版本的软件——比我的版本更新。他很友好地把代码发给了我,展示了如何在 Borland C++ 4.5 版本的 Windows 表单中,在按 Tab 键离开文本框后触发一个事件。我研究了它,并成功地将其应用到我更旧的 Borland Turbo C++ 3.1 编译器上——谢天谢地!

解决问题的 BORLAND C++ 代码

说实话,如果没有他的帮助,我真不知道接下来该怎么办。掌握如何实现这种编程技巧对我来说至关重要。从我从事基于 MS-DOS 编程的日子起,我就知道客户会期望发票屏幕在添加和/或更改数字后能自动重新计算。以下是一些代码片段,它们来自我实际制作的一个 Borland C++ 5.02 程序,用于实现此操作。



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;




当操作员在文本框中输入按键(数字)时,这段程序会运行。它会过滤掉非数字字符或非句点的字符,并将文本框设置为数字零,让操作员重新输入有效的内容。



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;

}




当操作员按 Tab 键离开一个接受美元金额的数字文本框时,这段代码会运行。



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;

}




这在 WM_GETDLGCODE 消息到达父窗口后被触发。将执行数学运算,并且文本框将更新为计算出的结果。



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

}




结论

就在你以为一切都完了的时候,你会在网上找到一个教育资源或一个好心人来帮助你。如果你自己解决不了,互联网上充满了乐于伸出援手的好人。这无疑是最好的可用资源。对于我遇到的那个问题,互联网的出现真是及时雨,把我从那个费用高得令人望而却步(而且不总是有用)的付费技术支持世界中拯救了出来。谢天谢地,那个选项已经像打字机一样被淘汰了。