[EVENTVWR] Improve details controls transition when updating events list

CORE-20021, CORE-20023, CORE-20037

Complements commits 1786a68256 (#7757) and d1aa59982d (#7921)

- When starting eventvwr, the details buttons are disabled and the fields
  are empty.

- During events enumeration, i.e. when refreshing the events list, the
  Previous/Next navigation arrow buttons are disabled. They get re-enabled
  once enumeration is done. No default event item is auto-selected at first.

- When the user selects an item, the details fields are filled (and the
  Copy button is enabled; the Byte/Word mode buttons are enabled only if
  the selected event has associated data).

- When changing the current filter via the TreeView, the events list is
  refreshed, but also the event details fields are emptied and buttons
  are disabled. The navigation arrows are re-enabled once enumeration is
  finished, but the details fields remain empty until an event is selected.

- Pressing the Previous/Next buttons just after the events list refresh
  (when no item is selected), automatically selects respectively the
  last/the first event in the list.
  The rationale for this behaviour is the following: in this situation,
  no item is selected, so it is as if the "current" item is at the same
  time, at the top and at the end (i.e. at the borders) of the list.

- Temporary HACK: When disabling the navigation arrows, this is usually
  because the events list is being refreshed, so we loose access to the
  event's data and we cannot use the bytes/words mode buttons anymore.
This commit is contained in:
Hermès Bélusca-Maïto
2025-04-27 20:25:09 +02:00
parent fe6de816d6
commit 87eac43fb9
3 changed files with 155 additions and 60 deletions

View File

@@ -1978,7 +1978,6 @@ EnumEventsThread(IN LPVOID lpParameter)
BOOL bResult = TRUE; /* Read succeeded */
HANDLE hProcessHeap = GetProcessHeap();
PSID pLastSid = NULL;
INT nItems;
UINT uStep = 0, uStepAt = 0, uPos = 0;
@@ -1998,7 +1997,8 @@ EnumEventsThread(IN LPVOID lpParameter)
SYSTEMTIME time;
LVITEMW lviEventItem;
EnableEventDetailsButtons(hwndEventDetails, FALSE);
/* Disable the Previous/Next buttons */
SendMessageW(hwndEventDetails, EVT_DISPLAY, FALSE, (LPARAM)-1);
/* Save the current event log filter globally */
EventLogFilter_AddRef(EventLogFilter);
@@ -2265,9 +2265,6 @@ Quit:
/* All events loaded */
Cleanup:
nItems = ListView_GetItemCount(hwndListView);
EnableEventDetailsButtons(hwndEventDetails, (nItems > 0));
ShowWindow(hwndStatusProgress, SW_HIDE);
SendMessageW(hwndListView, LVM_PROGRESS, 0, FALSE);
@@ -2298,6 +2295,11 @@ Cleanup:
/* Resume list view redraw */
SendMessageW(hwndListView, WM_SETREDRAW, TRUE, 0);
/* Re-enable the Previous/Next buttons, keeping the current event details
* displayed, if any. Don't auto-select the first list item but wait for
* the user to do it. */
SendMessageW(hwndEventDetails, EVT_DISPLAY, FALSE, 0);
EventLogFilter_Release(EventLogFilter);
CloseHandle(hStopEnumEvent);
@@ -3342,7 +3344,7 @@ WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
MB_OK | MB_ICONERROR);
break;
}
SendMessageW(hwndEventDetails, EVT_DISPLAY, 0, (LPARAM)pnmv->iItem);
SendMessageW(hwndEventDetails, EVT_DISPLAY, TRUE, (LPARAM)pnmv->iItem);
}
break;
}
@@ -4347,9 +4349,9 @@ EventDetails(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
cxOld = rcWnd.right - rcWnd.left;
cyOld = rcWnd.bottom - rcWnd.top;
/* Show event info in dialog control */
iEventItem = (lParam != 0 ? ((PEVENTDETAIL_INFO)lParam)->iEventItem : 0);
SendMessageW(hWndDetailsCtrl, EVT_DISPLAY, 0, (LPARAM)iEventItem);
/* Display the event info in the dialog */
iEventItem = (lParam != 0 ? ((PEVENTDETAIL_INFO)lParam)->iEventItem : -1);
SendMessageW(hWndDetailsCtrl, EVT_DISPLAY, TRUE, (LPARAM)iEventItem);
// SetWindowPos(hWndDetailsCtrl, NULL,
// 0, 0,

View File

@@ -4,7 +4,7 @@
* PURPOSE: Event Details Control.
* COPYRIGHT: Copyright 2007 Marc Piulachs <marc.piulachs@codexchange.net>
* Copyright 2008-2016 Eric Kohl <eric.kohl@reactos.org>
* Copyright 2016-2022 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
* Copyright 2016-2025 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
*/
#include "eventvwr.h"
@@ -16,6 +16,7 @@
#define EVENT_MESSAGE_EVENTTEXT_BUFFER (1024*10)
extern WCHAR szTitle[];
extern HWND hwndListView;
extern BOOL
GetEventMessage(IN LPCWSTR KeyName,
IN LPCWSTR SourceName,
@@ -25,6 +26,9 @@ GetEventMessage(IN LPCWSTR KeyName,
typedef struct _DETAILDATA
{
/* The event record being displayed */
PEVENTLOGRECORD pevlr;
/* Data initialized from EVENTDETAIL_INFO */
PEVENTLOGFILTER EventLogFilter;
INT iEventItem;
@@ -38,16 +42,21 @@ typedef struct _DETAILDATA
} DETAILDATA, *PDETAILDATA;
static
VOID
DisplayEventData(
_In_ HWND hDlg,
_In_ PDETAILDATA pDetailData);
static
VOID
DisplayEvent(
_In_ HWND hDlg,
_In_ PDETAILDATA pDetailData)
{
PEVENTLOGRECORD pevlr;
PEVENTLOGFILTER EventLogFilter = pDetailData->EventLogFilter;
INT iItem = pDetailData->iEventItem;
LVITEMW li;
PEVENTLOGRECORD pevlr;
BOOL bEventData;
WCHAR szEventType[MAX_PATH];
@@ -60,12 +69,13 @@ DisplayEvent(
WCHAR szEventID[MAX_PATH];
WCHAR szEventText[EVENT_MESSAGE_EVENTTEXT_BUFFER];
/* Retrieve and cache the pointer to the selected event item */
LVITEMW li;
li.mask = LVIF_PARAM;
li.iItem = iItem;
li.iSubItem = 0;
ListView_GetItem(hwndListView, &li);
pevlr = (PEVENTLOGRECORD)li.lParam;
pevlr = pDetailData->pevlr = (PEVENTLOGRECORD)li.lParam;
ListView_GetItemText(hwndListView, iItem, 0, szEventType, ARRAYSIZE(szEventType));
ListView_GetItemText(hwndListView, iItem, 1, szDate, ARRAYSIZE(szDate));
@@ -92,6 +102,8 @@ DisplayEvent(
// FIXME: At the moment we support only one event log in the filter
GetEventMessage(EventLogFilter->EventLogs[0]->LogName, szSource, pevlr, szEventText);
SetDlgItemTextW(hDlg, IDC_EVENTTEXTEDIT, szEventText);
DisplayEventData(hDlg, pDetailData);
}
static
@@ -179,22 +191,17 @@ DisplayEventData(
_In_ HWND hDlg,
_In_ PDETAILDATA pDetailData)
{
PEVENTLOGRECORD pevlr = pDetailData->pevlr;
BOOL bDisplayWords = pDetailData->bDisplayWords;
INT iItem = pDetailData->iEventItem;
LVITEMW li;
PEVENTLOGRECORD pevlr;
LPBYTE pData;
UINT i, uOffset;
UINT uBufferSize, uLineLength;
PWCHAR pTextBuffer, pLine;
li.mask = LVIF_PARAM;
li.iItem = iItem;
li.iSubItem = 0;
ListView_GetItem(hwndListView, &li);
if (!pevlr)
return;
pevlr = (PEVENTLOGRECORD)li.lParam;
if (pevlr->DataLength == 0)
{
SetDlgItemTextW(hDlg, IDC_EVENTDATAEDIT, L"");
@@ -728,6 +735,46 @@ OnSize(HWND hDlg, PDETAILDATA pData, INT cx, INT cy)
}
}
static
VOID
EnableNavigationArrows(
_In_ HWND hDlg,
_In_ BOOL bEnable)
{
/* Enable Previous/Next only if there is more than one item in the list */
if (bEnable)
bEnable &= (ListView_GetItemCount(hwndListView) > 1);
EnableDlgItem(hDlg, IDC_PREVIOUS, bEnable);
EnableDlgItem(hDlg, IDC_NEXT, bEnable);
}
static
VOID
ClearContents(
_In_ HWND hDlg)
{
/* Disable the Previous/Next and Copy buttons */
EnableNavigationArrows(hDlg, FALSE);
EnableDlgItem(hDlg, IDC_COPY, FALSE);
/* Disable the Bytes/Words mode buttons */
EnableDlgItem(hDlg, IDC_BYTESRADIO, FALSE);
EnableDlgItem(hDlg, IDC_WORDRADIO, FALSE);
/* Clear the data fields */
SetDlgItemTextW(hDlg, IDC_EVENTDATESTATIC, L"");
SetDlgItemTextW(hDlg, IDC_EVENTTIMESTATIC, L"");
SetDlgItemTextW(hDlg, IDC_EVENTUSERSTATIC, L"");
SetDlgItemTextW(hDlg, IDC_EVENTSOURCESTATIC, L"");
SetDlgItemTextW(hDlg, IDC_EVENTCOMPUTERSTATIC, L"");
SetDlgItemTextW(hDlg, IDC_EVENTCATEGORYSTATIC, L"");
SetDlgItemTextW(hDlg, IDC_EVENTIDSTATIC, L"");
SetDlgItemTextW(hDlg, IDC_EVENTTYPESTATIC, L"");
SetDlgItemTextW(hDlg, IDC_EVENTTEXTEDIT, L"");
SetDlgItemTextW(hDlg, IDC_EVENTDATAEDIT, L"");
}
static
VOID
InitDetailsDlgCtrl(HWND hDlg, PDETAILDATA pData)
@@ -761,6 +808,20 @@ InitDetailsDlgCtrl(HWND hDlg, PDETAILDATA pData)
SendDlgItemMessageW(hDlg, pData->bDisplayWords ? IDC_WORDRADIO : IDC_BYTESRADIO, BM_SETCHECK, BST_CHECKED, 0);
SendDlgItemMessageW(hDlg, IDC_EVENTDATAEDIT, WM_SETFONT, (WPARAM)pData->hMonospaceFont, (LPARAM)TRUE);
//ClearContents(hDlg);
if (pData->iEventItem != -1)
{
EnableNavigationArrows(hDlg, TRUE);
EnableDlgItem(hDlg, IDC_COPY, TRUE);
}
else
{
EnableNavigationArrows(hDlg, FALSE);
EnableDlgItem(hDlg, IDC_COPY, FALSE);
}
EnableDlgItem(hDlg, IDC_BYTESRADIO, FALSE);
EnableDlgItem(hDlg, IDC_WORDRADIO, FALSE);
}
/* Message handler for Event Details control */
@@ -806,9 +867,8 @@ EventDetailsCtrl(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
pData->scPos.x = pData->scPos.y = 0;
InitDetailsDlgCtrl(hDlg, pData);
EnableWindow(GetDlgItem(hDlg, IDC_BYTESRADIO), FALSE);
EnableWindow(GetDlgItem(hDlg, IDC_WORDRADIO), FALSE);
/* NOTE: Showing the event (if any) is currently delayed to later */
// SendMessageW(hDlg, EVT_DISPLAY, TRUE, (LPARAM)pData->iEventItem);
// OnSize(hDlg, pData, pData->cxOld, pData->cyOld);
return (INT_PTR)TRUE;
@@ -824,17 +884,58 @@ EventDetailsCtrl(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
return (INT_PTR)TRUE;
case EVT_SETFILTER:
{
/* Disable the display first, before changing the current filter */
pData->pevlr = NULL;
pData->iEventItem = -1;
ClearContents(hDlg);
pData->EventLogFilter = (PEVENTLOGFILTER)lParam;
return (INT_PTR)TRUE;
}
case EVT_DISPLAY:
{
pData->iEventItem = (INT)lParam;
if (pData->EventLogFilter)
if (wParam)
{
/* Show event info in control */
DisplayEvent(hDlg, pData);
DisplayEventData(hDlg, pData);
INT iEventItem = (INT)lParam;
/* If no filter is set, don't change anything */
if (!pData->EventLogFilter)
return (INT_PTR)TRUE;
/* If we re-enable display from previously disabled state, re-enable the buttons */
if ((pData->iEventItem == -1) && (iEventItem != -1))
{
EnableNavigationArrows(hDlg, TRUE);
EnableDlgItem(hDlg, IDC_COPY, TRUE);
}
else
/* If we disable display from previously enabled state, clear and disable it */
if ((pData->iEventItem != -1) && (iEventItem == -1))
{
ClearContents(hDlg);
}
/* Set the new item */
pData->pevlr = NULL;
pData->iEventItem = iEventItem;
/* Display the event info, if there is one */
if (pData->iEventItem != -1)
DisplayEvent(hDlg, pData);
}
else
{
/* Enable or disable the Previous/Next buttons,
* but keep the existing contents, if any */
EnableNavigationArrows(hDlg, (lParam != -1));
// HACK: Disable the Bytes/Words mode buttons
// because we won't have access anymore to the
// event data. (This will be fixed in the future.)
pData->pevlr = NULL; // Invalidate also the cache.
EnableDlgItem(hDlg, IDC_BYTESRADIO, FALSE);
EnableDlgItem(hDlg, IDC_WORDRADIO, FALSE);
}
return (INT_PTR)TRUE;
}
@@ -846,25 +947,33 @@ EventDetailsCtrl(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
case IDC_NEXT:
{
BOOL bPrev = (LOWORD(wParam) == IDC_PREVIOUS);
INT iItem, iSel, nItems = ListView_GetItemCount(hwndListView);
WCHAR szText[200];
INT nItems = ListView_GetItemCount(hwndListView);
INT iItem, iSel;
if (nItems <= 0) /* No items? */
break;
/* Get the index of the first selected item */
iSel = ListView_GetNextItem(hwndListView, -1, LVNI_SELECTED);
/* Select the previous/next item from our current one */
iItem = ListView_GetNextItem(hwndListView, -1, LVNI_ALL | LVNI_SELECTED);
iItem = ListView_GetNextItem(hwndListView, iItem,
iItem = ListView_GetNextItem(hwndListView, iSel,
(bPrev ? LVNI_ABOVE : LVNI_BELOW));
if (iItem < 0 || iItem >= nItems)
{
LoadStringW(hInst,
(bPrev ? IDS_CONTFROMEND : IDS_CONTFROMBEGINNING),
szText, _countof(szText));
if (MessageBoxW(hDlg, szText, szTitle, MB_YESNO | MB_ICONQUESTION) == IDNO)
break;
/* Confirm selection restart only if an item was previously
* selected. If not, just proceed with default selection. */
if (iSel != -1)
{
WCHAR szText[200];
LoadStringW(hInst,
(bPrev ? IDS_CONTFROMEND : IDS_CONTFROMBEGINNING),
szText, _countof(szText));
if (MessageBoxW(hDlg, szText, szTitle, MB_YESNO | MB_ICONQUESTION) != IDYES)
break;
}
/* Determine from where to restart */
/* Determine where to restart from */
iItem = (bPrev ? (nItems - 1) : 0);
}
@@ -886,14 +995,12 @@ EventDetailsCtrl(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
LVIS_FOCUSED | LVIS_SELECTED);
ListView_EnsureVisible(hwndListView, iItem, FALSE);
pData->pevlr = NULL;
pData->iEventItem = iItem;
/* Show event info in control */
/* Display the event info */
if (pData->EventLogFilter)
{
DisplayEvent(hDlg, pData);
DisplayEventData(hDlg, pData);
}
return (INT_PTR)TRUE;
}
@@ -904,14 +1011,10 @@ EventDetailsCtrl(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
case IDC_BYTESRADIO:
case IDC_WORDRADIO:
{
pData->bDisplayWords = (LOWORD(wParam) == IDC_WORDRADIO);
if (pData->EventLogFilter)
{
pData->bDisplayWords = (LOWORD(wParam) == IDC_WORDRADIO);
DisplayEventData(hDlg, pData);
}
return (INT_PTR)TRUE;
}
default:
break;
@@ -962,11 +1065,3 @@ CreateEventDetailsCtrl(HINSTANCE hInstance,
MAKEINTRESOURCEW(IDD_EVENTDETAILS_CTRL),
hParentWnd, EventDetailsCtrl, lParam);
}
VOID
EnableEventDetailsButtons(HWND hWnd, BOOL bEnable)
{
EnableDlgItem(hWnd, IDC_PREVIOUS, bEnable);
EnableDlgItem(hWnd, IDC_NEXT, bEnable);
EnableDlgItem(hWnd, IDC_COPY, bEnable);
}

View File

@@ -4,7 +4,7 @@
* PURPOSE: Event Details Control.
* COPYRIGHT: Copyright 2007 Marc Piulachs <marc.piulachs@codexchange.net>
* Copyright 2008-2016 Eric Kohl <eric.kohl@reactos.org>
* Copyright 2016-2022 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
* Copyright 2016-2025 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
*/
#pragma once
@@ -24,5 +24,3 @@ HWND
CreateEventDetailsCtrl(HINSTANCE hInstance,
HWND hParentWnd,
LPARAM lParam);
VOID EnableEventDetailsButtons(HWND hWnd, BOOL bEnable);