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

📄 mainfrm.cpp

📁 测量被试的阅读速度
💻 CPP
字号:
// MainFrm.cpp : implmentation of the CMainFrame class
//
/////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "resource.h"

#include "aboutdlg.h"
#include "SpeedView.h"
//#include "kFlatCombo.h"
//#include "kFontCombo.h"
#include "MainFrm.h"
#include ".\mainfrm.h"

//#include <fstream>
//using namespace std;
#define BUFFER_BLOCK 4096

CMainFrame::CMainFrame()
    :m_bTimer(false), m_fontPoint(10)
{
	m_strTextBuf = new TCHAR[BUFFER_BLOCK*256+1];
}

CMainFrame::~CMainFrame()
{
	if (m_strTextBuf)
		delete []m_strTextBuf;
	m_strTextBuf = NULL;
}

BOOL CMainFrame::PreTranslateMessage(MSG* pMsg)
{
	if(CFrameWindowImpl<CMainFrame>::PreTranslateMessage(pMsg))
		return TRUE;

	return m_view.PreTranslateMessage(pMsg);
}

BOOL CMainFrame::OnIdle()
{
	UIUpdateToolBar();
	return FALSE;
}

LRESULT CMainFrame::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
	CenterWindow();
	// create command bar window
	HWND hWndCmdBar = m_CmdBar.Create(m_hWnd, rcDefault, NULL, ATL_SIMPLE_CMDBAR_PANE_STYLE);
	// attach menu
	m_CmdBar.AttachMenu(GetMenu());
	// load command bar images
	m_CmdBar.LoadImages(IDR_MAINFRAME);
	// remove old menu
	SetMenu(NULL);

	HWND hWndToolBar = CreateSimpleToolBarCtrl(m_hWnd, IDR_MAINFRAME, FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE);

	CToolBarCtrl m_tbar(hWndToolBar);
	RECT rc;
	TBBUTTONINFO tbi;
	tbi.cbSize = sizeof TBBUTTONINFO;		
	tbi.dwMask = TBIF_STYLE | TBIF_SIZE;
	tbi.fsStyle = TBSTYLE_SEP;

	//CClientDC dc(m_hWnd);
	//dc.SelectFont((HFONT) GetStockObject( DEFAULT_GUI_FONT ));		
	//TEXTMETRIC tm;
	//dc.GetTextMetrics( &tm );
	//int cxChar = tm.tmAveCharWidth;
	//int cyChar = tm.tmHeight + tm.tmExternalLeading;
	//int cx = (LF_FACESIZE + 4) * cxChar;
	//int cy = 16 * cyChar;

	//tbi.cx = (unsigned short)cx;

	//m_tbar.SetButtonInfo(1, &tbi); 						
	//m_tbar.GetItemRect(0, &rc); 

	////	int left = rc.left; 
	//rc.right -= cxChar * 8;
	//rc.bottom = cy;

	//HWND hWndFont =  m_comboFont.CreateEx(m_hWnd, rc, -1, IDC_FONTNAME); 
	//hWndFont;
	//ATLASSERT(hWndFont != 0);

	//rc.left = rc.right + 2; rc.right = rc.left + cxChar * 8 - 2;
	//HWND hWndSize =  m_comboSize.Create(m_hWnd, rc, 0, WS_CHILD|WS_TABSTOP|WS_VSCROLL|WS_VISIBLE|CBS_DROPDOWN, 0, IDC_FONTSIZE, 0);
	//ATLASSERT(hWndSize != 0);



// Digit Clock Control
/////////////////////////////////////////////////
	tbi.cx = (unsigned short)120;
	m_tbar.SetButtonInfo(ID_DIG_CLOCK, &tbi); 						
	m_tbar.GetItemRect(9, &rc);	
	m_clock.Create(m_hWnd, rc);
/////////////////////////////////////////////////
	
	
	m_clock.SetParent(hWndToolBar);
//	m_comboSize.SetParent (hWndToolBar);
//	m_comboFont.SetParent(hWndToolBar); 
//	m_comboSize.SetFont((HFONT)GetStockObject( DEFAULT_GUI_FONT ));

	//m_comboSize.LimitText(4);

	//TCHAR str[10];

	//for( int i=0; i < sizeof font_size / sizeof font_size[0]; i++ )
	//{
	//	wsprintf(str, "%d", font_size[i] );			
	//	m_comboSize.AddString( str );
	//}

	CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);
	AddSimpleReBarBand(hWndCmdBar, NULL, FALSE);
	AddSimpleReBarBand(hWndToolBar, NULL, TRUE);

	//RECT combox_rect = {0, 0, 60, 50};
	//HWND hCombo = m_combo.Create(m_hWnd, combox_rect, NULL,  WS_VISIBLE | WS_CHILD | WS_TABSTOP |
 //          WS_VSCROLL | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_NORESIZE |
 //          CBS_AUTOHSCROLL | CBS_DROPDOWNLIST);
	//AddSimpleReBarBand(hCombo, NULL, FALSE);

	CreateSimpleStatusBar();

	m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | 
		WS_CLIPCHILDREN | WS_VSCROLL |  ES_MULTILINE | ES_NOHIDESEL | ES_READONLY, WS_EX_CLIENTEDGE);

	UIAddToolBar(hWndToolBar);
	UISetCheck(ID_VIEW_TOOLBAR, 1);
	UISetCheck(ID_VIEW_STATUS_BAR, 1);

	UIEnable(ID_EDIT_CUT, false);
	UIEnable(ID_EDIT_PASTE, false);
	UIEnable(ID_FILE_NEW, false);
	UIEnable(ID_FILE_SAVE, false);
	UIEnable(ID_TIMER_START, false);
	UIEnable(ID_TIMER_STOP, false);

	m_strTextBuf[0] = '\0';

	// register object for message filtering and idle updates
	CMessageLoop* pLoop = _Module.GetMessageLoop();
	ATLASSERT(pLoop != NULL);
	pLoop->AddMessageFilter(this);
	pLoop->AddIdleHandler(this);

	return 0;
}

LRESULT CMainFrame::OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
	PostMessage(WM_CLOSE);
	return 0;
}

LRESULT CMainFrame::OnFileNew(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
	return 0;
}

LRESULT CMainFrame::OnViewToolBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
	static BOOL bVisible = TRUE;	// initially visible
	bVisible = !bVisible;
	CReBarCtrl rebar = m_hWndToolBar;
	int nBandIndex = rebar.IdToIndex(ATL_IDW_BAND_FIRST + 1);	// toolbar is 2nd added band
	rebar.ShowBand(nBandIndex, bVisible);
	UISetCheck(ID_VIEW_TOOLBAR, bVisible);
	UpdateLayout();
	return 0;
}

LRESULT CMainFrame::OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
	BOOL bVisible = !::IsWindowVisible(m_hWndStatusBar);
	::ShowWindow(m_hWndStatusBar, bVisible ? SW_SHOWNOACTIVATE : SW_HIDE);
	UISetCheck(ID_VIEW_STATUS_BAR, bVisible);
	UpdateLayout();
	return 0;
}

LRESULT CMainFrame::OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
	CAboutDlg dlg;
	dlg.DoModal();
	return 0;
}

inline bool my_isdigit(TCHAR c)
{
	if (c >= '0' && c <= '9')
		return true;
	return false;
}

bool CMainFrame::ReadText(LPTSTR filename, int *fontsize)
{
	FILE *fp = fopen(filename, "rb");
	if (fp == NULL) {
		ATLTRACE("file open error\n");
		return false;
	}

	//TCHAR *buf = new TCHAR[BUFFER_BLOCK*256+1], *buf_seek;
	TCHAR *buf_seek;
	buf_seek = m_strTextBuf;

    // read first line to set font
	size_t r_size, i = 0;
    TCHAR str_match[] = _T("字体="), line[1024];
    int j = 0, fs = 0;
	buf_seek = line;
	r_size=fread(buf_seek, sizeof(TCHAR), 1024, fp);
	if (r_size > 0) {
        if (*buf_seek != '#')
            goto _UNMATCH;
        do {
            i++, buf_seek++;
            if (*buf_seek==' ' || *buf_seek=='\t')
                continue;
            if (*buf_seek == '\n')
                goto _UNMATCH;
            //match
            if (j >= 5 && my_isdigit(*buf_seek))
                break;
            if (*buf_seek != str_match[j++])
                goto _UNMATCH;
        } while(i < r_size);
        
        //here is the match
		if (j >= 5) {
			while(i < r_size && my_isdigit(*buf_seek)) {
				fs = fs*10 + *buf_seek - '0';
				buf_seek++, i++;
			}
            //write font size
            if (fontsize) *fontsize = fs;
			while(i < r_size && *buf_seek != '\n') i++, buf_seek++;
			if (*buf_seek == '\n') buf_seek++, i++;
			buf_seek += i, r_size -= i;
			ATLTRACE("success matched!\n");
		}
	}
 _UNMATCH:
    buf_seek -= i;
	strncpy(m_strTextBuf, buf_seek, r_size);
	buf_seek = m_strTextBuf+r_size;
	while ((r_size=fread(buf_seek, sizeof(TCHAR), BUFFER_BLOCK, fp)) == BUFFER_BLOCK) {
		buf_seek += r_size;
		if (buf_seek > m_strTextBuf+BUFFER_BLOCK*255) {
			MessageBox("File is too large!\n", "Sorry", MB_OK|MB_ICONWARNING);
			m_strTextBuf[0] = '\0';
			fclose(fp);
			return false;
		} 
	}
	if (feof(fp)) {
		buf_seek[r_size] = '\0';
		//m_view.SetWindowText(m_strTextBuf);
	}
	else {
		MessageBox("IO error!\n", "Sorry", MB_OK|MB_ICONWARNING);
	}

	fclose(fp);

	return true;
}

LRESULT CMainFrame::OnFileOpen(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
	TCHAR szFilters[]=
		"Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0";
	CFileDialog fileDlg (TRUE, "txt", "*.txt",
		OFN_HIDEREADONLY, szFilters);

	if (fileDlg.DoModal() == IDCANCEL)
		return 0;

	int fontsize = 0;
	ReadText(fileDlg.m_szFileName, &fontsize);
	m_fontPoint = fontsize;

	WTL::CString title;
	title.Format("Speed - %s", fileDlg.m_szFileName);
	SetWindowText(title);
	UIEnable(ID_TIMER_START, true);
	UIEnable(ID_TIMER_STOP, true);

	return 0;
}

LRESULT CMainFrame::OnFileSave(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
	TCHAR szFilters[]=
		"Text Files (*.log)\0*.log\0All Files (*.*)\0*.*\0";
	CFileDialog fileDlg (FALSE, "log", "*.log",
		OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilters);

	if (fileDlg.DoModal() == IDCANCEL)
		return 0;

	FILE *fp = fopen(fileDlg.m_szFileName, "wb");
	if (fp == NULL) {
		ATLTRACE("file open error\n");
		return 0;
	}

	fwrite(m_strReport.GetBuffer(m_strReport.GetLength()), sizeof(TCHAR), m_strReport.GetLength(), fp);
	fclose(fp);

	UIEnable(ID_FILE_SAVE, false);
	return 0;
}

WTL::CString CMainFrame::CountWords()
{
	unsigned int ascii = 0, wide = 0, cr = 0, lf = 0, other = 0, space = 0;

	size_t len = m_view.GetWindowTextLength();
	if (len > 0)
	{
		TCHAR *text = new TCHAR[len + 1];
		m_view.GetWindowText(text, len+1);
		text[len] = 0;

		TCHAR * prev = text, * cur = text;

		cur = CharNext(cur);
		while (*prev)
		{
			if ((BYTE *)cur - (BYTE *)prev == sizeof(char)) {
				if ('\r' == *prev)
					cr++;
				else if ('\n' == *prev)
					lf++;
				else if (' ' == *prev || '\t' == *prev)
                    space++;
				else
					ascii++;
            }
			else if ((BYTE *)cur - (BYTE *)prev == sizeof(WCHAR)) {
				if (*reinterpret_cast<WCHAR *>(prev) < 0x80)
					if ('\r' == *prev)
						cr++;
					else if ('\n' == *prev)
						lf++;
					else if (' ' == *prev || '\t' == *prev)
						space++;
					else
						ascii++;
				else
					wide++;
			}
			else
				other++;

			prev = cur;
			cur = CharNext(cur);
		}

		delete []text;
	}

	float sec;
	WTL::CString report;
	TCHAR buf_report[1024];
	SYSTEMTIME diff;

	TimeDiff(m_stStart, m_stStop, &diff);
	sec = diff.wHour*3600+diff.wMinute*60+diff.wSecond+(float)diff.wMilliseconds/1000;
	float speed, speed_nosp;
	if (fabs(sec) > 1e-6) {
		speed = (float)(ascii+wide+space)/sec;
		speed_nosp = (float)(ascii+wide)/sec;
	}
	else speed = 0;

	//report.Format("英文=%d(个), 汉字=%d(个), 换行=%d(个)\r\n\r\n总计字数=%d(个), 时间=%d(秒), 速度=%d(字/秒)\r\n", 
	//	ascii, wide, lf, words, sec, (int)speed);
	sprintf(buf_report, "英文字符(计空格)=%d(个), 英文字符(不计空格)=%d(个), 汉字=%d(个)\r\n\r\n"
		"总计字数(计空格)=%d(个), 时间=%.3f(秒), 速度=%.2f(字/秒)\r\n\r\n"
		"总计字数(不计空格)=%d(个), 时间=%.3f(秒), 速度=%.2f(字/秒)\r\n",
		ascii+space, ascii, wide, ascii+wide+space, sec, speed, ascii+wide, sec, speed_nosp);
	report = buf_report;

	//MessageBox(report, "字数统计", MB_OK|MB_ICONINFORMATION);
	//MessageBeep(MB_ICONINFORMATION);
	//m_view.SetWindowText(report);
	return report;
}

LRESULT CMainFrame::OnTimerStart(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
	if (UIGetState(ID_TIMER_START) != 1) {
		return 0;
	}
    if (m_bTimer)
        return 0;
	m_view.SetFontPoint(m_fontPoint);
	m_view.SetWindowText(m_strTextBuf);

	SetTimer(TIMER_WORDS_COUNT, 31);
	GetLocalTime(&m_stStart);
    m_clock.SetTime(0,0,0,0);
	
	UIEnable(ID_FILE_OPEN, false);
	UIEnable(ID_FILE_SAVE, false);
	UISetCheck(ID_TIMER_START, true);
    m_bTimer =  true;

	return 0;
}

LRESULT CMainFrame::OnTimerStop(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
	if (UIGetState(ID_TIMER_STOP) != 1) {
		return 0;
	}
	if (!m_bTimer) {
		m_clock.SetTime(0,0,0,0);
        return 0;
	}
	KillTimer(TIMER_WORDS_COUNT);
    m_bTimer = false;

	UIEnable(ID_FILE_OPEN, true);
	UISetCheck(ID_TIMER_START, false);
	m_strReport = CountWords();

	MessageBeep(MB_ICONINFORMATION);
	m_view.SetWindowText(m_strReport);
	m_view.SetDefaultFont();

	UIEnable(ID_FILE_SAVE, true);

	//m_view.SetWindowText("");
	return 0;
}

void CMainFrame::TimeDiff(const SYSTEMTIME& start, const SYSTEMTIME& stop, SYSTEMTIME* diff)
{
	int hour=0, min=0, sec=0, millsec=0;
	millsec += stop.wMilliseconds - start.wMilliseconds;
	if (millsec < 0) millsec+=1000, sec-=1;
	sec += stop.wSecond - start.wSecond;
	if (sec < 0) sec+=60, min-=1;
	min += stop.wMinute - start.wMinute;
	if (min < 0) min+=60, hour-=1;
	hour += stop.wHour - start.wHour;
	if (hour < 0) hour+=24;

	diff->wHour = hour;
	diff->wMinute = min;
	diff->wSecond = sec;
	diff->wMilliseconds = millsec;
}

LRESULT CMainFrame::OnTimer(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
	if (wParam == TIMER_WORDS_COUNT) {
		GetLocalTime(&m_stStop);

		SYSTEMTIME diff;
		TimeDiff(m_stStart, m_stStop, &diff);
		m_clock.SetTime(diff.wHour, diff.wMinute, diff.wSecond, diff.wMilliseconds);
	}
	return 0;
}

⌨️ 快捷键说明

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