一不小心做了一个小程序
// 在文件开头添加这些定义
#define _WIN32_IE 0x0500
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <commctrl.h>
#include <shlwapi.h>
#include <string>
using namespace std;
// 在文件开头添加
#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:WinMainCRTStartup")
// MinGW 兼容的链接方式
extern "C" {
#pragma comment(lib, "comctl32")
#pragma comment(lib, "shlwapi")
#pragma comment(lib, "gdi32")
#pragma comment(lib, "comdlg32")
}
// 控件ID定义
#define IDC_EDIT 1001
#define IDC_STATUS_BAR 1002
#define IDM_FILE_OPEN 2001
#define IDM_FILE_SAVE 2002
#define IDM_FILE_SAVEAS 2003
#define IDM_FILE_EXIT 2004
#define IDM_ENCODING 2100
// 资源ID定义
#define IDI_APP_ICON 101
// 全局变量
HWND g_hEdit = NULL;
HWND g_hStatusBar = NULL;
string g_currentFile;
UINT g_currentEncoding = CP_UTF8; // 默认UTF-8编码
// 编码选项
struct EncodingOption {
UINT codePage;
const char* name;
int menuId;
};
EncodingOption g_encodingOptions[] = {
{ CP_UTF8, "UTF-8", IDM_ENCODING + 1 },
{ 936, "GBK", IDM_ENCODING + 2 },
{ 20936, "GB2312", IDM_ENCODING + 3 },
{ CP_ACP, "ANSI", IDM_ENCODING + 4 },
{ 0, NULL, 0 }
};
// 函数声明
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow);
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
void CreateControls(HWND hWnd);
BOOL LoadFile(const string& filename);
BOOL SaveFile(const string& filename);
void UpdateWindowTitle(HWND hWnd);
void SetStatusText(const char* text);
void CreateMainMenu(HWND hWnd);
string GetEncodingName(UINT codePage);
string AnsiToAnsi(const string& str, UINT fromCodePage, UINT toCodePage);
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// 初始化通用控件
INITCOMMONCONTROLSEX icex;
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
icex.dwICC = ICC_BAR_CLASSES;
InitCommonControlsEx(&icex);
if (!InitInstance(hInstance, nCmdShow))
{
return FALSE;
}
// 主消息循环
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APP_ICON));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = L"TextEditorClass";
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APP_ICON));
if (!RegisterClassEx(&wcex))
{
return FALSE;
}
HWND hWnd = CreateWindow(L"TextEditorClass", L"北山办公", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, 800, 600, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
CreateControls(hWnd);
CreateMainMenu(hWnd);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
void CreateControls(HWND hWnd)
{
// 创建编辑控件
g_hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "",
WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL,
0, 0, 0, 0, hWnd, (HMENU)IDC_EDIT, GetModuleHandle(NULL), NULL);
// 设置字体
HFONT hFont = CreateFont(16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "宋体");
SendMessage(g_hEdit, WM_SETFONT, (WPARAM)hFont, TRUE);
// 创建状态栏
g_hStatusBar = CreateWindowEx(0, STATUSCLASSNAME, NULL,
WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP, 0, 0, 0, 0, hWnd, (HMENU)IDC_STATUS_BAR,
GetModuleHandle(NULL), NULL);
// 设置状态栏分区
int parts[] = { 200, 400, -1 };
SendMessage(g_hStatusBar, SB_SETPARTS, 3, (LPARAM)parts);
SetStatusText("就绪");
}
void CreateMainMenu(HWND hWnd)
{
HMENU hMenu = CreateMenu();
HMENU hFileMenu = CreatePopupMenu();
HMENU hEncodingMenu = CreatePopupMenu();
AppendMenu(hFileMenu, MF_STRING, IDM_FILE_OPEN, "打开(&O)");
AppendMenu(hFileMenu, MF_STRING, IDM_FILE_SAVE, "保存(&S)");
AppendMenu(hFileMenu, MF_STRING, IDM_FILE_SAVEAS, "另存为(&A)");
AppendMenu(hFileMenu, MF_SEPARATOR, 0, NULL);
AppendMenu(hFileMenu, MF_STRING, IDM_FILE_EXIT, "退出(&X)");
for (int i = 0; g_encodingOptions[i].name != NULL; i++)
{
AppendMenu(hEncodingMenu, MF_STRING, g_encodingOptions[i].menuId, g_encodingOptions[i].name);
}
AppendMenu(hMenu, MF_POPUP, (UINT_PTR)hFileMenu, "文件(&F)");
AppendMenu(hMenu, MF_POPUP, (UINT_PTR)hEncodingMenu, "编码(&E)");
SetMenu(hWnd, hMenu);
}
BOOL LoadFile(const string& filename)
{
HANDLE hFile = CreateFile(filename.c_str(), GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return FALSE;
}
DWORD fileSize = GetFileSize(hFile, NULL);
if (fileSize == INVALID_FILE_SIZE)
{
CloseHandle(hFile);
return FALSE;
}
char* buffer = new char[fileSize + 1];
DWORD bytesRead;
if (!ReadFile(hFile, buffer, fileSize, &bytesRead, NULL))
{
delete[] buffer;
CloseHandle(hFile);
return FALSE;
}
buffer[bytesRead] = '\0';
CloseHandle(hFile);
// 转换为当前编码
string text = AnsiToAnsi(string(buffer, bytesRead), g_currentEncoding, CP_ACP);
delete[] buffer;
// 设置编辑控件文本
SetWindowText(g_hEdit, text.c_str());
g_currentFile = filename;
return TRUE;
}
BOOL SaveFile(const string& filename)
{
// 获取编辑控件文本
int textLength = GetWindowTextLength(g_hEdit);
char* buffer = new char[textLength + 1];
GetWindowText(g_hEdit, buffer, textLength + 1);
string text(buffer);
delete[] buffer;
// 转换为目标编码
string ansiText = AnsiToAnsi(text, CP_ACP, g_currentEncoding);
HANDLE hFile = CreateFile(filename.c_str(), GENERIC_WRITE, 0,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return FALSE;
}
DWORD bytesWritten;
BOOL result = WriteFile(hFile, ansiText.c_str(), (DWORD)ansiText.size(), &bytesWritten, NULL);
CloseHandle(hFile);
if (result)
{
g_currentFile = filename;
}
return result;
}
string AnsiToAnsi(const string& str, UINT fromCodePage, UINT toCodePage)
{
if (str.empty()) return "";
// 先转换为宽字符
int wideSize = MultiByteToWideChar(fromCodePage, 0, str.c_str(), (int)str.size(), NULL, 0);
wchar_t* wideBuffer = new wchar_t[wideSize + 1];
MultiByteToWideChar(fromCodePage, 0, str.c_str(), (int)str.size(), wideBuffer, wideSize);
wideBuffer[wideSize] = L'\0';
// 再转换回目标编码
int ansiSize = WideCharToMultiByte(toCodePage, 0, wideBuffer, wideSize, NULL, 0, NULL, NULL);
char* ansiBuffer = new char[ansiSize + 1];
WideCharToMultiByte(toCodePage, 0, wideBuffer, wideSize, ansiBuffer, ansiSize, NULL, NULL);
ansiBuffer[ansiSize] = '\0';
string result(ansiBuffer);
delete[] wideBuffer;
delete[] ansiBuffer;
return result;
}
void UpdateWindowTitle(HWND hWnd)
{
string title = "北山办公";
if (!g_currentFile.empty())
{
title += " - " + g_currentFile;
title += " (" + GetEncodingName(g_currentEncoding) + ")";
}
SetWindowText(hWnd, title.c_str());
}
string GetEncodingName(UINT codePage)
{
for (int i = 0; g_encodingOptions[i].name != NULL; i++)
{
if (g_encodingOptions[i].codePage == codePage)
{
return g_encodingOptions[i].name;
}
}
return "未知编码";
}
void SetStatusText(const char* text)
{
SendMessage(g_hStatusBar, SB_SETTEXT, 0, (LPARAM)text);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_SIZE:
{
// 调整编辑控件和状态栏大小
RECT rcClient;
GetClientRect(hWnd, &rcClient);
// 先调整状态栏
SendMessage(g_hStatusBar, WM_SIZE, wParam, lParam);
// 获取状态栏高度
RECT rcStatus;
GetWindowRect(g_hStatusBar, &rcStatus);
int statusHeight = rcStatus.bottom - rcStatus.top;
// 调整编辑控件
SetWindowPos(g_hEdit, NULL, 0, 0, rcClient.right, rcClient.bottom - statusHeight, SWP_NOZORDER);
break;
}
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// 文件菜单
if (wmId == IDM_FILE_OPEN)
{
OPENFILENAME ofn;
char szFile[MAX_PATH] = {0};
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hWnd;
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = "文本文件 (*.txt)\0*.txt\0VBS文件 (*.vbs)\0*.vbs\0NZF文件 (*.nzf)\0*.nzf\0所有文件 (*.*)\0*.*\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
if (GetOpenFileName(&ofn))
{
if (LoadFile(szFile))
{
UpdateWindowTitle(hWnd);
SetStatusText("文件加载成功");
}
else
{
SetStatusText("无法加载文件");
}
}
}
else if (wmId == IDM_FILE_SAVE)
{
if (g_currentFile.empty())
{
// 如果没有当前文件,执行另存为
SendMessage(hWnd, WM_COMMAND, IDM_FILE_SAVEAS, 0);
}
else
{
if (SaveFile(g_currentFile))
{
UpdateWindowTitle(hWnd);
SetStatusText("文件保存成功");
}
else
{
SetStatusText("无法保存文件");
}
}
}
else if (wmId == IDM_FILE_SAVEAS)
{
OPENFILENAME ofn;
char szFile[MAX_PATH] = {0};
if (!g_currentFile.empty())
{
strcpy(szFile, g_currentFile.c_str());
}
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hWnd;
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = "文本文件 (*.txt)\0*.txt\0VBS文件 (*.vbs)\0*.vbs\0NZF文件 (*.nzf)\0*.nzf\0所有文件 (*.*)\0*.*\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT;
if (GetSaveFileName(&ofn))
{
if (SaveFile(szFile))
{
UpdateWindowTitle(hWnd);
SetStatusText("文件保存成功");
}
else
{
SetStatusText("无法保存文件");
}
}
}
else if (wmId == IDM_FILE_EXIT)
{
DestroyWindow(hWnd);
}
// 编码菜单
for (int i = 0; g_encodingOptions[i].name != NULL; i++)
{
if (wmId == g_encodingOptions[i].menuId)
{
g_currentEncoding = g_encodingOptions[i].codePage;
UpdateWindowTitle(hWnd);
SetStatusText((string("编码已切换为: ") + g_encodingOptions[i].name).c_str());
break;
}
}
break;
}
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
1338



被折叠的 条评论
为什么被折叠?



