Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4f65c303a0 | ||
|
|
6ae4312bdf | ||
|
|
001270e4ad | ||
|
|
aa2ca80822 | ||
|
|
43314a3006 | ||
|
|
a682f27223 | ||
|
|
a50d88f2c2 | ||
|
|
6f62e6b2a0 | ||
|
|
bf4111cc81 |
11
App.config
11
App.config
@@ -2,9 +2,16 @@
|
||||
<configuration>
|
||||
<configSections>
|
||||
<section name="SystemIcons" type="System.Configuration.DictionarySectionHandler" />
|
||||
<section name="ShowSecondsSettings" type="System.Configuration.DictionarySectionHandler" />
|
||||
<section name="SystemBGs" type="System.Collections.ObjectModel.ObservableCollection" />
|
||||
<section name="GradientBGParam" type="GeekDesk.ViewModel.GradientBGParam" />
|
||||
</configSections>
|
||||
<ShowSecondsSettings>
|
||||
<add key="Version" value="1.0.01" />
|
||||
<add key="LProportion" value="0.82" />
|
||||
<add key="TProportion" value="0.03" />
|
||||
<add key="DelayTime" value="800" />
|
||||
</ShowSecondsSettings>
|
||||
<SystemIcons>
|
||||
<add key="Calculator" value="计算器" />
|
||||
<add key="Computer" value="此电脑" />
|
||||
@@ -54,7 +61,7 @@
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
<appSettings>
|
||||
<add key="Version" value="2.5.11" />
|
||||
<add key="Version" value="2.5.12" />
|
||||
<add key="GitHubUrl" value="https://github.com/BookerLiu/GeekDesk" />
|
||||
<add key="GiteeUrl" value="https://gitee.com/BookerLiu/GeekDesk/tree/master" />
|
||||
<add key="GitHubUpdateUrl" value="https://raw.githubusercontent.com/BookerLiu/GeekDesk/master/Update.json" />
|
||||
@@ -62,7 +69,7 @@
|
||||
<!--<add key="GiteeUpdateUrl" value="file:///D:/WorkSpace/workspace-VS/GeekDesk/Update.json" />-->
|
||||
<add key="ClientSettingsProvider.ServiceUri" value="" />
|
||||
<add key="CustomIconTeachUrl" value="https://mp.weixin.qq.com/s/LxoHAekho9HBVl4FRw_Law" />
|
||||
<add key="ShowPublicWeChat" value="Y"/>
|
||||
<add key="ShowPublicWeChat" value="Y" />
|
||||
</appSettings>
|
||||
<system.web>
|
||||
<membership defaultProvider="ClientAuthenticationMembershipProvider">
|
||||
|
||||
@@ -24,7 +24,6 @@ namespace GeekDesk
|
||||
|
||||
private void App_Startup(object sender, StartupEventArgs e)
|
||||
{
|
||||
|
||||
mutex = new System.Threading.Mutex(true, Constants.MY_NAME, out bool ret);
|
||||
if (!ret)
|
||||
{
|
||||
@@ -32,6 +31,10 @@ namespace GeekDesk
|
||||
mutex = new System.Threading.Mutex(true, Constants.MY_NAME, out ret);
|
||||
if (!ret)
|
||||
{
|
||||
MessageUtil.SendMsgByWName(
|
||||
"GeekDesk_Main_" + Constants.MY_UUID,
|
||||
"ShowApp"
|
||||
);
|
||||
Environment.Exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace GeekDesk.Constant
|
||||
|
||||
public static string MY_NAME = DEV ? "GeekDesk-D" : "GeekDesk";
|
||||
|
||||
|
||||
public static string MY_UUID = "8400A17AEEF7C029";
|
||||
/// <summary>
|
||||
/// app数据文件路径
|
||||
/// </summary>
|
||||
@@ -30,6 +30,12 @@ namespace GeekDesk.Constant
|
||||
|
||||
public static string ERROR_FILE_PATH = APP_DIR + "logs\\error.log"; // 错误日志
|
||||
|
||||
/// <summary>
|
||||
/// 插件文件夹
|
||||
/// </summary>
|
||||
public static string PLUGINS_PATH = APP_DIR + "plugins\\";
|
||||
|
||||
|
||||
public static int SHADOW_WIDTH = 20;
|
||||
|
||||
//系统图标
|
||||
|
||||
@@ -40,5 +40,23 @@
|
||||
/// </summary>
|
||||
public static bool IS_MENU_EDIT = false;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 图标card 鼠标滚轮是否正在工作
|
||||
/// 用来控制popup的显示 否则低性能机器会造成卡顿
|
||||
/// </summary>
|
||||
public static bool ICONLIST_MOUSE_WHEEL = false;
|
||||
/// <summary>
|
||||
/// 控制多少毫秒后 关闭(ICONLIST_MOUSE_WHEEL)鼠标滚轮运行状态
|
||||
/// </summary>
|
||||
public static int MOUSE_WHEEL_WAIT_MS = 100;
|
||||
/// <summary>
|
||||
/// 与关闭popup 配合使用, 避免线程结束后不显示popup
|
||||
/// </summary>
|
||||
public static bool MOUSE_ENTER_ICON = false;
|
||||
/// <summary>
|
||||
/// 控制每次刷新搜索结果 鼠标移动后显示popup
|
||||
/// </summary>
|
||||
public static int MOUSE_MOVE_COUNT = 0;
|
||||
}
|
||||
}
|
||||
|
||||
15
Constant/WidthTypeEnum.cs
Normal file
15
Constant/WidthTypeEnum.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GeekDesk.Constant
|
||||
{
|
||||
public enum WidthTypeEnum
|
||||
{
|
||||
LEFT_CARD = 0, //左侧托盘宽度
|
||||
RIGHT_CARD = 1, //右侧托盘宽度
|
||||
RIGHT_CARD_HALF = 2 //右侧托盘宽度的一半
|
||||
}
|
||||
}
|
||||
@@ -315,14 +315,17 @@ namespace GeekDesk.Control.UserControls.Config
|
||||
/// <param name="e"></param>
|
||||
private void MouseMiddle_Changed(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (appConfig.MouseMiddleShow)
|
||||
{
|
||||
MouseHookThread.MiddleHook();
|
||||
}
|
||||
else
|
||||
{
|
||||
MouseHookThread.Dispose();
|
||||
}
|
||||
//if (appConfig.MouseMiddleShow)
|
||||
//{
|
||||
// MouseHookThread.MiddleHook();
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// MouseHookThread.DisposeMiddle();
|
||||
//}
|
||||
|
||||
MouseHookThread.Dispose();
|
||||
MouseHookThread.Hook();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:cvt="clr-namespace:GeekDesk.Converts"
|
||||
xmlns:local="clr-namespace:GeekDesk.Control.UserControls.PannelCard"
|
||||
xmlns:hc="https://handyorg.github.io/handycontrol"
|
||||
xmlns:hc="https://handyorg.github.io/handycontrol" xmlns:viewmodel="clr-namespace:GeekDesk.ViewModel" d:DataContext="{d:DesignInstance Type=viewmodel:AppConfig}"
|
||||
mc:Ignorable="d"
|
||||
Background="Transparent"
|
||||
d:DesignHeight="400" d:DesignWidth="500"
|
||||
@@ -41,6 +41,20 @@
|
||||
</CheckBox.Background>
|
||||
</CheckBox>
|
||||
</hc:UniformSpacingPanel>
|
||||
<TextBlock Text="插件" Margin="0,20,0,0"/>
|
||||
<hc:UniformSpacingPanel Spacing="10" Margin="20,6,0,0">
|
||||
<CheckBox Content="时钟显秒" Click="ShowSeconds_Click" IsChecked="{Binding SecondsWindow}"
|
||||
hc:Poptip.HitMode="None"
|
||||
hc:Poptip.IsOpen="{Binding IsMouseOver, RelativeSource={RelativeSource Self}}"
|
||||
hc:Poptip.Content="仅Win11有效"
|
||||
hc:Poptip.Placement="TopLeft">
|
||||
<CheckBox.Background>
|
||||
<LinearGradientBrush EndPoint="1,0" StartPoint="0,0">
|
||||
<GradientStop Color="#FF9EA3A6"/>
|
||||
</LinearGradientBrush>
|
||||
</CheckBox.Background>
|
||||
</CheckBox>
|
||||
</hc:UniformSpacingPanel>
|
||||
<TextBlock Text="排序方式" Margin="0,25,0,0"/>
|
||||
|
||||
<hc:UniformSpacingPanel Spacing="10" Margin="20,8,0,0">
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
using GeekDesk.Constant;
|
||||
using GeekDesk.MyThread;
|
||||
using GeekDesk.Util;
|
||||
using GeekDesk.ViewModel;
|
||||
using ShowSeconds;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Management;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
@@ -112,5 +118,80 @@ namespace GeekDesk.Control.UserControls.Config
|
||||
{
|
||||
CommonCode.BakAppData();
|
||||
}
|
||||
|
||||
private void ShowSeconds_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
//if (MainWindow.appData.AppConfig.SecondsWindow == true)
|
||||
//{
|
||||
// //StartSecondsWindow();
|
||||
// //SecondsWindow.ShowWindow();
|
||||
// MouseHookThread.Dispose();
|
||||
// MouseHookThread.Hook();
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// MouseHookThread.Dispose();
|
||||
// MouseHookThread.Hook();
|
||||
//}
|
||||
|
||||
MouseHookThread.Dispose();
|
||||
MouseHookThread.Hook();
|
||||
}
|
||||
|
||||
public static void StopSecondsWindow()
|
||||
{
|
||||
if (MessageUtil.CheckWindowIsRuning("ShowSeconds_Main_" + Constants.MY_UUID))
|
||||
{
|
||||
MessageUtil.SendMsgByWName(
|
||||
"ShowSeconds_Main_" + Constants.MY_UUID,
|
||||
"Shutdown"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static void StartSecondsWindow()
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var objOS = new ManagementObjectSearcher("SELECT * FROM Win32_OperatingSystem"))
|
||||
{
|
||||
foreach (ManagementObject objMgmt in objOS.Get())
|
||||
{
|
||||
if (objMgmt.Properties["Caption"].Value != null)
|
||||
{
|
||||
string caption = objMgmt.Properties["Caption"].Value.ToString(); ;
|
||||
LogUtil.WriteLog("获取的系统版本号为:" + caption);
|
||||
if (caption.Contains("Windows 11"))
|
||||
{
|
||||
//找到ShowSeconds插件
|
||||
FileInfo fi = FileUtil.GetFileByNameWithDir("ShowSeconds.exe", Constants.PLUGINS_PATH);
|
||||
if (fi == null)
|
||||
{
|
||||
HandyControl.Controls.MessageBox.Show("未安装程序插件:ShowSeconds");
|
||||
}
|
||||
else
|
||||
{
|
||||
//检查是否在运行
|
||||
if (!MessageUtil.CheckWindowIsRuning("ShowSeconds_Main_" + Constants.MY_UUID))
|
||||
{
|
||||
using (Process p = new Process())
|
||||
{
|
||||
p.StartInfo.FileName = fi.FullName;
|
||||
p.StartInfo.WorkingDirectory = fi.FullName.Substring(0, fi.FullName.LastIndexOf("\\"));
|
||||
p.Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex) { }
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,13 +161,17 @@ namespace GeekDesk.Control.UserControls.PannelCard
|
||||
|
||||
private void Lbi_Selected(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ListBoxItem lbi = sender as ListBoxItem;
|
||||
try
|
||||
{
|
||||
ListBoxItem lbi = sender as ListBoxItem;
|
||||
|
||||
SolidColorBrush fontColor = new SolidColorBrush(Colors.Black);
|
||||
SolidColorBrush fontColor = new SolidColorBrush(Colors.Black);
|
||||
|
||||
lbi.MouseLeave -= Lbi_MouseLeave;
|
||||
lbi.Background = bac;
|
||||
lbi.Foreground = fontColor;
|
||||
lbi.MouseLeave -= Lbi_MouseLeave;
|
||||
lbi.Background = bac;
|
||||
lbi.Foreground = fontColor;
|
||||
} catch { }
|
||||
|
||||
}
|
||||
|
||||
private void Lbi_MouseLeave(object sender, MouseEventArgs e)
|
||||
@@ -329,7 +333,6 @@ namespace GeekDesk.Control.UserControls.PannelCard
|
||||
appData.AppConfig.SelectedMenuIcons = null;
|
||||
RunTimeStatus.SHOW_MENU_PASSWORDBOX = true;
|
||||
MainWindow.mainWindow.RightCard.PDDialog.Title.Text = "输入密码";
|
||||
MainWindow.mainWindow.RightCard.PDDialog.type = PasswordType.INPUT;
|
||||
MainWindow.mainWindow.RightCard.PDDialog.Visibility = Visibility.Visible;
|
||||
}
|
||||
else
|
||||
@@ -339,6 +342,7 @@ namespace GeekDesk.Control.UserControls.PannelCard
|
||||
}
|
||||
}
|
||||
MainWindow.mainWindow.RightCard.WrapUFG.Visibility = Visibility.Visible;
|
||||
//App.DoEvents();
|
||||
}
|
||||
|
||||
|
||||
@@ -421,32 +425,46 @@ namespace GeekDesk.Control.UserControls.PannelCard
|
||||
private void Menu_MouseWheel(object sender, MouseWheelEventArgs e)
|
||||
{
|
||||
if (RunTimeStatus.IS_MENU_EDIT) return;
|
||||
|
||||
ScrollViewer scrollViewer = ScrollUtil.FindSimpleVisualChild<ScrollViewer>(MenuListBox);
|
||||
if (e.Delta < 0)
|
||||
{
|
||||
int index = MenuListBox.SelectedIndex;
|
||||
if (index < MenuListBox.Items.Count - 1)
|
||||
//判断是否到了最底部
|
||||
if (ScrollUtil.IsBootomScrollView(scrollViewer))
|
||||
{
|
||||
index ++;
|
||||
} else
|
||||
{
|
||||
index = 0;
|
||||
int index = MenuListBox.SelectedIndex;
|
||||
if (index < MenuListBox.Items.Count - 1)
|
||||
{
|
||||
index++;
|
||||
}
|
||||
else
|
||||
{
|
||||
index = 0;
|
||||
}
|
||||
MenuListBox.SelectedIndex = index;
|
||||
}
|
||||
MenuListBox.SelectedIndex = index;
|
||||
} else if (e.Delta > 0)
|
||||
{
|
||||
int index = MenuListBox.SelectedIndex;
|
||||
if (index > 0)
|
||||
if (ScrollUtil.IsTopScrollView(scrollViewer))
|
||||
{
|
||||
index --;
|
||||
int index = MenuListBox.SelectedIndex;
|
||||
if (index > 0)
|
||||
{
|
||||
index--;
|
||||
}
|
||||
else
|
||||
{
|
||||
index = MenuListBox.Items.Count - 1;
|
||||
}
|
||||
MenuListBox.SelectedIndex = index;
|
||||
}
|
||||
else
|
||||
{
|
||||
index = MenuListBox.Items.Count - 1;
|
||||
}
|
||||
MenuListBox.SelectedIndex = index;
|
||||
}
|
||||
|
||||
//滚动到选中项
|
||||
MenuListBox.ScrollIntoView(MenuListBox.SelectedItem);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void Menu_PreviewDragLeave(object sender, DragEventArgs e)
|
||||
{
|
||||
|
||||
@@ -6,9 +6,11 @@
|
||||
xmlns:temp="clr-namespace:GeekDesk.ViewModel.Temp"
|
||||
xmlns:hc="https://handyorg.github.io/handycontrol"
|
||||
xmlns:cvt="clr-namespace:GeekDesk.Converts"
|
||||
xmlns:cst="clr-namespace:GeekDesk.Constant"
|
||||
xmlns:DraggAnimatedPanel="clr-namespace:DraggAnimatedPanel"
|
||||
xmlns:xf="clr-namespace:XamlFlair;assembly=XamlFlair.WPF"
|
||||
xmlns:ot="clr-namespace:GeekDesk.Control.Other"
|
||||
xmlns:ot="clr-namespace:GeekDesk.Control.Other"
|
||||
xmlns:viewmodel="clr-namespace:GeekDesk.ViewModel" d:DataContext="{d:DesignInstance Type=viewmodel:AppData}"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800"
|
||||
>
|
||||
@@ -58,6 +60,25 @@
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="MyPoptipStyle" TargetType="Border">
|
||||
<Setter Property="HorizontalAlignment" Value="Center"/>
|
||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="Background" Value="White"/>
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource BorderBrush}"/>
|
||||
<Setter Property="CornerRadius" Value="{StaticResource DefaultCornerRadius}"/>
|
||||
<Setter Property="Padding" Value="{StaticResource DefaultControlPadding}"/>
|
||||
<!--<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="hc:Poptip">
|
||||
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="{Binding Path=(hc:BorderElement.CornerRadius),RelativeSource={RelativeSource TemplatedParent}}">
|
||||
<ContentPresenter Margin="{TemplateBinding Padding}" ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}" ContentStringFormat="{TemplateBinding ContentStringFormat}" ContentTemplate="{TemplateBinding ContentTemplate}"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>-->
|
||||
</Style>
|
||||
|
||||
<Storyboard x:Key="Custom1Transition1" x:Shared="False">
|
||||
<DoubleAnimation From="50" To="0" Duration="0:0:0.4" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
|
||||
<DoubleAnimation.EasingFunction>
|
||||
@@ -82,11 +103,23 @@
|
||||
</Storyboard>
|
||||
|
||||
<cvt:OpcityConvert x:Key="OpcityConvert"/>
|
||||
<cvt:SearchResWidth x:Key="SearchResWidth"/>
|
||||
<cvt:GetWidthByWWConvert x:Key="GetWidthByWWConvert"/>
|
||||
<temp:SearchIconList x:Key="SearchIconList"/>
|
||||
</UserControl.Resources>
|
||||
<!--右侧栏-->
|
||||
<Grid>
|
||||
<Popup Name="MyPoptip" FlowDirection="LeftToRight"
|
||||
PopupAnimation="None" Placement="Mouse"
|
||||
IsOpen="False"
|
||||
AllowsTransparency="True"
|
||||
>
|
||||
<Grid Background="Transparent">
|
||||
<Border Style="{StaticResource MyPoptipStyle}">
|
||||
<TextBlock Name="MyPoptipContent" HorizontalAlignment="Center" VerticalAlignment="Center" TextAlignment="Left" Text="Test" FontSize="13"/>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Popup>
|
||||
|
||||
<hc:Card AllowDrop="True"
|
||||
x:Name="WrapCard"
|
||||
Visibility="Visible"
|
||||
@@ -96,6 +129,7 @@
|
||||
Margin="5,0,5,5" Grid.ColumnSpan="2"
|
||||
PreviewMouseRightButtonDown="WrapCard_PreviewMouseRightButtonDown"
|
||||
hc:Dialog.Token="RightWrapCardDialog"
|
||||
MouseWheel="IconListBox_MouseWheel"
|
||||
>
|
||||
<hc:Card.Background>
|
||||
<SolidColorBrush Color="AliceBlue" hc:GeometryEffect.GeometryEffect="20" Opacity="{Binding AppConfig.CardOpacity, Mode=TwoWay, Converter={StaticResource OpcityConvert}}"/>
|
||||
@@ -118,72 +152,95 @@
|
||||
IsVisibleChanged="PDDialog_IsVisibleChanged"
|
||||
Margin="0,-100,0,0"/>
|
||||
<StackPanel Panel.ZIndex="1" Margin="0,-10,-0,0"/>
|
||||
<WrapPanel Orientation="Horizontal"
|
||||
|
||||
<WrapPanel Orientation="Horizontal"
|
||||
VirtualizingPanel.VirtualizationMode="Recycling"
|
||||
VirtualizingPanel.IsVirtualizing="True"
|
||||
VirtualizingPanel.IsContainerVirtualizable="True"
|
||||
>
|
||||
<UniformGrid x:Name="WrapUFG" xf:Animations.Primary="{xf:Animate BasedOn={StaticResource FadeInAndGrowHorizontally}, Event=Visibility}">
|
||||
<!--<hc:TransitioningContentControl TransitionStoryboard="{StaticResource Custom3Transition3}">-->
|
||||
<ListBox x:Name="IconListBox"
|
||||
ItemsSource="{Binding AppConfig.SelectedMenuIcons, Mode=OneWay}"
|
||||
BorderThickness="0"
|
||||
Padding="0,10,0,0"
|
||||
>
|
||||
<ListBox.Background>
|
||||
<SolidColorBrush Opacity="0"/>
|
||||
</ListBox.Background>
|
||||
<ListBox.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<!--<DraggAnimatedPanel:DraggAnimatedPanel Background="#00FFFFFF"
|
||||
<ListBox x:Name="IconListBox"
|
||||
ItemsSource="{Binding AppConfig.SelectedMenuIcons, Mode=OneWay}"
|
||||
BorderThickness="0"
|
||||
Padding="0,10,0,0"
|
||||
ScrollViewer.CanContentScroll ="False"
|
||||
>
|
||||
<ListBox.Template>
|
||||
<ControlTemplate TargetType="ListBox">
|
||||
<hc:ScrollViewer x:Name="WrapScroll"
|
||||
Orientation="Vertical"
|
||||
HorizontalScrollBarVisibility="Hidden"
|
||||
VerticalScrollBarVisibility="Auto"
|
||||
IsInertiaEnabled="True"
|
||||
CanContentScroll="True"
|
||||
PreviewMouseWheel="IconListBox_MouseWheel"
|
||||
>
|
||||
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderBrush}">
|
||||
<ItemsPresenter/>
|
||||
|
||||
</Border>
|
||||
</hc:ScrollViewer>
|
||||
</ControlTemplate>
|
||||
</ListBox.Template>
|
||||
<ListBox.Background>
|
||||
<SolidColorBrush Color="#00FFFFFF" />
|
||||
</ListBox.Background>
|
||||
<ListBox.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<!--<DraggAnimatedPanel:DraggAnimatedPanel Background="#00FFFFFF"
|
||||
ItemsWidth="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}},Path=DataContext.AppConfig.ImgPanelWidth, Mode=OneWay}"
|
||||
ItemsHeight="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}},Path=DataContext.AppConfig.ImgPanelHeight, Mode=OneWay}"
|
||||
HorizontalAlignment="Center"
|
||||
SwapCommand="{Binding SwapCommand, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"/>-->
|
||||
<WrapPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</ListBox.ItemsPanel>
|
||||
|
||||
<ListBox.Resources>
|
||||
<ContextMenu x:Key="IconDialog" Width="200">
|
||||
<MenuItem Header="管理员方式运行" Click="IconAdminStart" Tag="{Binding}"/>
|
||||
<MenuItem Header="打开文件所在位置" Click="ShowInExplore" Tag="{Binding}"/>
|
||||
<MenuItem Header="添加URL项目" Click="AddUrlIcon"/>
|
||||
<MenuItem Header="添加系统项目" Click="AddSystemIcon"/>
|
||||
<MenuItem Header="资源管理器菜单" Click="SystemContextMenu" Tag="{Binding}"/>
|
||||
<MenuItem Header="属性" Click="PropertyConfig" Tag="{Binding}"/>
|
||||
<MenuItem Header="从列表移除" Click="RemoveIcon" Tag="{Binding}"/>
|
||||
</ContextMenu>
|
||||
</ListBox.Resources>
|
||||
<WrapPanel Background="#00FFFFFF"
|
||||
Width="{Binding AppConfig.WindowWidth, Mode=OneWay,
|
||||
Converter={StaticResource GetWidthByWWConvert},
|
||||
ConverterParameter={x:Static cst:WidthTypeEnum.RIGHT_CARD}}"
|
||||
/>
|
||||
</ItemsPanelTemplate>
|
||||
</ListBox.ItemsPanel>
|
||||
|
||||
<ListBox.ItemContainerStyle>
|
||||
<Style TargetType="ListBoxItem" BasedOn="{StaticResource MyListBoxItemStyle}">
|
||||
<Setter Property="ContextMenu" Value="{StaticResource IconDialog}"/>
|
||||
</Style>
|
||||
</ListBox.ItemContainerStyle>
|
||||
<ListBox.Resources>
|
||||
<ContextMenu x:Key="IconDialog" Width="200">
|
||||
<MenuItem Header="管理员方式运行" Click="IconAdminStart" Tag="{Binding}"/>
|
||||
<MenuItem Header="打开文件所在位置" Click="ShowInExplore" Tag="{Binding}"/>
|
||||
<MenuItem Header="添加URL项目" Click="AddUrlIcon"/>
|
||||
<MenuItem Header="添加系统项目" Click="AddSystemIcon"/>
|
||||
<MenuItem Header="资源管理器菜单" Click="SystemContextMenu" Tag="{Binding}"/>
|
||||
<MenuItem Header="属性" Click="PropertyConfig" Tag="{Binding}"/>
|
||||
<MenuItem Header="从列表移除" Click="RemoveIcon" Tag="{Binding}"/>
|
||||
</ContextMenu>
|
||||
</ListBox.Resources>
|
||||
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<ListBox.ItemContainerStyle>
|
||||
<Style TargetType="ListBoxItem" BasedOn="{StaticResource MyListBoxItemStyle}">
|
||||
<Setter Property="ContextMenu" Value="{StaticResource IconDialog}"/>
|
||||
</Style>
|
||||
</ListBox.ItemContainerStyle>
|
||||
|
||||
<hc:SimpleStackPanel Tag="{Binding}"
|
||||
Height="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}},Path=DataContext.AppConfig.ImgPanelHeight, Mode=OneWay}"
|
||||
Width="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}},Path=DataContext.AppConfig.ImgPanelWidth, Mode=OneWay}"
|
||||
HorizontalAlignment="Center"
|
||||
hc:Poptip.Content="{Binding Content}"
|
||||
hc:Poptip.Placement="BottomLeft"
|
||||
Background="#00FFFFFF"
|
||||
MouseEnter="StackPanel_MouseEnter"
|
||||
MouseLeave="StackPanel_MouseLeave"
|
||||
MouseLeftButtonDown="Icon_MouseLeftButtonDown"
|
||||
MouseLeftButtonUp="Icon_MouseLeftButtonUp"
|
||||
>
|
||||
<!--<StackPanel Background="#00FFFFFF"
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
|
||||
<hc:SimpleStackPanel Tag="{Binding}"
|
||||
Height="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}},Path=DataContext.AppConfig.ImgPanelHeight, Mode=OneWay}"
|
||||
Width="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}},Path=DataContext.AppConfig.ImgPanelWidth, Mode=OneWay}"
|
||||
HorizontalAlignment="Center"
|
||||
Background="#00FFFFFF"
|
||||
MouseEnter="MenuIcon_MouseEnter"
|
||||
MouseLeave="MenuIcon_MouseLeave"
|
||||
MouseMove="MenuIcon_MouseMove"
|
||||
MouseLeftButtonDown="Icon_MouseLeftButtonDown"
|
||||
MouseLeftButtonUp="Icon_MouseLeftButtonUp"
|
||||
>
|
||||
<!--<StackPanel Background="#00FFFFFF"
|
||||
MouseEnter="CursorPanel_MouseEnter"
|
||||
MouseLeave="CursorPanel_MouseLeave"
|
||||
Width="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}},Path=DataContext.AppConfig.ImageWidth, Mode=OneWay}">-->
|
||||
<Image Style="{StaticResource ImageStyle}"
|
||||
<Image Style="{StaticResource ImageStyle}"
|
||||
RenderOptions.BitmapScalingMode="HighQuality"/>
|
||||
<TextBlock MaxWidth="80"
|
||||
<TextBlock MaxWidth="80"
|
||||
Margin="0,5,0,0"
|
||||
MaxHeight="40"
|
||||
FontSize="13"
|
||||
@@ -193,15 +250,16 @@
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}},Path=DataContext.AppConfig.TextColor}"
|
||||
Text="{Binding Name}"/>
|
||||
<!--</StackPanel>-->
|
||||
<!--</StackPanel>-->
|
||||
|
||||
</hc:SimpleStackPanel>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
<!--</hc:TransitioningContentControl>-->
|
||||
</hc:SimpleStackPanel>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
<!--</hc:TransitioningContentControl>-->
|
||||
</UniformGrid>
|
||||
</WrapPanel>
|
||||
|
||||
</Grid>
|
||||
</hc:DialogContainer>
|
||||
</hc:Card>
|
||||
@@ -234,7 +292,23 @@
|
||||
x:Name="SearchListBox"
|
||||
SelectionChanged="SearchListBox_SelectionChanged"
|
||||
>
|
||||
<ListBox.Background>
|
||||
<ListBox.Template>
|
||||
<ControlTemplate TargetType="ListBox">
|
||||
<hc:ScrollViewer Orientation="Vertical"
|
||||
HorizontalScrollBarVisibility="Hidden"
|
||||
VerticalScrollBarVisibility="Auto"
|
||||
IsInertiaEnabled="True"
|
||||
CanContentScroll="True"
|
||||
PreviewMouseWheel="VerticalIconList_PreviewMouseWheel"
|
||||
>
|
||||
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderBrush}">
|
||||
<ItemsPresenter/>
|
||||
</Border>
|
||||
</hc:ScrollViewer>
|
||||
</ControlTemplate>
|
||||
</ListBox.Template>
|
||||
|
||||
<ListBox.Background>
|
||||
<SolidColorBrush Opacity="0"/>
|
||||
</ListBox.Background>
|
||||
|
||||
@@ -258,7 +332,9 @@
|
||||
<ListBox.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Background="#00FFFFFF"
|
||||
Width="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}},Path=DataContext.AppConfig.MenuCardWidth, Mode=OneWay, Converter={StaticResource SearchResWidth}, ConverterParameter=1}"
|
||||
Width="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}},Path=DataContext.AppConfig.WindowWidth, Mode=OneWay,
|
||||
Converter={StaticResource GetWidthByWWConvert},
|
||||
ConverterParameter={x:Static cst:WidthTypeEnum.RIGHT_CARD}}"
|
||||
/>
|
||||
</ItemsPanelTemplate>
|
||||
</ListBox.ItemsPanel>
|
||||
@@ -283,16 +359,19 @@
|
||||
</Border.Style>
|
||||
<WrapPanel Tag="{Binding}"
|
||||
Height="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}},Path=DataContext.AppConfig.ImageHeight, Mode=OneWay}"
|
||||
Width="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}},Path=DataContext.AppConfig.MenuCardWidth, Mode=OneWay, Converter={StaticResource SearchResWidth}, ConverterParameter=2}"
|
||||
Width="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}},Path=DataContext.AppConfig.WindowWidth, Mode=OneWay,
|
||||
Converter={StaticResource GetWidthByWWConvert},
|
||||
ConverterParameter={x:Static cst:WidthTypeEnum.RIGHT_CARD_HALF}}"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
hc:Poptip.HitMode="None"
|
||||
hc:Poptip.IsOpen="{Binding IsMouseOver, RelativeSource={RelativeSource Self}}"
|
||||
hc:Poptip.Content="{Binding Content}"
|
||||
hc:Poptip.Placement="BottomLeft"
|
||||
Background="#00FFFFFF"
|
||||
MouseEnter="SearchIcon_MouseEnter"
|
||||
MouseLeave="SearchIcon_MouseLeave"
|
||||
MouseLeftButtonDown="Icon_MouseLeftButtonDown"
|
||||
MouseLeftButtonUp="Icon_MouseLeftButtonUp"
|
||||
MouseMove="SearchIcon_MouseMove"
|
||||
Margin="25,10,0,10"
|
||||
>
|
||||
<Image Style="{StaticResource ImageStyle}" RenderOptions.BitmapScalingMode="HighQuality"/>
|
||||
|
||||
@@ -9,6 +9,7 @@ using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
@@ -177,8 +178,15 @@ namespace GeekDesk.Control.UserControls.PannelCard
|
||||
|
||||
try
|
||||
{
|
||||
using (Process p = new Process())
|
||||
{
|
||||
Process p = new Process();
|
||||
//using ()
|
||||
//{
|
||||
p.StartInfo.UseShellExecute = false;
|
||||
p.StartInfo.RedirectStandardInput = true;
|
||||
p.StartInfo.RedirectStandardOutput = true;
|
||||
p.StartInfo.RedirectStandardError = true;
|
||||
p.StartInfo.CreateNoWindow = true;
|
||||
|
||||
string startArg = icon.StartArg;
|
||||
|
||||
if (startArg != null && Constants.SYSTEM_ICONS.ContainsKey(startArg))
|
||||
@@ -220,11 +228,7 @@ namespace GeekDesk.Control.UserControls.PannelCard
|
||||
switch (type)
|
||||
{
|
||||
case IconStartType.ADMIN_STARTUP:
|
||||
//p.StartInfo.Arguments = "1";//启动参数
|
||||
p.StartInfo.Verb = "runas";
|
||||
//p.StartInfo.CreateNoWindow = false; //设置显示窗口
|
||||
p.StartInfo.UseShellExecute = true;//不使用操作系统外壳程序启动进程
|
||||
//p.StartInfo.ErrorDialog = false;
|
||||
if (appData.AppConfig.AppHideType == AppHideType.START_EXE && !RunTimeStatus.LOCK_APP_PANEL)
|
||||
{
|
||||
//如果开启了贴边隐藏 则窗体不贴边才隐藏窗口
|
||||
@@ -242,7 +246,7 @@ namespace GeekDesk.Control.UserControls.PannelCard
|
||||
|
||||
}
|
||||
break;// c#好像不能case穿透
|
||||
case IconStartType.DEFAULT_STARTUP:
|
||||
case IconStartType.DEFAULT_STARTUP:
|
||||
if (appData.AppConfig.AppHideType == AppHideType.START_EXE && !RunTimeStatus.LOCK_APP_PANEL)
|
||||
{
|
||||
//如果开启了贴边隐藏 则窗体不贴边才隐藏窗口
|
||||
@@ -284,13 +288,15 @@ namespace GeekDesk.Control.UserControls.PannelCard
|
||||
}
|
||||
}
|
||||
p.Start();
|
||||
p.Close();
|
||||
p.Dispose();
|
||||
if (useRelativePath)
|
||||
{
|
||||
//如果使用相对路径启动成功 那么重新设置程序绝对路径
|
||||
icon.Path = path;
|
||||
}
|
||||
}
|
||||
}
|
||||
//}
|
||||
icon.Count++;
|
||||
|
||||
//隐藏搜索框
|
||||
@@ -310,7 +316,7 @@ namespace GeekDesk.Control.UserControls.PannelCard
|
||||
HandyControl.Controls.Growl.WarningGlobal("程序启动失败(可能为不支持的启动方式)!");
|
||||
LogUtil.WriteErrorLog(e, "程序启动失败:path=" + icon.Path + ",type=" + type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -453,38 +459,55 @@ namespace GeekDesk.Control.UserControls.PannelCard
|
||||
}
|
||||
}
|
||||
|
||||
private void StackPanel_MouseEnter(object sender, MouseEventArgs e)
|
||||
private void MenuIcon_MouseEnter(object sender, MouseEventArgs e)
|
||||
{
|
||||
RunTimeStatus.MOUSE_ENTER_ICON = true;
|
||||
if (!RunTimeStatus.ICONLIST_MOUSE_WHEEL)
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem(state =>
|
||||
{
|
||||
this.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
IconInfo info = (sender as Panel).Tag as IconInfo;
|
||||
MyPoptipContent.Text = info.Content;
|
||||
MyPoptip.VerticalOffset = 30;
|
||||
Thread.Sleep(50);
|
||||
if (!RunTimeStatus.ICONLIST_MOUSE_WHEEL)
|
||||
{
|
||||
MyPoptip.IsOpen = true;
|
||||
}
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
double width = appData.AppConfig.ImageWidth;
|
||||
double height = appData.AppConfig.ImageHeight;
|
||||
width += width * 0.15;
|
||||
height += height * 0.15;
|
||||
Thread t = new Thread(() =>
|
||||
|
||||
ThreadPool.QueueUserWorkItem(state =>
|
||||
{
|
||||
this.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
ImgStoryBoard(sender, (int)width, (int)height, 1, true);
|
||||
}));
|
||||
});
|
||||
t.IsBackground = true;
|
||||
t.Start();
|
||||
|
||||
}
|
||||
|
||||
private void StackPanel_MouseLeave(object sender, MouseEventArgs e)
|
||||
private void MenuIcon_MouseLeave(object sender, MouseEventArgs e)
|
||||
{
|
||||
RunTimeStatus.MOUSE_ENTER_ICON = false;
|
||||
MyPoptip.IsOpen = false;
|
||||
|
||||
Thread t = new Thread(() =>
|
||||
ThreadPool.QueueUserWorkItem(state =>
|
||||
{
|
||||
this.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
ImgStoryBoard(sender, appData.AppConfig.ImageWidth, appData.AppConfig.ImageHeight, 260);
|
||||
}));
|
||||
this.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
ImgStoryBoard(sender, appData.AppConfig.ImageWidth, appData.AppConfig.ImageHeight, 260);
|
||||
}));
|
||||
});
|
||||
t.IsBackground = true;
|
||||
t.Start();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -758,6 +781,10 @@ namespace GeekDesk.Control.UserControls.PannelCard
|
||||
|
||||
public void SearchListBoxIndexAdd()
|
||||
{
|
||||
//控制移动后 鼠标即使在图标上也不显示popup
|
||||
RunTimeStatus.MOUSE_MOVE_COUNT = 0;
|
||||
MyPoptip.IsOpen = false;
|
||||
|
||||
if (SearchListBox.Items.Count > 0)
|
||||
{
|
||||
if (SearchListBox.SelectedIndex < SearchListBox.Items.Count - 1)
|
||||
@@ -769,6 +796,10 @@ namespace GeekDesk.Control.UserControls.PannelCard
|
||||
|
||||
public void SearchListBoxIndexSub()
|
||||
{
|
||||
//控制移动后 鼠标即使在图标上也不显示popup
|
||||
RunTimeStatus.MOUSE_MOVE_COUNT = 0;
|
||||
MyPoptip.IsOpen = false;
|
||||
|
||||
if (SearchListBox.Items.Count > 0)
|
||||
{
|
||||
if (SearchListBox.SelectedIndex > 0)
|
||||
@@ -818,5 +849,204 @@ namespace GeekDesk.Control.UserControls.PannelCard
|
||||
MainWindow.mainWindow.Focus();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 菜单结果icon 列表鼠标滚轮预处理时间
|
||||
/// 主要使用自定义popup解决卡顿问题解决卡顿问题
|
||||
/// 以及滚动条收尾切换菜单
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void IconListBox_MouseWheel(object sender, MouseWheelEventArgs e)
|
||||
{
|
||||
|
||||
//控制在滚动时不显示popup 否则会在低GPU性能机器上造成卡顿
|
||||
MyPoptip.IsOpen = false;
|
||||
if (RunTimeStatus.ICONLIST_MOUSE_WHEEL)
|
||||
{
|
||||
RunTimeStatus.MOUSE_WHEEL_WAIT_MS = 500;
|
||||
} else
|
||||
{
|
||||
RunTimeStatus.ICONLIST_MOUSE_WHEEL = true;
|
||||
|
||||
new Thread(() =>
|
||||
{
|
||||
while (RunTimeStatus.MOUSE_WHEEL_WAIT_MS > 0)
|
||||
{
|
||||
Thread.Sleep(1);
|
||||
RunTimeStatus.MOUSE_WHEEL_WAIT_MS -= 1;
|
||||
}
|
||||
if (RunTimeStatus.MOUSE_ENTER_ICON)
|
||||
{
|
||||
this.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
MyPoptip.IsOpen = true;
|
||||
}));
|
||||
}
|
||||
RunTimeStatus.MOUSE_WHEEL_WAIT_MS = 100;
|
||||
RunTimeStatus.ICONLIST_MOUSE_WHEEL = false;
|
||||
}).Start();
|
||||
}
|
||||
|
||||
//修改菜单时不切换菜单
|
||||
if (RunTimeStatus.IS_MENU_EDIT) return;
|
||||
|
||||
|
||||
//切换菜单
|
||||
System.Windows.Controls.ScrollViewer scrollViewer = sender as System.Windows.Controls.ScrollViewer;
|
||||
if (scrollViewer == null)
|
||||
{
|
||||
//在card 上获取的事件
|
||||
scrollViewer = ScrollUtil.FindSimpleVisualChild<System.Windows.Controls.ScrollViewer>(IconListBox);
|
||||
}
|
||||
if (e.Delta < 0)
|
||||
{
|
||||
int index = MainWindow.mainWindow.LeftCard.MenuListBox.SelectedIndex;
|
||||
if (ScrollUtil.IsBootomScrollView(scrollViewer))
|
||||
{
|
||||
if (index < MainWindow.mainWindow.LeftCard.MenuListBox.Items.Count - 1)
|
||||
{
|
||||
index++;
|
||||
}
|
||||
else
|
||||
{
|
||||
index = 0;
|
||||
}
|
||||
MainWindow.mainWindow.LeftCard.MenuListBox.SelectedIndex = index;
|
||||
scrollViewer.ScrollToVerticalOffset(0);
|
||||
}
|
||||
}
|
||||
else if (e.Delta > 0)
|
||||
{
|
||||
if (ScrollUtil.IsTopScrollView(scrollViewer))
|
||||
{
|
||||
int index = MainWindow.mainWindow.LeftCard.MenuListBox.SelectedIndex;
|
||||
if (index > 0)
|
||||
{
|
||||
index--;
|
||||
}
|
||||
else
|
||||
{
|
||||
index = MainWindow.mainWindow.LeftCard.MenuListBox.Items.Count - 1;
|
||||
}
|
||||
MainWindow.mainWindow.LeftCard.MenuListBox.SelectedIndex = index;
|
||||
scrollViewer.ScrollToVerticalOffset(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 搜索结果icon 列表鼠标滚轮预处理时间
|
||||
/// 主要使用自定义popup解决卡顿问题解决卡顿问题
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void VerticalIconList_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
|
||||
{
|
||||
//控制在滚动时不显示popup 否则会在低GPU性能机器上造成卡顿
|
||||
MyPoptip.IsOpen = false;
|
||||
if (RunTimeStatus.ICONLIST_MOUSE_WHEEL)
|
||||
{
|
||||
RunTimeStatus.MOUSE_WHEEL_WAIT_MS = 500;
|
||||
}
|
||||
else
|
||||
{
|
||||
RunTimeStatus.ICONLIST_MOUSE_WHEEL = true;
|
||||
|
||||
new Thread(() =>
|
||||
{
|
||||
while (RunTimeStatus.MOUSE_WHEEL_WAIT_MS > 0)
|
||||
{
|
||||
Thread.Sleep(1);
|
||||
RunTimeStatus.MOUSE_WHEEL_WAIT_MS -= 1;
|
||||
}
|
||||
if (RunTimeStatus.MOUSE_ENTER_ICON)
|
||||
{
|
||||
this.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
MyPoptip.IsOpen = true;
|
||||
}));
|
||||
}
|
||||
RunTimeStatus.MOUSE_WHEEL_WAIT_MS = 100;
|
||||
RunTimeStatus.ICONLIST_MOUSE_WHEEL = false;
|
||||
}).Start();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询结果 ICON 鼠标进入事件
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void SearchIcon_MouseEnter(object sender, MouseEventArgs e)
|
||||
{
|
||||
|
||||
//显示popup
|
||||
RunTimeStatus.MOUSE_ENTER_ICON = true;
|
||||
if (!RunTimeStatus.ICONLIST_MOUSE_WHEEL)
|
||||
{
|
||||
new Thread(() =>
|
||||
{
|
||||
this.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
IconInfo info = (sender as Panel).Tag as IconInfo;
|
||||
MyPoptipContent.Text = info.Content;
|
||||
MyPoptip.VerticalOffset = 30;
|
||||
Thread.Sleep(100);
|
||||
if (!RunTimeStatus.ICONLIST_MOUSE_WHEEL && RunTimeStatus.MOUSE_MOVE_COUNT > 1)
|
||||
{
|
||||
MyPoptip.IsOpen = true;
|
||||
}
|
||||
}));
|
||||
}).Start();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询结果ICON鼠标离开事件
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void SearchIcon_MouseLeave(object sender, MouseEventArgs e)
|
||||
{
|
||||
RunTimeStatus.MOUSE_ENTER_ICON = false;
|
||||
MyPoptip.IsOpen = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询结果ICON鼠标移动事件
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void SearchIcon_MouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
//控制首次刷新搜索结果后, 鼠标首次移动后显示popup
|
||||
RunTimeStatus.MOUSE_MOVE_COUNT++;
|
||||
|
||||
//防止移动后不刷新popup content
|
||||
IconInfo info = (sender as Panel).Tag as IconInfo;
|
||||
MyPoptipContent.Text = info.Content;
|
||||
MyPoptip.VerticalOffset = 30;
|
||||
|
||||
if (RunTimeStatus.MOUSE_MOVE_COUNT > 1 && !RunTimeStatus.ICONLIST_MOUSE_WHEEL)
|
||||
{
|
||||
MyPoptip.IsOpen = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// menu结果ICON鼠标移动事件
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void MenuIcon_MouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
//防止移动后不刷新popup content
|
||||
IconInfo info = (sender as Panel).Tag as IconInfo;
|
||||
MyPoptipContent.Text = info.Content;
|
||||
MyPoptip.VerticalOffset = 30;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
Background="Black"
|
||||
PreviewMouseMove="Window_PreviewMouseMove"
|
||||
MouseLeftButtonDown="Window_MouseLeftButtonDown"
|
||||
MouseRightButtonDown="Window_MouseRightButtonDown"
|
||||
MouseWheel="Window_MouseWheel"
|
||||
>
|
||||
<Window.Resources>
|
||||
|
||||
@@ -39,7 +39,11 @@ namespace GeekDesk.Control.Windows
|
||||
{
|
||||
InitializeComponent();
|
||||
this.colorPicker = colorPicker;
|
||||
SetProcessDPIAware();
|
||||
//try
|
||||
//{
|
||||
// SetProcessDPIAware();
|
||||
//}
|
||||
//catch (Exception e) { }
|
||||
ColorPickerWindow_Init();
|
||||
}
|
||||
|
||||
@@ -58,9 +62,12 @@ namespace GeekDesk.Control.Windows
|
||||
DesktopBG.Height = this.Height;
|
||||
this.Topmost = true;
|
||||
|
||||
//获取缩放比例
|
||||
double scale = ScreenUtil.GetScreenScalingFactor();
|
||||
|
||||
bgBitmap = new System.Drawing.Bitmap(
|
||||
Screen.AllScreens[0].Bounds.Width,
|
||||
Screen.AllScreens[0].Bounds.Height,
|
||||
(int)(Width * scale),
|
||||
(int)(Height * scale),
|
||||
System.Drawing.Imaging.PixelFormat.Format32bppArgb
|
||||
);
|
||||
|
||||
@@ -199,5 +206,16 @@ namespace GeekDesk.Control.Windows
|
||||
SetPixelAbout(e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 右键按下
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void Window_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
GlobalColorPickerWindow.ShowOrHide();
|
||||
//关闭
|
||||
this.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
40
Converts/GetWidthByWWConvert.cs
Normal file
40
Converts/GetWidthByWWConvert.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using GeekDesk.Constant;
|
||||
using GeekDesk.ViewModel;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace GeekDesk.Converts
|
||||
{
|
||||
/// <summary>
|
||||
/// 根据主窗口width 和传入类型 获取其它宽度
|
||||
/// </summary>
|
||||
class GetWidthByWWConvert : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
WidthTypeEnum type = (WidthTypeEnum)parameter;
|
||||
|
||||
AppConfig config = MainWindow.appData.AppConfig;
|
||||
|
||||
if (WidthTypeEnum.LEFT_CARD == type)
|
||||
{
|
||||
return config.MenuCardWidth;
|
||||
}
|
||||
else if (WidthTypeEnum.RIGHT_CARD == type)
|
||||
{
|
||||
return config.WindowWidth - config.MenuCardWidth;
|
||||
} else if (WidthTypeEnum.RIGHT_CARD_HALF == type)
|
||||
{
|
||||
return (config.WindowWidth - config.MenuCardWidth) / 2;
|
||||
}
|
||||
|
||||
return config.WindowWidth;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace GeekDesk.Converts
|
||||
{
|
||||
class SearchResWidth : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
string param = parameter as string;
|
||||
if ("1".Equals(param))
|
||||
{
|
||||
double menuLeftWidth = double.Parse(value.ToString());
|
||||
return MainWindow.mainWindow.Width - menuLeftWidth;
|
||||
}
|
||||
else
|
||||
{
|
||||
double menuLeftWidth = double.Parse(value.ToString());
|
||||
return (MainWindow.mainWindow.Width - menuLeftWidth) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,9 @@
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Deterministic>true</Deterministic>
|
||||
<TargetFrameworkProfile />
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
@@ -30,11 +33,8 @@
|
||||
<MapFileExtensions>true</MapFileExtensions>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
@@ -52,7 +52,7 @@
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<OutputPath>bin\GeekDesk\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
@@ -61,7 +61,8 @@
|
||||
<GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<StartupObject>GeekDesk.App</StartupObject>
|
||||
<StartupObject>
|
||||
</StartupObject>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SignManifests>false</SignManifests>
|
||||
@@ -75,6 +76,9 @@
|
||||
<PropertyGroup>
|
||||
<GenerateManifests>false</GenerateManifests>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="CommonServiceLocator, Version=2.0.6.0, Culture=neutral, PublicKeyToken=489b6accfaf20ef0, processorArchitecture=MSIL">
|
||||
<HintPath>packages\CommonServiceLocator.2.0.6\lib\net45\CommonServiceLocator.dll</HintPath>
|
||||
@@ -85,9 +89,6 @@
|
||||
<Reference Include="HandyControl, Version=3.3.0.0, Culture=neutral, PublicKeyToken=45be8712787a1e5b, processorArchitecture=MSIL">
|
||||
<HintPath>packages\HandyControl.3.3.0\lib\net472\HandyControl.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="KeyMouseHook, Version=1.0.6.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>packages\KeyMouseHook.1.0.6\lib\net40\KeyMouseHook.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Extensions.Logging.Abstractions, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Microsoft.Extensions.Logging.Abstractions.2.1.1\lib\netstandard2.0\Microsoft.Extensions.Logging.Abstractions.dll</HintPath>
|
||||
</Reference>
|
||||
@@ -113,6 +114,7 @@
|
||||
<Reference Include="System.Drawing.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Drawing.Common.6.0.0-preview.6.21352.12\lib\net461\System.Drawing.Common.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Management" />
|
||||
<Reference Include="System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Memory.4.5.4\lib\net461\System.Memory.dll</HintPath>
|
||||
</Reference>
|
||||
@@ -170,6 +172,7 @@
|
||||
<Compile Include="Constant\TodoTaskExecType.cs" />
|
||||
<Compile Include="Constant\BGStyle.cs" />
|
||||
<Compile Include="Constant\UpdateType.cs" />
|
||||
<Compile Include="Constant\WidthTypeEnum.cs" />
|
||||
<Compile Include="Control\Other\GlobalMsgNotification.xaml.cs">
|
||||
<DependentUpon>GlobalMsgNotification.xaml</DependentUpon>
|
||||
</Compile>
|
||||
@@ -251,7 +254,7 @@
|
||||
<Compile Include="Converts\StringAppendConvert.cs" />
|
||||
<Compile Include="Converts\DoubleToGridLength.cs" />
|
||||
<Compile Include="Converts\MenuInfoConvert.cs" />
|
||||
<Compile Include="Converts\SearchResWidth.cs" />
|
||||
<Compile Include="Converts\GetWidthByWWConvert.cs" />
|
||||
<Compile Include="Converts\SortTypeConvert.cs" />
|
||||
<Compile Include="Converts\TodoTaskExecConvert.cs" />
|
||||
<Compile Include="Converts\IntToCornerRadius.cs" />
|
||||
@@ -265,7 +268,10 @@
|
||||
<Compile Include="Converts\HideTypeConvert.cs" />
|
||||
<Compile Include="Interface\IWindowCommon.cs" />
|
||||
<Compile Include="MyThread\RelativePathThread.cs" />
|
||||
<Compile Include="Task\ShowSecondTask.cs" />
|
||||
<Compile Include="Plugins\ShowSeconds\ViewModel\SecondsDataContext.cs" />
|
||||
<Compile Include="Plugins\ShowSeconds\SecondsWindow.xaml.cs">
|
||||
<DependentUpon>SecondsWindow.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Task\ToDoTask.cs" />
|
||||
<Compile Include="MyThread\MouseHookThread.cs" />
|
||||
<Compile Include="MyThread\DispatcherBuild.cs" />
|
||||
@@ -279,6 +285,7 @@
|
||||
<Compile Include="Util\CommonCode.cs" />
|
||||
<Compile Include="Util\FileIcon.cs" />
|
||||
<Compile Include="Util\FileUtil.cs" />
|
||||
<Compile Include="Util\HideWindowUtil.cs" />
|
||||
<Compile Include="Util\KeyUtil.cs" />
|
||||
<Compile Include="Util\ListBoxDragDropManager.cs" />
|
||||
<Compile Include="Util\LogUtil.cs" />
|
||||
@@ -287,13 +294,18 @@
|
||||
<Compile Include="Util\ImageUtil.cs" />
|
||||
<Compile Include="Converts\MenuWidthConvert.cs" />
|
||||
<Compile Include="Util\MD5Util.cs" />
|
||||
<Compile Include="Util\MessageUtil.cs" />
|
||||
<Compile Include="Util\MouseHook.cs" />
|
||||
<Compile Include="Util\MouseUtil.cs" />
|
||||
<Compile Include="Util\RegisterUtil.cs" />
|
||||
<Compile Include="Util\RelayCommand.cs" />
|
||||
<Compile Include="Util\ScreenUtil.cs" />
|
||||
<Compile Include="Util\ScrollUtil.cs" />
|
||||
<Compile Include="Util\ShellContextMenu.cs" />
|
||||
<Compile Include="Util\ShowWindowFollowMouse.cs" />
|
||||
<Compile Include="Util\StringUtil.cs" />
|
||||
<Compile Include="Util\SvgToGeometry.cs" />
|
||||
<Compile Include="Util\UserActivityHook.cs" />
|
||||
<Compile Include="ViewModel\AppConfig.cs" />
|
||||
<Compile Include="ViewModel\AppData.cs" />
|
||||
<Compile Include="ViewModel\GradientBGParam.cs" />
|
||||
@@ -416,6 +428,10 @@
|
||||
<DependentUpon>MainWindow.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Page Include="Plugins\ShowSeconds\SecondsWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Resource\Dictionary\Geometry.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
@@ -449,6 +465,7 @@
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<Resource Include="Resource\Iconfont\iconfont.json" />
|
||||
<None Include="app.manifest" />
|
||||
<None Include="Properties\app.manifest" />
|
||||
<None Include="Update.json" />
|
||||
<None Include="packages.config" />
|
||||
@@ -517,6 +534,7 @@
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
x:Name="AppWindow"
|
||||
xmlns:hc="https://handyorg.github.io/handycontrol" xmlns:viewmodel="clr-namespace:GeekDesk.ViewModel"
|
||||
d:DataContext="{d:DesignInstance Type=viewmodel:AppData}"
|
||||
Title="GeekDesk"
|
||||
Title="GeekDesk_Main_8400A17AEEF7C029"
|
||||
MinWidth="600"
|
||||
MinHeight="400"
|
||||
WindowStyle="None"
|
||||
|
||||
@@ -10,6 +10,7 @@ using GeekDesk.ViewModel;
|
||||
using GeekDesk.ViewModel.Temp;
|
||||
using Microsoft.Win32;
|
||||
using NPinyin;
|
||||
using ShowSeconds;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
@@ -106,6 +107,11 @@ namespace GeekDesk
|
||||
|
||||
if (!RunTimeStatus.SEARCH_BOX_SHOW) ShowSearchBox();
|
||||
|
||||
//刷新搜索后 鼠标移动次数置为0
|
||||
RunTimeStatus.MOUSE_MOVE_COUNT = 0;
|
||||
//隐藏popup
|
||||
RightCard.MyPoptip.IsOpen = false;
|
||||
|
||||
string inputText = SearchBox.Text.ToLower();
|
||||
RightCard.VerticalUFG.Visibility = Visibility.Collapsed;
|
||||
if (!string.IsNullOrEmpty(inputText))
|
||||
@@ -168,7 +174,6 @@ namespace GeekDesk
|
||||
this.Height = appData.AppConfig.WindowHeight;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 窗口加载完毕 执行方法
|
||||
/// </summary>
|
||||
@@ -176,6 +181,8 @@ namespace GeekDesk
|
||||
/// <param name="e"></param>
|
||||
void Window_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
SecondsWindow.ShowWindow();
|
||||
|
||||
BGSettingUtil.BGSetting();
|
||||
if (!appData.AppConfig.StartedShowPanel)
|
||||
{
|
||||
@@ -185,7 +192,6 @@ namespace GeekDesk
|
||||
{
|
||||
ShowApp();
|
||||
}
|
||||
//ShowSecondTask.SHowSecond();
|
||||
//给任务栏图标一个名字
|
||||
BarIcon.Text = Constants.MY_NAME;
|
||||
|
||||
@@ -210,11 +216,12 @@ namespace GeekDesk
|
||||
RegisterUtil.SetSelfStarting(appData.AppConfig.SelfStartUp, Constants.MY_NAME);
|
||||
}
|
||||
|
||||
//注册鼠标中键监听事件
|
||||
if (appData.AppConfig.MouseMiddleShow)
|
||||
//注册鼠标监听事件
|
||||
if (appData.AppConfig.MouseMiddleShow || appData.AppConfig.SecondsWindow==true)
|
||||
{
|
||||
MouseHookThread.MiddleHook();
|
||||
MouseHookThread.Hook();
|
||||
}
|
||||
|
||||
|
||||
//更新线程开启 检测更新
|
||||
UpdateThread.Update();
|
||||
@@ -224,6 +231,8 @@ namespace GeekDesk
|
||||
|
||||
//毛玻璃 暂时未解决阴影问题
|
||||
//BlurGlassUtil.EnableBlur(this);
|
||||
|
||||
MessageUtil.ChangeWindowMessageFilter(MessageUtil.WM_COPYDATA, 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -452,6 +461,11 @@ namespace GeekDesk
|
||||
else
|
||||
{
|
||||
appData.AppConfig.IsShow = null;
|
||||
//防止永远不显示界面
|
||||
if (mainWindow.Opacity < 1)
|
||||
{
|
||||
mainWindow.Opacity = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -663,7 +677,7 @@ namespace GeekDesk
|
||||
/// <param name="e"></param>
|
||||
private void ExitApp(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (appData.AppConfig.MouseMiddleShow)
|
||||
if (appData.AppConfig.MouseMiddleShow || appData.AppConfig.SecondsWindow==true)
|
||||
{
|
||||
MouseHookThread.Dispose();
|
||||
}
|
||||
@@ -676,7 +690,7 @@ namespace GeekDesk
|
||||
/// <param name="e"></param>
|
||||
private void ReStartApp(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (appData.AppConfig.MouseMiddleShow)
|
||||
if (appData.AppConfig.MouseMiddleShow || appData.AppConfig.SecondsWindow == true)
|
||||
{
|
||||
MouseHookThread.Dispose();
|
||||
}
|
||||
@@ -838,6 +852,30 @@ namespace GeekDesk
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnSourceInitialized(EventArgs e)
|
||||
{
|
||||
base.OnSourceInitialized(e);
|
||||
HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource;
|
||||
if (hwndSource != null)
|
||||
{
|
||||
IntPtr handle = hwndSource.Handle;
|
||||
hwndSource.AddHook(new HwndSourceHook(WndProc));
|
||||
}
|
||||
}
|
||||
|
||||
IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
|
||||
{
|
||||
if (msg == MessageUtil.WM_COPYDATA)
|
||||
{
|
||||
MessageUtil.CopyDataStruct cds = (MessageUtil.CopyDataStruct)System.Runtime.InteropServices.Marshal.PtrToStructure(lParam, typeof(MessageUtil.CopyDataStruct));
|
||||
if ("ShowApp".Equals(cds.msg))
|
||||
{
|
||||
ShowApp();
|
||||
}
|
||||
}
|
||||
return hwnd;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
using GeekDesk.Control.UserControls.Config;
|
||||
using GeekDesk.Control.Windows;
|
||||
using GeekDesk.Util;
|
||||
using GeekDesk.ViewModel;
|
||||
using Gma.System.MouseKeyHook;
|
||||
using ShowSeconds;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
using System.Windows.Threading;
|
||||
|
||||
@@ -9,28 +14,46 @@ namespace GeekDesk.MyThread
|
||||
{
|
||||
public class MouseHookThread
|
||||
{
|
||||
private static AppConfig appConfig = MainWindow.appData.AppConfig;
|
||||
private static IKeyboardMouseEvents m_GlobalHook = Hook.GlobalEvents();
|
||||
private static Dispatcher dispatcher;
|
||||
private static readonly AppConfig appConfig = MainWindow.appData.AppConfig;
|
||||
public static Dispatcher dispatcher;
|
||||
private static UserActivityHook hook;
|
||||
|
||||
|
||||
|
||||
public static void MiddleHook()
|
||||
public static void Hook()
|
||||
{
|
||||
//使用dispatcher来单独监听UI线程 防止程序卡顿
|
||||
//使用dispatcher来单独监听UI线程 防止程序卡顿
|
||||
dispatcher = DispatcherBuild.Build();
|
||||
m_GlobalHook = Hook.GlobalEvents();
|
||||
dispatcher.BeginInvoke((Action)(() =>
|
||||
dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
|
||||
{
|
||||
m_GlobalHook.MouseUpExt += M_GlobalHook_MouseUpExt;
|
||||
hook = new UserActivityHook();
|
||||
|
||||
if (appConfig.MouseMiddleShow)
|
||||
{
|
||||
hook.OnMouseWheelUp += OnMouseWheelUp;
|
||||
}
|
||||
|
||||
if (appConfig.SecondsWindow == true)
|
||||
{
|
||||
hook.OnMouseLeftDown += OnMouseLeftDown;
|
||||
hook.OnMouseLeftUp += OnMouseLeftUp;
|
||||
}
|
||||
|
||||
hook.Start(true, false);
|
||||
}));
|
||||
}
|
||||
|
||||
public static void Dispose()
|
||||
private static void OnMouseLeftDown(object sender, System.Windows.Forms.MouseEventArgs e)
|
||||
{
|
||||
m_GlobalHook.MouseUpExt -= M_GlobalHook_MouseUpExt;
|
||||
m_GlobalHook.Dispose();
|
||||
dispatcher.InvokeShutdown();
|
||||
SecondsWindow.SecondsBakColorFun(sender, e);
|
||||
}
|
||||
|
||||
private static void OnMouseLeftUp(object sender, System.Windows.Forms.MouseEventArgs e)
|
||||
{
|
||||
SecondsWindow.SecondsHookSetFuc(sender, e);
|
||||
}
|
||||
|
||||
private static void OnMouseWheelUp(object sender, System.Windows.Forms.MouseEventArgs e)
|
||||
{
|
||||
MouseWheelShowApp(sender, e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -38,26 +61,55 @@ namespace GeekDesk.MyThread
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private static void M_GlobalHook_MouseUpExt(object sender, System.Windows.Forms.MouseEventArgs e)
|
||||
private static void MouseWheelShowApp(object sender, System.Windows.Forms.MouseEventArgs e)
|
||||
{
|
||||
if (appConfig.MouseMiddleShow && e.Button == System.Windows.Forms.MouseButtons.Middle)
|
||||
//中键打开App
|
||||
if (appConfig.MouseMiddleShow && MotionControl.hotkeyFinished)
|
||||
{
|
||||
if (MotionControl.hotkeyFinished)
|
||||
App.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
|
||||
{
|
||||
App.Current.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Render, new Action(() =>
|
||||
if (MainWindow.mainWindow.Visibility == Visibility.Collapsed || MainWindow.mainWindow.Opacity == 0)
|
||||
{
|
||||
if (MainWindow.mainWindow.Visibility == Visibility.Collapsed || MainWindow.mainWindow.Opacity == 0)
|
||||
{
|
||||
MainWindow.ShowApp();
|
||||
}
|
||||
else
|
||||
{
|
||||
MainWindow.HideApp();
|
||||
}
|
||||
}));
|
||||
}
|
||||
MainWindow.ShowApp();
|
||||
}
|
||||
else
|
||||
{
|
||||
MainWindow.HideApp();
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (hook != null)
|
||||
{
|
||||
if (hook.MouseWheelUpEnable())
|
||||
{
|
||||
hook.OnMouseWheelUp -= OnMouseWheelUp;
|
||||
}
|
||||
if (hook.MouseLeftDownEnable())
|
||||
{
|
||||
hook.OnMouseLeftDown -= OnMouseLeftDown;
|
||||
}
|
||||
if (hook.MouseLeftUpEnable())
|
||||
{
|
||||
hook.OnMouseLeftUp -= OnMouseLeftUp;
|
||||
}
|
||||
hook.Stop();
|
||||
dispatcher.InvokeShutdown();
|
||||
hook = null;
|
||||
dispatcher = null;
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
LogUtil.WriteErrorLog(ex, "关闭hook出错");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,13 +2,9 @@
|
||||
using GeekDesk.Util;
|
||||
using GeekDesk.ViewModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GeekDesk.MyThread
|
||||
{
|
||||
@@ -18,24 +14,32 @@ namespace GeekDesk.MyThread
|
||||
{
|
||||
new Thread(() =>
|
||||
{
|
||||
ObservableCollection<MenuInfo> menuList = MainWindow.appData.MenuList;
|
||||
|
||||
string myExePath = Constants.APP_DIR + "GeekDesk.exe";
|
||||
foreach (MenuInfo mi in menuList)
|
||||
try
|
||||
{
|
||||
ObservableCollection<IconInfo> iconList = mi.IconList;
|
||||
foreach (IconInfo icon in iconList)
|
||||
ObservableCollection<MenuInfo> menuList = MainWindow.appData.MenuList;
|
||||
|
||||
string myExePath = Constants.APP_DIR + "GeekDesk.exe";
|
||||
foreach (MenuInfo mi in menuList)
|
||||
{
|
||||
string relativePath = FileUtil.MakeRelativePath(myExePath, icon.Path);
|
||||
if (File.Exists(icon.Path)
|
||||
&& !string.IsNullOrEmpty(relativePath)
|
||||
&& !relativePath.Equals(icon.Path)) {
|
||||
icon.RelativePath_NoWrite = relativePath;
|
||||
ObservableCollection<IconInfo> iconList = mi.IconList;
|
||||
foreach (IconInfo icon in iconList)
|
||||
{
|
||||
if (icon == null) continue;
|
||||
string relativePath = FileUtil.MakeRelativePath(myExePath, icon.Path);
|
||||
if (File.Exists(icon.Path)
|
||||
&& !string.IsNullOrEmpty(relativePath)
|
||||
&& !relativePath.Equals(icon.Path))
|
||||
{
|
||||
icon.RelativePath_NoWrite = relativePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
CommonCode.SaveAppData(MainWindow.appData, Constants.DATA_FILE_PATH);
|
||||
CommonCode.SaveAppData(MainWindow.appData, Constants.DATA_FILE_BAK_PATH);
|
||||
} catch (Exception ex)
|
||||
{
|
||||
LogUtil.WriteErrorLog(ex, "init相对路径出错!");
|
||||
}
|
||||
CommonCode.SaveAppData(MainWindow.appData, Constants.DATA_FILE_PATH);
|
||||
CommonCode.SaveAppData(MainWindow.appData, Constants.DATA_FILE_BAK_PATH);
|
||||
}).Start();
|
||||
}
|
||||
}
|
||||
|
||||
34
Plugins/ShowSeconds/SecondsWindow.xaml
Normal file
34
Plugins/ShowSeconds/SecondsWindow.xaml
Normal file
@@ -0,0 +1,34 @@
|
||||
<Window x:Class="ShowSeconds.SecondsWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:hc="https://handyorg.github.io/handycontrol"
|
||||
xmlns:xf="clr-namespace:XamlFlair;assembly=XamlFlair.WPF"
|
||||
Height="90"
|
||||
Width="160"
|
||||
WindowStyle="None"
|
||||
Title="ShowSeconds_Main_8400A17AEEF7C029"
|
||||
AllowsTransparency="True"
|
||||
Background="Transparent"
|
||||
ShowInTaskbar="False"
|
||||
Focusable="True"
|
||||
Loaded="Window_Loaded"
|
||||
ShowActivated="False"
|
||||
>
|
||||
|
||||
<Grid Margin="20">
|
||||
<Grid.Effect>
|
||||
<DropShadowEffect BlurRadius="20" Direction="-90" Color="Gray"
|
||||
RenderingBias="Quality" ShadowDepth="2"/>
|
||||
</Grid.Effect>
|
||||
<Border x:Name="BGBorder" CornerRadius="8" xf:Animations.Primary="{xf:Animate BasedOn={StaticResource FadeInAndSlideFromRight}, Event=Visibility, Delay=0}">
|
||||
<TextBlock x:Name="SecondsText" HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="25"
|
||||
FontWeight="Bold"
|
||||
Foreground="White"
|
||||
Text="{Binding Seconds}"/>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Window>
|
||||
367
Plugins/ShowSeconds/SecondsWindow.xaml.cs
Normal file
367
Plugins/ShowSeconds/SecondsWindow.xaml.cs
Normal file
@@ -0,0 +1,367 @@
|
||||
using GeekDesk;
|
||||
using GeekDesk.MyThread;
|
||||
using GeekDesk.Util;
|
||||
using ShowSeconds.ViewModel;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Timers;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace ShowSeconds
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
public partial class SecondsWindow : Window
|
||||
{
|
||||
|
||||
private static Color beforeColor;
|
||||
private static Color topBeforeColor;
|
||||
|
||||
//dark theam
|
||||
private readonly static System.Windows.Media.SolidColorBrush darkBG
|
||||
= new System.Windows.Media.SolidColorBrush
|
||||
{
|
||||
Color = System.Windows.Media.Color.FromRgb(46, 50, 54),
|
||||
Opacity = 0.8
|
||||
};
|
||||
private readonly static System.Windows.Media.SolidColorBrush darkFont
|
||||
= new System.Windows.Media.SolidColorBrush
|
||||
{
|
||||
Color = System.Windows.Media.Color.FromRgb(255, 255, 255)
|
||||
};
|
||||
|
||||
//light theam
|
||||
private readonly static System.Windows.Media.SolidColorBrush lightBG
|
||||
= new System.Windows.Media.SolidColorBrush
|
||||
{
|
||||
Color = System.Windows.Media.Color.FromRgb(236, 244, 251),
|
||||
Opacity = 1
|
||||
};
|
||||
private readonly static System.Windows.Media.SolidColorBrush lightFont
|
||||
= new System.Windows.Media.SolidColorBrush
|
||||
{
|
||||
Color = System.Windows.Media.Color.FromRgb(65, 63, 61),
|
||||
};
|
||||
|
||||
private static bool expandClock = true; //是否展开时钟
|
||||
private static System.Windows.Forms.Timer timer;
|
||||
private static double lProportion = 0.82;
|
||||
private static double tProportion = 0.03;
|
||||
private static int sleepTime = 800;
|
||||
public SecondsWindow()
|
||||
{
|
||||
SecondsDataContext dc = new SecondsDataContext
|
||||
{
|
||||
Seconds = (DateTime.Now.Hour).ToString() + ":" +
|
||||
FormatMS(DateTime.Now.Minute) + ":" +
|
||||
FormatMS(DateTime.Now.Second)
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
Hashtable settings = (Hashtable)ConfigurationManager.GetSection("ShowSecondsSettings");
|
||||
|
||||
lProportion = Convert.ToDouble(settings["LProportion"]);
|
||||
tProportion = Convert.ToDouble(settings["TProportion"]);
|
||||
sleepTime = Convert.ToInt32(settings["DelayTime"]);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
lProportion = 0.82;
|
||||
tProportion = 0.03;
|
||||
sleepTime = 800;
|
||||
}
|
||||
|
||||
InitializeComponent();
|
||||
this.DataContext = dc;
|
||||
this.Topmost = true;
|
||||
BGBorder.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
private void Window_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
timer = new System.Windows.Forms.Timer();
|
||||
timer.Interval = 1000;
|
||||
timer.Tick += Timer_Tick;
|
||||
HideWindowUtil.HideAltTab(this);
|
||||
}
|
||||
|
||||
public static void SecondsHookSetFuc(object sender, System.Windows.Forms.MouseEventArgs e)
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem(state =>
|
||||
{
|
||||
window.Dispatcher.Invoke(() =>
|
||||
{
|
||||
if (ScreenUtil.IsPrimaryFullScreen()) return;
|
||||
|
||||
App.Current.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Render, new Action(() =>
|
||||
{
|
||||
int x = e.X;
|
||||
int y = e.Y;
|
||||
|
||||
//获取实际坐标 windows可能会有缩放
|
||||
IntPtr hdc = GetDC(IntPtr.Zero);
|
||||
double scale = ScreenUtil.GetScreenScalingFactor();
|
||||
|
||||
x = (int)(x / scale);
|
||||
y = (int)(y / scale);
|
||||
|
||||
double w = 1920;
|
||||
double h = 1080;
|
||||
double width = SystemParameters.PrimaryScreenWidth;
|
||||
double height = SystemParameters.PrimaryScreenHeight;
|
||||
|
||||
if (x > 1843 / w * width
|
||||
&& x < 1907 / w * width
|
||||
&& y > 1037 / h * height
|
||||
&& y < 1074 / h * height)
|
||||
{
|
||||
Color c;
|
||||
int count = sleepTime;
|
||||
do
|
||||
{
|
||||
c = GetBottomBeforeColor();
|
||||
if (c.A != beforeColor.A
|
||||
|| c.R != beforeColor.R
|
||||
|| c.G != beforeColor.G
|
||||
|| c.B != beforeColor.B)
|
||||
{
|
||||
break;
|
||||
}
|
||||
Thread.Sleep(50);
|
||||
count -= 50;
|
||||
} while (count > 0);
|
||||
|
||||
if (c.A != beforeColor.A
|
||||
|| c.R != beforeColor.R
|
||||
|| c.G != beforeColor.G
|
||||
|| c.B != beforeColor.B)
|
||||
{
|
||||
//判断是否展开时钟
|
||||
Color ct = GetTopBeforeColor();
|
||||
if (ct.A != topBeforeColor.A
|
||||
|| ct.R != topBeforeColor.R
|
||||
|| ct.G != topBeforeColor.G
|
||||
|| ct.B != topBeforeColor.B)
|
||||
{
|
||||
expandClock = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
expandClock = false;
|
||||
}
|
||||
|
||||
if (!window.BGBorder.IsVisible)
|
||||
{
|
||||
Color theamColor = GetColor(1919, 1079);
|
||||
if (CalculateLight(theamColor) > 255 / 2)
|
||||
{
|
||||
//light
|
||||
window.BGBorder.Background = lightBG;
|
||||
window.SecondsText.Foreground = lightFont;
|
||||
}
|
||||
else
|
||||
{
|
||||
// dark
|
||||
window.BGBorder.Background = darkBG;
|
||||
window.SecondsText.Foreground = darkFont;
|
||||
}
|
||||
|
||||
SecondsDataContext dc = window.DataContext as SecondsDataContext;
|
||||
dc.Seconds = (DateTime.Now.Hour).ToString() + ":" +
|
||||
FormatMS(DateTime.Now.Minute) + ":" +
|
||||
FormatMS(DateTime.Now.Second);
|
||||
|
||||
int sx = (int)(width * lProportion);
|
||||
int sMarginBottom = (int)(height * tProportion);
|
||||
window.Left = sx - window.Width;
|
||||
window.Top = SystemParameters.WorkArea.Height - window.Height;
|
||||
window.BGBorder.Visibility = Visibility.Visible;
|
||||
timer.Start();
|
||||
}
|
||||
else
|
||||
{
|
||||
window.BGBorder.Visibility = Visibility.Collapsed;
|
||||
timer.Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((expandClock && (x < 1574 / w * width
|
||||
|| x > 1906 / w * width
|
||||
|| y < 598 / h * height
|
||||
|| y > 1020 / h * height)
|
||||
)
|
||||
|| !expandClock && (x < 1574 / w * width
|
||||
|| x > 1906 / w * width
|
||||
|| y < 950 / h * height
|
||||
|| y > 1020 / h * height)
|
||||
)
|
||||
{
|
||||
window.BGBorder.Visibility = Visibility.Collapsed;
|
||||
timer.Stop();
|
||||
}
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public static void SecondsBakColorFun(object sender, System.Windows.Forms.MouseEventArgs e)
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem(state =>
|
||||
{
|
||||
window.Dispatcher.Invoke(() =>
|
||||
{
|
||||
beforeColor = GetBottomBeforeColor();
|
||||
topBeforeColor = GetTopBeforeColor();
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void Timer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
string str = (DateTime.Now.Hour).ToString() + ":" +
|
||||
FormatMS(DateTime.Now.Minute) + ":" +
|
||||
FormatMS(DateTime.Now.Second);
|
||||
SecondsDataContext dc = this.DataContext as SecondsDataContext;
|
||||
dc.Seconds = str;
|
||||
|
||||
this.DataContext = null;
|
||||
this.DataContext = dc;
|
||||
}
|
||||
|
||||
private static string FormatMS(int ms)
|
||||
{
|
||||
if (ms < 10)
|
||||
{
|
||||
return "0" + ms;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ms.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
private static Color GetBottomBeforeColor()
|
||||
{
|
||||
return GetColor(1760, 985);
|
||||
}
|
||||
|
||||
private static Color GetTopBeforeColor()
|
||||
{
|
||||
return GetColor(1751, 693);
|
||||
}
|
||||
|
||||
private static Color GetColor(int w2, int h2)
|
||||
{
|
||||
double w = 1920;
|
||||
double h = 1080;
|
||||
double width = SystemParameters.PrimaryScreenWidth;
|
||||
double height = SystemParameters.PrimaryScreenHeight;
|
||||
double scale = ScreenUtil.GetScreenScalingFactor();
|
||||
|
||||
System.Drawing.Point p = new System.Drawing.Point((int)(w2 / w * width * scale), (int)(h2 / h * height * scale));
|
||||
return ScreenUtil.GetColorAt(p);
|
||||
}
|
||||
|
||||
protected override void OnSourceInitialized(EventArgs e)
|
||||
{
|
||||
base.OnSourceInitialized(e);
|
||||
HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource;
|
||||
if (hwndSource != null)
|
||||
{
|
||||
IntPtr handle = hwndSource.Handle;
|
||||
hwndSource.AddHook(new HwndSourceHook(WndProc));
|
||||
}
|
||||
}
|
||||
|
||||
IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
|
||||
{
|
||||
if (msg == MessageUtil.WM_COPYDATA)
|
||||
{
|
||||
MessageUtil.CopyDataStruct cds = (MessageUtil.CopyDataStruct)System.Runtime.InteropServices.Marshal.PtrToStructure(lParam, typeof(MessageUtil.CopyDataStruct));
|
||||
|
||||
if ("Shutdown".Equals(cds.msg))
|
||||
{
|
||||
Application.Current.Shutdown();
|
||||
}
|
||||
}
|
||||
return hwnd;
|
||||
}
|
||||
|
||||
|
||||
private static int CalculateLight(Color color)
|
||||
{
|
||||
int[] colorArr = new int[] {color.R, color.G, color.B};
|
||||
|
||||
int max = 0;
|
||||
int min = 255;
|
||||
foreach (int i in colorArr)
|
||||
{
|
||||
max = Math.Max(max, i);
|
||||
min = Math.Min(min, i);
|
||||
}
|
||||
int avg = (max + min) / 2;
|
||||
return avg;
|
||||
}
|
||||
|
||||
private static SecondsWindow window = null;
|
||||
public static void ShowWindow()
|
||||
{
|
||||
if (window == null || !window.Activate())
|
||||
{
|
||||
window = new SecondsWindow();
|
||||
}
|
||||
window.Show();
|
||||
Keyboard.Focus(window);
|
||||
}
|
||||
|
||||
|
||||
//#######################################################
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 该函数检索一指定窗口的客户区域或整个屏幕的显示设备上下文环境的句柄,
|
||||
/// 以后可以在GDI函数中使用该句柄来在设备上下文环境中绘图。
|
||||
/// </summary>
|
||||
/// <param name="hWnd">设备上下文环境被检索的窗口的句柄,如果该值为NULL,GetDC则检索整个屏幕的设备上下文环境。</param>
|
||||
/// <returns>如果成功,返回指定窗口客户区的设备上下文环境;如果失败,返回值为Null。</returns>
|
||||
[DllImport("user32")]
|
||||
public static extern IntPtr GetDC(IntPtr hWnd);
|
||||
/// <summary>
|
||||
/// 该函数释放设备上下文环境(DC)供其他应用程序使用。函数的效果与设备上下文环境类型有关。
|
||||
/// 它只释放公用的和设备上下文环境,对于类或私有的则无效。
|
||||
/// </summary>
|
||||
/// <param name="hWnd">指向要释放的设备上下文环境所在的窗口的句柄。</param>
|
||||
/// <param name="hDC">指向要释放的设备上下文环境的句柄。</param>
|
||||
/// <returns>如果释放成功,则返回值为1;如果没有释放成功,则返回值为0。</returns>
|
||||
[DllImport("user32")]
|
||||
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
|
||||
[DllImport("user32")]
|
||||
public static extern bool GetCursorPos(out System.Drawing.Point pt);
|
||||
|
||||
}
|
||||
}
|
||||
25
Plugins/ShowSeconds/ViewModel/SecondsDataContext.cs
Normal file
25
Plugins/ShowSeconds/ViewModel/SecondsDataContext.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System.ComponentModel;
|
||||
|
||||
|
||||
namespace ShowSeconds.ViewModel
|
||||
{
|
||||
public class SecondsDataContext : INotifyPropertyChanged
|
||||
{
|
||||
private string seconds;
|
||||
public string Seconds
|
||||
{
|
||||
set
|
||||
{
|
||||
seconds = value;
|
||||
OnPropertyChanged("Seconds");
|
||||
}
|
||||
get { return seconds; }
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
private void OnPropertyChanged(string propertyName)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GeekDesk.Task
|
||||
{
|
||||
internal class ShowSecondTask
|
||||
{
|
||||
|
||||
public static void SHowSecond()
|
||||
{
|
||||
System.Timers.Timer timer = new System.Timers.Timer
|
||||
{
|
||||
Enabled = true,
|
||||
Interval = 5000
|
||||
};
|
||||
timer.Start();
|
||||
timer.Elapsed += Timer_Elapsed;
|
||||
}
|
||||
|
||||
private static void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
|
||||
{
|
||||
Process[] pcArr = Process.GetProcessesByName("ShellExperienceHost.exe");
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,7 @@ namespace GeekDesk.Task
|
||||
}
|
||||
}
|
||||
}
|
||||
ClearMemory();
|
||||
//ClearMemory();
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"title": "GeekDesk版本更新",
|
||||
"subTitle": "V2.5.11",
|
||||
"subTitle": "V2.5.12",
|
||||
"msgTitle": "本次更新内容如下",
|
||||
"msg": "['依旧耗费了我大量精力开发,希望大家去给我点个免费的Star', '这个版本有一些优化点, 大家可以自行探索, 另外征集新Logo的设计, 要求美观并能体现\\'极客\\'风格','本次重新打包了程序文件(文件目录更清爽了,注意,这次不要使用覆盖升级(2.5.10可覆盖)), 可以将旧版本根目录下的Data文件复制到新版本根目录, 然后使用新版本启动','修复了2.5.10版本部分相对路径创建导致启动崩溃的bug','增加可拖动图标到其它菜单的功能,取消了拖动时的动画','增加了列表展开动画的开关','增加了数据备份功能','优化大部分动画','优化搜索功能(达到了可只用键盘或只用鼠标启动所需目标)','增加了相对路径(实验性,可能有bug)','增加列表加密功能(实验性,可能有bug)','其它已知问题修复']",
|
||||
"msg": "['求Star,求Star', '集成Win11显秒插件', '崩溃问题修复', '现在在右侧栏(快捷图标区域)也可以鼠标滚轮切换菜单了', '缩放屏幕截图问题修复(感谢@1062406901提的PR)', '其它已知问题修复']",
|
||||
"githubUrl": "https://github.com/BookerLiu/GeekDesk/releases",
|
||||
"giteeUrl": "https://gitee.com/BookerLiu/GeekDesk/releases",
|
||||
"version": "2.5.11"
|
||||
"version": "2.5.12"
|
||||
}
|
||||
@@ -142,26 +142,7 @@ namespace GeekDesk.Util
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 判断当前屏幕(鼠标最后活动屏幕)是否有全屏化应用
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static bool IsPrimaryFullScreen()
|
||||
{
|
||||
RECT rect = new RECT();
|
||||
GetWindowRect(new HandleRef(null, GetForegroundWindow()), ref rect);
|
||||
|
||||
int windowHeight = rect.bottom - rect.top;
|
||||
int screenHeight = (int)SystemParameters.PrimaryScreenHeight;
|
||||
|
||||
if (windowHeight >= screenHeight)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 根据路径获取文件图标等信息
|
||||
@@ -263,21 +244,7 @@ namespace GeekDesk.Util
|
||||
}
|
||||
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct RECT
|
||||
{
|
||||
public int left;
|
||||
public int top;
|
||||
public int right;
|
||||
public int bottom;
|
||||
}
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern bool GetWindowRect(HandleRef hWnd, [In, Out] ref RECT rect);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern IntPtr GetForegroundWindow();
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -179,5 +179,25 @@ namespace GeekDesk.Util
|
||||
return relativePath;
|
||||
}
|
||||
|
||||
|
||||
public static FileInfo GetFileByNameWithDir(string name, string dir)
|
||||
{
|
||||
DirectoryInfo d = new DirectoryInfo(dir);
|
||||
FileInfo[] files = d.GetFiles();//文件
|
||||
foreach (FileInfo fi in files)
|
||||
{
|
||||
if (fi.Name.Equals(name))
|
||||
{
|
||||
return fi;
|
||||
}
|
||||
}
|
||||
DirectoryInfo[] directs = d.GetDirectories();
|
||||
foreach (DirectoryInfo direct in directs)
|
||||
{
|
||||
return GetFileByNameWithDir(name, direct.FullName);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
227
Util/HideWindowUtil.cs
Normal file
227
Util/HideWindowUtil.cs
Normal file
@@ -0,0 +1,227 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Interop;
|
||||
|
||||
namespace GeekDesk.Util
|
||||
{
|
||||
public class HideWindowUtil
|
||||
{
|
||||
|
||||
public enum GetWindowLongFields
|
||||
{
|
||||
// ...
|
||||
GWL_EXSTYLE = (-20),
|
||||
// ...
|
||||
}
|
||||
|
||||
public static void HideAltTab(Window window)
|
||||
{
|
||||
try
|
||||
{
|
||||
WindowInteropHelper wndHelper = new WindowInteropHelper(window);
|
||||
int exStyle = (int)HideWindowUtil.GetWindowLong(wndHelper.Handle, (int)HideWindowUtil.GetWindowLongFields.GWL_EXSTYLE);
|
||||
exStyle |= (int)HideWindowUtil.ExtendedWindowStyles.WS_EX_TOOLWINDOW;
|
||||
HideWindowUtil.SetWindowLong(wndHelper.Handle, (int)HideWindowUtil.GetWindowLongFields.GWL_EXSTYLE, (IntPtr)exStyle);
|
||||
} catch (Exception e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern IntPtr GetWindowLong(IntPtr hWnd, int nIndex);
|
||||
|
||||
public static IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong)
|
||||
{
|
||||
int error = 0;
|
||||
IntPtr result = IntPtr.Zero;
|
||||
// Win32 SetWindowLong doesn't clear error on success
|
||||
SetLastError(0);
|
||||
|
||||
if (IntPtr.Size == 4)
|
||||
{
|
||||
// use SetWindowLong
|
||||
Int32 tempResult = IntSetWindowLong(hWnd, nIndex, IntPtrToInt32(dwNewLong));
|
||||
error = Marshal.GetLastWin32Error();
|
||||
result = new IntPtr(tempResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
// use SetWindowLongPtr
|
||||
result = IntSetWindowLongPtr(hWnd, nIndex, dwNewLong);
|
||||
error = Marshal.GetLastWin32Error();
|
||||
}
|
||||
|
||||
if ((result == IntPtr.Zero) && (error != 0))
|
||||
{
|
||||
throw new System.ComponentModel.Win32Exception(error);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr", SetLastError = true)]
|
||||
private static extern IntPtr IntSetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
|
||||
|
||||
[DllImport("user32.dll", EntryPoint = "SetWindowLong", SetLastError = true)]
|
||||
private static extern Int32 IntSetWindowLong(IntPtr hWnd, int nIndex, Int32 dwNewLong);
|
||||
|
||||
private static int IntPtrToInt32(IntPtr intPtr)
|
||||
{
|
||||
return unchecked((int)intPtr.ToInt64());
|
||||
}
|
||||
|
||||
[DllImport("kernel32.dll", EntryPoint = "SetLastError")]
|
||||
public static extern void SetLastError(int dwErrorCode);
|
||||
/// <summary>
|
||||
/// 扩展的窗口风格
|
||||
/// </summary>
|
||||
/// 代码:[Extended Window Styles (Windows)](https://msdn.microsoft.com/en-us/library/windows/desktop/ff700543(v=vs.85).aspx )
|
||||
/// code from [Extended Window Styles (Windows)](https://msdn.microsoft.com/en-us/library/windows/desktop/ff700543(v=vs.85).aspx )
|
||||
[Flags]
|
||||
public enum ExtendedWindowStyles : long
|
||||
{
|
||||
/// <summary>
|
||||
/// The window accepts drag-drop files
|
||||
/// </summary>
|
||||
WS_EX_ACCEPTFILES = 0x00000010L,
|
||||
|
||||
/// <summary>
|
||||
/// Forces a top-level window onto the taskbar when the window is visible
|
||||
/// </summary>
|
||||
WS_EX_APPWINDOW = 0x00040000L,
|
||||
|
||||
/// <summary>
|
||||
/// The window has a border with a sunken edge.
|
||||
/// </summary>
|
||||
WS_EX_CLIENTEDGE = 0x00000200L,
|
||||
|
||||
/// <summary>
|
||||
/// Paints all descendants of a window in bottom-to-top painting order using double-buffering. For more information, see Remarks. This cannot be used if the window has a class style of either CS_OWNDC or CS_CLASSDC.Windows 2000: This style is not supported.
|
||||
/// </summary>
|
||||
WS_EX_COMPOSITED = 0x02000000L,
|
||||
|
||||
/// <summary>
|
||||
/// The title bar of the window includes a question mark. When the user clicks the question mark, the cursor changes to a question mark with a pointer. If the user then clicks a child window, the child receives a WM_HELP message. The child window should pass the message to the parent window procedure, which should call the WinHelp function using the HELP_WM_HELP command. The Help application displays a pop-up window that typically contains help for the child window.WS_EX_CONTEXTHELP cannot be used with the WS_MAXIMIZEBOX or WS_MINIMIZEBOX styles.
|
||||
/// </summary>
|
||||
WS_EX_CONTEXTHELP = 0x00000400L,
|
||||
|
||||
/// <summary>
|
||||
/// The window itself contains child windows that should take part in dialog box navigation. If this style is specified, the dialog manager recurses into children of this window when performing navigation operations such as handling the TAB key, an arrow key, or a keyboard mnemonic.
|
||||
/// </summary>
|
||||
WS_EX_CONTROLPARENT = 0x00010000L,
|
||||
|
||||
/// <summary>
|
||||
/// The window has a double border; the window can, optionally, be created with a title bar by specifying the WS_CAPTION style in the dwStyle parameter.
|
||||
/// </summary>
|
||||
WS_EX_DLGMODALFRAME = 0x00000001L,
|
||||
|
||||
/// <summary>
|
||||
/// The window is a layered window. This style cannot be used if the window has a class style of either CS_OWNDC or CS_CLASSDC.Windows 8: The WS_EX_LAYERED style is supported for top-level windows and child windows. Previous Windows versions support WS_EX_LAYERED only for top-level windows.
|
||||
/// </summary>
|
||||
WS_EX_LAYERED = 0x00080000,
|
||||
|
||||
/// <summary>
|
||||
/// If the shell language is Hebrew, Arabic, or another language that supports reading order alignment, the horizontal origin of the window is on the right edge. Increasing horizontal values advance to the left.
|
||||
/// </summary>
|
||||
WS_EX_LAYOUTRTL = 0x00400000L,
|
||||
|
||||
/// <summary>
|
||||
/// The window has generic left-aligned properties. This is the default.
|
||||
/// </summary>
|
||||
WS_EX_LEFT = 0x00000000L,
|
||||
|
||||
/// <summary>
|
||||
/// If the shell language is Hebrew, Arabic, or another language that supports reading order alignment, the vertical scroll bar (if present) is to the left of the client area. For other languages, the style is ignored.
|
||||
/// </summary>
|
||||
WS_EX_LEFTSCROLLBAR = 0x00004000L,
|
||||
|
||||
/// <summary>
|
||||
/// The window text is displayed using left-to-right reading-order properties. This is the default.
|
||||
/// </summary>
|
||||
WS_EX_LTRREADING = 0x00000000L,
|
||||
|
||||
/// <summary>
|
||||
/// The window is a MDI child window.
|
||||
/// </summary>
|
||||
WS_EX_MDICHILD = 0x00000040L,
|
||||
|
||||
/// <summary>
|
||||
/// A top-level window created with this style does not become the foreground window when the user clicks it. The system does not bring this window to the foreground when the user minimizes or closes the foreground window.To activate the window, use the SetActiveWindow or SetForegroundWindow function.The window does not appear on the taskbar by default. To force the window to appear on the taskbar, use the WS_EX_APPWINDOW style.
|
||||
/// </summary>
|
||||
WS_EX_NOACTIVATE = 0x08000000L,
|
||||
|
||||
/// <summary>
|
||||
/// The window does not pass its window layout to its child windows.
|
||||
/// </summary>
|
||||
WS_EX_NOINHERITLAYOUT = 0x00100000L,
|
||||
|
||||
/// <summary>
|
||||
/// The child window created with this style does not send the WM_PARENTNOTIFY message to its parent window when it is created or destroyed.
|
||||
/// </summary>
|
||||
WS_EX_NOPARENTNOTIFY = 0x00000004L,
|
||||
|
||||
/// <summary>
|
||||
/// The window does not render to a redirection surface. This is for windows that do not have visible content or that use mechanisms other than surfaces to provide their visual.
|
||||
/// </summary>
|
||||
WS_EX_NOREDIRECTIONBITMAP = 0x00200000L,
|
||||
|
||||
/// <summary>
|
||||
/// The window is an overlapped window.
|
||||
/// </summary>
|
||||
WS_EX_OVERLAPPEDWINDOW = (WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE),
|
||||
|
||||
/// <summary>
|
||||
/// The window is palette window, which is a modeless dialog box that presents an array of commands.
|
||||
/// </summary>
|
||||
WS_EX_PALETTEWINDOW = (WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST),
|
||||
|
||||
/// <summary>
|
||||
/// The window has generic "right-aligned" properties. This depends on the window class. This style has an effect only if the shell language is Hebrew, Arabic, or another language that supports reading-order alignment; otherwise, the style is ignored.Using the WS_EX_RIGHT style for static or edit controls has the same effect as using the SS_RIGHT or ES_RIGHT style, respectively. Using this style with button controls has the same effect as using BS_RIGHT and BS_RIGHTBUTTON styles.
|
||||
/// </summary>
|
||||
WS_EX_RIGHT = 0x00001000L,
|
||||
|
||||
/// <summary>
|
||||
/// The vertical scroll bar (if present) is to the right of the client area. This is the default.
|
||||
/// </summary>
|
||||
WS_EX_RIGHTSCROLLBAR = 0x00000000L,
|
||||
|
||||
/// <summary>
|
||||
/// If the shell language is Hebrew, Arabic, or another language that supports reading-order alignment, the window text is displayed using right-to-left reading-order properties. For other languages, the style is ignored.
|
||||
/// </summary>
|
||||
WS_EX_RTLREADING = 0x00002000L,
|
||||
|
||||
/// <summary>
|
||||
/// The window has a three-dimensional border style intended to be used for items that do not accept user input.
|
||||
/// </summary>
|
||||
WS_EX_STATICEDGE = 0x00020000L,
|
||||
|
||||
/// <summary>
|
||||
/// The window is intended to be used as a floating toolbar. A tool window has a title bar that is shorter than a normal title bar, and the window title is drawn using a smaller font. A tool window does not appear in the taskbar or in the dialog that appears when the user presses ALT+TAB. If a tool window has a system menu, its icon is not displayed on the title bar. However, you can display the system menu by right-clicking or by typing ALT+SPACE.
|
||||
/// </summary>
|
||||
WS_EX_TOOLWINDOW = 0x00000080L,
|
||||
|
||||
/// <summary>
|
||||
/// The window should be placed above all non-topmost windows and should stay above them, even when the window is deactivated. To add or remove this style, use the SetWindowPos function.
|
||||
/// </summary>
|
||||
WS_EX_TOPMOST = 0x00000008L,
|
||||
|
||||
/// <summary>
|
||||
/// The window should not be painted until siblings beneath the window (that were created by the same thread) have been painted. The window appears transparent because the bits of underlying sibling windows have already been painted.To achieve transparency without these restrictions, use the SetWindowRgn function.
|
||||
/// </summary>
|
||||
WS_EX_TRANSPARENT = 0x00000020L,
|
||||
|
||||
/// <summary>
|
||||
/// The window has a border with a raised edge
|
||||
/// </summary>
|
||||
WS_EX_WINDOWEDGE = 0x00000100L
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -490,6 +490,7 @@ namespace GeekDesk.Util
|
||||
return false;
|
||||
|
||||
ListBoxItem item = this.GetListBoxItem( this.indexToSelect );
|
||||
if (item == null) return false;
|
||||
Rect bounds = VisualTreeHelper.GetDescendantBounds( item );
|
||||
Point ptInItem = this.listBox.TranslatePoint( this.ptMouseDown, item );
|
||||
|
||||
|
||||
131
Util/MessageUtil.cs
Normal file
131
Util/MessageUtil.cs
Normal file
@@ -0,0 +1,131 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GeekDesk.Util
|
||||
{
|
||||
public class MessageUtil
|
||||
{
|
||||
|
||||
public const int WM_COPYDATA = 0x004A;
|
||||
public static bool SendMsgByPName(string processName, string msg)
|
||||
{
|
||||
try
|
||||
{
|
||||
Process[] processArr = Process.GetProcessesByName(processName);
|
||||
if (processArr != null && processArr.Length > 0)
|
||||
{
|
||||
foreach (Process process in processArr)
|
||||
{
|
||||
IntPtr windowHandle = process.MainWindowHandle;
|
||||
// 发送消息
|
||||
CopyDataStruct cds = new CopyDataStruct(IntPtr.Zero, msg);
|
||||
SendMessage(
|
||||
windowHandle,
|
||||
WM_COPYDATA,
|
||||
0, ref cds);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} catch (Exception e)
|
||||
{
|
||||
LogUtil.WriteErrorLog(e, processName + "P发送消息失败!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool SendMsgByWName(string windowName, string msg)
|
||||
{
|
||||
try
|
||||
{
|
||||
IntPtr hwnd = FindWindow(null, windowName);
|
||||
if (hwnd != IntPtr.Zero)
|
||||
{
|
||||
// 发送消息
|
||||
CopyDataStruct cds = new CopyDataStruct(IntPtr.Zero, msg);
|
||||
SendMessage(
|
||||
hwnd,
|
||||
WM_COPYDATA,
|
||||
0, ref cds);
|
||||
} else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LogUtil.WriteErrorLog(e, windowName + "W发送消息失败!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static bool CheckProcessIsRuning(string processName)
|
||||
{
|
||||
try
|
||||
{
|
||||
Process[] processArr = Process.GetProcessesByName(processName);
|
||||
return (processArr != null && processArr.Length > 0);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LogUtil.WriteErrorLog(e, processName + "检查进程名失败!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool CheckWindowIsRuning(string windowName)
|
||||
{
|
||||
try
|
||||
{
|
||||
IntPtr hwnd = FindWindow(null, windowName);
|
||||
return (hwnd != IntPtr.Zero);
|
||||
} catch(Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
[DllImport("User32.dll", EntryPoint = "FindWindow")]
|
||||
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
|
||||
|
||||
[DllImport("User32.dll", EntryPoint = "SendMessage")]
|
||||
private static extern int SendMessage(
|
||||
IntPtr hWnd, //目标窗体句柄
|
||||
int Msg, //WM_COPYDATA
|
||||
int wParam, //自定义数值
|
||||
ref CopyDataStruct lParam //传递消息的结构体,
|
||||
);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct CopyDataStruct
|
||||
{
|
||||
public CopyDataStruct(IntPtr custom, string msg)
|
||||
{
|
||||
this.custom = custom;
|
||||
this.msg = msg;
|
||||
this.msgLength = msg.Length + 1;
|
||||
}
|
||||
public IntPtr custom;//用户定义数据
|
||||
public int msgLength;//字符串长度
|
||||
[MarshalAs(UnmanagedType.LPStr)]
|
||||
public string msg;//字符串
|
||||
}
|
||||
|
||||
|
||||
[DllImport("user32")]
|
||||
public static extern bool ChangeWindowMessageFilter(uint msg, int flags);
|
||||
|
||||
}
|
||||
}
|
||||
156
Util/MouseHook.cs
Normal file
156
Util/MouseHook.cs
Normal file
@@ -0,0 +1,156 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace GeekDesk.Util
|
||||
{
|
||||
public class MouseHook
|
||||
{
|
||||
|
||||
private Point point;
|
||||
private Point Point
|
||||
{
|
||||
get { return point; }
|
||||
set
|
||||
{
|
||||
if (point != value)
|
||||
{
|
||||
point = value;
|
||||
if (MouseMoveEvent != null)
|
||||
{
|
||||
var e = new MouseEventArgs(MouseButtons.None, 0, point.X, point.Y, 0);
|
||||
MouseMoveEvent(this, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private int hHook;
|
||||
private const int WM_MOUSEMOVE = 0x200;
|
||||
private const int WM_LBUTTONDOWN = 0x201;
|
||||
private const int WM_RBUTTONDOWN = 0x204;
|
||||
private const int WM_MBUTTONDOWN = 0x207;
|
||||
private const int WM_LBUTTONUP = 0x202;
|
||||
private const int WM_RBUTTONUP = 0x205;
|
||||
private const int WM_MBUTTONUP = 0x208;
|
||||
private const int WM_LBUTTONDBLCLK = 0x203;
|
||||
private const int WM_RBUTTONDBLCLK = 0x206;
|
||||
private const int WM_MBUTTONDBLCLK = 0x209;
|
||||
public const int WH_MOUSE_LL = 14;
|
||||
public Win32Api.HookProc hProc;
|
||||
public MouseHook()
|
||||
{
|
||||
this.Point = new Point();
|
||||
}
|
||||
public int SetHook()
|
||||
{
|
||||
hProc = new Win32Api.HookProc(MouseHookProc);
|
||||
hHook = Win32Api.SetWindowsHookEx(WH_MOUSE_LL, hProc, IntPtr.Zero, 0);
|
||||
return hHook;
|
||||
}
|
||||
public void UnHook()
|
||||
{
|
||||
Win32Api.UnhookWindowsHookEx(hHook);
|
||||
}
|
||||
private int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
Win32Api.MouseHookStruct MyMouseHookStruct = (Win32Api.MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(Win32Api.MouseHookStruct));
|
||||
if (nCode < 0)
|
||||
{
|
||||
return Win32Api.CallNextHookEx(hHook, nCode, wParam, lParam);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (MouseClickEvent != null)
|
||||
{
|
||||
MouseButtons button = MouseButtons.None;
|
||||
int clickCount = 0;
|
||||
switch ((Int32)wParam)
|
||||
{
|
||||
case WM_LBUTTONDOWN:
|
||||
button = MouseButtons.Left;
|
||||
clickCount = 1;
|
||||
MouseDownEvent(this, new MouseEventArgs(button, clickCount, point.X, point.Y, 0));
|
||||
break;
|
||||
case WM_RBUTTONDOWN:
|
||||
button = MouseButtons.Right;
|
||||
clickCount = 1;
|
||||
MouseDownEvent(this, new MouseEventArgs(button, clickCount, point.X, point.Y, 0));
|
||||
break;
|
||||
case WM_MBUTTONDOWN:
|
||||
button = MouseButtons.Middle;
|
||||
clickCount = 1;
|
||||
MouseDownEvent(this, new MouseEventArgs(button, clickCount, point.X, point.Y, 0));
|
||||
break;
|
||||
case WM_LBUTTONUP:
|
||||
button = MouseButtons.Left;
|
||||
clickCount = 1;
|
||||
MouseUpEvent(this, new MouseEventArgs(button, clickCount, point.X, point.Y, 0));
|
||||
break;
|
||||
case WM_RBUTTONUP:
|
||||
button = MouseButtons.Right;
|
||||
clickCount = 1;
|
||||
MouseUpEvent(this, new MouseEventArgs(button, clickCount, point.X, point.Y, 0));
|
||||
break;
|
||||
case WM_MBUTTONUP:
|
||||
button = MouseButtons.Middle;
|
||||
clickCount = 1;
|
||||
MouseUpEvent(this, new MouseEventArgs(button, clickCount, point.X, point.Y, 0));
|
||||
break;
|
||||
}
|
||||
|
||||
var e = new MouseEventArgs(button, clickCount, point.X, point.Y, 0);
|
||||
MouseClickEvent(this, e);
|
||||
}
|
||||
this.Point = new Point(MyMouseHookStruct.pt.x, MyMouseHookStruct.pt.y);
|
||||
return Win32Api.CallNextHookEx(hHook, nCode, wParam, lParam);
|
||||
}
|
||||
}
|
||||
|
||||
public delegate void MouseMoveHandler(object sender, MouseEventArgs e);
|
||||
public event MouseMoveHandler MouseMoveEvent;
|
||||
|
||||
public delegate void MouseClickHandler(object sender, MouseEventArgs e);
|
||||
public event MouseClickHandler MouseClickEvent;
|
||||
|
||||
public delegate void MouseDownHandler(object sender, MouseEventArgs e);
|
||||
public event MouseDownHandler MouseDownEvent;
|
||||
|
||||
public delegate void MouseUpHandler(object sender, MouseEventArgs e);
|
||||
public event MouseUpHandler MouseUpEvent;
|
||||
|
||||
|
||||
public class Win32Api
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class POINT
|
||||
{
|
||||
public int x;
|
||||
public int y;
|
||||
}
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class MouseHookStruct
|
||||
{
|
||||
public POINT pt;
|
||||
public int hwnd;
|
||||
public int wHitTestCode;
|
||||
public int dwExtraInfo;
|
||||
}
|
||||
public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern bool UnhookWindowsHookEx(int idHook);
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
156
Util/ScreenUtil.cs
Normal file
156
Util/ScreenUtil.cs
Normal file
@@ -0,0 +1,156 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace GeekDesk.Util
|
||||
{
|
||||
public class ScreenUtil
|
||||
{
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
static extern bool GetCursorPos(ref System.Drawing.Point lpPoint);
|
||||
|
||||
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
|
||||
public static extern int BitBlt(IntPtr hDC, int x, int y, int nWidth, int nHeight, IntPtr hSrcDC, int xSrc, int ySrc, int dwRop);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct RECT
|
||||
{
|
||||
public int left;
|
||||
public int top;
|
||||
public int right;
|
||||
public int bottom;
|
||||
}
|
||||
|
||||
//取得前台窗口句柄函数
|
||||
[DllImport("user32.dll")]
|
||||
private static extern IntPtr GetForegroundWindow();
|
||||
//取得桌面窗口句柄函数
|
||||
[DllImport("user32.dll")]
|
||||
private static extern IntPtr GetDesktopWindow();
|
||||
//取得Shell窗口句柄函数
|
||||
[DllImport("user32.dll")]
|
||||
private static extern IntPtr GetShellWindow();
|
||||
//取得窗口大小函数
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
private static extern int GetWindowRect(IntPtr hwnd, out RECT rc);
|
||||
//获取窗口标题
|
||||
[DllImport("user32", SetLastError = true)]
|
||||
private static extern int GetWindowText(
|
||||
IntPtr hWnd,//窗口句柄
|
||||
StringBuilder lpString,//标题
|
||||
int nMaxCount //最大值
|
||||
);
|
||||
|
||||
//获取类的名字
|
||||
[DllImport("user32.dll")]
|
||||
private static extern int GetClassName(
|
||||
IntPtr hWnd,//句柄
|
||||
StringBuilder lpString, //类名
|
||||
int nMaxCount); //最大值
|
||||
|
||||
/// <summary>
|
||||
/// 判断当前屏幕(鼠标最后活动屏幕)是否有全屏化应用
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static bool IsPrimaryFullScreen()
|
||||
{
|
||||
|
||||
//桌面窗口句柄
|
||||
IntPtr desktopHandle; //Window handle for the desktop
|
||||
//Shell窗口句柄
|
||||
IntPtr shellHandle; //Window handle for the shell 因为桌面窗口和Shell窗口也是全屏,要排除在其他全屏程序之外。 //取得桌面和Shell窗口句柄
|
||||
desktopHandle = GetDesktopWindow();
|
||||
shellHandle = GetShellWindow(); //取得前台窗口句柄并判断是否全屏
|
||||
bool runningFullScreen = false;
|
||||
RECT appBounds;
|
||||
Rectangle screenBounds;
|
||||
IntPtr hWnd;
|
||||
//取得前台窗口
|
||||
hWnd = GetForegroundWindow();
|
||||
|
||||
StringBuilder sb = new StringBuilder(256);
|
||||
try
|
||||
{
|
||||
GetClassName(hWnd, sb, sb.Capacity);
|
||||
}
|
||||
catch { }
|
||||
if (sb.ToString().ToLower().Equals("workerw")) return false;
|
||||
if (hWnd != null && !hWnd.Equals(IntPtr.Zero))
|
||||
{
|
||||
//判断是否桌面或shell
|
||||
if (!(hWnd.Equals(desktopHandle) || hWnd.Equals(shellHandle)))
|
||||
{
|
||||
//取得窗口大小
|
||||
GetWindowRect(hWnd, out appBounds);
|
||||
//判断是否全屏
|
||||
screenBounds = Screen.FromHandle(hWnd).Bounds;
|
||||
if ((appBounds.bottom - appBounds.top) == screenBounds.Height
|
||||
&& (appBounds.right - appBounds.left) == screenBounds.Width)
|
||||
runningFullScreen = true;
|
||||
}
|
||||
}
|
||||
return runningFullScreen;
|
||||
}
|
||||
|
||||
|
||||
public static Color GetColorAt(System.Drawing.Point location)
|
||||
{
|
||||
Bitmap screenPixel = new Bitmap(1, 1, PixelFormat.Format32bppArgb);
|
||||
|
||||
using (Graphics gdest = Graphics.FromImage(screenPixel))
|
||||
{
|
||||
using (Graphics gsrc = Graphics.FromHwnd(IntPtr.Zero))
|
||||
{
|
||||
IntPtr hSrcDC = gsrc.GetHdc();
|
||||
IntPtr hDC = gdest.GetHdc();
|
||||
int retval = BitBlt(hDC, 0, 0, 1, 1, hSrcDC, location.X, location.Y, (int)CopyPixelOperation.SourceCopy);
|
||||
gdest.ReleaseHdc();
|
||||
gsrc.ReleaseHdc();
|
||||
}
|
||||
}
|
||||
|
||||
return screenPixel.GetPixel(0, 0);
|
||||
}
|
||||
|
||||
|
||||
[DllImport("gdi32")]
|
||||
static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
|
||||
|
||||
public const int HORZRES = 8;
|
||||
public const int VERTRES = 10;
|
||||
public const int DESKTOPVERTRES = 117;
|
||||
public const int DESKTOPHORZRES = 118;
|
||||
/// <summary>
|
||||
/// 获取屏幕缩放比例
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static double GetScreenScalingFactor()
|
||||
{
|
||||
try
|
||||
{
|
||||
var g = Graphics.FromHwnd(IntPtr.Zero);
|
||||
IntPtr desktop = g.GetHdc();
|
||||
var physicalScreenHeight = GetDeviceCaps(desktop, (int)DESKTOPVERTRES);
|
||||
|
||||
var screenScalingFactor =
|
||||
(double)physicalScreenHeight / SystemParameters.PrimaryScreenHeight;
|
||||
//SystemParameters.PrimaryScreenHeight;
|
||||
|
||||
return screenScalingFactor;
|
||||
} catch (Exception e)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
75
Util/ScrollUtil.cs
Normal file
75
Util/ScrollUtil.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace GeekDesk.Util
|
||||
{
|
||||
public class ScrollUtil
|
||||
{
|
||||
|
||||
public static bool IsBootomScrollView(ScrollViewer view)
|
||||
{
|
||||
try
|
||||
{
|
||||
bool isBottom = false;
|
||||
double dVer = view.VerticalOffset;
|
||||
double vViewport = view.ViewportHeight;
|
||||
double eextent = view.ExtentHeight;
|
||||
if (dVer + vViewport >= eextent)
|
||||
{
|
||||
isBottom = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
isBottom = false;
|
||||
}
|
||||
return isBottom;
|
||||
} catch (Exception e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static bool IsTopScrollView(ScrollViewer view)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (int)view.VerticalOffset == 0;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static T FindSimpleVisualChild<T>(DependencyObject element) where T : class
|
||||
{
|
||||
try
|
||||
{
|
||||
while (element != null)
|
||||
{
|
||||
|
||||
if (element is T)
|
||||
return element as T;
|
||||
if (VisualTreeHelper.GetChildrenCount(element) > 0)
|
||||
{
|
||||
element = VisualTreeHelper.GetChild(element, 0);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
837
Util/UserActivityHook.cs
Normal file
837
Util/UserActivityHook.cs
Normal file
@@ -0,0 +1,837 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace GeekDesk.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// This class allows you to tap keyboard and mouse and / or to detect their activity even when an
|
||||
/// application runes in background or does not have any user interface at all. This class raises
|
||||
/// common .NET events with KeyEventArgs and MouseEventArgs so you can easily retrive any information you need.
|
||||
/// </summary>
|
||||
public class UserActivityHook
|
||||
{
|
||||
#region Windows structure definitions
|
||||
|
||||
/// <summary>
|
||||
/// The POINT structure defines the x- and y- coordinates of a point.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/rectangl_0tiq.asp
|
||||
/// </remarks>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private class POINT
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the x-coordinate of the point.
|
||||
/// </summary>
|
||||
public int x;
|
||||
/// <summary>
|
||||
/// Specifies the y-coordinate of the point.
|
||||
/// </summary>
|
||||
public int y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The MOUSEHOOKSTRUCT structure contains information about a mouse event passed to a WH_MOUSE hook procedure, MouseProc.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookstructures/cwpstruct.asp
|
||||
/// </remarks>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private class MouseHookStruct
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies a POINT structure that contains the x- and y-coordinates of the cursor, in screen coordinates.
|
||||
/// </summary>
|
||||
public POINT pt;
|
||||
/// <summary>
|
||||
/// Handle to the window that will receive the mouse message corresponding to the mouse event.
|
||||
/// </summary>
|
||||
public int hwnd;
|
||||
/// <summary>
|
||||
/// Specifies the hit-test value. For a list of hit-test values, see the description of the WM_NCHITTEST message.
|
||||
/// </summary>
|
||||
public int wHitTestCode;
|
||||
/// <summary>
|
||||
/// Specifies extra information associated with the message.
|
||||
/// </summary>
|
||||
public int dwExtraInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The MSLLHOOKSTRUCT structure contains information about a low-level keyboard input event.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private class MouseLLHookStruct
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies a POINT structure that contains the x- and y-coordinates of the cursor, in screen coordinates.
|
||||
/// </summary>
|
||||
public POINT pt;
|
||||
/// <summary>
|
||||
/// If the message is WM_MOUSEWHEEL, the high-order word of this member is the wheel delta.
|
||||
/// The low-order word is reserved. A positive value indicates that the wheel was rotated forward,
|
||||
/// away from the user; a negative value indicates that the wheel was rotated backward, toward the user.
|
||||
/// One wheel click is defined as WHEEL_DELTA, which is 120.
|
||||
///If the message is WM_XBUTTONDOWN, WM_XBUTTONUP, WM_XBUTTONDBLCLK, WM_NCXBUTTONDOWN, WM_NCXBUTTONUP,
|
||||
/// or WM_NCXBUTTONDBLCLK, the high-order word specifies which X button was pressed or released,
|
||||
/// and the low-order word is reserved. This value can be one or more of the following values. Otherwise, mouseData is not used.
|
||||
///XBUTTON1
|
||||
///The first X button was pressed or released.
|
||||
///XBUTTON2
|
||||
///The second X button was pressed or released.
|
||||
/// </summary>
|
||||
public int mouseData;
|
||||
/// <summary>
|
||||
/// Specifies the event-injected flag. An application can use the following value to test the mouse flags. Value Purpose
|
||||
///LLMHF_INJECTED Test the event-injected flag.
|
||||
///0
|
||||
///Specifies whether the event was injected. The value is 1 if the event was injected; otherwise, it is 0.
|
||||
///1-15
|
||||
///Reserved.
|
||||
/// </summary>
|
||||
public int flags;
|
||||
/// <summary>
|
||||
/// Specifies the time stamp for this message.
|
||||
/// </summary>
|
||||
public int time;
|
||||
/// <summary>
|
||||
/// Specifies extra information associated with the message.
|
||||
/// </summary>
|
||||
public int dwExtraInfo;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The KBDLLHOOKSTRUCT structure contains information about a low-level keyboard input event.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookstructures/cwpstruct.asp
|
||||
/// </remarks>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private class KeyboardHookStruct
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies a virtual-key code. The code must be a value in the range 1 to 254.
|
||||
/// </summary>
|
||||
public int vkCode;
|
||||
/// <summary>
|
||||
/// Specifies a hardware scan code for the key.
|
||||
/// </summary>
|
||||
public int scanCode;
|
||||
/// <summary>
|
||||
/// Specifies the extended-key flag, event-injected flag, context code, and transition-state flag.
|
||||
/// </summary>
|
||||
public int flags;
|
||||
/// <summary>
|
||||
/// Specifies the time stamp for this message.
|
||||
/// </summary>
|
||||
public int time;
|
||||
/// <summary>
|
||||
/// Specifies extra information associated with the message.
|
||||
/// </summary>
|
||||
public int dwExtraInfo;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Windows function imports
|
||||
/// <summary>
|
||||
/// The SetWindowsHookEx function installs an application-defined hook procedure into a hook chain.
|
||||
/// You would install a hook procedure to monitor the system for certain types of events. These events
|
||||
/// are associated either with a specific thread or with all threads in the same desktop as the calling thread.
|
||||
/// </summary>
|
||||
/// <param name="idHook">
|
||||
/// [in] Specifies the type of hook procedure to be installed. This parameter can be one of the following values.
|
||||
/// </param>
|
||||
/// <param name="lpfn">
|
||||
/// [in] Pointer to the hook procedure. If the dwThreadId parameter is zero or specifies the identifier of a
|
||||
/// thread created by a different process, the lpfn parameter must point to a hook procedure in a dynamic-link
|
||||
/// library (DLL). Otherwise, lpfn can point to a hook procedure in the code associated with the current process.
|
||||
/// </param>
|
||||
/// <param name="hMod">
|
||||
/// [in] Handle to the DLL containing the hook procedure pointed to by the lpfn parameter.
|
||||
/// The hMod parameter must be set to NULL if the dwThreadId parameter specifies a thread created by
|
||||
/// the current process and if the hook procedure is within the code associated with the current process.
|
||||
/// </param>
|
||||
/// <param name="dwThreadId">
|
||||
/// [in] Specifies the identifier of the thread with which the hook procedure is to be associated.
|
||||
/// If this parameter is zero, the hook procedure is associated with all existing threads running in the
|
||||
/// same desktop as the calling thread.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// If the function succeeds, the return value is the handle to the hook procedure.
|
||||
/// If the function fails, the return value is NULL. To get extended error information, call GetLastError.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookfunctions/setwindowshookex.asp
|
||||
/// </remarks>
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto,
|
||||
CallingConvention = CallingConvention.StdCall, SetLastError = true)]
|
||||
private static extern int SetWindowsHookEx(
|
||||
int idHook,
|
||||
HookProc lpfn,
|
||||
IntPtr hMod,
|
||||
int dwThreadId);
|
||||
|
||||
/// <summary>
|
||||
/// The UnhookWindowsHookEx function removes a hook procedure installed in a hook chain by the SetWindowsHookEx function.
|
||||
/// </summary>
|
||||
/// <param name="idHook">
|
||||
/// [in] Handle to the hook to be removed. This parameter is a hook handle obtained by a previous call to SetWindowsHookEx.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// If the function succeeds, the return value is nonzero.
|
||||
/// If the function fails, the return value is zero. To get extended error information, call GetLastError.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookfunctions/setwindowshookex.asp
|
||||
/// </remarks>
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto,
|
||||
CallingConvention = CallingConvention.StdCall, SetLastError = true)]
|
||||
private static extern int UnhookWindowsHookEx(int idHook);
|
||||
|
||||
/// <summary>
|
||||
/// The CallNextHookEx function passes the hook information to the next hook procedure in the current hook chain.
|
||||
/// A hook procedure can call this function either before or after processing the hook information.
|
||||
/// </summary>
|
||||
/// <param name="idHook">Ignored.</param>
|
||||
/// <param name="nCode">
|
||||
/// [in] Specifies the hook code passed to the current hook procedure.
|
||||
/// The next hook procedure uses this code to determine how to process the hook information.
|
||||
/// </param>
|
||||
/// <param name="wParam">
|
||||
/// [in] Specifies the wParam value passed to the current hook procedure.
|
||||
/// The meaning of this parameter depends on the type of hook associated with the current hook chain.
|
||||
/// </param>
|
||||
/// <param name="lParam">
|
||||
/// [in] Specifies the lParam value passed to the current hook procedure.
|
||||
/// The meaning of this parameter depends on the type of hook associated with the current hook chain.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// This value is returned by the next hook procedure in the chain.
|
||||
/// The current hook procedure must also return this value. The meaning of the return value depends on the hook type.
|
||||
/// For more information, see the descriptions of the individual hook procedures.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookfunctions/setwindowshookex.asp
|
||||
/// </remarks>
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto,
|
||||
CallingConvention = CallingConvention.StdCall)]
|
||||
private static extern int CallNextHookEx(
|
||||
int idHook,
|
||||
int nCode,
|
||||
int wParam,
|
||||
IntPtr lParam);
|
||||
|
||||
/// <summary>
|
||||
/// The CallWndProc hook procedure is an application-defined or library-defined callback
|
||||
/// function used with the SetWindowsHookEx function. The HOOKPROC type defines a pointer
|
||||
/// to this callback function. CallWndProc is a placeholder for the application-defined
|
||||
/// or library-defined function name.
|
||||
/// </summary>
|
||||
/// <param name="nCode">
|
||||
/// [in] Specifies whether the hook procedure must process the message.
|
||||
/// If nCode is HC_ACTION, the hook procedure must process the message.
|
||||
/// If nCode is less than zero, the hook procedure must pass the message to the
|
||||
/// CallNextHookEx function without further processing and must return the
|
||||
/// value returned by CallNextHookEx.
|
||||
/// </param>
|
||||
/// <param name="wParam">
|
||||
/// [in] Specifies whether the message was sent by the current thread.
|
||||
/// If the message was sent by the current thread, it is nonzero; otherwise, it is zero.
|
||||
/// </param>
|
||||
/// <param name="lParam">
|
||||
/// [in] Pointer to a CWPSTRUCT structure that contains details about the message.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// If nCode is less than zero, the hook procedure must return the value returned by CallNextHookEx.
|
||||
/// If nCode is greater than or equal to zero, it is highly recommended that you call CallNextHookEx
|
||||
/// and return the value it returns; otherwise, other applications that have installed WH_CALLWNDPROC
|
||||
/// hooks will not receive hook notifications and may behave incorrectly as a result. If the hook
|
||||
/// procedure does not call CallNextHookEx, the return value should be zero.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/hooks/hookreference/hookfunctions/callwndproc.asp
|
||||
/// </remarks>
|
||||
private delegate int HookProc(int nCode, int wParam, IntPtr lParam);
|
||||
|
||||
/// <summary>
|
||||
/// The ToAscii function translates the specified virtual-key code and keyboard
|
||||
/// state to the corresponding character or characters. The function translates the code
|
||||
/// using the input language and physical keyboard layout identified by the keyboard layout handle.
|
||||
/// </summary>
|
||||
/// <param name="uVirtKey">
|
||||
/// [in] Specifies the virtual-key code to be translated.
|
||||
/// </param>
|
||||
/// <param name="uScanCode">
|
||||
/// [in] Specifies the hardware scan code of the key to be translated.
|
||||
/// The high-order bit of this value is set if the key is up (not pressed).
|
||||
/// </param>
|
||||
/// <param name="lpbKeyState">
|
||||
/// [in] Pointer to a 256-byte array that contains the current keyboard state.
|
||||
/// Each element (byte) in the array contains the state of one key.
|
||||
/// If the high-order bit of a byte is set, the key is down (pressed).
|
||||
/// The low bit, if set, indicates that the key is toggled on. In this function,
|
||||
/// only the toggle bit of the CAPS LOCK key is relevant. The toggle state
|
||||
/// of the NUM LOCK and SCROLL LOCK keys is ignored.
|
||||
/// </param>
|
||||
/// <param name="lpwTransKey">
|
||||
/// [out] Pointer to the buffer that receives the translated character or characters.
|
||||
/// </param>
|
||||
/// <param name="fuState">
|
||||
/// [in] Specifies whether a menu is active. This parameter must be 1 if a menu is active, or 0 otherwise.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// If the specified key is a dead key, the return value is negative. Otherwise, it is one of the following values.
|
||||
/// Value Meaning
|
||||
/// 0 The specified virtual key has no translation for the current state of the keyboard.
|
||||
/// 1 One character was copied to the buffer.
|
||||
/// 2 Two characters were copied to the buffer. This usually happens when a dead-key character
|
||||
/// (accent or diacritic) stored in the keyboard layout cannot be composed with the specified
|
||||
/// virtual key to form a single character.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/keyboardinput/keyboardinputreference/keyboardinputfunctions/toascii.asp
|
||||
/// </remarks>
|
||||
[DllImport("user32")]
|
||||
private static extern int ToAscii(
|
||||
int uVirtKey,
|
||||
int uScanCode,
|
||||
byte[] lpbKeyState,
|
||||
byte[] lpwTransKey,
|
||||
int fuState);
|
||||
|
||||
/// <summary>
|
||||
/// The GetKeyboardState function copies the status of the 256 virtual keys to the
|
||||
/// specified buffer.
|
||||
/// </summary>
|
||||
/// <param name="pbKeyState">
|
||||
/// [in] Pointer to a 256-byte array that contains keyboard key states.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// If the function succeeds, the return value is nonzero.
|
||||
/// If the function fails, the return value is zero. To get extended error information, call GetLastError.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/keyboardinput/keyboardinputreference/keyboardinputfunctions/toascii.asp
|
||||
/// </remarks>
|
||||
[DllImport("user32")]
|
||||
private static extern int GetKeyboardState(byte[] pbKeyState);
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
|
||||
private static extern short GetKeyState(int vKey);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Windows constants
|
||||
|
||||
//values from Winuser.h in Microsoft SDK.
|
||||
/// <summary>
|
||||
/// Windows NT/2000/XP: Installs a hook procedure that monitors low-level mouse input events.
|
||||
/// </summary>
|
||||
private const int WH_MOUSE_LL = 14;
|
||||
/// <summary>
|
||||
/// Windows NT/2000/XP: Installs a hook procedure that monitors low-level keyboard input events.
|
||||
/// </summary>
|
||||
private const int WH_KEYBOARD_LL = 13;
|
||||
|
||||
/// <summary>
|
||||
/// Installs a hook procedure that monitors mouse messages. For more information, see the MouseProc hook procedure.
|
||||
/// </summary>
|
||||
private const int WH_MOUSE = 7;
|
||||
/// <summary>
|
||||
/// Installs a hook procedure that monitors keystroke messages. For more information, see the KeyboardProc hook procedure.
|
||||
/// </summary>
|
||||
private const int WH_KEYBOARD = 2;
|
||||
|
||||
/// <summary>
|
||||
/// The WM_MOUSEMOVE message is posted to a window when the cursor moves.
|
||||
/// </summary>
|
||||
private const int WM_MOUSEMOVE = 0x200;
|
||||
/// <summary>
|
||||
/// The WM_LBUTTONDOWN message is posted when the user presses the left mouse button
|
||||
/// </summary>
|
||||
private const int WM_LBUTTONDOWN = 0x201;
|
||||
/// <summary>
|
||||
/// The WM_RBUTTONDOWN message is posted when the user presses the right mouse button
|
||||
/// </summary>
|
||||
private const int WM_RBUTTONDOWN = 0x204;
|
||||
/// <summary>
|
||||
/// The WM_MBUTTONDOWN message is posted when the user presses the middle mouse button
|
||||
/// </summary>
|
||||
private const int WM_MBUTTONDOWN = 0x207;
|
||||
/// <summary>
|
||||
/// The WM_LBUTTONUP message is posted when the user releases the left mouse button
|
||||
/// </summary>
|
||||
private const int WM_LBUTTONUP = 0x202;
|
||||
/// <summary>
|
||||
/// The WM_RBUTTONUP message is posted when the user releases the right mouse button
|
||||
/// </summary>
|
||||
private const int WM_RBUTTONUP = 0x205;
|
||||
/// <summary>
|
||||
/// The WM_MBUTTONUP message is posted when the user releases the middle mouse button
|
||||
/// </summary>
|
||||
private const int WM_MBUTTONUP = 0x208;
|
||||
/// <summary>
|
||||
/// The WM_LBUTTONDBLCLK message is posted when the user double-clicks the left mouse button
|
||||
/// </summary>
|
||||
private const int WM_LBUTTONDBLCLK = 0x203;
|
||||
/// <summary>
|
||||
/// The WM_RBUTTONDBLCLK message is posted when the user double-clicks the right mouse button
|
||||
/// </summary>
|
||||
private const int WM_RBUTTONDBLCLK = 0x206;
|
||||
/// <summary>
|
||||
/// The WM_RBUTTONDOWN message is posted when the user presses the right mouse button
|
||||
/// </summary>
|
||||
private const int WM_MBUTTONDBLCLK = 0x209;
|
||||
/// <summary>
|
||||
/// The WM_MOUSEWHEEL message is posted when the user presses the mouse wheel.
|
||||
/// </summary>
|
||||
private const int WM_MOUSEWHEEL = 0x020A;
|
||||
|
||||
/// <summary>
|
||||
/// The WM_KEYDOWN message is posted to the window with the keyboard focus when a nonsystem
|
||||
/// key is pressed. A nonsystem key is a key that is pressed when the ALT key is not pressed.
|
||||
/// </summary>
|
||||
private const int WM_KEYDOWN = 0x100;
|
||||
/// <summary>
|
||||
/// The WM_KEYUP message is posted to the window with the keyboard focus when a nonsystem
|
||||
/// key is released. A nonsystem key is a key that is pressed when the ALT key is not pressed,
|
||||
/// or a keyboard key that is pressed when a window has the keyboard focus.
|
||||
/// </summary>
|
||||
private const int WM_KEYUP = 0x101;
|
||||
/// <summary>
|
||||
/// The WM_SYSKEYDOWN message is posted to the window with the keyboard focus when the user
|
||||
/// presses the F10 key (which activates the menu bar) or holds down the ALT key and then
|
||||
/// presses another key. It also occurs when no window currently has the keyboard focus;
|
||||
/// in this case, the WM_SYSKEYDOWN message is sent to the active window. The window that
|
||||
/// receives the message can distinguish between these two contexts by checking the context
|
||||
/// code in the lParam parameter.
|
||||
/// </summary>
|
||||
private const int WM_SYSKEYDOWN = 0x104;
|
||||
/// <summary>
|
||||
/// The WM_SYSKEYUP message is posted to the window with the keyboard focus when the user
|
||||
/// releases a key that was pressed while the ALT key was held down. It also occurs when no
|
||||
/// window currently has the keyboard focus; in this case, the WM_SYSKEYUP message is sent
|
||||
/// to the active window. The window that receives the message can distinguish between
|
||||
/// these two contexts by checking the context code in the lParam parameter.
|
||||
/// </summary>
|
||||
private const int WM_SYSKEYUP = 0x105;
|
||||
|
||||
private const byte VK_SHIFT = 0x10;
|
||||
private const byte VK_CAPITAL = 0x14;
|
||||
private const byte VK_NUMLOCK = 0x90;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of UserActivityHook object and sets mouse and keyboard hooks.
|
||||
/// </summary>
|
||||
/// <exception cref="Win32Exception">Any windows problem.</exception>
|
||||
public UserActivityHook()
|
||||
{
|
||||
Start();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of UserActivityHook object and installs both or one of mouse and/or keyboard hooks and starts rasing events
|
||||
/// </summary>
|
||||
/// <param name="InstallMouseHook"><b>true</b> if mouse events must be monitored</param>
|
||||
/// <param name="InstallKeyboardHook"><b>true</b> if keyboard events must be monitored</param>
|
||||
/// <exception cref="Win32Exception">Any windows problem.</exception>
|
||||
/// <remarks>
|
||||
/// To create an instance without installing hooks call new UserActivityHook(false, false)
|
||||
/// </remarks>
|
||||
public UserActivityHook(bool InstallMouseHook, bool InstallKeyboardHook)
|
||||
{
|
||||
Start(InstallMouseHook, InstallKeyboardHook);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destruction.
|
||||
/// </summary>
|
||||
~UserActivityHook()
|
||||
{
|
||||
//uninstall hooks and do not throw exceptions
|
||||
Stop(true, true, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when the user moves the mouse, presses any mouse button or scrolls the wheel
|
||||
/// </summary>
|
||||
///
|
||||
public bool EnableMouse = false;
|
||||
|
||||
|
||||
public event MouseEventHandler OnMouseLeftDown;
|
||||
|
||||
public event MouseEventHandler OnMouseLeftUp;
|
||||
|
||||
public event MouseEventHandler OnMouseWheelDown;
|
||||
|
||||
public event MouseEventHandler OnMouseWheelUp;
|
||||
|
||||
public bool MouseLeftDownEnable()
|
||||
{
|
||||
return OnMouseLeftDown != null;
|
||||
}
|
||||
public bool MouseLeftUpEnable()
|
||||
{
|
||||
return OnMouseLeftUp != null;
|
||||
}
|
||||
public bool MouseWheelDownEnable()
|
||||
{
|
||||
return OnMouseWheelDown != null;
|
||||
}
|
||||
public bool MouseWheelUpEnable()
|
||||
{
|
||||
return OnMouseWheelUp != null;
|
||||
}
|
||||
/// <summary>
|
||||
/// Occurs when the user presses a key
|
||||
/// </summary>
|
||||
public event KeyEventHandler KeyDown;
|
||||
/// <summary>
|
||||
/// Occurs when the user presses and releases
|
||||
/// </summary>
|
||||
public event KeyPressEventHandler KeyPress;
|
||||
/// <summary>
|
||||
/// Occurs when the user releases a key
|
||||
/// </summary>
|
||||
public event KeyEventHandler KeyUp;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Stores the handle to the mouse hook procedure.
|
||||
/// </summary>
|
||||
private int hMouseHook = 0;
|
||||
/// <summary>
|
||||
/// Stores the handle to the keyboard hook procedure.
|
||||
/// </summary>
|
||||
private int hKeyboardHook = 0;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Declare MouseHookProcedure as HookProc type.
|
||||
/// </summary>
|
||||
private static HookProc MouseHookProcedure;
|
||||
/// <summary>
|
||||
/// Declare KeyboardHookProcedure as HookProc type.
|
||||
/// </summary>
|
||||
private static HookProc KeyboardHookProcedure;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Installs both mouse and keyboard hooks and starts rasing events
|
||||
/// </summary>
|
||||
/// <exception cref="Win32Exception">Any windows problem.</exception>
|
||||
public void Start()
|
||||
{
|
||||
this.Start(true, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Installs both or one of mouse and/or keyboard hooks and starts rasing events
|
||||
/// </summary>
|
||||
/// <param name="InstallMouseHook"><b>true</b> if mouse events must be monitored</param>
|
||||
/// <param name="InstallKeyboardHook"><b>true</b> if keyboard events must be monitored</param>
|
||||
/// <exception cref="Win32Exception">Any windows problem.</exception>
|
||||
public void Start(bool InstallMouseHook, bool InstallKeyboardHook)
|
||||
{
|
||||
this.EnableMouse = InstallMouseHook;
|
||||
// install Mouse hook only if it is not installed and must be installed
|
||||
if (hMouseHook == 0 && EnableMouse)
|
||||
{
|
||||
// Create an instance of HookProc.
|
||||
MouseHookProcedure = new HookProc(MouseHookProc);
|
||||
//install hook
|
||||
hMouseHook = SetWindowsHookEx(
|
||||
WH_MOUSE_LL,
|
||||
MouseHookProcedure,
|
||||
Marshal.GetHINSTANCE(
|
||||
Assembly.GetExecutingAssembly().GetModules()[0]),
|
||||
0);
|
||||
//If SetWindowsHookEx fails.
|
||||
if (hMouseHook == 0)
|
||||
{
|
||||
//Returns the error code returned by the last unmanaged function called using platform invoke that has the DllImportAttribute.SetLastError flag set.
|
||||
int errorCode = Marshal.GetLastWin32Error();
|
||||
//do cleanup
|
||||
Stop(true, false, false);
|
||||
//Initializes and throws a new instance of the Win32Exception class with the specified error.
|
||||
throw new Win32Exception(errorCode);
|
||||
}
|
||||
}
|
||||
|
||||
// install Keyboard hook only if it is not installed and must be installed
|
||||
if (hKeyboardHook == 0 && InstallKeyboardHook)
|
||||
{
|
||||
// Create an instance of HookProc.
|
||||
KeyboardHookProcedure = new HookProc(KeyboardHookProc);
|
||||
//install hook
|
||||
hKeyboardHook = SetWindowsHookEx(
|
||||
WH_KEYBOARD_LL,
|
||||
KeyboardHookProcedure,
|
||||
Marshal.GetHINSTANCE(
|
||||
Assembly.GetExecutingAssembly().GetModules()[0]),
|
||||
0);
|
||||
//If SetWindowsHookEx fails.
|
||||
if (hKeyboardHook == 0)
|
||||
{
|
||||
//Returns the error code returned by the last unmanaged function called using platform invoke that has the DllImportAttribute.SetLastError flag set.
|
||||
int errorCode = Marshal.GetLastWin32Error();
|
||||
//do cleanup
|
||||
Stop(false, true, false);
|
||||
//Initializes and throws a new instance of the Win32Exception class with the specified error.
|
||||
throw new Win32Exception(errorCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops monitoring both mouse and keyboard events and rasing events.
|
||||
/// </summary>
|
||||
/// <exception cref="Win32Exception">Any windows problem.</exception>
|
||||
public void Stop()
|
||||
{
|
||||
this.Stop(true, true, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops monitoring both or one of mouse and/or keyboard events and rasing events.
|
||||
/// </summary>
|
||||
/// <param name="UninstallMouseHook"><b>true</b> if mouse hook must be uninstalled</param>
|
||||
/// <param name="UninstallKeyboardHook"><b>true</b> if keyboard hook must be uninstalled</param>
|
||||
/// <param name="ThrowExceptions"><b>true</b> if exceptions which occured during uninstalling must be thrown</param>
|
||||
/// <exception cref="Win32Exception">Any windows problem.</exception>
|
||||
public void Stop(bool UninstallMouseHook, bool UninstallKeyboardHook, bool ThrowExceptions)
|
||||
{
|
||||
//if mouse hook set and must be uninstalled
|
||||
if (hMouseHook != 0 && UninstallMouseHook)
|
||||
{
|
||||
//uninstall hook
|
||||
int retMouse = UnhookWindowsHookEx(hMouseHook);
|
||||
//reset invalid handle
|
||||
hMouseHook = 0;
|
||||
//if failed and exception must be thrown
|
||||
if (retMouse == 0 && ThrowExceptions)
|
||||
{
|
||||
//Returns the error code returned by the last unmanaged function called using platform invoke that has the DllImportAttribute.SetLastError flag set.
|
||||
int errorCode = Marshal.GetLastWin32Error();
|
||||
//Initializes and throws a new instance of the Win32Exception class with the specified error.
|
||||
throw new Win32Exception(errorCode);
|
||||
}
|
||||
}
|
||||
|
||||
//if keyboard hook set and must be uninstalled
|
||||
if (hKeyboardHook != 0 && UninstallKeyboardHook)
|
||||
{
|
||||
//uninstall hook
|
||||
int retKeyboard = UnhookWindowsHookEx(hKeyboardHook);
|
||||
//reset invalid handle
|
||||
hKeyboardHook = 0;
|
||||
//if failed and exception must be thrown
|
||||
if (retKeyboard == 0 && ThrowExceptions)
|
||||
{
|
||||
//Returns the error code returned by the last unmanaged function called using platform invoke that has the DllImportAttribute.SetLastError flag set.
|
||||
int errorCode = Marshal.GetLastWin32Error();
|
||||
//Initializes and throws a new instance of the Win32Exception class with the specified error.
|
||||
throw new Win32Exception(errorCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A callback function which will be called every time a mouse activity detected.
|
||||
/// </summary>
|
||||
/// <param name="nCode">
|
||||
/// [in] Specifies whether the hook procedure must process the message.
|
||||
/// If nCode is HC_ACTION, the hook procedure must process the message.
|
||||
/// If nCode is less than zero, the hook procedure must pass the message to the
|
||||
/// CallNextHookEx function without further processing and must return the
|
||||
/// value returned by CallNextHookEx.
|
||||
/// </param>
|
||||
/// <param name="wParam">
|
||||
/// [in] Specifies whether the message was sent by the current thread.
|
||||
/// If the message was sent by the current thread, it is nonzero; otherwise, it is zero.
|
||||
/// </param>
|
||||
/// <param name="lParam">
|
||||
/// [in] Pointer to a CWPSTRUCT structure that contains details about the message.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// If nCode is less than zero, the hook procedure must return the value returned by CallNextHookEx.
|
||||
/// If nCode is greater than or equal to zero, it is highly recommended that you call CallNextHookEx
|
||||
/// and return the value it returns; otherwise, other applications that have installed WH_CALLWNDPROC
|
||||
/// hooks will not receive hook notifications and may behave incorrectly as a result. If the hook
|
||||
/// procedure does not call CallNextHookEx, the return value should be zero.
|
||||
/// </returns>
|
||||
private int MouseHookProc(int nCode, int wParam, IntPtr lParam)
|
||||
{
|
||||
// if ok and someone listens to our events
|
||||
if ((nCode >= 0) && EnableMouse)
|
||||
{
|
||||
//Marshall the data from callback.
|
||||
MouseLLHookStruct mouseHookStruct = (MouseLLHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseLLHookStruct));
|
||||
|
||||
//detect button clicked
|
||||
MouseButtons button = MouseButtons.None;
|
||||
short mouseDelta = 0;
|
||||
switch (wParam)
|
||||
{
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_LBUTTONUP:
|
||||
button = MouseButtons.Left;
|
||||
|
||||
break;
|
||||
case WM_RBUTTONDOWN:
|
||||
case WM_RBUTTONUP:
|
||||
//case WM_RBUTTONUP:
|
||||
//case WM_RBUTTONDBLCLK:
|
||||
button = MouseButtons.Right;
|
||||
break;
|
||||
case WM_MOUSEWHEEL:
|
||||
case WM_MBUTTONDOWN:
|
||||
case WM_MBUTTONUP:
|
||||
button = MouseButtons.Middle;
|
||||
//If the message is WM_MOUSEWHEEL, the high-order word of mouseData member is the wheel delta.
|
||||
//One wheel click is defined as WHEEL_DELTA, which is 120.
|
||||
//(value >> 16) & 0xffff; retrieves the high-order word from the given 32-bit value
|
||||
mouseDelta = (short)((mouseHookStruct.mouseData >> 16) & 0xffff);
|
||||
|
||||
//TODO: X BUTTONS (I havent them so was unable to test)
|
||||
//If the message is WM_XBUTTONDOWN, WM_XBUTTONUP, WM_XBUTTONDBLCLK, WM_NCXBUTTONDOWN, WM_NCXBUTTONUP,
|
||||
//or WM_NCXBUTTONDBLCLK, the high-order word specifies which X button was pressed or released,
|
||||
//and the low-order word is reserved. This value can be one or more of the following values.
|
||||
//Otherwise, mouseData is not used.
|
||||
break;
|
||||
}
|
||||
|
||||
//double clicks
|
||||
int clickCount = 0;
|
||||
if (button != MouseButtons.None)
|
||||
if (wParam == WM_LBUTTONDBLCLK || wParam == WM_RBUTTONDBLCLK) clickCount = 2;
|
||||
else clickCount = 1;
|
||||
|
||||
//generate event
|
||||
MouseEventArgs e = new MouseEventArgs(
|
||||
button,
|
||||
clickCount,
|
||||
mouseHookStruct.pt.x,
|
||||
mouseHookStruct.pt.y,
|
||||
mouseDelta);
|
||||
//raise it
|
||||
switch (wParam)
|
||||
{
|
||||
case WM_LBUTTONDOWN:
|
||||
this.OnMouseLeftDown?.Invoke(this, e);
|
||||
break;
|
||||
case WM_LBUTTONUP:
|
||||
this.OnMouseLeftUp?.Invoke(this, e);
|
||||
break;
|
||||
case WM_RBUTTONDOWN:
|
||||
break;
|
||||
case WM_RBUTTONUP:
|
||||
break;
|
||||
case WM_MOUSEWHEEL:
|
||||
break;
|
||||
case WM_MBUTTONDOWN:
|
||||
this.OnMouseWheelDown?.Invoke(this, e);
|
||||
break;
|
||||
case WM_MBUTTONUP:
|
||||
this.OnMouseWheelUp?.Invoke(this, e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
//call next hook
|
||||
return CallNextHookEx(hMouseHook, nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A callback function which will be called every time a keyboard activity detected.
|
||||
/// </summary>
|
||||
/// <param name="nCode">
|
||||
/// [in] Specifies whether the hook procedure must process the message.
|
||||
/// If nCode is HC_ACTION, the hook procedure must process the message.
|
||||
/// If nCode is less than zero, the hook procedure must pass the message to the
|
||||
/// CallNextHookEx function without further processing and must return the
|
||||
/// value returned by CallNextHookEx.
|
||||
/// </param>
|
||||
/// <param name="wParam">
|
||||
/// [in] Specifies whether the message was sent by the current thread.
|
||||
/// If the message was sent by the current thread, it is nonzero; otherwise, it is zero.
|
||||
/// </param>
|
||||
/// <param name="lParam">
|
||||
/// [in] Pointer to a CWPSTRUCT structure that contains details about the message.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// If nCode is less than zero, the hook procedure must return the value returned by CallNextHookEx.
|
||||
/// If nCode is greater than or equal to zero, it is highly recommended that you call CallNextHookEx
|
||||
/// and return the value it returns; otherwise, other applications that have installed WH_CALLWNDPROC
|
||||
/// hooks will not receive hook notifications and may behave incorrectly as a result. If the hook
|
||||
/// procedure does not call CallNextHookEx, the return value should be zero.
|
||||
/// </returns>
|
||||
private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
|
||||
{
|
||||
//indicates if any of underlaing events set e.Handled flag
|
||||
bool handled = false;
|
||||
//it was ok and someone listens to events
|
||||
if ((nCode >= 0) && (KeyDown != null || KeyUp != null || KeyPress != null))
|
||||
{
|
||||
//read structure KeyboardHookStruct at lParam
|
||||
KeyboardHookStruct MyKeyboardHookStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
|
||||
//raise KeyDown
|
||||
if (KeyDown != null && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN))
|
||||
{
|
||||
Keys keyData = (Keys)MyKeyboardHookStruct.vkCode;
|
||||
KeyEventArgs e = new KeyEventArgs(keyData);
|
||||
KeyDown(this, e);
|
||||
handled = handled || e.Handled;
|
||||
}
|
||||
|
||||
// raise KeyPress
|
||||
if (KeyPress != null && wParam == WM_KEYDOWN)
|
||||
{
|
||||
bool isDownShift = ((GetKeyState(VK_SHIFT) & 0x80) == 0x80 ? true : false);
|
||||
bool isDownCapslock = (GetKeyState(VK_CAPITAL) != 0 ? true : false);
|
||||
|
||||
byte[] keyState = new byte[256];
|
||||
GetKeyboardState(keyState);
|
||||
byte[] inBuffer = new byte[2];
|
||||
if (ToAscii(MyKeyboardHookStruct.vkCode,
|
||||
MyKeyboardHookStruct.scanCode,
|
||||
keyState,
|
||||
inBuffer,
|
||||
MyKeyboardHookStruct.flags) == 1)
|
||||
{
|
||||
char key = (char)inBuffer[0];
|
||||
if ((isDownCapslock ^ isDownShift) && Char.IsLetter(key)) key = Char.ToUpper(key);
|
||||
KeyPressEventArgs e = new KeyPressEventArgs(key);
|
||||
KeyPress(this, e);
|
||||
handled = handled || e.Handled;
|
||||
}
|
||||
}
|
||||
|
||||
// raise KeyUp
|
||||
if (KeyUp != null && (wParam == WM_KEYUP || wParam == WM_SYSKEYUP))
|
||||
{
|
||||
Keys keyData = (Keys)MyKeyboardHookStruct.vkCode;
|
||||
KeyEventArgs e = new KeyEventArgs(keyData);
|
||||
KeyUp(this, e);
|
||||
handled = handled || e.Handled;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//if event handled in application do not handoff to other listeners
|
||||
if (handled)
|
||||
return 1;
|
||||
else
|
||||
return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -103,7 +103,24 @@ namespace GeekDesk.ViewModel
|
||||
|
||||
private bool itemSpradeAnimation; //列表展开动画
|
||||
|
||||
private bool? secondsWindow; //秒数窗口 默认打开
|
||||
|
||||
#region GetSet
|
||||
|
||||
public bool? SecondsWindow
|
||||
{
|
||||
get
|
||||
{
|
||||
if (secondsWindow == null) secondsWindow = true;
|
||||
return secondsWindow;
|
||||
}
|
||||
set
|
||||
{
|
||||
secondsWindow = value;
|
||||
OnPropertyChanged("SecondsWindow");
|
||||
}
|
||||
}
|
||||
|
||||
public bool ItemSpradeAnimation
|
||||
{
|
||||
get
|
||||
|
||||
79
app.manifest
Normal file
79
app.manifest
Normal file
@@ -0,0 +1,79 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||
<security>
|
||||
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<!-- UAC 清单选项
|
||||
如果想要更改 Windows 用户帐户控制级别,请使用
|
||||
以下节点之一替换 requestedExecutionLevel 节点。
|
||||
|
||||
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
||||
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
|
||||
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
|
||||
|
||||
指定 requestedExecutionLevel 元素将禁用文件和注册表虚拟化。
|
||||
如果你的应用程序需要此虚拟化来实现向后兼容性,则移除此
|
||||
元素。
|
||||
-->
|
||||
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<!-- 设计此应用程序与其一起工作且已针对此应用程序进行测试的
|
||||
Windows 版本的列表。取消评论适当的元素,
|
||||
Windows 将自动选择最兼容的环境。 -->
|
||||
|
||||
<!-- Windows Vista -->
|
||||
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />-->
|
||||
|
||||
<!-- Windows 7 -->
|
||||
<!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />-->
|
||||
|
||||
<!-- Windows 8 -->
|
||||
<!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />-->
|
||||
|
||||
<!-- Windows 8.1 -->
|
||||
<!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />-->
|
||||
|
||||
<!-- Windows 10 -->
|
||||
<!--<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />-->
|
||||
|
||||
</application>
|
||||
</compatibility>
|
||||
|
||||
<!-- 指示该应用程序可感知 DPI 且 Windows 在 DPI 较高时将不会对其进行
|
||||
自动缩放。Windows Presentation Foundation (WPF)应用程序自动感知 DPI,无需
|
||||
选择加入。选择加入此设置的 Windows 窗体应用程序(面向 .NET Framework 4.6)还应
|
||||
在其 app.config 中将 "EnableWindowsFormsHighDpiAutoResizing" 设置设置为 "true"。
|
||||
|
||||
将应用程序设为感知长路径。请参阅 https://docs.microsoft.com/windows/win32/fileio/maximum-file-path-limitation -->
|
||||
|
||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<windowsSettings>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True/PM</dpiAware>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
|
||||
|
||||
<!-- 启用 Windows 公共控件和对话框的主题(Windows XP 和更高版本) -->
|
||||
<!--
|
||||
<dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity
|
||||
type="win32"
|
||||
name="Microsoft.Windows.Common-Controls"
|
||||
version="6.0.0.0"
|
||||
processorArchitecture="*"
|
||||
publicKeyToken="6595b64144ccf1df"
|
||||
language="*"
|
||||
/>
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
-->
|
||||
|
||||
</assembly>
|
||||
@@ -2,7 +2,6 @@
|
||||
<packages>
|
||||
<package id="CommonServiceLocator" version="2.0.6" targetFramework="net452" requireReinstallation="true" />
|
||||
<package id="HandyControl" version="3.3.0" targetFramework="net472" />
|
||||
<package id="KeyMouseHook" version="1.0.6" targetFramework="net472" developmentDependency="true" />
|
||||
<package id="Microsoft.Build.Tasks.Git" version="1.0.0" targetFramework="net472" developmentDependency="true" />
|
||||
<package id="Microsoft.Extensions.Logging.Abstractions" version="2.1.1" targetFramework="net472" />
|
||||
<package id="Microsoft.SourceLink.Common" version="1.0.0" targetFramework="net472" developmentDependency="true" />
|
||||
|
||||
Reference in New Issue
Block a user