⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 student.cpp

📁 这个个系统是学生管理系统。利用SDK做界面
💻 CPP
📖 第 1 页 / 共 4 页
字号:
#include "stdafx.h"
#include "resource.h"

typedef struct tagDate
{
    unsigned int  m_nYear;
    unsigned int  m_nMonth;
    unsigned int  m_nDay;
}DATE, *LPDATE;

typedef struct tagStudentInfo
{
    char      m_szName[8];      // 姓名
    char      m_szNumber[8];    // 学号
    int       m_bSex;           // 性别,TRUE为男,FALSE为女
    DATE      m_dtBirthday;     // 出生年月日
    char      m_szClass[8];     // 班级
    char      m_szTelephone[10];// 电话
    char      m_szAddress[50];  // 家庭住址
    struct    tagStudentInfo  *m_lpNext;    // 下一个学生
}STUDENT_INFO, *LPSTUDENT_INFO;

// 枚举类型,定义一组枚举常量
enum tagSortBy{NUMBER=IDM_VIEW_NUMBER, NAME, SEX, AGE, CLASS, TELEPHONE, ADDRESS};

// 全局变量:
HINSTANCE       g_hAppInst = NULL;          // 全局变量,应用程序实例
HWND            g_hMainWnd = NULL;          // 全局变量,主窗口句柄

SIZE            g_sInfoTextSize = {1280, 100};      // 窗口中显示的文本最大高度和宽度
LPSTUDENT_INFO  g_lpStudentHeader = NULL;           // 学生链表头指针
TCHAR           g_szFileName[MAX_STRING] = "\0";    // 用来保存学生信息的文件名

BOOL            g_bIsSaved = TRUE;          // 文件是否已经保存
BOOL            g_bOrderByAsc = TRUE;       // 排序规则
UINT            g_uOrderByField = NUMBER;   // 排序字段
// 用户自定义函数:
// 一些回调函数:
LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);   // 主窗口回调函数
LRESULT CALLBACK AboutDlgProc(HWND, UINT, WPARAM, LPARAM);  // 【关于】对话框回调函数
LRESULT CALLBACK NewStuDlgProc(HWND, UINT, WPARAM, LPARAM); // 【增加新学生】对话框回调函数
LRESULT CALLBACK DeleteDlgProc(HWND, UINT, WPARAM, LPARAM); // 【删除学生】对话框回调函数

// 主窗口消息响应函数:
void    OnCreate(CREATESTRUCT *);       // 响应WM_CREATE消息
void    OnPaint(HDC);                   // 响应WM_PAINT消息
void    OnCommand(WPARAM, LPARAM);      // 响应WM_COMMAND消息
void    OnClose(void);                  // 响应WM_CLOSE消息
void    OnVScroll(UINT, UINT, HWND);    // 响应垂直滚动条消息WM_VSCROLL
void    OnHScroll(UINT, UINT, HWND);    // 响应水平滚动条消息WM_HSCROLL
void    OnSize(UINT, UINT);             // 响应WM_SIZE消息函数,窗口大小发生改变
void    OnRButtonUp(POINT, UINT);       // 鼠标右键抬起消息WM_RBUTTONUP
void    OnLButtonDblClk(POINT, UINT);   // 鼠标左键双击消息WM_LBUTTONDBCLICK
BOOL    OnFileSave(void);               // 响应菜单【文件】->【保存】事件
BOOL    OnFileSaveAs(void);             // 响应菜单【文件】->【另存为】事件
void    OnFileOpen(void);               // 响应菜单【文件】->【打开】事件
void    OnFileNew(void);                // 响应菜单【文件】->【新建】事件
void    OnViewNumber(void);             // 响应菜单【查看】->【按学号排序】事件
void    OnViewName(void);               // 响应菜单【查看】->【按姓名排序】事件
void    OnViewSex(void);                // 响应菜单【查看】->【按性别排序】事件
void    OnViewAge(void);                // 响应菜单【查看】->【按年龄排序】事件
void    OnViewClass(void);              // 响应菜单【查看】->【按班级排序】事件
void    OnViewTelephone(void);          // 响应菜单【查看】->【按电话号码排序】事件
void    OnViewAddress(void);            // 响应菜单【查看】->【按家庭住址排序】事件
void    OnToolAddNew(void);             // 响应菜单【工具】->【增加学生】事件
void    OnToolDelete(void);             // 响应菜单【工具】->【删除学生】事件
void    OnToolModify(void);             // 响应菜单【工具】->【修改学生】事件

// 链表操作函数
void    AddToLink(LPSTUDENT_INFO);       // 增加一个节点到链表
void    DeleteFromLink(LPSTUDENT_INFO);  // 删除一个节点
LPSTUDENT_INFO SearchLink(TCHAR *, BOOL);// 查找节点
void    ClearLink(void);                 // 清空链表
BOOL    SaveLinkToFile(void);            // 将链表保存到文件
BOOL    ReadLinkFromFile(void);          // 从文件读出链表
void    SortLinkBy(enum tagSortBy, BOOL);// 将链表以指定规则排序
void    ExChangeNode(LPSTUDENT_INFO, LPSTUDENT_INFO);   // 交换两个节点

// 其他一些函数
void    SetSaveFlag(BOOL);               // 设置保存标志
void    SaveQuestion(void);              // 文件数据可能已经更改,询问是否需要保存
TCHAR  *CommFileDlg(BOOL);               // 显示Windows通用对话框,保存或者打开文件对话框
int     CompareAge(DATE, DATE);          // 比较两个个学生的年龄
void    InitDateCombo(HWND);             // 初始化【添加新学生】对话框上的日期下拉框
void    InitScrollBar(SIZE, BOOL);       // 初始化主窗口滚动条
LPSTUDENT_INFO GetNewStudentInfo(HWND, LPSTUDENT_INFO);  // 得到新输入的或刚修改的学生信息

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
	MSG         msg;                      // 消息结构体
	HACCEL      hAccelTable;              // 加速键表资源句柄
	WNDCLASSEX  wcex;                     // 窗口类结构体
    TCHAR       szClass[MAX_STRING];      // 用来存放窗口类字符串
    TCHAR       szTitle[MAX_STRING];      // 用来存放窗口标题字符串
    HWND        hWnd;                     // 窗口句柄

	g_hAppInst = hInstance;

    // 从字符串资源中载入字符串
    LoadString(hInstance, IDC_STUDENT, szClass, MAX_STRING);
    // 开始注册窗口类
	wcex.cbSize         = sizeof(WNDCLASSEX); 
	wcex.style			= CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
	wcex.lpfnWndProc	= (WNDPROC)MainWndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(hInstance, (LPCTSTR)IDI_STUDENT);
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= (LPCSTR)IDC_STUDENT;
	wcex.lpszClassName	= szClass;
	wcex.hIconSm		= LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
	RegisterClassEx(&wcex);  // 注册窗口类

	// 从字符串资源中载入字符串
    LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_STRING);
    // 创建窗口
    hWnd = CreateWindow(szClass, szTitle, WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL,
                    CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

    if (!hWnd)     return 0;

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

	// 载入加速键资源
    hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_STUDENT);

	// 主消息循环:
	while (GetMessage(&msg, NULL, 0, 0)) 
	{
		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

    UnregisterClass(szClass, hInstance);  // 反注册窗口类

	return msg.wParam;
}

// 主窗口回调函数:
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message) 
	{
		case WM_CREATE:
            g_hMainWnd = hWnd;
            OnCreate((LPCREATESTRUCT)lParam);
            break;
        case WM_COMMAND:
            OnCommand(wParam, lParam);
			break;
		case WM_PAINT:
            PAINTSTRUCT ps;
            HDC         hdc;
            hdc = BeginPaint(hWnd, &ps);
            OnPaint(hdc);
            EndPaint(hWnd, &ps);
			break;
		case WM_SIZE:       // 当窗口大小发生改变的时候得到此消息
		    OnSize(LOWORD(lParam), HIWORD(lParam));
		    break;
		case WM_VSCROLL:    // 当垂直滚动条发生改变是发送此消息,比如拖动滚动条等
		    OnVScroll(LOWORD(wParam), HIWORD(wParam), NULL);
		    break;
		case WM_HSCROLL:    // 当水平滚动条发生改变是发送此消息,比如拖动滚动条等
		    OnHScroll(LOWORD(wParam), HIWORD(wParam), NULL);
            break;
        case WM_CLOSE:
            OnClose();
            break;
        case WM_RBUTTONUP:
            POINT  pt1;
            pt1.x = LOWORD(lParam);
            pt1.y = HIWORD(lParam);
            OnRButtonUp(pt1, wParam);
            break;
        case WM_LBUTTONDBLCLK:
            POINT  pt2;
            pt2.x = LOWORD(lParam);
            pt2.y = HIWORD(lParam);
            OnLButtonDblClk(pt2, wParam);
            break;
		case WM_DESTROY:
			PostQuitMessage(0);
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
   }
   return 0;
}

/////////////////////////////////////////////////////////////////
// 下面的所有函数都是主窗口消息响应函数
////////////////////////////////////////////////////////////////

// 响应WM_CREATE消息
void OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    HMENU   hMenu;

    ClearLink();        // 窗口刚刚创建,清除链表结构
    SetSaveFlag(TRUE);  // 没有信息,无所谓保存

    // 设置【查看】菜单下的菜单项单选状况
    hMenu = GetMenu(g_hMainWnd);
    CheckMenuRadioItem(hMenu, IDM_VIEW_ASC, IDM_VIEW_DESC, IDM_VIEW_ASC, MF_BYCOMMAND);
    CheckMenuRadioItem(hMenu, IDM_VIEW_NUMBER, IDM_VIEW_ADDRESS, IDM_VIEW_NUMBER, MF_BYCOMMAND);

    g_bOrderByAsc = TRUE;
    g_uOrderByField = NUMBER;
}

// 响应WM_COMMAND消息
void OnCommand(WPARAM wParam, LPARAM lParam)
{
    int     wmEvent, wmID;
    HMENU   hMenu = NULL;

    wmID    = LOWORD(wParam); 
    wmEvent = HIWORD(wParam); 

    switch(wmID)
    {
	    case IDM_HELP_ABOUT:    // 菜单【帮助->关于】项
		    DialogBox(g_hAppInst, (LPCTSTR)IDD_ABOUTBOX, g_hMainWnd, (DLGPROC)AboutDlgProc);
		    break;
        case IDM_HELP_HELP:     // 菜单【帮助->帮助】项
            MessageBox(g_hMainWnd, "即将显示帮助", "消息", MB_OK);
            break;
        case IDM_FILE_SAVE:     // 菜单【文件->保存】项
            OnFileSave();
            break;
        case IDM_FILE_SAVEAS:   // 菜单【文件->另存为】项
            OnFileSaveAs();
            break;
        case IDM_FILE_NEW:      // 菜单【文件->新建】项
            OnFileNew();
            break;
        case IDM_FILE_OPEN:     // 菜单【文件->打开】项
            OnFileOpen();
            break;
	    case IDM_FILE_EXIT:     // 菜单【文件->退出】项
	        PostMessage(g_hMainWnd, WM_CLOSE, 0, 0);
	        break;
        case IDM_VIEW_NAME:     // 菜单【查看->按姓名排序】事件
        case IDM_VIEW_NUMBER:   // 菜单【查看->按学号排序】事件
        case IDM_VIEW_SEX:      // 菜单【查看->按性别排序】项
        case IDM_VIEW_AGE:      // 菜单【查看->按年龄排序】项
        case IDM_VIEW_CLASS:    // 菜单【查看->按班级排序】项
        case IDM_VIEW_TELEPHONE:// 菜单【查看->按电话号码排序】项
        case IDM_VIEW_ADDRESS:  // 菜单【查看->按家庭住址排序】项
            g_uOrderByField = wmID; // 将排序字段保存到全局变量
            // 实现排序
            SortLinkBy((enum tagSortBy)g_uOrderByField, g_bOrderByAsc);
            // 设置菜单单选状态
            hMenu = GetMenu(g_hMainWnd);
            CheckMenuRadioItem(hMenu, IDM_VIEW_NUMBER, IDM_VIEW_ADDRESS, wmID, MF_BYCOMMAND);
            InvalidateRect(g_hMainWnd, NULL, TRUE);
            break;
        case IDM_VIEW_ASC:      // 菜单【查看->升序】项
        case IDM_VIEW_DESC:     // 菜单【查看->降序】项
            g_bOrderByAsc = (wmID == IDM_VIEW_ASC); // 将排序规则保存到全局变量
            // 实现排序
            SortLinkBy((enum tagSortBy)g_uOrderByField, g_bOrderByAsc);
            // 设置菜单单选状态
            hMenu = GetMenu(g_hMainWnd);
            CheckMenuRadioItem(hMenu, IDM_VIEW_ASC, IDM_VIEW_DESC, wmID, MF_BYCOMMAND);
            InvalidateRect(g_hMainWnd, NULL, TRUE);
            break;
        case IDM_VIEW_FRESH:    // 菜单【查看】->【刷新】事件
            InvalidateRect(g_hMainWnd, NULL, TRUE);
            break;
        case IDM_TOOL_ADDNEW:   // 菜单【工具】->【增加新学生】事件
            OnToolAddNew();
            break;
        case IDM_TOOL_DELETE:   // 菜单【工具】->【删除学生】事件
            OnToolDelete();
            break;
        case IDM_TOOL_MODIFY:   // 菜单【工具】->【修改学生】事件
            OnToolModify();
            break;
        default: 
            DefWindowProc(g_hMainWnd, WM_COMMAND, wParam, lParam);
            break;
    }
    return;
}

// 响应消息WM_PAINT,将学生信息显示到屏幕
void OnPaint(HDC hMainDC)
{

    TCHAR           szTitle[MAX_STRING] = "学号              "      // 显示列表的标题
                                          "姓名              "
                                          "性别 "
                                          "出生年月            "
                                          "班级                  "
                                          "联系电话          "
                                          "家庭住址";
    TCHAR           szSex[4]            = "男";
    TCHAR           szBirthday[20]      = "8888年88月88日";
    HFONT           hFont = NULL, hOldFont = NULL;
    LPSTUDENT_INFO  lpTmp = NULL;
    RECT            rt;
    int             xOrg, yOrg, yPos = 0;

    GetClientRect(g_hMainWnd, &rt);     // 得到客户区大小

    // 注:如果本窗口没有滚动条,则下面3行代码可以去掉
    xOrg = -GetScrollPos(g_hMainWnd, SB_HORZ);      // 得到水平滚动条的位置
    yOrg = -GetScrollPos(g_hMainWnd, SB_VERT);      // 得到垂直滚动条的位置
    SetViewportOrgEx(hMainDC, xOrg, yOrg, NULL);    // 设置视口起点

    // 创建一个字体,以后的文字输出按照此字体输出
    // 如果不使用自创字体,则可能导致输出难以对齐,输出不够美观
    hFont   = CreateFont(14,                    // 字体高度16像素
                         7,                     // 字体宽度16像素
                         0,                     // 字体不倾斜
                         0,                     // 行不倾斜
                         FW_SEMIBOLD,           // 字体适当加粗
                         FALSE,                 // 字体不斜体
                         FALSE,                 // 字体不加下划线
                         FALSE,                 // 字体不加删除线(中划线)
                         ANSI_CHARSET,          // ANSI字符
                         OUT_DEFAULT_PRECIS,    // 缺省输出精度
                         CLIP_DEFAULT_PRECIS,   // 缺省输出精度
                         DEFAULT_QUALITY,       // 缺省输出质量
                         DEFAULT_PITCH,         // 缺省字符间距
                         NULL);                 // 使用默认字体名

    // 将字体选入设备上下文
    hOldFont = (HFONT)SelectObject(hMainDC, hFont);
    // 显示表头信息
    SetTextColor(hMainDC, RGB(255,50,50));
    TextOut(hMainDC, 0, yPos, szTitle, strlen(szTitle));
    MoveToEx(hMainDC, 0, 20, NULL);
    LineTo(hMainDC, 1280, 20);
    MoveToEx(hMainDC, 0, 22, NULL);
    LineTo(hMainDC, 1280, 22);

    // 开始显示学生信息
    lpTmp = g_lpStudentHeader;
    yPos = 30;
    SetTextColor(hMainDC, RGB(50,50,255));
    while(lpTmp != NULL)
    {
        // 初始化“性别”字段
        if(lpTmp->m_bSex)  sprintf(szSex, "男");
        else               sprintf(szSex, "女");
        // 初始化“出生年月”字段
        sprintf(szBirthday, "%04d年%02d月%02d日",
            lpTmp->m_dtBirthday.m_nYear, lpTmp->m_dtBirthday.m_nMonth, lpTmp->m_dtBirthday.m_nDay);
        
        // 显示学生学号
        TextOut(hMainDC,   0, yPos, lpTmp->m_szNumber, strlen(lpTmp->m_szNumber));
        // 显示学生姓名
        TextOut(hMainDC, 100, yPos, lpTmp->m_szName, strlen(lpTmp->m_szName));
        // 显示学生性别
        TextOut(hMainDC, 200, yPos, szSex, strlen(szSex));
        // 显示学生出生年月日
        TextOut(hMainDC, 230, yPos, szBirthday, strlen(szBirthday));
        // 显示学生班级号
        TextOut(hMainDC, 355, yPos, lpTmp->m_szClass, strlen(lpTmp->m_szClass));
        // 显示学生电话号码
        TextOut(hMainDC, 470, yPos, lpTmp->m_szTelephone, strlen(lpTmp->m_szTelephone));
        // 显示学生家庭住址

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -