• 文章
  • 我如何學會一項重要的 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);

}




結論

就在你以為一切都完了的時候,你會在網上找到一個教育資源或一個好心人來幫助你。如果你自己解決不了,網際網路上充滿了樂於伸出援手的好人。這無疑是最好的可用資源。對於我遇到的那個問題,網際網路的出現真是及時雨,把我從那個費用高得令人望而卻步(而且不總是有用)的付費技術支援世界中拯救了出來。謝天謝地,那個選項已經像打字機一樣被淘汰了。