#41, #49, #68, #76, #78, version 0.9.2.22

This commit is contained in:
Markus Hofknecht 2020-04-15 17:23:42 +02:00
parent b887c25bb3
commit b13eb62f52
9 changed files with 125 additions and 116 deletions

View file

@ -8,7 +8,6 @@ using System.Linq;
using System.Security; using System.Security;
using System.Windows.Forms; using System.Windows.Forms;
using SystemTrayMenu.DataClasses; using SystemTrayMenu.DataClasses;
using SystemTrayMenu.DllImports;
using SystemTrayMenu.Handler; using SystemTrayMenu.Handler;
using SystemTrayMenu.Helper; using SystemTrayMenu.Helper;
using SystemTrayMenu.UserInterface; using SystemTrayMenu.UserInterface;
@ -27,7 +26,8 @@ namespace SystemTrayMenu
private readonly Screen screen = Screen.PrimaryScreen; private readonly Screen screen = Screen.PrimaryScreen;
private readonly WaitLeave waitLeave = new WaitLeave(MenuDefines.TimeUntilClose); private readonly WaitLeave waitLeave = new WaitLeave(MenuDefines.TimeUntilClose);
private readonly KeyboardInput keyboardInput; private readonly KeyboardInput keyboardInput;
private int clicksInQueue = 0; private readonly Timer timerStillActiveCheck = new Timer();
private DateTime deactivatedTime = DateTime.Now;
public SystemTrayMenu() public SystemTrayMenu()
{ {
@ -53,9 +53,10 @@ namespace SystemTrayMenu
menuNotifyIcon.HandleClick += SwitchOpenClose; menuNotifyIcon.HandleClick += SwitchOpenClose;
void SwitchOpenClose() void SwitchOpenClose()
{ {
if (string.IsNullOrEmpty(Config.Path)) if (string.IsNullOrEmpty(Config.Path) ||
(DateTime.Now - deactivatedTime).TotalMilliseconds < 300)
{ {
//Case when Folder Dialog open //Case when Folder Dialog open or restarts to fast
} }
else if (openCloseState == OpenCloseState.Opening || else if (openCloseState == OpenCloseState.Opening ||
menus[0].Visible && openCloseState == OpenCloseState.Default) menus[0].Visible && openCloseState == OpenCloseState.Default)
@ -71,27 +72,10 @@ namespace SystemTrayMenu
openCloseState = OpenCloseState.Default; openCloseState = OpenCloseState.Default;
} }
} }
else if (worker.IsBusy)
{
if (clicksInQueue < MenuDefines.MaxClicksInQueue)
{
clicksInQueue++;
while (worker.IsBusy)
{
Application.DoEvents();
}
clicksInQueue--;
SwitchOpenClose();
}
else
{
Log.Info("User is clicking too often => throw event away");
}
}
else else
{ {
openCloseState = OpenCloseState.Opening; openCloseState = OpenCloseState.Opening;
menuNotifyIcon.LoadingStart(); menuNotifyIcon.LoadingStart(true);
worker.RunWorkerAsync(); worker.RunWorkerAsync();
} }
} }
@ -114,15 +98,8 @@ namespace SystemTrayMenu
DisposeMenu(menus[0]); DisposeMenu(menus[0]);
menus[0] = CreateMenu(menuData, Path.GetFileName(Config.Path)); menus[0] = CreateMenu(menuData, Path.GetFileName(Config.Path));
menus[0].AdjustLocationAndSize(screen); menus[0].AdjustLocationAndSize(screen);
menus[0].Visible = false; // resets activated
menus[0].Visible = true; // resets activated
Menus().ToList().ForEach(m => { m.ShowWithFade(); }); Menus().ToList().ForEach(m => { m.ShowWithFade(); });
menus[0].Activate();
menus[0].SetTitleColorActive();
NativeMethods.ForceForegroundWindow(menus[0].Handle);
} }
openCloseState = OpenCloseState.Default;
} }
menuNotifyIcon.OpenLog += Log.OpenLogFile; menuNotifyIcon.OpenLog += Log.OpenLogFile;
@ -147,6 +124,7 @@ namespace SystemTrayMenu
keyboardInput.Dispose(); keyboardInput.Dispose();
menuNotifyIcon.Dispose(); menuNotifyIcon.Dispose();
waitLeave.Dispose(); waitLeave.Dispose();
timerStillActiveCheck.Dispose();
DisposeMenu(menus[0]); DisposeMenu(menus[0]);
IconReader.Dispose(); IconReader.Dispose();
} }
@ -422,20 +400,36 @@ namespace SystemTrayMenu
menu.Deactivate += Deactivate; menu.Deactivate += Deactivate;
void Deactivate(object sender, EventArgs e) void Deactivate(object sender, EventArgs e)
{ {
if (!(Form.ActiveForm is Menu)) if (!FadeHalfOrOutIfNeeded())
{ {
FadeHalfOrOutIfNeeded(); deactivatedTime = DateTime.Now;
menus[0].SetTitleColorDeactive();
} }
} }
menu.Activated += Activated; menu.Activated += Activated;
void Activated(object sender, EventArgs e) void Activated(object sender, EventArgs e)
{ {
if (Form.ActiveForm is Menu) if (Form.ActiveForm is Menu &&
menus[0].IsUsable)
{ {
FadeInIfNeeded();
menus[0].SetTitleColorActive(); menus[0].SetTitleColorActive();
Menus().ToList().ForEach(m => m.ShowWithFade());
}
CheckIfWindowsStartStoleFocusNoDeactivateInRareCase();
void CheckIfWindowsStartStoleFocusNoDeactivateInRareCase()
{
timerStillActiveCheck.Interval = 1000;
timerStillActiveCheck.Tick += StillActiveTick;
void StillActiveTick(object senderTimer, EventArgs eTimer)
{
if (!waitLeave.IsRunning &&
!FadeHalfOrOutIfNeeded())
{
timerStillActiveCheck.Stop();
}
}
timerStillActiveCheck.Start();
} }
} }
@ -549,7 +543,6 @@ namespace SystemTrayMenu
{ {
int level = (int)eDoWork.Argument; int level = (int)eDoWork.Argument;
BackgroundWorker worker = (BackgroundWorker)senderDoWork; BackgroundWorker worker = (BackgroundWorker)senderDoWork;
rowData.RestartLoading = false;
eDoWork.Result = ReadMenu(worker, rowData.TargetFilePath, level); eDoWork.Result = ReadMenu(worker, rowData.TargetFilePath, level);
} }
@ -560,12 +553,12 @@ namespace SystemTrayMenu
MenuData menuData = (MenuData)e.Result; MenuData menuData = (MenuData)e.Result;
if (rowData.RestartLoading) if (rowData.RestartLoading)
{ {
rowData.RestartLoading = false;
rowData.Reading.RunWorkerAsync(menuData.Level); rowData.Reading.RunWorkerAsync(menuData.Level);
} }
else else
{ {
menuNotifyIcon.LoadingStop(); menuNotifyIcon.LoadingStop();
menuNotifyIcon.LoadWait();
if (menuData.Validity != MenuDataValidity.Invalid) if (menuData.Validity != MenuDataValidity.Invalid)
{ {
menu = CreateMenu(menuData); menu = CreateMenu(menuData);
@ -585,7 +578,6 @@ namespace SystemTrayMenu
rowData.SubMenu = menu; rowData.SubMenu = menu;
rowData.MenuLoaded(); rowData.MenuLoaded();
} }
menuNotifyIcon.LoadStop();
} }
} }
} }
@ -620,46 +612,35 @@ namespace SystemTrayMenu
DisposeMenu(menus[menuTriggered.Level]); DisposeMenu(menus[menuTriggered.Level]);
menus[menuTriggered.Level] = menuTriggered; menus[menuTriggered.Level] = menuTriggered;
AdjustSubMenusLocationAndSize(); AdjustSubMenusLocationAndSize();
menus[menuTriggered.Level].ShowWithFadeOrTransparent(
#warning wrap into showorshowtransparent or find way without asking active form Form.ActiveForm is Menu);
if (Form.ActiveForm is Menu)
{
menus[menuTriggered.Level].ShowWithFade();
}
else
{
menus[menuTriggered.Level].ShowTransparent();
}
} }
private void FadeInIfNeeded() private void FadeInIfNeeded()
{ {
if (menus[0].IsUsable) if (menus[0].IsUsable)
{ {
if (Form.ActiveForm is Menu) bool isActive = Form.ActiveForm is Menu;
{ Menus().ToList().ForEach(
Menus().ToList().ForEach(menu => menu.ShowWithFade()); menu => menu.ShowWithFadeOrTransparent(isActive));
}
else
{
Menus().ToList().ForEach(menu => menu.ShowTransparent());
}
} }
} }
private void FadeHalfOrOutIfNeeded() private bool FadeHalfOrOutIfNeeded()
{ {
bool menuActive = false;
if (menus[0].IsUsable) if (menus[0].IsUsable)
{ {
if (!(Form.ActiveForm is Menu)) menuActive = Form.ActiveForm is Menu;
if (!menuActive)
{ {
Point position = Control.MousePosition; Point position = Control.MousePosition;
if (Menus().Any(m => m.IsMouseOn(position))) if (Menus().Any(m => m.IsMouseOn(position)))
{ {
if (!keyboardInput.InUse) if (!keyboardInput.InUse)
{ {
Menus().ToList().ForEach(menu => Menus().ToList().ForEach(
menu.ShowTransparent()); menu => menu.ShowTransparent());
} }
} }
else else
@ -668,10 +649,13 @@ namespace SystemTrayMenu
} }
} }
} }
return menuActive;
} }
private void MenusFadeOut() private void MenusFadeOut()
{ {
openCloseState = OpenCloseState.Closing;
Menus().ToList().ForEach(menu => Menus().ToList().ForEach(menu =>
{ {
if (menu.Level > 0) if (menu.Level > 0)

View file

@ -10,10 +10,12 @@ namespace SystemTrayMenu.Handler
private readonly Timer timerLeaveCheck = new Timer(); private readonly Timer timerLeaveCheck = new Timer();
public bool IsRunning => timerLeaveCheck.Enabled;
public WaitLeave(int timeUntilTriggered) public WaitLeave(int timeUntilTriggered)
{ {
timerLeaveCheck.Interval = timeUntilTriggered; timerLeaveCheck.Interval = timeUntilTriggered;
timerLeaveCheck.Tick += Leave; timerLeaveCheck.Tick += TimerLeaveCheckTick;
} }
public void Start() public void Start()
@ -27,7 +29,7 @@ namespace SystemTrayMenu.Handler
timerLeaveCheck.Stop(); timerLeaveCheck.Stop();
} }
private void Leave(object sender, EventArgs e) private void TimerLeaveCheckTick(object sender, EventArgs e)
{ {
timerLeaveCheck.Stop(); timerLeaveCheck.Stop();
LeaveTriggered.Invoke(); LeaveTriggered.Invoke();

View file

@ -22,7 +22,6 @@ namespace SystemTrayMenu
internal const int Scrollspeed = 4; internal const int Scrollspeed = 4;
internal const int WaitMenuOpen = 200; internal const int WaitMenuOpen = 200;
internal const int MenusMax = 50; internal const int MenusMax = 50;
internal const int MaxClicksInQueue = 1;
internal const int TimeUntilClose = 1000; internal const int TimeUntilClose = 1000;
} }

View file

@ -194,7 +194,7 @@ namespace SystemTrayMenu.DataClasses
} }
catch (ArgumentException ex) catch (ArgumentException ex)
{ {
Log.Error($"iconLocation:'{iconLocation}'", ex); Log.Warn($"iconLocation:'{iconLocation}'", ex);
} }
} }
} }

View file

@ -43,28 +43,16 @@ namespace SystemTrayMenu.UserInterface
StartStopTimer(state); StartStopTimer(state);
} }
private void StartStopTimer(FadingState state) private void StartStopTimer(FadingState newState)
{ {
#warning if too many threads throw some away? win32 exception if too fast here if (newState == FadingState.Idle)
if (state == FadingState.Idle)
{ {
this.state = state; state = newState;
timer.Stop(); timer.Stop();
} }
else else
{ {
ShowAtLeastTransparentBeforeHideItAgain(); state = newState;
void ShowAtLeastTransparentBeforeHideItAgain()
{
if (state == FadingState.Hide)
{
while (opacity < TransparentMinus)
{
Application.DoEvents();
}
}
}
this.state = state;
timer.Start(); timer.Start();
FadeStep(); FadeStep();
} }

View file

@ -35,5 +35,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.9.2.21")] [assembly: AssemblyVersion("0.9.2.22")]
[assembly: AssemblyFileVersion("0.9.2.21")] [assembly: AssemblyFileVersion("0.9.2.22")]

View file

@ -111,6 +111,7 @@
<DebugType>full</DebugType> <DebugType>full</DebugType>
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<Prefer32Bit>false</Prefer32Bit> <Prefer32Bit>false</Prefer32Bit>
<Optimize>true</Optimize>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'x64|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'x64|AnyCPU'">
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>
@ -351,6 +352,9 @@
</ItemGroup> </ItemGroup>
<ItemGroup /> <ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PreBuildEvent>taskkill /f /fi "imagename eq $(TargetFileName)"</PreBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild"> <Target Name="BeforeBuild">

View file

@ -67,19 +67,21 @@ namespace SystemTrayMenu.UserInterface
notifyIcon.MouseClick += NotifyIcon_MouseClick; notifyIcon.MouseClick += NotifyIcon_MouseClick;
void NotifyIcon_MouseClick(object sender, MouseEventArgs e) void NotifyIcon_MouseClick(object sender, MouseEventArgs e)
{ {
if (e.Button == MouseButtons.Left) VerifyClick(e);
{
HandleClick.Invoke();
}
} }
notifyIcon.MouseDoubleClick += NotifyIcon_MouseDoubleClick; notifyIcon.MouseDoubleClick += NotifyIcon_MouseDoubleClick;
void NotifyIcon_MouseDoubleClick(object sender, MouseEventArgs e) void NotifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
{ {
if (e.Button == MouseButtons.Left) VerifyClick(e);
{ }
HandleClick.Invoke(); }
}
private void VerifyClick(MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
HandleClick.Invoke();
} }
} }
@ -90,8 +92,13 @@ namespace SystemTrayMenu.UserInterface
load.Dispose(); load.Dispose();
} }
public void LoadingStart() public void LoadingStart(bool reset = false)
{ {
if (reset)
{
threadsLoading = 0;
}
timeLoadingStart = DateTime.Now; timeLoadingStart = DateTime.Now;
threadsLoading++; threadsLoading++;
load.Start(); load.Start();
@ -101,14 +108,16 @@ namespace SystemTrayMenu.UserInterface
{ {
threadsLoading--; threadsLoading--;
} }
public void LoadWait()
{ // Show a static icon when mainthread blocked
notifyIcon.Icon = bitmapsLoading[loadCount++ % indexLoad]; //public void LoadingStaticWait()
} //{
public void LoadStop() // notifyIcon.Icon = bitmapsLoading[loadCount++ % indexLoad];
{ //}
notifyIcon.Icon = R.SystemTrayMenu; //public void LoadingStaticStop()
} //{
// notifyIcon.Icon = R.SystemTrayMenu;
//}
private void Load_Tick(object sender, EventArgs e) private void Load_Tick(object sender, EventArgs e)
{ {

View file

@ -16,10 +16,11 @@ namespace SystemTrayMenu.UserInterface
internal new event EventHandlerEmpty MouseEnter; internal new event EventHandlerEmpty MouseEnter;
internal new event EventHandlerEmpty MouseLeave; internal new event EventHandlerEmpty MouseLeave;
internal event EventHandlerEmpty UserClickedOpenFolder; internal event EventHandlerEmpty UserClickedOpenFolder;
#warning use event not action
internal event Action<Keys> CmdKeyProcessed; internal event Action<Keys> CmdKeyProcessed;
#warning #68 => use event and not a action here?
internal bool IsUsable => Visible && !fading.IsHiding; internal bool IsUsable => Visible && !fading.IsHiding &&
!IsDisposed && !Disposing;
internal enum MenuType internal enum MenuType
{ {
@ -45,7 +46,30 @@ namespace SystemTrayMenu.UserInterface
fading.Show += Fading_Show; fading.Show += Fading_Show;
void Fading_Show() void Fading_Show()
{ {
NativeMethods.User32ShowInactiveTopmost(this); if (Level == 0)
{
try
{
Visible = true;
}
catch (ObjectDisposedException)
{
Visible = false;
Log.Info($"Could not open menu, menu already closed," +
$" IsDisposed={IsDisposed}");
}
if (Visible)
{
Activate();
NativeMethods.ForceForegroundWindow(Handle);
SetTitleColorActive();
}
}
else
{
NativeMethods.User32ShowInactiveTopmost(this);
}
} }
fading.Hide += Hide; fading.Hide += Hide;
@ -89,10 +113,12 @@ namespace SystemTrayMenu.UserInterface
{ {
SetType(MenuType.Sub); SetType(MenuType.Sub);
} }
internal void SetTypeEmpty() internal void SetTypeEmpty()
{ {
SetType(MenuType.Empty); SetType(MenuType.Empty);
} }
internal void SetTypeNoAccess() internal void SetTypeNoAccess()
{ {
SetType(MenuType.NoAccess); SetType(MenuType.NoAccess);
@ -127,17 +153,6 @@ namespace SystemTrayMenu.UserInterface
} }
} }
internal bool IsVisible()
{
return Visible;
}
internal bool IsActive(Form activeForm)
{
bool isActive = (this == activeForm);
return isActive;
}
internal bool IsMouseOn(Point mousePosition) internal bool IsMouseOn(Point mousePosition)
{ {
bool isMouseOn = Visible && ClientRectangle.Contains( bool isMouseOn = Visible && ClientRectangle.Contains(
@ -149,10 +164,6 @@ namespace SystemTrayMenu.UserInterface
{ {
return dgv; return dgv;
} }
internal Label GetLabel()
{
return labelTitle;
}
internal void SetTitle(string title) internal void SetTitle(string title)
{ {
@ -166,6 +177,18 @@ namespace SystemTrayMenu.UserInterface
} }
} }
internal void ShowWithFadeOrTransparent(bool formActiveFormIsMenu)
{
if (formActiveFormIsMenu)
{
ShowWithFade();
}
else
{
ShowTransparent();
}
}
internal void ShowWithFade() internal void ShowWithFade()
{ {
fading.Fade(Fading.FadingState.Show); fading.Fade(Fading.FadingState.Show);