一、軟件安裝
Visual Studio 2022
Visual Studio 2022 是微軟提供的強大集成開發環境(IDE),廣泛用于C/C++、C#、Python等多種編程語言的開發。它提供了許多強大的工具,幫助開發者編寫、調試和優化代碼。
1.下載 Visual Studio 2022:訪問Visual Studio 官網
2.點擊 Download Visual Studio,選擇 Community Edition(免費)或其他版本,根據需求選擇。
2.安裝 Visual Studio:運行下載的安裝程序,啟動 Visual Studio 安裝程序。
在安裝界面選擇 Desktop development with C++,開發 C++ 程序所需的工作負載。
可以根據需要選擇其他組件,比如 Windows 10 SDK、C++ CMake tools 等,幫助進行圖形和圖像處理的開發,完成安裝后,啟動 Visual Studio 2022,選擇 Create a new project 來創建新的C++項目。(不會安裝的可以搜一下相關教程)
安裝 EasyX 圖形庫?
1.下載 EasyX 圖形庫:EasyX官網,根據需要選擇合適版本。
2.安裝 EasyX:
?
二、效果演示
1.界面樣式
2.讀入文件
3.查找
4.插入文字
5.替換
三、代碼實現
Text.h:該文件是 Text.cpp 的頭文件,聲明了文本操作相關的結構體和函數接口。
-
Node
結構體:表示鏈表中的一個字符節點。包含字符內容、字符在屏幕上的位置、是否為普通字符、是否被選中等信息。 -
Text
結構體:表示文本內容,包含頭指針、尾指針和當前光標位置。 -
File
結構體:表示文件,包含文件路徑和文本內容。 -
函數聲明:如
readFile()
、writeFile()
、insertText()
、deleteCharacter()
等。
#pragma once
/*
該模塊用于文本的操作
*/#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>// 該結構體表示鏈表結點
typedef struct Node Node;
struct Node {char content[3]; // 表示一個普通字符或中午字符int rect[4]; // 字符在屏幕上所占的區域bool normal; // 是否是普通字符bool selected; // 是否被選中Node* next;Node* prev;
};// 該結構體表示文本
typedef struct Text Text;
struct Text {Node* head; // 頭指針Node* tail; // 尾指針Node* cursor; // 當前指針位置
};// 該結構體表示文件
typedef struct File File;
struct File {char path[256]; // 文件的路徑Text* text; // 文件的內容
};// 讀入文件
bool readFile(char* path);// 寫入文件
void writeFile();// 新建文件
bool createFile(char* path);// 保存文件
bool saveFile(char* path);// 獲取當前文件
File* getCurrentFile();// 釋放相關內存
void freeResources();// 插入文字
void insertText(char* mContent);// 刪除字符
void deleteCharacter(bool isAfter);// 重置選中標志
void resetSelected();// 查找字符串
void findString(char* searchText);// 替換字符串
void replaceString(char* srcText, char* dstText);
Text.cpp:實現了文本內容的管理與操作,包括文件的讀取、保存、文本的插入、刪除、查找和替換等。它使用了鏈表結構來組織文本內容。
-
readFile()
:-
讀取指定路徑的文件,并將文件內容解析為字符。讀取的字符根據其字節數判斷是普通字符還是中文字符,并將其存儲到鏈表中。
-
使用
fread()
函數按字節讀取文件內容,若字符為普通字符,則將其存儲在content[]
中,若為中文字符,則按兩個字節讀取。
-
-
writeFile()
:-
將當前內存中的文本內容(鏈表結構)保存到文件中。通過
fopen()
打開文件,并逐個節點將文本內容寫入。
-
-
createFile()
:-
創建新文件并為其分配內存。調用
writeFile()
保存當前文件內容,釋放內存,創建新文件,并初始化新的文本結構。
-
-
insertText()
:-
在當前光標位置插入文本。通過
appendString()
函數將新的文本插入到鏈表的對應位置。
-
-
deleteCharacter()
:-
刪除當前光標位置的字符。通過檢查光標的位置(
isAfter
參數決定刪除前或后字符)來刪除指定的字符節點。
-
-
findString()
:-
查找指定的字符串,并將找到的部分高亮顯示。通過遍歷鏈表中的節點,并檢查每個節點的
content
是否與目標字符串匹配。
-
-
replaceString()
:-
查找并替換文本中的指定字符串。通過遍歷鏈表查找目標字符串,若找到則替換為指定的新字符串。
-
#include "Text.h"// 在某個節點后添加字符串
void appendString(Node** beforeNode, char* mContent, bool modifyBeforeNode);// 當前的文件
static File* curFile = NULL;// 為新文件分配內容
static void initFile(File* file, char* path) {strcpy(curFile->path, path);curFile->text = (Text*)calloc(1, sizeof(Text));curFile->text->head = (Node*)calloc(1, sizeof(Node));curFile->text->tail = (Node*)calloc(1, sizeof(Node));curFile->text->head->next = curFile->text->tail;curFile->text->tail->prev = curFile->text->head;curFile->text->cursor = curFile->text->head;
}// 釋放文件占用的內存
static void destroyFile(File** file) {while ((*file)->text->head->next != (*file)->text->tail) {Node* node = (*file)->text->head->next;(*file)->text->head->next = node->next;free(node);}free((*file)->text->head);free((*file)->text->tail);free(*file);*file = NULL;
}// 在Text中添加一個Node
static void insertNode(Node* beforeNode, char content[], bool normal) {Node* node = (Node*)calloc(1, sizeof(Node));strcpy(node->content, content);node->normal = normal;node->selected = false;node->next = beforeNode->next;node->prev = beforeNode;beforeNode->next->prev = node;beforeNode->next = node;
}// 讀入文件
bool readFile(char* path) {// 確保文件存在FILE* file = fopen(path, "rb");if (!file) {return false;}// 保存當前文件writeFile();// 釋放內存if (curFile) {destroyFile(&curFile);}// 為新文件分配內存curFile = (File*)calloc(1, sizeof(File));initFile(curFile, path);// 讀取新的文件char byte;char content[3] = {0};bool normal;while (fread(&byte, 1, 1, file) == 1) {if (byte >= 0) {// 這是普通字符content[0] = byte;if (byte == '\r') {char nextByte;fread(&nextByte, 1, 1, file);content[1] = nextByte;normal = false;}else {content[1] = '\0';normal = true;}}else {// 這是中文,其占2個字節char nextByte;fread(&nextByte, 1, 1, file);content[0] = byte;content[1] = nextByte;normal = false;}// 添加當前普通字符或者中文字符到文件的文本中insertNode(curFile->text->tail->prev, content, normal);}fclose(file);return true;
}// 寫入文件
void writeFile() {if (!curFile) return;// 把新內容寫入文件FILE* fp = fopen(curFile->path, "w");Node* node = curFile->text->head->next;while (node != curFile->text->tail) {fprintf(fp, "%s", node->content);node = node->next;}fclose(fp);
}// 新建文件
bool createFile(char* path) {// 保存當前文件writeFile();// 釋放內存if (curFile) {destroyFile(&curFile);}FILE* fp = fopen(path, "w");if (!fp) return false;fclose(fp);// 為新文件分配內存curFile = (File*)calloc(1, sizeof(File));initFile(curFile, path);return true;
}// 保存文件
bool saveFile(char* path) {if (!curFile) return false;// 把內容寫入新的文件FILE* fp = fopen(path, "w");if (!fp) return false;Node* node = curFile->text->head->next;while (node != curFile->text->tail) {fprintf(fp, "%s", node->content);node = node->next;}fclose(fp);return true;
}// 獲取當前文件
File* getCurrentFile() {return curFile;
}// 釋放相關內存
void freeResources() {if (curFile) {destroyFile(&curFile);}
}// 插入文字
void insertText(char* mContent) {if (!curFile || !mContent || strlen(mContent) == 0) return;// 添加字符串到當前指針后面appendString(&curFile->text->cursor, mContent, true);
}// 刪除當前字符
void deleteCharacter(bool isAfter) {if (curFile) {if (isAfter) {// 刪除指針后面的字符Node* node = curFile->text->cursor->next;if (node != curFile->text->tail) {curFile->text->cursor->next = node->next;node->next->prev = curFile->text->cursor;free(node);}}else {// 刪除指針指向的字符Node* node = curFile->text->cursor;if (node != curFile->text->head) {curFile->text->cursor = node->prev;curFile->text->cursor->next = node->next;node->next->prev = curFile->text->cursor;free(node);}}}
}// 重置選中標志
void resetSelected() {if (!curFile) return;Node* node = curFile->text->head->next;while (node != curFile->text->tail) {node->selected = false;node = node->next;}
}// 查找字符串
void findString(char* searchText) {if (!curFile) return;char content[3] = { 0 };char byte;size_t len = strlen(searchText);Node* curNode = curFile->text->head->next;while (curNode != curFile->text->tail) {Node* tmpNode = curNode;bool isFound = true;// 查找子串for (int i = 0; i < len && tmpNode != curFile->text->tail; i++) {byte = searchText[i];if (byte >= 0) {// 這是普通字符content[0] = byte;if (byte == '\r') {char nextByte = searchText[++i];content[1] = nextByte;}else {content[1] = '\0';}}else {// 這是中文,其占2個字節char nextByte = searchText[++i];content[0] = byte;content[1] = nextByte;}// 判斷兩個字符是否相同if (strcmp(tmpNode->content, content) != 0) {isFound = false;break;}tmpNode = tmpNode->next;}if (isFound) {// 設置對應的字符序列為選中Node* node = curNode;while (node != tmpNode) {node->selected = true;node = node->next;}}curNode = curNode->next;}
}// 在某個節點后添加字符串
void appendString(Node** beforeNode, char* mContent, bool modifyBeforeNode) {int i = 0;char byte;bool normal;char content[3] = { 0 };size_t len = strlen(mContent);Node* prev = *beforeNode;while (i < len) {byte = mContent[i];if (byte >= 0) {// 這是普通字符content[0] = byte;if (byte == '\r') {char nextByte = mContent[++i];content[1] = nextByte;normal = false;}else {content[1] = '\0';normal = true;}}else {// 這是中文,其占2個字節char nextByte = mContent[++i];content[0] = byte;content[1] = nextByte;normal = false;}// 添加當前普通字符或者中文字符到該指針后面insertNode(prev, content, normal);prev = prev->next;if (modifyBeforeNode) {*beforeNode = prev;}i++;}
}// 替換字符串
void replaceString(char* srcText, char* dstText) {if (!curFile) return;char content[3] = { 0 };char byte;size_t len = strlen(srcText);Node* curNode = curFile->text->head->next;while (curNode != curFile->text->tail) {Node* tmpNode = curNode;bool isFound = true;// 查找子串for (int i = 0; i < len && tmpNode != curFile->text->tail; i++) {byte = srcText[i];if (byte >= 0) {// 這是普通字符content[0] = byte;if (byte == '\r') {char nextByte = srcText[++i];content[1] = nextByte;}else {content[1] = '\0';}}else {// 這是中文,其占2個字節char nextByte = srcText[++i];content[0] = byte;content[1] = nextByte;}// 判斷兩個字符是否相同if (strcmp(tmpNode->content, content) != 0) {isFound = false;break;}tmpNode = tmpNode->next;}if (isFound) {// 首先刪除原字符串Node* beforeNode = curNode->prev;while (beforeNode->next != tmpNode) {Node* node = beforeNode->next;beforeNode->next = node->next;node->next->prev = beforeNode;free(node);}curNode = tmpNode;// 添加替換字符串appendString(&beforeNode, dstText, false);}else {curNode = curNode->next;}}
}
Editor.h:是 Editor.cpp 的頭文件,聲明了文本編輯器相關的函數接口,確保其他文件能夠調用 Editor.cpp 中定義的函數。
聲明了文本編輯器相關的函數,如:
-
initTextEditor()
:初始化編輯器。 -
runTextEditor()
:運行編輯器的主循環。 -
destroyTextEditor()
:銷毀編輯器。
#pragma once
/*
該模塊用于顯示文本編輯器的界面和用戶交互
*/// 初始化文本編輯器
void initTextEditor();// 運行文本編輯器
void runTextEditor();// 銷毀文本編輯器
void destroyTextEditor();
Editor.cpp:文本編輯器的核心,負責創建并顯示圖形界面,同時處理文件操作、文本編輯、用戶輸入事件等。它利用 EasyX 圖形庫來繪制窗口和菜單,支持文件的讀寫操作、文本的插入與刪除、文本的查找和替換。
-
initTextEditor()
:-
初始化文本編輯器,創建窗口并設置背景色。
-
使用
initgraph()
函數來初始化窗口,setbkcolor()
設置背景色為白色,SetWindowText()
設置窗口的標題為 "文本編輯器"。 -
還通過
readResources()
函數加載圖像資源(如editor.png
),并設置圖形界面的直線樣式。
-
-
runTextEditor()
:-
啟動文本編輯器的主循環。在這個循環中,程序不斷更新窗口,清除設備并重新繪制所有組件(如菜單和文本區域)。
-
處理鍵盤事件(如刪除字符)和鼠標點擊事件(如選擇菜單項):
-
鍵盤事件:當按下刪除鍵(
VK_BACK
)時,刪除當前光標位置的字符。 -
鼠標事件:檢測鼠標點擊的區域,根據用戶點擊的菜單項執行不同操作,如讀入文件、寫入文件、新建文件等。
-
-
-
drawWindow()
:-
用于繪制編輯器窗口,包括背景圖像、菜單區域和文本區域。
-
使用
putimage()
函數繪制背景圖像,并調用drawMenu()
和drawText()
來繪制菜單和文本區域。
-
-
drawMenu()
:-
繪制頂部的菜單區域,包括文件操作(如讀入、寫入、保存等)和文本編輯操作(如插入文本、查找、替換)。
-
使用
outtextxy()
函數繪制菜單項文本,并用roundrect()
繪制按鈕。
-
-
InsertText()
:-
提示用戶輸入要插入的文字,并調用
insertText()
函數將文字插入到當前光標位置。
-
-
FindString()
:-
查找字符串。調用
findString()
函數查找指定的字符串并將找到的文本高亮顯示。
-
-
ReplaceString()
:-
替換字符串。通過
replaceString()
函數,查找指定的原字符串并將其替換為新字符串。
-
#include "Editor.h"
#include <graphics.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <time.h>
#include <math.h>
#include "Text.h"// 窗口大小
static int WINDOW_WIDTH = 1000;
static int WINDOW_HEIGHT = 700;// 設置每幀的時間
static double FPS = 30;
static double PER_FRAME_TIME = 1000.0 / FPS;// 查找字符串
static char searchText[256] = {0};// 原字符串
static char sourceText[256] = { 0 };// 替換字符串
static char replaceText[256] = { 0 };// 設置菜單區域的位置
static int MENU_LEFT_TOP[] = { 10, 80 };
static int MENU_RIGHT_BOTTOM[] = { 900, 220 };
static int PADDING[] = {50, 16};// 讀入文件菜單位置
static int READ_FILE_MENU[] = { MENU_LEFT_TOP[0] + PADDING[0], MENU_LEFT_TOP[1] + PADDING[1],MENU_LEFT_TOP[0] + PADDING[0] + 104, MENU_LEFT_TOP[1] + PADDING[1] + 25 };
// 寫入文件菜單位置
static int WRITE_FILE_MENU[] = { READ_FILE_MENU[2] + PADDING[0], MENU_LEFT_TOP[1] + PADDING[1],READ_FILE_MENU[2] + PADDING[0] + 104, MENU_LEFT_TOP[1] + PADDING[1] + 25 };
// 新建文件菜單位置
static int CREATE_FILE_MENU[] = { WRITE_FILE_MENU[2] + PADDING[0], MENU_LEFT_TOP[1] + PADDING[1],WRITE_FILE_MENU[2] + PADDING[0] + 104, MENU_LEFT_TOP[1] + PADDING[1] + 25 };
// 保存文件菜單位置
static int SAVE_FILE_MENU[] = { CREATE_FILE_MENU[2] + PADDING[0], MENU_LEFT_TOP[1] + PADDING[1],CREATE_FILE_MENU[2] + PADDING[0] + 104, MENU_LEFT_TOP[1] + PADDING[1] + 25 };
// 退出菜單位置
static int EXIT_MENU[] = { SAVE_FILE_MENU[2] + PADDING[0], MENU_LEFT_TOP[1] + PADDING[1],SAVE_FILE_MENU[2] + PADDING[0] + 52, MENU_LEFT_TOP[1] + PADDING[1] + 25 };
// 編輯文件菜單位置
static int EDIT_FILE_MENU[] = { MENU_LEFT_TOP[0] + PADDING[0], READ_FILE_MENU[3] + PADDING[1],MENU_LEFT_TOP[0] + PADDING[0] + 104, READ_FILE_MENU[3] + PADDING[1] + 25 };
// 插入菜單位置
static int INSERT_TEXT_MENU[] = { MENU_LEFT_TOP[0] + PADDING[0], EDIT_FILE_MENU[3] + PADDING[1],MENU_LEFT_TOP[0] + PADDING[0] + 104, EDIT_FILE_MENU[3] + PADDING[1] + 25 };
// 查找文本位置
static int SEARCH_TEXT[] = { EDIT_FILE_MENU[2] + PADDING[0], READ_FILE_MENU[3] + PADDING[1],EDIT_FILE_MENU[2] + PADDING[0] + 208, READ_FILE_MENU[3] + PADDING[1] + 25 };
// 查找菜單位置
static int FIND_MENU[] = { SEARCH_TEXT[2] + PADDING[0], READ_FILE_MENU[3] + PADDING[1],SEARCH_TEXT[2] + PADDING[0] + 52, READ_FILE_MENU[3] + PADDING[1] + 25 };
// 清除高亮菜單位置
static int CLEAR_MENU[] = { FIND_MENU[2] + PADDING[0], READ_FILE_MENU[3] + PADDING[1],FIND_MENU[2] + PADDING[0] + 104, READ_FILE_MENU[3] + PADDING[1] + 25 };
// 原文本位置
static int SOURCE_TEXT[] = { EDIT_FILE_MENU[2] + PADDING[0], FIND_MENU[3] + PADDING[1],EDIT_FILE_MENU[2] + PADDING[0] + 208, FIND_MENU[3] + PADDING[1] + 25 };
// 替換文本位置
static int REPLACE_TEXT[] = { SOURCE_TEXT[2] + PADDING[0], FIND_MENU[3] + PADDING[1],SOURCE_TEXT[2] + PADDING[0] + 208, FIND_MENU[3] + PADDING[1] + 25 };
// 替換菜單位置
static int REPLACE_MENU[] = { REPLACE_TEXT[2] + PADDING[0], FIND_MENU[3] + PADDING[1],REPLACE_TEXT[2] + PADDING[0] + 52, FIND_MENU[3] + PADDING[1] + 25 };
// 文本區域位置
static int TEXT_AREA[] = { 10, MENU_RIGHT_BOTTOM[1] + PADDING[1], WINDOW_WIDTH-20, WINDOW_HEIGHT - 20 };// 圖片資源
static IMAGE editorImage;// 讀取圖片資源
static void readResources();// 繪制窗口
static void drawWindow();// 繪制菜單區域
static void drawMenu();// 繪制文本區域
static void drawText();// 讀入文件
static void ReadFile();// 寫入文件
static void WriteFile();// 新建文件
static void CreateNewFile();// 保存文件
static void SaveFile();// 插入文字
static void InsertText();// 查找
static void FindString();// 清除輸入
static void ClearInput();// 替換
static void ReplaceString();// 更新文件指針位置
static void updateCursor(int x, int y);// 初始化文本編輯器
void initTextEditor() {// 創建窗口 initgraph(WINDOW_WIDTH, WINDOW_HEIGHT);setbkcolor(RGB(255, 255, 255));// 設置窗口名稱HWND hWnd = GetHWnd();SetWindowText(hWnd, "文本編輯器");// 讀取圖片資源readResources();// 設置直線樣式LINESTYLE style;style.thickness = 2;setlinestyle(&style);
}// 運行文本編輯器
void runTextEditor() {bool exitCode = false;while (!exitCode) {int startTime = clock();// 雙緩沖 BeginBatchDraw();cleardevice();// 繪制窗口drawWindow();EndBatchDraw();// 處理消息static ExMessage msg;while (peekmessage(&msg, EM_KEY | EM_MOUSE)) {// 鍵盤按下事件if (msg.message == WM_KEYDOWN) {if (msg.vkcode == VK_BACK) {// 刪除指針指向的字符deleteCharacter(false);}else if (msg.vkcode == VK_DELETE) {// 刪除指針后面的字符deleteCharacter(true);}}// 鼠標左鍵按下事件else if (msg.message == WM_LBUTTONDOWN) {int x = msg.x;int y = msg.y;// 點擊了讀入文件按鈕if (x > READ_FILE_MENU[0] && x < READ_FILE_MENU[2] &&y > READ_FILE_MENU[1] && y < READ_FILE_MENU[3]) {ReadFile();}// 點擊了寫入文件按鈕else if (x > WRITE_FILE_MENU[0] && x < WRITE_FILE_MENU[2] &&y > WRITE_FILE_MENU[1] && y < WRITE_FILE_MENU[3]) {WriteFile();}// 點擊了創建文件按鈕else if (x > CREATE_FILE_MENU[0] && x < CREATE_FILE_MENU[2] &&y > CREATE_FILE_MENU[1] && y < CREATE_FILE_MENU[3]) {CreateNewFile();}// 點擊了保存文件按鈕else if (x > SAVE_FILE_MENU[0] && x < SAVE_FILE_MENU[2] &&y > SAVE_FILE_MENU[1] && y < SAVE_FILE_MENU[3]) {SaveFile();}// 點擊了退出按鈕else if (x > EXIT_MENU[0] && x < EXIT_MENU[2] &&y > EXIT_MENU[1] && y < EXIT_MENU[3]) {// 釋放相關內存freeResources();exitCode = true;break;}// 點擊了插入文字按鈕else if (x > INSERT_TEXT_MENU[0] && x < INSERT_TEXT_MENU[2] &&y > INSERT_TEXT_MENU[1] && y < INSERT_TEXT_MENU[3]) {InsertText();}// 點擊了查找按鈕else if (x > FIND_MENU[0] && x < FIND_MENU[2] &&y > FIND_MENU[1] && y < FIND_MENU[3]) {FindString();}// 點擊了清楚高亮按鈕else if (x > CLEAR_MENU[0] && x < CLEAR_MENU[2] &&y > CLEAR_MENU[1] && y < CLEAR_MENU[3]) {ClearInput();}// 點擊了替換按鈕else if (x > REPLACE_MENU[0] && x < REPLACE_MENU[2] &&y > REPLACE_MENU[1] && y < REPLACE_MENU[3]) {ReplaceString();}// 點擊了文本區域else if (x > TEXT_AREA[0] && x < TEXT_AREA[2] &&y > TEXT_AREA[1] && y < TEXT_AREA[3]) {updateCursor(x, y);}// 輸入查找字符串else if (x > SEARCH_TEXT[0] && x < SEARCH_TEXT[2] &&y > SEARCH_TEXT[1] && y < SEARCH_TEXT[3]) {InputBox(searchText, 255, "輸入查找字符串:");}// 輸入原字符串else if (x > SOURCE_TEXT[0] && x < SOURCE_TEXT[2] &&y > SOURCE_TEXT[1] && y < SOURCE_TEXT[3]) {InputBox(sourceText, 255, "輸入原字符串:");}// 輸入替換字符串else if (x > REPLACE_TEXT[0] && x < REPLACE_TEXT[2] &&y > REPLACE_TEXT[1] && y < REPLACE_TEXT[3]) {InputBox(replaceText, 255, "輸入替換字符串:");}}}// 控制每幀時間 int duration = clock() - startTime;if (duration < PER_FRAME_TIME) {Sleep(PER_FRAME_TIME - duration);}}
}// 銷毀文本編輯器
void destroyTextEditor() {closegraph();
}// 讀取圖片資源
static void readResources() {loadimage(&editorImage, "editor.png");
}// 繪制窗口
static void drawWindow() {// 繪制編輯器圖片putimage(0, 0, &editorImage);// 繪制菜單區域drawMenu();// 繪制文本區域drawText();
}// 繪制菜單區域
static void drawMenu() {// 設置字體LOGFONT f;gettextstyle(&f);f.lfHeight = 25;_tcscpy(f.lfFaceName, _T("黑體"));f.lfQuality = ANTIALIASED_QUALITY;f.lfWeight = 800;settextstyle(&f);settextcolor(RGB(0, 0, 0));// 繪制文件編輯器的菜單setlinecolor(RGB(0, 0, 0));rectangle(MENU_LEFT_TOP[0], MENU_LEFT_TOP[1], MENU_RIGHT_BOTTOM[0], MENU_RIGHT_BOTTOM[1]);// 讀入文件菜單outtextxy(READ_FILE_MENU[0], READ_FILE_MENU[1], "讀入文件");roundrect(READ_FILE_MENU[0], READ_FILE_MENU[1], READ_FILE_MENU[2], READ_FILE_MENU[3], 5, 5);// 寫入文件菜單outtextxy(WRITE_FILE_MENU[0], WRITE_FILE_MENU[1], "寫入文件");roundrect(WRITE_FILE_MENU[0], WRITE_FILE_MENU[1], WRITE_FILE_MENU[2], WRITE_FILE_MENU[3], 5, 5);// 新建文件菜單outtextxy(CREATE_FILE_MENU[0], CREATE_FILE_MENU[1], "新建文件");roundrect(CREATE_FILE_MENU[0], CREATE_FILE_MENU[1], CREATE_FILE_MENU[2], CREATE_FILE_MENU[3], 5, 5);// 保存文件菜單outtextxy(SAVE_FILE_MENU[0], SAVE_FILE_MENU[1], "保存文件");roundrect(SAVE_FILE_MENU[0], SAVE_FILE_MENU[1], SAVE_FILE_MENU[2], SAVE_FILE_MENU[3], 5, 5);// 退出菜單outtextxy(EXIT_MENU[0], EXIT_MENU[1], "退出");roundrect(EXIT_MENU[0], EXIT_MENU[1], EXIT_MENU[2], EXIT_MENU[3], 5, 5);// 編輯文件菜單outtextxy(EDIT_FILE_MENU[0], EDIT_FILE_MENU[1], "編輯文件");// 插入菜單outtextxy(INSERT_TEXT_MENU[0], INSERT_TEXT_MENU[1], "插入文字");roundrect(INSERT_TEXT_MENU[0], INSERT_TEXT_MENU[1], INSERT_TEXT_MENU[2], INSERT_TEXT_MENU[3], 5, 5);// 查找菜單outtextxy(FIND_MENU[0], FIND_MENU[1], "查找");roundrect(FIND_MENU[0], FIND_MENU[1], FIND_MENU[2], FIND_MENU[3], 5, 5);// 清除輸入菜單outtextxy(CLEAR_MENU[0], CLEAR_MENU[1], "清除輸入");roundrect(CLEAR_MENU[0], CLEAR_MENU[1], CLEAR_MENU[2], CLEAR_MENU[3], 5, 5);// 替換菜單outtextxy(REPLACE_MENU[0], REPLACE_MENU[1], "替換");roundrect(REPLACE_MENU[0], REPLACE_MENU[1], REPLACE_MENU[2], REPLACE_MENU[3], 5, 5);// 設置字體gettextstyle(&f);f.lfHeight = 18;_tcscpy(f.lfFaceName, _T("宋體"));f.lfQuality = ANTIALIASED_QUALITY;f.lfWeight = 800;settextstyle(&f);settextcolor(RGB(0, 0, 0));// 查找文本if (strlen(searchText) > 0) {outtextxy(SEARCH_TEXT[0], SEARCH_TEXT[1]+3, searchText);}roundrect(SEARCH_TEXT[0], SEARCH_TEXT[1], SEARCH_TEXT[2], SEARCH_TEXT[3], 5, 5);// 原文本if (strlen(sourceText) > 0) {outtextxy(SOURCE_TEXT[0], SOURCE_TEXT[1] + 3, sourceText);}roundrect(SOURCE_TEXT[0], SOURCE_TEXT[1], SOURCE_TEXT[2], SOURCE_TEXT[3], 5, 5);// 替換文本if (strlen(replaceText) > 0) {outtextxy(REPLACE_TEXT[0], REPLACE_TEXT[1] + 3, replaceText);}roundrect(REPLACE_TEXT[0], REPLACE_TEXT[1], REPLACE_TEXT[2], REPLACE_TEXT[3], 5, 5);
}// 繪制文本區域
static void drawText() {// 設置字體LOGFONT f;gettextstyle(&f);f.lfHeight = 20;f.lfWeight = 600;_tcscpy(f.lfFaceName, _T("宋體"));f.lfQuality = ANTIALIASED_QUALITY;settextstyle(&f);settextcolor(RGB(0, 0, 0));// 顯示文本區域框rectangle(TEXT_AREA[0], TEXT_AREA[1], TEXT_AREA[2], TEXT_AREA[3]);// 顯示文件內容File* file = getCurrentFile();if (!file) return;int leftX = TEXT_AREA[0] + 5;int x = leftX;int y = TEXT_AREA[1] + 5;int w = textwidth("a");int h = f.lfHeight;Node* node = file->text->head->next;// 設置頭指針的位置file->text->head->rect[0] = TEXT_AREA[0]+4;file->text->head->rect[1] = y;file->text->head->rect[2] = TEXT_AREA[0]+4;file->text->head->rect[3] = y;// 如果文件是空的,則在開頭顯示指針if (node == file->text->tail) {line(node->prev->rect[2], node->prev->rect[1], node->prev->rect[2], node->prev->rect[1] + h);return;}while (node != file->text->tail) {// 設置字符所占的區域node->rect[0] = x;node->rect[1] = y;node->rect[2] = x + (node->normal ? w : w*2);node->rect[3] = y + h;// 判斷是否需要換行if (strcmp(node->content, "\r\n") == 0 || strcmp(node->content, "\n") == 0 || node->rect[2] >= TEXT_AREA[2]) {// 需要換行,更新位置x = leftX;y += f.lfHeight;node->rect[0] = x;node->rect[1] = y;node->rect[2] = x + (node->normal ? w : w * 2);node->rect[3] = y + h;}if (strcmp(node->content, "\r\n") != 0 && strcmp(node->content, "\n") != 0) {// 如果字符被選中,則更改顏色if (node->selected) {setcolor(RED);}else {setcolor(BLACK);}// 顯示該字符outtextxy(node->rect[0], node->rect[1], node->content);// 更新x值x = node->rect[2];}// 繪制當前位置指針if (file->text->cursor == node->prev) {line(node->prev->rect[2], node->prev->rect[1], node->prev->rect[2], node->prev->rect[1] + h);}else if (file->text->cursor == node && node->next == file->text->tail) {line(node->rect[2], node->rect[1], node->rect[2], node->rect[1] + h);}node = node->next;}
}// 更新文件指針位置
static void updateCursor(int x, int y) {File* file = getCurrentFile();if (!file) return;// 設置文件指針到最靠近鼠標的文字的位置(距離不能超過26)int minDistance = INT_MAX;Node* node = file->text->head->next;while (node != file->text->tail) {if (x > node->rect[0] && x < node->rect[2] &&y > node->rect[1] && y < node->rect[3]) {file->text->cursor = node;break;}else {// 判斷該文字是否更加靠近鼠標點擊的位置int dx = (node->rect[0] + node->rect[2]) / 2 - x;int dy = (node->rect[1] + node->rect[3]) / 2 - y;double dist = sqrt(dx * dx + dy * dy);if (dist < 26 && dist < minDistance) {minDistance = dist;file->text->cursor = node;}}node = node->next;}
}// 讀入文件
static void ReadFile() {// 提示用戶輸入文件路徑char path[256];InputBox(path, 255, "輸入文件路徑:");// 讀入文件內容if (!readFile(path)) {MessageBox(GetHWnd(), "該文件不存在", "提示", MB_OK);}
}// 寫入文件
static void WriteFile() {if (getCurrentFile()) {writeFile();MessageBox(GetHWnd(), "內容已被寫入文件", "提示", MB_OK);}
}// 新建文件
static void CreateNewFile() {// 提示用戶輸入文件路徑char path[256];InputBox(path, 255, "輸入文件路徑:");// 創建新的文件if (!createFile(path)) {MessageBox(GetHWnd(), "創建文件失敗", "提示", MB_OK);}
}// 保存文件
static void SaveFile() {// 提示用戶輸入文件路徑char path[256];InputBox(path, 255, "輸入文件路徑:");if (!saveFile(path)) {MessageBox(GetHWnd(), "保存文件失敗", "提示", MB_OK);}else {MessageBox(GetHWnd(), "文件已被保存", "提示", MB_OK);}
}// 插入文字
static void InsertText() {// 提示輸入要插入的文字char content[256];InputBox(content, 255, "輸入要插入的文字:");// 把該文字插入指針所在位置insertText(content);
}// 查找
static void FindString() {resetSelected();if (strlen(searchText) > 0) {findString(searchText);}
}// 清除輸入
static void ClearInput() {memset(searchText, 0, sizeof(searchText));memset(sourceText, 0, sizeof(sourceText));memset(replaceText, 0, sizeof(replaceText));// 重置選中標志resetSelected();
}// 替換
static void ReplaceString() {if (strlen(sourceText) > 0 && strlen(replaceText) > 0) {replaceString(sourceText, replaceText);}
}
Main.cpp:程序的入口文件,主要用于啟動文本編輯器的初始化、運行和銷毀。
main()
:
-
程序啟動時首先調用
initTextEditor()
函數初始化文本編輯器。 -
接著調用
runTextEditor()
啟動文本編輯器的主循環,允許用戶進行各種操作(如文件操作、文本編輯等)。 -
最后通過
destroyTextEditor()
銷毀編輯器,釋放資源。
#include "Editor.h"int main() {// 初始化文本編輯器initTextEditor();// 運行文本編輯器runTextEditor();// 銷毀文本編輯器destroyTextEditor();return 0;
}