This repository has been archived by the owner on Jun 27, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
1,116 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,34 @@ | ||
# SUSTech_HowManyGPA | ||
SUSTech's GPA Viewer | ||
SUSTech GPA Viewer | ||
|
||
## 运行环境 | ||
|
||
- 64位Windows操作系统 | ||
|
||
## 运行 | ||
|
||
### 介绍 | ||
|
||
项目是MFC应用程序,使用Visual Studio 2019编译,项目编码为多字节。 | ||
|
||
程序需要访问网络。 | ||
|
||
程序不会保存,或向除CAS系统以外的地方发送学生个人CAS账号密码。 | ||
|
||
程序先向CAS系统post账号密码登录,然后前往教务系统读取成绩信息。 | ||
|
||
### GPA计算 | ||
|
||
暂未找到同一节课多次F的案例,未知多次F时,GPA计入多次F,还是只计入一个F,程序代码暂时按仅计入1个F计算。 | ||
|
||
### 挖坑 | ||
|
||
- 加上根据课程编号前缀筛选功能 | ||
- 加上根据课程编号排序功能 | ||
- 减少画面卡顿和闪烁 | ||
- 迁移到Qt | ||
- 开发小程序 | ||
|
||
## 注 | ||
|
||
本程序内图片来源网络。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,208 @@ | ||
// DIALOG_LOGIN.cpp: 实现文件 | ||
// | ||
|
||
#include "pch.h" | ||
#include "SUSTech_HowManyGPA.h" | ||
#include "DIALOG_LOGIN.h" | ||
#include "afxinet.h" | ||
#include <regex> | ||
|
||
// DIALOG_LOGIN 对话框 | ||
|
||
IMPLEMENT_DYNAMIC(DIALOG_LOGIN, CDialogEx) | ||
|
||
DIALOG_LOGIN::DIALOG_LOGIN(CWnd* pParent /*=nullptr*/) | ||
: CDialogEx(IDD_DIALOG_LOGIN, pParent) | ||
, inputAccount(_T("")) | ||
, inputPassword(_T("")) | ||
{ | ||
|
||
} | ||
|
||
DIALOG_LOGIN::~DIALOG_LOGIN() | ||
{ | ||
} | ||
|
||
void DIALOG_LOGIN::DoDataExchange(CDataExchange* pDX) | ||
{ | ||
CDialogEx::DoDataExchange(pDX); | ||
DDX_Text(pDX, IDC_EDIT_ACCOUNT, inputAccount); | ||
DDX_Text(pDX, IDC_EDIT_PASSWORD, inputPassword); | ||
} | ||
|
||
|
||
BEGIN_MESSAGE_MAP(DIALOG_LOGIN, CDialogEx) | ||
ON_BN_CLICKED(IDOK, &DIALOG_LOGIN::OnBnClickedOk) | ||
ON_BN_CLICKED(IDCANCEL, &DIALOG_LOGIN::OnBnClickedCancel) | ||
ON_WM_PAINT() | ||
ON_WM_CTLCOLOR() | ||
ON_WM_DRAWITEM() | ||
END_MESSAGE_MAP() | ||
|
||
|
||
// DIALOG_LOGIN 消息处理程序 | ||
BOOL DIALOG_LOGIN::OnInitDialog() | ||
{ | ||
newFont.CreatePointFont(120, "等线"); | ||
GetDlgItem(IDC_STATIC_ACCOUNT)->SetFont(&newFont); | ||
GetDlgItem(IDC_STATIC_PASSWORD)->SetFont(&newFont); | ||
GetDlgItem(IDOK)->SetFont(&newFont); | ||
GetDlgItem(IDCANCEL)->SetFont(&newFont); | ||
return TRUE; | ||
} | ||
|
||
|
||
wchar_t* DIALOG_LOGIN::UTF8toWide(CString& str) | ||
{ | ||
char* pStr = (char*)str.GetBuffer(str.GetLength()); | ||
int nBufferSize = MultiByteToWideChar(CP_UTF8, 0, pStr, -1, NULL, 0); | ||
wchar_t* pBuffer = (wchar_t*)malloc(nBufferSize * sizeof(wchar_t)); | ||
MultiByteToWideChar(CP_UTF8, 0, pStr, -1, pBuffer, nBufferSize); | ||
return pBuffer; | ||
} | ||
|
||
|
||
char* DIALOG_LOGIN::WidetoUTF8(CString& str) | ||
{ | ||
// CString to Unicode | ||
char* pStr = (char*)str.GetBuffer(str.GetLength()); | ||
int nBufferSize = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, pStr, -1, NULL, 0); | ||
wchar_t* wszUTF8 = new wchar_t[nBufferSize + 1]; | ||
memset(wszUTF8, 0, nBufferSize * 2 + 2); | ||
MultiByteToWideChar(CP_ACP, 0, pStr, -1, wszUTF8, nBufferSize); | ||
|
||
// Unicode to UTF-8 | ||
nBufferSize = WideCharToMultiByte(CP_UTF8, 0, wszUTF8, -1, NULL, 0, NULL, NULL); | ||
char* szUTF8 = new char[nBufferSize + 1]; | ||
memset(szUTF8, 0, nBufferSize + 1); | ||
WideCharToMultiByte(CP_UTF8, 0, wszUTF8, -1, szUTF8, nBufferSize, NULL, NULL); | ||
delete[] wszUTF8; | ||
return szUTF8; | ||
} | ||
|
||
|
||
void DIALOG_LOGIN::OnBnClickedOk() | ||
{ | ||
// TODO: 在此添加控件通知处理程序代码 | ||
UpdateData(TRUE); | ||
if (inputAccount.GetLength() != 8) { | ||
AfxMessageBox("请输入正确长度的学号!"); | ||
return; | ||
} | ||
|
||
CString loginURL = "cas.sustech.edu.cn"; | ||
CHttpConnection* pServer = session.GetHttpConnection(loginURL, INTERNET_FLAG_SECURE, (INTERNET_PORT)443, NULL, NULL); | ||
CHttpFile* pfile = pServer->OpenRequest(CHttpConnection::HTTP_VERB_GET, "/cas/login", NULL, 1, | ||
NULL, NULL, INTERNET_FLAG_SECURE | INTERNET_FLAG_TRANSFER_ASCII | INTERNET_FLAG_DONT_CACHE); | ||
pfile->SendRequest(); | ||
DWORD dwRet; | ||
pfile->QueryInfoStatusCode(dwRet); | ||
if (dwRet != HTTP_STATUS_OK) { | ||
AfxMessageBox("网络异常!"); | ||
return; | ||
} | ||
|
||
CString getCAS = "", strLine; | ||
while (pfile->ReadString(strLine)) | ||
getCAS += strLine; | ||
wchar_t* pBuffer = UTF8toWide(getCAS); | ||
std::wstring wstr = pBuffer; | ||
|
||
CString postInformation; | ||
std::wregex regCASInformation(L"on\" value=\"(.+?)\""); | ||
std::wsmatch wsm; | ||
std::regex_search(wstr, wsm, regCASInformation); | ||
postInformation = (CString)("username=" + inputAccount + "&password=" + inputPassword + "&_eventId=submit&execution="); | ||
postInformation += ((std::wstring)wsm[1]).c_str(); | ||
free(pBuffer); | ||
|
||
pfile = pServer->OpenRequest(CHttpConnection::HTTP_VERB_POST, "/cas/login?service=https%3A%2F%2Fjwxt.sustech.edu.cn%2Fjsxsd%2F", NULL, 1, | ||
NULL, NULL, INTERNET_FLAG_SECURE | INTERNET_FLAG_TRANSFER_ASCII | INTERNET_FLAG_DONT_CACHE); | ||
char* wait_send = WidetoUTF8(postInformation); | ||
CString strHeaders = "Content-Type: application/x-www-form-urlencoded\r\n"; | ||
pfile->SendRequest(strHeaders, wait_send, strlen(wait_send)); | ||
pfile->QueryInfoStatusCode(dwRet); | ||
delete[] wait_send; | ||
|
||
getCAS = "", strLine; | ||
while (pfile->ReadString(strLine)) | ||
getCAS += strLine; | ||
pBuffer = UTF8toWide(getCAS); | ||
wstr = pBuffer; | ||
|
||
if (dwRet == HTTP_STATUS_DENIED || (dwRet == HTTP_STATUS_OK && wstr.find(L"登录成功") == wstr.npos)) { | ||
AfxMessageBox("密码错误!"); | ||
return; | ||
} | ||
else if (dwRet != HTTP_STATUS_OK) { | ||
AfxMessageBox("网络异常!"); | ||
return; | ||
} | ||
CDialogEx::OnOK(); | ||
::SendMessage(GetParent()->m_hWnd, WM_USER_FRESH_SCORE, (WPARAM)0, (LPARAM)0); | ||
} | ||
|
||
|
||
void DIALOG_LOGIN::OnBnClickedCancel() | ||
{ | ||
// TODO: 在此添加控件通知处理程序代码 | ||
CDialogEx::OnCancel(); | ||
::SendMessage(GetParent()->m_hWnd, WM_CLOSE, 0, 0); | ||
} | ||
|
||
|
||
void DIALOG_LOGIN::OnPaint() | ||
{ | ||
CPaintDC dc(this); // device context for painting | ||
// TODO: 在此处添加消息处理程序代码 | ||
// 不为绘图消息调用 CDialogEx::OnPaint() | ||
CRect myrect; | ||
GetClientRect(&myrect); | ||
CDC dcMem; | ||
dcMem.CreateCompatibleDC(&dc); | ||
CBitmap bmpBackground; | ||
bmpBackground.LoadBitmap(IDB_BITMAP_LOGIN); | ||
BITMAP bitmap; | ||
bmpBackground.GetBitmap(&bitmap); | ||
CBitmap* pbmpOld = dcMem.SelectObject(&bmpBackground); | ||
dc.StretchBlt(0, 0, myrect.Width(), myrect.Height(), &dcMem, 0, 0, | ||
bitmap.bmWidth, bitmap.bmHeight, SRCCOPY); | ||
|
||
CDialogEx::OnPaint(); | ||
} | ||
|
||
|
||
HBRUSH DIALOG_LOGIN::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) | ||
{ | ||
HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor); | ||
|
||
// TODO: 在此更改 DC 的任何特性 | ||
if (pWnd->GetDlgCtrlID() == IDC_STATIC_ACCOUNT || pWnd->GetDlgCtrlID() == IDC_STATIC_PASSWORD) | ||
{ | ||
pDC->SetTextColor(RGB(20, 60, 80)); | ||
pDC->SetBkMode(TRANSPARENT); | ||
hbr = (HBRUSH)GetStockObject(NULL_BRUSH); | ||
} | ||
// TODO: 如果默认的不是所需画笔,则返回另一个画笔 | ||
return hbr; | ||
} | ||
|
||
|
||
void DIALOG_LOGIN::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) | ||
{ | ||
// TODO: 在此添加消息处理程序代码和/或调用默认值 | ||
if (nIDCtl == IDOK || nIDCtl == IDCANCEL) { | ||
CDC dc; | ||
dc.Attach(lpDrawItemStruct->hDC); | ||
|
||
CString strText; | ||
((CButton*)GetDlgItem(nIDCtl))->GetWindowText(strText); | ||
dc.Draw3dRect(&(lpDrawItemStruct->rcItem), RGB(0, 0, 0), RGB(255, 255, 255)); | ||
dc.FillSolidRect(&(lpDrawItemStruct->rcItem), RGB(50, 170, 165)); | ||
DrawText(lpDrawItemStruct->hDC, strText, strText.GetLength(), | ||
&lpDrawItemStruct->rcItem, DT_SINGLELINE | DT_VCENTER | DT_CENTER); | ||
dc.Detach(); | ||
} | ||
else | ||
CDialogEx::OnDrawItem(nIDCtl, lpDrawItemStruct); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
#pragma once | ||
#include "afxinet.h" | ||
#define WM_USER_FRESH_SCORE WM_USER+1 | ||
// DIALOG_LOGIN 对话框 | ||
class DIALOG_LOGIN : public CDialogEx | ||
{ | ||
DECLARE_DYNAMIC(DIALOG_LOGIN) | ||
|
||
public: | ||
DIALOG_LOGIN(CWnd* pParent = nullptr); // 标准构造函数 | ||
virtual ~DIALOG_LOGIN(); | ||
|
||
// 对话框数据 | ||
#ifdef AFX_DESIGN_TIME | ||
enum { IDD = IDD_DIALOG_LOGIN }; | ||
#endif | ||
|
||
protected: | ||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 | ||
|
||
DECLARE_MESSAGE_MAP() | ||
public: | ||
CString inputAccount; | ||
CString inputPassword; | ||
CInternetSession session; | ||
CFont newFont; | ||
|
||
static wchar_t* DIALOG_LOGIN::UTF8toWide(CString& str); | ||
static char* DIALOG_LOGIN::WidetoUTF8(CString& str); | ||
virtual BOOL OnInitDialog(); | ||
afx_msg void OnBnClickedOk(); | ||
afx_msg void OnBnClickedCancel(); | ||
afx_msg void OnPaint(); | ||
afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor); | ||
afx_msg void OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct); | ||
}; |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
|
||
// SUSTech_HowManyGPA.cpp: 定义应用程序的类行为。 | ||
// | ||
|
||
#include "pch.h" | ||
#include "framework.h" | ||
#include "SUSTech_HowManyGPA.h" | ||
#include "SUSTech_HowManyGPADlg.h" | ||
|
||
#ifdef _DEBUG | ||
#define new DEBUG_NEW | ||
#endif | ||
|
||
|
||
// CSUSTechHowManyGPAApp | ||
|
||
BEGIN_MESSAGE_MAP(CSUSTechHowManyGPAApp, CWinApp) | ||
ON_COMMAND(ID_HELP, &CWinApp::OnHelp) | ||
END_MESSAGE_MAP() | ||
|
||
|
||
// CSUSTechHowManyGPAApp 构造 | ||
|
||
CSUSTechHowManyGPAApp::CSUSTechHowManyGPAApp() | ||
{ | ||
// 支持重新启动管理器 | ||
m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART; | ||
|
||
// TODO: 在此处添加构造代码, | ||
// 将所有重要的初始化放置在 InitInstance 中 | ||
} | ||
|
||
|
||
// 唯一的 CSUSTechHowManyGPAApp 对象 | ||
|
||
CSUSTechHowManyGPAApp theApp; | ||
|
||
|
||
// CSUSTechHowManyGPAApp 初始化 | ||
|
||
BOOL CSUSTechHowManyGPAApp::InitInstance() | ||
{ | ||
// 如果一个运行在 Windows XP 上的应用程序清单指定要 | ||
// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式, | ||
//则需要 InitCommonControlsEx()。 否则,将无法创建窗口。 | ||
INITCOMMONCONTROLSEX InitCtrls; | ||
InitCtrls.dwSize = sizeof(InitCtrls); | ||
// 将它设置为包括所有要在应用程序中使用的 | ||
// 公共控件类。 | ||
InitCtrls.dwICC = ICC_WIN95_CLASSES; | ||
InitCommonControlsEx(&InitCtrls); | ||
|
||
CWinApp::InitInstance(); | ||
|
||
|
||
AfxEnableControlContainer(); | ||
|
||
// 创建 shell 管理器,以防对话框包含 | ||
// 任何 shell 树视图控件或 shell 列表视图控件。 | ||
CShellManager *pShellManager = new CShellManager; | ||
|
||
// 激活“Windows Native”视觉管理器,以便在 MFC 控件中启用主题 | ||
CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows)); | ||
|
||
// 标准初始化 | ||
// 如果未使用这些功能并希望减小 | ||
// 最终可执行文件的大小,则应移除下列 | ||
// 不需要的特定初始化例程 | ||
// 更改用于存储设置的注册表项 | ||
// TODO: 应适当修改该字符串, | ||
// 例如修改为公司或组织名 | ||
SetRegistryKey(_T("应用程序向导生成的本地应用程序")); | ||
|
||
CSUSTechHowManyGPADlg dlg; | ||
m_pMainWnd = &dlg; | ||
INT_PTR nResponse = dlg.DoModal(); | ||
if (nResponse == IDOK) | ||
{ | ||
// TODO: 在此放置处理何时用 | ||
// “确定”来关闭对话框的代码 | ||
} | ||
else if (nResponse == IDCANCEL) | ||
{ | ||
// TODO: 在此放置处理何时用 | ||
// “取消”来关闭对话框的代码 | ||
} | ||
else if (nResponse == -1) | ||
{ | ||
TRACE(traceAppMsg, 0, "警告: 对话框创建失败,应用程序将意外终止。\n"); | ||
TRACE(traceAppMsg, 0, "警告: 如果您在对话框上使用 MFC 控件,则无法 #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS。\n"); | ||
} | ||
|
||
// 删除上面创建的 shell 管理器。 | ||
if (pShellManager != nullptr) | ||
{ | ||
delete pShellManager; | ||
} | ||
|
||
#if !defined(_AFXDLL) && !defined(_AFX_NO_MFC_CONTROLS_IN_DIALOGS) | ||
ControlBarCleanUp(); | ||
#endif | ||
|
||
// 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序, | ||
// 而不是启动应用程序的消息泵。 | ||
return FALSE; | ||
} | ||
|
Oops, something went wrong.