📄 student.cpp
字号:
TextOut(hMainDC, 585, yPos, lpTmp->m_szAddress, strlen(lpTmp->m_szAddress));
lpTmp = lpTmp->m_lpNext;
yPos += 16; // 每次都必须让yPos增加,实现每个学生只占用一行
}
SelectObject(hMainDC, hOldFont);// 恢复设备上下文
DeleteObject(hFont); // 删除创建的字体
}
// 右键弹起消息WM_RBUTTONUP
// 将弹出一个快捷菜单
void OnRButtonUp(POINT pt, UINT wFlags)
{
HMENU hMenu, hSubMenu;
hMenu = LoadMenu(g_hAppInst, MAKEINTRESOURCE(IDR_RIGHT));
hSubMenu = GetSubMenu(hMenu, 0);
ClientToScreen(g_hMainWnd, &pt);
TrackPopupMenu(hSubMenu, TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, 0, g_hMainWnd, NULL);
DestroyMenu(hMenu);
}
// 左键双击实践WM_LBUTTONDBCLK,也可用来修改学生信息
void OnLButtonDblClk(POINT pt, UINT wFlags)
{
OnToolModify();
}
// 处理窗口大小变化消息WM_SIZE
// UINT nWidht:当前窗口的宽度
// UINT nHeight:当前窗口的高度
void OnSize(UINT nWidth, UINT nHeight)
{
//SCROLLINFO si;
//int nPos;
SIZE size;
size.cx = nWidth;
size.cy = nHeight;
InitScrollBar(size, TRUE); // 初始化水平滚动条
InitScrollBar(size, FALSE); // 初始化垂直滚动条
}
// 处理垂直滚动条消息WM_VSCROLL
// UINT nSBCode:滚动类型
// UINT nPos:滚动条滑块位置
// HWND hScrollBar:滚动条控件句柄
void OnVScroll(UINT nSBCode, UINT nPos, HWND hScrollBar)
{
static int nOriginalPos = 0;
int nTmp;
RECT rt;
nTmp = nOriginalPos;
switch(nSBCode)
{
case SB_TOP: // 一次性达到最顶端
nTmp = 0;
break;
case SB_BOTTOM: // 一次性达到最底端
nTmp = g_sInfoTextSize.cy;
break;
case SB_PAGEUP: // 向上翻页
nTmp -= 150;
if(nTmp < 0) nTmp = 0;
break;
case SB_PAGEDOWN: // 向下翻页
nTmp += 150;
if(nTmp > g_sInfoTextSize.cy) nTmp = g_sInfoTextSize.cy;
break;
case SB_LINEUP: // 向下翻动,通常是点击滚动条的向下箭头
nTmp -= 20;
if(nTmp < 0) nTmp = 0;
break;
case SB_LINEDOWN: // 向下翻动,通常是点击滚动条的向下箭头
nTmp += 20;
if(nTmp > g_sInfoTextSize.cy) nTmp = g_sInfoTextSize.cy;
break;
case SB_THUMBTRACK: // 正在拖动
nTmp = nPos;
break;
case SB_THUMBPOSITION: // 拖动即将结束
break;
case SB_ENDSCROLL: // 停止滚动
break;
default: break;
}
// 设置滚动条上滑块的位置
SetScrollPos(g_hMainWnd, SB_VERT, nTmp, TRUE);
// 滚动窗口
ScrollWindow(g_hMainWnd, 0, nOriginalPos - nTmp, NULL, NULL);
// 下面计算窗口中需要更新的区域
rt.left = 0; rt.right = g_sInfoTextSize.cx;
if(nTmp > nOriginalPos)
{
rt.bottom = g_sInfoTextSize.cy;
rt.top = rt.bottom - (nTmp - nOriginalPos);
}
else
{
rt.top = 0;
rt.bottom = rt.top + (nOriginalPos - nTmp);
}
// 更新区域
InvalidateRect(g_hMainWnd, &rt, TRUE);
nOriginalPos = nTmp;
}
// 处理水平滚动条消息WM_HSCROLL
// UINT nSBCode:滚动类型
// UINT nPos:滚动条滑块位置
// HWND hScrollBar:滚动条控件句柄
void OnHScroll(UINT nSBCode, UINT nPos, HWND hScrollBar)
{
static int nOriginalPos = 0;
int nTmp;
RECT rt;
nTmp = nOriginalPos;
switch(nSBCode)
{
case SB_LEFT: // 一次性达到最顶端
nTmp = 0;
break;
case SB_RIGHT: // 一次性达到最底端
nTmp = g_sInfoTextSize.cx;
break;
case SB_PAGELEFT: // 向上翻页
nTmp -= 150;
if(nTmp < 0) nTmp = 0;
break;
case SB_PAGERIGHT: // 向下翻页
nTmp += 150;
if(nTmp > g_sInfoTextSize.cx) nTmp = g_sInfoTextSize.cx;
break;
case SB_LINELEFT: // 向下翻动,通常是点击滚动条的向下箭头
nTmp -= 20;
if(nTmp < 0) nTmp = 0;
break;
case SB_LINERIGHT: // 向下翻动,通常是点击滚动条的向下箭头
nTmp += 20;
if(nTmp > g_sInfoTextSize.cx) nTmp = g_sInfoTextSize.cx;
break;
case SB_THUMBTRACK: // 正在拖动
nTmp = nPos;
break;
case SB_THUMBPOSITION: // 拖动即将结束
break;
case SB_ENDSCROLL: // 停止滚动
break;
default: break;
}
SetScrollPos(g_hMainWnd, SB_HORZ, nTmp, TRUE);
ScrollWindow(g_hMainWnd, nOriginalPos - nTmp, 0, NULL, NULL);
rt.top = 0; rt.bottom = g_sInfoTextSize.cy;
if(nTmp > nOriginalPos)
{
rt.right = g_sInfoTextSize.cx;
rt.left = rt.right - (nTmp - nOriginalPos);
}
else
{
rt.left = 0;
rt.right = rt.left + (nOriginalPos - nTmp);
}
InvalidateRect(g_hMainWnd, &rt, TRUE);
nOriginalPos = nTmp;
}
// 响应消息WM_CLOSE
void OnClose(void)
{
if(!g_bIsSaved)
{
int nRet;
nRet = MessageBox(g_hMainWnd, "文件数据已经被更改,是否需要保存?",
"提示", MB_YESNOCANCEL | MB_ICONQUESTION);
if(nRet == IDCANCEL) return;
else if(nRet == IDYES)
{
OnFileSave();
}
}
DefWindowProc(g_hMainWnd, WM_CLOSE, 0, 0);
}
// 响应菜单项【新建信息文件】事件
void OnFileNew(void)
{
if(!g_bIsSaved)
{
int nRet;
nRet = MessageBox(g_hMainWnd, "当前数据已经更改,在打开新文件前是否需要保存原数据?",
"提示", MB_ICONQUESTION | MB_YESNOCANCEL);
if(nRet == IDCANCEL) return;
else if(nRet == IDYES)
{
OnFileSave();
}
}
ClearLink();
memset(g_szFileName, '\0', sizeof(g_szFileName));
SetSaveFlag(TRUE);
InvalidateRect(g_hMainWnd, NULL, TRUE);
}
// 响应菜单项【保存文件】事件
BOOL OnFileSave(void)
{
// 如果文件从来就没有被保存过,即文件还没有命名,
// 则直接调用【另存为】项功能
if(!strlen(g_szFileName))
return OnFileSaveAs();
else if(!SaveLinkToFile()) // 将文件保存到链表
{
MessageBox(g_hMainWnd, " 文件保存失败!磁盘错误!", "错误", MB_OK | MB_ICONERROR);
SetSaveFlag(FALSE);
return FALSE;
}
SetSaveFlag(TRUE);
return TRUE;
}
// 响应菜单项【文件另存为】事件
// 返回值:TRUE表示已经保存好,FALSE表示没有保存
BOOL OnFileSaveAs(void)
{
TCHAR *lpszFilePath = NULL;
TCHAR *lpTmp;
lpszFilePath = CommFileDlg(TRUE);
if(!lpszFilePath) return FALSE;
// 下面的代码检查用户是否为文件输入了扩展名,如果没有输入扩展名,则加上默认扩展名".DAT"
lpTmp = lpszFilePath;
while(!*lpTmp) lpTmp++; // 搜索到字符串的最后
while(*lpTmp != '.') lpTmp--; // 找到最后一个‘.’字符,即看用户是否输入了文件后缀名
if(lpTmp == lpszFilePath)
{
strcat(lpszFilePath, ".dat");
}
// 将最终的文件路径保存到全局变量
strcpy(g_szFileName, lpszFilePath);
if(!SaveLinkToFile())
{
MessageBox(g_hMainWnd, " 文件保存失败!磁盘错误!", "错误", MB_OK | MB_ICONERROR);
return FALSE;
}
SetSaveFlag(TRUE);
return TRUE;
}
// 响应菜单项【打开文件】事件
void OnFileOpen(void)
{
TCHAR *lpText = NULL;
RECT rt;
SIZE size;
int cy = 0;
LPSTUDENT_INFO lpTmp = NULL;
lpText = CommFileDlg(FALSE); // 显示Windows通用文件对话框
if(!lpText) return;
if(!g_bIsSaved)
{
int nRet;
nRet = MessageBox(g_hMainWnd, "当前数据已经更改,在打开新文件前是否需要保存原数据?",
"提示", MB_ICONQUESTION | MB_YESNOCANCEL);
if(nRet == IDCANCEL) return;
else if(nRet == IDYES)
{
if(!OnFileSave())
{
return;
}
}
}
ClearLink();
strcpy(g_szFileName, lpText);
if(!ReadLinkFromFile())
{
MessageBox(g_hMainWnd, " 文件打开失败!数据错误!", "错误", MB_OK | MB_ICONERROR);
ClearLink();
}
SortLinkBy((enum tagSortBy)g_uOrderByField, g_bOrderByAsc);
SetSaveFlag(TRUE);
GetClientRect(g_hMainWnd, &rt);
size.cx = rt.right - rt.left;
size.cy = rt.bottom - rt.top;
// 重置滚动条
lpTmp=g_lpStudentHeader;
cy = 60;
while(lpTmp)
{
cy += 16;
lpTmp=lpTmp->m_lpNext;
}
g_sInfoTextSize.cy = cy; // 得到文本的高度
InitScrollBar(size, FALSE); // 重置滚动条
InvalidateRect(g_hMainWnd, NULL, TRUE);
return;
}
// 响应菜单项【添加新学生】事件
void OnToolAddNew(void)
{
int nRet;
RECT rt;
SIZE size;
// 弹出【新建学生】对话框
nRet = DialogBoxParam(g_hAppInst, (LPCTSTR)IDD_NEWSTU_DLG, g_hMainWnd, (DLGPROC)NewStuDlgProc, NULL);
if(nRet == IDCANCEL || nRet == 0) return;
AddToLink((LPSTUDENT_INFO)nRet); // 将学生信息添加到链表
g_sInfoTextSize.cy += 16; // 当前文本信息的最大宽度将增加
GetClientRect(g_hMainWnd, &rt);
size.cx = rt.right - rt.left;
size.cy = rt.bottom - rt.top;
InitScrollBar(size, FALSE); // 此时还需要重置垂直滚动条
// 保证插入新节点之后链表仍然是排序的
SortLinkBy((enum tagSortBy)g_uOrderByField, g_bOrderByAsc);
SetSaveFlag(FALSE);
InvalidateRect(g_hMainWnd, NULL, TRUE);
return;
}
// 响应菜单项【删除一个学生】事件
void OnToolDelete(void)
{
int nRet;
RECT rt;
SIZE size;
// 弹出【删除一个学生】对话框
nRet = DialogBoxParam(g_hAppInst, (LPCTSTR)IDD_DELETE_DLG, g_hMainWnd, (DLGPROC)DeleteDlgProc, TRUE);
if(nRet == IDCANCEL) return;
DeleteFromLink((LPSTUDENT_INFO)nRet);
g_sInfoTextSize.cy -= 16; // 当前文本信息的最大宽度将减少
GetClientRect(g_hMainWnd, &rt);
size.cx = rt.right - rt.left;
size.cy = rt.bottom - rt.top;
InitScrollBar(size, FALSE); // 此时需要重置垂直滚动条
InvalidateRect(g_hMainWnd, NULL, TRUE);
}
// 响应菜单项【修改一个学生信息】事件
void OnToolModify(void)
{
// 弹出【修改一个学生信息】对话框
DialogBoxParam(g_hAppInst, (LPCTSTR)IDD_DELETE_DLG, g_hMainWnd, (DLGPROC)DeleteDlgProc, FALSE);
}
/////////////////////////////////////////////////////////////////
// 主窗口消息响应函数到此结束
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
// 下面都是链表操作函数
/////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -