Compare commits
246 commits
Author | SHA1 | Date | |
---|---|---|---|
|
ae8da16834 | ||
|
6745982d60 | ||
|
cd29b29282 | ||
|
3a473bdc10 | ||
|
3d2ed7395c | ||
|
3884c4446f | ||
|
11d0c30ddb | ||
|
f7eb0abe43 | ||
|
cad1ec393f | ||
|
4df563f1bb | ||
|
e8f06c1368 | ||
|
2c06fe1684 | ||
|
9e85ee5810 | ||
|
4998a104ea | ||
|
1fd82f35c8 | ||
|
e7b141e095 | ||
|
304c654e80 | ||
|
9661f8bd79 | ||
|
5d26d86e28 | ||
|
f05d569387 | ||
|
f66dc3afd8 | ||
|
5f666b20d1 | ||
|
2d695d11bf | ||
|
8da7d9b4bc | ||
|
f7a1f92343 | ||
|
8771c2edd7 | ||
|
f34fffa574 | ||
|
cce0f7f52d | ||
|
8c5d6475ad | ||
|
052cb05f53 | ||
|
40f8f5cefd | ||
|
7dc0cbee82 | ||
|
1a5d9442d2 | ||
|
d36bf0c56c | ||
|
9224d62191 | ||
|
e41caba220 | ||
|
769f35b681 | ||
|
2ba0a5395b | ||
|
e4be317e77 | ||
|
fb5f538b88 | ||
|
3b5813bb35 | ||
|
de1b815d57 | ||
|
62452f3e0b | ||
|
0adf762fa0 | ||
|
05a740a21f | ||
|
4330c95216 | ||
|
23b63d09ea | ||
|
6097ab4bc7 | ||
|
aacaefc205 | ||
|
557a3bbddb | ||
|
189611ad3a | ||
|
86926ffd27 | ||
|
10dd03498a | ||
|
3c585c1dab | ||
|
172cbdc35c | ||
|
5fc59d5bc5 | ||
|
8c710ab55c | ||
|
4f7479b0b7 | ||
|
c15ab870ac | ||
|
c719aee32f | ||
|
2cfa8ce92f | ||
|
83c228b6fe | ||
|
5d6c71d03a | ||
|
c58027bb9c | ||
|
62a03e4ed3 | ||
|
fe06972d58 | ||
|
b70db0aa53 | ||
|
2bfd021698 | ||
|
0e622b8021 | ||
|
5a794baf8b | ||
|
a5dd48becf | ||
|
13cd0ab8d5 | ||
|
52231e20ab | ||
|
362df4c720 | ||
|
5925950f24 | ||
|
c292fdd1b1 | ||
|
ecd57678e1 | ||
|
145769a886 | ||
|
b32fbee4d0 | ||
|
cfb1793dc6 | ||
|
2b288cb295 | ||
|
04e569fbcb | ||
|
3c6f053b00 | ||
|
bac953a9e4 | ||
|
ab1f69d06b | ||
|
44b17d4225 | ||
|
23fd9ba665 | ||
|
7d431a22f1 | ||
|
384154254a | ||
|
041ddcbb6d | ||
|
6764546824 | ||
|
453a4cb9e9 | ||
|
6feaa24d92 | ||
|
b03ddd4470 | ||
|
886182afc1 | ||
|
b519812fa5 | ||
|
cf4a966e28 | ||
|
9334f516a1 | ||
|
21e664b4c0 | ||
|
bc25a0ea01 | ||
|
d4742d6127 | ||
|
ddbbe88032 | ||
|
021205f255 | ||
|
a398bba08a | ||
|
e3b184b68d | ||
|
fffdf03c10 | ||
|
0d6940b6ec | ||
|
12e6522a78 | ||
|
9e63a2b853 | ||
|
b392ac84f9 | ||
|
573b453704 | ||
|
cabca12856 | ||
|
7f5f465362 | ||
|
cd328c2979 | ||
|
7dfd7f5616 | ||
|
3cb7f93cee | ||
|
e4571e4f34 | ||
|
4d6b24d8fc | ||
|
6910013026 | ||
|
0d5d0372ee | ||
|
b758b474cd | ||
|
3847a6eff0 | ||
|
94c7bd18c4 | ||
|
34c0dbd0cf | ||
|
1a13cf8b11 | ||
|
cea1088a7d | ||
|
8e33aab670 | ||
|
c7f0f29961 | ||
|
5296f7dff5 | ||
|
dfec7db6b7 | ||
|
80c43c2051 | ||
|
db3201ade2 | ||
|
efc2d0bb67 | ||
|
0d3d5c24f3 | ||
|
76118726a8 | ||
|
ee8603c5b6 | ||
|
9cb7fd2e90 | ||
|
382a427a47 | ||
|
c0e1af0c10 | ||
|
a40273567a | ||
|
c5c12dcad3 | ||
|
6cbfea8f69 | ||
|
cee860c2d4 | ||
|
a515bd6e6e | ||
|
23fd772152 | ||
|
b02d160872 | ||
|
b758dfed2d | ||
|
96caaa9cd8 | ||
|
5d15d4c042 | ||
|
580a0864e2 | ||
|
748d86ddc8 | ||
|
a98717ab4e | ||
|
3d38b70cf1 | ||
|
d39563b9b5 | ||
|
df594f6045 | ||
|
c8575c1b03 | ||
|
cc2fa3311c | ||
|
ea1b7baea6 | ||
|
346e5fdb36 | ||
|
bff39c71dc | ||
|
f23646e480 | ||
|
31e0ebc85e | ||
|
860034633a | ||
|
9d80f6c1b2 | ||
|
61133e14b5 | ||
|
6b2bbba706 | ||
|
2fd2ff129b | ||
|
cf5e26af87 | ||
|
a541eb0a6c | ||
|
c47246cc65 | ||
|
4fc6f7ad40 | ||
|
bcd23a31f2 | ||
|
2b0c470ce5 | ||
|
665aed45f7 | ||
|
ed3ee46735 | ||
|
e04dc2ee07 | ||
|
5d286a467d | ||
|
ebe7c5d33d | ||
|
08ef381f96 | ||
|
090fa0e3ad | ||
|
2763659b4c | ||
|
f6007a4b62 | ||
|
d22a183554 | ||
|
b575920805 | ||
|
2b73c3c2bc | ||
|
eea9165382 | ||
|
8d3816553b | ||
|
e6f11c354d | ||
|
1b4f62ee7d | ||
|
800b6afa15 | ||
|
452ef9017c | ||
|
1ef5e99d40 | ||
|
7fd80af8bf | ||
|
e8322d5a8a | ||
|
ef02d287d5 | ||
|
a1a3574f73 | ||
|
1e580843ff | ||
|
4cece1ab9c | ||
|
0a6c00c3a7 | ||
|
697e79b1ba | ||
|
7bd8511bb9 | ||
|
2a7a108748 | ||
|
3240042a68 | ||
|
ae75d66172 | ||
|
05dec2e6dd | ||
|
8b12f6e4a8 | ||
|
eade031052 | ||
|
b13bcf0b58 | ||
|
2d14ef2cb9 | ||
|
bed63a11f4 | ||
|
e7b52a035c | ||
|
4136e5d2a1 | ||
|
e99518f23b | ||
|
b1888cbf9b | ||
|
e5194d8660 | ||
|
ef6e0a6b37 | ||
|
451ecb9424 | ||
|
d3b1862113 | ||
|
f81735509a | ||
|
b8a03dd189 | ||
|
2b36e580b9 | ||
|
806fcd6bd2 | ||
|
185b34268c | ||
|
db6ca09f65 | ||
|
ff53cc352d | ||
|
5ecc8bdf1b | ||
|
a723695ff4 | ||
|
c6877b688f | ||
|
d1cf04ec3d | ||
|
8890db68e6 | ||
|
cf7a4b831a | ||
|
28a02c0a12 | ||
|
b782e9b034 | ||
|
63334fa67c | ||
|
5fc803757a | ||
|
958624db0a | ||
|
db2d8c5fb0 | ||
|
dfe5dbd16c | ||
|
8d68937a96 | ||
|
88e5a24441 | ||
|
a5221064eb | ||
|
74da136678 | ||
|
9c7c17a5b7 | ||
|
e166a3f89d | ||
|
2a95cebe6a | ||
|
d0ed7aa288 |
18
Help.md
|
@ -6,8 +6,9 @@
|
|||
| --- | --- |
|
||||
| -gui=0 | Do not display the PersistentWindows icon on the System Tray. Effectively runs PersistentWindows as a service
|
||||
| -splash=0 | No splash window at PersistentWindows startup
|
||||
| -legacy_icon | Switch to the original icon (as of 5.49 release)
|
||||
| -legacy_icon | Switch to the original icon 
|
||||
| -silent | No splash window, no balloon tip hint, no event logging
|
||||
| -capture_floating_window=0 | Disable capture floating child window and dialog window position
|
||||
| -ignore_process "notepad.exe;foo" | Avoid restoring windows for the processes notepad.exe and foo
|
||||
| -debug_process "notepad.exe;foo" | Print the window positioning event logs in Event Viewer for the processes *notepad.exe* and *foo*
|
||||
| -foreground_background_dual_position=0 | Turn off dual position switching
|
||||
|
@ -15,6 +16,7 @@
|
|||
| -hotkey "Q" | register Alt + Q as the hotkey to (de)activate webpage commander window, default hotkey is "W" (Alt + W)
|
||||
| -ctrl_minimize_to_tray=0 | Turn off ctrl minimize window to notification tray
|
||||
| -prompt_session_restore | Ask the user before restoring the window layout upon resuming the last session. This may help reduce the total restore time for remote desktop sessions on slow internet connections.
|
||||
| -delay_restart 5 | Restart PersistentWindows in 5 seconds. This option should only be used in case normal start of PersistentWindows fails.
|
||||
| -delay_auto_capture 1.0 | Adjust the lag between window move event and auto-capture to 1.0 second, the default lag is 3~4 seconds.
|
||||
| *-delay_auto_restore 2.5* | Adjust the lag between monitor on/off event and auto-restore to 2.5 seconds (the default lag is 1 second). This is in case the restore is incomplete or the monitor fails to go to sleep due to the restore starting too early.
|
||||
| -redraw_desktop | Redraw the whole desktop after a restore, in case some window workarea is not refreshed
|
||||
|
@ -22,13 +24,17 @@
|
|||
| -fix_offscreen_window=0 | Turn off auto correction of off-screen windows
|
||||
| -fix_unminimized_window=0 | Turn off auto restore of unminimized windows. Use this switch to avoid undesirable window shifting during window activation, which comes with Event id 9999 : "restore minimized window ...." in event viewer.
|
||||
|-auto_restore_new_display_session_from_db=0| Disable window restore from DB upon PC startup or switching display for the first time
|
||||
|-auto_restore_existing_window_to_last_capture=1 | Turn on auto restore existing window from last capture upon PW start
|
||||
|-auto_restore_new_window_to_last_capture=0 | Turn off auto restore new window to last killed position
|
||||
|-pos_match_threshold 80 | Auto correct new window position to last killed position within range of 80 pixels, default is 40
|
||||
| ‑auto_restore_missing_windows=1 | When restoring from disk, restore missing windows without prompting the user
|
||||
| ‑auto_restore_missing_windows=2 | At startup, automatically restore missing windows from disk. The user will be prompted before restoring each missing window
|
||||
| ‑auto_restore_missing_windows=3 | At startup, automatically restore missing windows from disk without prompting the user
|
||||
| -invoke_multi_window_process_only_once=0 | Launch an application multiple times when multiple windows of the same process need to be restored from the database.
|
||||
| -check_upgrade=0 | Disable the PersistentWindows upgrade check
|
||||
| -auto_upgrade=1 | Upgrade PersistentWindows automatically without user interaction
|
||||
|
||||
| -dump_window_position_history=0 | Disable window position history dump
|
||||
| -restore_snapshot "0" | restore snapshot 0 and exit. The range of snapshot id is [0-9a-z], as well as "~" or "`", the last two special ids represent the last auto restore. Note the window z-order can not be fully retored using this method, due to lack of capability to do multi-pass restore.
|
||||
---
|
||||
|
||||
### Shortcuts to capture/restore snapshots
|
||||
|
@ -54,7 +60,6 @@
|
|||
|
||||
* Dual Position Switching functionality:
|
||||
* Click the desktop window to bring the foreground window to its previous background position and Z-order.
|
||||
* Shift + Click the desktop window to bring the foreground window to its *second* last background position. This is useful if the previous background position is mis-captured due to invoking start menu or other popups.
|
||||
* Ctrl + Click the desktop window to bring the foreground window to its previous Z-order while keeping the current location and size.
|
||||
|
||||
* To cancel Dual Position Switching:
|
||||
|
@ -110,7 +115,8 @@
|
|||
| Alt + click commander window || send the mouse click to the underlying browser window
|
||||
|
||||
### Other features
|
||||
* To replace the default app icon with your customized one:
|
||||
* Rename your .ico (or .png) file as `pwIcon.ico` (or `pwIcon.png`) and copy it to the PersistentWindows program folder, or alternatively to `C:/Users/<YOUR_ID>/AppData/Local/PersistentWindows/`.
|
||||
* Copy another icon file to the same directory and rename it to `pwIconBusy.*`. This icon is displayed when PersistentWindows is busy restoring windows.
|
||||
* To replace the default app icons with customized one:
|
||||
* Rename customized .ico (or .png) file as `pwIcon.ico` (or `pwIcon.png`) and copy it to the PersistentWindows program folder, or alternatively to `C:/Users/<YOUR_ID>/AppData/Local/PersistentWindows/`.
|
||||
* Copy another ico/png file to the same directory and rename it to `pwIconBusy.*`. This icon is displayed when PersistentWindows is busy restoring windows.
|
||||
* Copy yet another ico/png file to the same directory and rename it to `pwIconUpdate.*`. This icon is displayed when a new PersistentWindows release is available.
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
|
@ -93,21 +94,9 @@
|
|||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="DbKeySelect.resx">
|
||||
<DependentUpon>DbKeySelect.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="HotKeyWindow.resx">
|
||||
<DependentUpon>HotKeyWindow.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="LayoutProfile.resx">
|
||||
<DependentUpon>LayoutProfile.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="LaunchProcess.resx">
|
||||
<DependentUpon>LaunchProcess.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="NameDbKey.resx">
|
||||
<DependentUpon>NameDbKey.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
|
|
|
@ -1,120 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
|
@ -6,7 +6,6 @@ using System.Data;
|
|||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
|
@ -21,25 +20,30 @@ namespace PersistentWindows.Common
|
|||
private uint hotkey;
|
||||
|
||||
public static IntPtr commanderWnd = IntPtr.Zero;
|
||||
public static bool invokedFromBrowser = false;
|
||||
|
||||
private static System.Timers.Timer aliveTimer;
|
||||
private static int callerAliveTimer = -1; //for tracing the starting source of alive timer
|
||||
|
||||
private System.Timers.Timer mouseScrollDelayTimer;
|
||||
private bool init = true;
|
||||
private bool active = false;
|
||||
private static bool tiny = false;
|
||||
private static bool browserWindowActivated = false;
|
||||
private static bool restoring = false;
|
||||
private int origWidth;
|
||||
private int origHeight;
|
||||
private int mouseOffset = 0;
|
||||
private int mouseOffset = 0; //mouse dithering to workaround mouse location mis-update issue in rdp session
|
||||
private static POINT lastCursorPos;
|
||||
private POINT lastWheelCursorPos;
|
||||
private bool handCursor = false;
|
||||
private bool ibeamCursor = false;
|
||||
private int titleHeight;
|
||||
private static int callerAliveTimer = -1; //for tracing the starting source of alive timer
|
||||
private Color dfltBackColor;
|
||||
private bool promptZkey = true;
|
||||
private bool clickThrough = false;
|
||||
private bool defocused = false;
|
||||
private int totalWaitSecondsForWhiteColor = 0;
|
||||
|
||||
public HotKeyWindow(uint hkey)
|
||||
{
|
||||
|
@ -203,6 +207,7 @@ namespace PersistentWindows.Common
|
|||
Visible = false;
|
||||
IntPtr fgwnd = GetForegroundWindow();
|
||||
User32.SetForegroundWindow(fgwnd);
|
||||
FgSleep();
|
||||
|
||||
if (alt_key_pressed || clickThrough)
|
||||
{
|
||||
|
@ -273,7 +278,7 @@ namespace PersistentWindows.Common
|
|||
StartAliveTimer(1);
|
||||
}
|
||||
|
||||
bool IsBrowserWindow(IntPtr hwnd)
|
||||
private bool IsBrowserWindow(IntPtr hwnd)
|
||||
{
|
||||
return PersistentWindowProcessor.IsBrowserWindow(hwnd);
|
||||
}
|
||||
|
@ -591,9 +596,16 @@ namespace PersistentWindows.Common
|
|||
{
|
||||
if (!from_menu)
|
||||
{
|
||||
IntPtr fgwnd = GetForegroundWindow();
|
||||
if (!IsBrowserWindow(fgwnd))
|
||||
IntPtr fgwnd = GetForegroundWindow(strict : true);
|
||||
if (fgwnd == commanderWnd)
|
||||
fgwnd = GetForegroundWindow();
|
||||
if (IsBrowserWindow(fgwnd))
|
||||
{
|
||||
invokedFromBrowser = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
invokedFromBrowser = false;
|
||||
//forward hotkey
|
||||
char c = Convert.ToChar(hotkey);
|
||||
string cmd = $"%{c}";
|
||||
|
@ -629,13 +641,18 @@ namespace PersistentWindows.Common
|
|||
active = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static void BrowserActivate(IntPtr hwnd, bool is_browser_window = true)
|
||||
public static void BrowserActivate(IntPtr hwnd, bool is_browser_window = true, bool in_restore = false)
|
||||
{
|
||||
if (browserWindowActivated == is_browser_window)
|
||||
return;
|
||||
|
||||
browserWindowActivated = is_browser_window;
|
||||
restoring = in_restore;
|
||||
|
||||
Console.WriteLine($"browser activated {hwnd.ToString("X")}");
|
||||
|
||||
if (!tiny && !User32.IsWindowVisible(commanderWnd))
|
||||
return;
|
||||
|
@ -715,7 +732,7 @@ namespace PersistentWindows.Common
|
|||
return result;
|
||||
}
|
||||
|
||||
private bool IsSimilarColor(IntPtr hwnd, int x, int y, int xsize, int ysize)
|
||||
private bool IsSimilarColor(IntPtr hwnd, int x, int y, int xsize, int ysize, Color px)
|
||||
{
|
||||
using (Bitmap screenPixel = new Bitmap(xsize, ysize))
|
||||
{
|
||||
|
@ -731,20 +748,16 @@ namespace PersistentWindows.Common
|
|||
}
|
||||
}
|
||||
|
||||
var p1 = screenPixel.GetPixel(0, 0);
|
||||
var p2 = screenPixel.GetPixel(xsize - 1, 0);
|
||||
Console.WriteLine($"pixel ({x}, {y}) {p1}");
|
||||
for (int i = 1; i < xsize; ++i)
|
||||
Console.WriteLine($"pixel ({x}, {y}) {px}");
|
||||
for (int i = 0; i < xsize; ++i)
|
||||
{
|
||||
Color p = screenPixel.GetPixel(i, i);
|
||||
if (DiffColor(p, p1) > 10)
|
||||
if (DiffColor(p, px) > 15)
|
||||
return false;
|
||||
p1 = p;
|
||||
|
||||
p = screenPixel.GetPixel(xsize - i - 1, i);
|
||||
if (DiffColor(p, p2) > 10)
|
||||
if (DiffColor(p, px) > 15)
|
||||
return false;
|
||||
p2 = p;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -783,6 +796,37 @@ namespace PersistentWindows.Common
|
|||
}
|
||||
}
|
||||
|
||||
private bool IsSameColor(IntPtr hwnd, int x, int y, int xsize, int ysize, Color px)
|
||||
{
|
||||
using (Bitmap screenPixel = new Bitmap(xsize, ysize))
|
||||
{
|
||||
using (Graphics gdest = Graphics.FromImage(screenPixel))
|
||||
{
|
||||
using (Graphics gsrc = Graphics.FromHwnd(hwnd))
|
||||
{
|
||||
IntPtr hsrcdc = gsrc.GetHdc();
|
||||
IntPtr hdc = gdest.GetHdc();
|
||||
Gdi32.BitBlt(hdc, 0, 0, xsize, ysize, hsrcdc, x, y, (int)CopyPixelOperation.SourceCopy);
|
||||
gdest.ReleaseHdc();
|
||||
gsrc.ReleaseHdc();
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine($"pixel ({x}, {y}) {px}");
|
||||
for (int i = 0; i < xsize; ++i)
|
||||
{
|
||||
var p = screenPixel.GetPixel(i, i);
|
||||
if (p.ToArgb() != px.ToArgb())
|
||||
return false;
|
||||
p = screenPixel.GetPixel(xsize - i - 1, i);
|
||||
if (p.ToArgb() != px.ToArgb())
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private void AliveTimerCallBack(Object source, ElapsedEventArgs e)
|
||||
{
|
||||
if (!active)
|
||||
|
@ -793,12 +837,15 @@ namespace PersistentWindows.Common
|
|||
IntPtr fgwnd = GetForegroundWindow();
|
||||
if (!PersistentWindowProcessor.IsBrowserWindow(fgwnd))
|
||||
{
|
||||
if (browserWindowActivated)
|
||||
{
|
||||
if (browserWindowActivated || restoring)
|
||||
StartAliveTimer(6, 1000);
|
||||
return;
|
||||
}
|
||||
Visible = false;
|
||||
else
|
||||
Visible = false;
|
||||
return;
|
||||
}
|
||||
else if (restoring)
|
||||
{
|
||||
StartAliveTimer(6, 1000);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -823,7 +870,9 @@ namespace PersistentWindows.Common
|
|||
}
|
||||
else if (Math.Abs(cursorPos.X - lastCursorPos.X) > 3 || Math.Abs(cursorPos.Y - lastCursorPos.Y) > 3)
|
||||
{
|
||||
ibeamCursor = false;
|
||||
//mouse moving, continue monitor
|
||||
totalWaitSecondsForWhiteColor = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -831,39 +880,53 @@ namespace PersistentWindows.Common
|
|||
if (hCursor == Cursors.Default.Handle)
|
||||
{
|
||||
handCursor = false;
|
||||
if (!commanderWndUnderCursor && !IsSimilarColor(IntPtr.Zero, cursorPos.X - Width/2, cursorPos.Y - Height/2, 12, 12))
|
||||
|
||||
if (callerAliveTimer == 6)
|
||||
{
|
||||
// hide hotkey window to allow click through possible link
|
||||
Visible = false;
|
||||
clickThrough = true;
|
||||
//browser activation
|
||||
;
|
||||
}
|
||||
else if (!commanderWndUnderCursor && !IsUniColor(IntPtr.Zero, cursorPos.X - Width / 2, cursorPos.Y - Height / 2, 12, 12))
|
||||
{
|
||||
// shift commander window to allow click possible link
|
||||
Left = cursorPos.X - 10;
|
||||
Top = cursorPos.Y - 10;
|
||||
totalWaitSecondsForWhiteColor = 0;
|
||||
StartAliveTimer(11, 1000);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!commanderWndUnderCursor && !IsUniColor(IntPtr.Zero, cursorPos.X - Width / 2, cursorPos.Y - Height / 2, 12, 12))
|
||||
else if (!commanderWndUnderCursor && !IsSimilarColor(IntPtr.Zero, cursorPos.X - Width / 2, cursorPos.Y - Height / 2, 1, 1, Color.White))
|
||||
{
|
||||
Left = cursorPos.X - 10;
|
||||
Top = cursorPos.Y - 10;
|
||||
StartAliveTimer(11, 1000);
|
||||
return;
|
||||
// wait for possible menu selection within webpage
|
||||
++totalWaitSecondsForWhiteColor;
|
||||
if (Visible && totalWaitSecondsForWhiteColor < 3)
|
||||
{
|
||||
StartAliveTimer(11, 1000);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (hCursor == Cursors.IBeam.Handle)
|
||||
{
|
||||
ibeamCursor = true;
|
||||
Visible = false;
|
||||
StartAliveTimer(11, 1000);
|
||||
return;
|
||||
}
|
||||
else if (hCursor == Cursors.Cross.Handle || handCursor)
|
||||
{
|
||||
ibeamCursor = false;
|
||||
StartAliveTimer(7);
|
||||
return;
|
||||
}
|
||||
|
||||
totalWaitSecondsForWhiteColor = 0;
|
||||
|
||||
bool regain_focus = true;
|
||||
bool change_to_visible = false;
|
||||
if (!Visible)
|
||||
{
|
||||
Visible = true;
|
||||
change_to_visible = true;
|
||||
TopMost = true;
|
||||
if (defocused)
|
||||
{
|
||||
|
@ -871,7 +934,7 @@ namespace PersistentWindows.Common
|
|||
regain_focus = false;
|
||||
}
|
||||
}
|
||||
else if (!handCursor)
|
||||
else if (hCursor == Cursors.Default.Handle)
|
||||
{
|
||||
/*
|
||||
if (!commanderWndUnderCursor)
|
||||
|
@ -882,15 +945,29 @@ namespace PersistentWindows.Common
|
|||
*/
|
||||
regain_focus = !commanderWndUnderCursor;
|
||||
}
|
||||
else if (!handCursor)
|
||||
{
|
||||
regain_focus = false;
|
||||
}
|
||||
|
||||
if (ibeamCursor && hCursor == Cursors.Default.Handle)
|
||||
//&& Math.Abs(cursorPos.X - lastCursorPos.X) < 3 && Math.Abs(cursorPos.Y - lastCursorPos.Y) < 3)
|
||||
{
|
||||
ibeamCursor = false;
|
||||
StartAliveTimer(11, 1000);
|
||||
return;
|
||||
}
|
||||
|
||||
// let tiny hotkey window follow cursor position
|
||||
ResetHotKeyVirtualDesktop();
|
||||
ResetHotkeyWindowPos();
|
||||
if (change_to_visible)
|
||||
Visible = true;
|
||||
if (regain_focus)
|
||||
{
|
||||
User32.SetForegroundWindow(Handle);
|
||||
User32.SetFocus(Handle);
|
||||
}
|
||||
ResetHotkeyWindowPos();
|
||||
|
||||
if (hCursor == Cursors.Default.Handle)
|
||||
{
|
||||
|
@ -903,6 +980,7 @@ namespace PersistentWindows.Common
|
|||
// hand cursor shape
|
||||
if (!handCursor)
|
||||
{
|
||||
ibeamCursor = false;
|
||||
handCursor = true;
|
||||
Left -= 10;
|
||||
}
|
||||
|
@ -1054,9 +1132,9 @@ namespace PersistentWindows.Common
|
|||
User32.SetForegroundWindow(Handle);
|
||||
}
|
||||
|
||||
private static IntPtr GetForegroundWindow()
|
||||
public static IntPtr GetForegroundWindow(bool strict = false)
|
||||
{
|
||||
return PersistentWindowProcessor.GetForegroundWindow();
|
||||
return PersistentWindowProcessor.GetForegroundWindow(strict);
|
||||
}
|
||||
|
||||
private void FormSizeChanged(object sender, EventArgs e)
|
||||
|
|
|
@ -1,120 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
|
@ -1,120 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
|
@ -1,7 +1,10 @@
|
|||
using System;
|
||||
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
using PersistentWindows.Common.WinApiBridge;
|
||||
using PersistentWindows.Common.Diagnostics;
|
||||
|
||||
namespace PersistentWindows.Common.Models
|
||||
{
|
||||
|
@ -23,6 +26,8 @@ namespace PersistentWindows.Common.Models
|
|||
public bool IsFullScreen { get; set; }
|
||||
public bool IsMinimized { get; set; }
|
||||
public bool IsInvisible { get; set; }
|
||||
public long Style { get; set; }
|
||||
public long ExtStyle { get; set; }
|
||||
|
||||
// for restore window position to display session end time
|
||||
public DateTime CaptureTime { get; set; }
|
||||
|
@ -55,7 +60,15 @@ namespace PersistentWindows.Common.Models
|
|||
public override string ToString()
|
||||
{
|
||||
//return string.Format("{0}.{1} {2}", ProcessId, HWnd.ToString("X8"), ProcessName);
|
||||
return string.Format("{0}.{1:x8} {2}", ProcessId, HWnd.ToInt64(), ProcessName);
|
||||
//return string.Format("process:{0:x4} hwnd:{1:x6} {2}", ProcessId, HWnd.ToInt64(), ProcessName);
|
||||
DataContractSerializer dcs = new DataContractSerializer(typeof(ApplicationDisplayMetrics));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
using (XmlWriter xw = XmlWriter.Create(sb))
|
||||
{
|
||||
dcs.WriteObject(xw, this);
|
||||
}
|
||||
string xml = sb.ToString();
|
||||
return xml;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,120 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
|
@ -41,6 +41,7 @@ namespace PersistentWindows.Common.WinApiBridge
|
|||
EVENT_SYSTEM_IME_KEY_NOTIFICATION = 0x0029,
|
||||
EVENT_SYSTEM_END = 0x00FF,
|
||||
|
||||
EVENT_OBJECT_CREATE = 0x8000,
|
||||
EVENT_OBJECT_DESTROY = 0x8001,
|
||||
EVENT_OBJECT_REORDER = 0x8004,
|
||||
EVENT_OBJECT_LOCATIONCHANGE = 0x800B,
|
||||
|
@ -623,6 +624,9 @@ namespace PersistentWindows.Common.WinApiBridge
|
|||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern bool CloseHandle(IntPtr hHandle);
|
||||
|
||||
[DllImport("kernel32")]
|
||||
public static extern UInt64 GetTickCount64();
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern IntPtr OpenProcess(
|
||||
ProcessAccessFlags processAccess,
|
||||
|
|
|
@ -28,6 +28,10 @@ namespace PersistentWindows.Common.WinApiBridge
|
|||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format($"({X}, {Y})");
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
|
@ -57,5 +61,11 @@ namespace PersistentWindows.Common.WinApiBridge
|
|||
{
|
||||
return string.Format("({0}, {1}), {2} x {3}", Left, Top, Width, Height);
|
||||
}
|
||||
|
||||
public int Diff(RECT r)
|
||||
{
|
||||
int diff = Math.Abs(Left - r.Left) + Math.Abs(Right - r.Right) + Math.Abs(Top - r.Top) + Math.Abs(Bottom - r.Bottom);
|
||||
return diff / 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
using System;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
using PersistentWindows.Common;
|
||||
using PersistentWindows.Common.WinApiBridge;
|
||||
|
@ -10,6 +12,7 @@ namespace PersistentWindows.SystrayShell
|
|||
{
|
||||
public class HotKeyForm : Form
|
||||
{
|
||||
static bool init = true;
|
||||
static HotKeyWindow hkwin = null;
|
||||
static Thread messageLoop;
|
||||
|
||||
|
@ -60,9 +63,42 @@ namespace PersistentWindows.SystrayShell
|
|||
User32.KeyModifier modifier = (User32.KeyModifier)((int)m.LParam & 0xFFFF); // The modifier of the hotkey that was pressed.
|
||||
int id = m.WParam.ToInt32(); // The id of the hotkey that was pressed.
|
||||
|
||||
Program.HideRestoreTip(false); //hide icon
|
||||
Program.HideRestoreTip(); //show icon
|
||||
IntPtr fgWnd = PersistentWindowProcessor.GetForegroundWindow(strict : true);
|
||||
hkwin.HotKeyPressed(from_menu : false);
|
||||
if (PersistentWindowProcessor.IsBrowserWindow(fgWnd))
|
||||
{
|
||||
Program.HideRestoreTip(false); //hide icon
|
||||
Program.HideRestoreTip(); //show icon
|
||||
|
||||
if (init)
|
||||
{
|
||||
init = false;
|
||||
string webpage_commander_notification = Path.Combine(Program.AppdataFolder, "webpage_commander_notification");
|
||||
if (File.Exists(webpage_commander_notification))
|
||||
{
|
||||
Program.systrayForm.notifyIconMain.ShowBalloonTip(8000, "webpage commander is invoked via hotkey", "Press the hotkey (Alt + W) again to revoke", ToolTipIcon.Info);
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Create(webpage_commander_notification);
|
||||
|
||||
uint processId;
|
||||
User32.GetWindowThreadProcessId(fgWnd, out processId);
|
||||
string procPath = PersistentWindowProcessor.GetProcExePath(processId);
|
||||
Process.Start(procPath, Program.ProjectUrl + "/blob/master/webpage_commander.md");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex.ToString());
|
||||
Program.systrayForm.notifyIconMain.ShowBalloonTip(8000, "webpage commander is invoked via hotkey", "Press the hotkey (Alt + W) again to revoke", ToolTipIcon.Info);
|
||||
Process.Start(Program.ProjectUrl + "/blob/master/webpage_commander.md");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else if (m.Msg == 0x0010 || m.Msg == 0x0002)
|
||||
|
|
|
@ -21,15 +21,21 @@ namespace PersistentWindows.SystrayShell
|
|||
public static System.Drawing.Icon BusyIcon = null;
|
||||
public static System.Drawing.Icon UpdateIcon = null;
|
||||
public static string AppdataFolder = null;
|
||||
public static string DisableWebpageCommander = null;
|
||||
public static string DisableUpgradeNotice = null;
|
||||
public static string CmdArgs;
|
||||
public static bool Gui = true;
|
||||
public static bool hotkey_window = true;
|
||||
public static uint hotkey = 'W'; //Alt + W
|
||||
public static string WaitPwFinish = @":wait_to_finish
|
||||
timeout /t 2 /nobreak >nul
|
||||
tasklist | find ""PersistentWindows"" >nul
|
||||
if not errorlevel 1 goto wait_to_finish";
|
||||
|
||||
private const int MaxSnapshots = 38; // 0-9, a-z, ` and final one for undo
|
||||
|
||||
static PersistentWindowProcessor pwp = null;
|
||||
static SystrayForm systrayForm = null;
|
||||
public static PersistentWindowProcessor pwp = null;
|
||||
public static SystrayForm systrayForm = null;
|
||||
static bool silent = false; //suppress all balloon tip & sound prompt
|
||||
static bool notification = false; //pop balloon when auto restore
|
||||
static int delay_manual_capture = 5000; //in millisecond
|
||||
|
@ -50,9 +56,18 @@ namespace PersistentWindows.SystrayShell
|
|||
|
||||
pwp = new PersistentWindowProcessor();
|
||||
|
||||
var process = Process.GetCurrentProcess();
|
||||
pwp.processPriority = process.PriorityClass;
|
||||
process.PriorityClass = ProcessPriorityClass.High;
|
||||
var timer = new System.Threading.Timer(state =>
|
||||
{
|
||||
process.PriorityClass = pwp.processPriority;
|
||||
});
|
||||
timer.Change(10000, System.Threading.Timeout.Infinite);
|
||||
|
||||
bool splash = true;
|
||||
int delay_start = 0;
|
||||
bool relaunch = false;
|
||||
int delay_restart = 0;
|
||||
int relaunch_delay = 0;
|
||||
int delay_manual_capture = 0;
|
||||
int delay_auto_capture = 0;
|
||||
bool redirect_appdata = false; // use "." instead of appdata/local/PersistentWindows to store db file
|
||||
|
@ -68,13 +83,16 @@ namespace PersistentWindows.SystrayShell
|
|||
bool offscreen_fix = true;
|
||||
bool fix_unminimized_window = true;
|
||||
bool enhanced_offscreen_fix = false;
|
||||
bool set_pos_match_threshold = false;
|
||||
bool auto_restore_missing_windows = false;
|
||||
bool auto_restore_from_db_at_startup = false;
|
||||
bool auto_restore_last_capture_at_startup = false;
|
||||
bool launch_once_per_process_id = true;
|
||||
bool check_upgrade = true;
|
||||
bool auto_upgrade = false;
|
||||
bool legacy_icon = false;
|
||||
bool waiting_taskbar = false;
|
||||
int restore_snapshot = -1;
|
||||
|
||||
foreach (var arg in args)
|
||||
{
|
||||
|
@ -86,13 +104,12 @@ namespace PersistentWindows.SystrayShell
|
|||
pwp.haltRestore = (Int32)(float.Parse(arg) * 1000);
|
||||
continue;
|
||||
}
|
||||
else if (delay_start != 0)
|
||||
else if (delay_restart != 0)
|
||||
{
|
||||
delay_start = 0;
|
||||
delay_restart = 0;
|
||||
if (!waiting_taskbar)
|
||||
{
|
||||
Thread.Sleep((Int32)(float.Parse(arg) * 1000));
|
||||
relaunch = true;
|
||||
relaunch_delay = (Int32)(float.Parse(arg));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -131,6 +148,17 @@ namespace PersistentWindows.SystrayShell
|
|||
hotkey = arg[0];
|
||||
continue;
|
||||
}
|
||||
else if (restore_snapshot != -1)
|
||||
{
|
||||
restore_snapshot = SnapshotCharToId(arg[0]);
|
||||
continue;
|
||||
}
|
||||
else if (set_pos_match_threshold)
|
||||
{
|
||||
set_pos_match_threshold = false;
|
||||
pwp.MaxDiffPos = int.Parse(arg);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(arg)
|
||||
{
|
||||
|
@ -153,8 +181,11 @@ namespace PersistentWindows.SystrayShell
|
|||
case "-enable_auto_restore_by_manual_capture":
|
||||
pwp.manualNormalSession = true;
|
||||
break;
|
||||
case "-delay_start":
|
||||
delay_start = 1;
|
||||
case "-fast_restore=0":
|
||||
pwp.fastRestore = false;
|
||||
break;
|
||||
case "-delay_restart":
|
||||
delay_restart = 1;
|
||||
break;
|
||||
case "-wait_taskbar":
|
||||
waiting_taskbar = true;
|
||||
|
@ -165,6 +196,9 @@ namespace PersistentWindows.SystrayShell
|
|||
case "-delay_auto_capture":
|
||||
delay_auto_capture = 1;
|
||||
break;
|
||||
case "-capture_floating_window=0":
|
||||
pwp.captureFloatingWindow = false;
|
||||
break;
|
||||
case "-dpi_sensitive_call=1":
|
||||
User32.DpiSenstiveCall = true;
|
||||
break;
|
||||
|
@ -199,7 +233,10 @@ namespace PersistentWindows.SystrayShell
|
|||
fix_unminimized_window = false;
|
||||
break;
|
||||
case "-fix_taskbar=0":
|
||||
pwp.fixTaskBar = false;
|
||||
pwp.fixTaskBar = 0;
|
||||
break;
|
||||
case "-fix_taskbar_no_game":
|
||||
pwp.fixTaskBar = -1;
|
||||
break;
|
||||
case "-foreground_background_dual_position=0":
|
||||
pwp.enableDualPosSwitch = false;
|
||||
|
@ -239,6 +276,15 @@ namespace PersistentWindows.SystrayShell
|
|||
case "-redraw_desktop":
|
||||
redraw_desktop = true;
|
||||
break;
|
||||
case "-auto_restore_existing_window_to_last_capture=1":
|
||||
auto_restore_last_capture_at_startup = true;
|
||||
break;
|
||||
case "-auto_restore_new_window_to_last_capture=0":
|
||||
pwp.autoRestoreNewWindowToLastCapture = false;
|
||||
break;
|
||||
case "-pos_match_threshold":
|
||||
set_pos_match_threshold = true;
|
||||
break;
|
||||
case "-auto_restore_missing_windows":
|
||||
case "-auto_restore_missing_windows=1":
|
||||
auto_restore_missing_windows = true;
|
||||
|
@ -251,7 +297,7 @@ namespace PersistentWindows.SystrayShell
|
|||
auto_restore_missing_windows = true;
|
||||
break;
|
||||
case "-auto_restore_new_display_session_from_db=0":
|
||||
pwp.autoRestoreLiveWindows = false;
|
||||
pwp.autoRestoreLiveWindowsFromDb = false;
|
||||
Log.Error("turn off auto restore db for new session");
|
||||
break;
|
||||
case "-invoke_multi_window_process_only_once=0":
|
||||
|
@ -263,9 +309,21 @@ namespace PersistentWindows.SystrayShell
|
|||
case "-auto_upgrade=1":
|
||||
auto_upgrade = true;
|
||||
break;
|
||||
case "-dump_window_position_history=0":
|
||||
pwp.dumpHistoryData = false;
|
||||
break;
|
||||
case "-restore_snapshot":
|
||||
restore_snapshot = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (restore_snapshot >= 0)
|
||||
{
|
||||
pwp.RestoreSnapshotCmd(restore_snapshot);
|
||||
return;
|
||||
}
|
||||
|
||||
string productName = System.Windows.Forms.Application.ProductName;
|
||||
string appDataFolder = redirect_appdata ? "." :
|
||||
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
|
||||
|
@ -278,11 +336,18 @@ namespace PersistentWindows.SystrayShell
|
|||
#endif
|
||||
AppdataFolder = appDataFolder;
|
||||
|
||||
if (!Directory.Exists(appDataFolder))
|
||||
Directory.CreateDirectory(appDataFolder);
|
||||
|
||||
DisableWebpageCommander = Path.Combine(AppdataFolder, "disable_webpage_commander");
|
||||
DisableUpgradeNotice = Path.Combine(AppdataFolder, "disable_upgrade_notice");
|
||||
|
||||
// default icons
|
||||
IdleIcon = legacy_icon ? Properties.Resources.pwIcon2 : Properties.Resources.pwIcon;
|
||||
var iconHandle = Properties.Resources.pwIconBusy.GetHicon();
|
||||
BusyIcon = legacy_icon ? Properties.Resources.pwIconBusy2 : System.Drawing.Icon.FromHandle(iconHandle);
|
||||
iconHandle = Properties.Resources.pwIconUpdate.GetHicon();
|
||||
var iconHandle = (legacy_icon ? Properties.Resources.pwIcon2: Properties.Resources.pwIcon).GetHicon();
|
||||
IdleIcon = System.Drawing.Icon.FromHandle(iconHandle);
|
||||
iconHandle = (legacy_icon ? Properties.Resources.pwIconBusy2 : Properties.Resources.pwIconBusy).GetHicon();
|
||||
BusyIcon = System.Drawing.Icon.FromHandle(iconHandle);
|
||||
iconHandle = (legacy_icon ? Properties.Resources.pwIconUpdate2 : Properties.Resources.pwIconUpdate).GetHicon();
|
||||
UpdateIcon = System.Drawing.Icon.FromHandle(iconHandle);
|
||||
|
||||
// customized icon/png
|
||||
|
@ -291,38 +356,49 @@ namespace PersistentWindows.SystrayShell
|
|||
if (i == 1)
|
||||
iconFolder = AppDomain.CurrentDomain.BaseDirectory;
|
||||
|
||||
string icon_path = Path.Combine(iconFolder, "pwIcon.ico");
|
||||
string icon_png_path = Path.Combine(iconFolder, "pwIcon.png");
|
||||
if (File.Exists(icon_png_path))
|
||||
string ico_path = Path.Combine(iconFolder, "pwIcon.ico");
|
||||
string png_path = Path.Combine(iconFolder, "pwIcon.png");
|
||||
if (File.Exists(png_path))
|
||||
{
|
||||
var bitmap = new System.Drawing.Bitmap(icon_png_path); // or get it from resource
|
||||
var bitmap = new System.Drawing.Bitmap(png_path);
|
||||
IdleIcon = System.Drawing.Icon.FromHandle(bitmap.GetHicon());
|
||||
}
|
||||
else if (File.Exists(icon_path))
|
||||
else if (File.Exists(ico_path))
|
||||
{
|
||||
IdleIcon = new System.Drawing.Icon(icon_path);
|
||||
IdleIcon = new System.Drawing.Icon(ico_path);
|
||||
}
|
||||
|
||||
icon_path = Path.Combine(iconFolder, "pwIconBusy.ico");
|
||||
icon_png_path = Path.Combine(iconFolder, "pwIconBusy.png");
|
||||
if (File.Exists(icon_png_path))
|
||||
ico_path = Path.Combine(iconFolder, "pwIconBusy.ico");
|
||||
png_path = Path.Combine(iconFolder, "pwIconBusy.png");
|
||||
if (File.Exists(png_path))
|
||||
{
|
||||
var bitmap = new System.Drawing.Bitmap(icon_png_path);
|
||||
var bitmap = new System.Drawing.Bitmap(png_path);
|
||||
BusyIcon = System.Drawing.Icon.FromHandle(bitmap.GetHicon());
|
||||
}
|
||||
else if (File.Exists(icon_path))
|
||||
else if (File.Exists(ico_path))
|
||||
{
|
||||
BusyIcon = new System.Drawing.Icon(icon_path);
|
||||
BusyIcon = new System.Drawing.Icon(ico_path);
|
||||
}
|
||||
|
||||
ico_path = Path.Combine(iconFolder, "pwIconUpdate.ico");
|
||||
png_path = Path.Combine(iconFolder, "pwIconUpdate.png");
|
||||
if (File.Exists(png_path))
|
||||
{
|
||||
var bitmap = new System.Drawing.Bitmap(png_path);
|
||||
UpdateIcon = System.Drawing.Icon.FromHandle(bitmap.GetHicon());
|
||||
}
|
||||
else if (File.Exists(ico_path))
|
||||
{
|
||||
UpdateIcon = new System.Drawing.Icon(ico_path);
|
||||
}
|
||||
}
|
||||
|
||||
systrayForm = new SystrayForm();
|
||||
systrayForm.enableUpgradeNotice = check_upgrade;
|
||||
systrayForm = new SystrayForm(check_upgrade);
|
||||
systrayForm.autoUpgrade = auto_upgrade;
|
||||
|
||||
if (relaunch)
|
||||
if (relaunch_delay > 0)
|
||||
{
|
||||
Restart(2);
|
||||
Restart(relaunch_delay);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -363,10 +439,10 @@ namespace PersistentWindows.SystrayShell
|
|||
if (ignore_process.Length > 0)
|
||||
pwp.SetIgnoreProcess(ignore_process);
|
||||
|
||||
if (hotkey_window)
|
||||
if (!File.Exists(DisableWebpageCommander) && hotkey_window)
|
||||
HotKeyForm.Start(hotkey);
|
||||
|
||||
if (!pwp.Start(auto_restore_from_db_at_startup))
|
||||
if (!pwp.Start(auto_restore_from_db_at_startup, auto_restore_last_capture_at_startup))
|
||||
{
|
||||
systrayForm.notifyIconMain.Visible = false;
|
||||
return;
|
||||
|
@ -401,17 +477,25 @@ namespace PersistentWindows.SystrayShell
|
|||
Log.Error("taskbar not ready, restart PersistentWindows");
|
||||
}
|
||||
|
||||
Restart(10);
|
||||
Restart(1);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void Restart(int delay)
|
||||
static public void Restart(int delay, bool hidden = true)
|
||||
{
|
||||
Process p = new Process();
|
||||
string batFile = Path.Combine(AppdataFolder, $"pw_restart.bat");
|
||||
string content = $"timeout /t {delay} /nobreak > NUL";
|
||||
string content = WaitPwFinish;
|
||||
content += $"\ntimeout /t {delay} /nobreak > NUL";
|
||||
content += "\nstart \"\" /B \"" + Path.Combine(Application.StartupPath, Application.ProductName) + ".exe\" " + "-wait_taskbar " + Program.CmdArgs;
|
||||
File.WriteAllText(batFile, content);
|
||||
Process.Start(batFile);
|
||||
p.StartInfo.FileName = batFile;
|
||||
if (hidden)
|
||||
{
|
||||
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
||||
p.StartInfo.UseShellExecute = true;
|
||||
}
|
||||
p.Start();
|
||||
|
||||
Log.Error("program restarted");
|
||||
}
|
||||
|
@ -426,7 +510,9 @@ namespace PersistentWindows.SystrayShell
|
|||
else
|
||||
{
|
||||
NotifyIcon ni = systrayForm.notifyIconMain;
|
||||
ni.Icon = BusyIcon;
|
||||
if (!systrayForm.toggleIcon) {
|
||||
ni.Icon = BusyIcon;
|
||||
}
|
||||
|
||||
if (silent)
|
||||
return;
|
||||
|
@ -451,7 +537,10 @@ namespace PersistentWindows.SystrayShell
|
|||
else
|
||||
{
|
||||
NotifyIcon ni = systrayForm.notifyIconMain;
|
||||
ni.Icon = IdleIcon;
|
||||
if (!systrayForm.toggleIcon)
|
||||
{
|
||||
ni.Icon = IdleIcon;
|
||||
}
|
||||
|
||||
if (Gui)
|
||||
{
|
||||
|
@ -775,5 +864,14 @@ namespace PersistentWindows.SystrayShell
|
|||
Log.Error(format, args);
|
||||
}
|
||||
|
||||
public static void WriteDataDump()
|
||||
{
|
||||
pwp.WriteDataDump();
|
||||
}
|
||||
|
||||
public static void Stop()
|
||||
{
|
||||
pwp.Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
|
|||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("5.56.*")]
|
||||
[assembly: AssemblyVersion("5.65.*")]
|
||||
|
||||
|
|
|
@ -61,22 +61,22 @@ namespace PersistentWindows.SystrayShell.Properties {
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Icon pwIcon {
|
||||
internal static System.Drawing.Bitmap pwIcon {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("pwIcon", resourceCulture);
|
||||
return ((System.Drawing.Icon)(obj));
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Icon pwIcon2 {
|
||||
internal static System.Drawing.Bitmap pwIcon2 {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("pwIcon2", resourceCulture);
|
||||
return ((System.Drawing.Icon)(obj));
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,12 +91,12 @@ namespace PersistentWindows.SystrayShell.Properties {
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Icon pwIconBusy2 {
|
||||
internal static System.Drawing.Bitmap pwIconBusy2 {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("pwIconBusy2", resourceCulture);
|
||||
return ((System.Drawing.Icon)(obj));
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,6 +110,16 @@ namespace PersistentWindows.SystrayShell.Properties {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap pwIconUpdate2 {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("pwIconUpdate2", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
|
|
|
@ -119,20 +119,23 @@
|
|||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="pwIcon" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\pwIcon.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
<value>..\Resources\pwIcon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="pwIcon2" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\pwIcon2.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
<value>..\Resources\pwIcon2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="pwIconBusy" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\pwIconBusy.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="pwIconBusy2" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\pwIconBusy2.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
<value>..\Resources\pwIconBusy2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="pwIconUpdate" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\pwIconUpdate.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="pwIconUpdate2" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\pwIconUpdate2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="question" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\question.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
|
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 66 KiB |
After Width: | Height: | Size: 5.9 KiB |
Before Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 14 KiB |
|
@ -1,123 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="timer1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
</root>
|
|
@ -168,10 +168,6 @@ namespace PersistentWindows.SystrayShell
|
|||
// pause/resume upgrade notice
|
||||
//this.upgradeNoticeMenuItem.Text = "Disable upgrade notice";
|
||||
this.upgradeNoticeMenuItem.Click += new System.EventHandler(this.PauseResumeUpgradeNotice);
|
||||
if (this.enableUpgradeNotice)
|
||||
this.upgradeNoticeMenuItem.Text = "Disable upgrade notice";
|
||||
else
|
||||
this.upgradeNoticeMenuItem.Text = "Enable upgrade notice";
|
||||
|
||||
//
|
||||
// exitToolStripMenuItem
|
||||
|
|
|
@ -17,16 +17,11 @@ namespace PersistentWindows.SystrayShell
|
|||
{
|
||||
private const int MaxSnapshots = 38; // 0-9, a-z, ` and final one for undo
|
||||
|
||||
public bool restoreToolStripMenuItemEnabled;
|
||||
public bool restoreSnapshotMenuItemEnabled;
|
||||
|
||||
private bool pauseAutoRestore = false;
|
||||
private bool toggleIcon = false;
|
||||
public bool toggleIcon = false;
|
||||
|
||||
public bool enableUpgradeNotice = true;
|
||||
private int skipUpgradeCounter = 0;
|
||||
private bool pauseUpgradeCounter = false;
|
||||
private bool foundUpgrade = false;
|
||||
|
||||
public bool autoUpgrade = false;
|
||||
|
||||
|
@ -43,10 +38,25 @@ namespace PersistentWindows.SystrayShell
|
|||
|
||||
private Dictionary<string, bool> upgradeDownloaded = new Dictionary<string, bool>();
|
||||
|
||||
public SystrayForm()
|
||||
public SystrayForm(bool enable_upgrade_notice)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
if (File.Exists(Program.DisableUpgradeNotice))
|
||||
upgradeNoticeMenuItem.Text = "Enable upgrade notice";
|
||||
else if (!enable_upgrade_notice)
|
||||
{
|
||||
File.Create(Program.DisableUpgradeNotice);
|
||||
upgradeNoticeMenuItem.Text = "Enable upgrade notice";
|
||||
}
|
||||
else
|
||||
upgradeNoticeMenuItem.Text = "Disable upgrade notice";
|
||||
|
||||
if (File.Exists(Program.DisableWebpageCommander))
|
||||
{
|
||||
invokeWebCommander.Text = "Enable webpage commander";
|
||||
}
|
||||
|
||||
clickDelayTimer = new System.Timers.Timer(1000);
|
||||
clickDelayTimer.Elapsed += ClickTimerCallBack;
|
||||
clickDelayTimer.SynchronizingObject = this.contextMenuStripSysTray;
|
||||
|
@ -166,7 +176,6 @@ namespace PersistentWindows.SystrayShell
|
|||
ctrlKeyPressed = 0;
|
||||
shiftKeyPressed = 0;
|
||||
altKeyPressed = 0;
|
||||
|
||||
}
|
||||
|
||||
//private void TimerEventProcessor(Object myObject, EventArgs myEventArgs)
|
||||
|
@ -177,7 +186,7 @@ namespace PersistentWindows.SystrayShell
|
|||
else
|
||||
restoreToolStripMenuItem.Image = Properties.Resources.question;
|
||||
|
||||
if (checkUpgrade && enableUpgradeNotice)
|
||||
if (checkUpgrade && upgradeNoticeMenuItem.Text.Contains("Disable"))
|
||||
{
|
||||
if (pauseUpgradeCounter)
|
||||
{
|
||||
|
@ -239,10 +248,21 @@ namespace PersistentWindows.SystrayShell
|
|||
|| current_major == latest_major && current_minor < latest_minor)
|
||||
{
|
||||
notifyIconMain.ShowBalloonTip(5000, $"{Application.ProductName} {latestVersion} upgrade is available", "The upgrade notice can be disabled in menu", ToolTipIcon.Info);
|
||||
foundUpgrade = true;
|
||||
upgradeNoticeMenuItem.Text = $"Upgrade to {latestVersion}";
|
||||
|
||||
if (!upgradeDownloaded.ContainsKey(latestVersion))
|
||||
{
|
||||
string url = Program.ProjectUrl + "/releases";
|
||||
var os_version = Environment.OSVersion;
|
||||
if (os_version.Version.Major < 10)
|
||||
Process.Start(url);
|
||||
else if (os_version.Version.Build < 22000)
|
||||
Process.Start(url);
|
||||
/* windows 11
|
||||
else
|
||||
Process.Start(new ProcessStartInfo(url));
|
||||
*/
|
||||
|
||||
var src_file = $"{Program.ProjectUrl}/releases/download/{latestVersion}/{System.Windows.Forms.Application.ProductName}{latestVersion}.zip";
|
||||
var dst_file = $"{Program.AppdataFolder}/upgrade.zip";
|
||||
var dst_dir = Path.Combine($"{Program.AppdataFolder}", "upgrade");
|
||||
|
@ -256,7 +276,7 @@ namespace PersistentWindows.SystrayShell
|
|||
upgradeDownloaded[latestVersion] = true;
|
||||
|
||||
string batFile = Path.Combine(Program.AppdataFolder, $"pw_upgrade.bat");
|
||||
string content = "timeout /t 5 /nobreak > NUL";
|
||||
string content = Program.WaitPwFinish;
|
||||
content += $"\ncopy /Y \"{dst_dir}\\*.*\" \"{install_dir}\"";
|
||||
content += "\nstart \"\" /B \"" + Path.Combine(install_dir, Application.ProductName) + ".exe\" " + Program.CmdArgs;
|
||||
File.WriteAllText(batFile, content);
|
||||
|
@ -264,10 +284,7 @@ namespace PersistentWindows.SystrayShell
|
|||
if (autoUpgrade)
|
||||
Upgrade();
|
||||
else
|
||||
{
|
||||
upgradeNoticeMenuItem.Text = $"Upgrade to {latestVersion}";
|
||||
notifyIconMain.Icon = Program.UpdateIcon;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -275,15 +292,24 @@ namespace PersistentWindows.SystrayShell
|
|||
|
||||
private void Exit()
|
||||
{
|
||||
#if DEBUG
|
||||
var process = Process.GetCurrentProcess();
|
||||
process.PriorityClass = ProcessPriorityClass.High;
|
||||
|
||||
Program.WriteDataDump();
|
||||
Log.Event("Session exit");
|
||||
|
||||
this.notifyIconMain.Visible = false;
|
||||
#endif
|
||||
//this.notifyIconMain.Icon = null;
|
||||
|
||||
Log.Exit();
|
||||
Program.Stop();
|
||||
Application.Exit();
|
||||
}
|
||||
|
||||
private void Upgrade()
|
||||
{
|
||||
Program.WriteDataDump();
|
||||
|
||||
string batFile = Path.Combine(Program.AppdataFolder, "pw_upgrade.bat");
|
||||
Process.Start(batFile);
|
||||
Exit();
|
||||
|
@ -345,11 +371,21 @@ namespace PersistentWindows.SystrayShell
|
|||
HotKeyForm.InvokeFromMenu();
|
||||
else if (this.invokeWebCommander.Text.Contains("Disable"))
|
||||
{
|
||||
File.Create(Program.DisableWebpageCommander);
|
||||
this.invokeWebCommander.Text = "Enable webpage commander";
|
||||
HotKeyForm.Stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(Program.DisableWebpageCommander);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex.ToString());
|
||||
}
|
||||
|
||||
this.invokeWebCommander.Text = "Disable webpage commander";
|
||||
HotKeyForm.Start(Program.hotkey);
|
||||
}
|
||||
|
@ -394,20 +430,27 @@ namespace PersistentWindows.SystrayShell
|
|||
|
||||
private void PauseResumeUpgradeNotice(Object sender, EventArgs e)
|
||||
{
|
||||
if (foundUpgrade)
|
||||
if (upgradeNoticeMenuItem.Text.Contains("Upgrade to"))
|
||||
{
|
||||
Upgrade();
|
||||
}
|
||||
else if (enableUpgradeNotice)
|
||||
else if (upgradeNoticeMenuItem.Text.Contains("Enable"))
|
||||
{
|
||||
enableUpgradeNotice = false;
|
||||
upgradeNoticeMenuItem.Text = "Enable upgrade notice";
|
||||
}
|
||||
else
|
||||
{
|
||||
enableUpgradeNotice = true;
|
||||
upgradeNoticeMenuItem.Text = "Disable upgrade notice";
|
||||
CheckUpgradeSafe();
|
||||
try
|
||||
{
|
||||
File.Delete(Program.DisableUpgradeNotice);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex.ToString());
|
||||
}
|
||||
}
|
||||
else //menu is "Disable upgrade notice"
|
||||
{
|
||||
File.Create(Program.DisableUpgradeNotice);
|
||||
upgradeNoticeMenuItem.Text = "Enable upgrade notice";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -418,6 +461,9 @@ namespace PersistentWindows.SystrayShell
|
|||
|
||||
private void ExitToolStripMenuItemClickHandler(object sender, EventArgs e)
|
||||
{
|
||||
bool ctrl_key_pressed = (User32.GetKeyState(0x11) & 0x8000) != 0;
|
||||
if (ctrl_key_pressed)
|
||||
Program.Restart(2, hidden:false);
|
||||
Exit();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,127 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="notifyIconMain.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
<metadata name="contextMenuStripSysTray.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>150, 17</value>
|
||||
</metadata>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
</root>
|
|
@ -52,7 +52,9 @@
|
|||
</PropertyGroup>
|
||||
<PropertyGroup />
|
||||
<PropertyGroup />
|
||||
<PropertyGroup />
|
||||
<PropertyGroup>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
|
@ -84,19 +86,12 @@
|
|||
</Compile>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<EmbeddedResource Include="SplashForm.resx">
|
||||
<DependentUpon>SplashForm.cs</DependentUpon>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="SystrayForm.resx">
|
||||
<DependentUpon>SystrayForm.cs</DependentUpon>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<None Include="app.manifest" />
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
|
@ -131,12 +126,6 @@
|
|||
<ItemGroup>
|
||||
<None Include="Resources\pwIconUpdate.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\pwIcon2.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\pwIconBusy2.ico" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>copy $(SolutionDir)*.bat $(TargetDir)
|
||||
|
|
|
@ -28,16 +28,16 @@
|
|||
and Windows will automatically select the most compatible environment. -->
|
||||
|
||||
<!-- Windows Vista -->
|
||||
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />-->
|
||||
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />
|
||||
|
||||
<!-- Windows 7 -->
|
||||
<!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />-->
|
||||
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
|
||||
|
||||
<!-- Windows 8 -->
|
||||
<!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />-->
|
||||
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
|
||||
|
||||
<!-- Windows 8.1 -->
|
||||
<!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />-->
|
||||
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
|
||||
|
||||
<!-- Windows 10 -->
|
||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
||||
|
|
11
README.md
|
@ -11,10 +11,11 @@ and restores back to its previous settings.
|
|||
this tool and not have to worry about re-arranging when all is back to normal.
|
||||
|
||||
## Key Features
|
||||
- Keeps track of window position changes, and automatically restores the desktop layout, including the taskbar position, to the last matching monitor setup.
|
||||
- Auto restore: Keeps track of window position changes, and automatically restores the desktop layout, including the taskbar position, to the last matching monitor setup.
|
||||
- Supports remote desktop sessions with multiple display configurations.
|
||||
- Capture windows to disk: saves desktop layout capture to hard drive in liteDB format, so that closed windows can be restored after PC reboot, with virtual desktop observed.
|
||||
- Capture snapshot to ram: saves desktop layout in memory using one char from [0-9a-z] as the name. The window Z-order is preserved in the snapshot.
|
||||
- Capture windows to disk: manually saves desktop layout capture to hard drive in liteDB format, so that closed windows can be restored to corresponding virtual desktop after PC reboot.
|
||||
- Capture snapshot: manually saves desktop layout to ram. The window Z-order is preserved in the snapshot. Up to 36 snapshots ([0-9a-z]) can be taken for each display configuration.
|
||||
- Automatically persists the location history of all windows (alive and closed) to hard drive in xml format, so that manual-restore-point (aka snapshot) and auto-restore-point will continue to function smoothly upon app upgrade/restart, even after PC reboot.
|
||||
- Webpage commander to improve the efficiency of web browsing for all major web browsers using one-letter commands like in vi editor.
|
||||
- Efficient window switching between foreground and background dual positions.
|
||||
- Pause/resume auto restore.
|
||||
|
@ -28,11 +29,11 @@ this tool and not have to worry about re-arranging when all is back to normal.
|
|||
> Note: the program can be run from any directory, but the program saves its data in
|
||||
> *C:\Users\\[User]\AppData\Local\PersistentWindows*
|
||||
|
||||
**For PersistentWindows to be able to restore windows with elevated privileges (for tools like Task Manager or Event Viewer), it needs to be run with Administrator privileges.**
|
||||
|
||||
### To set up PersistentWindows to automatically start at user login:
|
||||
This can be done by creating a task in **Task Scheduler**, or by adding a shortcut to the **Startup Folder** (shell:startup).
|
||||
|
||||
For PersistentWindows to be able to restore windows with elevated privileges (for tools like Task Manager or Event Viewer), it needs to be run with Administrator privileges.
|
||||
|
||||
Choose **one** of the three options:
|
||||
|
||||
**Task Scheduler (Windows 10/11)**
|
||||
|
|
5
webpage_commander.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
|
||||
### Webpage commander window is invoked via hotkey (Alt + W)
|
||||
* If the invocation is unintentional, press the hotkey again to revoke webpage commander. The hotkey can be disabled via PW menu or command line.
|
||||
* Webpage commander improves the efficiency of web browsing using single-letter command shortcut.
|
||||
* Check out [Online Help](https://www.github.com/kangyu-california/PersistentWindows/blob/master/Help.md) for detailed instructions.
|