fix: speed up ShowWindow

This commit is contained in:
Rainer Kottenhoff 2026-02-23 19:24:04 +01:00
parent fb58254482
commit ba67fe2668
3 changed files with 103 additions and 46 deletions

View File

@ -266,34 +266,41 @@ unsigned GetMUILanguageIndexByLocaleName(LPCWSTR pLocaleName) {
//
// CheckAvailableLanguages
//
static bool s_bFullLngScanDone = false;
static bool _CheckLanguageDLL(unsigned lng)
{
if (lng == 0 || lng >= MuiLanguages_CountOf()) {
return (lng == 0); // internal (index 0) is always available
}
if (!IsValidLocaleName(MUI_LanguageDLLs[lng].LocaleName)) {
return false;
}
#if (defined(_DEBUG) || defined(DEBUG)) && !defined(NDEBUG)
WCHAR wchLngLocalName[LOCALE_NAME_MAX_LENGTH + 1];
if (ResolveLocaleName(MUI_LanguageDLLs[lng].LocaleName, wchLngLocalName, COUNTOF(wchLngLocalName))) {
assert(IsSameLocale(MUI_LanguageDLLs[lng].LocaleName, wchLngLocalName) && "Problem with Locale Name of Language!");
}
#endif
WCHAR wchRelPath[SMALL_BUFFER] = { L'\0' };
StringCchPrintf(wchRelPath, COUNTOF(wchRelPath), L"lng/%s/np3lng.dll.mui", MUI_LanguageDLLs[lng].LocaleName);
HPATHL hpth = Path_Allocate(wchRelPath);
Path_AbsoluteFromApp(hpth, false);
bool const bAvail = Path_IsExistingFile(hpth);
Path_Release(hpth);
MUI_LanguageDLLs[lng].bHasDLL = bAvail;
return bAvail;
}
static unsigned _CheckAvailableLanguageDLLs()
{
unsigned count = 1; // internal instance always available
HPATHL hpth = Path_Allocate(NULL);
for (unsigned lng = 1; lng < MuiLanguages_CountOf(); ++lng) {
if (IsValidLocaleName(MUI_LanguageDLLs[lng].LocaleName)) {
#if (defined(_DEBUG) || defined(DEBUG)) && !defined(NDEBUG)
WCHAR wchLngLocalName[LOCALE_NAME_MAX_LENGTH + 1];
if (ResolveLocaleName(MUI_LanguageDLLs[lng].LocaleName, wchLngLocalName, COUNTOF(wchLngLocalName))) {
//~StringCchCopy(MUI_LanguageDLLs[lng].LocaleName, COUNTOF(MUI_LanguageDLLs[lng].LocaleName), wchLngLocalName); // put back resolved name
assert(IsSameLocale(MUI_LanguageDLLs[lng].LocaleName, wchLngLocalName) && "Problem with Locale Name of Language!");
}
#endif
// check for DLL
WCHAR wchRelPath[SMALL_BUFFER] = { L'\0' };
StringCchPrintf(wchRelPath, COUNTOF(wchRelPath), L"lng/%s/np3lng.dll.mui", MUI_LanguageDLLs[lng].LocaleName);
Path_Reset(hpth, wchRelPath);
Path_AbsoluteFromApp(hpth, false);
bool const bAvail = Path_IsExistingFile(hpth);
MUI_LanguageDLLs[lng].bHasDLL = bAvail;
count += bAvail ? 1 : 0;
if (_CheckLanguageDLL(lng)) {
++count;
}
}
Path_Release(hpth);
s_bFullLngScanDone = true;
return count;
}
@ -344,22 +351,28 @@ unsigned LoadLanguageResources(LPCWSTR pLocaleName) {
unsigned const iInternalLngIndex = max_u(0, GetMUILanguageIndexByLocaleName(MUI_BASE_LNG_ID));
// 1st check language resources
Globals.uAvailLngCount = _CheckAvailableLanguageDLLs();
// set the appropriate fallback list
// Check only the preferred locale's DLL on startup (defer full scan to menu population)
unsigned iLngIndex = MuiLanguages_CountOf();
WCHAR tchAvailLngs[2 * (LOCALE_NAME_MAX_LENGTH + 1)] = { L'\0' };
for (unsigned lng = 0; lng < MuiLanguages_CountOf(); ++lng) {
if (StrCmpIW(MUI_LanguageDLLs[lng].LocaleName, pLocaleName) == 0) {
if (MUI_LanguageDLLs[lng].bHasDLL && (lng > 0)) {
StringCchCatW(tchAvailLngs, COUNTOF(tchAvailLngs), MUI_LanguageDLLs[lng].LocaleName);
StringCchCatW(tchAvailLngs, COUNTOF(tchAvailLngs), L";");
}
iLngIndex = lng;
if (lng > 0 && !s_bFullLngScanDone) {
_CheckLanguageDLL(lng); // check only the preferred locale
}
break;
}
}
if (!s_bFullLngScanDone) {
// Set count > 1 so language menu creation is not skipped prematurely
Globals.uAvailLngCount = MuiLanguages_CountOf();
}
// set the appropriate fallback list
WCHAR tchAvailLngs[2 * (LOCALE_NAME_MAX_LENGTH + 1)] = { L'\0' };
if (iLngIndex < MuiLanguages_CountOf() && MUI_LanguageDLLs[iLngIndex].bHasDLL && (iLngIndex > 0)) {
StringCchCatW(tchAvailLngs, COUNTOF(tchAvailLngs), MUI_LanguageDLLs[iLngIndex].LocaleName);
StringCchCatW(tchAvailLngs, COUNTOF(tchAvailLngs), L";");
}
StringCchCatW(tchAvailLngs, COUNTOF(tchAvailLngs), MUI_LanguageDLLs[iInternalLngIndex].LocaleName); // en-US fallback
// NOTES:
@ -473,6 +486,11 @@ static HMENU s_hmenuLanguage = NULL;
bool InsertLanguageMenu(HMENU hMenuBar) {
// Perform full language DLL scan if deferred from startup
if (!s_bFullLngScanDone) {
Globals.uAvailLngCount = _CheckAvailableLanguageDLLs();
}
// check, if we need a language switching menu
if (Globals.uAvailLngCount < 2) {
Settings.PreferredLocale4DateFmt = false;

View File

@ -968,7 +968,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
#endif
_InitGlobals();
InitDarkMode();
// Dark mode init deferred to after LoadSettings() — see below
// Windows Class name
StringCchCopy(s_wchWndClass, COUNTOF(s_wchWndClass), _W(SAPPNAME));
@ -1046,7 +1046,13 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
Scintilla_RegisterClasses(hInstance);
#ifdef D_NP3_WIN10_DARK_MODE
SetDarkMode(IsDarkModeSupported() && IsSettingDarkMode()); // settings
// Init dark mode after settings are loaded — skip UxTheme loading for explicit light mode
if (Settings.WinThemeDarkMode != WINDSPMOD_LIGHT) {
SetDarkMode(true); // probe: load UxTheme.dll, detect OS dark mode support
if (!IsSettingDarkMode()) {
SetDarkMode(false); // OS or user says light mode
}
}
#endif
HRSRC const hRes = FindResourceEx(hInstance, RT_RCDATA, MAKEINTRESOURCE(IDR_STD_DARKMODE_THEME),
@ -1451,7 +1457,14 @@ static BOOL CALLBACK _EnumWndProc(HWND hwnd, LPARAM lParam)
if (StrCmpW(szClassName, s_wchWndClass) == 0) {
UINT const iReuseLock = GetDlgItemInt(hwnd, IDC_REUSELOCK, NULL, FALSE);
WCHAR wchReuseLock[32] = { L'\0' };
DWORD_PTR dwResult = 0;
HWND const hCtl = GetDlgItem(hwnd, IDC_REUSELOCK);
if (!hCtl || SendMessageTimeout(hCtl, WM_GETTEXT, COUNTOF(wchReuseLock),
(LPARAM)wchReuseLock, SMTO_ABORTIFHUNG | SMTO_BLOCK, 500, &dwResult) == 0) {
return TRUE; // skip unresponsive instance
}
UINT const iReuseLock = (UINT)wcstoul(wchReuseLock, NULL, 10);
if ((GetTicks_ms() - iReuseLock) >= REUSEWINDOWLOCKTIMEOUT) {
*(HWND*)lParam = hwnd;
@ -1480,7 +1493,12 @@ static BOOL CALLBACK _EnumWndProc2(HWND hwnd, LPARAM lParam)
if (StrCmpW(szClassName, s_wchWndClass) == 0) {
WCHAR wchFileName[INTERNET_MAX_URL_LENGTH] = { L'\0' };
GetDlgItemText(hwnd, IDC_FILENAME, wchFileName, COUNTOF(wchFileName));
DWORD_PTR dwResult = 0;
HWND const hCtl = GetDlgItem(hwnd, IDC_FILENAME);
if (!hCtl || SendMessageTimeout(hCtl, WM_GETTEXT, COUNTOF(wchFileName),
(LPARAM)wchFileName, SMTO_ABORTIFHUNG | SMTO_BLOCK, 500, &dwResult) == 0) {
return TRUE; // skip unresponsive instance
}
HPATHL hpthFileName = Path_Allocate(wchFileName);
if (Path_StrgComparePath(hpthFileName, s_pthCheckFilePath, Paths.WorkingDirectory, true) == 0) {
@ -1771,17 +1789,39 @@ HWND InitInstance(const HINSTANCE hInstance, int nCmdShow)
SetWindowTransparentMode(hwndMain, true, Settings2.OpacityLevel);
}
// Determine if starting minimized/tray (don't show window early in that case)
bool const bStartMinimized = s_flagStartAsTrayIcon || (nCmdShow == SW_MINIMIZE) || (nCmdShow == SW_SHOWMINIMIZED);
// Show window frame early for faster perceived startup — the user sees
// the window (with initial toolbar from WM_CREATE) while we re-create bars
if (!bStartMinimized) {
if (!Settings.ShowTitlebar) {
SetWindowLong(hwndMain, GWL_STYLE, GetWindowLong(hwndMain, GWL_STYLE) & ~WS_CAPTION);
}
SetWindowPos(hwndMain, Settings.AlwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
ShowWindow(hwndMain, nCmdShow);
UpdateWindow(hwndMain);
}
CreateBars(hwndMain, hInstance);
SetMenu(hwndMain, (Settings.ShowMenubar ? Globals.hMainMenu : NULL));
DrawMenuBar(hwndMain);
// Force layout recalculation after toolbar/statusbar re-creation
// (early ShowWindow already triggered WM_SIZE with old child windows)
if (!bStartMinimized) {
RECT rc;
GetClientRect(hwndMain, &rc);
SendMessage(hwndMain, WM_SIZE, SIZE_RESTORED, MAKELPARAM(rc.right, rc.bottom));
}
Globals.hwndMain = hwndMain; // make main window globaly available
SetWindowAppUserModelID(hwndMain, Settings2.AppUserModelID);
HPATHL hfile_pth = Path_Copy(s_pthArgFilePath);
FileLoadFlags fLoadFlags = FLF_None;
// Source Encoding
Encoding_Forced(s_flagSetEncoding);
@ -1807,15 +1847,13 @@ HWND InitInstance(const HINSTANCE hInstance, int nCmdShow)
ShowWindowAsync(s_hwndEditFrame, SW_SHOWDEFAULT);
ShowWindowAsync(Globals.hwndEdit, SW_SHOWDEFAULT);
//~SnapToWinInfoPos(hwndMain, g_IniWinInfo, SCR_NORMAL, SW_HIDE); ~ instead set all needed properties here:
SetWindowPos(hwndMain, Settings.AlwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
UpdateWindow(hwndMain);
if (!Settings.ShowTitlebar) {
SetWindowLong(hwndMain, GWL_STYLE, GetWindowLong(hwndMain, GWL_STYLE) & ~WS_CAPTION);
}
if (s_flagStartAsTrayIcon || (nCmdShow == SW_MINIMIZE) || (nCmdShow == SW_SHOWMINIMIZED)) {
if (bStartMinimized) {
//~SnapToWinInfoPos(hwndMain, g_IniWinInfo, SCR_NORMAL, SW_HIDE);
SetWindowPos(hwndMain, Settings.AlwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
if (!Settings.ShowTitlebar) {
SetWindowLong(hwndMain, GWL_STYLE, GetWindowLong(hwndMain, GWL_STYLE) & ~WS_CAPTION);
}
if (Settings.MinimizeToTray) {
MinimizeWndToTray(hwndMain);
}
@ -1824,7 +1862,8 @@ HWND InitInstance(const HINSTANCE hInstance, int nCmdShow)
}
}
else {
ShowWindow(hwndMain, nCmdShow);
// Window was already shown above; ensure children are painted
UpdateWindow(hwndMain);
}
bool bOpened = false;

View File

@ -1123,7 +1123,7 @@ void PTHAPI Path_ExpandEnvStrings(HPATHL hpth_in_out)
StrgReplace(hstr_io, PATH_CSIDL_FAVORITES, PathGet(hfld_pth));
Path_Release(hfld_pth);
}
ExpandEnvironmentStrgs(hstr_io, true);
}
// ----------------------------------------------------------------------------