Skip to content
This repository has been archived by the owner on Jun 27, 2024. It is now read-only.

Commit

Permalink
Upload Code
Browse files Browse the repository at this point in the history
  • Loading branch information
HuaHuaY committed Mar 29, 2020
1 parent 5ed4a71 commit 6a8a5ff
Show file tree
Hide file tree
Showing 14 changed files with 1,116 additions and 1 deletion.
34 changes: 33 additions & 1 deletion README.md
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
- 开发小程序

##

本程序内图片来源网络。
208 changes: 208 additions & 0 deletions src/DIALOG_LOGIN.cpp
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);
}
36 changes: 36 additions & 0 deletions src/DIALOG_LOGIN.h
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 added src/SUSTechHowManyGPA.rc
Binary file not shown.
107 changes: 107 additions & 0 deletions src/SUSTech_HowManyGPA.cpp
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;
}

Loading

0 comments on commit 6a8a5ff

Please sign in to comment.