#2
sdta2023-04-29 13:48
|
通过这个项目,你可以学习到:
如何在 Visual FoxPro 中使用界面设计器创建界面,以及如何通过代码控制控件的属性和事件。
如何使用表格控件显示和编辑数据,以及如何对表格进行分组、排序、过滤等操作。
如何使用数据库引擎和查询语言实现数据的存储和检索。
如何掌握面向对象编程的基本概念,并应用于实际开发中。
如何设计和实现简单的业务逻辑,例如借阅和归还图书、更新可借阅数等。
如何处理用户输入错误、异常情况和数据安全等问题。
这些是开发任何项目中都需要关注的问题,这是一个简单的示例,帮助你更好地理解和应用这些概念和技术。
程序代码:
* 设置界面字体和日期格式
SET FONT TO "Arial", 9
SET DATE TO DMY
* 定义程序变量和常量
LOCAL lnBookCount, lnMemberCount
LOCAL lnMaxBooksPerMember, lnFinePerDay
CONST lcLibraryName = "图书馆管理系统"
* 定义窗体和控件
DEFINE WINDOW wndMain FROM 0, 0 TO 800, 600 TITLE lcLibraryName
DEFINE LABEL lblTitle PROMPT "图书管理系统" ROW 20 COL 300 FONT "Arial,B" HEIGHT 30
DEFINE TABSHEET tbsBooks FROM 50, 70 TO 750, 570 TITLE "图书"
DEFINE LABEL lblBookId PROMPT "图书编号:" ROW 20 COL 50
DEFINE TEXTBOX txtBookId ROW 20 COL 150 WIDTH 150
DEFINE LABEL lblTitle PROMPT "标题:" ROW 50 COL 50
DEFINE TEXTBOX txtTitle ROW 50 COL 150 WIDTH 200
DEFINE LABEL lblAuthor PROMPT "作者:" ROW 80 COL 50
DEFINE TEXTBOX txtAuthor ROW 80 COL 150 WIDTH 200
DEFINE LABEL lblSubject PROMPT "主题:" ROW 110 COL 50
DEFINE TEXTBOX txtSubject ROW 110 COL 150 WIDTH 200
DEFINE LABEL lblPublisher PROMPT "出版社:" ROW 140 COL 50
DEFINE TEXTBOX txtPublisher ROW 140 COL 150 WIDTH 200
DEFINE LABEL lblPubYear PROMPT "出版年份:" ROW 170 COL 50
DEFINE TEXTBOX txtPubYear ROW 170 COL 150 WIDTH 200
DEFINE LABEL lblIsbn PROMPT "ISBN:" ROW 200 COL 50
DEFINE TEXTBOX txtIsbn ROW 200 COL 150 WIDTH 200
DEFINE BUTTON btnAddBook PROMPT "添加图书" ROW 240 COL 150 WIDTH 100
DEFINE BUTTON btnClearBook PROMPT "清空" ROW 240 COL 280 WIDTH 100
DEFINE GRID grdBooks ROW 280 COL 50 WIDTH 700 HEIGHT 200 HEADERS "图书编号,标题,作者,主题,出版社,出版年份,ISBN" FONT "Arial" ;
UNITS PIXELS COLUMNS 7
DEFINE LABEL lblBookCount PROMPT "总图书数:" ROW 490 COL 50 FONT "Arial,B" HEIGHT 25
DEFINE LABEL lblAvailableCount PROMPT "可借图书数:" ROW 490 COL 280 FONT "Arial,B" HEIGHT 25
DEFINE TABSHEET tbsMembers FROM 50, 130 TO 750, 570 TITLE "会员"
DEFINE LABEL lblMemberId PROMPT "会员编号:" ROW 20 COL 50
DEFINE TEXTBOX txtMemberId ROW 20 COL 150 WIDTH 150
DEFINE LABEL lblName PROMPT "姓名:" ROW 50 COL 50
DEFINE TEXTBOX txtName ROW 50 COL 150 WIDTH 200
DEFINE LABEL lblAddress PROMPT "地址:" ROW 80 COL 50
DEFINE TEXTBOX txtAddress ROW 80 COL 150 WIDTH 200
DEFINE LABEL lblPhone PROMPT "电话:" ROW 110 COL 50
DEFINE TEXTBOX txtPhone ROW 110 COL 150 WIDTH 200
DEFINE BUTTON btnAddMember PROMPT "添加会员" ROW 140 COL 150 WIDTH 100
DEFINE BUTTON btnClearMember PROMPT "清空" ROW 140 COL 280 WIDTH 100
DEFINE GRID grdMembers ROW 180 COL 50 WIDTH 700 HEIGHT 200 HEADERS "会员编号,姓名,地址,电话,借书数" FONT "Arial" ;
UNITS PIXELS COLUMNS 5
DEFINE LABEL lblMemberCount PROMPT "总会员数:" ROW 390 COL 50 FONT "Arial,B" HEIGHT 25
DEFINE TABSHEET tbsLoans FROM 50, 190 TO 750, 570 TITLE "借阅"
DEFINE LABEL lblLoanBookId PROMPT "图书编号:" ROW 20 COL 50
DEFINE TEXTBOX txtLoanBookId ROW 20 COL 150 WIDTH 150
DEFINE LABEL lblLoanMemberId PROMPT "会员编号:" ROW 50 COL 50
DEFINE TEXTBOX txtLoanMemberId ROW 50 COL 150 WIDTH 150
DEFINE LABEL lblLoanDate PROMPT "借出日期:" ROW 80 COL 50
DEFINE TEXTBOX txtLoanDate ROW 80 COL 150 WIDTH 150
DEFINE BUTTON btnIssueLoan PROMPT "借出" ROW 110 COL 150 WIDTH 100
DEFINE BUTTON btnReturnLoan PROMPT "归还" ROW 110 COL 280 WIDTH 100
DEFINE GRID grdLoans ROW 150 COL 50 WIDTH 700 HEIGHT 350 HEADERS "图书编号,会员编号,借出日期,归还日期,罚款金额"
SET FONT TO "Arial", 9
SET DATE TO DMY
* 定义程序变量和常量
LOCAL lnBookCount, lnMemberCount
LOCAL lnMaxBooksPerMember, lnFinePerDay
CONST lcLibraryName = "图书馆管理系统"
* 定义窗体和控件
DEFINE WINDOW wndMain FROM 0, 0 TO 800, 600 TITLE lcLibraryName
DEFINE LABEL lblTitle PROMPT "图书管理系统" ROW 20 COL 300 FONT "Arial,B" HEIGHT 30
DEFINE TABSHEET tbsBooks FROM 50, 70 TO 750, 570 TITLE "图书"
DEFINE LABEL lblBookId PROMPT "图书编号:" ROW 20 COL 50
DEFINE TEXTBOX txtBookId ROW 20 COL 150 WIDTH 150
DEFINE LABEL lblTitle PROMPT "标题:" ROW 50 COL 50
DEFINE TEXTBOX txtTitle ROW 50 COL 150 WIDTH 200
DEFINE LABEL lblAuthor PROMPT "作者:" ROW 80 COL 50
DEFINE TEXTBOX txtAuthor ROW 80 COL 150 WIDTH 200
DEFINE LABEL lblSubject PROMPT "主题:" ROW 110 COL 50
DEFINE TEXTBOX txtSubject ROW 110 COL 150 WIDTH 200
DEFINE LABEL lblPublisher PROMPT "出版社:" ROW 140 COL 50
DEFINE TEXTBOX txtPublisher ROW 140 COL 150 WIDTH 200
DEFINE LABEL lblPubYear PROMPT "出版年份:" ROW 170 COL 50
DEFINE TEXTBOX txtPubYear ROW 170 COL 150 WIDTH 200
DEFINE LABEL lblIsbn PROMPT "ISBN:" ROW 200 COL 50
DEFINE TEXTBOX txtIsbn ROW 200 COL 150 WIDTH 200
DEFINE BUTTON btnAddBook PROMPT "添加图书" ROW 240 COL 150 WIDTH 100
DEFINE BUTTON btnClearBook PROMPT "清空" ROW 240 COL 280 WIDTH 100
DEFINE GRID grdBooks ROW 280 COL 50 WIDTH 700 HEIGHT 200 HEADERS "图书编号,标题,作者,主题,出版社,出版年份,ISBN" FONT "Arial" ;
UNITS PIXELS COLUMNS 7
DEFINE LABEL lblBookCount PROMPT "总图书数:" ROW 490 COL 50 FONT "Arial,B" HEIGHT 25
DEFINE LABEL lblAvailableCount PROMPT "可借图书数:" ROW 490 COL 280 FONT "Arial,B" HEIGHT 25
DEFINE TABSHEET tbsMembers FROM 50, 130 TO 750, 570 TITLE "会员"
DEFINE LABEL lblMemberId PROMPT "会员编号:" ROW 20 COL 50
DEFINE TEXTBOX txtMemberId ROW 20 COL 150 WIDTH 150
DEFINE LABEL lblName PROMPT "姓名:" ROW 50 COL 50
DEFINE TEXTBOX txtName ROW 50 COL 150 WIDTH 200
DEFINE LABEL lblAddress PROMPT "地址:" ROW 80 COL 50
DEFINE TEXTBOX txtAddress ROW 80 COL 150 WIDTH 200
DEFINE LABEL lblPhone PROMPT "电话:" ROW 110 COL 50
DEFINE TEXTBOX txtPhone ROW 110 COL 150 WIDTH 200
DEFINE BUTTON btnAddMember PROMPT "添加会员" ROW 140 COL 150 WIDTH 100
DEFINE BUTTON btnClearMember PROMPT "清空" ROW 140 COL 280 WIDTH 100
DEFINE GRID grdMembers ROW 180 COL 50 WIDTH 700 HEIGHT 200 HEADERS "会员编号,姓名,地址,电话,借书数" FONT "Arial" ;
UNITS PIXELS COLUMNS 5
DEFINE LABEL lblMemberCount PROMPT "总会员数:" ROW 390 COL 50 FONT "Arial,B" HEIGHT 25
DEFINE TABSHEET tbsLoans FROM 50, 190 TO 750, 570 TITLE "借阅"
DEFINE LABEL lblLoanBookId PROMPT "图书编号:" ROW 20 COL 50
DEFINE TEXTBOX txtLoanBookId ROW 20 COL 150 WIDTH 150
DEFINE LABEL lblLoanMemberId PROMPT "会员编号:" ROW 50 COL 50
DEFINE TEXTBOX txtLoanMemberId ROW 50 COL 150 WIDTH 150
DEFINE LABEL lblLoanDate PROMPT "借出日期:" ROW 80 COL 50
DEFINE TEXTBOX txtLoanDate ROW 80 COL 150 WIDTH 150
DEFINE BUTTON btnIssueLoan PROMPT "借出" ROW 110 COL 150 WIDTH 100
DEFINE BUTTON btnReturnLoan PROMPT "归还" ROW 110 COL 280 WIDTH 100
DEFINE GRID grdLoans ROW 150 COL 50 WIDTH 700 HEIGHT 350 HEADERS "图书编号,会员编号,借出日期,归还日期,罚款金额"
定义程序变量和常量:
程序代码:
* 定义程序变量和常量
lnBookCount = 0
lnMemberCount = 0
lnMaxBooksPerMember = 5
lnFinePerDay = 1
lnBookCount = 0
lnMemberCount = 0
lnMaxBooksPerMember = 5
lnFinePerDay = 1
在批量添加图书时,需要使用数组保存图书信息,定义一个名为 laBooks 的二维数组,每行包含图书编号、标题、作者、主题、出版社、出版年份和 ISBN:
* 定义图书数组
DIMENSION laBooks[100, 7]
DIMENSION laBooks[100, 7]
在批量添加会员时,需要使用数组保存会员信息,定义一个名为 laMembers 的二维数组,每行包含会员编号、姓名、地址、电话和已借书数:
* 定义会员数组
DIMENSION laMembers[100, 5]
DIMENSION laMembers[100, 5]
为添加图书按钮添加点击事件处理程序,将行输入框中的数据保存到二维数组中,然后更新图书数量和表格:
程序代码:
* 添加图书按钮点击事件处理程序
PROCEDURE AddBook
IF EMPTY(txtBookId.Value) OR EMPTY(txtTitle.Value) OR EMPTY(txtAuthor.Value) OR EMPTY(txtSubject.Value) OR EMPTY(txtPublisher.Value) OR EMPTY(txtPubYear.Value) OR EMPTY(txtIsbn.Value)
MESSAGEBOX("请输入完整的图书信息。", 16, lcLibraryName)
RETURN
ENDIF
lnBookCount = lnBookCount + 1
laBooks[lnBookCount, 1] = txtBookId.Value
laBooks[lnBookCount, 2] = txtTitle.Value
laBooks[lnBookCount, 3] = txtAuthor.Value
laBooks[lnBookCount, 4] = txtSubject.Value
laBooks[lnBookCount, 5] = txtPublisher.Value
laBooks[lnBookCount, 6] = txtPubYear.Value
laBooks[lnBookCount, 7] = txtIsbn.Value
CLEAR(txtBookId, txtTitle, txtAuthor, txtSubject, txtPublisher, txtPubYear, txtIsbn)
txtBookId.SetFocus()
lblBookCount.Caption = "总图书数:" + ALLTRIM(STR(lnBookCount))
lblAvailableCount.Caption = "可借图书数:" + ALLTRIM(STR(lnBookCount - GetLoanCount()))
UpdateBooksGrid()
ENDPROC
PROCEDURE AddBook
IF EMPTY(txtBookId.Value) OR EMPTY(txtTitle.Value) OR EMPTY(txtAuthor.Value) OR EMPTY(txtSubject.Value) OR EMPTY(txtPublisher.Value) OR EMPTY(txtPubYear.Value) OR EMPTY(txtIsbn.Value)
MESSAGEBOX("请输入完整的图书信息。", 16, lcLibraryName)
RETURN
ENDIF
lnBookCount = lnBookCount + 1
laBooks[lnBookCount, 1] = txtBookId.Value
laBooks[lnBookCount, 2] = txtTitle.Value
laBooks[lnBookCount, 3] = txtAuthor.Value
laBooks[lnBookCount, 4] = txtSubject.Value
laBooks[lnBookCount, 5] = txtPublisher.Value
laBooks[lnBookCount, 6] = txtPubYear.Value
laBooks[lnBookCount, 7] = txtIsbn.Value
CLEAR(txtBookId, txtTitle, txtAuthor, txtSubject, txtPublisher, txtPubYear, txtIsbn)
txtBookId.SetFocus()
lblBookCount.Caption = "总图书数:" + ALLTRIM(STR(lnBookCount))
lblAvailableCount.Caption = "可借图书数:" + ALLTRIM(STR(lnBookCount - GetLoanCount()))
UpdateBooksGrid()
ENDPROC
为清空图书按钮添加点击事件处理程序,将行输入框中的数据清空:
程序代码:
* 清空图书按钮点击事件处理程序
PROCEDURE ClearBook
CLEAR(txtBookId, txtTitle, txtAuthor, txtSubject, txtPublisher, txtPubYear, txtIsbn)
txtBookId.SetFocus()
ENDPROC
PROCEDURE ClearBook
CLEAR(txtBookId, txtTitle, txtAuthor, txtSubject, txtPublisher, txtPubYear, txtIsbn)
txtBookId.SetFocus()
ENDPROC
在更新图书表格时,先清空原有的数据,然后使用循环将二维数组中的数据插入到表格中:
程序代码:
* 更新图书表格
PROCEDURE UpdateBooksGrid
LOCAL i
grdBooks.Clear()
FOR i = 1 TO lnBookCount
grdBooks.AddRow(1)
grdBooks.Value(grdBooks.RowCount, 1) = laBooks[i, 1]
grdBooks.Value(grdBooks.RowCount, 2) = laBooks[i, 2]
grdBooks.Value(grdBooks.RowCount, 3) = laBooks[i, 3]
grdBooks.Value(grdBooks.RowCount, 4) = laBooks[i, 4]
grdBooks.Value(grdBooks.RowCount, 5) = laBooks[i, 5]
grdBooks.Value(grdBooks.RowCount, 6) = laBooks[i, 6]
grdBooks.Value(grdBooks.RowCount, 7) = laBooks[i, 7]
ENDFOR
ENDPROC
PROCEDURE UpdateBooksGrid
LOCAL i
grdBooks.Clear()
FOR i = 1 TO lnBookCount
grdBooks.AddRow(1)
grdBooks.Value(grdBooks.RowCount, 1) = laBooks[i, 1]
grdBooks.Value(grdBooks.RowCount, 2) = laBooks[i, 2]
grdBooks.Value(grdBooks.RowCount, 3) = laBooks[i, 3]
grdBooks.Value(grdBooks.RowCount, 4) = laBooks[i, 4]
grdBooks.Value(grdBooks.RowCount, 5) = laBooks[i, 5]
grdBooks.Value(grdBooks.RowCount, 6) = laBooks[i, 6]
grdBooks.Value(grdBooks.RowCount, 7) = laBooks[i, 7]
ENDFOR
ENDPROC
在更新会员表格时,先清空原有的数据,然后使用循环将二维数组中的数据插入到表格中,注意根据已借书数量判断是否可以再次借阅:
程序代码:
* 更新会员表格
PROCEDURE UpdateMembersGrid
LOCAL i
grdMembers.Clear()
FOR i = 1 TO lnMemberCount
grdMembers.AddRow(1)
grdMembers.Value(grdMembers.RowCount, 1) = laMembers[i, 1]
grdMembers.Value(grdMembers.RowCount, 2) = laMembers[i, 2]
grdMembers.Value(grdMembers.RowCount, 3) = laMembers[i, 3]
grdMembers.Value(grdMembers.RowCount, 4) = laMembers[i, 4]
grdMembers.Value(grdMembers.RowCount, 5) = ALLTRIM(STR(laMembers[i, 5]))
PROCEDURE UpdateMembersGrid
LOCAL i
grdMembers.Clear()
FOR i = 1 TO lnMemberCount
grdMembers.AddRow(1)
grdMembers.Value(grdMembers.RowCount, 1) = laMembers[i, 1]
grdMembers.Value(grdMembers.RowCount, 2) = laMembers[i, 2]
grdMembers.Value(grdMembers.RowCount, 3) = laMembers[i, 3]
grdMembers.Value(grdMembers.RowCount, 4) = laMembers[i, 4]
grdMembers.Value(grdMembers.RowCount, 5) = ALLTRIM(STR(laMembers[i, 5]))
为添加会员按钮添加点击事件处理程序,将行输入框中的数据保存到二维数组中,然后更新会员数量和表格:
程序代码:
* 添加会员按钮点击事件处理程序
PROCEDURE AddMember
IF EMPTY(txtMemberId.Value) OR EMPTY(txtName.Value) OR EMPTY(txtAddress.Value) OR EMPTY(txtPhone.Value)
MESSAGEBOX("请输入完整的会员信息。", 16, lcLibraryName)
RETURN
ENDIF
lnMemberCount = lnMemberCount + 1
laMembers[lnMemberCount, 1] = txtMemberId.Value
laMembers[lnMemberCount, 2] = txtName.Value
laMembers[lnMemberCount, 3] = txtAddress.Value
laMembers[lnMemberCount, 4] = txtPhone.Value
laMembers[lnMemberCount, 5] = 0
CLEAR(txtMemberId, txtName, txtAddress, txtPhone)
txtMemberId.SetFocus()
lblMemberCount.Caption = "总会员数:" + ALLTRIM(STR(lnMemberCount))
UpdateMembersGrid()
ENDPROC
PROCEDURE AddMember
IF EMPTY(txtMemberId.Value) OR EMPTY(txtName.Value) OR EMPTY(txtAddress.Value) OR EMPTY(txtPhone.Value)
MESSAGEBOX("请输入完整的会员信息。", 16, lcLibraryName)
RETURN
ENDIF
lnMemberCount = lnMemberCount + 1
laMembers[lnMemberCount, 1] = txtMemberId.Value
laMembers[lnMemberCount, 2] = txtName.Value
laMembers[lnMemberCount, 3] = txtAddress.Value
laMembers[lnMemberCount, 4] = txtPhone.Value
laMembers[lnMemberCount, 5] = 0
CLEAR(txtMemberId, txtName, txtAddress, txtPhone)
txtMemberId.SetFocus()
lblMemberCount.Caption = "总会员数:" + ALLTRIM(STR(lnMemberCount))
UpdateMembersGrid()
ENDPROC
为清空会员按钮添加点击事件处理程序,将行输入框中的数据清空:
程序代码:
* 清空会员按钮点击事件处理程序
PROCEDURE ClearMember
CLEAR(txtMemberId, txtName, txtAddress, txtPhone)
txtMemberId.SetFocus()
ENDPROC
PROCEDURE ClearMember
CLEAR(txtMemberId, txtName, txtAddress, txtPhone)
txtMemberId.SetFocus()
ENDPROC
为借阅图书按钮添加点击事件处理程序,根据选择的行和会员编号判断是否可以借阅,如果可以,则在该会员的已借书列表中添加该图书的编号,并更新表格和可借阅数:
程序代码:
* 借阅图书按钮点击事件处理程序
PROCEDURE LoanBook
LOCAL lnSelectedRow, lcMemberId, lcBookId, lnLoanCount
lnSelectedRow = grdBooks.SelectedRow()
IF lnSelectedRow = 0
MESSAGEBOX("请先选择一本图书。", 16, lcLibraryName)
RETURN
ENDIF
lcMemberId = txtLoanMemberId.Value
lcBookId = grdBooks.Value(lnSelectedRow, 1)
lnLoanCount = GetLoanCount(lcMemberId)
IF lnLoanCount >= lnMaxBooksPerMember
MESSAGEBOX("该会员已达到最大借阅量。", 16, lcLibraryName)
RETURN
ENDIF
IF LoanBookToMember(lcBookId, lcMemberId)
MESSAGEBOX("借阅成功。", 64, lcLibraryName)
lblAvailableCount.Caption = "可借图书数:" + ALLTRIM(STR(lnBookCount - GetLoanCount()))
UpdateBooksGrid()
UpdateMembersGrid()
ELSE
MESSAGEBOX("该图书已被借阅。", 16, lcLibraryName)
ENDIF
ENDPROC
PROCEDURE LoanBook
LOCAL lnSelectedRow, lcMemberId, lcBookId, lnLoanCount
lnSelectedRow = grdBooks.SelectedRow()
IF lnSelectedRow = 0
MESSAGEBOX("请先选择一本图书。", 16, lcLibraryName)
RETURN
ENDIF
lcMemberId = txtLoanMemberId.Value
lcBookId = grdBooks.Value(lnSelectedRow, 1)
lnLoanCount = GetLoanCount(lcMemberId)
IF lnLoanCount >= lnMaxBooksPerMember
MESSAGEBOX("该会员已达到最大借阅量。", 16, lcLibraryName)
RETURN
ENDIF
IF LoanBookToMember(lcBookId, lcMemberId)
MESSAGEBOX("借阅成功。", 64, lcLibraryName)
lblAvailableCount.Caption = "可借图书数:" + ALLTRIM(STR(lnBookCount - GetLoanCount()))
UpdateBooksGrid()
UpdateMembersGrid()
ELSE
MESSAGEBOX("该图书已被借阅。", 16, lcLibraryName)
ENDIF
ENDPROC
在判断会员是否已借阅一本特定的图书时,使用 laMembers 数组中的已借书列表进行判断。在添加一本新的已借书时,首先要找到该会员的位置,然后在已借书列表中查找这本图书,如果没有查找到,则将该图书编号添加到列表末尾,并将该会员的已借书数加 1:
程序代码:
* 借一本图书给会员
FUNCTION LoanBookToMember(lcBookId, lcMemberId)
LOCAL i, j
FOR i = 1 TO lnMemberCount
IF laMembers[i, 1] = lcMemberId
FOR j = 1 TO lnMaxBooksPerMember
IF EMPTY(laMembers[i, 5, j])
laMembers[i, 5, j] = lcBookId
laMembers[i, 5] = laMembers[i, 5] + 1
RETURN .T.
ENDIF
ENDFOR
ENDIF
ENDFOR
RETURN .F.
ENDFUNC
FUNCTION LoanBookToMember(lcBookId, lcMemberId)
LOCAL i, j
FOR i = 1 TO lnMemberCount
IF laMembers[i, 1] = lcMemberId
FOR j = 1 TO lnMaxBooksPerMember
IF EMPTY(laMembers[i, 5, j])
laMembers[i, 5, j] = lcBookId
laMembers[i, 5] = laMembers[i, 5] + 1
RETURN .T.
ENDIF
ENDFOR
ENDIF
ENDFOR
RETURN .F.
ENDFUNC
在获取一个会员已借书数时,查找 laMembers 数组中对应会员的已借书列表,然后返回不为空的数量:
程序代码:
* 获取一个会员已借书数
FUNCTION GetLoanCount(lcMemberId)
LOCAL i, lnCount
FOR i = 1 TO lnMemberCount
IF laMembers[i, 1] = lcMemberId
lnCount = 0
DO WHILE NOT EMPTY(laMembers[i, 5, lnCount + 1])
lnCount = lnCount + 1
ENDDO
RETURN lnCount
ENDIF
ENDFOR
FUNCTION GetLoanCount(lcMemberId)
LOCAL i, lnCount
FOR i = 1 TO lnMemberCount
IF laMembers[i, 1] = lcMemberId
lnCount = 0
DO WHILE NOT EMPTY(laMembers[i, 5, lnCount + 1])
lnCount = lnCount + 1
ENDDO
RETURN lnCount
ENDIF
ENDFOR
接下来,为归还图书按钮添加点击事件处理程序,根据选择的行、会员编号和图书编号判断是否可以归还,如果可以,则在该会员的已借书列表中删除该图书的编号,并更新表格和可借阅数:
程序代码:
* 归还图书按钮点击事件处理程序
PROCEDURE ReturnBook
LOCAL lnSelectedRow, lcMemberId, lcBookId, lnLoanCount
lnSelectedRow = grdLoans.SelectedRow()
IF lnSelectedRow = 0
MESSAGEBOX("请先选择一条借阅记录。", 16, lcLibraryName)
RETURN
ENDIF
lcMemberId = txtReturnMemberId.Value
lcBookId = grdLoans.Value(lnSelectedRow, 2)
IF ReturnBookFromMember(lcBookId, lcMemberId)
MESSAGEBOX("归还成功。", 64, lcLibraryName)
lblAvailableCount.Caption = "可借图书数:" + ALLTRIM(STR(lnBookCount - GetLoanCount()))
UpdateBooksGrid()
UpdateMembersGrid()
ELSE
MESSAGEBOX("该图书已被归还。", 16, lcLibraryName)
ENDIF
ENDPROC
PROCEDURE ReturnBook
LOCAL lnSelectedRow, lcMemberId, lcBookId, lnLoanCount
lnSelectedRow = grdLoans.SelectedRow()
IF lnSelectedRow = 0
MESSAGEBOX("请先选择一条借阅记录。", 16, lcLibraryName)
RETURN
ENDIF
lcMemberId = txtReturnMemberId.Value
lcBookId = grdLoans.Value(lnSelectedRow, 2)
IF ReturnBookFromMember(lcBookId, lcMemberId)
MESSAGEBOX("归还成功。", 64, lcLibraryName)
lblAvailableCount.Caption = "可借图书数:" + ALLTRIM(STR(lnBookCount - GetLoanCount()))
UpdateBooksGrid()
UpdateMembersGrid()
ELSE
MESSAGEBOX("该图书已被归还。", 16, lcLibraryName)
ENDIF
ENDPROC
在查找会员的已借书列表并删除一个图书时,首先要找到该会员的位置,然后在已借书列表中查找这本图书,如果找到了,则将该图书删除,并将该会员的已借书数减 1:
程序代码:
* 从会员那里归还一本图书
FUNCTION ReturnBookFromMember(lcBookId, lcMemberId)
LOCAL i, j
FOR i = 1 TO lnMemberCount
IF laMembers[i, 1] = lcMemberId
FOR j = 1 TO lnMaxBooksPerMember
IF laMembers[i, 5, j] = lcBookId
laMembers[i, 5, j] = ""
laMembers[i, 5] = laMembers[i, 5] - 1
RETURN .T.
ENDIF
ENDFOR
ENDIF
ENDFOR
RETURN .F.
ENDFUNC
FUNCTION ReturnBookFromMember(lcBookId, lcMemberId)
LOCAL i, j
FOR i = 1 TO lnMemberCount
IF laMembers[i, 1] = lcMemberId
FOR j = 1 TO lnMaxBooksPerMember
IF laMembers[i, 5, j] = lcBookId
laMembers[i, 5, j] = ""
laMembers[i, 5] = laMembers[i, 5] - 1
RETURN .T.
ENDIF
ENDFOR
ENDIF
ENDFOR
RETURN .F.
ENDFUNC
最后,为统计按钮添加点击事件处理程序,统计所有会员的借阅情况,并将统计结果输出到消息框中:
程序代码:
* 统计按钮点击事件处理程序
PROCEDURE ShowStatistics
LOCAL i, j, lcOutput
lcOutput = "会员编号,姓名,已借书数\n"
FOR i = 1 TO lnMemberCount
IF laMembers[i, 5] > 0
lcOutput = lcOutput + ALLTRIM(laMembers[i, 1]) + "," + ALLTRIM(laMembers[i, 2]) + "," + ALLTRIM(STR(laMembers[i, 5])) + "\n"
ENDIF
ENDFOR
MESSAGEBOX(lcOutput, 64, lcLibraryName)
ENDPROC
PROCEDURE ShowStatistics
LOCAL i, j, lcOutput
lcOutput = "会员编号,姓名,已借书数\n"
FOR i = 1 TO lnMemberCount
IF laMembers[i, 5] > 0
lcOutput = lcOutput + ALLTRIM(laMembers[i, 1]) + "," + ALLTRIM(laMembers[i, 2]) + "," + ALLTRIM(STR(laMembers[i, 5])) + "\n"
ENDIF
ENDFOR
MESSAGEBOX(lcOutput, 64, lcLibraryName)
ENDPROC
至此,我们完成了图书馆管理系统的开发。
[此贴子已经被作者于2023-4-29 12:31编辑过]