Release v0.6.12: improve continuous correction and resize log viewer
This commit is contained in:
+56
-46
@@ -34,6 +34,7 @@ struct WindowLayout
|
||||
bool scrolling{}, arranging{}, history{};
|
||||
int wheelRemainder{}, horizontalWheelRemainder{};
|
||||
std::vector<std::pair<HWND, RECT>> controls; // Original 96-DPI geometry; never rescale rounded pixels.
|
||||
HWND stretch{}, bottomLeft{}, bottomRight{};
|
||||
};
|
||||
WindowLayout *windowLayoutState(HWND w)
|
||||
{
|
||||
@@ -69,8 +70,9 @@ void arrangeWindow(HWND w)
|
||||
layout->y = SetScrollInfo(w, SB_VERT, &vertical, TRUE);
|
||||
}
|
||||
RECT client{}; GetClientRect(w, &client);
|
||||
int extraWidth = layout->history ? std::max(0, int(client.right) - scale(w, layout->width)) : 0;
|
||||
int extraHeight = layout->history ? std::max(0, int(client.bottom) - scale(w, layout->height)) : 0;
|
||||
bool expandable = layout->history || layout->stretch;
|
||||
int extraWidth = expandable ? std::max(0, int(client.right) - scale(w, layout->width)) : 0;
|
||||
int extraHeight = expandable ? std::max(0, int(client.bottom) - scale(w, layout->height)) : 0;
|
||||
struct Move { HWND child; RECT rect; };
|
||||
std::vector<Move> moves;
|
||||
for (const auto &[child, r] : layout->controls)
|
||||
@@ -80,6 +82,13 @@ void arrangeWindow(HWND w)
|
||||
scale(w, r.top) - layout->y + (id >= 110 && id <= 114 ? extraHeight : 0)};
|
||||
next.right = next.left + scale(w, r.right - r.left) + (id == 101 || id == 102 ? extraWidth : 0);
|
||||
next.bottom = next.top + scale(w, r.bottom - r.top) + (id == 102 ? extraHeight : 0);
|
||||
if (child == layout->stretch)
|
||||
{
|
||||
next.right += extraWidth;
|
||||
next.bottom += extraHeight;
|
||||
}
|
||||
if (child == layout->bottomLeft || child == layout->bottomRight)
|
||||
OffsetRect(&next, child == layout->bottomRight ? extraWidth : 0, extraHeight);
|
||||
RECT current{}; GetWindowRect(child, ¤t);
|
||||
MapWindowPoints(nullptr, w, reinterpret_cast<POINT *>(¤t), 2);
|
||||
if (!EqualRect(¤t, &next)) moves.push_back({child, next});
|
||||
@@ -1530,53 +1539,41 @@ void showHistory(App &app, bool visible)
|
||||
SetFocus(GetDlgItem(app.historyWindow, 101));
|
||||
refreshHistory(app);
|
||||
}
|
||||
#endif
|
||||
#ifndef KS_RESIDENT_APP
|
||||
namespace
|
||||
{
|
||||
constexpr int LogChoice = 601, LogRows = 602, LogRefresh = 603, LogStatus = 604, LogCopy = 605,
|
||||
LogClear = 606;
|
||||
LRESULT CALLBACK logListProc(HWND w, UINT msg, WPARAM wp, LPARAM lp, UINT_PTR, DWORD_PTR)
|
||||
void fitLogDetails(HWND list)
|
||||
{
|
||||
// Header notifications go to the ListView, not its top-level parent.
|
||||
if (msg == WM_NOTIFY && ((NMHDR *)lp)->hwndFrom == ListView_GetHeader(w) &&
|
||||
((NMHDR *)lp)->code == NM_CUSTOMDRAW)
|
||||
if (GetPropW(list, L"FittingLogDetails") || Header_GetItemCount(ListView_GetHeader(list)) != 4) return;
|
||||
SetPropW(list, L"FittingLogDetails", (HANDLE)1);
|
||||
RECT client{};
|
||||
GetClientRect(list, &client);
|
||||
int remaining = client.right;
|
||||
for (int column = 0; column < 3; ++column)
|
||||
remaining -= ListView_GetColumnWidth(list, column);
|
||||
int width = std::max(scale(list, 120), remaining);
|
||||
if (ListView_GetColumnWidth(list, 3) != width)
|
||||
ListView_SetColumnWidth(list, 3, width);
|
||||
RemovePropW(list, L"FittingLogDetails");
|
||||
}
|
||||
LRESULT CALLBACK logListResizeProc(HWND w, UINT msg, WPARAM wp, LPARAM lp, UINT_PTR, DWORD_PTR)
|
||||
{
|
||||
auto result = DefSubclassProc(w, msg, wp, lp);
|
||||
if (msg == WM_SIZE)
|
||||
fitLogDetails(w);
|
||||
if (msg == WM_NOTIFY && lp)
|
||||
{
|
||||
auto *draw = (NMCUSTOMDRAW *)lp;
|
||||
if (draw->dwDrawStage == CDDS_PREPAINT)
|
||||
{
|
||||
FillRect(draw->hdc, &draw->rc, GetSysColorBrush(COLOR_BTNFACE));
|
||||
return CDRF_NOTIFYITEMDRAW;
|
||||
}
|
||||
if (draw->dwDrawStage == CDDS_ITEMPREPAINT)
|
||||
{
|
||||
int saved = SaveDC(draw->hdc);
|
||||
FillRect(draw->hdc, &draw->rc, GetSysColorBrush(COLOR_BTNFACE));
|
||||
RECT edge = draw->rc;
|
||||
edge.top = edge.bottom - 1;
|
||||
FillRect(draw->hdc, &edge, GetSysColorBrush(COLOR_3DSHADOW));
|
||||
edge = draw->rc;
|
||||
edge.left = edge.right - 1;
|
||||
FillRect(draw->hdc, &edge, GetSysColorBrush(COLOR_3DSHADOW));
|
||||
wchar_t title[128]{};
|
||||
HDITEMW item{};
|
||||
item.mask = HDI_TEXT;
|
||||
item.pszText = title;
|
||||
item.cchTextMax = 128;
|
||||
Header_GetItem(draw->hdr.hwndFrom, (int)draw->dwItemSpec, &item);
|
||||
auto headerFont = (HFONT)SendMessageW(draw->hdr.hwndFrom, WM_GETFONT, 0, 0);
|
||||
if (headerFont)
|
||||
SelectObject(draw->hdc, headerFont);
|
||||
SetBkMode(draw->hdc, TRANSPARENT);
|
||||
SetTextColor(draw->hdc, GetSysColor(COLOR_BTNTEXT));
|
||||
RECT text = draw->rc;
|
||||
InflateRect(&text, -scale(w, 6), 0);
|
||||
DrawTextW(draw->hdc, title, -1, &text, DT_SINGLELINE | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX);
|
||||
RestoreDC(draw->hdc, saved);
|
||||
return CDRF_SKIPDEFAULT;
|
||||
}
|
||||
auto *header = reinterpret_cast<NMHEADERW *>(lp);
|
||||
if (header->hdr.hwndFrom == ListView_GetHeader(w) &&
|
||||
(header->hdr.code == HDN_ITEMCHANGEDW || header->hdr.code == HDN_ITEMCHANGEDA) &&
|
||||
header->iItem >= 0 && header->iItem < 3)
|
||||
fitLogDetails(w);
|
||||
}
|
||||
if (msg == WM_NCDESTROY)
|
||||
RemoveWindowSubclass(w, logListProc, 1);
|
||||
return DefSubclassProc(w, msg, wp, lp);
|
||||
if (msg == WM_NCDESTROY) RemoveWindowSubclass(w, logListResizeProc, 3);
|
||||
return result;
|
||||
}
|
||||
void copyLogRows(HWND w, App &app)
|
||||
{
|
||||
@@ -1596,7 +1593,11 @@ void copyLogRows(HWND w, App &app)
|
||||
copied += L"\r\n";
|
||||
}
|
||||
if (!copied.empty())
|
||||
app.ownSequence = writeClipboard(app.window, textClip(copied));
|
||||
{
|
||||
auto clip = textClip(copied);
|
||||
clip.formats.push_back({0, L"ExcludeClipboardContentFromMonitorProcessing", {1, 0, 0, 0}});
|
||||
app.ownSequence = writeClipboard(app.window, clip);
|
||||
}
|
||||
}
|
||||
void refreshLogView(HWND w, App &app)
|
||||
{
|
||||
@@ -1664,6 +1665,7 @@ void refreshLogView(HWND w, App &app)
|
||||
InvalidateRect(list, nullptr, TRUE);
|
||||
if (row)
|
||||
ListView_EnsureVisible(list, row - 1, FALSE);
|
||||
fitLogDetails(list);
|
||||
value(w, LogStatus, app.settings.writeLog ? L"Logging enabled: failed operations only."
|
||||
: L"Logging disabled. Showing previously saved entries.");
|
||||
}
|
||||
@@ -1696,7 +1698,7 @@ LRESULT CALLBACK logProc(HWND w, UINT msg, WPARAM wp, LPARAM lp)
|
||||
{
|
||||
try
|
||||
{
|
||||
clearDiagnosticLog(SendDlgItemMessageW(w, LogChoice, CB_GETCURSEL, 0, 0) == 1);
|
||||
app->clearLog(SendDlgItemMessageW(w, LogChoice, CB_GETCURSEL, 0, 0) == 1);
|
||||
refreshLogView(w, *app);
|
||||
}
|
||||
catch (const std::exception &e) { error(w, e); }
|
||||
@@ -1758,7 +1760,7 @@ void showLogs(App &app)
|
||||
auto list = control(w, WC_LISTVIEWW, L"", WS_TABSTOP | WS_BORDER | LVS_REPORT | LVS_SHOWSELALWAYS,
|
||||
LogRows, 16, 82, 868, 454);
|
||||
ListView_SetExtendedListViewStyle(list, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_DOUBLEBUFFER);
|
||||
SetWindowSubclass(list, logListProc, 1, 0);
|
||||
SetWindowSubclass(list, logListResizeProc, 3, 0);
|
||||
const wchar_t *titles[] = {L"Time", L"Attempt", L"Event", L"Details"};
|
||||
const int widths[] = {155, 65, 195, 900};
|
||||
for (int i = 0; i < 4; ++i)
|
||||
@@ -1769,12 +1771,20 @@ void showLogs(App &app)
|
||||
column.cx = scale(w, widths[i]);
|
||||
ListView_InsertColumn(list, i, &column);
|
||||
}
|
||||
label(w, L"Select rows to copy. Ctrl+A selects all; Ctrl+C copies selected rows.", 16, 551, 720);
|
||||
auto hint = control(w, L"STATIC", L"Select rows to copy. Ctrl+A selects all; Ctrl+C copies selected rows.",
|
||||
0, 0, 16, 551, 720, 22);
|
||||
button(w, L"Close", IDCANCEL, 774, 548, 110);
|
||||
auto *layout = windowLayoutState(w);
|
||||
layout->stretch = list;
|
||||
layout->bottomLeft = hint;
|
||||
layout->bottomRight = GetDlgItem(w, IDCANCEL);
|
||||
arrangeWindow(w);
|
||||
refreshLogView(w, app);
|
||||
showRequestedWindow(w);
|
||||
activateWindow(w);
|
||||
}
|
||||
#else
|
||||
void showLogs(App &app) { launchConfiguration(app, false, true); }
|
||||
#endif
|
||||
#ifndef KS_RESIDENT_APP
|
||||
void showSettings(App &app, bool visible)
|
||||
|
||||
Reference in New Issue
Block a user