diff --git a/README.md b/README.md index b6b879b..4abcce3 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ A lightweight, 25x fast, Windows notepad alternative built with C++17 and Win32 ## Features -- **Multi-language support**: English and Japanese translations with runtime switching. +- **Multi-language support**: English, Japanese, and Traditional Chinese translations with runtime switching. - **Multi-encoding text**: UTF-8, UTF-8 BOM, UTF-16 LE/BE, ANSI with line-ending selection. - **Rich editing**: word wrap toggle, font selection, zoom, time/date stamp, find/replace/goto. - **Backgrounds**: optional image with tile/stretch/fit/fill/anchor modes and opacity control. (known issues) diff --git a/src/lang/en.h b/src/lang/en.h index 1280d2e..e346439 100644 --- a/src/lang/en.h +++ b/src/lang/en.h @@ -61,6 +61,9 @@ inline LangStrings g_langEN = { L"Fill", L"Window &Transparency...", L"Always on &Top", + L"&Icon", + L"&Change Icon...", + L"&Reset to Default", L"&Help", L"&About Notepad", @@ -68,7 +71,8 @@ inline LangStrings g_langEN = { L"&Language", L"&English", - L"&Japanese", + L"日本語(&J)", + L"繁體中文(&T)", L"Find", L"Find and Replace", diff --git a/src/lang/ja.h b/src/lang/ja.h index 31f8822..0cf923d 100644 --- a/src/lang/ja.h +++ b/src/lang/ja.h @@ -61,6 +61,9 @@ inline LangStrings g_langJA = { L"フィル", L"ウィンドウの透明度(&T)...", L"常に最前面に表示(&T)", + L"アイコン(&I)", + L"アイコンを変更(&C)...", + L"既定に戻す(&R)", L"ヘルプ(&H)", L"メモ帳について(&A)", @@ -69,6 +72,7 @@ inline LangStrings g_langJA = { L"言語(&L)", L"英語(&E)", L"日本語(&J)", + L"繁體中文(&T)", L"検索", L"検索と置換", diff --git a/src/lang/lang.cpp b/src/lang/lang.cpp index 955a42c..50d6eda 100644 --- a/src/lang/lang.cpp +++ b/src/lang/lang.cpp @@ -1,6 +1,7 @@ #include "lang.h" #include "en.h" #include "ja.h" +#include "zh_tw.h" #include static LangID g_currentLang = LangID::EN; @@ -49,6 +50,9 @@ void SetLanguage(LangID lang) case LangID::JA: g_currentStrings = &g_langJA; break; + case LangID::ZH_TW: + g_currentStrings = &g_langZHTW; + break; case LangID::EN: default: g_currentStrings = &g_langEN; diff --git a/src/lang/lang.h b/src/lang/lang.h index 838be65..398ec12 100644 --- a/src/lang/lang.h +++ b/src/lang/lang.h @@ -6,7 +6,8 @@ enum class LangID { EN, - JA + JA, + ZH_TW }; struct LangStrings @@ -69,6 +70,9 @@ struct LangStrings std::wstring menuBgPosFill; std::wstring menuTransparency; std::wstring menuAlwaysOnTop; + std::wstring menuIcon; + std::wstring menuIconChange; + std::wstring menuIconReset; std::wstring menuHelp; std::wstring menuAbout; @@ -77,6 +81,7 @@ struct LangStrings std::wstring menuLanguage; std::wstring menuLangEnglish; std::wstring menuLangJapanese; + std::wstring menuLangTraditionalChinese; std::wstring dialogFind; std::wstring dialogFindReplace; diff --git a/src/lang/zh_tw.h b/src/lang/zh_tw.h new file mode 100644 index 0000000..8ece934 --- /dev/null +++ b/src/lang/zh_tw.h @@ -0,0 +1,110 @@ +#pragma once + +#include "lang.h" + +inline LangStrings g_langZHTW = { + L"記事本", + L"未命名", + + L"檔案(&F)", + L"開新檔案(&N)\tCtrl+N", + L"開啟(&O)...\tCtrl+O", + L"儲存檔案(&S)\tCtrl+S", + L"另存新檔(&A)...\tCtrl+Shift+S", + L"列印(&P)...\tCtrl+P", + L"版面設定(&U)...", + L"結束(&X)", + L"最近使用的檔案", + + L"編輯(&E)", + L"復原(&U)\tCtrl+Z", + L"重做(&R)\tCtrl+Y", + L"剪下(&T)\tCtrl+X", + L"複製(&C)\tCtrl+C", + L"貼上(&P)\tCtrl+V", + L"刪除(&L)\tDel", + L"尋找(&F)...\tCtrl+F", + L"找下一個(&N)\tF3", + L"找上一個(&V)\tShift+F3", + L"取代(&H)...\tCtrl+H", + L"到指定行(&G)...\tCtrl+G", + L"全選(&A)\tCtrl+A", + L"時間/日期(&D)\tF5", + + L"格式(&O)", + L"自動換行(&W)", + L"字型(&F)...", + + L"檢視(&V)", + L"放大(&I)\tCtrl+Plus", + L"縮小(&O)\tCtrl+Minus", + L"還原預設縮放(&R)\tCtrl+0", + L"狀態列(&S)", + L"深色模式(&D)", + L"背景(&B)", + L"選取圖片(&S)...", + L"清除背景(&C)", + L"不透明度(&O)...", + L"位置(&P)", + L"左上", + L"上方置中", + L"右上", + L"中央靠左", + L"置中", + L"中央靠右", + L"左下", + L"下方置中", + L"右下", + L"並排顯示", + L"延展", + L"最適大小", + L"填滿", + L"視窗透明度(&T)...", + L"最上層顯示(&A)", + L"圖示(&I)", + L"變更圖示(&C)...", + L"重設為預設值(&R)", + + L"說明(&H)", + L"關於記事本(&A)", + L"檢查更新(&U)", + + L"語言(&L)", + L"English(&E)", + L"日本語(&J)", + L"繁體中文(&T)", + + L"尋找", + L"尋找與取代", + L"到指定行", + L"視窗透明度", + L"尋找:", + L"取代為:", + L"找下一個", + L"取代", + L"全部取代", + L"關閉", + L"行號:", + L"確定", + L"取消", + L"不透明度 (10-100%):", + + L"找不到 \"", + L"是否要儲存對下列檔案的變更: ", + L"無法開啟檔案。", + L"無法儲存檔案。", + L"錯誤", + L"Legacy Notepad v1.2.0\n\n快速、輕量的文字編輯器。\n\n使用 C++ 與 Win32 API 建置。\n", + + L" 第 ", + L" 行,第 ", + + L"UTF-8", + L"UTF-8 with BOM", + L"UTF-16 LE", + L"UTF-16 BE", + L"ANSI", + + L"Windows (CRLF)", + L"Unix (LF)", + L"Macintosh (CR)"}; diff --git a/src/main.cpp b/src/main.cpp index 9eb4b5f..5409a7d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -68,9 +68,13 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) return -1; } } + + DWORD editorStyle = WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN | ES_NOHIDESEL; + if (!g_state.wordWrap) + editorStyle |= WS_HSCROLL | ES_AUTOHSCROLL; + g_hwndEditor = CreateWindowExW(0, richEditClass, nullptr, - WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN | ES_NOHIDESEL, - 0, 0, 100, 100, hwnd, reinterpret_cast(IDC_EDITOR), GetModuleHandleW(nullptr), nullptr); + editorStyle, 0, 0, 100, 100, hwnd, reinterpret_cast(IDC_EDITOR), GetModuleHandleW(nullptr), nullptr); g_origEditorProc = reinterpret_cast(SetWindowLongPtrW(g_hwndEditor, GWLP_WNDPROC, reinterpret_cast(EditorSubclassProc))); g_hwndStatus = CreateWindowExW(0, STATUSCLASSNAMEW, nullptr, WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP, 0, 0, 0, 0, hwnd, reinterpret_cast(IDC_STATUSBAR), GetModuleHandleW(nullptr), nullptr); @@ -81,6 +85,7 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) SetupStatusBarParts(); UpdateMenuStrings(); UpdateLanguageMenu(); + CheckMenuItem(GetMenu(g_hwndMain), IDM_FORMAT_WORDWRAP, g_state.wordWrap ? MF_CHECKED : MF_UNCHECKED); CheckMenuItem(GetMenu(g_hwndMain), IDM_VIEW_ALWAYSONTOP, g_state.alwaysOnTop ? MF_CHECKED : MF_UNCHECKED); if (g_state.alwaysOnTop) SetWindowPos(g_hwndMain, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); @@ -442,6 +447,18 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) UpdateTitle(); UpdateStatus(); break; + case IDM_VIEW_LANG_ZH_TW: + if (g_hwndFindDlg) + { + DestroyWindow(g_hwndFindDlg); + g_hwndFindDlg = nullptr; + } + SetLanguage(LangID::ZH_TW); + UpdateMenuStrings(); + UpdateLanguageMenu(); + UpdateTitle(); + UpdateStatus(); + break; case IDM_VIEW_ICON_CHANGE: ViewChangeIcon(); break; diff --git a/src/modules/background.cpp b/src/modules/background.cpp index 56575ad..0ccbf9c 100644 --- a/src/modules/background.cpp +++ b/src/modules/background.cpp @@ -17,6 +17,7 @@ #include "core/globals.h" #include "theme.h" #include "resource.h" +#include "lang/lang.h" #include #include #include @@ -331,11 +332,12 @@ static INT_PTR CALLBACK OpacityDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARA case WM_INITDIALOG: { ApplyBackgroundDialogDarkMode(hDlg); + const auto &lang = GetLangStrings(); HFONT hFont = reinterpret_cast(GetStockObject(DEFAULT_GUI_FONT)); - CreateWindowExW(0, L"STATIC", L"Opacity (0-100%):", WS_CHILD | WS_VISIBLE, 10, 15, 110, 20, hDlg, nullptr, nullptr, nullptr); - hEdit = CreateWindowExW(WS_EX_CLIENTEDGE, L"EDIT", L"", WS_CHILD | WS_VISIBLE | ES_NUMBER, 125, 12, 60, 22, hDlg, reinterpret_cast(1001), nullptr, nullptr); - CreateWindowExW(0, L"BUTTON", L"OK", WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 55, 50, 70, 26, hDlg, reinterpret_cast(IDOK), nullptr, nullptr); - CreateWindowExW(0, L"BUTTON", L"Cancel", WS_CHILD | WS_VISIBLE, 135, 50, 70, 26, hDlg, reinterpret_cast(IDCANCEL), nullptr, nullptr); + CreateWindowExW(0, L"STATIC", lang.dialogOpacityLabel.c_str(), WS_CHILD | WS_VISIBLE, 15, 25, 135, 20, hDlg, nullptr, nullptr, nullptr); + hEdit = CreateWindowExW(WS_EX_CLIENTEDGE, L"EDIT", L"", WS_CHILD | WS_VISIBLE | ES_NUMBER, 155, 22, 70, 24, hDlg, reinterpret_cast(1001), nullptr, nullptr); + CreateWindowExW(0, L"BUTTON", lang.dialogOK.c_str(), WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 75, 72, 85, 28, hDlg, reinterpret_cast(IDOK), nullptr, nullptr); + CreateWindowExW(0, L"BUTTON", lang.dialogCancel.c_str(), WS_CHILD | WS_VISIBLE, 175, 72, 85, 28, hDlg, reinterpret_cast(IDCANCEL), nullptr, nullptr); for (HWND h = GetWindow(hDlg, GW_CHILD); h; h = GetWindow(h, GW_HWNDNEXT)) SendMessageW(h, WM_SETFONT, reinterpret_cast(hFont), TRUE); int pct = g_state.background.opacity * 100 / 255; @@ -397,8 +399,8 @@ static INT_PTR CALLBACK OpacityDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARA void ViewBackgroundOpacity() { - HWND hDlg = CreateWindowExW(WS_EX_DLGMODALFRAME, L"#32770", L"Background Opacity", - WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE, 300, 300, 270, 120, + const auto &lang = GetLangStrings(); +HWND hDlg = CreateWindowExW(WS_EX_DLGMODALFRAME, L"#32770", lang.menuBgOpacity.c_str(), WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE, 300, 300, 340, 175, g_hwndMain, nullptr, GetModuleHandleW(nullptr), nullptr); if (!hDlg) return; diff --git a/src/modules/commands.cpp b/src/modules/commands.cpp index 996cf9e..3ff2a68 100644 --- a/src/modules/commands.cpp +++ b/src/modules/commands.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include static HICON LoadCustomIcon(const wchar_t *path) @@ -199,7 +200,7 @@ void FilePageSetup() } void EditUndo() { SendMessageW(g_hwndEditor, EM_UNDO, 0, 0); } -void EditRedo() { SendMessageW(g_hwndEditor, EM_UNDO, 0, 0); } +void EditRedo() { SendMessageW(g_hwndEditor, EM_REDO, 0, 0); } void EditCut() { SendMessageW(g_hwndEditor, WM_CUT, 0, 0); } void EditCopy() { SendMessageW(g_hwndEditor, WM_COPY, 0, 0); } void EditPaste() { SendMessageW(g_hwndEditor, WM_PASTE, 0, 0); } @@ -221,6 +222,7 @@ void FormatWordWrap() { g_state.wordWrap = !g_state.wordWrap; CheckMenuItem(GetMenu(g_hwndMain), IDM_FORMAT_WORDWRAP, g_state.wordWrap ? MF_CHECKED : MF_UNCHECKED); + SaveFontSettings(); ApplyWordWrap(); } diff --git a/src/modules/dialog.cpp b/src/modules/dialog.cpp index fed1632..8305d0d 100644 --- a/src/modules/dialog.cpp +++ b/src/modules/dialog.cpp @@ -282,7 +282,9 @@ INT_PTR CALLBACK FindDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) newText += text.substr(lastPos); if (newText != text) { - SetEditorText(newText); + SendMessageW(g_hwndEditor, EM_SETSEL, 0, -1); + SendMessageW(g_hwndEditor, EM_REPLACESEL, TRUE, reinterpret_cast(newText.c_str())); + SendMessageW(g_hwndEditor, EM_SETSEL, 0, 0); g_state.modified = true; UpdateTitle(); } @@ -336,15 +338,15 @@ void EditFind() } const auto &lang = GetLangStrings(); g_hwndFindDlg = CreateWindowExW(WS_EX_DLGMODALFRAME, L"#32770", lang.dialogFind.c_str(), - WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE, 100, 100, 420, 120, + WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE, 100, 100, 520, 170, g_hwndMain, nullptr, GetModuleHandleW(nullptr), nullptr); if (g_hwndFindDlg) { HFONT hFont = reinterpret_cast(GetStockObject(DEFAULT_GUI_FONT)); - CreateWindowExW(0, L"STATIC", lang.dialogFindLabel.c_str(), WS_CHILD | WS_VISIBLE, 10, 12, 45, 16, g_hwndFindDlg, nullptr, nullptr, nullptr); - CreateWindowExW(WS_EX_CLIENTEDGE, L"EDIT", g_state.findText.c_str(), WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL, 60, 10, 230, 20, g_hwndFindDlg, reinterpret_cast(1001), nullptr, nullptr); - CreateWindowExW(0, L"BUTTON", lang.dialogFindNext.c_str(), WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 300, 10, 100, 22, g_hwndFindDlg, reinterpret_cast(1), nullptr, nullptr); - CreateWindowExW(0, L"BUTTON", lang.dialogClose.c_str(), WS_CHILD | WS_VISIBLE, 300, 38, 100, 22, g_hwndFindDlg, reinterpret_cast(2), nullptr, nullptr); + CreateWindowExW(0, L"STATIC", lang.dialogFindLabel.c_str(), WS_CHILD | WS_VISIBLE, 15, 18, 70, 18, g_hwndFindDlg, nullptr, nullptr, nullptr); + CreateWindowExW(WS_EX_CLIENTEDGE, L"EDIT", g_state.findText.c_str(), WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL, 90, 15, 270, 24, g_hwndFindDlg, reinterpret_cast(1001), nullptr, nullptr); + CreateWindowExW(0, L"BUTTON", lang.dialogFindNext.c_str(), WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 375, 14, 120, 28, g_hwndFindDlg, reinterpret_cast(1), nullptr, nullptr); + CreateWindowExW(0, L"BUTTON", lang.dialogClose.c_str(), WS_CHILD | WS_VISIBLE, 375, 50, 120, 28, g_hwndFindDlg, reinterpret_cast(2), nullptr, nullptr); for (HWND h = GetWindow(g_hwndFindDlg, GW_CHILD); h; h = GetWindow(h, GW_HWNDNEXT)) SendMessageW(h, WM_SETFONT, reinterpret_cast(hFont), TRUE); SetWindowLongPtrW(g_hwndFindDlg, GWLP_WNDPROC, reinterpret_cast(FindDlgProc)); @@ -375,19 +377,19 @@ void EditReplace() } const auto &lang = GetLangStrings(); g_hwndFindDlg = CreateWindowExW(WS_EX_DLGMODALFRAME, L"#32770", lang.dialogFindReplace.c_str(), - WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE, 100, 100, 420, 175, + WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE, 100, 100, 540, 240, g_hwndMain, nullptr, GetModuleHandleW(nullptr), nullptr); if (g_hwndFindDlg) { HFONT hFont = reinterpret_cast(GetStockObject(DEFAULT_GUI_FONT)); - CreateWindowExW(0, L"STATIC", lang.dialogFindLabel.c_str(), WS_CHILD | WS_VISIBLE, 10, 12, 45, 16, g_hwndFindDlg, nullptr, nullptr, nullptr); - CreateWindowExW(WS_EX_CLIENTEDGE, L"EDIT", g_state.findText.c_str(), WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL, 60, 10, 230, 20, g_hwndFindDlg, reinterpret_cast(1001), nullptr, nullptr); - CreateWindowExW(0, L"STATIC", lang.dialogReplaceLabel.c_str(), WS_CHILD | WS_VISIBLE, 10, 40, 50, 16, g_hwndFindDlg, nullptr, nullptr, nullptr); - CreateWindowExW(WS_EX_CLIENTEDGE, L"EDIT", g_state.replaceText.c_str(), WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL, 60, 38, 230, 20, g_hwndFindDlg, reinterpret_cast(1002), nullptr, nullptr); - CreateWindowExW(0, L"BUTTON", lang.dialogFindNext.c_str(), WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 300, 10, 100, 22, g_hwndFindDlg, reinterpret_cast(1), nullptr, nullptr); - CreateWindowExW(0, L"BUTTON", lang.dialogReplace.c_str(), WS_CHILD | WS_VISIBLE, 300, 38, 100, 22, g_hwndFindDlg, reinterpret_cast(3), nullptr, nullptr); - CreateWindowExW(0, L"BUTTON", lang.dialogReplaceAll.c_str(), WS_CHILD | WS_VISIBLE, 300, 66, 100, 22, g_hwndFindDlg, reinterpret_cast(4), nullptr, nullptr); - CreateWindowExW(0, L"BUTTON", lang.dialogClose.c_str(), WS_CHILD | WS_VISIBLE, 300, 94, 100, 22, g_hwndFindDlg, reinterpret_cast(2), nullptr, nullptr); + CreateWindowExW(0, L"STATIC", lang.dialogFindLabel.c_str(), WS_CHILD | WS_VISIBLE, 15, 18, 70, 18, g_hwndFindDlg, nullptr, nullptr, nullptr); + CreateWindowExW(WS_EX_CLIENTEDGE, L"EDIT", g_state.findText.c_str(), WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL, 90, 15, 270, 24, g_hwndFindDlg, reinterpret_cast(1001), nullptr, nullptr); + CreateWindowExW(0, L"STATIC", lang.dialogReplaceLabel.c_str(), WS_CHILD | WS_VISIBLE, 15, 54, 70, 18, g_hwndFindDlg, nullptr, nullptr, nullptr); + CreateWindowExW(WS_EX_CLIENTEDGE, L"EDIT", g_state.replaceText.c_str(), WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL, 90, 51, 270, 24, g_hwndFindDlg, reinterpret_cast(1002), nullptr, nullptr); + CreateWindowExW(0, L"BUTTON", lang.dialogFindNext.c_str(), WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 380, 14, 130, 28, g_hwndFindDlg, reinterpret_cast(1), nullptr, nullptr); + CreateWindowExW(0, L"BUTTON", lang.dialogReplace.c_str(), WS_CHILD | WS_VISIBLE, 380, 50, 130, 28, g_hwndFindDlg, reinterpret_cast(3), nullptr, nullptr); + CreateWindowExW(0, L"BUTTON", lang.dialogReplaceAll.c_str(), WS_CHILD | WS_VISIBLE, 380, 86, 130, 28, g_hwndFindDlg, reinterpret_cast(4), nullptr, nullptr); + CreateWindowExW(0, L"BUTTON", lang.dialogClose.c_str(), WS_CHILD | WS_VISIBLE, 380, 122, 130, 28, g_hwndFindDlg, reinterpret_cast(2), nullptr, nullptr); for (HWND h = GetWindow(g_hwndFindDlg, GW_CHILD); h; h = GetWindow(h, GW_HWNDNEXT)) SendMessageW(h, WM_SETFONT, reinterpret_cast(hFont), TRUE); SetWindowLongPtrW(g_hwndFindDlg, GWLP_WNDPROC, reinterpret_cast(FindDlgProc)); @@ -459,12 +461,12 @@ void EditGoto() { const auto &lang = GetLangStrings(); HWND hDlg = CreateWindowExW(WS_EX_DLGMODALFRAME, L"#32770", lang.dialogGoTo.c_str(), - WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE, 100, 100, 250, 140, + WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE, 100, 100, 330, 190, g_hwndMain, nullptr, GetModuleHandleW(nullptr), nullptr); if (hDlg) { HFONT hFont = reinterpret_cast(GetStockObject(DEFAULT_GUI_FONT)); - CreateWindowExW(0, L"STATIC", lang.dialogLineNumber.c_str(), WS_CHILD | WS_VISIBLE, 15, 15, 100, 16, hDlg, nullptr, nullptr, nullptr); + CreateWindowExW(0, L"STATIC", lang.dialogLineNumber.c_str(), WS_CHILD | WS_VISIBLE, 15, 20, 250, 18, hDlg, nullptr, nullptr, nullptr); DWORD start = 0; SendMessageW(g_hwndEditor, EM_GETSEL, reinterpret_cast(&start), 0); @@ -472,11 +474,11 @@ void EditGoto() wchar_t buf[32]; wsprintfW(buf, L"%d", curLine); - HWND hEdit = CreateWindowExW(WS_EX_CLIENTEDGE, L"EDIT", buf, WS_CHILD | WS_VISIBLE | ES_NUMBER | ES_AUTOHSCROLL, 15, 35, 210, 22, hDlg, reinterpret_cast(1001), nullptr, nullptr); + HWND hEdit = CreateWindowExW(WS_EX_CLIENTEDGE, L"EDIT", buf, WS_CHILD | WS_VISIBLE | ES_NUMBER | ES_AUTOHSCROLL, 15, 45, 280, 24, hDlg, reinterpret_cast(1001), nullptr, nullptr); SendMessageW(hEdit, EM_SETSEL, 0, -1); - CreateWindowExW(0, L"BUTTON", lang.dialogOK.c_str(), WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 60, 70, 80, 25, hDlg, reinterpret_cast(IDOK), nullptr, nullptr); - CreateWindowExW(0, L"BUTTON", lang.dialogCancel.c_str(), WS_CHILD | WS_VISIBLE, 145, 70, 80, 25, hDlg, reinterpret_cast(IDCANCEL), nullptr, nullptr); + CreateWindowExW(0, L"BUTTON", lang.dialogOK.c_str(), WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 80, 90, 90, 28, hDlg, reinterpret_cast(IDOK), nullptr, nullptr); + CreateWindowExW(0, L"BUTTON", lang.dialogCancel.c_str(), WS_CHILD | WS_VISIBLE, 185, 90, 90, 28, hDlg, reinterpret_cast(IDCANCEL), nullptr, nullptr); for (HWND h = GetWindow(hDlg, GW_CHILD); h; h = GetWindow(h, GW_HWNDNEXT)) SendMessageW(h, WM_SETFONT, reinterpret_cast(hFont), TRUE); @@ -533,15 +535,15 @@ void ViewTransparency() wchar_t buf[32]; wsprintfW(buf, L"%d", pct); HWND hDlg = CreateWindowExW(WS_EX_DLGMODALFRAME, L"#32770", lang.dialogTransparency.c_str(), - WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE, 300, 300, 280, 110, + WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_VISIBLE, 300, 300, 340, 175, g_hwndMain, nullptr, GetModuleHandleW(nullptr), nullptr); if (hDlg) { HFONT hFont = reinterpret_cast(GetStockObject(DEFAULT_GUI_FONT)); - CreateWindowExW(0, L"STATIC", lang.dialogOpacityLabel.c_str(), WS_CHILD | WS_VISIBLE, 10, 18, 110, 20, hDlg, nullptr, nullptr, nullptr); - HWND hEdit = CreateWindowExW(WS_EX_CLIENTEDGE, L"EDIT", buf, WS_CHILD | WS_VISIBLE | ES_NUMBER, 125, 15, 60, 22, hDlg, reinterpret_cast(1001), nullptr, nullptr); - CreateWindowExW(0, L"BUTTON", lang.dialogOK.c_str(), WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 50, 50, 70, 26, hDlg, reinterpret_cast(IDOK), nullptr, nullptr); - CreateWindowExW(0, L"BUTTON", lang.dialogCancel.c_str(), WS_CHILD | WS_VISIBLE, 130, 50, 70, 26, hDlg, reinterpret_cast(IDCANCEL), nullptr, nullptr); + CreateWindowExW(0, L"STATIC", lang.dialogOpacityLabel.c_str(), WS_CHILD | WS_VISIBLE, 15, 25, 135, 20, hDlg, nullptr, nullptr, nullptr); + HWND hEdit = CreateWindowExW(WS_EX_CLIENTEDGE, L"EDIT", buf, WS_CHILD | WS_VISIBLE | ES_NUMBER, 155, 22, 70, 24, hDlg, reinterpret_cast(1001), nullptr, nullptr); + CreateWindowExW(0, L"BUTTON", lang.dialogOK.c_str(), WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 75, 72, 85, 28, hDlg, reinterpret_cast(IDOK), nullptr, nullptr); + CreateWindowExW(0, L"BUTTON", lang.dialogCancel.c_str(), WS_CHILD | WS_VISIBLE, 175, 72, 85, 28, hDlg, reinterpret_cast(IDCANCEL), nullptr, nullptr); for (HWND h = GetWindow(hDlg, GW_CHILD); h; h = GetWindow(h, GW_HWNDNEXT)) SendMessageW(h, WM_SETFONT, reinterpret_cast(hFont), TRUE); g_transparencyEdit = hEdit; diff --git a/src/modules/editor.cpp b/src/modules/editor.cpp index 967cf57..558ee58 100644 --- a/src/modules/editor.cpp +++ b/src/modules/editor.cpp @@ -123,7 +123,7 @@ void ApplyWordWrap() DWORD start = 0, end = 0; SendMessageW(g_hwndEditor, EM_GETSEL, reinterpret_cast(&start), reinterpret_cast(&end)); DestroyWindow(g_hwndEditor); - DWORD style = WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE | ES_WANTRETURN | ES_NOHIDESEL; + DWORD style = WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN | ES_NOHIDESEL; if (!g_state.wordWrap) style |= WS_HSCROLL | ES_AUTOHSCROLL; g_hwndEditor = CreateWindowExW(0, MSFTEDIT_CLASS, nullptr, style, diff --git a/src/modules/menu.cpp b/src/modules/menu.cpp index fac2ad1..8258d33 100644 --- a/src/modules/menu.cpp +++ b/src/modules/menu.cpp @@ -94,6 +94,14 @@ void UpdateMenuStrings() ModifyMenuW(hViewMenu, 9, MF_BYPOSITION | MF_STRING, IDM_VIEW_TRANSPARENCY, lang.menuTransparency.c_str()); ModifyMenuW(hViewMenu, 10, MF_BYPOSITION | MF_STRING, IDM_VIEW_ALWAYSONTOP, lang.menuAlwaysOnTop.c_str()); + + HMENU hIconMenu = GetSubMenu(hViewMenu, 12); + if (hIconMenu) + { + ModifyMenuW(hViewMenu, 12, MF_BYPOSITION | MF_STRING | MF_POPUP, reinterpret_cast(hIconMenu), lang.menuIcon.c_str()); + ModifyMenuW(hIconMenu, 0, MF_BYPOSITION | MF_STRING, IDM_VIEW_ICON_CHANGE, lang.menuIconChange.c_str()); + ModifyMenuW(hIconMenu, 1, MF_BYPOSITION | MF_STRING, IDM_VIEW_ICON_RESET, lang.menuIconReset.c_str()); + } } HMENU hLangMenu = GetSubMenu(hMenu, 4); @@ -101,6 +109,7 @@ void UpdateMenuStrings() { ModifyMenuW(hLangMenu, 0, MF_BYPOSITION | MF_STRING, IDM_VIEW_LANG_EN, lang.menuLangEnglish.c_str()); ModifyMenuW(hLangMenu, 1, MF_BYPOSITION | MF_STRING, IDM_VIEW_LANG_JA, lang.menuLangJapanese.c_str()); + ModifyMenuW(hLangMenu, 2, MF_BYPOSITION | MF_STRING, IDM_VIEW_LANG_ZH_TW, lang.menuLangTraditionalChinese.c_str()); } HMENU hHelpMenu = GetSubMenu(hMenu, 5); @@ -126,4 +135,5 @@ void UpdateLanguageMenu() LangID currentLang = GetCurrentLanguage(); CheckMenuItem(hLangMenu, IDM_VIEW_LANG_EN, (currentLang == LangID::EN) ? MF_CHECKED : MF_UNCHECKED); CheckMenuItem(hLangMenu, IDM_VIEW_LANG_JA, (currentLang == LangID::JA) ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hLangMenu, IDM_VIEW_LANG_ZH_TW, (currentLang == LangID::ZH_TW) ? MF_CHECKED : MF_UNCHECKED); } diff --git a/src/modules/settings.cpp b/src/modules/settings.cpp index c556aee..8ca60ce 100644 --- a/src/modules/settings.cpp +++ b/src/modules/settings.cpp @@ -25,6 +25,7 @@ #define FONT_ITALIC_VALUE L"FontItalic" #define FONT_UNDERLINE_VALUE L"FontUnderline" #define ALWAYS_ON_TOP_VALUE L"AlwaysOnTop" +#define WORD_WRAP_VALUE L"WordWrap" #define WINDOW_X_VALUE L"WindowX" #define WINDOW_Y_VALUE L"WindowY" #define WINDOW_WIDTH_VALUE L"WindowWidth" @@ -82,6 +83,13 @@ void LoadFontSettings() g_state.alwaysOnTop = (top != 0); } + DWORD wrap = 0; + size = sizeof(wrap); + if (RegQueryValueExW(hKey, WORD_WRAP_VALUE, nullptr, nullptr, reinterpret_cast(&wrap), &size) == ERROR_SUCCESS) + { + g_state.wordWrap = (wrap != 0); + } + RegCloseKey(hKey); } } @@ -120,6 +128,11 @@ void SaveFontSettings() reinterpret_cast(&top), sizeof(top)); + DWORD wrap = g_state.wordWrap ? 1 : 0; + RegSetValueExW(hKey, WORD_WRAP_VALUE, 0, REG_DWORD, + reinterpret_cast(&wrap), + sizeof(wrap)); + RegCloseKey(hKey); } } diff --git a/src/notepad.rc b/src/notepad.rc index f9265f6..1cd7df0 100644 --- a/src/notepad.rc +++ b/src/notepad.rc @@ -90,6 +90,7 @@ BEGIN BEGIN MENUITEM "&English", IDM_VIEW_LANG_EN MENUITEM "&Japanese", IDM_VIEW_LANG_JA + MENUITEM "&Traditional Chinese", IDM_VIEW_LANG_ZH_TW END POPUP "&Help" BEGIN diff --git a/src/resource.h b/src/resource.h index 6fe2f3b..62b1d1a 100644 --- a/src/resource.h +++ b/src/resource.h @@ -81,3 +81,4 @@ #define IDM_VIEW_LANG_EN 40090 #define IDM_VIEW_LANG_JA 40091 +#define IDM_VIEW_LANG_ZH_TW 40092