Merge pull request #5831 from RaiKoHoff/dev_master

Commits on May 6, 2026      feat: modern print dialog, fixing minor issues
This commit is contained in:
Rainer Kottenhoff 2026-05-07 08:14:57 +02:00 committed by GitHub
commit 409fa45cae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 50 additions and 103 deletions

View File

@ -1879,6 +1879,9 @@ static VOID CALLBACK _DeferMinimizeTimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEv
if (IsAsyncKeyDown(VK_CONTROL)) {
return; // user held Ctrl during the deferral window — keep window visible
}
if (!SciCall_CanPaste()) {
return; // clipboard has nothing pasteable — keep window visible so the user can act
}
_StartupMinimizeMainWnd(hwnd);
}
@ -4235,15 +4238,18 @@ LRESULT MsgInitMenu(HWND hwnd, WPARAM wParam, LPARAM lParam)
int i = 0;
if (Encoding_IsUNICODE_REVERSE(Encoding_GetCurrent())) {
i = IDM_ENCODING_UNICODEREV;
} else if (Encoding_IsUNICODE(Encoding_GetCurrent())) {
i = IDM_ENCODING_UNICODE;
} else if (Encoding_IsUTF8_SIGN(Encoding_GetCurrent())) {
cpi_enc_t const iCurEnc = Encoding_GetCurrent();
// test most-specific first: UTF-8 variants also carry NCP_UNICODE, so they
// must be checked before Encoding_IsUNICODE() to avoid being shadowed.
if (Encoding_IsUTF8_SIGN(iCurEnc)) {
i = IDM_ENCODING_UTF8SIGN;
} else if (Encoding_MaybeUTF8(Encoding_GetCurrent())) {
} else if (Encoding_MaybeUTF8(iCurEnc)) {
i = IDM_ENCODING_UTF8;
} else if (Encoding_IsSystemANSI_CP(Encoding_GetCurrent())) {
} else if (Encoding_IsUNICODE_REVERSE(iCurEnc)) {
i = IDM_ENCODING_UNICODEREV;
} else if (Encoding_IsUNICODE(iCurEnc)) {
i = IDM_ENCODING_UNICODE;
} else if (Encoding_IsSystemANSI_CP(iCurEnc)) {
i = IDM_ENCODING_ANSI;
} else {
i = -1;
@ -10844,7 +10850,11 @@ static void _UpdateStatusbarDelayed(bool bForceRedraw)
}
SendMessage(Globals.hwndStatus, WM_SETREDRAW, TRUE, 0);
InvalidateRect(Globals.hwndStatus, NULL, FALSE);
// bErase=TRUE: SB_SETPARTS may have shifted part boundaries; without a
// background erase the control's own separator pixels at OLD positions
// linger (ghost separators / artefacts at segment starts after file
// load or new/clear). WS_EX_COMPOSITED keeps this flicker-free.
InvalidateRect(Globals.hwndStatus, NULL, TRUE);
}
// --------------------------------------------------------------------------

View File

@ -40,6 +40,7 @@
#include <windows.h>
#include <commctrl.h>
#include <objbase.h> // STDMETHOD — gates PRINTDLGEX / PRINTPAGERANGE in commdlg.h
#include <commdlg.h>
#include <string_view>
@ -72,81 +73,6 @@ static void _StatusUpdatePrintPage(int iPageNum)
}
//=============================================================================
//
// LPPRINTHOOKPROC _LPPrintHookProc()
//
static UINT_PTR CALLBACK _LPPrintHookProc(HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
switch (uiMsg) {
case WM_INITDIALOG: {
SetDialogIconNP3(hwnd);
InitWindowCommon(hwnd, true);
#ifdef D_NP3_WIN10_DARK_MODE
if (UseDarkMode()) {
SetExplorerTheme(GetDlgItem(hwnd, IDOK));
SetExplorerTheme(GetDlgItem(hwnd, IDCANCEL));
SetExplorerTheme(GetDlgItem(hwnd, 0x401));
int const ctl[] = { chx1, rad1, rad2, rad3, grp1, grp2, grp4, cmb4 };
for (int i : ctl) {
SetWindowTheme(GetDlgItem(hwnd, i), L"", L""); // remove theme for BS_AUTORADIOBUTTON
}
}
#endif
SendMessage(hwnd, WM_THEMECHANGED, 0, 0);
}
break;
case WM_DPICHANGED:
UpdateWindowLayoutForDPI(hwnd, (RECT*)lParam, LOWORD(wParam));
break;
#ifdef D_NP3_WIN10_DARK_MODE
CASE_WM_CTLCOLOR_SET:
return SetDarkModeCtlColors((HDC)wParam, UseDarkMode());
break;
case WM_SETTINGCHANGE:
if (IsDarkModeSupported() && IsColorSchemeChangeMessage(lParam)) {
SendMessage(hwnd, WM_THEMECHANGED, 0, 0);
}
break;
case WM_THEMECHANGED:
if (IsDarkModeSupported()) {
bool const darkModeEnabled = CheckDarkModeEnabled();
AllowDarkModeForWindowEx(hwnd, darkModeEnabled);
RefreshTitleBarThemeColor(hwnd);
int const buttons[] = { IDOK, IDCANCEL, 0x401 };
for (int button : buttons) {
HWND const hBtn = GetDlgItem(hwnd, button);
AllowDarkModeForWindowEx(hBtn, darkModeEnabled);
SendMessage(hBtn, WM_THEMECHANGED, 0, 0);
}
UpdateWindowEx(hwnd);
}
break;
#endif
case WM_COMMAND:
if (IsYesOkay(wParam)) {
}
break;
default:
break;
}
return FALSE;
}
//=============================================================================
//
// EditPrint() - Code from SciTE
@ -161,22 +87,25 @@ extern "C" bool EditPrint(HWND hwnd,LPCWSTR pszDocTitle,LPCWSTR pszPageFormat)
constexpr COLORREF const colorBlack = RGB(0x00, 0x00, 0x00);
constexpr COLORREF const colorWhite = RGB(0xFF, 0xFF, 0xFF);
PRINTDLG pdlg = { sizeof(PRINTDLG), nullptr, nullptr, nullptr, nullptr,
0, 0, 0, 0, 0, 0, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
};
// Modern Common Print Dialog (Win2000+, property-sheet host).
// PRINTDLGEX has no nFromPage/nToPage; page ranges live in lpPageRanges.
// Single-range to match the existing downstream loop behaviour.
PRINTPAGERANGE pageRanges[1] = { { 1, 0xffffU } };
pdlg.hwndOwner = GetParent(hwnd);
pdlg.hInstance = Globals.hInstance;
pdlg.Flags = PD_ENABLEPRINTHOOK | PD_USEDEVMODECOPIES | PD_ALLPAGES | PD_RETURNDC;
pdlg.nFromPage = 1;
pdlg.nToPage = 1;
pdlg.nMinPage = 1;
pdlg.nMaxPage = 0xffffU;
pdlg.nCopies = 1;
pdlg.hDC = nullptr;
pdlg.hDevMode = hDevMode;
pdlg.hDevNames = hDevNames;
pdlg.lpfnPrintHook = _LPPrintHookProc;
PRINTDLGEX pdlg = { 0 };
pdlg.lStructSize = sizeof(PRINTDLGEX);
pdlg.hwndOwner = GetParent(hwnd);
pdlg.hDevMode = hDevMode;
pdlg.hDevNames = hDevNames;
pdlg.hDC = nullptr;
pdlg.Flags = PD_USEDEVMODECOPIES | PD_ALLPAGES | PD_RETURNDC | PD_NOCURRENTPAGE;
pdlg.nPageRanges = 0; // no preset ranges; user picks land here
pdlg.nMaxPageRanges = ARRAYSIZE(pageRanges);
pdlg.lpPageRanges = pageRanges;
pdlg.nMinPage = 1;
pdlg.nMaxPage = 0xffffU;
pdlg.nCopies = 1;
pdlg.nStartPage = START_PAGE_GENERAL;
DocPos const startPos = SciCall_GetSelectionStart();
DocPos const endPos = SciCall_GetSelectionEnd();
@ -188,10 +117,13 @@ extern "C" bool EditPrint(HWND hwnd,LPCWSTR pszDocTitle,LPCWSTR pszPageFormat)
}
// |= 0 - Don't display dialog box, just use the default printer and options
pdlg.Flags |= (Flags.PrintFileAndLeave == 1) ? PD_RETURNDEFAULT : 0;
if (Flags.PrintFileAndLeave == 1) {
pdlg.Flags |= PD_RETURNDEFAULT;
}
if (!PrintDlg(&pdlg)) {
return true; // False means error...
HRESULT const hr = PrintDlgEx(&pdlg);
if (FAILED(hr) || (pdlg.dwResultAction == PD_RESULT_CANCEL)) {
return true;
}
hDevMode = pdlg.hDevMode;
@ -199,6 +131,11 @@ extern "C" bool EditPrint(HWND hwnd,LPCWSTR pszDocTitle,LPCWSTR pszPageFormat)
HDC const hdc = pdlg.hDC;
// Resolve the (single) page range; downstream code reads these instead of
// the legacy nFromPage/nToPage fields, which PRINTDLGEX does not have.
DWORD const dwPageFrom = (pdlg.nPageRanges > 0) ? pdlg.lpPageRanges[0].nFromPage : 1U;
DWORD const dwPageTo = (pdlg.nPageRanges > 0) ? pdlg.lpPageRanges[0].nToPage : 0xffffU;
// Get printer resolution
POINT ptDpi;
ptDpi.x = GetDeviceCaps(hdc, LOGPIXELSX); // dpi in X direction
@ -406,7 +343,7 @@ extern "C" bool EditPrint(HWND hwnd,LPCWSTR pszDocTitle,LPCWSTR pszPageFormat)
while (lengthPrinted < lengthDoc) {
bool printPage = (!(pdlg.Flags & PD_PAGENUMS) ||
((pageNum >= pdlg.nFromPage) && (pageNum <= pdlg.nToPage)));
(((DWORD)pageNum >= dwPageFrom) && ((DWORD)pageNum <= dwPageTo)));
StringCchPrintf(pageString,COUNTOF(pageString),pszPageFormat,pageNum);
@ -491,7 +428,7 @@ extern "C" bool EditPrint(HWND hwnd,LPCWSTR pszDocTitle,LPCWSTR pszPageFormat)
}
pageNum++;
if ((pdlg.Flags & PD_PAGENUMS) && (pageNum > pdlg.nToPage)) {
if ((pdlg.Flags & PD_PAGENUMS) && ((DWORD)pageNum > dwPageTo)) {
break;
}
}