• 文章
  • Turbo C++ 3.1 列表框代码示例
发布
2014 年 3 月 6 日(最后更新:2014 年 6 月 14 日)

Turbo C++ 3.1 列表框代码示例

评分:3.5/5 (80 票)
*****
引言

在 20 世纪 90 年代,我还在使用旧的 Borland Turbo C++ 3.1 平台为 Windows 操作系统进行商业 编程应用程序开发 时,我经常需要创建“列表框”。我用它们来存放各种东西,例如客户、库存项目、簿记交易、发票等等。




下面我将举例说明我是如何创建的。这个特别的列表框将用于存储供应商列表的单选列表框控件。是的,与 Microsoft Visual Studio 等最佳开发平台相比,它很简陋,但它确实有效!

声明所需类

首先,这是项目 C++ 源文件中的“TVendDlg”类的类声明,该类将创建供应商的数据录入屏幕。

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

// declare “TvendDlg”, a TDialog descendant
class TVendDlg : public TDialog {
public:
    virtual void SetupWindow();
    virtual void VendDel(RTMessage Msg)
      = [ID_FIRST + ID_DELX_];
    virtual void VendChs(RTMessage Msg)
      = [ID_FIRST + ID_CHS1_];
    virtual void VendPrn(RTMessage Msg)
      = [ID_FIRST + ID_VPRN_];
    char Vncode[MAXCCODE];
    char Vnname[MAXCNAME];
    char Vnstreet[MAXCSTREET];
    char Vnstreet2[MAXCSTREET];
    char Vncity[MAXCCITY];
    char Vnstate[MAXCSTATE];
    char Vnzip[MAXCZIP];
    char VnTell1[MAXCTF1];
    char VnFax1[MAXCTF1];
    char Vnatt[MAXATT];
    char VnPaytrm[MAXTERM];
    char VnNote1[MAXNOTE];
    char VnNote2[MAXNOTE];

TEdit *Edit1,*Edit2,*Edit3,*Edit4,*Edit5,*Edit6,*Edit7,*Edit8,*Edit9,*Edit10,
*Edit11,*Edit12,*Edit13;

    TVendDlg(PTWindowsObject AParent, LPSTR name);
    virtual BOOL CanClose();
};


接下来,您将看到“ListBoxDialog”类,它将用于填充列表框并从中检索用户的选择。

1
2
3
4
5
6
7
8
9
10
11
12

// declare “ListBoxDialog”, a TDialog descendant
class ListBoxDialog : public TDialog
{
public:
  ListBoxDialog(PTWindowsObject AParent, LPSTR AName)
    : TDialog(AParent, AName) {};
  virtual void SetupWindow();
  virtual void HandleListBoxMsg(RTMessage Msg)
    = [ID_FIRST + ID_LISTBOX];
};


点击“选择”按钮激活列表框

“TVendDlg”类的这个成员函数将在点击供应商数据录入屏幕上的“选择”按钮时触发。 “选择”按钮下的命令 “GetApplication()->ExecDialog(new ListBoxDialog(this, "VENDORDIALOG"));” 将实例化用于帮助填充列表框的“ListBoxDialog”类。

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

void TVendDlg::VendChs(RTMessage)
{
  int       a;
  streambuf *inn = cin.rdbuf();
  ifpstream ifile;
  Globalvar = 0;
  GetApplication()->ExecDialog(new ListBoxDialog(this, "VENDORDIALOG"));

  	// if the Global variable, “Globalvar” is set to 1 from the
	// “ListBoxDialog::HandleListBoxMsg(RTMessage Msg)” member
	// function, then proceed.
  	if( Globalvar == 1) {

  	// set the global flag, “hasbeenselected”, to signal a vendor
	// has been selected from the list box.
  	hasbeenselected = 1;

  		// display the retrieved vendor data in the vendor data entry
  		// screen after the selection in the list box has been clicked
  		// by the user. the data for the selected vendor will be 
                // assigned to the edit controls in the vendor data entry 
                // screen.
  		ifile.open("vend.txt", ios::in | ios::binary);
  		inn = ifile.rdbuf();
		// position the filestream ofthe binary vendor
		// data file to the calculated filestream offset
		// value of the selected list box item.
  		inn -> seekpos(offsetvar, ios::in);
  		for(a=0; a<MAXCCODE-1; a++) Vncode[a] = ifile.readByte();
  		Vncode[MAXCCODE-1] = 0;
  		Edit1->SetText(Vncode);
  		for(a=0; a<MAXCNAME-1; a++) Vnname[a] = ifile.readByte();
  		Vnname[MAXCNAME-1] = 0;
  		Edit2->SetText(Vnname);
  		for(a=0; a<MAXCSTREET-1; a++) Vnstreet[a] = ifile.readByte();
  		Vnstreet[MAXCSTREET-1] = 0;
  		Edit3->SetText(Vnstreet);
  		for(a=0; a<MAXCSTREET-1; a++) Vnstreet2[a] = ifile.readByte();
  		Vnstreet2[MAXCSTREET-1] = 0;
  		Edit4->SetText(Vnstreet2);
  		for(a=0; a<MAXCCITY-1; a++) Vncity[a] = ifile.readByte();
  		Vncity[MAXCCITY-1] = 0;
  		Edit5->SetText(Vncity);
  		for(a=0; a<MAXCSTATE-1; a++) Vnstate[a] = ifile.readByte();
  		Vnstate[MAXCSTATE-1] = 0;
  		Edit6->SetText(Vnstate);
  		for(a=0; a<MAXCZIP-1; a++) Vnzip[a] = ifile.readByte();
  		Vnzip[MAXCZIP-1] = 0;
  		Edit7->SetText(Vnzip);
  		for(a=0; a<3; a++) VnTell1[a] = ifile.readByte();
  		VnTell1[3] = '-';
  		for(a=0; a<3; a++) VnTell1[4+a] = ifile.readByte();
  		VnTell1[7] = '-';
  		for(a=0; a<4; a++) VnTell1[8+a] = ifile.readByte();
  		VnTell1[MAXCTF1-1] = 0;
  		Edit8->SetText(VnTell1);
  		for(a=0; a<3; a++) VnFax1[a] = ifile.readByte();
  		VnFax1[3] = '-';
  		for(a=0; a<3; a++) VnFax1[4+a] = ifile.readByte();
  		VnFax1[7] = '-';
  		for(a=0; a<4; a++) VnFax1[8+a] = ifile.readByte();
  		VnFax1[MAXCTF1-1] = 0;
  		Edit9->SetText(VnFax1);
  		for(a=0; a<MAXATT-1; a++) Vnatt[a] = ifile.readByte();
  		Vnatt[MAXATT-1] = 0;
  		Edit10->SetText(Vnatt);
  		for(a=0; a<MAXTERM-1; a++) VnPaytrm[a] = ifile.readByte();
  		VnPaytrm[MAXTERM-1] = 0;
  		Edit11->SetText(VnPaytrm);
  		for(a=0; a<MAXNOTE-1; a++) VnNote1[a] = ifile.readByte();
  		VnNote1[MAXNOTE-1] = 0;
  		Edit12->SetText(VnNote1);
  		for(a=0; a<MAXNOTE-1; a++) VnNote2[a] = ifile.readByte();
  		VnNote2[MAXNOTE-1] = 0;
  		Edit13->SetText(VnNote2);
  		ifile.close();

  	}

  }


构造列表框并填充它

这是来自项目的资源文件,它构造了供应商列表框的布局。该资源名为“VENDORDIALOG”。请注意,它使用了固定宽度的 Courier 字体,这将使列显示得整齐且均匀。

1
2
3
4
5
6
7
8
9
10
11

VENDORDIALOG DIALOG DISCARDABLE LOADONCALL PURE MOVEABLE 30, 18, 208, 108
STYLE WS_POPUP | WS_DLGFRAME
FONT 10, "COURIER"
BEGIN
  CONTROL "Vendor Name                   Vend. Code   ", 10055, "static", SS_LEFT | WS_CHILD, 20, 3, 188, 8
  CONTROL "&Exit" IDCANCEL, "BUTTON", WS_CHILD | WS_VISIBLE | WS_TABSTOP, 20, 93, 48, 12
  CONTROL "Vendor Listing", 10056, "static", SS_LEFT | WS_CHILD, 75, 93, 200, 8
  CONTROL "LISTBOX" ID_LISTBOX, "LISTBOX", WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL | 0x3L, 20, 15, 168, 73
END


接下来,我将展示“ListBoxDialog”类的“SetupWindow”成员函数,它将使用来自供应商二进制数据文件“vend.txt”的数据填充列表框。命令 “SendDlgItemMsg(ID_LISTBOX, LB_ADDSTRING, 0, (LONG)char_array);” 将定义的常量“ID_LISTBOX”标识的列表框中的每个供应商名称和供应商代码对添加为一行。

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

void ListBoxDialog::SetupWindow()
{
  long int   fileoffset, sizeofdatafile;
  int        a,fileinfo,t;
  streambuf  *inn = cin.rdbuf();
  ifpstream  ifile;

  // this will loop around the “vend.txt” binary data file of
  // vendors and add a data record to the list box, which includes
  // vendor name and vendor code.
  fileinfo = open("vend.txt", ios::in | ios::binary);
  sizeofdatafile = filelength(fileinfo);
  close(fileinfo);
  ifile.open("vend.txt", ios::in | ios::binary);
  inn = ifile.rdbuf();
  fileoffset  = 0;
  do {

        // initialize the char array, “char_array”, with space characters.	
     	for(a=0; a<100; a++) char_array[a] = 32;

		// read the vendor name and vendor code from the file stream.
  		inn -> seekpos(fileoffset, ios::in);
    		for(a=0; a<MAXCCODE-1; a++) char_array[32+a] = ifile.readByte();
  		inn -> seekpos(fileoffset+MAXCCODE-1, ios::in);
  		for(a=0; a<MAXCNAME-1; a++) char_array[a] = ifile.readByte();

			// mask out white space characters.
  			for(a=0; a<100; a++) {
  			if(char_array[a]<33 || char_array[a]>126) char_array[a] = 32;
  			}

				// read the sequential position of the record in the binary text file.
  				inn -> seekpos(fileoffset+VENDLEN-5, ios::in);
  				for(a=0; a<5; a++) char_array[70+a] = ifile.readByte();
				// null space the end of the char array to  suppress trailing random chars.
  				char_array[99] = 0;

					// convert the char array to lower case.
  					strlwr(char_array);

						// add the vendor name and vendor code pair to the list box control.
  						SendDlgItemMsg(ID_LISTBOX, LB_ADDSTRING, 0, (LONG) char_array);

  // advance to the next record in the binary text file.		
  fileoffset = fileoffset + VENDLEN;

  } while(fileoffset<sizeofdatafile);

  ifile.close();

}


最后,“ListBoxDialog”类的“HandleListBoxMsg”成员函数将在用户单击列表框中的选定行时触发。此时,列表框将消失,并且所选供应商记录的文件流偏移量将通过选定的“索引”组件计算出来。然后,此偏移量将在之前提到的“TVendDlg”类的“VendChs”成员函数的数据检索部分中使用。

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

void ListBoxDialog::HandleListBoxMsg(RTMessage Msg)
{
  long int   a, convert_to_number[5];
  DWORD      Idx;
 
  // if the exit button is clicked, then exit and reset global variable to 0.
  if ( Msg.LP.Hi == LBN_SELCANCEL ) Globalvar = 0;

  	// if a selection is made, then reset the global variable to 1 and proceed to calculate the
  	// filestream offset after getting the list box index of the selection, “Idx”.
  	if ( Msg.LP.Hi == LBN_SELCHANGE ) {

        // initialize the char array, “char_array”, with space characters.	
    	for(a=0; a<80; a++) char_array[a] = 32;

    	Globalvar = 1;

    	// get the index of the selected list box item.
    	Idx = SendDlgItemMsg(ID_LISTBOX, LB_GETCURSEL, 0, 0L);

    	char_array[79] = 0;

    	// use the index to retrieve the contents of the selected list box row into a char array, “char_array”.
    	SendDlgItemMsg(ID_LISTBOX, LB_GETTEXT, (WORD)Idx, (DWORD) char_array);

    	// close the list box window after retrieving info into the char array from above.
    	CloseWindow();

    			// this will take the auto-generated sequential
			// position of the vendor record stored in each record of the binary text file, “vend.txt” 
			// from the char array and convert it to a numerical value to be multiplied by the defined constant,
			// “VENDLEN”. this will produce the filestream offset I call “offsetvar”, which is used to locate the
			// vendor data in the member function “VendChs” of the “TVendDlg” dialog class, which will populate
			// the edit controls in the vendor data entry screen. 
    			for(a=0; a<5; a++) {
    			convert_to_number[a] = 0;
    			if(char_array[70+a] == 48) convert_to_number[a] = 0;
    			if(char_array[70+a] == 49) convert_to_number[a] = 1;
    			if(char_array[70+a] == 50) convert_to_number[a] = 2;
    			if(char_array[70+a] == 51) convert_to_number[a] = 3;
    			if(char_array[70+a] == 52) convert_to_number[a] = 4;
    			if(char_array[70+a] == 53) convert_to_number[a] = 5;
    			if(char_array[70+a] == 54) convert_to_number[a] = 6;
    			if(char_array[70+a] == 55) convert_to_number[a] = 7;
    			if(char_array[70+a] == 56) convert_to_number[a] = 8;
    			if(char_array[70+a] == 57) convert_to_number[a] = 9;
		  	}
    			offsetvar = ( (convert_to_number[0] * 10000) + (convert_to_number[1] * 1000) + (convert_to_number [2] * 100) + (convert_to_number [3] * 10 ) + (convert_to_number[4] * 1) ) * VENDLEN;

  	}

}


上面的 C++ 代码图解

这是从“TVendDlg”类创建的供应商数据录入屏幕。




点击“选择”按钮后,将出现此列表框,其中包含我录入的供应商记录。




点击列表框中的供应商后,列表框将消失,我内置的编程会将选定的供应商填充到供应商数据录入屏幕中,如下所示。





结论

您可以看到,如果您不具备面向对象编程所需的开发技能,这可能会很困难。我的软件设计技术可能有点冗长,但这一切都能正常工作,能够快速实现其预期目的,而不会出现 Windows 异常屏幕、惊恐的眼神、血压升高等等。如果说有什么的话,那就是它让人更加欣赏当今用于定制软件设计的现代编码平台。