-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwdwstate.html
292 lines (283 loc) · 15.7 KB
/
wdwstate.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
---
dl-file-prefix: "dd-wdwstate-"
layout: "codelib-tplt"
group: lib
priority: 2
version: "5.6.1"
release-date: "2014-10-28"
platforms: ["Win32", "Win64"]
frameworks: ["VCL"]
compatibility: "Delphi 5 and later"
title: "Window State Components"
precis: "Components that save and restore window size, location & state"
summary: "Three components that save and restore window size, state and position using either, ini files, the registry or user-defined storage."
meta-title: "Window State Save & Restore Components for Delphi Pascal VCL | Open Source | 32 & 64 bit"
meta-desc: "Three Delphi Pascal VCL components for saving and restoring a window's position in the registry, ini file or custom storage. Requires Delphi 5 & later."
download-base-url: "https://sourceforge.net/projects/ddablib/files/wdwstate/"
repo-url: "https://github.com/ddablib/wdwstate"
docs-url: "https://github.com/delphidabbler/ddab-lib-docs/blob/master/Docs/WindowStateComponents.md"
faq-url: "https://github.com/delphidabbler/ddab-lib-docs/blob/master/FAQs/WindowStateComponents.md"
want-header-buttons: true
status: "current"
---
{% assign dl-file = page.dl-file-prefix | append: page.version | append: ".zip" %}
{% assign dl-url = page.download-base-url | append: dl-file %}
<section class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">
Overview
</h2>
</div>
<div class="panel-body">
<p>
The <em>{{ page.title }}</em> can save and restore a window's size, position and state between program executions. Three components are provided that use different means of storing the information. They are:
</p>
<dl>
<dt id="TPJWdwState">
TPJWdwState
</dt>
<dd>
<p>
Records window information in an ini file. The user has control over the ini file name (via the <var>IniFileName</var> property) and the name of the section of the ini file where window information is recorded (using the <var>Section</var> property). Alternatively the ini file and section names can be configured by handling the <var>OnGetIniData</var> event that is triggered immediately before the ini file is read or written.
</p>
</dd>
<dt id="TPJRegWdwState">
TPJRegWdwState
</dt>
<dd>
<p>
Uses the registry to record window information. The registry root key and sub key where the information is stored are controlled by the <var>RootKey(Ex)</var> and <var>SubKey</var> properties, or by handling the <var>OnGetRegData(Ex)</var> event. This event is triggered just before the registry is accessed. Additional application defined data can be read from or written to the registry by handling the <var>OnGettingRegData</var> and <var>OnPuttingRegData</var> events that are triggered after the component reads or writes the registry.
</p>
<p class="alert alert-warning glyph">
You are discouraged from using <var>TPJRegWdwState</var> for programs compiled with Delphi 5 and earlier that may be run on 64 bit Windows, because the component may not be able to access the 64 bit registry correctly and window state may be lost.
</p>
</dd>
<dt id="TPJUserWdwState">
TPJUserWdwState
</dt>
<dd>
<p>
When using this component the user must handle saving and reading the window state data to or from persistent storage. The component gives the most flexibility of all the components at the expense of placing the storage burden on the user. The component triggers <var>OnReadData</var> and <var>OnSaveData</var> events when it is ready to read or save data.
</p>
</dd>
</dl>
<h3 data-toggle="collapse" data-target="#features" class="collapsible collapsed">
Features
</h3>
<div id="features" class="collapse"> <!-- begin collapsible #features section -->
<p>
All components implement the same functionality, controlled by some common properties and events, as follows:
</p>
<ul class="wide">
<li>
The components can automatically restore and save windows when the program starts up and closes down (using the <var>AutoSaveRestore</var> property). If <var>AutoSaveRestore</var> is set to False then the <var>Restore</var> and <var>Save</var> methods must be called from the host application.
</li>
<li>
The <var>Options</var> property can be used to customise the way the window is restored:
<ul class="wide">
<li>
The components can be instructed to ignore the saved window state – the window is then displayed in the normal state.
</li>
<li>
The window's saved size can be ignored and the default size of the form used instead. This is useful for dialogue boxes and fixed size windows.
</li>
<li>
The window can be kept within the current work area of the desktop. If this option is used the window also appears on the correct monitor on multi-monitor systems. If the form containing the window state component is a MDI child form this option keeps the window within the parent form's client area, after allowing for any menu, toolbars or status bar etc.
</li>
</ul>
</li>
<li>
When the form is to be restored in a minimized state it briefly appears on screen in the normal state before being minimized. The <var>MinimizeDelay</var> property controls the delay between the window appearing and being minimized.
</li>
</ul>
<p>
<var>TPJWdwState</var> and <var>TPJRegWdwState</var> also support the <var>OnReadWdwState</var> event. Handling this event enables the stored window's state, size and position values to be changed before the window is restored. This event is called after reading the data and before sizing the window. <var>TPJUserWdwState</var> does not expose this event because the user is in charge of reading the data and can modify it in the <var>OnReadData</var> event.
</p>
<p>
All the components derive from an abstract base class named <var>TPJCustomWdwState</var>. This class provides the core window handling and sizing functionality. It provides abstract methods for accessing the required storage medium. Therefore it is quite straightforward to create further components that use alternative storage systems. All that needs to be provided are methods to read/write the window information along with any additional properties that are required to configure the storage medium.
</p>
</div> <!-- /#features -->
<h3 data-toggle="collapse" data-target="#demo" class="collapsible collapsed">
Demo code
</h3>
<div id="demo" class="collapse"> <!-- begin collapsible #demo section -->
<p>
There are four demo projects included with these components. They are:
</p>
<ol class="wide">
<li>
<code>StandardDemo.dpr</code> – Demonstrates how to use the components in the standard way, i.e. dropped on a form from the component palette. This demo uses <var>TPJRegWdwState</var>.
</li>
<li>
<code>StandAloneDemo.dpr</code> – Demonstrates how to create and use the components dynamically using the <var>CreateStandAlone</var> constructor. This demo uses <var>TPJWdwState</var>.
</li>
<li>
<code>UserDemo.dpr</code> – Demonstrates how to use <var>TPJUserWdwState</var> and load and save data in the <var>OnReadData</var> and <var>OnSaveData</var> events.
</li>
<li>
<code>MDIDemo.dpr</code> – Demonstrates the use of <var>TPJWdwState</var> with MDI applications.
</li>
</ol>
</div> <!-- /#demo -->
<h3 data-toggle="collapse" data-target="#how-it-works" class="collapsible collapsed">
How the components work
</h3>
<div id="how-it-works" class="collapse"> <!-- begin collapsible #how-it-works section -->
<p>
The underlying principle used in the code is described in the article "<a href="/articles/article-4">How to remember a window's size, state and position</a>".
</p>
<p>
We can't rely on Delphi's own <var>Width</var> and <var>Height</var> properties for recording window size, since these do not maintain size of the normalised window size when the window is maximized. Instead we have to use the <var>GetWindowPlacement</var> and <var>SetWindowPlacement</var> Windows API calls.
</p>
<p>
Finding the right time to restore a window on application startup has proved problematic. It is not possible to call the <var>Restore</var> method before the form's window handle has been created. We therefore need to delay any such restoration until the form has been shown. A hook class is used to peek at the Windows messages sent to the parent form. This class forwards relevant messages to the component.
</p>
<p class="alert alert-info glyph">
One side effect of this complexity is that you can't create instances of the components at run time using the standard constructor. The code is not initialised properly unless the component is added to a form at design time. A special constructor – <var>CreateStandAlone</var> – has been provided that makes dynamic construction possible.
</p>
</div> <!-- /#how-it-works -->
</div>
</section>
<section class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">
Get The Code
</h2>
</div>
<div class="panel-body">
<p>
You can download the latest version of the <em>{{page.title}}</em> directly from SourceForge as <code>{{ dl-file }}</code>.
</p>
<p class="text-center">
<a class="btn btn-primary" role="button" href="{{ dl-url }}" aria-label="Go to SourceForge and download latest version automatically">Download <span class="hidden-xs">release </span>v{{ page.version }}<span class="hidden-xs"> from SourceForge</span></a>
</p>
<p>
The <em>{{ page.title }}</em> source code is hosted in the <a href="{{ page.repo-url }}" aria-label="Link to the ddablib/wdwstate repository on GitHub"><code>ddablib/wdwstate</code></a> GitHub repository. You can <code>git clone</code> or fork the repository as required.
</p>
</div>
</section>
<section class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">
Installation
</h2>
</div>
<div class="panel-body">
<p>
The <em>{{ page.title }}</em> are supplied in a zip file. Before installing you need to extract all the files from the zip file, preserving the directory structure. The following files will be extracted:
</p>
<ul class="list-group">
<li class="list-group-item">
<strong><code>PJWdwState.pas</code></strong> – component source code.
</li>
<li class="list-group-item">
<strong><code>PJWdwState.dcr</code></strong> – resource file containing component palette glyphs.
</li>
<li class="list-group-item">
<code>ReadMe.htm</code> – read-me file.
</li>
<li class="list-group-item">
<code>ChangeLog.txt</code> – the project's change log.
</li>
<li class="list-group-item">
<code>MPL-2.txt</code> – the Mozilla Public License v2.0.
</li>
<li class="list-group-item">
<code>Documentation.URL</code> – short-cut to the component's online documentation.
</li>
<li class="list-group-item">
<code>PJWdwState.hlp</code> – component help file that integrates with the Delphi 4 to 7 OpenHelp system. <span class="text-warning bg-warning glyph">Deprecated</span>
</li>
<li class="list-group-item">
<code>PJWdwState.als</code> – a-link keyword file for integration
with the Delphi 6 or 7 OpenHelp system. <span class="text-warning bg-warning glyph">Deprecated</span>
</li>
</ul>
<p>
In addition to the above files you will find the the source code of four demo projects along with readme files in the <code>Demos</code> directory and its <code>1</code>, <code>2</code>, <code>3</code> and <code>4</code> sub-directories. Read <code>DemoReadMe.htm</code> for details of the demos. Although the components are known to compile with Delphi 5 and later, the demos require Delphi 7 as a minimum.
</p>
<p>
You can now install the components into the Delphi IDE. If you need help doing this <a href="{{ site.data.core.install-to-ide-link }}" aria-title="see a tip on working with design time packages">see here</a>.
</p>
</div>
</section>
<section class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">
Documentation
</h2>
</div>
<div class="panel-body">
<p>
The <em>{{ page.title }}</em> are comprehensively documented online <a href="{{ page.docs-url }}" aria-title="View the online documentation">here</a>
</p>
<p>
The project's change log can be viewed <a href="https://raw.githubusercontent.com/ddablib/wdwstate/main/Docs/ChangeLog.txt" aria-title="View the change log in plain text">here</a>.
</p>
<p>
A read-me file (<code>ReadMe.htm</code>) is included in the project download.
</p>
<div class="alert alert-info">
<p>
A legacy WinHelp help file is included in the download that can only be integrated with the IDE in Delphi 7 and earlier. <a href="/articles/article-15">this article</a> explains how to do it.
</p>
<p class="alert alert-warning glyph">
This help file is deprecated and is no longer being updated. The last update was in the v5.4.1 release. The help file <strong>will</strong> be removed from any future release.
</p>
<p class="alert alert-danger glyph">
WinHelp is an optional download for Windows Vista through to Windows 8.1 and can't be installed at all on Windows 10 and later.
</p>
</div>
<p>
There is also an <a href="{{ page.faq-url }}">FAQ</a>.
</p>
</div>
</section>
<section class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title" id="feedback">
Feedback & Queries
</h2>
</div>
<div class="panel-body">
<p>
If you find any bugs or want to suggest a new feature please report them using the <em>{{page.title}}</em> <a href="https://github.com/ddablib/wdwstate/issues">issue tracker</a>.
</p>
<p>
If you have created a bug fix or have implemented a new feature please open a pull request for it.
</p>
<p>
Should you have any queries about using the components please read the <a href="{{ page.docs-url }}">documentation</a> and/or <a href="{{ page.faq-url }}">FAQ</a>. If you can't find an answer in the documentation then post a message in the <a href="https://github.com/orgs/ddablib/discussions">discussion group</a>
</p>
</div>
</section>
<section class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">
License
</h2>
</div>
<div class="panel-body">
<p>
<span class="fa fa-copyright fa-pull-left fa-3x"></span>
The <em>{{ page.title }}</em> are open source. They are copyright © 1999-2014 by <a href="https://en.gravatar.com/delphidabbler" aria-label="Peter Johnson's Gravatar account">Peter Johnson</a>. The source code is made available under the terms of the <a href="https://www.mozilla.org/MPL/2.0/" aria-label="Mozilla Public License v2.0 on mozilla.org">Mozilla Public License v2.0</a>. All relevant trademarks are acknowledged.
</p>
<p>
The following people contributed to the project:
<ul>
<li>
Stefan Winter
</li>
<li>
Enrico Bortolazzi
</li>
<li>
Bruce J Miller
</li>
<li>
Craig Symons
</li>
</ul>
</p>
</div>
</section>