当我发现,添加文件,计时器,刷新列表出现问题后,我又翻出屋顶打字通代码做了一番修改,勉强添加了显示英的样式,把刷新列表的问题用绝对路径解决了,至此,我的屋顶打字通算是完成了它的第二个版本,这份代码也没什么特别的,就开源出来分享给大家,整个工程几乎用的都是Unicode,当然也有用的不是宽字节的,我写了这两个之间的转换函数,只是字符串之间的转换,这次写打字通学到了,GDI绘图,多线程的使用,U码和A码转换,绝对路径和相对路径的使用,WINDOWS消息机制(主要是绘图)。
用到两种创建窗口的方式,而且这两种方式都通过resource添加了对话框:
DialogBox(hInstance,MAKEINTRESOURCE(ID_MENU_STARTMENU),NULL,DlgMain);//这种方式不会立即返回,只有对话框结束了才会返回
CreateDialog(hIstanceMain,MAKEINTRESOURCE(ID_DIG_GAMEVIEW),NULL,DlaGame);//这种方式会立即返回
设计界面:
一、开始界面
菜单栏,显示列表,选中提示框,开始按钮
(1):菜单栏
(1.1)编辑:
(1.1.1)添加:
(1.1.2)中英文显示转换:
(1.2)帮助:
(1.2.1)链接:
(1.2.2)关于:
(2):显示列表
用于显示文件夹内的TXT文件
(2.1):左键单击选中列表一行,选中提示框内容变化
(2.2):左键双击列表中的一行,直接打开文件
(2.3):右键单击列表中的一行,可以对文件进行操作,包括删除该文件和全删除
(3):选中提示框
用于提示用户选中了哪一行
(4):开始按钮
点击开始按钮则会判断选中框内是否有内容,有,则打开指定文件,没有,则提示用户进行选择
二、打字界面
当前文章标题,进度条,计时器,三行文字显示和输入框,速度显示,错误字数
(1):当前文章标题
显示打开文件的标题
(2):进度条
显示打字进度,数字显示百分比,进度条根据百分比显示相应长度
(3):计时器
当有字符键入时,开始计时
(4):三行显示和输入
(4.1):显示文章的20个字符,根据二维数组内的数字判断画出字的颜色
(4.2):输入框等待用户输入,对输入的每一个字符进行判断,与上面字符相匹配则显示蓝色,不匹配则显示红色,用户不可以更改输入框的焦点,特殊处理有:显示的时候遇到换行符则变成空格,到键入最后一个字符时,如果键入多个的时候,自动换行或换页显示
(4.3):输入至文章末尾,则结束打字界面
(5):速度显示
计时器线程的创建,显示 时 分 秒
(6):错误字数
每次键入都会判断是否匹配,计数显示
打字通写得一般,代码质量也不高,因为这份代码确实是想到哪里写到哪里的,连有那些功能都是想到了才去完成那些部分的,展示给大家全部代码,但是大家也用不了,因为资源文件是我手动创建的,所以直接复制源码还是用不了的,这是WIN32程序,对C/C++感兴趣并且对Windows消息机制和GDI绘图感兴趣的可以仔细看看我这份代码。
TypeMain.cpp
#include"Constant.h" void EditFontController(float AimSize) { LOGFONT LogFont; memset(&LogFont, 0, sizeof(LOGFONT)); lstrcpy(LogFont.lfFaceName, L"Arial"); LogFont.lfWeight = FW_BLACK;//FW_NORMAL; LogFont.lfHeight = (LONG)AimSize; // 字体大小 LogFont.lfCharSet = 134; LogFont.lfOutPrecision = 3; LogFont.lfClipPrecision = 2; LogFont.lfOrientation = 45; LogFont.lfQuality = 1; LogFont.lfPitchAndFamily = 2; // 创建字体 HFONT hFont = CreateFontIndirect(&LogFont); // 取得控件句柄 for (int i = 0; i < 3; i++) {//设置控件字体 hWndEdit[i] = GetDlgItem(hWndGameView, EditInput1 + i); SendMessage(hWndEdit[i], WM_SETFONT, (WPARAM)hFont, TRUE); } } wchar_t* GetCurrentPath(wchar_t * target) { LPWSTR PointPath = NULL; wchar_t *cppoint = 0; cppoint = new wchar_t[MAX_PATH]; cppoint[0] = 0; GetModuleFileName(NULL, cppoint, MAX_PATH);//获得绝对路径 (_tcsrchr(cppoint, _T('\\')))[1] = 0;//截掉exe文件名 if (target) {//根据需要粘贴指定字符串 wcscat_s(cppoint, MAX_PATH, target);//给路径添加MyResource } PointPath = cppoint; return PointPath; } void InitArray() {//初始化数组,赋值1 for (int i = 0; i < 3; i++) for (int j = 0; j < 20; j++) ColorFlage[i][j] = 1; } void InitTxt() { InitArray(); SetDlgItemText(hWndGameView, EditInput1, L"");//清空文本框内容 SetDlgItemText(hWndGameView, EditInput2, L"");// SetDlgItemText(hWndGameView, EditInput3, L"");// } void Counter(int &hour, int &minute, int &second) { if (++second == 60) {//计时器 TimePane[6] = 0;//满60秒记1分钟,秒的十位归零 if (++minute == 60) { TimePane[3] = 0;//满60分钟记1小时,分钟的十位归零 if (++hour == 60) return; minute = 0; } second = 0; } } void TimeChanger(int time, int shift) { int tmp1 = 0; wchar_t wtmp[2];//必须两个,不然没有办法安放'\0' if (time<10) { _itow_s(time, wtmp, 2, 10); TimePane[shift] = wtmp[0]; }else { tmp1 = time / 10; _itow_s(tmp1, wtmp, 2, 10); TimePane[shift - 1] = wtmp[0]; tmp1 = time % 10; _itow_s(tmp1, wtmp, 2, 10); TimePane[shift] = wtmp[0]; } } DWORD WINAPI TimerFunction(LPVOID lpParam) {//计时器线程 int Hour = 0, Minute = 0, Second = 0; RECT tmpR; for (int i = 0; i < 8; i++) { TimePane[i] = 0;//TimePane里面是这样的 00:00:00 }//初始化时间面板数组 TimePane[2] = ':'; TimePane[5] = ':'; tmpR.left = 620L; tmpR.right = 680L; tmpR.top = 42L; tmpR.bottom = 62L; while (hAndleTimer) { Sleep(1000);//下面采用最麻烦的计时,然后提取个位和十位数字分别放在要显示的面板上 Counter(Hour, Minute, Second); if (Hour == 60) return 0; TimeChanger(Second, 7); TimeChanger(Minute, 4); TimeChanger(Hour, 1); CountSecond = Hour * 60 * 60 + Minute * 60 + Second;//统计时间用于计算速度 InvalidateRect(hWndGameView, &tmpR, false); UpdateWindow(hWndGameView); } return 0; } void StepMoveOn(int model) { if (model == 1) FlagBack = true; else FlagBack = false; if (FlagBack) { MOVE = MOVE - 1; TxtInfo.MoveAddress = TxtInfo.MoveAddress - 1; } int GoDown = (int)INTERVAL*(NUMBEREDIT - 1); AimRect.left = RECTX + (LONG)(MOVE)*(RECTA); AimRect.right = AimRect.left + RECTA; if (AimRect.right >= 234) AimRect.right = AimRect.right + 3L; if (AimRect.right >= 294) AimRect.right = AimRect.right + 5L; if (AimRect.right >= 512) AimRect.right = AimRect.right + 5L; AimRect.top = (((LONG)PointY - (LONG)3) + (LONG)GoDown); AimRect.bottom = (((LONG)PointY - (LONG)3) + ((LONG)SizeFont + (LONG)4) + (LONG)GoDown); ColorFlage[NUMBEREDIT - 1][MOVE] = model; if (EnglishOrChinese) { InvalidateRect(hWndGameView, &AimRect, false); UpdateWindow(hWndGameView); } else { InvalidateRect(hWndGameView, 0, false); UpdateWindow(hWndGameView); } if (!FlagBack) { MOVE = MOVE + 1; TxtInfo.MoveAddress = TxtInfo.MoveAddress + 1; } wchar_t * TmpCurrentPathA = GetCurrentPath(NULL);//exe所在绝对路径 wchar_t SoundName[] = L"1466.wav"; wcscat_s(TmpCurrentPathA, MAX_PATH, SoundName);//给路径添加MyResource PlaySound(TmpCurrentPathA, 0, SND_FILENAME | SND_ASYNC); delete[] TmpCurrentPathA; } void DealEditCallBack(WPARAM wWord) { if (TxtInfo.TXTSIZE) { wchar_t TmpChar = (wchar_t)wWord; wchar_t TmpSource = TxtInfo.TXTCONTENT[TxtInfo.MoveAddress]; int tmpCount = 0; if (TmpChar != TmpSource) {//匹配失败 if (wWord == 8) {//退格符 if (MOVE>0) {//退格符有效 StepMoveOn(GreyNUMBER); } //退格符无效 } else {//不是退格符且匹配失败 StepMoveOn(RedNUMBER); if (CountSecond > 0) { double SPEED = (double)TxtInfo.MoveAddress / (double)CountSecond * 60; stringstream tmpus; string tmpstr; tmpus << (int)SPEED; tmpus >> tmpstr; wchar_t *tmp1 = ConvertLPSTRtoLPWSTR(tmpstr.c_str()); SetDlgItemText(hWndGameView, ViewSpeed, tmp1); delete[] tmp1; } } }else {//匹配成功 StepMoveOn(BlueNUMBER); if (CountSecond > 0) { double SPEED = (double)TxtInfo.MoveAddress / (double)CountSecond * 60; stringstream tmpus; string tmpstr; tmpus << (int)SPEED; tmpus >> tmpstr; wchar_t * tmp2 = ConvertLPSTRtoLPWSTR(tmpstr.c_str()); SetDlgItemText(hWndGameView, ViewSpeed, tmp2); delete[] tmp2; } } if (!hAndleTimer) {//计时器线程句柄 hAndleTimer = CreateThread(0, 0, TimerFunction, 0, 0, 0);//创建计时器线程,返回值为句柄赋值给hAndleTimer } for (int i = 0; i < 3; i++) for (int j = 0; j < 20; j++) if (ColorFlage[i][j] == 3) tmpCount++; stringstream tmpus; string tmpstr; tmpus << tmpCount; tmpus >> tmpstr;//输入错误字数计数 wchar_t * tmp3 = ConvertLPSTRtoLPWSTR(tmpstr.c_str()); SetDlgItemText(hWndGameView, ErCount, tmp3); delete[] tmp3; if (MOVE == 20) {//换行 if (NUMBEREDIT == 3) {//当焦点在第三个输入框 TxtInfo.ViewStart = TxtInfo.ViewEnd; TxtInfo.ViewEnd = TxtInfo.ViewEnd + 60; InitTxt();//初始化 InvalidateRect(hWndGameView, 0, true);//更新窗口 UpdateWindow(hWndGameView); } TxtInfo.PartBuffer[0] = 0; TmpChar = 0; MOVE = 0; RowGrow(NUMBEREDIT); SetFocus(hWndEdit[NUMBEREDIT - 1]); } wchar_t tmplater[2]; int seek = 0; if (wWord == 8) { for (; TxtInfo.PartBuffer[seek] != 0; seek++); if (!seek) TxtInfo.PartBuffer[0] = 0; else { TxtInfo.PartBuffer[seek - 1] = 0; } } else { tmplater[0] = TmpChar; tmplater[1] = 0; wcscat_s(TxtInfo.PartBuffer, tmplater); for (; TxtInfo.PartBuffer[seek] != 0; seek++); } if (NUMBEREDIT == 1) { SetDlgItemText(hWndGameView, EditInput3, L""); } SetDlgItemText(hWndGameView, EditInput1 + (NUMBEREDIT - 1), TxtInfo.PartBuffer); SendMessage(hWndEdit[NUMBEREDIT - 1], EM_SETSEL, seek, seek); SendMessage(hWndProgressBar, PBM_SETPOS, (WPARAM)TxtInfo.MoveAddress, 0); double tmpBar = ((double)TxtInfo.MoveAddress / (double)TxtInfo.TXTSIZE); int tmpView = (int)(tmpBar * 100); wchar_t viewint[10]; viewint[0] = 0; _itow_s(tmpView, viewint, 10); SetDlgItemText(hWndGameView, PgIndex, viewint); if (TxtInfo.MoveAddress == TxtInfo.TXTSIZE) { InitTxt(); MOVE = 0; NUMBEREDIT = 1; TxtInfo.PartBuffer[0] = 0; TxtInfo.MoveAddress = 0; InvalidateRect(hWndStart, 0, true); UpdateWindow(hWndStart); MessageBox(hWndGameView, L"congratulation!", L"Caution", MB_OK); ShowWindow(hWndStart, SW_SHOW);//GameView对话框已经创建,将它显示出来 EndDialog(hWndGameView, 0); } } else { MessageBox(hWndGameView, L"Error!", L"Caution", MB_OK); ShowWindow(hWndStart, SW_SHOW); EndDialog(hWndGameView, 0); } return; } LRESULT CALLBACK EditProc1(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { CallWindowProc(g_Edit[0], hWnd, message, wParam, lParam); switch (message) { case WM_CHAR: DealEditCallBack(wParam); break; } return 0; } void RdviewFile() { wchar_t * TmpCurrentPathB = GetCurrentPath(L"MyResource\\");//exe所在绝对路径 wcscat_s(TmpCurrentPathB, MAX_PATH, SELECTEDTXT); HANDLE MFILE = CreateFile(TmpCurrentPathB, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);//windowsAPT获取文件句柄 int Msize = GetFileSize(MFILE, 0);//获取文件大小 if (Msize > 0) { char *Mtxt = new char[Msize + 1];//为缓冲区申请内存 DWORD Mbyte;//out读取文件的实际大小 ReadFile(MFILE, Mtxt, Msize, &Mbyte, 0);//读取文件保存到缓冲区 Mtxt[Msize] = 0;//为结尾赋零 int unicodelen = MultiByteToWideChar(CP_ACP, 0, Mtxt, -1, 0, 0); wchar_t * pUnicode;//定义U码指针 pUnicode = new wchar_t[unicodelen];//申请U码缓冲区 MultiByteToWideChar(CP_ACP, 0, Mtxt, -1, pUnicode, unicodelen);//ANSI转换宽字节 TxtInfo.TXTCONTENT = pUnicode; TxtInfo.TXTSIZE = unicodelen;//字符数 } else { TxtInfo.TXTCONTENT = 0; TxtInfo.TXTSIZE = 0; } CloseHandle(MFILE); return; } void RefreshList(HWND lview) { wchar_t * TmpCurrentPathC = GetCurrentPath(L"MyResource");//exe所在绝对路径 char * filePath = ConvertLPWSTRToLPSTR(TmpCurrentPathC); vector<string> files; getFiles(filePath, "txt", files); int size = files.size(),pos; string s; LVITEM vitem; vitem.mask = LVIF_TEXT; SendMessage(lview, LVM_DELETEALLITEMS, 0, 0); for (int i = 0; i < size; i++){ pos = files[i].find_last_of('\\'); s = (string)(files[i].substr(pos + 1)); wchar_t * pUnicode = ConvertLPSTRtoLPWSTR(s.c_str()); vitem.pszText = pUnicode; vitem.iItem = i; vitem.iSubItem = 0; SendMessage(lview, LVM_INSERTITEM, i, (long)&vitem); delete[] pUnicode; } delete[] filePath; } VOID OnPaint(HDC hdc) { Graphics graphics(hdc); FontFamily fontFamily(L"Arial"); Font font(&fontFamily, SizeFont, FontStyleRegular, UnitPixel); PointF pointFA((PointX), PointY); SolidBrush solidBrush(GreyFont); SolidBrush solidBrush1(Color(255, 255, 255, 255)); Pen solidBrush2(Color(255, 0, 0, 0)); int nowaddress = TxtInfo.ViewStart; int ColumnNum = 20,ColorController=0; graphics.FillRectangle(&solidBrush1, 46, 95, 633, 40); graphics.DrawRectangle(&solidBrush2, 46, 95, 633, 82); graphics.FillRectangle(&solidBrush1, 46, 205, 633, 40); graphics.DrawRectangle(&solidBrush2, 46, 205, 633, 82); graphics.FillRectangle(&solidBrush1, 46, 315, 633, 40); graphics.DrawRectangle(&solidBrush2, 46, 315, 633, 82); if (EnglishOrChinese) { ColumnNum = 20; } else { ColumnNum = 20; } for (int p = 1; p < 4; p++) { pointFA.X = PointX; MeasureStringIntervel=0; for (int i = 0; i<ColumnNum; i++) { if (TxtInfo.MoveAddress <= TxtInfo.TXTSIZE) { if (TxtInfo.TXTCONTENT!=NULL) { wchar_t tmpwchar = TxtInfo.TXTCONTENT[nowaddress++]; switch (ColorFlage[p - 1][i]) { case 1: solidBrush.SetColor(GreyFont); break; case 2: solidBrush.SetColor(BlueFont); break; case 3: solidBrush.SetColor(RedFont); break; } if (tmpwchar == 10) {//换行符 tmpwchar = 32;//空格符 } if (EnglishOrChinese) { graphics.DrawString(&tmpwchar, 1, &font, pointFA, &solidBrush); pointFA.X = (PointX)+(SizeFont)*(i + 1) + (float)(i + 1); } else { Font font2(&fontFamily, SizeFont-10, FontStyleRegular, UnitPixel); RectF boundRect; graphics.DrawString(&tmpwchar, 1, &font2, pointFA, &solidBrush); graphics.MeasureString(&tmpwchar, 1, &font2, pointFA, &boundRect); //graphics.DrawRectangle(&Pen(Color(255, 0, 0, 0)), boundRect.X, boundRect.Y, boundRect.Width, boundRect.Height); MeasureStringIntervel = MeasureStringIntervel + boundRect.Width; pointFA.X = (PointX)+MeasureStringIntervel; } } }else { i = ColumnNum+1, p = 5; } if (nowaddress == (TxtInfo.TXTSIZE - 1)) { i = ColumnNum+1, p = 5;//此时为字符结尾 } } pointFA.Y = PointY + INTERVAL*p; } if (hAndleTimer) { Font font1(&fontFamily, 12.0f, FontStyleRegular, UnitPixel); solidBrush.SetColor(Color(255, 0, 0, 0)); pointFA.X = 620; pointFA.Y = 42; SolidBrush solidBrush3(Color(255, 255, 255, 255)); graphics.DrawRectangle(&solidBrush2, 620, 42, 55, 15); graphics.FillRectangle(&solidBrush3, 620, 42, 55, 15); graphics.DrawString(TimePane, 8, &font1, pointFA, &solidBrush); } } BOOL CALLBACK DlgGame(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { hWndGameView = hWnd; HDC hdc; PAINTSTRUCT ps; switch (message){ case WM_PAINT: { hdc = BeginPaint(hWnd, &ps); OnPaint(hdc); EndPaint(hWnd, &ps); return 0; } case WM_CLOSE:{//当点击×时候执行结束函数 hAndleTimer = 0;//结束线程 CloseHandle(hAndleTimer); ShowWindow(hWndStart, SW_SHOW);//GameView对话框已经创建,将它显示出来 EndDialog(hWnd, 0);//结束对话框 return 0; } } return FALSE; } BOOL CALLBACK DlgMain(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){ HWND hListview=NULL; hListview = GetDlgItem(hWnd, ListBox);// hWndStart = hWnd; switch (message){ case WM_CLOSE:{//当点击×时候执行结束函数 if (TxtInfo.TXTCONTENT) { delete[] TxtInfo.TXTCONTENT; } EndDialog(hWnd, 0); return 0; } case WM_COMMAND:{ switch (LOWORD(wParam)){ case E_ADD: {//当点击Add时 TCHAR szBuffer[MAX_PATH] = { 0 }; OPENFILENAME ofn = { 0 }; ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = 0; ofn.lpstrFilter = TEXT("txt文件(*.txt)\0*.txt\0");//要选择的文件后缀 ofn.lpstrFile = szBuffer;//存放文件的缓冲区 ofn.nMaxFile = sizeof(szBuffer) / sizeof(*szBuffer); ofn.nFilterIndex = 0; ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXPLORER | OFN_ALLOWMULTISELECT;//标志如果是多选要加上OFN_ALLOWMULTISELECT GetOpenFileName(&ofn);//此时打开文件选择框,不关闭此对话框,此函数不返回 //上面函数如果不在当前路径操作,会改变当前路径 int i = (int)ofn.nFileOffset,j=0; wchar_t ExitFile[MAX_PATH] = { 0 }; for (; j < i; j++) { if (szBuffer[j] == 0) { ExitFile[j] = '\\'; ExitFile[j + 1] = 0; break; } ExitFile[j] = szBuffer[j]; ExitFile[j + 1] = 0; }//获取除文件名外的路径 while (1) { int p = 0;//循环,一次复制一个文件 wchar_t ExitCopy[MAX_PATH] = { 0 };//初始化 选择文件路径的临时变量 wchar_t NameFile[MAX_PATH] = { 0 };//文件名 wcscpy_s(ExitCopy, MAX_PATH, ExitFile);//将ExitFile内容赋值给ExitCopy int q = j;//保存当前j值 for (; szBuffer[i] != 0; i++) { ExitCopy[j++] = szBuffer[i]; NameFile[p++] = szBuffer[i]; }//给临时变量ExitCopy添加上文件名,将文件名保存进NameFile,用于CurrentPath NameFile[p] = 0;//处理结尾 ExitCopy[j] = 0; j = q;//让j变会原来值以确保下次可以从文件名结尾赋值 wchar_t * TmpCurrentPathD = GetCurrentPath(L"MyResource\\");//exe所在绝对路径 wcscat_s(TmpCurrentPathD, MAX_PATH, NameFile);//给路径添加文件名 if (!CopyFile(ExitCopy, TmpCurrentPathD, FALSE))//CopyFile失败返回0 return 0;//失败退出 if (szBuffer[++i] == 0)//如果szBuffer下一位还是0则说明没有选中文件了结束循环 break; } RefreshList(hListview);//刷新listitem显示列表 break; } case ID_MENU_FLAG_ENGLISH: {//点击菜单Switch to English EnglishOrChinese = false;//转换成英文 EditFontController(SizeFont-(float)5); EnableMenuItem(hMeStartM, ID_MENU_FLAG_ENGLISH, MF_GRAYED);//将英文设为灰色 EnableMenuItem(hMeStartM, ID_MENU_FLAG_CHINESE, MF_ENABLED);//将中文设为可用 DrawMenuBar(hWnd); break; } case ID_MENU_FLAG_CHINESE: {//点击菜单Switch to English EnglishOrChinese = true;//转换成中文 EditFontController(SizeFont); EnableMenuItem(hMeStartM, ID_MENU_FLAG_ENGLISH, MF_ENABLED);//将英文设为可用 EnableMenuItem(hMeStartM, ID_MENU_FLAG_CHINESE, MF_GRAYED);//将中文设为灰色 break; } case R_DELETE: { wchar_t * TmpCurrentPathE = GetCurrentPath(L"MyResource\\");//exe所在绝对路径 wcscat_s(TmpCurrentPathE,MAX_PATH, SELECTEDTXT); DeleteFile(TmpCurrentPathE); RefreshList(hListview);//刷新listitem显示列表 SECFLAG = false; wcharTXT[0] = 0; SetDlgItemText(hWnd, ChoiceText, L""); break; } case R_DELETEALL: { wchar_t * TmpCurrentPathF = GetCurrentPath(L"MyResource");//exe所在绝对路径 char *filePath = ConvertLPWSTRToLPSTR(TmpCurrentPathF); wchar_t * TmpCurrentPathG = GetCurrentPath(L"MyResource\\");//exe所在绝对路径 vector<string> files; getFiles(filePath, "txt", files); int size = files.size(),pos; string s; for (int i = 0; i < size; i++){ wchar_t ExitCopy[MAX_PATH] = { 0 };//初始化 选择文件路径的临时变量 wchar_t *tmppath = ConvertLPSTRtoLPWSTR(filePath); wcscpy_s(ExitCopy, MAX_PATH, TmpCurrentPathG);//将ExitFile内容赋值给ExitCopy pos = files[i].find_last_of('\\'); s = (string)(files[i].substr(pos + 1)); wchar_t * pUnicode = ConvertLPSTRtoLPWSTR(s.c_str()); wcscat_s(ExitCopy, MAX_PATH, pUnicode);// DeleteFile(ExitCopy); delete[] tmppath; delete[] pUnicode; } RefreshList(hListview);//刷新listitem显示列表 SECFLAG = false; wcharTXT[0] = 0; SetDlgItemText(hWnd, ChoiceText, L""); delete[] filePath; break; } case MENU_WEB: { ShellExecute(NULL, NULL, L"http://www.roofso.com/", NULL, NULL, SW_SHOWNORMAL); break; } case MENU_About: { MSGBOXPARAMS mbp; mbp.cbSize = sizeof(MSGBOXPARAMS); mbp.hwndOwner = hWnd; mbp.hInstance = hInstanceMain; mbp.lpszText = L"RoofType is a game for fun.Brief and Green is its characteristic.At first I just want to excercise myself,but I think why not make a software.It also has a lot BUG,we will make it better together.\nWEB:www.roofso.com\nAuthor:Caeser"; mbp.lpszCaption = L"About RoofType"; mbp.dwStyle = MB_USERICON; mbp.lpszIcon = MAKEINTRESOURCE(roofsologo); mbp.dwContextHelpId = 0; mbp.lpfnMsgBoxCallback = NULL; mbp.dwLanguageId = 0; MessageBoxIndirect(&mbp); break; } case StartButton: { if (SECFLAG) { ShowWindow(hWndGameView, SW_SHOW);//GameView对话框已经创建,将它显示出来 ShowWindow(hWndStart, SW_HIDE); SetDlgItemText(hWndGameView, TxtContent, SELECTEDTXT);//对该对话框的EditControl设置Text SendMessage(hWndProgressBar, PBM_SETPOS, 0, 0); InitTxt(); TxtInfo.MoveAddress = 0; TxtInfo.ViewStart = 0; TxtInfo.ViewEnd = 60; TxtInfo.PartBuffer[0] = 0; NUMBEREDIT = 1; MOVE = 0; ErrorCount = 0; RdviewFile(); SendMessage(hWndProgressBar, PBM_SETRANGE32, 0, TxtInfo.TXTSIZE);//MAKELPARAM(0, TxtInfo.size) SendMessage(hWndProgressBar, PBM_SETSTEP, (WPARAM)1, 0); SetFocus(hWndEdit[0]); }else MessageBox(hWnd, L"Please choose text!", L"Tipe", MB_OK); break; } default: break; } break; } case WM_INITDIALOG: { // 设置ListView的列 LVCOLUMN vcl; vcl.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM; // 第一列 vcl.pszText = L"Title";//列标题 vcl.cx = 260;//列宽 vcl.iSubItem = 2;//子项索引,第一列无子项 SendMessage(hListview, LVM_INSERTCOLUMN, 0, (long)&vcl);//消息//ListView_InsertColumn(hListview, 0, &vcl);//宏 SendMessage(hListview, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);//更改item样式 RefreshList(hListview);//刷新listitem显示列表 hWndGameView = 0; CreateDialog(hInstanceMain, MAKEINTRESOURCE(ID_DIG_GAMEVIEW), NULL, DlgGame);//创建GameView对话框,但是隐藏它,并且返回 EditFontController(SizeFont);//设置输入框字体大小 hWndProgressBar = GetDlgItem(hWndGameView, UpgBar); hWndPgIdex = GetDlgItem(hWndGameView, PgIndex); g_Edit[0] = (WNDPROC)SetWindowLong(hWndEdit[0], GWL_WNDPROC, (LONG)EditProc1); g_Edit[0] = (WNDPROC)SetWindowLong(hWndEdit[1], GWL_WNDPROC, (LONG)EditProc1); g_Edit[0] = (WNDPROC)SetWindowLong(hWndEdit[2], GWL_WNDPROC, (LONG)EditProc1); SetMenu(hWnd, LoadMenu(hInstanceMain, MAKEINTRESOURCE(ID_MENU_STARTMENU))); hMeStartM = GetMenu(hWnd); break; } case WM_NOTIFY:{ switch (LOWORD(wParam)){ case ListBox: { if (((LPNMHDR)lParam)->code == NM_CLICK) {//ITEMCHANGED LVITEM litem; wchar_t buf[MAXLEN]; buf[0] = 0; int iItem = ((LPNMITEMACTIVATE)lParam)->iItem; int iSubItem = ((LPNMITEMACTIVATE)lParam)->iSubItem; if (iItem != -1) { litem.iSubItem = 0; litem.pszText = buf; litem.cchTextMax = MAXLEN; SendMessage(hListview, LVM_GETITEMTEXT, iItem, (long)&litem); wcscpy_s(SELECTEDTXT, MAXLEN, litem.pszText); SetDlgItemText(hWnd, ChoiceText, litem.pszText); SECFLAG = true; }else { if (!SECFLAG) MessageBox(hWnd, L"Please choose text!", L"Tipe", MB_OK); } }else if (((LPNMHDR)lParam)->code == NM_DBLCLK) { if (SECFLAG) { int p = GetLastError(); ShowWindow(hWndGameView, SW_SHOW);//GameView对话框已经创建,将它显示出来 SetDlgItemText(hWndGameView, TxtContent, SELECTEDTXT);//对该对话框的EditControl设置Text SendMessage(hWndProgressBar, PBM_SETPOS, 0, 0); InitTxt(); TxtInfo.MoveAddress = 0; TxtInfo.ViewStart = 0; TxtInfo.ViewEnd = 60; TxtInfo.PartBuffer[0] = 0; NUMBEREDIT = 1; MOVE = 0; ErrorCount = 0; RdviewFile(); SendMessage(hWndProgressBar, PBM_SETRANGE32, 0, TxtInfo.TXTSIZE);//MAKELPARAM(0, TxtInfo.size) SendMessage(hWndProgressBar, PBM_SETSTEP, (WPARAM)1, 0); SetFocus(hWndEdit[0]); ShowWindow(hWndStart, SW_HIDE); } }else if (((LPNMHDR)lParam)->code == NM_RCLICK) { LVITEM litem; wchar_t buf[MAXLEN]; int iItem = ((LPNMITEMACTIVATE)lParam)->iItem; int iSubItem = ((LPNMITEMACTIVATE)lParam)->iSubItem; if (iItem != -1) { litem.iSubItem = 0; litem.pszText = buf; litem.cchTextMax = MAXLEN; SendMessage(hListview, LVM_GETITEMTEXT, iItem, (long)&litem); wcscpy_s(SELECTEDTXT, MAXLEN, litem.pszText); SetDlgItemText(hWnd, ChoiceText, litem.pszText); SECFLAG = true; HMENU TMPmenu1 = LoadMenu(hInstanceMain, MAKEINTRESOURCE(ID_MENU_RIGHTCLICK)); TMPmenu1 = GetSubMenu(TMPmenu1, 0); POINT TMPp; GetCursorPos(&TMPp); //ScreenToClient(hWnd, &TMPp); TrackPopupMenu(TMPmenu1, TPM_LEFTALIGN | TPM_RIGHTBUTTON, TMPp.x, TMPp.y, 0, hWnd, NULL); } } }//case ListBox }//switch (LOWORD(wParam)) break; } default: break; } return FALSE; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { //主函数,从这里开始执行,调用DialogBox函数MAKEINTRESOURCE(IDD_DIALOG1),括号内是对话框的名称 MeasureStringIntervel = 0; TxtInfo.MoveAddress = 0; TxtInfo.ViewStart = 0; TxtInfo.ViewEnd = 60; TxtInfo.PartBuffer[0] = 0; hAndleTimer = 0;//事件句柄 hInstanceMain = hInstance; wcharTXT[0] = 0; SELECTEDTXT = wcharTXT; ErrorCount = 0; GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); EnglishOrChinese = true;//中英转换标志为中文 DialogBox(hInstance, MAKEINTRESOURCE(ID_MENU_STARTMENU), NULL, DlgMain); GdiplusShutdown(gdiplusToken); return 0; }
Constant.h
#include"Header.h"HINSTANCE hInstanceMain;//打开游戏界面用到的句柄LPWSTR SELECTEDTXT=NULL;//已选择文本信息BOOL SECFLAG=false;//是否已选择文本wchar_t wcharTXT[MAXLEN];//保存文本信息缓冲区HWND hWndGameView;//打字游戏界面句柄HWND hWndEdit[3];//文本控件句柄HWND hWndProgressBar;//进度条句柄HWND hWndPgIdex;//显示进度条半分比HWND hWndStart;//开始界面句柄HANDLE hAndleTimer;//计时线程句柄wchar_t TimePane[8];//显示时间int CountSecond;//用于计算时间GdiplusStartupInput gdiplusStartupInput;//绘图ULONG_PTR gdiplusToken;//绘图WNDPROC g_Edit[1];//EditControl回调BOOL FlagBack = false;//判断退格符RECT AimRect;//更新用的矩形区域Color GreyFont(145, 145, 145);//No.1Color BlueFont(0, 0, 255);//No.2Color RedFont(220, 20, 60);//No.3const int GreyNUMBER = 1;//灰色字体的FLAGconst int BlueNUMBER = 2;//蓝色字体的FLAGconst int RedNUMBER = 3;//红色字体的FLAGconst int ChineseBYTE = 2;//调整字体显示的偏移量const int EnglishBYTE = 1;//调整字体显示的偏移量int NUMBEREDIT = 1;//当前获得焦点的文本控件IDfloat SizeFont = 30.0f;//字体大小const float PointX = 46.0f;//EditControl在Dlag上的Y轴const float PointY = 100.0f;//EditControl在Dlag上的Y轴const float INTERVAL = 110.0f;//两个EditControl间隔int ColorFlage[][20] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};//显示在文本控件字符【中文】int ErrorCount;long RECTX = 54L;//跟新矩形区域的X值long RECTA = 30L;//更新矩形区域的位移值int MOVE = 0;//记录当前输入量struct TXTINFO{ int ViewStart; int ViewEnd; int MoveAddress; wchar_t *TXTCONTENT; wchar_t PartBuffer[20]; int TXTSIZE; }TxtInfo; BOOL EnglishOrChinese;//中英转换HMENU hMeStartM;//STARTVIEW的菜单float MeasureStringIntervel;//文字间距
Header.h
#include<Windows.h>#include<stdio.h>#include "resource.h"#include <string>#include <io.h>#include <vector>#include"commctrl.h"#include <objidl.h>#include <gdiplus.h>#include <sstream>#include<tchar.h>#include "mmsystem.h"//导入声音头文件 #pragma comment(lib,"winmm.lib")//导入声音头文件库using namespace Gdiplus;#pragma comment (lib,"Gdiplus.lib")#define MAXLEN 1024using namespace std;char* ConvertLPWSTRToLPSTR(LPWSTR lpwszStrIn);wchar_t* ConvertLPSTRtoLPWSTR(const char * lpStrIn);BOOL CALLBACK DlgMain(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);void getFiles(string path, string exd, vector<string>& files);void RowGrow(int & source);