Skip to content

Commit 131d602

Browse files
committed
Merge branch 'hotfix/4.24.2'
Release v4.24.2 HOTFIX
2 parents e5c0ce6 + 0ad4fbe commit 131d602

File tree

6 files changed

+97
-36
lines changed

6 files changed

+97
-36
lines changed

Diff for: CHANGELOG.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,14 @@ Releases are listed in reverse version number order.
66

77
> Note that _CodeSnip_ v4 was developed in parallel with v3 for a while. As a consequence some v3 releases have later release dates than early v4 releases.
88
9-
## Release v4.24.1 of 13 April 2005
9+
## Release v4.24.2 of 14 April 2025
10+
11+
Hotfix release.
12+
13+
* Updated bug fix implemented in v4.24.1 to avoid relying on a potentially problematic windows event [issue #70 (2nd attempt)].
14+
* Corrected release date error for v4.24.1 in `CHANGELOG.md`.
15+
16+
## Release v4.24.1 of 13 April 2025
1017

1118
* Fixed bug where CodeSnip occasionally crashes after a computer resumes from hibernation [issue #70].
1219
* Bumped some copyright dates for 2025.

Diff for: Src/FmMain.pas

+4-6
Original file line numberDiff line numberDiff line change
@@ -524,9 +524,10 @@ TMainForm = class(THelpAwareForm)
524524

525525
/// <summary>Handles the <c>WM_POWERBROADCAST</c> messages to detect and
526526
/// respond to hibernation messages.</summary>
527-
/// <remarks>This is necessary as part of the fix for an obscure bug. See
527+
/// <remarks>!! HACK necessary as part of the fix for an obscure bug. See
528528
/// https://github.com/delphidabbler/codesnip/issues/70</remarks>
529529
procedure WMPowerBroadcast(var Msg: TMessage); message WM_POWERBROADCAST;
530+
530531
/// <summary>Displays view item given by TViewItemAction instance
531532
/// referenced by Sender and adds to history list.</summary>
532533
procedure ActViewItemExecute(Sender: TObject);
@@ -1587,18 +1588,15 @@ procedure TMainForm.splitVertCanResize(Sender: TObject;
15871588

15881589
procedure TMainForm.WMPowerBroadcast(var Msg: TMessage);
15891590
begin
1591+
// !! HACK
15901592
// Sometimes when the computer is resumed from hibernation the tree view in
15911593
// the overview frame is destroyed and recreated by Windows. Unfortunately the
15921594
// IView instances associated with the recreated tree nodes are lost.
15931595
// Attempting to read those (now nil) IView instances was resulting in an
15941596
// access violation.
15951597
case Msg.WParam of
15961598
PBT_APMSUSPEND:
1597-
// Get ready for isolation
1598-
fMainDisplayMgr.PrepareForHibernate;
1599-
PBT_APMPOWERSTATUSCHANGE:
1600-
// Restore from hibernation: ensure the IView instances are recreeated
1601-
fMainDisplayMgr.RestoreFromHibernation;
1599+
fMainDisplayMgr._HACK_PrepareForHibernate;
16021600
end;
16031601
end;
16041602

Diff for: Src/FrOverview.pas

+52
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,29 @@ interface
2626

2727
type
2828

29+
// !! HACK
30+
// Horrible hack to expose CreateWnd for overiding TTreeView.CreateWnd for the
31+
// existing TTreeView component of TOverviewFrame. The hack avoids having to
32+
// remove the component and replacing it with a descendant class that is
33+
// manually constructed at run time.
34+
// This is here to enable the tree view to be recreated with correctly
35+
// instantiated TViewItemTreeNode nodes after Windows recreates the tree
36+
// behind the scenes after resuming from hibernation.
37+
// I am deeply ashamed of this hack.
38+
TTreeView = class(ComCtrls.TTreeView)
39+
strict private
40+
var
41+
_HACK_fOnAfterCreateNilViews: TNotifyEvent;
42+
protected
43+
procedure CreateWnd; override;
44+
public
45+
/// <summary>!! HACK. Event triggered after the inherited CreateWnd is
46+
/// called. Only called if the tree view has nil references to IView
47+
/// objects.</summary>
48+
property _HACK_OnAfterCreateNilViews: TNotifyEvent
49+
read _HACK_fOnAfterCreateNilViews write _HACK_fOnAfterCreateNilViews;
50+
end;
51+
2952
{
3053
TOverviewFrame:
3154
Titled frame that displays lists of snippets grouped in various ways and
@@ -214,6 +237,10 @@ TTVDraw = class(TSnippetsTVDraw)
214237
procedure RestoreTreeState;
215238
{Restores last saved treeview expansion state from memory.
216239
}
240+
/// <summary>!! HACK: Sets an event handler on the tree view to work
241+
/// around a bug that can occur after resuming from hibernation.</summary>
242+
/// <remarks>Method of IOverviewDisplayMgr.</remarks>
243+
procedure _HACK_SetHibernateHandler(const AHandler: TNotifyEvent);
217244
{ IPaneInfo }
218245
function IsInteractive: Boolean;
219246
{Checks if the pane is currently interactive with user.
@@ -955,6 +982,12 @@ procedure TOverviewFrame.UpdateTreeState(const State: TTreeNodeAction);
955982
end;
956983
end;
957984

985+
procedure TOverviewFrame._HACK_SetHibernateHandler(
986+
const AHandler: TNotifyEvent);
987+
begin
988+
tvSnippets._HACK_OnAfterCreateNilViews := AHandler;
989+
end;
990+
958991
{ TOverviewFrame.TTVDraw }
959992

960993
function TOverviewFrame.TTVDraw.IsSectionHeadNode(
@@ -993,5 +1026,24 @@ function TOverviewFrame.TTVDraw.IsUserDefinedNode(
9931026
Result := False;
9941027
end;
9951028

1029+
{ TTreeView }
1030+
1031+
procedure TTreeView.CreateWnd;
1032+
var
1033+
HasNilViews: Boolean;
1034+
Node: TTreeNode;
1035+
begin
1036+
inherited;
1037+
HasNilViews := False;
1038+
for Node in Items do
1039+
begin
1040+
HasNilViews := not Assigned((Node as TViewItemTreeNode).ViewItem);
1041+
if HasNilViews then
1042+
Break;
1043+
end;
1044+
if HasNilViews and Assigned(_HACK_fOnAfterCreateNilViews) then
1045+
_HACK_fOnAfterCreateNilViews(Self);
1046+
end;
1047+
9961048
end.
9971049

Diff for: Src/IntfFrameMgrs.pas

+5-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
44
* obtain one at https://mozilla.org/MPL/2.0/
55
*
6-
* Copyright (C) 2005-2021, Peter Johnson (gravatar.com/delphidabbler).
6+
* Copyright (C) 2005-2025, Peter Johnson (gravatar.com/delphidabbler).
77
*
88
* Declares interfaces, constants and enumerations required to manage various
99
* parts of CodeSnip's UI.
@@ -19,6 +19,7 @@ interface
1919
uses
2020
// Delphi
2121
SHDocVw, ActiveX,
22+
Classes, // !! For HACK
2223
// Project
2324
Browser.IntfDocHostUI, DB.USnippet, Compilers.UGlobals, UCommandBars, UView;
2425

@@ -145,6 +146,9 @@ interface
145146
/// <summary>Restore expand / collapse state of treeview to last save
146147
/// state.</summary>
147148
procedure RestoreTreeState;
149+
/// <summary>!! HACK: Sets an event handler on the tree view to work
150+
/// around a bug that can occur after resuming from hibernation.</summary>
151+
procedure _HACK_SetHibernateHandler(const AHandler: TNotifyEvent);
148152
end;
149153

150154
type

Diff for: Src/UMainDisplayMgr.pas

+26-26
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,11 @@ TMainDisplayMgr = class(TObject)
165165
procedure DisplayViewItem(ViewItem: IView; Mode: TDetailPageDisplayMode);
166166
overload;
167167

168+
/// <summary>!! HACK event handle to redisplay the overview pane treeview.
169+
/// Called only if Windows has mysteriously recreated the treeview and lost
170+
/// necessary object references.</summary>
171+
procedure _HACK_HibernateHandler(Sender: TObject);
172+
168173
public
169174
/// <summary>Object contructor. Sets up object to work with given frame
170175
/// manager objects.</summary>
@@ -292,21 +297,12 @@ TMainDisplayMgr = class(TObject)
292297
/// <summary>Prepares display ready for database to be reloaded.</summary>
293298
procedure PrepareForDBReload;
294299

295-
/// <summary>Gets the overview frame prepared for program hibernation.
296-
/// </summary>
300+
/// <summary>!!HACK: gets the overview frame prepared for program
301+
/// hibernation.</summary>
297302
/// <remarks>Saves the overview tree view state ready for restoring after
298-
/// hibernation.</remarks>
299-
procedure PrepareForHibernate;
300-
301-
/// <summary>Restores the overview's tree view to have the correct IView
302-
/// instances after hibernation restores the previously saved state.
303-
/// </summary>
304-
/// <remarks>Sometimes, Windows quietly recreates the node of the tree view
305-
/// after resuming from hibernation, without restoring the associated IView
306-
/// instances, leading to access violations. This method should be called
307-
/// after resuming from hibernation to recreate the tree view with the
308-
/// correct IView instances.</remarks>
309-
procedure RestoreFromHibernation;
303+
/// hibernation if Windows has recreated the overview pane's treeview,
304+
/// losing necessary IView object references..</remarks>
305+
procedure _HACK_PrepareForHibernate;
310306

311307
end;
312308

@@ -583,12 +579,6 @@ procedure TMainDisplayMgr.PrepareForDBViewChange(View: IView);
583579
fPendingViewChange := True;
584580
end;
585581

586-
procedure TMainDisplayMgr.PrepareForHibernate;
587-
begin
588-
// simply save the state of the overview tree view ready for later restoration
589-
(fOverviewMgr as IOverviewDisplayMgr).SaveTreeState;
590-
end;
591-
592582
procedure TMainDisplayMgr.RedisplayOverview;
593583
begin
594584
(fOverviewMgr as IOverviewDisplayMgr).Display(Query.Selection, True);
@@ -616,12 +606,6 @@ procedure TMainDisplayMgr.ReStart;
616606
(fOverviewMgr as IOverviewDisplayMgr).Display(Query.Selection, True);
617607
end;
618608

619-
procedure TMainDisplayMgr.RestoreFromHibernation;
620-
begin
621-
(fOverviewMgr as IOverviewDisplayMgr).Display(Query.Selection, True);
622-
(fOverviewMgr as IOverviewDisplayMgr).RestoreTreeState;
623-
end;
624-
625609
procedure TMainDisplayMgr.SelectAll;
626610
begin
627611
// Only details pane supports text selection
@@ -720,5 +704,21 @@ procedure TMainDisplayMgr.UpdateOverviewTreeState(const State: TTreeNodeAction);
720704
(fOverviewMgr as IOverviewDisplayMgr).UpdateTreeState(State);
721705
end;
722706

707+
procedure TMainDisplayMgr._HACK_HibernateHandler(Sender: TObject);
708+
begin
709+
(fOverviewMgr as IOverviewDisplayMgr).Display(Query.Selection, True);
710+
(fOverviewMgr as IOverviewDisplayMgr).RestoreTreeState;
711+
// disable this handler until next resume from hibernation
712+
(fOverviewMgr as IOverviewDisplayMgr)._HACK_SetHibernateHandler(nil);
713+
end;
714+
715+
procedure TMainDisplayMgr._HACK_PrepareForHibernate;
716+
begin
717+
(fOverviewMgr as IOverviewDisplayMgr).SaveTreeState;
718+
(fOverviewMgr as IOverviewDisplayMgr)._HACK_SetHibernateHandler(
719+
_HACK_HibernateHandler
720+
);
721+
end;
722+
723723
end.
724724

Diff for: Src/VersionInfo.vi-inc

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# CodeSnip Version Information Macros for Including in .vi files
22

33
# Version & build numbers
4-
version=4.24.1
5-
build=273
4+
version=4.24.2
5+
build=274
66

77
# String file information
88
copyright=Copyright © P.D.Johnson, 2005-<YEAR>.

0 commit comments

Comments
 (0)