From fa00ff72a05fb2c0147f9dc314921cd641889e19 Mon Sep 17 00:00:00 2001 From: Xavier Roche Date: Mon, 24 Aug 2026 21:34:49 +0200 Subject: [PATCH 1/3] Read the option tab titles when the sheet opens, not when it is built The option pages are constructed with the main frame, which on a first run happens before the language dialog, so LANG_T(-1) is still 0 and the PSP_USETITLE branch never runs. Every other string on a page is set at display time, so the sheet came up with translated content under English tabs, and only a restart fixed it. CMainTab::DoModal() now re-reads the eleven titles first, which covers all three call sites. SetWindowText() copies into the page's own m_strCaption, so the hash-table string a language change frees is not stashed (#56). Signed-off-by: Xavier Roche Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: Xavier Roche --- WinHTTrack/MainTab.cpp | 24 ++++++++++++++++++++++++ WinHTTrack/MainTab.h | 4 ++++ 2 files changed, 28 insertions(+) diff --git a/WinHTTrack/MainTab.cpp b/WinHTTrack/MainTab.cpp index 686b1fc..22c9dc7 100755 --- a/WinHTTrack/MainTab.cpp +++ b/WinHTTrack/MainTab.cpp @@ -132,6 +132,30 @@ void CMainTab::AddControlPages() AddPage(&m_option3); /* Expert */ } +/* The pages are built with the main frame, which on a first run happens before the + language is picked, so their titles would keep the .rc caption while every other + string on the page is set at display time. Re-read them each time the sheet opens. */ +void CMainTab::SetLangTitles(void) +{ + m_option10.SetWindowText(LANG(LANG_IOPT10)); + m_option7.SetWindowText(LANG(LANG_IOPT7)); + m_option5.SetWindowText(LANG(LANG_IOPT5)); + m_option4.SetWindowText(LANG(LANG_IOPT4)); + m_option1.SetWindowText(LANG(LANG_IOPT1)); + m_option2.SetWindowText(LANG(LANG_IOPT2)); + m_option8.SetWindowText(LANG(LANG_IOPT8)); + m_option11.SetWindowText(LANG(LANG_IOPT11)); + m_option6.SetWindowText(LANG(LANG_IOPT6)); + m_option9.SetWindowText(LANG(LANG_IOPT9)); + m_option3.SetWindowText(LANG(LANG_IOPT3)); +} + +INT_PTR CMainTab::DoModal() +{ + SetLangTitles(); + return CPropertySheet::DoModal(); +} + void CMainTab::DefineDefaultProxy() { while(GetPageCount()>0) diff --git a/WinHTTrack/MainTab.h b/WinHTTrack/MainTab.h index 6681f0b..b65e693 100644 --- a/WinHTTrack/MainTab.h +++ b/WinHTTrack/MainTab.h @@ -54,8 +54,12 @@ class CMainTab : public CPropertySheet CMainTab(UINT nIDCaption, CWnd* pParentWnd = NULL, UINT iSelectPage = 0); CMainTab(LPCTSTR pszCaption, CWnd* pParentWnd = NULL, UINT iSelectPage = 0); +public: + virtual INT_PTR DoModal(); + protected: void AddControlPages(void); + void SetLangTitles(void); // Attributes public: From 958a4274c5c04a3a32bf75baf5ffde24e4c72648 Mon Sep 17 00:00:00 2001 From: Xavier Roche Date: Mon, 24 Aug 2026 21:56:06 +0200 Subject: [PATCH 2/3] Relabel the tabs from the sheet, not from the pages before it exists Setting each page's caption ahead of CPropertySheet::DoModal() stopped the sheet from opening at all: a French walk reached the main window, clicked Define options, and no sheet appeared. CPropertyPage::SetWindowText() is not usable on a page whose window does not exist yet. The tab control owns the text once the sheet is up, so OnInitDialog() sets it there instead. Pages are matched with GetPageIndex() rather than by tab order, so DefineDefaultProxy(), which leaves all but one page out, still works. Signed-off-by: Xavier Roche Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: Xavier Roche --- WinHTTrack/MainTab.cpp | 46 +++++++++++++++++++++++++----------------- WinHTTrack/MainTab.h | 3 --- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/WinHTTrack/MainTab.cpp b/WinHTTrack/MainTab.cpp index 22c9dc7..8b25fe3 100755 --- a/WinHTTrack/MainTab.cpp +++ b/WinHTTrack/MainTab.cpp @@ -133,27 +133,33 @@ void CMainTab::AddControlPages() } /* The pages are built with the main frame, which on a first run happens before the - language is picked, so their titles would keep the .rc caption while every other - string on the page is set at display time. Re-read them each time the sheet opens. */ + language is known, so their titles keep the .rc caption while every other string on a + page is set at display time. The tab control owns the text once the sheet exists. */ void CMainTab::SetLangTitles(void) { - m_option10.SetWindowText(LANG(LANG_IOPT10)); - m_option7.SetWindowText(LANG(LANG_IOPT7)); - m_option5.SetWindowText(LANG(LANG_IOPT5)); - m_option4.SetWindowText(LANG(LANG_IOPT4)); - m_option1.SetWindowText(LANG(LANG_IOPT1)); - m_option2.SetWindowText(LANG(LANG_IOPT2)); - m_option8.SetWindowText(LANG(LANG_IOPT8)); - m_option11.SetWindowText(LANG(LANG_IOPT11)); - m_option6.SetWindowText(LANG(LANG_IOPT6)); - m_option9.SetWindowText(LANG(LANG_IOPT9)); - m_option3.SetWindowText(LANG(LANG_IOPT3)); -} - -INT_PTR CMainTab::DoModal() -{ - SetLangTitles(); - return CPropertySheet::DoModal(); + const struct { CPropertyPage* page; const char* title; } named[] = { + { &m_option1, LANG_IOPT1 }, { &m_option2, LANG_IOPT2 }, + { &m_option3, LANG_IOPT3 }, { &m_option4, LANG_IOPT4 }, + { &m_option5, LANG_IOPT5 }, { &m_option6, LANG_IOPT6 }, + { &m_option7, LANG_IOPT7 }, { &m_option8, LANG_IOPT8 }, + { &m_option9, LANG_IOPT9 }, { &m_option10, LANG_IOPT10 }, + { &m_option11, LANG_IOPT11 } + }; + CTabCtrl* const tabs = GetTabControl(); + + if (tabs == NULL) + return; + for(int i = 0 ; i < (int) (sizeof(named)/sizeof(named[0])) ; i++) { + /* A missing key reads as empty, and DefineDefaultProxy() leaves most pages out. */ + const int at = GetPageIndex(named[i].page); + if (at >= 0 && named[i].title != NULL && named[i].title[0] != '\0') { + TCITEM item; + memset(&item, 0, sizeof(item)); + item.mask = TCIF_TEXT; + item.pszText = (LPSTR) named[i].title; + tabs->SetItem(at, &item); + } + } } void CMainTab::DefineDefaultProxy() @@ -222,6 +228,8 @@ BOOL CMainTab::OnInitDialog() //SetActivePage(GetPageCount()-1); SetActivePage(0); + SetLangTitles(); + /* Fallback for a sheet SheetPreCreate could not reach, and a no-op once it did: the thicker border comes out of the client area, so give that back. */ CRect before, after, frame; diff --git a/WinHTTrack/MainTab.h b/WinHTTrack/MainTab.h index b65e693..f308a5a 100644 --- a/WinHTTrack/MainTab.h +++ b/WinHTTrack/MainTab.h @@ -54,9 +54,6 @@ class CMainTab : public CPropertySheet CMainTab(UINT nIDCaption, CWnd* pParentWnd = NULL, UINT iSelectPage = 0); CMainTab(LPCTSTR pszCaption, CWnd* pParentWnd = NULL, UINT iSelectPage = 0); -public: - virtual INT_PTR DoModal(); - protected: void AddControlPages(void); void SetLangTitles(void); From d708edc3972f6c5df77c32beb35aa602e928a0f6 Mon Sep 17 00:00:00 2001 From: Xavier Roche Date: Mon, 24 Aug 2026 22:29:25 +0200 Subject: [PATCH 3/3] Set the titles before the sheet is built, or a row of tabs is lost Relabelling the tab control from OnInitDialog came too late. comctl32 sizes the strip from the captions in effect when the sheet is created, which on a first run are the English .rc ones, so longer labels wrapped into a row the sheet had no room for. A Romanian walk showed six tabs of eleven, with five pages unreachable: worse than the English titles it replaced. Each page now exposes SetLangTitle(), which is the block its constructor already ran, and CMainTab::DoModal() calls all eleven before the base creates the sheet. The constructor calls the same method, so the two copies that used to drift are one. English still keeps its .rc caption, as before: the catalog would otherwise retitle one tab MIME Types over MIME types for every English user. Signed-off-by: Xavier Roche Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: Xavier Roche --- WinHTTrack/MainTab.cpp | 38 +++++++++----------------------------- WinHTTrack/MainTab.h | 4 +++- WinHTTrack/OptionTab1.cpp | 16 ++++++++++++---- WinHTTrack/OptionTab1.h | 1 + WinHTTrack/OptionTab10.cpp | 16 ++++++++++++---- WinHTTrack/OptionTab10.h | 1 + WinHTTrack/OptionTab11.cpp | 16 ++++++++++++---- WinHTTrack/OptionTab11.h | 1 + WinHTTrack/OptionTab2.cpp | 16 ++++++++++++---- WinHTTrack/OptionTab2.h | 1 + WinHTTrack/OptionTab3.cpp | 16 ++++++++++++---- WinHTTrack/OptionTab3.h | 1 + WinHTTrack/OptionTab4.cpp | 16 ++++++++++++---- WinHTTrack/OptionTab4.h | 1 + WinHTTrack/OptionTab5.cpp | 16 ++++++++++++---- WinHTTrack/OptionTab5.h | 1 + WinHTTrack/OptionTab6.cpp | 16 ++++++++++++---- WinHTTrack/OptionTab6.h | 1 + WinHTTrack/OptionTab7.cpp | 16 ++++++++++++---- WinHTTrack/OptionTab7.h | 1 + WinHTTrack/OptionTab8.cpp | 16 ++++++++++++---- WinHTTrack/OptionTab8.h | 1 + WinHTTrack/OptionTab9.cpp | 16 ++++++++++++---- WinHTTrack/OptionTab9.h | 1 + tools/screenshot-walk.py | 4 ++-- 25 files changed, 157 insertions(+), 76 deletions(-) diff --git a/WinHTTrack/MainTab.cpp b/WinHTTrack/MainTab.cpp index 8b25fe3..063dc0d 100755 --- a/WinHTTrack/MainTab.cpp +++ b/WinHTTrack/MainTab.cpp @@ -132,34 +132,16 @@ void CMainTab::AddControlPages() AddPage(&m_option3); /* Expert */ } -/* The pages are built with the main frame, which on a first run happens before the - language is known, so their titles keep the .rc caption while every other string on a - page is set at display time. The tab control owns the text once the sheet exists. */ -void CMainTab::SetLangTitles(void) +/* The pages are built before a first run knows its language, so each one re-reads its + title here. It must happen before the base creates the sheet: comctl32 sizes the tab + strip from the captions in effect then, and relabelling afterwards loses a row. */ +INT_PTR CMainTab::DoModal() { - const struct { CPropertyPage* page; const char* title; } named[] = { - { &m_option1, LANG_IOPT1 }, { &m_option2, LANG_IOPT2 }, - { &m_option3, LANG_IOPT3 }, { &m_option4, LANG_IOPT4 }, - { &m_option5, LANG_IOPT5 }, { &m_option6, LANG_IOPT6 }, - { &m_option7, LANG_IOPT7 }, { &m_option8, LANG_IOPT8 }, - { &m_option9, LANG_IOPT9 }, { &m_option10, LANG_IOPT10 }, - { &m_option11, LANG_IOPT11 } - }; - CTabCtrl* const tabs = GetTabControl(); - - if (tabs == NULL) - return; - for(int i = 0 ; i < (int) (sizeof(named)/sizeof(named[0])) ; i++) { - /* A missing key reads as empty, and DefineDefaultProxy() leaves most pages out. */ - const int at = GetPageIndex(named[i].page); - if (at >= 0 && named[i].title != NULL && named[i].title[0] != '\0') { - TCITEM item; - memset(&item, 0, sizeof(item)); - item.mask = TCIF_TEXT; - item.pszText = (LPSTR) named[i].title; - tabs->SetItem(at, &item); - } - } + m_option1.SetLangTitle(); m_option2.SetLangTitle(); m_option3.SetLangTitle(); + m_option4.SetLangTitle(); m_option5.SetLangTitle(); m_option6.SetLangTitle(); + m_option7.SetLangTitle(); m_option8.SetLangTitle(); m_option9.SetLangTitle(); + m_option10.SetLangTitle(); m_option11.SetLangTitle(); + return CPropertySheet::DoModal(); } void CMainTab::DefineDefaultProxy() @@ -228,8 +210,6 @@ BOOL CMainTab::OnInitDialog() //SetActivePage(GetPageCount()-1); SetActivePage(0); - SetLangTitles(); - /* Fallback for a sheet SheetPreCreate could not reach, and a no-op once it did: the thicker border comes out of the client area, so give that back. */ CRect before, after, frame; diff --git a/WinHTTrack/MainTab.h b/WinHTTrack/MainTab.h index f308a5a..81909db 100644 --- a/WinHTTrack/MainTab.h +++ b/WinHTTrack/MainTab.h @@ -54,9 +54,11 @@ class CMainTab : public CPropertySheet CMainTab(UINT nIDCaption, CWnd* pParentWnd = NULL, UINT iSelectPage = 0); CMainTab(LPCTSTR pszCaption, CWnd* pParentWnd = NULL, UINT iSelectPage = 0); +public: + virtual INT_PTR DoModal(); + protected: void AddControlPages(void); - void SetLangTitles(void); // Attributes public: diff --git a/WinHTTrack/OptionTab1.cpp b/WinHTTrack/OptionTab1.cpp index b823e33..afa3257 100755 --- a/WinHTTrack/OptionTab1.cpp +++ b/WinHTTrack/OptionTab1.cpp @@ -42,14 +42,22 @@ static char THIS_FILE[] = __FILE__; IMPLEMENT_DYNCREATE(COptionTab1, CPropertyPage) -COptionTab1::COptionTab1() : CPropertyPage(COptionTab1::IDD) +/* Called again before each show: the page is built before a first run knows its + language. The copy is page-owned, since a language change frees the hash string. */ +void COptionTab1::SetLangTitle(void) { - // Patcher titre - if (LANG_T(-1)) { // Patcher en français - m_strCaption = LANG(LANG_IOPT1); // page-owned copy; the hash-table string is freed on a language change + const char *const title = LANG(LANG_IOPT1); + /* English keeps the .rc caption, as it did when this ran only from the constructor. */ + if (LANG_T(-1) != 0 && title[0] != '\0') { + m_strCaption = title; m_psp.pszTitle = m_strCaption; m_psp.dwFlags|=PSP_USETITLE; } +} + +COptionTab1::COptionTab1() : CPropertyPage(COptionTab1::IDD) +{ + SetLangTitle(); m_psp.dwFlags|=PSP_HASHELP; // //{{AFX_DATA_INIT(COptionTab1) diff --git a/WinHTTrack/OptionTab1.h b/WinHTTrack/OptionTab1.h index 12ccea5..343859e 100644 --- a/WinHTTrack/OptionTab1.h +++ b/WinHTTrack/OptionTab1.h @@ -42,6 +42,7 @@ class COptionTab1 : public CPropertyPage // Construction public: + void SetLangTitle(void); COptionTab1(); ~COptionTab1(); const char* GetTip(int id); diff --git a/WinHTTrack/OptionTab10.cpp b/WinHTTrack/OptionTab10.cpp index a680275..d9c5859 100755 --- a/WinHTTrack/OptionTab10.cpp +++ b/WinHTTrack/OptionTab10.cpp @@ -56,14 +56,22 @@ extern "C" { IMPLEMENT_DYNCREATE(COptionTab10, CPropertyPage) -COptionTab10::COptionTab10() : CPropertyPage(COptionTab10::IDD) +/* Called again before each show: the page is built before a first run knows its + language. The copy is page-owned, since a language change frees the hash string. */ +void COptionTab10::SetLangTitle(void) { - // Patcher titre - if (LANG_T(-1)) { // Patcher en français - m_strCaption = LANG(LANG_IOPT10); // page-owned copy; the hash-table string is freed on a language change + const char *const title = LANG(LANG_IOPT10); + /* English keeps the .rc caption, as it did when this ran only from the constructor. */ + if (LANG_T(-1) != 0 && title[0] != '\0') { + m_strCaption = title; m_psp.pszTitle = m_strCaption; m_psp.dwFlags|=PSP_USETITLE; } +} + +COptionTab10::COptionTab10() : CPropertyPage(COptionTab10::IDD) +{ + SetLangTitle(); m_psp.dwFlags|=PSP_HASHELP; // //{{AFX_DATA_INIT(COptionTab10) diff --git a/WinHTTrack/OptionTab10.h b/WinHTTrack/OptionTab10.h index 0907cbf..46daa37 100644 --- a/WinHTTrack/OptionTab10.h +++ b/WinHTTrack/OptionTab10.h @@ -42,6 +42,7 @@ class COptionTab10 : public CPropertyPage // Construction public: + void SetLangTitle(void); COptionTab10(); ~COptionTab10(); const char* GetTip(int id); diff --git a/WinHTTrack/OptionTab11.cpp b/WinHTTrack/OptionTab11.cpp index 8a35cef..2cf6ab3 100755 --- a/WinHTTrack/OptionTab11.cpp +++ b/WinHTTrack/OptionTab11.cpp @@ -42,14 +42,22 @@ static char THIS_FILE[] = __FILE__; IMPLEMENT_DYNCREATE(COptionTab11, CPropertyPage) -COptionTab11::COptionTab11() : CPropertyPage(COptionTab11::IDD) +/* Called again before each show: the page is built before a first run knows its + language. The copy is page-owned, since a language change frees the hash string. */ +void COptionTab11::SetLangTitle(void) { - // Patcher titre - if (LANG_T(-1)) { // Patcher en français - m_strCaption = LANG(LANG_IOPT11); // page-owned copy; the hash-table string is freed on a language change + const char *const title = LANG(LANG_IOPT11); + /* English keeps the .rc caption, as it did when this ran only from the constructor. */ + if (LANG_T(-1) != 0 && title[0] != '\0') { + m_strCaption = title; m_psp.pszTitle = m_strCaption; m_psp.dwFlags|=PSP_USETITLE; } +} + +COptionTab11::COptionTab11() : CPropertyPage(COptionTab11::IDD) +{ + SetLangTitle(); m_psp.dwFlags|=PSP_HASHELP; //{{AFX_DATA_INIT(COptionTab11) m_ext1 = _T(""); diff --git a/WinHTTrack/OptionTab11.h b/WinHTTrack/OptionTab11.h index 8454fd9..b8fd3d6 100644 --- a/WinHTTrack/OptionTab11.h +++ b/WinHTTrack/OptionTab11.h @@ -44,6 +44,7 @@ class COptionTab11 : public CPropertyPage // Construction public: + void SetLangTitle(void); COptionTab11(); ~COptionTab11(); const char* GetTip(int id); diff --git a/WinHTTrack/OptionTab2.cpp b/WinHTTrack/OptionTab2.cpp index 0892615..b772095 100755 --- a/WinHTTrack/OptionTab2.cpp +++ b/WinHTTrack/OptionTab2.cpp @@ -42,14 +42,22 @@ static char THIS_FILE[] = __FILE__; IMPLEMENT_DYNCREATE(COptionTab2, CPropertyPage) -COptionTab2::COptionTab2() : CPropertyPage(COptionTab2::IDD) +/* Called again before each show: the page is built before a first run knows its + language. The copy is page-owned, since a language change frees the hash string. */ +void COptionTab2::SetLangTitle(void) { - // Patcher titre - if (LANG_T(-1)) { // Patcher en français - m_strCaption = LANG(LANG_IOPT2); // page-owned copy; the hash-table string is freed on a language change + const char *const title = LANG(LANG_IOPT2); + /* English keeps the .rc caption, as it did when this ran only from the constructor. */ + if (LANG_T(-1) != 0 && title[0] != '\0') { + m_strCaption = title; m_psp.pszTitle = m_strCaption; m_psp.dwFlags|=PSP_USETITLE; } +} + +COptionTab2::COptionTab2() : CPropertyPage(COptionTab2::IDD) +{ + SetLangTitle(); m_psp.dwFlags|=PSP_HASHELP; // //{{AFX_DATA_INIT(COptionTab2) diff --git a/WinHTTrack/OptionTab2.h b/WinHTTrack/OptionTab2.h index 49149c2..d018673 100644 --- a/WinHTTrack/OptionTab2.h +++ b/WinHTTrack/OptionTab2.h @@ -47,6 +47,7 @@ class COptionTab2 : public CPropertyPage // Construction public: + void SetLangTitle(void); COptionTab2(); ~COptionTab2(); CBuildOptions Bopt; diff --git a/WinHTTrack/OptionTab3.cpp b/WinHTTrack/OptionTab3.cpp index e9d9ae4..daeab56 100755 --- a/WinHTTrack/OptionTab3.cpp +++ b/WinHTTrack/OptionTab3.cpp @@ -42,14 +42,22 @@ static char THIS_FILE[] = __FILE__; IMPLEMENT_DYNCREATE(COptionTab3, CPropertyPage) -COptionTab3::COptionTab3() : CPropertyPage(COptionTab3::IDD) +/* Called again before each show: the page is built before a first run knows its + language. The copy is page-owned, since a language change frees the hash string. */ +void COptionTab3::SetLangTitle(void) { - // Patcher titre - if (LANG_T(-1)) { // Patcher en français - m_strCaption = LANG(LANG_IOPT3); // page-owned copy; the hash-table string is freed on a language change + const char *const title = LANG(LANG_IOPT3); + /* English keeps the .rc caption, as it did when this ran only from the constructor. */ + if (LANG_T(-1) != 0 && title[0] != '\0') { + m_strCaption = title; m_psp.pszTitle = m_strCaption; m_psp.dwFlags|=PSP_USETITLE; } +} + +COptionTab3::COptionTab3() : CPropertyPage(COptionTab3::IDD) +{ + SetLangTitle(); m_psp.dwFlags|=PSP_HASHELP; // //{{AFX_DATA_INIT(COptionTab3) diff --git a/WinHTTrack/OptionTab3.h b/WinHTTrack/OptionTab3.h index 3be8967..5d03bc3 100644 --- a/WinHTTrack/OptionTab3.h +++ b/WinHTTrack/OptionTab3.h @@ -44,6 +44,7 @@ class COptionTab3 : public CPropertyPage // Construction public: + void SetLangTitle(void); COptionTab3(); ~COptionTab3(); int modify; diff --git a/WinHTTrack/OptionTab4.cpp b/WinHTTrack/OptionTab4.cpp index f709b94..5a4a654 100755 --- a/WinHTTrack/OptionTab4.cpp +++ b/WinHTTrack/OptionTab4.cpp @@ -42,14 +42,22 @@ static char THIS_FILE[] = __FILE__; IMPLEMENT_DYNCREATE(COptionTab4, CPropertyPage) -COptionTab4::COptionTab4() : CPropertyPage(COptionTab4::IDD) +/* Called again before each show: the page is built before a first run knows its + language. The copy is page-owned, since a language change frees the hash string. */ +void COptionTab4::SetLangTitle(void) { - // Patcher titre - if (LANG_T(-1)) { // Patcher en français - m_strCaption = LANG(LANG_IOPT4); // page-owned copy; the hash-table string is freed on a language change + const char *const title = LANG(LANG_IOPT4); + /* English keeps the .rc caption, as it did when this ran only from the constructor. */ + if (LANG_T(-1) != 0 && title[0] != '\0') { + m_strCaption = title; m_psp.pszTitle = m_strCaption; m_psp.dwFlags|=PSP_USETITLE; } +} + +COptionTab4::COptionTab4() : CPropertyPage(COptionTab4::IDD) +{ + SetLangTitle(); m_psp.dwFlags|=PSP_HASHELP; // //{{AFX_DATA_INIT(COptionTab4) diff --git a/WinHTTrack/OptionTab4.h b/WinHTTrack/OptionTab4.h index 28cef5e..412d28e 100644 --- a/WinHTTrack/OptionTab4.h +++ b/WinHTTrack/OptionTab4.h @@ -42,6 +42,7 @@ class COptionTab4 : public CPropertyPage // Construction public: + void SetLangTitle(void); COptionTab4(); ~COptionTab4(); const char* GetTip(int id); diff --git a/WinHTTrack/OptionTab5.cpp b/WinHTTrack/OptionTab5.cpp index 3c4d124..b8371ed 100755 --- a/WinHTTrack/OptionTab5.cpp +++ b/WinHTTrack/OptionTab5.cpp @@ -42,14 +42,22 @@ static char THIS_FILE[] = __FILE__; IMPLEMENT_DYNCREATE(COptionTab5, CPropertyPage) -COptionTab5::COptionTab5() : CPropertyPage(COptionTab5::IDD) +/* Called again before each show: the page is built before a first run knows its + language. The copy is page-owned, since a language change frees the hash string. */ +void COptionTab5::SetLangTitle(void) { - // Patcher titre - if (LANG_T(-1)) { // Patcher en français - m_strCaption = LANG(LANG_IOPT5); // page-owned copy; the hash-table string is freed on a language change + const char *const title = LANG(LANG_IOPT5); + /* English keeps the .rc caption, as it did when this ran only from the constructor. */ + if (LANG_T(-1) != 0 && title[0] != '\0') { + m_strCaption = title; m_psp.pszTitle = m_strCaption; m_psp.dwFlags|=PSP_USETITLE; } +} + +COptionTab5::COptionTab5() : CPropertyPage(COptionTab5::IDD) +{ + SetLangTitle(); m_psp.dwFlags|=PSP_HASHELP; // //{{AFX_DATA_INIT(COptionTab5) diff --git a/WinHTTrack/OptionTab5.h b/WinHTTrack/OptionTab5.h index 74d0f3d..33017a6 100644 --- a/WinHTTrack/OptionTab5.h +++ b/WinHTTrack/OptionTab5.h @@ -42,6 +42,7 @@ class COptionTab5 : public CPropertyPage // Construction public: + void SetLangTitle(void); COptionTab5(); ~COptionTab5(); const char* GetTip(int id); diff --git a/WinHTTrack/OptionTab6.cpp b/WinHTTrack/OptionTab6.cpp index d19de05..1961a17 100755 --- a/WinHTTrack/OptionTab6.cpp +++ b/WinHTTrack/OptionTab6.cpp @@ -54,14 +54,22 @@ extern const char *const FooterPresets[] = { IMPLEMENT_DYNCREATE(COptionTab6, CPropertyPage) -COptionTab6::COptionTab6() : CPropertyPage(COptionTab6::IDD) +/* Called again before each show: the page is built before a first run knows its + language. The copy is page-owned, since a language change frees the hash string. */ +void COptionTab6::SetLangTitle(void) { - // Patcher titre - if (LANG_T(-1)) { // Patcher en français - m_strCaption = LANG(LANG_IOPT6); // page-owned copy; the hash-table string is freed on a language change + const char *const title = LANG(LANG_IOPT6); + /* English keeps the .rc caption, as it did when this ran only from the constructor. */ + if (LANG_T(-1) != 0 && title[0] != '\0') { + m_strCaption = title; m_psp.pszTitle = m_strCaption; m_psp.dwFlags|=PSP_USETITLE; } +} + +COptionTab6::COptionTab6() : CPropertyPage(COptionTab6::IDD) +{ + SetLangTitle(); m_psp.dwFlags|=PSP_HASHELP; // //{{AFX_DATA_INIT(COptionTab6) diff --git a/WinHTTrack/OptionTab6.h b/WinHTTrack/OptionTab6.h index bf0e9aa..38a1c12 100644 --- a/WinHTTrack/OptionTab6.h +++ b/WinHTTrack/OptionTab6.h @@ -48,6 +48,7 @@ class COptionTab6 : public CPropertyPage // Construction public: + void SetLangTitle(void); COptionTab6(); ~COptionTab6(); const char* GetTip(int id); diff --git a/WinHTTrack/OptionTab7.cpp b/WinHTTrack/OptionTab7.cpp index d6bc242..8b8ce57 100755 --- a/WinHTTrack/OptionTab7.cpp +++ b/WinHTTrack/OptionTab7.cpp @@ -50,14 +50,22 @@ static char THIS_FILE[] = __FILE__; IMPLEMENT_DYNCREATE(COptionTab7, CPropertyPage) -COptionTab7::COptionTab7() : CPropertyPage(COptionTab7::IDD) +/* Called again before each show: the page is built before a first run knows its + language. The copy is page-owned, since a language change frees the hash string. */ +void COptionTab7::SetLangTitle(void) { - // Patcher titre - if (LANG_T(-1)) { // Patcher en français - m_strCaption = LANG(LANG_IOPT7); // page-owned copy; the hash-table string is freed on a language change + const char *const title = LANG(LANG_IOPT7); + /* English keeps the .rc caption, as it did when this ran only from the constructor. */ + if (LANG_T(-1) != 0 && title[0] != '\0') { + m_strCaption = title; m_psp.pszTitle = m_strCaption; m_psp.dwFlags|=PSP_USETITLE; } +} + +COptionTab7::COptionTab7() : CPropertyPage(COptionTab7::IDD) +{ + SetLangTitle(); m_psp.dwFlags|=PSP_HASHELP; // //{{AFX_DATA_INIT(COptionTab7) diff --git a/WinHTTrack/OptionTab7.h b/WinHTTrack/OptionTab7.h index 0f3cbab..3588878 100644 --- a/WinHTTrack/OptionTab7.h +++ b/WinHTTrack/OptionTab7.h @@ -44,6 +44,7 @@ class COptionTab7 : public CPropertyPage // Construction public: + void SetLangTitle(void); COptionTab7(); ~COptionTab7(); const char* GetTip(int id); diff --git a/WinHTTrack/OptionTab8.cpp b/WinHTTrack/OptionTab8.cpp index ae4547e..40889ce 100755 --- a/WinHTTrack/OptionTab8.cpp +++ b/WinHTTrack/OptionTab8.cpp @@ -42,14 +42,22 @@ static char THIS_FILE[] = __FILE__; IMPLEMENT_DYNCREATE(COptionTab8, CPropertyPage) -COptionTab8::COptionTab8() : CPropertyPage(COptionTab8::IDD) +/* Called again before each show: the page is built before a first run knows its + language. The copy is page-owned, since a language change frees the hash string. */ +void COptionTab8::SetLangTitle(void) { - // Patcher titre - if (LANG_T(-1)) { // Patcher en français - m_strCaption = LANG(LANG_IOPT8); // page-owned copy; the hash-table string is freed on a language change + const char *const title = LANG(LANG_IOPT8); + /* English keeps the .rc caption, as it did when this ran only from the constructor. */ + if (LANG_T(-1) != 0 && title[0] != '\0') { + m_strCaption = title; m_psp.pszTitle = m_strCaption; m_psp.dwFlags|=PSP_USETITLE; } +} + +COptionTab8::COptionTab8() : CPropertyPage(COptionTab8::IDD) +{ + SetLangTitle(); m_psp.dwFlags|=PSP_HASHELP; // //{{AFX_DATA_INIT(COptionTab8) diff --git a/WinHTTrack/OptionTab8.h b/WinHTTrack/OptionTab8.h index 877378a..ae8de75 100644 --- a/WinHTTrack/OptionTab8.h +++ b/WinHTTrack/OptionTab8.h @@ -44,6 +44,7 @@ class COptionTab8 : public CPropertyPage // Construction public: + void SetLangTitle(void); COptionTab8(); ~COptionTab8(); const char* GetTip(int id); diff --git a/WinHTTrack/OptionTab9.cpp b/WinHTTrack/OptionTab9.cpp index f5f3d5d..ccf3c49 100755 --- a/WinHTTrack/OptionTab9.cpp +++ b/WinHTTrack/OptionTab9.cpp @@ -42,14 +42,22 @@ static char THIS_FILE[] = __FILE__; IMPLEMENT_DYNCREATE(COptionTab9, CPropertyPage) -COptionTab9::COptionTab9() : CPropertyPage(COptionTab9::IDD) +/* Called again before each show: the page is built before a first run knows its + language. The copy is page-owned, since a language change frees the hash string. */ +void COptionTab9::SetLangTitle(void) { - // Patcher titre - if (LANG_T(-1)) { // Patcher en français - m_strCaption = LANG(LANG_IOPT9); // page-owned copy; the hash-table string is freed on a language change + const char *const title = LANG(LANG_IOPT9); + /* English keeps the .rc caption, as it did when this ran only from the constructor. */ + if (LANG_T(-1) != 0 && title[0] != '\0') { + m_strCaption = title; m_psp.pszTitle = m_strCaption; m_psp.dwFlags|=PSP_USETITLE; } +} + +COptionTab9::COptionTab9() : CPropertyPage(COptionTab9::IDD) +{ + SetLangTitle(); m_psp.dwFlags|=PSP_HASHELP; // //{{AFX_DATA_INIT(COptionTab9) diff --git a/WinHTTrack/OptionTab9.h b/WinHTTrack/OptionTab9.h index cbf0954..a79ef1f 100644 --- a/WinHTTrack/OptionTab9.h +++ b/WinHTTrack/OptionTab9.h @@ -42,6 +42,7 @@ class COptionTab9 : public CPropertyPage // Construction public: + void SetLangTitle(void); COptionTab9(); ~COptionTab9(); const char* GetTip(int id); diff --git a/tools/screenshot-walk.py b/tools/screenshot-walk.py index 46173f1..e8bf5e8 100644 --- a/tools/screenshot-walk.py +++ b/tools/screenshot-walk.py @@ -327,8 +327,8 @@ def options(main, pid, ids, shots, connections=8, rate=2_000_000): sheet, tabs, captions = open_options(main, pid, ids) count = win32gui.SendMessage(tabs, TCM_GETITEMCOUNT, 0, 0) print(f" options sheet {sheet:#x}: {count} tabs") - # Keyed by a control each page owns: tab labels come from the .rc and stay - # English, but a display string would be the wrong key regardless. + # Keyed by a control each page owns, because the tab labels are translated, and a + # display string would be the wrong key regardless. wanted = {"IDC_maxrate": rate, "IDC_connexion": connections} owns = {} for i in range(count):