windowsAPI文本编辑器(不能编)
2026-02-11 15:23:50
发布于:四川
// 提升Windows API版本到Vista
#define WINVER 0x0600
#define _WIN32_WINNT 0x0600
// 强制使用ANSI字符集
#define _MBCS
#include <windows.h>
#include <string>
#include <vector>
#include <algorithm>
#include <sstream>
#include <set>
#include <cstring>
#include <cctype>
// 链接必要库
#pragma comment(lib, "comctl32.lib")
// 窗口类名
#define MAIN_WINDOW_CLASS "TextEditorMainClass"
#define EDITOR_WINDOW_CLASS "TextEditorEditClass"
// 控件ID
#define ID_BTN_ENTER_EDITOR 1001 // 主页跳转按钮
#define ID_STATIC_STATUS 1003 // 状态栏
// 颜色定义
#define COLOR_BG RGB(244, 164, 96) // 土黄色背景
#define COLOR_OPERATOR RGB(255, 0, 0) // 运算符:红色
#define COLOR_PREPROCESS RGB(128, 0, 128) // 预处理指令:紫色
#define COLOR_HEADER RGB(0, 102, 204) // 头文件:深蓝色
#define COLOR_COMMENT RGB(0, 128, 0) // 注释:绿色
#define COLOR_FUNC RGB(153, 0, 153) // 常用函数:深紫色
#define COLOR_CONSTANT RGB(139, 69, 19) // 常量:棕色
#define COLOR_KEYWORD RGB(255, 165, 0) // 核心关键字:橙色
#define COLOR_LINE_NUM RGB(0, 0, 0) // 行号:黑色
#define COLOR_TEXT RGB(0, 0, 0) // 普通文本:黑色
#define COLOR_CARET_LINE RGB(255, 248, 220) // 光标行高亮(浅黄)
#define COLOR_MATCH_BRACKET RGB(255, 215, 0) // 匹配括号(金色)
#define COLOR_EDIT_BG RGB(255, 255, 255) // 编辑区背景(白色)
#define COLOR_SELECTION RGB(173, 216, 230) // 选中区域高亮(浅蓝)
// 全局变量
HWND g_hwndEditor = NULL; // 编辑器窗口句柄
int g_fontSize = 12; // 默认字体大小
LOGFONT g_logFont = {0}; // 字体结构
HFONT g_hFont = NULL; // 字体句柄
stdsetstd::string g_operators; // 运算符集合
stdsetstd::string g_preprocess; // 预处理指令集合
stdsetstd::string g_headers; // 头文件集合
stdsetstd::string g_keywords; // 核心关键字集合
stdsetstd::string g_core_funcs; // 常用函数集合
stdsetstd::string g_constants; // 常量集合
// 文本缓冲区和光标信息
std::vectorstd::string g_textLines; // 存储每行文本
int g_caretLine = 0; // 当前光标行(从0开始)
int g_caretCol = 0; // 当前光标列(从0开始)
int g_viewportTop = 0; // 视图顶部可见行
int g_matchBracketLine = -1; // 匹配括号所在行
int g_matchBracketCol = -1; // 匹配括号所在列
// 新增:选中区域相关(全选/复制需要)
int g_selectStartLine = -1; // 选中起始行
int g_selectStartCol = -1; // 选中起始列
int g_selectEndLine = -1; // 选中结束行
int g_selectEndCol = -1; // 选中结束列
bool g_isSelected = false; // 是否有选中内容
// ===================== 核心修复:添加函数原型声明 =====================
// 确保所有被调用的函数在调用前有声明
void UpdateStatusBar();
void FindMatchingBracket();
void HandleDelete();
void InsertChar(char ch);
void HandleNewLine();
void HandleBackspace();
void ClearScreen();
void UpdateFont();
void ScreenToTextPos(int x, int y, int& line, int& col);
void DrawTextContent(HDC hdc);
COLORREF GetCharColor(int lineIdx, int colIdx);
void InitKeywordSets();
void InitSampleCode();
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK EditorWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
BOOL RegisterWindowClasses(HINSTANCE hInstance);
// 示例代码
const char* g_sampleCode =
"// 简易C示例代码(可自由修改)\n"
"#include <iostream>\n"
"#include <string>\n"
"#include <vector>\n"
"\n"
"// 计算两数之和的函数\n"
"int add(int a, int b) {\n"
" return a + b;\n"
"}\n"
"\n"
"int main() {\n"
" // 定义变量\n"
" int num1 = 10;\n"
" int num2 = 20;\n"
" std::string hello = "Hello, C!";\n"
" const bool flag = true;\n"
" \n"
" // 输出信息\n"
" stdcout << hello << stdendl;\n"
" stdcout << "10 + 20 = " << add(num1, num2) << stdendl;\n"
" \n"
" // 循环示例\n"
" for (int i = 0; i < 5; i++) {\n"
" stdcout << "循环次数:" << i << stdendl;\n"
" }\n"
" \n"
" // 条件判断\n"
" if (num1 > num2) {\n"
" stdcout << num1 << " 大于 " << num2 << stdendl;\n"
" } else {\n"
" stdcout << num1 << " 小于等于 " << num2 << stdendl;\n"
" }\n"
" \n"
" // 数组/容器示例\n"
" stdvector<int> nums = {1, 2, 3, 4, 5};\n"
" for (auto num : nums) {\n"
" stdcout << "数组元素:" << num << std::endl;\n"
" }\n"
" \n"
" return 0;\n"
"}\n";
// 初始化关键字集合
void InitKeywordSets() {
// 运算符集合
const char* ops[] = {"+", "-", "", "/", "%", "=", "+=", "-=", "=", "/=", "%=",
"==", "!=", "<", ">", "<=", ">=", "&&", "||", "!", "&", "|",
"^", "~", "<<", ">>", "", "--", "?", ":", ",", ";", "(", ")",
"{", "}", "[", "]", ".", "->", "<<=", ">>=", "&=", "^=", "|="};
for (size_t i = 0; i < sizeof(ops)/sizeof(ops[0]); i) {
g_operators.insert(ops[i]);
}
// 预处理指令
const char* pre[] = {"include", "define", "ifdef", "ifndef", "endif", "else", "elif",
"pragma", "error", "warning", "line", "undef"};
for (size_t i = 0; i < sizeof(pre)/sizeof(pre[0]); i++) {
g_preprocess.insert(pre[i]);
g_preprocess.insert("#" + std::string(pre[i]));
}
// 头文件
const char* c_headers[] = {"stdio.h", "stdlib.h", "string.h", "math.h", "ctype.h", "time.h",
"iostream", "fstream", "sstream", "vector", "string", "map", "set"};
const char* win_headers[] = {"windows.h", "winbase.h", "winuser.h"};
for (size_t i = 0; i < sizeof(c_headers)/sizeof(c_headers[0]); i++) {
g_headers.insert(c_headers[i]);
}
for (size_t i = 0; i < sizeof(win_headers)/sizeof(win_headers[0]); i++) {
g_headers.insert(win_headers[i]);
}
// 关键字
const char* keywords[] = {"int", "char", "float", "double", "bool", "void", "short", "long",
"if", "else", "for", "while", "do", "return", "const", "static",
"class", "struct", "enum", "namespace", "using", "auto", "true", "false"};
for (size_t i = 0; i < sizeof(keywords)/sizeof(keywords[0]); i++) {
g_keywords.insert(keywords[i]);
}
// 常用函数
const char* core_funcs[] = {"printf", "scanf", "cout", "cin", "endl", "malloc", "free", "abs", "sqrt"};
for (size_t i = 0; i < sizeof(core_funcs)/sizeof(core_funcs[0]); i++) {
g_core_funcs.insert(core_funcs[i]);
}
// 常量
const char* constants[] = {"true", "false", "NULL", "EOF"};
for (size_t i = 0; i < sizeof(constants)/sizeof(constants[0]); i++) {
g_constants.insert(constants[i]);
}
}
// 初始化示例代码到文本缓冲区
void InitSampleCode() {
g_textLines.clear();
std::string code(g_sampleCode);
size_t pos = 0;
size_t prev = 0;
// 按换行符分割示例代码到文本缓冲区
while ((pos = code.find('\n', prev)) != std::string::npos) {
g_textLines.push_back(code.substr(prev, pos - prev));
prev = pos + 1;
}
// 添加最后一行
g_textLines.push_back(code.substr(prev));
// 初始化光标位置到代码末尾
g_caretLine = g_textLines.size() - 1;
g_caretCol = g_textLines.back().length();
g_viewportTop = 0;
// 初始化选中状态
g_selectStartLine = g_selectEndLine = -1;
g_selectStartCol = g_selectEndCol = -1;
g_isSelected = false;
}
// 更新状态栏
void UpdateStatusBar() {
if (!g_hwndEditor) return;
// 计算总字符数
int charCount = 0;
for (const auto& line : g_textLines) {
charCount += line.length();
}
// 光标位置(行/列从1开始)
char buf[128] = {0};
sprintf(buf, "字符数:%d | 行:%d 列:%d", charCount, g_caretLine + 1, g_caretCol + 1);
SetWindowText(GetDlgItem(g_hwndEditor, ID_STATIC_STATUS), buf);
}
// 创建/更新字体
void UpdateFont() {
// 销毁旧字体
if (g_hFont) {
DeleteObject(g_hFont);
g_hFont = NULL;
}
// 创建新字体
g_logFont.lfHeight = -MulDiv(g_fontSize, GetDeviceCaps(GetDC(g_hwndEditor), LOGPIXELSY), 72);
g_logFont.lfWeight = FW_NORMAL;
g_logFont.lfCharSet = ANSI_CHARSET;
g_logFont.lfPitchAndFamily = FIXED_PITCH | FF_MODERN; // 等宽字体
strcpy(g_logFont.lfFaceName, "Consolas");
g_hFont = CreateFontIndirect(&g_logFont);
}
// 查找匹配的括号
void FindMatchingBracket() {
g_matchBracketLine = -1;
g_matchBracketCol = -1;
if (g_caretLine < 0 || g_caretLine >= (int)g_textLines.size()) return;
const std::string& line = g_textLines[g_caretLine];
if (g_caretCol <= 0 || g_caretCol > (int)line.length()) return;
char ch = line[g_caretCol - 1];
char matchCh = 0;
int dir = 0;
// 判断括号类型和查找方向
if (ch == '(') { matchCh = ')'; dir = 1; }
else if (ch == ')') { matchCh = '('; dir = -1; }
else if (ch == '{') { matchCh = '}'; dir = 1; }
else if (ch == '}') { matchCh = '{'; dir = -1; }
else if (ch == '[') { matchCh = ']'; dir = 1; }
else if (ch == ']') { matchCh = '['; dir = -1; }
else return;
int count = 1;
int currentLine = g_caretLine;
int currentCol = g_caretCol - 1 + dir;
while (count > 0) {
// 处理列边界
if (dir == 1) {
if (currentCol >= (int)g_textLines[currentLine].length()) {
currentLine++;
currentCol = 0;
}
} else {
if (currentCol < 0) {
currentLine--;
if (currentLine < 0) break;
currentCol = g_textLines[currentLine].length() - 1;
}
}
// 处理行边界
if (currentLine < 0 || currentLine >= (int)g_textLines.size()) break;
// 检查字符
char currCh = g_textLines[currentLine][currentCol];
if (currCh == ch) {
count++;
} else if (currCh == matchCh) {
count--;
}
// 找到匹配
if (count == 0) {
g_matchBracketLine = currentLine;
g_matchBracketCol = currentCol;
break;
}
currentCol += dir;
}
}
// 获取字符的着色颜色
COLORREF GetCharColor(int lineIdx, int colIdx) {
const std::string& line = g_textLines[lineIdx];
if (colIdx >= (int)line.length()) return COLOR_TEXT;
char ch = line[colIdx];
// 1. 注释(//)
if (colIdx + 1 < (int)line.length() && line[colIdx] == '/' && line[colIdx+1] == '/') {
return COLOR_COMMENT;
}
// 2. 预处理指令(#开头)
if (colIdx == 0 && ch == '#') {
return COLOR_PREPROCESS;
}
if (colIdx > 0 && line[colIdx-1] == '#' && isalpha(ch)) {
return COLOR_PREPROCESS;
}
// 3. 运算符
std::string op1(1, ch);
if (g_operators.count(op1)) {
return COLOR_OPERATOR;
}
if (colIdx + 1 < (int)line.length()) {
std::string op2 = line.substr(colIdx, 2);
if (g_operators.count(op2)) {
return COLOR_OPERATOR;
}
}
// 4. 关键字/函数/常量
if (isalpha(ch) || ch == '_') {
// 找到单词边界
int start = colIdx;
while (start > 0 && (isalnum(line[start-1]) || line[start-1] == '_')) {
start--;
}
int end = colIdx;
while (end < (int)line.length() && (isalnum(line[end]) || line[end] == '_')) {
end++;
}
std::string word = line.substr(start, end - start);
if (g_constants.count(word)) return COLOR_CONSTANT;
if (g_core_funcs.count(word)) return COLOR_FUNC;
if (g_keywords.count(word)) return COLOR_KEYWORD;
if (g_headers.count(word)) return COLOR_HEADER;
}
return COLOR_TEXT;
}
// 新增:将屏幕坐标转换为文本行/列(鼠标点击跳转核心)
void ScreenToTextPos(int x, int y, int& line, int& col) {
RECT rcClient;
GetClientRect(g_hwndEditor, &rcClient);
int lineNumWidth = g_fontSize * 2;
int editLeft = lineNumWidth + 10;
int editTop = 40;
int charWidth = g_fontSize * 0.6; // 等宽字体字符宽度
int lineHeight = g_fontSize + 2; // 行高
// 计算行(相对编辑区的y坐标转换为文本行)
int yRel = y - editTop;
if (yRel < 0) {
line = 0;
} else {
line = g_viewportTop + (yRel / lineHeight);
// 边界保护
if (line >= (int)g_textLines.size()) {
line = g_textLines.size() - 1;
}
}
// 计算列(相对编辑区的x坐标转换为文本列)
int xRel = x - editLeft;
if (xRel < 0) {
col = 0;
} else {
col = xRel / charWidth;
// 边界保护(不超过当前行长度)
if (col > (int)g_textLines[line].length()) {
col = g_textLines[line].length();
}
}
}
// 绘制文本(核心绘制逻辑,新增选中区域高亮)
void DrawTextContent(HDC hdc) {
if (g_textLines.empty()) return;
// 设置字体
SelectObject(hdc, g_hFont);
SetBkMode(hdc, TRANSPARENT);
// 获取编辑区区域
RECT rcClient;
GetClientRect(g_hwndEditor, &rcClient);
// 行号区域宽度
int lineNumWidth = g_fontSize * 2;
// 编辑区起始位置
int editLeft = lineNumWidth + 10;
int editTop = 40;
int charWidth = g_fontSize * 0.6; // 等宽字体字符宽度
int lineHeight = g_fontSize + 2; // 行高
// 计算可见行范围
int visibleLines = (rcClient.bottom - editTop) / lineHeight;
int endLine = std::min(g_viewportTop + visibleLines, (int)g_textLines.size());
// 绘制编辑区背景
RECT rcEdit = {editLeft, editTop, rcClient.right - 10, rcClient.bottom - 10};
HBRUSH hEditBrush = CreateSolidBrush(COLOR_EDIT_BG);
FillRect(hdc, &rcEdit, hEditBrush);
DeleteObject(hEditBrush);
// 新增:绘制选中区域高亮
if (g_isSelected && g_selectStartLine != -1 && g_selectEndLine != -1) {
int startLine = std::min(g_selectStartLine, g_selectEndLine);
int endLineSel = std::max(g_selectStartLine, g_selectEndLine);
// 只绘制可见范围内的选中区域
if (startLine < endLine && endLineSel >= g_viewportTop) {
for (int i = startLine; i <= endLineSel; i++) {
if (i < g_viewportTop || i >= endLine) continue;
int y = editTop + (i - g_viewportTop) * lineHeight;
// 计算当前行的选中列范围
int colStart = (i == g_selectStartLine) ? g_selectStartCol : 0;
int colEnd = (i == g_selectEndLine) ? g_selectEndCol : (int)g_textLines[i].length();
// 处理选中范围反转
if (startLine != g_selectStartLine) {
colStart = (i == endLineSel) ? g_selectEndCol : 0;
colEnd = (i == startLine) ? g_selectStartCol : (int)g_textLines[i].length();
}
int xStart = editLeft + colStart * charWidth;
int xEnd = editLeft + colEnd * charWidth;
// 绘制选中背景
RECT rcSelect = {xStart, y, xEnd, y + lineHeight};
HBRUSH hSelectBrush = CreateSolidBrush(COLOR_SELECTION);
FillRect(hdc, &rcSelect, hSelectBrush);
DeleteObject(hSelectBrush);
}
}
}
// 绘制光标行高亮
if (g_caretLine >= g_viewportTop && g_caretLine < endLine) {
int y = editTop + (g_caretLine - g_viewportTop) * lineHeight;
RECT rcCaretLine = {editLeft, y, rcClient.right - 10, y + lineHeight};
HBRUSH hCaretBrush = CreateSolidBrush(COLOR_CARET_LINE);
FillRect(hdc, &rcCaretLine, hCaretBrush);
DeleteObject(hCaretBrush);
}
// 逐行绘制
for (int i = g_viewportTop; i < endLine; i++) {
const std::string& line = g_textLines[i];
int y = editTop + (i - g_viewportTop) * lineHeight;
// 绘制行号
char lineNumBuf[16];
sprintf(lineNumBuf, "%d", i + 1);
SetTextColor(hdc, COLOR_LINE_NUM);
TextOut(hdc, 5, y, lineNumBuf, strlen(lineNumBuf));
// 逐字符绘制(支持语法着色)
for (int j = 0; j < (int)line.length(); j++) {
int x = editLeft + j * charWidth;
// 绘制匹配括号高亮
if ((i == g_caretLine && j == g_caretCol - 1) ||
(i == g_matchBracketLine && j == g_matchBracketCol)) {
// 括号背景高亮
RECT rcBracket = {x, y, x + charWidth, y + lineHeight};
HBRUSH hBracketBrush = CreateSolidBrush(COLOR_MATCH_BRACKET);
FillRect(hdc, &rcBracket, hBracketBrush);
DeleteObject(hBracketBrush);
}
// 设置字符颜色
COLORREF color = GetCharColor(i, j);
SetTextColor(hdc, color);
// 绘制单个字符
char chBuf[2] = {line[j], 0};
TextOut(hdc, x, y, chBuf, 1);
}
// 绘制光标
if (i == g_caretLine) {
int x = editLeft + g_caretCol * charWidth;
// 绘制光标竖线
SetTextColor(hdc, RGB(0, 0, 0));
MoveToEx(hdc, x, y, NULL);
LineTo(hdc, x, y + lineHeight - 2);
}
}
}
// 插入字符到当前光标位置
void InsertChar(char ch) {
// 插入前先清除选中内容
if (g_isSelected) {
HandleDelete(); // 复用删除逻辑清除选中内容
g_isSelected = false;
g_selectStartLine = g_selectEndLine = -1;
g_selectStartCol = g_selectEndCol = -1;
}
if (g_caretLine < 0 || g_caretLine >= (int)g_textLines.size()) return;
std::string& line = g_textLines[g_caretLine];
line.insert(g_caretCol, 1, ch);
g_caretCol++;
// 运算符自动补全
if (ch == '(') InsertChar(')'), g_caretCol--;
else if (ch == '{') InsertChar('}'), g_caretCol--;
else if (ch == '[') InsertChar(']'), g_caretCol--;
else if (ch == '<' && (g_caretCol == 1 || !isspace(line[g_caretCol-2]))) InsertChar('>'), g_caretCol--;
// 重绘并更新状态
InvalidateRect(g_hwndEditor, NULL, TRUE);
UpdateStatusBar();
FindMatchingBracket();
}
// 处理换行
void HandleNewLine() {
// 换行前清除选中
if (g_isSelected) {
HandleDelete();
g_isSelected = false;
g_selectStartLine = g_selectEndLine = -1;
g_selectStartCol = g_selectEndCol = -1;
}
if (g_caretLine < 0 || g_caretLine >= (int)g_textLines.size()) return;
// 拆分当前行
std::string& currentLine = g_textLines[g_caretLine];
std::string part1 = currentLine.substr(0, g_caretCol);
std::string part2 = currentLine.substr(g_caretCol);
// 更新当前行
currentLine = part1;
// 插入新行
g_textLines.insert(g_textLines.begin() + g_caretLine + 1, part2);
// 处理缩进
std::string indent;
for (char c : part1) {
if (c == ' ' || c == '\t') indent += c;
else break;
}
// 如果上一行以{结尾,增加缩进
if (!part1.empty() && part1.back() == '{') {
indent += " ";
}
// 移动光标到新行
g_caretLine++;
g_caretCol = indent.length();
// 插入缩进
g_textLines[g_caretLine] = indent + g_textLines[g_caretLine];
// 滚动视图(如果需要)
RECT rcClient;
GetClientRect(g_hwndEditor, &rcClient);
int visibleLines = (rcClient.bottom - 40) / (g_fontSize + 2);
if (g_caretLine >= g_viewportTop + visibleLines) {
g_viewportTop = g_caretLine - 10;
if (g_viewportTop < 0) g_viewportTop = 0;
}
InvalidateRect(g_hwndEditor, NULL, TRUE);
UpdateStatusBar();
FindMatchingBracket();
}
// 处理退格
void HandleBackspace() {
// 退格前清除选中
if (g_isSelected) {
HandleDelete();
g_isSelected = false;
g_selectStartLine = g_selectEndLine = -1;
g_selectStartCol = g_selectEndCol = -1;
return;
}
if (g_caretCol > 0) {
// 删除当前行的字符
std::string& line = g_textLines[g_caretLine];
line.erase(g_caretCol - 1, 1);
g_caretCol--;
} else if (g_caretLine > 0) {
// 合并到上一行
std::string& prevLine = g_textLines[g_caretLine - 1];
std::string& currLine = g_textLines[g_caretLine];
prevLine += currLine;
g_textLines.erase(g_textLines.begin() + g_caretLine);
g_caretLine--;
g_caretCol = prevLine.length() - currLine.length();
}
InvalidateRect(g_hwndEditor, NULL, TRUE);
UpdateStatusBar();
FindMatchingBracket();
}
// 处理删除键(新增:支持删除选中区域)
void HandleDelete() {
if (g_isSelected) {
// 删除选中区域
if (g_selectStartLine == g_selectEndLine) {
// 单行选中
g_textLines[g_selectStartLine].erase(g_selectStartCol, g_selectEndCol - g_selectStartCol);
g_caretLine = g_selectStartLine;
g_caretCol = g_selectStartCol;
} else {
// 多行选中
// 1. 处理起始行剩余内容
std::string& startLine = g_textLines[g_selectStartLine];
startLine.erase(g_selectStartCol);
// 2. 处理结束行剩余内容
std::string& endLine = g_textLines[g_selectEndLine];
std::string endPart = endLine.substr(g_selectEndCol);
// 3. 合并到起始行
startLine += endPart;
// 4. 删除中间行和结束行
g_textLines.erase(g_textLines.begin() + g_selectStartLine + 1,
g_textLines.begin() + g_selectEndLine + 1);
// 5. 更新光标位置
g_caretLine = g_selectStartLine;
g_caretCol = startLine.length() - endPart.length();
}
// 清除选中状态
g_isSelected = false;
g_selectStartLine = g_selectEndLine = -1;
g_selectStartCol = g_selectEndCol = -1;
} else if (g_caretCol < (int)g_textLines[g_caretLine].length()) {
// 删除当前字符
g_textLines[g_caretLine].erase(g_caretCol, 1);
} else if (g_caretLine < (int)g_textLines.size() - 1) {
// 合并下一行
std::string& currLine = g_textLines[g_caretLine];
std::string& nextLine = g_textLines[g_caretLine + 1];
currLine += nextLine;
g_textLines.erase(g_textLines.begin() + g_caretLine + 1);
}
InvalidateRect(g_hwndEditor, NULL, TRUE);
UpdateStatusBar();
FindMatchingBracket();
}
// 清屏功能(无system调用)
void ClearScreen() {
g_textLines.clear();
g_textLines.push_back("");
g_caretLine = 0;
g_caretCol = 0;
g_viewportTop = 0;
g_matchBracketLine = -1;
g_matchBracketCol = -1;
// 清除选中状态
g_isSelected = false;
g_selectStartLine = g_selectEndLine = -1;
g_selectStartCol = g_selectEndCol = -1;
InvalidateRect(g_hwndEditor, NULL, TRUE);
UpdateStatusBar();
}
// 主页窗口过程
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_CREATE: {
CreateWindowA("BUTTON", "进入文本编辑器",
WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
200, 150, 180, 40,
hwnd, (HMENU)ID_BTN_ENTER_EDITOR,
(HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE), NULL);
break;
}
case WM_COMMAND: {
if (LOWORD(wParam) == ID_BTN_ENTER_EDITOR) {
ShowWindow(hwnd, SW_HIDE);
g_hwndEditor = CreateWindowA(EDITOR_WINDOW_CLASS, "简易C++文本编辑器(纯绘制版)",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, 900, 700,
NULL, NULL, (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE), NULL);
}
break;
}
case WM_DESTROY: {
PostQuitMessage(0);
break;
}
default:
return DefWindowProcA(hwnd, msg, wParam, lParam);
}
return 0;
}
// 编辑器窗口过程(纯绘制实现,新增快捷键和鼠标处理)
LRESULT CALLBACK EditorWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_CREATE: {
// 创建状态栏
CreateWindowA("STATIC", "字符数:0 | 行:1 列:1",
WS_VISIBLE | WS_CHILD | SS_LEFT,
10, 10, 250, 20,
hwnd, (HMENU)ID_STATIC_STATUS,
(HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE), NULL);
// 初始化字体
UpdateFont();
// 加载示例代码
InitSampleCode();
// 初始化状态
UpdateStatusBar();
FindMatchingBracket();
break;
}
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
// 绘制窗口背景
RECT rcClient;
GetClientRect(hwnd, &rcClient);
HBRUSH hBgBrush = CreateSolidBrush(COLOR_BG);
FillRect(hdc, &rcClient, hBgBrush);
DeleteObject(hBgBrush);
// 绘制文本内容
DrawTextContent(hdc);
EndPaint(hwnd, &ps);
break;
}
// 新增:鼠标左键点击处理(光标跳转)
case WM_LBUTTONDOWN: {
// 获取鼠标屏幕坐标
int x = LOWORD(lParam);
int y = HIWORD(lParam);
// 转换为文本行/列
int targetLine, targetCol;
ScreenToTextPos(x, y, targetLine, targetCol);
// 更新光标位置
g_caretLine = targetLine;
g_caretCol = targetCol;
// 清除选中状态
g_isSelected = false;
g_selectStartLine = g_selectEndLine = -1;
g_selectStartCol = g_selectEndCol = -1;
// 重绘并更新状态
InvalidateRect(hwnd, NULL, TRUE);
UpdateStatusBar();
FindMatchingBracket();
break;
}
case WM_CHAR: {
switch (wParam) {
case '\b': // 退格
HandleBackspace();
break;
case '\t': // Tab键(4个空格)
InsertChar(' ');
InsertChar(' ');
InsertChar(' ');
InsertChar(' ');
break;
case '\n': // 换行
HandleNewLine();
break;
case 0x12: // Ctrl+L 清屏
ClearScreen();
break;
default: // 普通字符
if (wParam >= 32 && wParam <= 126) { // 可打印字符
InsertChar((char)wParam);
}
break;
}
return 0;
}
case WM_KEYDOWN: {
switch (wParam) {
case VK_DELETE: // 删除键
HandleDelete();
break;
case VK_LEFT: // 左箭头
if (g_caretCol > 0) g_caretCol--;
else if (g_caretLine > 0) {
g_caretLine--;
g_caretCol = g_textLines[g_caretLine].length();
}
InvalidateRect(hwnd, NULL, TRUE);
UpdateStatusBar();
FindMatchingBracket();
break;
case VK_RIGHT: // 右箭头
if (g_caretCol < (int)g_textLines[g_caretLine].length()) g_caretCol++;
else if (g_caretLine < (int)g_textLines.size() - 1) {
g_caretLine++;
g_caretCol = 0;
}
InvalidateRect(hwnd, NULL, TRUE);
UpdateStatusBar();
FindMatchingBracket();
break;
case VK_UP: // 上箭头
if (g_caretLine > 0) {
g_caretLine--;
// 调整列位置(不超过当前行长度)
g_caretCol = std::min(g_caretCol, (int)g_textLines[g_caretLine].length());
// 滚动视图
if (g_caretLine < g_viewportTop) {
g_viewportTop = g_caretLine;
}
}
InvalidateRect(hwnd, NULL, TRUE);
UpdateStatusBar();
FindMatchingBracket();
break;
case VK_DOWN: // 下箭头
if (g_caretLine < (int)g_textLines.size() - 1) {
g_caretLine++;
// 调整列位置
g_caretCol = std::min(g_caretCol, (int)g_textLines[g_caretLine].length());
// 滚动视图
RECT rcClient;
GetClientRect(hwnd, &rcClient);
int visibleLines = (rcClient.bottom - 40) / (g_fontSize + 2);
if (g_caretLine >= g_viewportTop + visibleLines) {
g_viewportTop = g_caretLine - visibleLines + 1;
}
}
InvalidateRect(hwnd, NULL, TRUE);
UpdateStatusBar();
FindMatchingBracket();
break;
case VK_CONTROL: // Ctrl键(配合滚轮调整字号)
break;
// 新增:Ctrl+A 全选
case 'A':
case 'a':
if (GetKeyState(VK_CONTROL) & 0x8000) {
// 设置全选范围
g_selectStartLine = 0;
g_selectStartCol = 0;
g_selectEndLine = g_textLines.size() - 1;
g_selectEndCol = g_textLines.back().length();
g_isSelected = true;
// 光标移到文本末尾
g_caretLine = g_selectEndLine;
g_caretCol = g_selectEndCol;
InvalidateRect(hwnd, NULL, TRUE);
UpdateStatusBar();
break;
}
// 新增:Ctrl+C 复制选中内容
case 'C':
case 'c':
if (GetKeyState(VK_CONTROL) & 0x8000 && g_isSelected) {
// 拼接选中的文本
std::string selectedText;
for (int i = g_selectStartLine; i <= g_selectEndLine; i++) {
const std::string& line = g_textLines[i];
int startCol = (i == g_selectStartLine) ? g_selectStartCol : 0;
int endCol = (i == g_selectEndLine) ? g_selectEndCol : (int)line.length();
if (startCol < endCol) {
selectedText += line.substr(startCol, endCol - startCol);
}
// 非最后一行添加换行符
if (i != g_selectEndLine) {
selectedText += "\n";
}
}
// 复制到剪贴板
if (!selectedText.empty()) {
OpenClipboard(hwnd);
EmptyClipboard();
// 分配全局内存
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, selectedText.length() + 1);
if (hGlobal) {
char* pBuf = (char*)GlobalLock(hGlobal);
strcpy(pBuf, selectedText.c_str());
GlobalUnlock(hGlobal);
// 设置剪贴板数据
SetClipboardData(CF_TEXT, hGlobal);
}
CloseClipboard();
}
break;
}
// 新增:Ctrl+V 粘贴剪贴板内容
case 'V':
case 'v':
if (GetKeyState(VK_CONTROL) & 0x8000) {
// 打开剪贴板
OpenClipboard(hwnd);
HANDLE hData = GetClipboardData(CF_TEXT);
if (hData) {
// 获取剪贴板文本
char* pBuf = (char*)GlobalLock(hData);
std::string pasteText(pBuf);
GlobalUnlock(hData);
// 先删除选中内容(如果有)
if (g_isSelected) {
HandleDelete();
}
// 分割粘贴文本为多行
size_t pos = 0;
size_t prev = 0;
std::vector<std::string> pasteLines;
while ((pos = pasteText.find('\n', prev)) != std::string::npos) {
pasteLines.push_back(pasteText.substr(prev, pos - prev));
prev = pos + 1;
}
pasteLines.push_back(pasteText.substr(prev));
// 插入粘贴内容
if (pasteLines.size() == 1) {
// 单行:直接插入到当前光标位置
g_textLines[g_caretLine].insert(g_caretCol, pasteLines[0]);
g_caretCol += pasteLines[0].length();
} else {
// 多行:拆分当前行并插入
std::string& currentLine = g_textLines[g_caretLine];
std::string part1 = currentLine.substr(0, g_caretCol);
std::string part2 = currentLine.substr(g_caretCol);
// 更新当前行
currentLine = part1 + pasteLines[0];
g_caretCol = currentLine.length();
// 插入中间行
for (size_t i = 1; i < pasteLines.size() - 1; i++) {
g_textLines.insert(g_textLines.begin() + g_caretLine + 1, pasteLines[i]);
g_caretLine++;
g_caretCol = pasteLines[i].length();
}
// 插入最后一行(拼接原行剩余内容)
g_textLines.insert(g_textLines.begin() + g_caretLine + 1, pasteLines.back() + part2);
g_caretLine++;
g_caretCol = pasteLines.back().length();
}
// 重绘并更新状态
InvalidateRect(hwnd, NULL, TRUE);
UpdateStatusBar();
FindMatchingBracket();
}
CloseClipboard();
break;
}
}
break;
}
case WM_MOUSEWHEEL: {
// Ctrl+滚轮调整字号
if (GET_KEYSTATE_WPARAM(wParam) & MK_CONTROL) {
int delta = GET_WHEEL_DELTA_WPARAM(wParam);
if (delta > 0 && g_fontSize < 24) {
g_fontSize++;
} else if (delta < 0 && g_fontSize > 8) {
g_fontSize--;
}
UpdateFont();
InvalidateRect(hwnd, NULL, TRUE);
} else {
// 滚轮滚动视图
int delta = GET_WHEEL_DELTA_WPARAM(wParam);
if (delta > 0 && g_viewportTop > 0) {
g_viewportTop--;
} else if (delta < 0) {
RECT rcClient;
GetClientRect(hwnd, &rcClient);
int visibleLines = (rcClient.bottom - 40) / (g_fontSize + 2);
if (g_viewportTop + visibleLines < (int)g_textLines.size()) {
g_viewportTop++;
}
}
InvalidateRect(hwnd, NULL, TRUE);
}
break;
}
case WM_DESTROY: {
// 销毁字体
if (g_hFont) {
DeleteObject(g_hFont);
g_hFont = NULL;
}
// 显示主页
HWND hwndMain = FindWindowA(MAIN_WINDOW_CLASS, "简易C++文本编辑器-主页");
if (hwndMain) ShowWindow(hwndMain, SW_SHOW);
DestroyWindow(hwnd);
g_hwndEditor = NULL;
break;
}
default:
return DefWindowProcA(hwnd, msg, wParam, lParam);
}
return 0;
}
// 注册窗口类
BOOL RegisterWindowClasses(HINSTANCE hInstance) {
// 注册主页窗口类
WNDCLASSEXA wcMain = {0};
wcMain.cbSize = sizeof(WNDCLASSEXA);
wcMain.lpfnWndProc = MainWndProc;
wcMain.hInstance = hInstance;
wcMain.lpszClassName = MAIN_WINDOW_CLASS;
wcMain.hbrBackground = CreateSolidBrush(COLOR_BG);
wcMain.hCursor = LoadCursor(NULL, IDC_ARROW);
if (!RegisterClassExA(&wcMain)) return FALSE;
// 注册编辑器窗口类
WNDCLASSEXA wcEditor = {0};
wcEditor.cbSize = sizeof(WNDCLASSEXA);
wcEditor.lpfnWndProc = EditorWndProc;
wcEditor.hInstance = hInstance;
wcEditor.lpszClassName = EDITOR_WINDOW_CLASS;
wcEditor.hbrBackground = CreateSolidBrush(COLOR_BG);
wcEditor.hCursor = LoadCursor(NULL, IDC_ARROW);
if (!RegisterClassExA(&wcEditor)) return FALSE;
return TRUE;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
// 初始化关键字集合
InitKeywordSets();
// 注册窗口类
if (!RegisterWindowClasses(hInstance)) {
MessageBoxA(NULL, "窗口类注册失败!", "错误", MB_ICONERROR);
return 1;
}
// 创建主页窗口
HWND hwndMain = CreateWindowA(MAIN_WINDOW_CLASS, "简易C++文本编辑器-主页",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, 600, 400,
NULL, NULL, hInstance, NULL);
if (!hwndMain) {
MessageBoxA(NULL, "窗口创建失败!", "错误", MB_ICONERROR);
return 1;
}
// 消息循环
MSG msg = {0};
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
这里空空如也


















有帮助,赞一个