【MFC】學生數據管理-廣州大學程序設計課程設計報告

在這裏插入圖片描述

一、課程設計題目及內容

(1)設計一個學生類Student,包括數據成員:姓名、學號、二門課程(面向對象程序設計、高等數學)的成績。
(2)創建一個管理學生的類Management,包括實現學生的數據的增加、刪除、修改、按課程成績排序、保存學生數據到文件及加載文件中的數據等功能。
(3)創建一個基於對話框的MFC應用程序,程序窗口的標題上有你姓名、學號和應用程序名稱。使用(1)和(2)中的類,實現對學生信息和成績的輸入和管理。
在這裏插入圖片描述
(4)創建一個單文檔的MFC應用程序,讀取(3)中保存的文件中的學生成績,分別用直方圖和折線方式顯示所有學生某課程的成績分佈圖。
在這裏插入圖片描述

二、程序中使用的數據及主要符號說明

//管理系統數據
CString studyNumber;	//學號
	CString name;	//姓名
	CListBox lis;	//列表名
	afx_msg void OnBnClickedButton1();
	afx_msg void OnBnClickedButton2();
	afx_msg void OnBnClickedButton3();
	afx_msg void OnLbnSelchangeList1();
	CButton del;	//刪除鍵命名
	afx_msg void OnBnClickedButton4();
	afx_msg void OnBnClickedButton5();
	void Removelis();	//清除列表
	afx_msg void OnDestroy();	//銷燬函數
	CString address;	//通信地址
	int sorting;	//排序下拉列表變量
	afx_msg void OnCbnSelchangeCombo2();
	afx_msg void OnBnClickedButton6();
	BOOL sex;		//性別
	CString age;	//年齡
	CString mTest;	//數學成績
CString cTest;	//C++成績CString temp;	//臨時字符串
	Student* pImfo = new Student;	//學生類指針
//繪圖數據

afx_msg void OnFilePrintPreview();
	afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
	afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
	DECLARE_MESSAGE_MAP()
	void DrawScore(CDC* pDC, int * fScore, int nNum);
	void Drawlist(CDC * pDC, int * fScore, int nNum);
	CButton m_button1, m_button2, m_button3, m_button4, m_button5, m_button6;
	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
	int m_Num[1000];
	afx_msg void OnHigger1();
	afx_msg void OnHigger2();
	afx_msg void OnHigger4();
	afx_msg void OnHigger5();

三、帶有詳細註釋的自己編寫的源程序

// Students.h
#pragma once
class Student {
public:
	char Name[10];	//姓名
	char StudyNumber[20];	//學號
	bool Sex;	//性別
	char Age[6];	//年齡
	char CTest[6];	//C++成績(C++Test)
	char MTest[6];	//數學成績(MathTest)
	char Test[6];		//總成績的字符型數值
	char Address[100];	//通信地址
};
// 管理系統Dlg.h

// 管理系統Dlg.h : 頭文件
#pragma once
#include "afxwin.h"
#include"Students.h"
// C管理系統Dlg 對話框
class C管理系統Dlg : public CDialogEx
{
// 構造
public:
	C管理系統Dlg(CWnd* pParent = NULL);	// 標準構造函數

// 對話框數據
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_MY_DIALOG };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持

// 實現
protected:
	HICON m_hIcon;

	// 生成的消息映射函數
	virtual BOOL OnInitDialog();
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
public:
	CString studyNumber;	//學號
	CString name;	//姓名
	CListBox lis;	//列表名
	afx_msg void OnBnClickedButton1();
	afx_msg void OnBnClickedButton2();
	afx_msg void OnBnClickedButton3();
	afx_msg void OnLbnSelchangeList1();
	CButton del;	//刪除鍵命名
	afx_msg void OnBnClickedButton4();
	afx_msg void OnBnClickedButton5();
	void Removelis();	//清除列表
	afx_msg void OnDestroy();	//銷燬函數
	CString address;	//通信地址
	int sorting;	//排序下拉列表變量
	afx_msg void OnCbnSelchangeCombo2();
	afx_msg void OnBnClickedButton6();
	BOOL sex;		//性別
	CString age;	//年齡
	CString mTest;	//數學成績
	CString cTest;	//C++成績
};

// 管理系統Dlg.cpp


// 管理系統Dlg.cpp : 實現文件
//

#include "stdafx.h"
#include "管理系統.h"
#include "管理系統Dlg.h"
#include "afxdialogex.h"
#include <fstream>
#include <iostream>
#include <algorithm>
#include <list>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
using namespace std;

// 用於應用程序“關於”菜單項的 CAboutDlg 對話框

class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();

// 對話框數據
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_ABOUTBOX };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 實現
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// C管理系統Dlg 對話框


//初始化類變量
C管理系統Dlg::C管理系統Dlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(IDD_MY_DIALOG, pParent)
	, studyNumber(_T(""))
	, name(_T(""))
	, address(_T(""))
	, sorting(0)
	, sex(FALSE)
	, age(_T(""))
	, mTest(_T(""))
	, cTest(_T(""))
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void C管理系統Dlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Text(pDX, IDC_EDIT1, studyNumber);
	DDX_Text(pDX, IDC_EDIT2, name);
	//  DDX_Radio(pDX, IDC_RADIO1, sex);
	//  DDX_Text(pDX, IDC_EDIT3, age);
	//  DDX_Text(pDX, IDC_EDIT5, mTest);
	//  DDX_Text(pDX, IDC_EDIT6, cTest);
	DDX_Control(pDX, IDC_LIST1, lis);
	DDX_Control(pDX, IDC_BUTTON2, del);
	DDX_Text(pDX, IDC_EDIT7, address);
	DDX_CBIndex(pDX, IDC_COMBO2, sorting);
	DDX_Radio(pDX, IDC_RADIO1, sex);
	DDX_Text(pDX, IDC_EDIT3, age);
	DDX_Text(pDX, IDC_EDIT5, mTest);
	DDV_MaxChars(pDX, mTest, 10);
	DDX_Text(pDX, IDC_EDIT6, cTest);
	DDV_MaxChars(pDX, cTest, 10);
}

BEGIN_MESSAGE_MAP(C管理系統Dlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON1, &C管理系統Dlg::OnBnClickedButton1)
	ON_BN_CLICKED(IDC_BUTTON2, &C管理系統Dlg::OnBnClickedButton2)
	ON_BN_CLICKED(IDC_BUTTON3, &C管理系統Dlg::OnBnClickedButton3)
	ON_LBN_SELCHANGE(IDC_LIST1, &C管理系統Dlg::OnLbnSelchangeList1)
	ON_BN_CLICKED(IDC_BUTTON4, &C管理系統Dlg::OnBnClickedButton4)
	ON_BN_CLICKED(IDC_BUTTON5, &C管理系統Dlg::OnBnClickedButton5)
	
	ON_WM_DESTROY()
	ON_CBN_SELCHANGE(IDC_COMBO2, &C管理系統Dlg::OnCbnSelchangeCombo2)
	ON_BN_CLICKED(IDC_BUTTON6, &C管理系統Dlg::OnBnClickedButton6)
END_MESSAGE_MAP()


// C管理系統Dlg 消息處理程序

BOOL C管理系統Dlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 將“關於...”菜單項添加到系統菜單中。
	// IDM_ABOUTBOX 必須在系統命令範圍內。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 設置此對話框的圖標。  當應用程序主窗口不是對話框時,框架將自動
	//  執行此操作
	SetIcon(m_hIcon, TRUE);			// 設置大圖標
	SetIcon(m_hIcon, FALSE);		// 設置小圖標

	// TODO: 在此添加額外的初始化代碼

	return TRUE;  // 除非將焦點設置到控件,否則返回 TRUE
}

void C管理系統Dlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

// 如果向對話框添加最小化按鈕,則需要下面的代碼
//  來繪製該圖標。  對於使用文檔/視圖模型的 MFC 應用程序,
//  這將由框架自動完成。

void C管理系統Dlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用於繪製的設備上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使圖標在工作區矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 繪製圖標
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

//當用戶拖動最小化窗口時系統調用此函數取得光標
//顯示。
HCURSOR C管理系統Dlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

void C管理系統Dlg::OnBnClickedButton1()
{
	// 增加
	if (UpdateData(true))
	{
		CString temp;	//臨時字符串
		Student* pImfo = new Student;	//學生類指針,用於存儲當前畫面新填入的信息

		//將畫面中的信息存儲到指針指向的類中
		strcpy_s(pImfo->Name, name);
		strcpy_s(pImfo->StudyNumber, studyNumber);
		strcpy_s(pImfo->Address, address);
		pImfo->Sex = sex;
		strcpy_s(pImfo->Age, age);
		strcpy_s(pImfo->MTest, mTest);
		strcpy_s(pImfo->CTest, cTest);
		int e = _ttoi(_T(mTest));
		int f = _ttoi(_T(cTest));
		temp.Format(_T("%d"), (e+f));
		strcpy_s(pImfo->Test, temp);

		//添加列表項目
		CString LongName = pImfo->Name;		//字符串LongName用於添加列表名稱
		LongName.Append("  總分");		
		LongName.Append(pImfo->Test);
		int nIndex = lis.AddString(LongName);	//接收索引號
		lis.SetItemData(nIndex, (DWORD_PTR)pImfo);		//設置相應項目ID

		//清空畫面操作
		name = "";
		studyNumber = "";
		address = "";
		sex = 0;
		age = "";
		mTest = "";
		cTest = "";
		UpdateData(FALSE);
	}
}


void C管理系統Dlg::OnBnClickedButton2()
{
	// 刪除
	int  nCur = lis.GetCurSel();	//讀取當前點中的列表索引號
	if (nCur != LB_ERR)
	{
		Student* pImfo = (Student*)lis.GetItemData(nCur);	//類指針指向對應列表數據
		lis.DeleteString(nCur);		//刪除該列

		//清空數據
		name = "";
		studyNumber = "";
		address = "";
		sex = 0;
		age = "";
		mTest = "";
		cTest = "";

		// 判斷當前行數,若行數爲0,則刪除鍵不可見
		if (lis.GetCount() == 0)
		{
			del.EnableWindow(FALSE);
		}
		UpdateData(FALSE);
		delete pImfo;	//釋放指針防止內存泄漏
	}

}


void C管理系統Dlg::OnBnClickedButton3()
{
	// 修改
	// 思路:刪舊增新
	int  nCur = lis.GetCurSel();	//讀取當前點中的列表索引號
	if (nCur != LB_ERR)
	{
		Student* pImfo = (Student*)lis.GetItemData(nCur);	//類指針指向對應列表數據
		lis.DeleteString(nCur);		//刪除該列
		delete pImfo;	//釋放指針防止內存泄漏
	}
	OnBnClickedButton1();	//調用“增加”按鈕,讀取當前畫面中的信息將其再次添加
}


void C管理系統Dlg::OnLbnSelchangeList1()
{
	// 列表事件
	int nCur = lis.GetCurSel();		//讀取當前點中的列表索引號
	if (nCur != LB_ERR)
	{
		del.EnableWindow(TRUE);		//if (nCur != LB_ERR)→有選中列表→可以刪除→刪除鍵可見
		Student* pImfo = (Student*)lis.GetItemData(nCur);	//類指針指向對應列表數據

		//數據讀取
		name = pImfo->Name;
		address = pImfo->Address;
		studyNumber = pImfo->StudyNumber;
		sex = pImfo->Sex;
		age = pImfo->Age;
		mTest = pImfo->MTest;
		cTest = pImfo->CTest;
		UpdateData(FALSE);
	}
	
}


void C管理系統Dlg::OnBnClickedButton4()
{
	// TODO: 保存
	CFileDialog dlg(FALSE);		//打開“另存爲”界面
	if (dlg.DoModal() == IDOK)
	{
		CString strFile = dlg.GetPathName();	//返回文件路徑
		ofstream out(strFile, ios::binary);		//二進制寫入數據
		if (out.is_open())
		{
			int n = lis.GetCount();		//獲取當前信息數目

			//將信息寫入文件中
			out.write((char*)&n, sizeof(int));
			for (int i = 0; i < n; i++)
			{
				Student* pImfo = (Student*)lis.GetItemData(i);
				out.write((char*)pImfo, sizeof(Student));
			}
		}
	}
}


void C管理系統Dlg::OnBnClickedButton5()
{
	// TODO: 讀取
	CFileDialog dlg(TRUE);	//打開“打開”界面
	if (dlg.DoModal() == IDOK)
	{
		Removelis();	//清空當前列表
		CString strFile = dlg.GetPathName();	//返回文件路徑
		ifstream in(strFile, ios::binary);		//二進制讀出數據
		if (in.is_open())
		{
			int n = lis.GetCount();		//獲取當前信息數目

			//從文件中讀取信息
			in.read((char*)&n, sizeof(int));
			for (int i = 0; i < n; i++)
			{
				Student* pImfo = new Student;
				in.read((char*)pImfo, sizeof(Student));
				CString LongName = pImfo->Name;		//字符串LongName用於添加列表名稱
				LongName.Append("  總分");
				LongName.Append(pImfo->Test);
				int nIndex = lis.AddString(LongName);	//接收索引號
				lis.SetItemData(nIndex, (DWORD_PTR)pImfo);		//設置相應項目ID
			}
			OnLbnSelchangeList1();		//更新列表欄
		}
		else
		{
			AfxMessageBox("Open File Err");
		}
	}
}

//快排調用
BOOL  cmpAll(Student* pt1, Student* pt2)   //比較總成績
{
	int temp1 = _ttoi(_T(pt1->Test));
	int temp2 = _ttoi(_T(pt2->Test));
	return temp1 > temp2;
}
BOOL  cmpM(Student* pt1, Student* pt2)   //比較數學成績
{
	int temp1 = _ttoi(_T(pt1->MTest));
	int temp2 = _ttoi(_T(pt2->MTest));
	return temp1 > temp2;
}
BOOL  cmpC(Student* pt1, Student* pt2)   //比較C成績
{
	int temp1 = _ttoi(_T(pt1->CTest));
	int temp2 = _ttoi(_T(pt2->CTest));
	return temp1 > temp2;
}
	
void C管理系統Dlg::Removelis()		
{
	//列表清除
	int n = lis.GetCount();		//獲取當前信息數目
	//逐條讀取指針,釋放指針
	for (int i = 0; i < n; i++)
	{
		Student* pImfo = (Student*)lis.GetItemData(i);
		delete pImfo;
	}
	lis.ResetContent();		//釋放內容
	OnLbnSelchangeList1();		//更新列表欄
}


void C管理系統Dlg::OnDestroy()
{
	CDialogEx::OnDestroy();
	Removelis();	//在關閉整個頁面前正確釋放指針,避免內存泄漏
	// TODO: 在此處添加消息處理程序代碼
}




void C管理系統Dlg::OnCbnSelchangeCombo2()
{
	// 排序
	if (UpdateData(true)) {

		//使用容器讀取信息,進行排序
		list<Student*> sts;
		int num = lis.GetCount();
		Student *temp;
		for (int i = 0; i < lis.GetCount(); i++)
		{
			temp = (Student*)lis.GetItemData(i);
			sts.push_back(temp);
		}

		//根據下拉列表框的選擇執行不同的排序
		switch (sorting)
		{
		case 0:
			break;
		case 1:
			sts.sort(cmpM);		//按照數學成績排序
			break;
		case 2:
			sts.sort(cmpC);		//按照程序設計成績排序
			break;
		case 3:
			sts.sort(cmpAll);		//按照總成績排序
			break;
		}
		//逐條刪除列表
		while (lis.GetCount() > 0) lis.DeleteString(0);
		//將在容器中排好序的信息再添加到列表中
		for (auto iter = sts.begin(); iter != sts.end(); ++iter)
		{
			auto st = *iter;
			CString LongName = st->Name;	//字符串LongName用於添加列表名稱
			LongName.Append("  總分");
			LongName.Append(st->Test);
			lis.AddString(LongName);
			lis.SetItemDataPtr(lis.GetCount() - 1, st);
		}
	}
}


void C管理系統Dlg::OnBnClickedButton6()
{
	// 呼叫繪圖程序
	ShellExecute(NULL, "open", ".\\MFCApplication8.exe", NULL, NULL, SW_SHOWNORMAL);
}


// MFCApplication8View.h
// MFCApplication8View.h : CMFCApplication8View 類的接口
//

#pragma once


class CMFCApplication8View : public CView
{
protected: // 僅從序列化創建
	CMFCApplication8View();
	DECLARE_DYNCREATE(CMFCApplication8View)

// 特性
public:
	CMFCApplication8Doc* GetDocument() const;

// 操作
public:

// 重寫
public:
	virtual void OnDraw(CDC* pDC);  // 重寫以繪製該視圖
	virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
	virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
	virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
	virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);

// 實現
public:
	virtual ~CMFCApplication8View();
#ifdef _DEBUG
	virtual void AssertValid() const;
	virtual void Dump(CDumpContext& dc) const;
#endif

protected:

// 生成的消息映射函數
protected:
	afx_msg void OnFilePrintPreview();
	afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
	afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
	DECLARE_MESSAGE_MAP()
	void DrawScore(CDC* pDC, int * fScore, int nNum);
	void Drawlist(CDC * pDC, int * fScore, int nNum);
	CButton m_button1, m_button2, m_button3, m_button4, m_button5, m_button6;
public:
	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
	int m_Num[1000];
	afx_msg void OnHigger1();
	afx_msg void OnHigger2();
	afx_msg void OnHigger4();
	afx_msg void OnHigger5();
};

#ifndef _DEBUG  // MFCApplication8View.cpp 中的調試版本
inline CMFCApplication8Doc* CMFCApplication8View::GetDocument() const
   { return reinterpret_cast<CMFCApplication8Doc*>(m_pDocument); }
#endif
// MFCApplication8View.cpp
// MFCApplication8View.cpp : CMFCApplication8View 類的實現
//

#include "stdafx.h"
// SHARED_HANDLERS 可以在實現預覽、縮略圖和搜索篩選器句柄的
// ATL 項目中進行定義,並允許與該項目共享文檔代碼。
#ifndef SHARED_HANDLERS
#include "MFCApplication8.h"
#endif

#include "MFCApplication8Doc.h"
#include "MFCApplication8View.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#include <fstream>
#include "Students.h"
using namespace std;

// CMFCApplication8View

IMPLEMENT_DYNCREATE(CMFCApplication8View, CView)

BEGIN_MESSAGE_MAP(CMFCApplication8View, CView)
	// 標準打印命令
	ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CMFCApplication8View::OnFilePrintPreview)
	ON_WM_CONTEXTMENU()
	ON_WM_RBUTTONUP()
	ON_WM_CREATE()
	ON_COMMAND(IDC_HIGGER1, &CMFCApplication8View::OnHigger1)
	ON_COMMAND(IDC_HIGGER2, &CMFCApplication8View::OnHigger2)
	ON_COMMAND(IDC_HIGGER4, &CMFCApplication8View::OnHigger4)
	ON_COMMAND(IDC_HIGGER5, &CMFCApplication8View::OnHigger5)
END_MESSAGE_MAP()

// CMFCApplication8View 構造/析構

CMFCApplication8View::CMFCApplication8View()
{
	// TODO: 在此處添加構造代碼

}

CMFCApplication8View::~CMFCApplication8View()
{
}

BOOL CMFCApplication8View::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: 在此處通過修改
	//  CREATESTRUCT cs 來修改窗口類或樣式

	return CView::PreCreateWindow(cs);
}

// CMFCApplication8View 繪製

void CMFCApplication8View::OnDraw(CDC* pDC)
{
	CMFCApplication8Doc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;
 
}
void CMFCApplication8View::OnFilePrintPreview()
{
#ifndef SHARED_HANDLERS
	AFXPrintPreview(this);
#endif
}

BOOL CMFCApplication8View::OnPreparePrinting(CPrintInfo* pInfo)
{
	// 默認準備
	return DoPreparePrinting(pInfo);
}
void CMFCApplication8View::OnRButtonUp(UINT /* nFlags */, CPoint point)
{
	ClientToScreen(&point);
	OnContextMenu(this, point);
}

void CMFCApplication8View::OnContextMenu(CWnd* /* pWnd */, CPoint point)
{
#ifndef SHARED_HANDLERS
	theApp.GetContextMenuManager()->ShowPopupMenu(IDR_POPUP_EDIT, point.x, point.y, this, TRUE);
#endif
}


// CMFCApplication8View 診斷

#ifdef _DEBUG
void CMFCApplication8View::AssertValid() const
{
	CView::AssertValid();
}

void CMFCApplication8View::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CMFCApplication8Doc* CMFCApplication8View::GetDocument() const // 非調試版本是內聯的
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMFCApplication8Doc)));
	return (CMFCApplication8Doc*)m_pDocument;
}
#endif //_DEBUG


// CMFCApplication8View 消息處理程序
void CMFCApplication8View::DrawScore(CDC* pDC, int * fScore, int nNum) //畫直方圖函數
{
	// fScore是成績數組指針,nNum是學生人數
	int nScoreNum[] = { 0, 0, 0, 0, 0 };  // 各成績段的人數的初 始值 
										  // 下面是用來統計各分數段的人數   
	for (int i = 0; i < nNum; i++)
	{
		int nSeg = (int)(fScore[i]) / 10; // 取數的"十"位上的值   
		if (nSeg < 6) nSeg = 5; // <60分    
		if (nSeg == 10) nSeg = 9;// 當爲100分,算爲>90分數段   
		nScoreNum[nSeg - 5] ++;   // 各分數段計數   
	}
	int nSegNum = sizeof(nScoreNum) / sizeof(int); // 計算有多少個分數段

												   // 求分數段上最大的人數 
	int nNumMax = nScoreNum[0];
	for (int i = 1; i < nSegNum; i++)
	{
		if (nNumMax < nScoreNum[i])
			nNumMax = nScoreNum[i];
	}
	CRect rc;
	GetClientRect(rc);
	rc.DeflateRect(280, 40);      // 縮小矩形大小  
	int nSegWidth = rc.Width() / nSegNum;   // 計算每段的寬度  
	int nSegHeight = rc.Height() / nNumMax;   // 計算每段的單位高度  
	COLORREF crSeg = RGB(0, 0, 192);  // 定義一個顏色變量   
	CBrush brush1(HS_FDIAGONAL, crSeg);
	CBrush brush2(HS_BDIAGONAL, crSeg);
	CPen   pen(PS_INSIDEFRAME, 2, crSeg);
	CBrush* oldBrush = pDC->SelectObject(&brush1);   // 將brush1選入設備環境   
	CPen* oldPen = pDC->SelectObject(&pen);  // 將pen選 入設備環境  
	CRect rcSeg(rc);
	rcSeg.right = rcSeg.left + nSegWidth;   // 使每段的矩形寬度等於nSegWidth  
	CString strSeg[] = { (CString)"<60", (CString)"60-70", (CString)"70-80", (CString)"80-90", (CString)">=90" };
	CRect rcStr;
	for (int i = 0; i<nSegNum; i++)
	{  // 保證相鄰的矩形填充樣式不相同    
		if (i % 2)
			pDC->SelectObject(&brush2);
		else
			pDC->SelectObject(&brush1);
		rcSeg.top = rcSeg.bottom - nScoreNum[i] * nSegHeight - 2;  // 計算每段矩形的高度   
		pDC->Rectangle(rcSeg);
		if (nScoreNum[i] > 0)
		{
			CString str;
			str.Format((CString)"%d人", nScoreNum[i]);
			pDC->DrawText(str, rcSeg, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
		}
		rcStr = rcSeg;
		rcStr.top = rcStr.bottom + 2;
		rcStr.bottom += 20;
		pDC->DrawText(strSeg[i], rcStr, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
		rcSeg.OffsetRect(nSegWidth, 0);  // 右移矩形   
	}
	pDC->SelectObject(oldBrush);  // 恢復原來的畫刷屬性   
	pDC->SelectObject(oldPen);    // 恢復原來的畫筆屬性 

	CDC* pControlDC = pDC;
	pControlDC->SelectStockObject(BLACK_BRUSH);//設置畫刷
	CString str;
}

void CMFCApplication8View::Drawlist(CDC* pDC, int* fScore, int nNum)//畫折線圖
{
	// fScore是成績數組指針,nNum是學生人數

	int nScoreNum[] = { 0, 0, 0, 0, 0 };  // 各成績段的人數的初 始值 
	// 下面是用來統計各分數段的人數   
	for (int i = 0; i < nNum; i++)
	{
		int nSeg = (int)(fScore[i]) / 10; // 取數的"十"位上的值   
		if (nSeg < 6) nSeg = 5; // <60分    
		if (nSeg == 10) nSeg = 9;// 當爲100分,算爲>90分數段   
		nScoreNum[nSeg - 5] ++;   // 各分數段計數   
	}
	CDC* pControlDC = pDC;
	pControlDC->SelectStockObject(BLACK_BRUSH);//設置畫刷
	CString str;
	CString strSeg[] = { (CString)"<60", (CString)"60-70", (CString)"70-80", (CString)"80-90", (CString)">=90" };
	pControlDC->MoveTo(280, 40);//畫線的開始位置
	pControlDC->LineTo(280, 380);
	pControlDC->MoveTo(280, 380);//畫線的開始位置
	pControlDC->LineTo(900, 380);
	pControlDC->MoveTo(280, 380);
	for (int i = 0; i < 5; i++)
	{
		pControlDC->SetPixel(0, 290, RGB(0, 0, 255));  //設置點的位置及顏色
		pControlDC->LineTo(i * 140 + 280, 380 - (380 * nScoreNum[i] / nNum));//換兩點之間的線
		str.Format("%d人", nScoreNum[i]);
		pControlDC->TextOut(i * 140 + 280, 380 - (380 * nScoreNum[i] / nNum) - 20, str);//在線的上方輸出文字
		pControlDC->TextOut(i * 140 + 280, 390, strSeg[i]);
	}
}


int CMFCApplication8View::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CView::OnCreate(lpCreateStruct) == -1)
		return -1;
	m_button1.Create((CString)"數學(直方)",//按鈕標題
		WS_CHILD | WS_VISIBLE | WS_BORDER,//按鈕風格
		CRect(10, 10, 200, 40),            //按鈕大小
		this,                          //按鈕父指針
		IDC_HIGGER1);                      //該按鈕對應的ID號
	m_button1.ShowWindow(SW_SHOWNORMAL);
	m_button2.Create((CString)"程序設計(直方)",//按鈕標題
		WS_CHILD | WS_VISIBLE | WS_BORDER,//按鈕風格
		CRect(10, 60, 200, 90),            //按鈕大小
		this,                          //按鈕父指針
		IDC_HIGGER2);                      //該按鈕對應的ID號
	m_button2.ShowWindow(SW_SHOWNORMAL);
	
	m_button4.Create((CString)"(折線)",//按鈕標題
		WS_CHILD | WS_VISIBLE | WS_BORDER,//按鈕風格
		CRect(200, 10, 270, 40),            //按鈕大小
		this,                          //按鈕父指針
		IDC_HIGGER4);                      //該按鈕對應的ID號
	m_button4.ShowWindow(SW_SHOWNORMAL);
	m_button5.Create((CString)"(折線)",//按鈕標題
		WS_CHILD | WS_VISIBLE | WS_BORDER,//按鈕風格
		CRect(200, 60, 270, 90),            //按鈕大小
		this,                          //按鈕父指針
		IDC_HIGGER5);                      //該按鈕對應的ID號
	m_button5.ShowWindow(SW_SHOWNORMAL);

	return 0;

}

void CMFCApplication8View::OnHigger1()
{
	// TODO: 在此添加命令處理程序代碼
	CFileDialog dlg(TRUE);	//打開“打開”界面
	if (dlg.DoModal() == IDOK)
	{
		CString strFile = dlg.GetPathName();	//返回文件路徑
		CFile file;
		if (!file.Open(strFile, CFile::modeReadWrite | CFile::shareDenyNone))
		{
			AfxMessageBox("文件無法打開,無法畫圖!");
			return;
		}
		Student u;
		int i = 0;
		int n;
		file.Read((char*)&n, sizeof(int));
		while (file.Read(&u, sizeof(u)) == sizeof(u))
		{
			m_Num[i] = _ttoi((CString)u.MTest);
			i++;
		}
		InvalidateRect(NULL);
		UpdateWindow();
		DrawScore(GetDC(), m_Num, i);
		file.Close();
	}
}


void CMFCApplication8View::OnHigger2()
{
	// TODO: 在此添加命令處理程序代碼
	CFileDialog dlg(TRUE);	//打開“打開”界面
	if (dlg.DoModal() == IDOK)
	{
		CString strFile = dlg.GetPathName();	//返回文件路徑
		CFile file;
		if (!file.Open(strFile, CFile::modeReadWrite | CFile::shareDenyNone))
		{
			AfxMessageBox("文件無法打開,無法畫圖!");
			return;
		}
		Student u;
		int i = 0;
		int n;
		file.Read((char*)&n, sizeof(int));
		while (file.Read(&u, sizeof(u)) == sizeof(u))
		{
			m_Num[i] = _ttoi((CString)u.CTest);
			i++;
		}
		InvalidateRect(NULL);
		UpdateWindow();
		DrawScore(GetDC(), m_Num, i);
		file.Close();
	}
}



void CMFCApplication8View::OnHigger4()
{
	// TODO: 在此添加命令處理程序代碼
	CFileDialog dlg(TRUE);	//打開“打開”界面
	if (dlg.DoModal() == IDOK)
	{
		CString strFile = dlg.GetPathName();	//返回文件路徑
		CFile file;
		if (!file.Open(strFile, CFile::modeReadWrite | CFile::shareDenyNone))
		{
			AfxMessageBox("文件無法打開,無法畫圖!");
			return;
		}
		Student u;
		int i = 0;
		int n;
		file.Read((char*)&n, sizeof(int));
		while (file.Read(&u, sizeof(u)) == sizeof(u))
		{
			m_Num[i] = _ttoi((CString)u.MTest);
			i++;
		}
		InvalidateRect(NULL);
		UpdateWindow();
		Drawlist(GetDC(), m_Num, i);
		file.Close();
	}
}


void CMFCApplication8View::OnHigger5()
{
	// TODO: 在此添加命令處理程序代碼
	CFileDialog dlg(TRUE);	//打開“打開”界面
	if (dlg.DoModal() == IDOK)
	{
		CString strFile = dlg.GetPathName();	//返回文件路徑
		CFile file;
		if (!file.Open(strFile, CFile::modeReadWrite | CFile::shareDenyNone))
		{
			AfxMessageBox("文件無法打開,無法畫圖!");
			return;
		}
		Student u;
		int i = 0;
		int n;
		file.Read((char*)&n, sizeof(int));
		while (file.Read(&u, sizeof(u)) == sizeof(u))
		{
			m_Num[i] = _tstoi(u.CTest);
			i++;
		}
		InvalidateRect(NULL);
		UpdateWindow();
		Drawlist(GetDC(), m_Num, i);
		file.Close();
	}

}
// Resource.h
//四個繪圖按鈕
#define IDC_HIGGER1					5001
#define IDC_HIGGER2					5002
#define IDC_HIGGER4					5004
#define IDC_HIGGER5					5005

四、程序運行時的效果圖

  1. 初始界面
    初始界面

  2. 填寫信息在這裏插入圖片描述

  3. 點選“增加”後在這裏插入圖片描述

  4. 點選左側列表框對信息進行修改在這裏插入圖片描述

  5. 點擊修改後可見左側列表框的總分和信息發生了改變在這裏插入圖片描述

  6. 增加了十個項目框在這裏插入圖片描述

  7. 列表框內信息:在這裏插入圖片描述

  8. 點選“保存”後
    在這裏插入圖片描述

  9. 點選“刪除”後List item

  10. 點選“讀取”後在這裏插入圖片描述

  11. “打開”文件後List item

  12. 排序方式選擇按數學成績排序後在這裏插入圖片描述

  13. 列表框內信息:可見與圖中排列方式一致在這裏插入圖片描述

  14. 排序方式選擇按程序設計成績排序後在這裏插入圖片描述

  15. 列表框內信息:可見與圖中排列方式一致在這裏插入圖片描述

  16. 排序方式選擇按總成績排序後在這裏插入圖片描述

  17. 列表框內信息:可見與圖中排列方式一致
    在這裏插入圖片描述

  18. 點選“繪圖”後List item

  19. 點選“數學(直方)”後在這裏插入圖片描述

  20. 點選“數學(折線)”後在這裏插入圖片描述

  21. 點選“程序設計(直方)”後在這裏插入圖片描述

  22. 點選“程序設計(折線)”後在這裏插入圖片描述

五、實驗結果分析,實驗收穫和體會。

1、實驗結果分析:

(1)調用sort函數進行排序,編寫了三種不同排序的bool型比較函數,將比較函數當陳參數傳入sort函數內。
(2)本實驗中按照降序進行排序。與一般的冒泡之類的排序方法不同的是,sort函數是通過不斷二分插入的方法進行排序的,時間複雜度爲nlogn,大大節省了排序時間。
(3)排序時將指針指向的列表內數據放入list中,然後將指針撤銷,將list內部的學生類數據按照選擇的排序方式進行排序,然後添加到列表中,實現排序。
(4)新建了Students.h頭文件存儲學生類
(5)將單文檔與管理系統關聯起來,使得在管理系統界面能夠實現繪圖功能。
(6)繪製了單文檔的按鈕,以及增加相應命令。

2、實驗收穫和體會:

(1)熟練使用UpdateDate函數進行界面數據更改與讀入。
(2)對如listbox等控件的使用有了深層次的理解
(3)對listbox的各項函數、、sort函數等的使用的更加得心應手。
(4)領悟了char與CString在調用時的區別,以及掌握了將浮點型轉化爲字符型的方法。
(5)能夠更加熟練的運用文件輸入輸出流對數據進行輸入輸出。
(6)踩過CString和double型數據的坑,後來把這些數據內容都改成了固定長度的char型。double類型和其他類型是不能緊挨着存儲的,都是會有空間浪費掉,但是作爲一個結構體存儲的時候,它們的數據會被挨在一起存放,重新讀取的時候就會出問題。
(7)對單文檔的繪圖功能有了一定的瞭解。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章