Rename the project.

This commit is contained in:
Yeechan Lu
2014-01-29 18:33:24 +08:00
parent c217828c18
commit 4db3bd7423
149 changed files with 1593 additions and 2021 deletions

20
Wox/App.config Normal file
View File

@@ -0,0 +1,20 @@
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="log4net" type="System.Configuration.IgnoreSectionHandler"/>
</configSections>
<log4net>
<appender name="LogFileAppender" type="log4net.Appender.FileAppender">
<file value="log.txt"/>
<appendToFile value="true"/>
<rollingStyle value="Date"/>
<datePattern value="yyyyMMdd-HH:mm:ss"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="Date%date Level%-5level Msg%message%newline"/>
</layout>
</appender>
<root>
<appender-ref ref="LogFileAppender"/>
</root>
</log4net>
<startup><supportedRuntime version="v2.0.50727"/></startup></configuration>

12
Wox/App.xaml Normal file
View File

@@ -0,0 +1,12 @@
<Application x:Class="Wox.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Themes/Default.xaml"></ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>

80
Wox/App.xaml.cs Normal file
View File

@@ -0,0 +1,80 @@
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading;
using System.Windows;
using Microsoft.VisualBasic.ApplicationServices;
using Wox.Commands;
using StartupEventArgs = System.Windows.StartupEventArgs;
namespace Wox
{
public static class EntryPoint
{
[STAThread]
public static void Main(string[] args)
{
SingleInstanceManager manager = new SingleInstanceManager();
manager.Run(args);
}
}
// Using VB bits to detect single instances and process accordingly:
// * OnStartup is fired when the first instance loads
// * OnStartupNextInstance is fired when the application is re-run again
// NOTE: it is redirected to this instance thanks to IsSingleInstance
public class SingleInstanceManager : WindowsFormsApplicationBase
{
App app;
public SingleInstanceManager()
{
this.IsSingleInstance = true;
}
protected override bool OnStartup(Microsoft.VisualBasic.ApplicationServices.StartupEventArgs e)
{
// First time app is launched
app = new App();
app.InitializeComponent();
app.Run();
return true;
}
protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs)
{
// Subsequent launches
base.OnStartupNextInstance(eventArgs);
app.Activate(eventArgs.CommandLine.ToArray());
}
}
public partial class App : Application
{
private static MainWindow window;
public static MainWindow Window
{
get
{
return window;
}
}
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
window = new MainWindow();
window.ShowApp();
window.ParseArgs(e.Args);
}
public void Activate(string[] args)
{
window.ShowApp();
window.ParseArgs(args);
}
}
}

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Wox.Plugin;
namespace Wox.Commands
{
public abstract class BaseCommand
{
public abstract void Dispatch(Query query, bool updateView = true);
protected void UpdateResultView(List<Result> results)
{
App.Window.OnUpdateResultView(results);
}
}
}

View File

@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Wox.Helper;
using Wox.Plugin;
namespace Wox.Commands
{
internal static class CommandFactory
{
private static PluginCommand pluginCmd;
private static SystemCommand systemCmd;
public static void DispatchCommand(Query query, bool updateView = true)
{
//lazy init command instance.
if (pluginCmd == null)
{
pluginCmd = new PluginCommand();
}
if (systemCmd == null)
{
systemCmd = new SystemCommand();
}
systemCmd.Dispatch(query,updateView);
pluginCmd.Dispatch(query,updateView);
}
}
}

View File

@@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Python.Runtime;
using Wox.Helper;
using Wox.Plugin;
using Wox.PluginLoader;
namespace Wox.Commands
{
public class PluginCommand : BaseCommand
{
private string currentPythonModulePath = string.Empty;
private IntPtr GIL;
public override void Dispatch(Query q,bool updateView = true)
{
PluginPair thirdPlugin = Plugins.AllPlugins.FirstOrDefault(o => o.Metadata.ActionKeyword == q.ActionName);
if (thirdPlugin != null && !string.IsNullOrEmpty(thirdPlugin.Metadata.ActionKeyword))
{
if (thirdPlugin.Metadata.Language == AllowedLanguage.Python)
{
SwitchPythonEnv(thirdPlugin);
}
ThreadPool.QueueUserWorkItem(t =>
{
try
{
List<Result> r = thirdPlugin.Plugin.Query(q);
r.ForEach(o =>
{
o.PluginDirectory = thirdPlugin.Metadata.PluginDirecotry;
o.OriginQuery = q;
});
if(updateView) UpdateResultView(r);
}
catch (Exception queryException)
{
Log.Error(string.Format("Plugin {0} query failed: {1}", thirdPlugin.Metadata.Name,
queryException.Message));
#if (DEBUG)
{
throw;
}
#endif
}
});
}
}
private void SwitchPythonEnv(PluginPair thirdPlugin)
{
if (currentPythonModulePath != thirdPlugin.Metadata.PluginDirecotry)
{
//this must initial in main thread
currentPythonModulePath = thirdPlugin.Metadata.PluginDirecotry;
if (GIL != IntPtr.Zero)
{
Runtime.PyEval_RestoreThread(GIL);
PythonEngine.Shutdown();
}
PythonEngine.Initialize();
IntPtr pyStrPtr = Runtime.PyString_FromString(thirdPlugin.Metadata.PluginDirecotry);
IntPtr SysDotPath = Runtime.PySys_GetObject("path");
Runtime.PyList_Append(SysDotPath, pyStrPtr);
GIL = PythonEngine.BeginAllowThreads();
}
}
}
}

View File

@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Wox.Plugin;
using Wox.PluginLoader;
namespace Wox.Commands
{
public class SystemCommand : BaseCommand
{
private List<PluginPair> systemPlugins;
public SystemCommand()
{
systemPlugins = Plugins.AllPlugins.Where(o => o.Metadata.PluginType == PluginType.System).ToList();
}
public override void Dispatch(Query query,bool updateView = true)
{
foreach (PluginPair pair in systemPlugins)
{
PluginPair pair1 = pair;
ThreadPool.QueueUserWorkItem(state =>
{
List<Result> results = pair1.Plugin.Query(query);
foreach (Result result in results)
{
result.PluginDirectory = pair1.Metadata.PluginDirecotry;
result.OriginQuery = query;
result.AutoAjustScore = true;
}
if(results.Count > 0 && updateView) UpdateResultView(results);
});
}
}
}
}

View File

@@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Threading;
namespace Wox
{
public static class DispatcherExtensions
{
private static Dictionary<string, DispatcherTimer> timers =
new Dictionary<string, DispatcherTimer>();
private static readonly object syncRoot = new object();
public static string DelayInvoke(this Dispatcher dispatcher, string namedInvocation,
Action<string> action, TimeSpan delay,
DispatcherPriority priority = DispatcherPriority.Normal)
{
return DelayInvoke(dispatcher, namedInvocation, action, delay, string.Empty, priority);
}
public static string DelayInvoke(this Dispatcher dispatcher, string namedInvocation,
Action<string> action, TimeSpan delay, string arg,
DispatcherPriority priority = DispatcherPriority.Normal)
{
lock (syncRoot)
{
if (String.IsNullOrEmpty(namedInvocation))
{
namedInvocation = Guid.NewGuid().ToString();
}
else
{
RemoveTimer(namedInvocation);
}
var timer = new DispatcherTimer(delay, priority, (s, e) =>
{
RemoveTimer(namedInvocation);
action(arg);
}, dispatcher);
timer.Start();
timers.Add(namedInvocation, timer);
return namedInvocation;
}
}
public static void CancelNamedInvocation(this Dispatcher dispatcher, string namedInvocation)
{
lock (syncRoot)
{
RemoveTimer(namedInvocation);
}
}
private static void RemoveTimer(string namedInvocation)
{
if (!timers.ContainsKey(namedInvocation)) return;
timers[namedInvocation].Stop();
timers.Remove(namedInvocation);
}
}
}

View File

@@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading;
using Newtonsoft.Json;
using Wox.Models;
namespace Wox.Helper
{
[Serializable]
public class CommonStorage
{
private static string configPath = Directory.GetCurrentDirectory() + "\\data.json";
private static object locker = new object();
private static CommonStorage storage;
public UserSetting UserSetting { get; set; }
public UserSelectedRecords UserSelectedRecords { get; set; }
private CommonStorage()
{
//default setting
UserSetting = new UserSetting
{
Theme = "Default",
ReplaceWinR = true,
WebSearches = new List<WebSearch>()
};
UserSelectedRecords = new UserSelectedRecords();
}
public void Save()
{
lock (locker)
{
//json is a good choise, readable and flexiable
string json = JsonConvert.SerializeObject(storage, Formatting.Indented);
File.WriteAllText(configPath, json);
}
}
private static void Load()
{
if (!File.Exists(configPath))
{
File.Create(configPath).Close();
}
string json = File.ReadAllText(configPath);
if (!string.IsNullOrEmpty(json))
{
try
{
storage = JsonConvert.DeserializeObject<CommonStorage>(json);
}
catch (Exception e)
{
//on-op, keep default storage
}
}
}
public static CommonStorage Instance
{
get
{
if (storage == null)
{
lock (locker)
{
if (storage == null)
{
storage = new CommonStorage();
Load();
}
}
}
return storage;
}
}
}
}

View File

@@ -0,0 +1,73 @@
using System;
using System.Drawing.Printing;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
namespace Wox.Helper
{
public static class DwmDropShadow
{
[DllImport("dwmapi.dll", PreserveSig = true)]
private static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize);
[DllImport("dwmapi.dll")]
private static extern int DwmExtendFrameIntoClientArea(IntPtr hWnd, ref Margins pMarInset);
/// <summary>
/// Drops a standard shadow to a WPF Window, even if the window isborderless. Only works with DWM (Vista and Seven).
/// This method is much more efficient than setting AllowsTransparency to true and using the DropShadow effect,
/// as AllowsTransparency involves a huge permormance issue (hardware acceleration is turned off for all the window).
/// </summary>
/// <param name="window">Window to which the shadow will be applied</param>
public static void DropShadowToWindow(Window window)
{
if (!DropShadow(window))
{
window.SourceInitialized += new EventHandler(window_SourceInitialized);
}
}
private static void window_SourceInitialized(object sender, EventArgs e) //fixed typo
{
Window window = (Window)sender;
DropShadow(window);
window.SourceInitialized -= new EventHandler(window_SourceInitialized);
}
/// <summary>
/// The actual method that makes API calls to drop the shadow to the window
/// </summary>
/// <param name="window">Window to which the shadow will be applied</param>
/// <returns>True if the method succeeded, false if not</returns>
private static bool DropShadow(Window window)
{
try
{
WindowInteropHelper helper = new WindowInteropHelper(window);
int val = 2;
int ret1 = DwmSetWindowAttribute(helper.Handle, 2, ref val, 2);
if (ret1 == 0)
{
Margins m = new Margins { Bottom = 0, Left = 0, Right = 0, Top = 0 };
int ret2 = DwmExtendFrameIntoClientArea(helper.Handle, ref m);
return ret2 == 0;
}
else
{
return false;
}
}
catch (Exception ex)
{
// Probably dwmapi.dll not found (incompatible OS)
return false;
}
}
}
}

217
Wox/Helper/IniParser.cs Normal file
View File

@@ -0,0 +1,217 @@
using System;
using System.Collections;
using System.IO;
namespace Wox.Helper
{
public class IniParser
{
private Hashtable keyPairs = new Hashtable();
private String iniFilePath;
private struct SectionPair
{
public String Section;
public String Key;
}
/// <summary>
/// Opens the INI file at the given path and enumerates the values in the IniParser.
/// </summary>
/// <param name="iniPath">Full path to INI file.</param>
public IniParser(String iniPath)
{
TextReader iniFile = null;
String strLine = null;
String currentRoot = null;
String[] keyPair = null;
iniFilePath = iniPath;
if (File.Exists(iniPath))
{
try
{
iniFile = new StreamReader(iniPath);
strLine = iniFile.ReadLine();
while (strLine != null)
{
strLine = strLine.Trim();
if (strLine != "")
{
if (strLine.StartsWith("[") && strLine.EndsWith("]"))
{
currentRoot = strLine.Substring(1, strLine.Length - 2).ToUpper();
}
else
{
keyPair = strLine.Split(new char[] { '=' }, 2);
SectionPair sectionPair;
String value = null;
if (currentRoot == null)
currentRoot = "ROOT";
sectionPair.Section = currentRoot;
sectionPair.Key = keyPair[0].ToUpper().Trim();
if (keyPair.Length > 1)
value = keyPair[1];
keyPairs.Add(sectionPair, value.Trim());
}
}
strLine = iniFile.ReadLine();
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (iniFile != null)
iniFile.Close();
}
}
else
throw new FileNotFoundException("Unable to locate " + iniPath);
}
/// <summary>
/// Returns the value for the given section, key pair.
/// </summary>
/// <param name="sectionName">Section name.</param>
/// <param name="settingName">Key name.</param>
public String GetSetting(String sectionName, String settingName)
{
SectionPair sectionPair;
sectionPair.Section = sectionName.ToUpper().Trim();
sectionPair.Key = settingName.ToUpper().Trim();
return (String)keyPairs[sectionPair];
}
/// <summary>
/// Enumerates all lines for given section.
/// </summary>
/// <param name="sectionName">Section to enum.</param>
public String[] EnumSection(String sectionName)
{
ArrayList tmpArray = new ArrayList();
foreach (SectionPair pair in keyPairs.Keys)
{
if (pair.Section == sectionName.ToUpper())
tmpArray.Add(pair.Key);
}
return (String[])tmpArray.ToArray(typeof(String));
}
/// <summary>
/// Adds or replaces a setting to the table to be saved.
/// </summary>
/// <param name="sectionName">Section to add under.</param>
/// <param name="settingName">Key name to add.</param>
/// <param name="settingValue">Value of key.</param>
public void AddSetting(String sectionName, String settingName, String settingValue)
{
SectionPair sectionPair;
sectionPair.Section = sectionName.ToUpper();
sectionPair.Key = settingName.ToUpper();
if (keyPairs.ContainsKey(sectionPair))
keyPairs.Remove(sectionPair);
keyPairs.Add(sectionPair, settingValue);
}
/// <summary>
/// Adds or replaces a setting to the table to be saved with a null value.
/// </summary>
/// <param name="sectionName">Section to add under.</param>
/// <param name="settingName">Key name to add.</param>
public void AddSetting(String sectionName, String settingName)
{
AddSetting(sectionName, settingName, null);
}
/// <summary>
/// Remove a setting.
/// </summary>
/// <param name="sectionName">Section to add under.</param>
/// <param name="settingName">Key name to add.</param>
public void DeleteSetting(String sectionName, String settingName)
{
SectionPair sectionPair;
sectionPair.Section = sectionName.ToUpper();
sectionPair.Key = settingName.ToUpper();
if (keyPairs.ContainsKey(sectionPair))
keyPairs.Remove(sectionPair);
}
/// <summary>
/// Save settings to new file.
/// </summary>
/// <param name="newFilePath">New file path.</param>
public void SaveSettings(String newFilePath)
{
ArrayList sections = new ArrayList();
String tmpValue = "";
String strToSave = "";
foreach (SectionPair sectionPair in keyPairs.Keys)
{
if (!sections.Contains(sectionPair.Section))
sections.Add(sectionPair.Section);
}
foreach (String section in sections)
{
strToSave += ("[" + section + "]\r\n");
foreach (SectionPair sectionPair in keyPairs.Keys)
{
if (sectionPair.Section == section)
{
tmpValue = (String)keyPairs[sectionPair];
if (tmpValue != null)
tmpValue = "=" + tmpValue;
strToSave += (sectionPair.Key + tmpValue + "\r\n");
}
}
strToSave += "\r\n";
}
try
{
TextWriter tw = new StreamWriter(newFilePath);
tw.Write(strToSave);
tw.Close();
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// Save settings back to ini file.
/// </summary>
public void SaveSettings()
{
SaveSettings(iniFilePath);
}
}
}

154
Wox/Helper/KeyboardHook.cs Normal file
View File

@@ -0,0 +1,154 @@
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace Wox.Helper
{
public sealed class KeyboardHook : IDisposable
{
// Registers a hot key with Windows.
[DllImport("user32.dll")]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
// Unregisters the hot key with Windows.
[DllImport("user32.dll")]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
/// <summary>
/// Represents the window that is used internally to get the messages.
/// </summary>
private class Window : NativeWindow, IDisposable
{
private static int wmHotkey = 0x0312;
public Window()
{
// create the handle for the window.
CreateHandle(new CreateParams());
}
/// <summary>
/// Overridden to get the notifications.
/// </summary>
/// <param name="m"></param>
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
// check if we got a hot key pressed.
if (m.Msg == wmHotkey)
{
// get the keys.
Keys key = (Keys)(((int)m.LParam >> 16) & 0xFFFF);
XModifierKeys xModifier = (XModifierKeys)((int)m.LParam & 0xFFFF);
// invoke the event to notify the parent.
if (KeyPressed != null)
KeyPressed(this, new KeyPressedEventArgs(xModifier, key));
}
}
public event EventHandler<KeyPressedEventArgs> KeyPressed;
#region IDisposable Members
public void Dispose()
{
DestroyHandle();
}
#endregion
}
private Window window = new Window();
private int currentId;
public KeyboardHook()
{
// register the event of the inner native window.
window.KeyPressed += delegate(object sender, KeyPressedEventArgs args)
{
if (KeyPressed != null)
KeyPressed(this, args);
};
}
/// <summary>
/// Registers a hot key in the system.
/// </summary>
/// <param name="xModifier">The modifiers that are associated with the hot key.</param>
/// <param name="key">The key itself that is associated with the hot key.</param>
public void RegisterHotKey(XModifierKeys xModifier, Keys key)
{
// increment the counter.
currentId = currentId + 1;
// register the hot key.
if (!RegisterHotKey(window.Handle, currentId, (uint)xModifier, (uint)key))
{
Log.Error("Couldnt register the hot key.");
MessageBox.Show("Couldnt register the hot key.");
#if (DEBUG)
{
throw new InvalidOperationException("Couldnt register the hot key.");
}
#endif
}
}
/// <summary>
/// A hot key has been pressed.
/// </summary>
public event EventHandler<KeyPressedEventArgs> KeyPressed;
#region IDisposable Members
public void Dispose()
{
// unregister all the registered hot keys.
for (int i = currentId; i > 0; i--)
{
UnregisterHotKey(window.Handle, i);
}
// dispose the inner native window.
window.Dispose();
}
#endregion
}
/// <summary>
/// Event Args for the event that is fired after the hot key has been pressed.
/// </summary>
public class KeyPressedEventArgs : EventArgs
{
private XModifierKeys xModifier;
private Keys key;
internal KeyPressedEventArgs(XModifierKeys xModifier, Keys key)
{
this.xModifier = xModifier;
this.key = key;
}
public XModifierKeys XModifier
{
get { return xModifier; }
}
public Keys Key
{
get { return key; }
}
}
/// <summary>
/// The enumeration of possible modifiers.
/// </summary>
public enum XModifierKeys : uint
{
Alt = 1,
Control = 2,
Shift = 4,
Win = 8
}
}

View File

@@ -0,0 +1,244 @@
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Wox.Helper
{
public enum KeyEvent : int
{
/// <summary>
/// Key down
/// </summary>
WM_KEYDOWN = 256,
/// <summary>
/// Key up
/// </summary>
WM_KEYUP = 257,
/// <summary>
/// System key up
/// </summary>
WM_SYSKEYUP = 261,
/// <summary>
/// System key down
/// </summary>
WM_SYSKEYDOWN = 260
}
public class SpecialKeyState
{
public bool CtrlPressed { get; set; }
public bool ShiftPressed { get; set; }
public bool AltPressed { get; set; }
public bool WinPressed { get; set; }
}
/// <summary>
/// Listens keyboard globally.
///
/// <remarks>Uses WH_KEYBOARD_LL.</remarks>
/// </summary>
public class KeyboardListener : IDisposable
{
private InterceptKeys.LowLevelKeyboardProc hookedLowLevelKeyboardProc;
private IntPtr hookId = IntPtr.Zero;
public delegate bool KeyboardCallback(KeyEvent keyEvent, int vkCode, SpecialKeyState state);
public event KeyboardCallback hookedKeyboardCallback;
//Modifier key constants
private const int VK_SHIFT = 0x10;
private const int VK_CONTROL = 0x11;
private const int VK_ALT = 0x12;
private const int VK_WIN = 91;
public KeyboardListener()
{
// We have to store the LowLevelKeyboardProc, so that it is not garbage collected runtime
hookedLowLevelKeyboardProc = LowLevelKeyboardProc;
// Set the hook
hookId = InterceptKeys.SetHook(hookedLowLevelKeyboardProc);
}
private SpecialKeyState CheckModifiers()
{
SpecialKeyState state = new SpecialKeyState();
if ((InterceptKeys.GetKeyState(VK_SHIFT) & 0x8000) != 0)
{
//SHIFT is pressed
state.ShiftPressed = true;
}
if ((InterceptKeys.GetKeyState(VK_CONTROL) & 0x8000) != 0)
{
//CONTROL is pressed
state.CtrlPressed = true;
}
if ((InterceptKeys.GetKeyState(VK_ALT) & 0x8000) != 0)
{
//ALT is pressed
state.AltPressed = true;
}
if ((InterceptKeys.GetKeyState(VK_WIN) & 0x8000) != 0)
{
//ALT is pressed
state.WinPressed = true;
}
return state;
}
[MethodImpl(MethodImplOptions.NoInlining)]
private IntPtr LowLevelKeyboardProc(int nCode, UIntPtr wParam, IntPtr lParam)
{
bool continues = true;
if (nCode >= 0)
{
if (wParam.ToUInt32() == (int)KeyEvent.WM_KEYDOWN ||
wParam.ToUInt32() == (int)KeyEvent.WM_KEYUP ||
wParam.ToUInt32() == (int)KeyEvent.WM_SYSKEYDOWN ||
wParam.ToUInt32() == (int)KeyEvent.WM_SYSKEYUP)
{
if (hookedKeyboardCallback != null)
continues = hookedKeyboardCallback((KeyEvent)wParam.ToUInt32(), Marshal.ReadInt32(lParam), CheckModifiers());
}
}
if (continues)
{
return InterceptKeys.CallNextHookEx(hookId, nCode, wParam, lParam);
}
return (IntPtr)1;
}
~KeyboardListener()
{
Dispose();
}
public void Dispose()
{
InterceptKeys.UnhookWindowsHookEx(hookId);
}
}
public static class InterceptKeys
{
public delegate IntPtr LowLevelKeyboardProc(int nCode, UIntPtr wParam, IntPtr lParam);
private static int WH_KEYBOARD_LL = 13;
public static IntPtr SetHook(LowLevelKeyboardProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
}
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, UIntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)]
public static extern short GetKeyState(int keyCode);
[DllImport("user32.dll")]
internal static extern uint SendInput(uint nInputs, [MarshalAs(UnmanagedType.LPArray), In] INPUT[] pInputs, int cbSize);
public static void SendKeyStroke(int funckey, int key)
{
INPUT[] input = new INPUT[4];
input[0].type = input[1].type = input[2].type = input[3].type = (int)InputType.INPUT_KEYBOARD;
input[0].ki.wVk = input[2].ki.wVk = (short) funckey;
input[1].ki.wVk = input[3].ki.wVk = (short) key;
input[2].ki.dwFlags = input[3].ki.dwFlags =(int) KEYEVENTF.KEYUP;
SendInput((uint)input.Length, input, Marshal.SizeOf(input[0]));
}
}
public enum InputType
{
INPUT_MOUSE = 0,
INPUT_KEYBOARD = 1,
INPUT_HARDWARE = 2,
}
[Flags()]
public enum MOUSEEVENTF
{
MOVE = 0x0001, //mouse move
LEFTDOWN = 0x0002, //left button down
LEFTUP = 0x0004, //left button up
RIGHTDOWN = 0x0008, //right button down
RIGHTUP = 0x0010, //right button up
MIDDLEDOWN = 0x0020, //middle button down
MIDDLEUP = 0x0040, //middle button up
XDOWN = 0x0080, //x button down
XUP = 0x0100, //x button down
WHEEL = 0x0800, //wheel button rolled
VIRTUALDESK = 0x4000, //map to entire virtual desktop
ABSOLUTE = 0x8000, //absolute move
}
[Flags()]
public enum KEYEVENTF
{
EXTENDEDKEY = 0x0001,
KEYUP = 0x0002,
UNICODE = 0x0004,
SCANCODE = 0x0008,
}
[StructLayout(LayoutKind.Explicit)]
public struct INPUT
{
[FieldOffset(0)]
public Int32 type;//0-MOUSEINPUT;1-KEYBDINPUT;2-HARDWAREINPUT
[FieldOffset(4)]
public KEYBDINPUT ki;
[FieldOffset(4)]
public MOUSEINPUT mi;
[FieldOffset(4)]
public HARDWAREINPUT hi;
}
[StructLayout(LayoutKind.Sequential)]
public struct MOUSEINPUT
{
public Int32 dx;
public Int32 dy;
public Int32 mouseData;
public Int32 dwFlags;
public Int32 time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
public struct KEYBDINPUT
{
public Int16 wVk;
public Int16 wScan;
public Int32 dwFlags;
public Int32 time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
public struct HARDWAREINPUT
{
public Int32 uMsg;
public Int16 wParamL;
public Int16 wParamH;
}
}

15
Wox/Helper/Log.cs Normal file
View File

@@ -0,0 +1,15 @@
using System.Reflection;
using log4net;
namespace Wox.Helper
{
public class Log
{
private static ILog fileLogger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public static void Error(string msg)
{
fileLogger.Error(msg);
}
}
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Wox.Helper
{
public class WoxException : Exception
{
public WoxException(string msg)
: base(msg)
{
}
}
}

BIN
Wox/Images/app.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

BIN
Wox/Images/bookmark.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
Wox/Images/close.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 B

BIN
Wox/Images/cmd.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
Wox/Images/ctrl.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
Wox/Images/enter.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 367 B

BIN
Wox/Images/exit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
Wox/Images/folder.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
Wox/Images/lock.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
Wox/Images/logoff.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 613 B

BIN
Wox/Images/work.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

25
Wox/MainWindow.xaml Normal file
View File

@@ -0,0 +1,25 @@
<Window x:Class="Wox.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:wox="clr-namespace:Wox"
Title="Wox"
Topmost="True"
Loaded="MainWindow_OnLoaded"
SizeToContent="Height"
ResizeMode="NoResize"
WindowStyle="None"
WindowStartupLocation="Manual"
ShowInTaskbar="False"
Style="{DynamicResource WindowStyle}"
Icon="Images\app.png"
>
<Grid Style="{DynamicResource GridStyle}" x:Name="grid">
<Grid.RowDefinitions>
<RowDefinition ></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<TextBox AllowDrop="True" Style="{DynamicResource QueryBoxStyle}" Grid.Row="0" x:Name="tbQuery" PreviewKeyDown="TbQuery_OnPreviewKeyDown" TextChanged="TextBoxBase_OnTextChanged" />
<Line Style="{DynamicResource PendingLineStyle}" x:Name="progressBar" Y1="0" Y2="0" X2="100" Grid.Row="1" Height="2" StrokeThickness="1"></Line>
<wox:ResultPanel x:Name="resultCtrl" Grid.Row="2"/>
</Grid>
</Window>

370
Wox/MainWindow.xaml.cs Normal file
View File

@@ -0,0 +1,370 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media.Animation;
using Wox.Commands;
using Wox.Helper;
using Wox.Plugin;
using Wox.PluginLoader;
using Application = System.Windows.Application;
using KeyEventArgs = System.Windows.Input.KeyEventArgs;
using MessageBox = System.Windows.MessageBox;
using UserControl = System.Windows.Controls.UserControl;
namespace Wox
{
public partial class MainWindow
{
private KeyboardHook hook = new KeyboardHook();
private NotifyIcon notifyIcon;
Storyboard progressBarStoryboard = new Storyboard();
private bool queryHasReturn = false;
private KeyboardListener keyboardListener = new KeyboardListener();
private bool WinRStroked = false;
private WindowsInput.KeyboardSimulator keyboardSimulator = new WindowsInput.KeyboardSimulator(new WindowsInput.InputSimulator());
public MainWindow()
{
InitializeComponent();
hook.KeyPressed += OnHotKey;
hook.RegisterHotKey(XModifierKeys.Alt, Keys.Space);
resultCtrl.resultItemChangedEvent += resultCtrl_resultItemChangedEvent;
ThreadPool.SetMaxThreads(30, 10);
InitProgressbarAnimation();
try
{
SetTheme(CommonStorage.Instance.UserSetting.Theme);
}
catch (IOException)
{
SetTheme(CommonStorage.Instance.UserSetting.Theme = "Default");
}
}
private void WakeupApp()
{
//After hide wox in the background for a long time. It will become very slow in the next show.
//This is caused by the Virtual Mermory Page Mechanisam. So, our solution is execute some codes in every min
//which may prevent sysetem uninstall memory from RAM to disk.
System.Timers.Timer t = new System.Timers.Timer(1000 * 60 * 5) { AutoReset = true, Enabled = true };
t.Elapsed += (o, e) => Dispatcher.Invoke(new Action(() =>
{
if (Visibility != Visibility.Visible)
{
double oldLeft = Left;
Left = 20000;
ShowWox();
CommandFactory.DispatchCommand(new Query("qq"), false);
HideWox();
Left = oldLeft;
}
}));
}
private void InitProgressbarAnimation()
{
DoubleAnimation da = new DoubleAnimation(progressBar.X2, Width + 100, new Duration(new TimeSpan(0, 0, 0, 0, 1600)));
DoubleAnimation da1 = new DoubleAnimation(progressBar.X1, Width, new Duration(new TimeSpan(0, 0, 0, 0, 1600)));
Storyboard.SetTargetProperty(da, new PropertyPath("(Line.X2)"));
Storyboard.SetTargetProperty(da1, new PropertyPath("(Line.X1)"));
progressBarStoryboard.Children.Add(da);
progressBarStoryboard.Children.Add(da1);
progressBarStoryboard.RepeatBehavior = RepeatBehavior.Forever;
progressBar.Visibility = Visibility.Hidden;
progressBar.BeginStoryboard(progressBarStoryboard);
}
private void InitialTray()
{
notifyIcon = new NotifyIcon { Text = "Wox", Icon = Properties.Resources.app, Visible = true };
notifyIcon.Click += (o, e) => ShowWox();
System.Windows.Forms.MenuItem open = new System.Windows.Forms.MenuItem("Open");
open.Click += (o, e) => ShowWox();
System.Windows.Forms.MenuItem exit = new System.Windows.Forms.MenuItem("Exit");
exit.Click += (o, e) => CloseApp();
System.Windows.Forms.MenuItem[] childen = { open, exit };
notifyIcon.ContextMenu = new System.Windows.Forms.ContextMenu(childen);
}
private void resultCtrl_resultItemChangedEvent()
{
resultCtrl.Margin = resultCtrl.GetCurrentResultCount() > 0 ? new Thickness { Top = grid.Margin.Top } : new Thickness { Top = 0 };
}
private void OnHotKey(object sender, KeyPressedEventArgs e)
{
if (!IsVisible)
{
ShowWox();
}
else
{
HideWox();
}
}
private void TextBoxBase_OnTextChanged(object sender, TextChangedEventArgs e)
{
resultCtrl.Dirty = true;
Dispatcher.DelayInvoke("UpdateSearch",
o =>
{
Dispatcher.DelayInvoke("ClearResults", i =>
{
// first try to use clear method inside resultCtrl, which is more closer to the add new results
// and this will not bring splash issues.After waiting 30ms, if there still no results added, we
// must clear the result. otherwise, it will be confused why the query changed, but the results
// didn't.
if (resultCtrl.Dirty) resultCtrl.Clear();
}, TimeSpan.FromMilliseconds(30), null);
var q = new Query(tbQuery.Text);
CommandFactory.DispatchCommand(q);
queryHasReturn = false;
if (Plugins.HitThirdpartyKeyword(q))
{
Dispatcher.DelayInvoke("ShowProgressbar", originQuery =>
{
if (!queryHasReturn && originQuery == tbQuery.Text)
{
StartProgress();
}
}, TimeSpan.FromSeconds(1), tbQuery.Text);
}
}, TimeSpan.FromMilliseconds(300));
}
private void StartProgress()
{
progressBar.Visibility = Visibility.Visible;
}
private void StopProgress()
{
progressBar.Visibility = Visibility.Hidden;
}
private void HideWox()
{
Hide();
}
private void ShowWox(bool selectAll = true)
{
Show();
Activate();
Focus();
tbQuery.Focus();
if (selectAll) tbQuery.SelectAll();
}
public void ParseArgs(string[] args)
{
if (args != null && args.Length > 0)
{
switch (args[0])
{
case "reloadWorkflows":
Plugins.Init();
break;
case "query":
if (args.Length > 1)
{
string query = args[1];
tbQuery.Text = query;
tbQuery.SelectAll();
}
break;
}
}
}
private void SetAutoStart(bool IsAtuoRun)
{
//string LnkPath = Environment.GetFolderPath(Environment.SpecialFolder.Startup) + "//Wox.lnk";
//if (IsAtuoRun)
//{
// WshShell shell = new WshShell();
// IWshShortcut shortcut = (IWshShortcut)shell.CreateShortcut(LnkPath);
// shortcut.TargetPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
// shortcut.WorkingDirectory = Environment.CurrentDirectory;
// shortcut.WindowStyle = 1; //normal window
// shortcut.Description = "Wox";
// shortcut.Save();
//}
//else
//{
// System.IO.File.Delete(LnkPath);
//}
}
private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
{
Left = (SystemParameters.PrimaryScreenWidth - ActualWidth) / 2;
Top = (SystemParameters.PrimaryScreenHeight - ActualHeight) / 3;
Plugins.Init();
InitialTray();
SetAutoStart(true);
WakeupApp();
//var engine = new Jurassic.ScriptEngine();
//MessageBox.Show(engine.Evaluate("5 * 10 + 2").ToString());
keyboardListener.hookedKeyboardCallback += KListener_hookedKeyboardCallback;
}
private bool KListener_hookedKeyboardCallback(KeyEvent keyevent, int vkcode, SpecialKeyState state)
{
if (CommonStorage.Instance.UserSetting.ReplaceWinR)
{
//todo:need refatoring. move those codes to CMD file or expose events
if (keyevent == KeyEvent.WM_KEYDOWN && vkcode == (int)Keys.R && state.WinPressed)
{
WinRStroked = true;
Dispatcher.BeginInvoke(new Action(OnWinRPressed));
return false;
}
if (keyevent == KeyEvent.WM_KEYUP && WinRStroked && vkcode == (int)Keys.LWin)
{
WinRStroked = false;
keyboardSimulator.ModifiedKeyStroke(WindowsInput.Native.VirtualKeyCode.LWIN, WindowsInput.Native.VirtualKeyCode.CONTROL);
return false;
}
}
return true;
}
private void OnWinRPressed()
{
ShowWox(false);
if (tbQuery.Text != ">")
{
resultCtrl.Clear();
ChangeQuery(">");
}
tbQuery.CaretIndex = tbQuery.Text.Length;
}
private void TbQuery_OnPreviewKeyDown(object sender, KeyEventArgs e)
{
switch (e.Key)
{
case Key.Escape:
HideWox();
e.Handled = true;
break;
case Key.Down:
resultCtrl.SelectNext();
e.Handled = true;
break;
case Key.Up:
resultCtrl.SelectPrev();
e.Handled = true;
break;
case Key.Enter:
AcceptSelect();
e.Handled = true;
break;
}
}
private void AcceptSelect()
{
Result result = resultCtrl.AcceptSelect();
if (result != null)
{
CommonStorage.Instance.UserSelectedRecords.Add(result);
if (!result.DontHideWoxAfterSelect)
{
HideWox();
}
}
}
public void OnUpdateResultView(List<Result> list)
{
queryHasReturn = true;
progressBar.Dispatcher.Invoke(new Action(StopProgress));
if (list.Count > 0)
{
//todo:this should be opened to users, it's their choise to use it or not in thier workflows
list.ForEach(o =>
{
if (o.AutoAjustScore) o.Score += CommonStorage.Instance.UserSelectedRecords.GetSelectedCount(o);
});
resultCtrl.Dispatcher.Invoke(new Action(() =>
{
List<Result> l = list.Where(o => o.OriginQuery != null && o.OriginQuery.RawQuery == tbQuery.Text).ToList();
resultCtrl.AddResults(l);
}));
}
}
public void SetTheme(string themeName)
{
ResourceDictionary dict = new ResourceDictionary
{
Source = new Uri("pack://application:,,,/Themes/" + themeName + ".xaml")
};
Application.Current.Resources.MergedDictionaries.Clear();
Application.Current.Resources.MergedDictionaries.Add(dict);
}
#region Public API
//Those method can be invoked by plugins
public void ChangeQuery(string query)
{
tbQuery.Text = query;
tbQuery.CaretIndex = tbQuery.Text.Length;
}
public void CloseApp()
{
notifyIcon.Visible = false;
Environment.Exit(0);
}
public void HideApp()
{
HideWox();
}
public void ShowApp()
{
ShowWox();
}
public void ShowMsg(string title, string subTitle, string iconPath)
{
Msg m = new Msg { Owner = GetWindow(this) };
m.Show(title, subTitle, iconPath);
}
public void OpenSettingDialog()
{
SettingWidow s = new SettingWidow(this);
s.Show();
}
#endregion
}
}

View File

@@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using Wox.Helper;
using Wox.Plugin;
namespace Wox.Models
{
[Serializable]
public class UserSelectedRecords
{
private static int hasAddedCount = 0;
public Dictionary<string,int> Records = new Dictionary<string, int>();
public void Add(Result result)
{
if (Records.ContainsKey(result.ToString()))
{
Records[result.ToString()] += 1;
}
else
{
Records.Add(result.ToString(), 1);
}
//hasAddedCount++;
//if (hasAddedCount == 10)
//{
// hasAddedCount = 0;
//}
CommonStorage.Instance.Save();
}
public int GetSelectedCount(Result result)
{
if (Records.ContainsKey(result.ToString()))
{
return Records[result.ToString()];
}
return 0;
}
}
}

14
Wox/Models/UserSetting.cs Normal file
View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Wox.Models
{
public class UserSetting
{
public string Theme { get; set; }
public bool ReplaceWinR { get; set; }
public List<WebSearch> WebSearches { get; set; }
}
}

10
Wox/Models/WebSearch.cs Normal file
View File

@@ -0,0 +1,10 @@
namespace Wox.Models
{
public class WebSearch
{
public string Keyword { get; set; }
public string IconPath { get; set; }
public string Website { get; set; }
public string Enabled { get; set; }
}
}

38
Wox/Msg.xaml Normal file
View File

@@ -0,0 +1,38 @@
<Window x:Class="Wox.Msg"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="#ebebeb"
Topmost="True"
SizeToContent="Height"
ResizeMode="NoResize"
WindowStyle="None"
ShowInTaskbar="False"
Title="Msg" Height="60" Width="420">
<Window.Triggers>
<EventTrigger RoutedEvent="Window.Loaded">
<BeginStoryboard>
<Storyboard >
<DoubleAnimation x:Name="showAnimation" Duration="0:0:0.3" Storyboard.TargetProperty="Top" AccelerationRatio="0.2"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Window.Triggers>
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="32"></ColumnDefinition>
<ColumnDefinition/>
<ColumnDefinition Width="16"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Image x:Name="imgIco" Width="32" Height="32" HorizontalAlignment="Left" ></Image>
<Grid HorizontalAlignment="Stretch" Margin="5 0 0 0" Grid.Column="1" VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="29"></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<TextBlock x:Name="tbTitle" FontSize="16" Foreground="#37392c" FontWeight="Medium">Title</TextBlock>
<TextBlock Grid.Row="1" Foreground="#8e94a4" x:Name="tbSubTitle">sdfdsf</TextBlock>
</Grid>
<Image x:Name="imgClose" Grid.Column="2" Cursor="Hand" Width="16" VerticalAlignment="Top" HorizontalAlignment="Right" />
</Grid>
</Window>

84
Wox/Msg.xaml.cs Normal file
View File

@@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Timer = System.Threading.Timer;
namespace Wox
{
public partial class Msg : Window
{
Storyboard fadeOutStoryboard = new Storyboard();
private bool closing = false;
public Msg()
{
InitializeComponent();
Left = Screen.PrimaryScreen.WorkingArea.Right - this.Width;
Top = Screen.PrimaryScreen.Bounds.Bottom;
showAnimation.From = Screen.PrimaryScreen.Bounds.Bottom;
showAnimation.To = Screen.PrimaryScreen.WorkingArea.Bottom - Height;
// Create the fade out storyboard
fadeOutStoryboard.Completed += new EventHandler(fadeOutStoryboard_Completed);
DoubleAnimation fadeOutAnimation = new DoubleAnimation(Screen.PrimaryScreen.WorkingArea.Bottom - Height, Screen.PrimaryScreen.Bounds.Bottom, new Duration(TimeSpan.FromSeconds(0.3)))
{
AccelerationRatio = 0.2
};
Storyboard.SetTarget(fadeOutAnimation, this);
Storyboard.SetTargetProperty(fadeOutAnimation, new PropertyPath(TopProperty));
fadeOutStoryboard.Children.Add(fadeOutAnimation);
imgClose.Source = new BitmapImage(new Uri(AppDomain.CurrentDomain.BaseDirectory + "\\Images\\close.png"));
imgClose.MouseUp += imgClose_MouseUp;
}
void imgClose_MouseUp(object sender, MouseButtonEventArgs e)
{
if (!closing)
{
closing = true;
fadeOutStoryboard.Begin();
}
}
private void fadeOutStoryboard_Completed(object sender, EventArgs e)
{
Close();
}
public void Show(string title, string subTitle, string icopath)
{
tbTitle.Text = title;
tbSubTitle.Text = subTitle;
if (!File.Exists(icopath))
{
icopath = AppDomain.CurrentDomain.BaseDirectory + "Images\\app.png";
}
imgIco.Source = new BitmapImage(new Uri(icopath));
Show();
Dispatcher.DelayInvoke("ShowMsg",
o =>
{
if (!closing)
{
closing = true;
Dispatcher.Invoke(new Action(fadeOutStoryboard.Begin));
}
}, TimeSpan.FromSeconds(3));
}
}
}

View File

@@ -0,0 +1,131 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using Wox.Helper;
using Wox.Plugin;
using Wox.Plugin.System;
namespace Wox.PluginLoader
{
public abstract class BasePluginLoader
{
private static string PluginPath = AppDomain.CurrentDomain.BaseDirectory + "Plugins";
private static string PluginConfigName = "plugin.ini";
protected static List<PluginMetadata> pluginMetadatas = new List<PluginMetadata>();
public abstract List<PluginPair> LoadPlugin();
public static void ParsePluginsConfig()
{
pluginMetadatas.Clear();
ParseSystemPlugins();
ParseThirdPartyPlugins();
}
private static void ParseSystemPlugins()
{
PluginMetadata metadata = new PluginMetadata();
metadata.Name = "System Plugins";
metadata.Author = "System";
metadata.Description = "system plugins collection";
metadata.Language = AllowedLanguage.CSharp;
metadata.Version = "1.0";
metadata.PluginType = PluginType.System;
metadata.ActionKeyword = "*";
metadata.ExecuteFileName = "Wox.Plugin.System.dll";
metadata.ExecuteFilePath = AppDomain.CurrentDomain.BaseDirectory + metadata.ExecuteFileName;
metadata.PluginDirecotry = AppDomain.CurrentDomain.BaseDirectory;
pluginMetadatas.Add(metadata);
}
private static void ParseThirdPartyPlugins()
{
if (!Directory.Exists(PluginPath))
Directory.CreateDirectory(PluginPath);
string[] directories = Directory.GetDirectories(PluginPath);
foreach (string directory in directories)
{
PluginMetadata metadata = GetMetadataFromIni(directory);
if (metadata != null) pluginMetadatas.Add(metadata);
}
}
private static PluginMetadata GetMetadataFromIni(string directory)
{
string iniPath = directory + "\\" + PluginConfigName;
if (!File.Exists(iniPath))
{
Log.Error(string.Format("parse plugin {0} failed: didn't find config file.", iniPath));
return null;
}
try
{
PluginMetadata metadata = new PluginMetadata();
IniParser ini = new IniParser(iniPath);
metadata.Name = ini.GetSetting("plugin", "Name");
metadata.Author = ini.GetSetting("plugin", "Author");
metadata.Description = ini.GetSetting("plugin", "Description");
metadata.Language = ini.GetSetting("plugin", "Language");
metadata.Version = ini.GetSetting("plugin", "Version");
metadata.PluginType = PluginType.ThirdParty;
metadata.ActionKeyword = ini.GetSetting("plugin", "ActionKeyword");
metadata.ExecuteFilePath = directory + "\\" + ini.GetSetting("plugin", "ExecuteFile");
metadata.PluginDirecotry = directory + "\\";
metadata.ExecuteFileName = ini.GetSetting("plugin", "ExecuteFile");
if (!AllowedLanguage.IsAllowed(metadata.Language))
{
string error = string.Format("Parse ini {0} failed: invalid language {1}", iniPath,
metadata.Language);
Log.Error(error);
#if (DEBUG)
{
throw new WoxException(error);
}
#endif
return null;
}
if (!File.Exists(metadata.ExecuteFilePath))
{
string error = string.Format("Parse ini {0} failed: ExecuteFilePath didn't exist {1}", iniPath,
metadata.ExecuteFilePath);
Log.Error(error);
#if (DEBUG)
{
throw new WoxException(error);
}
#endif
return null;
}
return metadata;
}
catch (Exception e)
{
Log.Error(string.Format("Parse ini {0} failed: {1}", iniPath, e.Message));
#if (DEBUG)
{
throw;
}
#endif
return null;
}
}
///// <summary>
///// Change python execute file name to unique file name using GUID
///// this is because if two pythong plugin use the same
///// </summary>
///// <param name="metadata"></param>
///// <returns></returns>
//private static PluginMetadata filterPythonMetadata(PluginMetadata metadata)
//{
//}
}
}

View File

@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading;
using Wox.Helper;
using Wox.Plugin;
using Wox.Plugin.System;
namespace Wox.PluginLoader
{
public class CSharpPluginLoader : BasePluginLoader
{
public override List<PluginPair> LoadPlugin()
{
List<PluginPair> plugins = new List<PluginPair>();
List<PluginMetadata> metadatas = pluginMetadatas.Where(o => o.Language.ToUpper() == AllowedLanguage.CSharp.ToUpper()).ToList();
foreach (PluginMetadata metadata in metadatas)
{
try
{
Assembly asm = Assembly.LoadFile(metadata.ExecuteFilePath);
List<Type> types = asm.GetTypes().Where(o => o.IsClass && !o.IsAbstract && (o.BaseType == typeof(BaseSystemPlugin) || o.GetInterfaces().Contains(typeof(IPlugin)))).ToList();
if (types.Count == 0)
{
Log.Error(string.Format("Cound't load plugin {0}: didn't find the class who implement IPlugin",
metadata.Name));
continue;
}
foreach (Type type in types)
{
PluginPair pair = new PluginPair()
{
Plugin = Activator.CreateInstance(type) as IPlugin,
Metadata = metadata
};
plugins.Add(pair);
}
}
catch (Exception e)
{
Log.Error(string.Format("Cound't load plugin {0}: {1}", metadata.Name, e.Message));
#if (DEBUG)
{
throw;
}
#endif
}
}
return plugins;
}
}
}

View File

@@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Microsoft.CSharp;
using Wox.Plugin;
namespace Wox.PluginLoader
{
public static class Plugins
{
private static List<PluginPair> plugins = new List<PluginPair>();
public static void Init()
{
plugins.Clear();
BasePluginLoader.ParsePluginsConfig();
plugins.AddRange(new PythonPluginLoader().LoadPlugin());
plugins.AddRange(new CSharpPluginLoader().LoadPlugin());
foreach (IPlugin plugin in plugins.Select(pluginPair => pluginPair.Plugin))
{
IPlugin plugin1 = plugin;
PluginPair pluginPair = plugins.FirstOrDefault(o => o.Plugin == plugin1);
if (pluginPair != null)
{
PluginMetadata metadata = pluginPair.Metadata;
ThreadPool.QueueUserWorkItem(o => plugin1.Init(new PluginInitContext()
{
Plugins = plugins,
PluginMetadata = metadata,
ChangeQuery = s => App.Window.ChangeQuery(s),
CloseApp = App.Window.CloseApp,
HideApp = App.Window.HideApp,
ShowApp = () => App.Window.ShowApp(),
ShowMsg = (title, subTitle, iconPath) => App.Window.ShowMsg(title, subTitle, iconPath),
OpenSettingDialog = () => App.Window.OpenSettingDialog()
}));
}
}
}
public static List<PluginPair> AllPlugins
{
get { return plugins; }
}
public static bool HitThirdpartyKeyword(Query query)
{
if (string.IsNullOrEmpty(query.ActionName)) return false;
return plugins.Any(o => o.Metadata.PluginType == PluginType.ThirdParty && o.Metadata.ActionKeyword == query.ActionName);
}
}
}

View File

@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Python.Runtime;
using Wox.Plugin;
namespace Wox.PluginLoader
{
public class PythonPluginLoader : BasePluginLoader
{
public override List<PluginPair> LoadPlugin()
{
List<PluginPair> plugins = new List<PluginPair>();
List<PluginMetadata> metadatas = pluginMetadatas.Where(o => o.Language.ToUpper() == AllowedLanguage.Python.ToUpper()).ToList();
foreach (PluginMetadata metadata in metadatas)
{
PythonPluginWrapper python = new PythonPluginWrapper(metadata);
PluginPair pair = new PluginPair()
{
Plugin = python,
Metadata = metadata
};
plugins.Add(pair);
}
return plugins;
}
}
}

View File

@@ -0,0 +1,99 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Documents;
using Newtonsoft.Json;
using Python.Runtime;
using Wox.Helper;
using Wox.Plugin;
namespace Wox.PluginLoader
{
public class PythonPluginWrapper : IPlugin
{
private PluginMetadata metadata;
private string moduleName;
public PythonPluginWrapper(PluginMetadata metadata)
{
this.metadata = metadata;
moduleName = metadata.ExecuteFileName.Replace(".py", "");
}
public List<Result> Query(Query query)
{
try
{
string jsonResult = InvokeFunc("query", query.RawQuery);
if (string.IsNullOrEmpty(jsonResult))
{
return new List<Result>();
}
List<PythonResult> o = JsonConvert.DeserializeObject<List<PythonResult>>(jsonResult);
List<Result> r = new List<Result>();
foreach (PythonResult pythonResult in o)
{
PythonResult ps = pythonResult;
if (!string.IsNullOrEmpty(ps.ActionName))
{
ps.Action = () => InvokeFunc(ps.ActionName, ps.ActionPara);
}
r.Add(ps);
}
return r;
}
catch (Exception)
{
#if (DEBUG)
{
throw;
}
#endif
}
}
private string InvokeFunc(string func, params string[] para)
{
string json;
PyObject[] paras = { };
if (para != null && para.Length > 0)
{
paras = para.Select(o => new PyString(o)).ToArray();
}
IntPtr gs = PythonEngine.AcquireLock();
PyObject module = PythonEngine.ImportModule(moduleName);
if (module.HasAttr(func))
{
PyObject res = paras.Length > 0 ? module.InvokeMethod(func, paras) : module.InvokeMethod(func);
json = Runtime.GetManagedString(res.Handle);
}
else
{
string error = string.Format("Python Invoke failed: {0} doesn't has function {1}",
metadata.ExecuteFilePath, func);
Log.Error(error);
#if (DEBUG)
{
throw new ArgumentException(error);
}
#endif
}
PythonEngine.ReleaseLock(gs);
return json;
}
public void Init(PluginInitContext context)
{
}
}
}

View File

@@ -0,0 +1,577 @@
using System;
#pragma warning disable 1591
// ReSharper disable UnusedMember.Global
// ReSharper disable MemberCanBePrivate.Global
// ReSharper disable UnusedAutoPropertyAccessor.Global
// ReSharper disable IntroduceOptionalParameters.Global
// ReSharper disable MemberCanBeProtected.Global
// ReSharper disable InconsistentNaming
namespace Wox.Annotations
{
/// <summary>
/// Indicates that the value of the marked element could be <c>null</c> sometimes,
/// so the check for <c>null</c> is necessary before its usage
/// </summary>
/// <example><code>
/// [CanBeNull] public object Test() { return null; }
/// public void UseTest() {
/// var p = Test();
/// var s = p.ToString(); // Warning: Possible 'System.NullReferenceException'
/// }
/// </code></example>
[AttributeUsage(
AttributeTargets.Method | AttributeTargets.Parameter |
AttributeTargets.Property | AttributeTargets.Delegate |
AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public sealed class CanBeNullAttribute : Attribute { }
/// <summary>
/// Indicates that the value of the marked element could never be <c>null</c>
/// </summary>
/// <example><code>
/// [NotNull] public object Foo() {
/// return null; // Warning: Possible 'null' assignment
/// }
/// </code></example>
[AttributeUsage(
AttributeTargets.Method | AttributeTargets.Parameter |
AttributeTargets.Property | AttributeTargets.Delegate |
AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
public sealed class NotNullAttribute : Attribute { }
/// <summary>
/// Indicates that the marked method builds string by format pattern and (optional) arguments.
/// Parameter, which contains format string, should be given in constructor. The format string
/// should be in <see cref="string.Format(IFormatProvider,string,object[])"/>-like form
/// </summary>
/// <example><code>
/// [StringFormatMethod("message")]
/// public void ShowError(string message, params object[] args) { /* do something */ }
/// public void Foo() {
/// ShowError("Failed: {0}"); // Warning: Non-existing argument in format string
/// }
/// </code></example>
[AttributeUsage(
AttributeTargets.Constructor | AttributeTargets.Method,
AllowMultiple = false, Inherited = true)]
public sealed class StringFormatMethodAttribute : Attribute
{
/// <param name="formatParameterName">
/// Specifies which parameter of an annotated method should be treated as format-string
/// </param>
public StringFormatMethodAttribute(string formatParameterName)
{
FormatParameterName = formatParameterName;
}
public string FormatParameterName { get; private set; }
}
/// <summary>
/// Indicates that the function argument should be string literal and match one
/// of the parameters of the caller function. For example, ReSharper annotates
/// the parameter of <see cref="System.ArgumentNullException"/>
/// </summary>
/// <example><code>
/// public void Foo(string param) {
/// if (param == null)
/// throw new ArgumentNullException("par"); // Warning: Cannot resolve symbol
/// }
/// </code></example>
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
public sealed class InvokerParameterNameAttribute : Attribute { }
/// <summary>
/// Indicates that the method is contained in a type that implements
/// <see cref="System.ComponentModel.INotifyPropertyChanged"/> interface
/// and this method is used to notify that some property value changed
/// </summary>
/// <remarks>
/// The method should be non-static and conform to one of the supported signatures:
/// <list>
/// <item><c>NotifyChanged(string)</c></item>
/// <item><c>NotifyChanged(params string[])</c></item>
/// <item><c>NotifyChanged{T}(Expression{Func{T}})</c></item>
/// <item><c>NotifyChanged{T,U}(Expression{Func{T,U}})</c></item>
/// <item><c>SetProperty{T}(ref T, T, string)</c></item>
/// </list>
/// </remarks>
/// <example><code>
/// public class Foo : INotifyPropertyChanged {
/// public event PropertyChangedEventHandler PropertyChanged;
/// [NotifyPropertyChangedInvocator]
/// protected virtual void NotifyChanged(string propertyName) { ... }
///
/// private string _name;
/// public string Name {
/// get { return _name; }
/// set { _name = value; NotifyChanged("LastName"); /* Warning */ }
/// }
/// }
/// </code>
/// Examples of generated notifications:
/// <list>
/// <item><c>NotifyChanged("Property")</c></item>
/// <item><c>NotifyChanged(() =&gt; Property)</c></item>
/// <item><c>NotifyChanged((VM x) =&gt; x.Property)</c></item>
/// <item><c>SetProperty(ref myField, value, "Property")</c></item>
/// </list>
/// </example>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class NotifyPropertyChangedInvocatorAttribute : Attribute
{
public NotifyPropertyChangedInvocatorAttribute() { }
public NotifyPropertyChangedInvocatorAttribute(string parameterName)
{
ParameterName = parameterName;
}
public string ParameterName { get; private set; }
}
/// <summary>
/// Describes dependency between method input and output
/// </summary>
/// <syntax>
/// <p>Function Definition Table syntax:</p>
/// <list>
/// <item>FDT ::= FDTRow [;FDTRow]*</item>
/// <item>FDTRow ::= Input =&gt; Output | Output &lt;= Input</item>
/// <item>Input ::= ParameterName: Value [, Input]*</item>
/// <item>Output ::= [ParameterName: Value]* {halt|stop|void|nothing|Value}</item>
/// <item>Value ::= true | false | null | notnull | canbenull</item>
/// </list>
/// If method has single input parameter, it's name could be omitted.<br/>
/// Using <c>halt</c> (or <c>void</c>/<c>nothing</c>, which is the same)
/// for method output means that the methos doesn't return normally.<br/>
/// <c>canbenull</c> annotation is only applicable for output parameters.<br/>
/// You can use multiple <c>[ContractAnnotation]</c> for each FDT row,
/// or use single attribute with rows separated by semicolon.<br/>
/// </syntax>
/// <examples><list>
/// <item><code>
/// [ContractAnnotation("=> halt")]
/// public void TerminationMethod()
/// </code></item>
/// <item><code>
/// [ContractAnnotation("halt &lt;= condition: false")]
/// public void Assert(bool condition, string text) // regular assertion method
/// </code></item>
/// <item><code>
/// [ContractAnnotation("s:null => true")]
/// public bool IsNullOrEmpty(string s) // string.IsNullOrEmpty()
/// </code></item>
/// <item><code>
/// // A method that returns null if the parameter is null, and not null if the parameter is not null
/// [ContractAnnotation("null => null; notnull => notnull")]
/// public object Transform(object data)
/// </code></item>
/// <item><code>
/// [ContractAnnotation("s:null=>false; =>true,result:notnull; =>false, result:null")]
/// public bool TryParse(string s, out Person result)
/// </code></item>
/// </list></examples>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public sealed class ContractAnnotationAttribute : Attribute
{
public ContractAnnotationAttribute([NotNull] string contract)
: this(contract, false) { }
public ContractAnnotationAttribute([NotNull] string contract, bool forceFullStates)
{
Contract = contract;
ForceFullStates = forceFullStates;
}
public string Contract { get; private set; }
public bool ForceFullStates { get; private set; }
}
/// <summary>
/// Indicates that marked element should be localized or not
/// </summary>
/// <example><code>
/// [LocalizationRequiredAttribute(true)]
/// public class Foo {
/// private string str = "my string"; // Warning: Localizable string
/// }
/// </code></example>
[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
public sealed class LocalizationRequiredAttribute : Attribute
{
public LocalizationRequiredAttribute() : this(true) { }
public LocalizationRequiredAttribute(bool required)
{
Required = required;
}
public bool Required { get; private set; }
}
/// <summary>
/// Indicates that the value of the marked type (or its derivatives)
/// cannot be compared using '==' or '!=' operators and <c>Equals()</c>
/// should be used instead. However, using '==' or '!=' for comparison
/// with <c>null</c> is always permitted.
/// </summary>
/// <example><code>
/// [CannotApplyEqualityOperator]
/// class NoEquality { }
/// class UsesNoEquality {
/// public void Test() {
/// var ca1 = new NoEquality();
/// var ca2 = new NoEquality();
/// if (ca1 != null) { // OK
/// bool condition = ca1 == ca2; // Warning
/// }
/// }
/// }
/// </code></example>
[AttributeUsage(
AttributeTargets.Interface | AttributeTargets.Class |
AttributeTargets.Struct, AllowMultiple = false, Inherited = true)]
public sealed class CannotApplyEqualityOperatorAttribute : Attribute { }
/// <summary>
/// When applied to a target attribute, specifies a requirement for any type marked
/// with the target attribute to implement or inherit specific type or types.
/// </summary>
/// <example><code>
/// [BaseTypeRequired(typeof(IComponent)] // Specify requirement
/// public class ComponentAttribute : Attribute { }
/// [Component] // ComponentAttribute requires implementing IComponent interface
/// public class MyComponent : IComponent { }
/// </code></example>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
[BaseTypeRequired(typeof(Attribute))]
public sealed class BaseTypeRequiredAttribute : Attribute
{
public BaseTypeRequiredAttribute([NotNull] Type baseType)
{
BaseType = baseType;
}
[NotNull] public Type BaseType { get; private set; }
}
/// <summary>
/// Indicates that the marked symbol is used implicitly
/// (e.g. via reflection, in external library), so this symbol
/// will not be marked as unused (as well as by other usage inspections)
/// </summary>
[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
public sealed class UsedImplicitlyAttribute : Attribute
{
public UsedImplicitlyAttribute()
: this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) { }
public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags)
: this(useKindFlags, ImplicitUseTargetFlags.Default) { }
public UsedImplicitlyAttribute(ImplicitUseTargetFlags targetFlags)
: this(ImplicitUseKindFlags.Default, targetFlags) { }
public UsedImplicitlyAttribute(
ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags)
{
UseKindFlags = useKindFlags;
TargetFlags = targetFlags;
}
public ImplicitUseKindFlags UseKindFlags { get; private set; }
public ImplicitUseTargetFlags TargetFlags { get; private set; }
}
/// <summary>
/// Should be used on attributes and causes ReSharper
/// to not mark symbols marked with such attributes as unused
/// (as well as by other usage inspections)
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public sealed class MeansImplicitUseAttribute : Attribute
{
public MeansImplicitUseAttribute()
: this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) { }
public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags)
: this(useKindFlags, ImplicitUseTargetFlags.Default) { }
public MeansImplicitUseAttribute(ImplicitUseTargetFlags targetFlags)
: this(ImplicitUseKindFlags.Default, targetFlags) { }
public MeansImplicitUseAttribute(
ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags)
{
UseKindFlags = useKindFlags;
TargetFlags = targetFlags;
}
[UsedImplicitly] public ImplicitUseKindFlags UseKindFlags { get; private set; }
[UsedImplicitly] public ImplicitUseTargetFlags TargetFlags { get; private set; }
}
[Flags]
public enum ImplicitUseKindFlags
{
Default = Access | Assign | InstantiatedWithFixedConstructorSignature,
/// <summary>Only entity marked with attribute considered used</summary>
Access = 1,
/// <summary>Indicates implicit assignment to a member</summary>
Assign = 2,
/// <summary>
/// Indicates implicit instantiation of a type with fixed constructor signature.
/// That means any unused constructor parameters won't be reported as such.
/// </summary>
InstantiatedWithFixedConstructorSignature = 4,
/// <summary>Indicates implicit instantiation of a type</summary>
InstantiatedNoFixedConstructorSignature = 8,
}
/// <summary>
/// Specify what is considered used implicitly
/// when marked with <see cref="MeansImplicitUseAttribute"/>
/// or <see cref="UsedImplicitlyAttribute"/>
/// </summary>
[Flags]
public enum ImplicitUseTargetFlags
{
Default = Itself,
Itself = 1,
/// <summary>Members of entity marked with attribute are considered used</summary>
Members = 2,
/// <summary>Entity marked with attribute and all its members considered used</summary>
WithMembers = Itself | Members
}
/// <summary>
/// This attribute is intended to mark publicly available API
/// which should not be removed and so is treated as used
/// </summary>
[MeansImplicitUse]
public sealed class PublicAPIAttribute : Attribute
{
public PublicAPIAttribute() { }
public PublicAPIAttribute([NotNull] string comment)
{
Comment = comment;
}
[NotNull] public string Comment { get; private set; }
}
/// <summary>
/// Tells code analysis engine if the parameter is completely handled
/// when the invoked method is on stack. If the parameter is a delegate,
/// indicates that delegate is executed while the method is executed.
/// If the parameter is an enumerable, indicates that it is enumerated
/// while the method is executed
/// </summary>
[AttributeUsage(AttributeTargets.Parameter, Inherited = true)]
public sealed class InstantHandleAttribute : Attribute { }
/// <summary>
/// Indicates that a method does not make any observable state changes.
/// The same as <c>System.Diagnostics.Contracts.PureAttribute</c>
/// </summary>
/// <example><code>
/// [Pure] private int Multiply(int x, int y) { return x * y; }
/// public void Foo() {
/// const int a = 2, b = 2;
/// Multiply(a, b); // Waring: Return value of pure method is not used
/// }
/// </code></example>
[AttributeUsage(AttributeTargets.Method, Inherited = true)]
public sealed class PureAttribute : Attribute { }
/// <summary>
/// Indicates that a parameter is a path to a file or a folder
/// within a web project. Path can be relative or absolute,
/// starting from web root (~)
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
public class PathReferenceAttribute : Attribute
{
public PathReferenceAttribute() { }
public PathReferenceAttribute([PathReference] string basePath)
{
BasePath = basePath;
}
[NotNull] public string BasePath { get; private set; }
}
// ASP.NET MVC attributes
/// <summary>
/// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter
/// is an MVC action. If applied to a method, the MVC action name is calculated
/// implicitly from the context. Use this attribute for custom wrappers similar to
/// <c>System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String)</c>
/// </summary>
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)]
public sealed class AspMvcActionAttribute : Attribute
{
public AspMvcActionAttribute() { }
public AspMvcActionAttribute([NotNull] string anonymousProperty)
{
AnonymousProperty = anonymousProperty;
}
[NotNull] public string AnonymousProperty { get; private set; }
}
/// <summary>
/// ASP.NET MVC attribute. Indicates that a parameter is an MVC area.
/// Use this attribute for custom wrappers similar to
/// <c>System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String)</c>
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
public sealed class AspMvcAreaAttribute : PathReferenceAttribute
{
public AspMvcAreaAttribute() { }
public AspMvcAreaAttribute([NotNull] string anonymousProperty)
{
AnonymousProperty = anonymousProperty;
}
[NotNull] public string AnonymousProperty { get; private set; }
}
/// <summary>
/// ASP.NET MVC attribute. If applied to a parameter, indicates that
/// the parameter is an MVC controller. If applied to a method,
/// the MVC controller name is calculated implicitly from the context.
/// Use this attribute for custom wrappers similar to
/// <c>System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String, String)</c>
/// </summary>
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)]
public sealed class AspMvcControllerAttribute : Attribute
{
public AspMvcControllerAttribute() { }
public AspMvcControllerAttribute([NotNull] string anonymousProperty)
{
AnonymousProperty = anonymousProperty;
}
[NotNull] public string AnonymousProperty { get; private set; }
}
/// <summary>
/// ASP.NET MVC attribute. Indicates that a parameter is an MVC Master.
/// Use this attribute for custom wrappers similar to
/// <c>System.Web.Mvc.Controller.View(String, String)</c>
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
public sealed class AspMvcMasterAttribute : Attribute { }
/// <summary>
/// ASP.NET MVC attribute. Indicates that a parameter is an MVC model type.
/// Use this attribute for custom wrappers similar to
/// <c>System.Web.Mvc.Controller.View(String, Object)</c>
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
public sealed class AspMvcModelTypeAttribute : Attribute { }
/// <summary>
/// ASP.NET MVC attribute. If applied to a parameter, indicates that
/// the parameter is an MVC partial view. If applied to a method,
/// the MVC partial view name is calculated implicitly from the context.
/// Use this attribute for custom wrappers similar to
/// <c>System.Web.Mvc.Html.RenderPartialExtensions.RenderPartial(HtmlHelper, String)</c>
/// </summary>
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)]
public sealed class AspMvcPartialViewAttribute : PathReferenceAttribute { }
/// <summary>
/// ASP.NET MVC attribute. Allows disabling all inspections
/// for MVC views within a class or a method.
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed class AspMvcSupressViewErrorAttribute : Attribute { }
/// <summary>
/// ASP.NET MVC attribute. Indicates that a parameter is an MVC display template.
/// Use this attribute for custom wrappers similar to
/// <c>System.Web.Mvc.Html.DisplayExtensions.DisplayForModel(HtmlHelper, String)</c>
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
public sealed class AspMvcDisplayTemplateAttribute : Attribute { }
/// <summary>
/// ASP.NET MVC attribute. Indicates that a parameter is an MVC editor template.
/// Use this attribute for custom wrappers similar to
/// <c>System.Web.Mvc.Html.EditorExtensions.EditorForModel(HtmlHelper, String)</c>
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
public sealed class AspMvcEditorTemplateAttribute : Attribute { }
/// <summary>
/// ASP.NET MVC attribute. Indicates that a parameter is an MVC template.
/// Use this attribute for custom wrappers similar to
/// <c>System.ComponentModel.DataAnnotations.UIHintAttribute(System.String)</c>
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
public sealed class AspMvcTemplateAttribute : Attribute { }
/// <summary>
/// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter
/// is an MVC view. If applied to a method, the MVC view name is calculated implicitly
/// from the context. Use this attribute for custom wrappers similar to
/// <c>System.Web.Mvc.Controller.View(Object)</c>
/// </summary>
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)]
public sealed class AspMvcViewAttribute : PathReferenceAttribute { }
/// <summary>
/// ASP.NET MVC attribute. When applied to a parameter of an attribute,
/// indicates that this parameter is an MVC action name
/// </summary>
/// <example><code>
/// [ActionName("Foo")]
/// public ActionResult Login(string returnUrl) {
/// ViewBag.ReturnUrl = Url.Action("Foo"); // OK
/// return RedirectToAction("Bar"); // Error: Cannot resolve action
/// }
/// </code></example>
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property)]
public sealed class AspMvcActionSelectorAttribute : Attribute { }
[AttributeUsage(
AttributeTargets.Parameter | AttributeTargets.Property |
AttributeTargets.Field, Inherited = true)]
public sealed class HtmlElementAttributesAttribute : Attribute
{
public HtmlElementAttributesAttribute() { }
public HtmlElementAttributesAttribute([NotNull] string name)
{
Name = name;
}
[NotNull] public string Name { get; private set; }
}
[AttributeUsage(
AttributeTargets.Parameter | AttributeTargets.Field |
AttributeTargets.Property, Inherited = true)]
public sealed class HtmlAttributeValueAttribute : Attribute
{
public HtmlAttributeValueAttribute([NotNull] string name)
{
Name = name;
}
[NotNull] public string Name { get; private set; }
}
// Razor attributes
/// <summary>
/// Razor attribute. Indicates that a parameter or a method is a Razor section.
/// Use this attribute for custom wrappers similar to
/// <c>System.Web.WebPages.WebPageBase.RenderSection(String)</c>
/// </summary>
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method, Inherited = true)]
public sealed class RazorSectionAttribute : Attribute { }
}

View File

@@ -0,0 +1,56 @@
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows;
// 有关程序集的常规信息通过以下
// 特性集控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("Wox")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("Wox")]
[assembly: AssemblyCopyright("Copyright © qianlifeng 2014")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 将 ComVisible 设置为 false 使此程序集中的类型
// 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型,
// 则将该类型上的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
//若要开始生成可本地化的应用程序,请在
//<PropertyGroup> 中的 .csproj 文件中
//设置 <UICulture>CultureYouAreCodingWith</UICulture>。例如,如果您在源文件中
//使用的是美国英语,请将 <UICulture> 设置为 en-US。然后取消
//对以下 NeutralResourceLanguage 特性的注释。更新
//以下行中的“en-US”以匹配项目文件中的 UICulture 设置。
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //主题特定资源词典所处位置
//(在页面或应用程序资源词典中
// 未找到某个资源的情况下使用)
ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置
//(在页面、应用程序或任何主题特定资源词典中
// 未找到某个资源的情况下使用)
)]
// 程序集的版本信息由下面四个值组成:
//
// 主版本
// 次版本
// 生成号
// 修订号
//
// 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
// 方法是按如下所示使用“*”:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: log4net.Config.XmlConfigurator(Watch = true)]

73
Wox/Properties/Resources.Designer.cs generated Normal file
View File

@@ -0,0 +1,73 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.18052
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
namespace Wox.Properties {
using System;
/// <summary>
/// 一个强类型的资源类,用于查找本地化的字符串等。
/// </summary>
// 此类是由 StronglyTypedResourceBuilder
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
// (以 /str 作为命令选项),或重新生成 VS 项目。
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// 返回此类使用的缓存的 ResourceManager 实例。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Wox.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// 使用此强类型资源类,为所有资源查找
/// 重写当前线程的 CurrentUICulture 属性。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// 查找类似于 (Icon) 的 System.Drawing.Icon 类型的本地化资源。
/// </summary>
internal static System.Drawing.Icon app {
get {
object obj = ResourceManager.GetObject("app", resourceCulture);
return ((System.Drawing.Icon)(obj));
}
}
}
}

View File

@@ -0,0 +1,124 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="app" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\app.ico;System.Drawing.Icon, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

26
Wox/Properties/Settings.Designer.cs generated Normal file
View File

@@ -0,0 +1,26 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.18052
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
namespace Wox.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
}
}

View File

@@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

BIN
Wox/Resources/app.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
Wox/Resources/ctrl.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

31
Wox/ResultItem.xaml Normal file
View File

@@ -0,0 +1,31 @@
<UserControl x:Class="Wox.ResultItem"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignWidth="400"
x:Name="resultItemControl"
Style="{DynamicResource ItemStyle}"
Height="50">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="5" Cursor="Hand">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="32"></ColumnDefinition>
<ColumnDefinition/>
<ColumnDefinition Width="73.064"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Image x:Name="imgIco" Width="32" Height="32" HorizontalAlignment="Left" ></Image>
<Grid HorizontalAlignment="Stretch" Margin="5 0 0 0" Grid.Column="1" VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="23"></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Style="{DynamicResource ItemTitleStyle}" x:Name="tbTitle">Title</TextBlock>
<TextBlock Style="{DynamicResource ItemSubTitleStyle}" Grid.Row="1" x:Name="tbSubTitle">sub title</TextBlock>
</Grid>
<DockPanel Grid.Column="2" Visibility="Hidden">
<Image x:Name="img" Source="Images\ctrl.png" VerticalAlignment="Center"/>
<TextBlock x:Name="tbIndex" Visibility="Hidden" FontSize="16" Foreground="#5c1f87" Margin="0 5 0 0" Text="1" VerticalAlignment="Center" HorizontalAlignment="Left" />
</DockPanel>
</Grid>
</UserControl>

110
Wox/ResultItem.xaml.cs Normal file
View File

@@ -0,0 +1,110 @@
using System;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Wox.Annotations;
using Wox.Helper;
using Wox.Plugin;
using Brush = System.Windows.Media.Brush;
namespace Wox
{
public partial class ResultItem : UserControl, INotifyPropertyChanged
{
private bool selected;
public Result Result { get; private set; }
public bool Selected
{
get
{
return selected;
}
set
{
selected = value;
if (selected)
{
img.Visibility = Visibility.Visible;
img.Source = new BitmapImage(new Uri(Directory.GetCurrentDirectory() + "\\Images\\enter.png"));
}
else
{
img.Visibility = Visibility.Hidden;
}
OnPropertyChanged("Selected");
}
}
public void SetIndex(int index)
{
tbIndex.Text = index.ToString();
}
public ResultItem(Result result)
{
InitializeComponent();
Result = result;
tbTitle.Text = result.Title;
tbSubTitle.Text = result.SubTitle;
string path = string.Empty;
if (!string.IsNullOrEmpty(result.IcoPath) && result.IcoPath.Contains(":\\") && File.Exists(result.IcoPath))
{
path = result.IcoPath;
}
else if (!string.IsNullOrEmpty(result.IcoPath) && File.Exists(result.PluginDirectory + result.IcoPath))
{
path = result.PluginDirectory + result.IcoPath;
}
if (!string.IsNullOrEmpty(path))
{
if (path.ToLower().EndsWith(".exe") || path.ToLower().EndsWith(".lnk"))
{
imgIco.Source = GetIcon(path);
}
else
{
imgIco.Source = new BitmapImage(new Uri(path));
}
}
AddHandler(MouseLeftButtonUpEvent, new RoutedEventHandler((o, e) =>
{
Result.Action();
CommonStorage.Instance.UserSelectedRecords.Add(result);
if (!result.DontHideWoxAfterSelect)
{
App.Window.HideApp();
}
e.Handled = true;
}));
}
private static ImageSource GetIcon(string fileName)
{
Icon icon = Icon.ExtractAssociatedIcon(fileName);
return System.Windows.Interop.Imaging.CreateBitmapSourceFromHIcon(
icon.Handle,
new Int32Rect(0, 0, icon.Width, icon.Height),
BitmapSizeOptions.FromEmptyOptions());
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}

11
Wox/ResultPanel.xaml Normal file
View File

@@ -0,0 +1,11 @@
<UserControl x:Class="Wox.ResultPanel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<ScrollViewer x:Name="sv" Template="{DynamicResource ScrollViewerControlTemplate}" MaxHeight="300" VerticalScrollBarVisibility="Auto">
<StackPanel x:Name="pnlContainer"/>
</ScrollViewer>
</UserControl>

237
Wox/ResultPanel.xaml.cs Normal file
View File

@@ -0,0 +1,237 @@
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using Wox.Plugin;
namespace Wox
{
public partial class ResultPanel : UserControl
{
public bool Dirty { get; set; }
public delegate void ResultItemsChanged();
public event ResultItemsChanged resultItemChangedEvent;
protected virtual void OnResultItemChangedEvent()
{
ResultItemsChanged handler = resultItemChangedEvent;
if (handler != null) handler();
}
public void AddResults(List<Result> results)
{
if (results.Count == 0) return;
if (Dirty)
{
Dirty = false;
pnlContainer.Children.Clear();
}
for (int i = 0; i < results.Count; i++)
{
Result result = results[i];
if (!CheckExisted(result))
{
ResultItem control = new ResultItem(result);
control.SetIndex(i + 1);
pnlContainer.Children.Insert(GetInsertLocation(result.Score), control);
}
}
SelectFirst();
pnlContainer.UpdateLayout();
double resultItemHeight = 0;
if (pnlContainer.Children.Count > 0)
{
var resultItem = pnlContainer.Children[0] as ResultItem;
if (resultItem != null)
resultItemHeight = resultItem.ActualHeight;
}
pnlContainer.Height = pnlContainer.Children.Count * resultItemHeight;
OnResultItemChangedEvent();
}
private bool CheckExisted(Result result)
{
return pnlContainer.Children.Cast<ResultItem>().Any(child => child.Result.Equals(result));
}
private int GetInsertLocation(int currentScore)
{
int location = pnlContainer.Children.Count;
if (pnlContainer.Children.Count == 0) return 0;
if (currentScore > ((ResultItem)pnlContainer.Children[0]).Result.Score) return 0;
for (int index = 1; index < pnlContainer.Children.Count; index++)
{
ResultItem next = pnlContainer.Children[index] as ResultItem;
ResultItem prev = pnlContainer.Children[index - 1] as ResultItem;
if (next != null && prev != null)
{
if ((currentScore >= next.Result.Score && currentScore <= prev.Result.Score))
{
if (currentScore == next.Result.Score)
{
location = index + 1;
}
else
{
location = index;
}
}
}
}
return location;
}
public int GetCurrentResultCount()
{
return pnlContainer.Children.Count;
}
public int GetCurrentSelectedResultIndex()
{
for (int i = 0; i < pnlContainer.Children.Count; i++)
{
var resultItemControl = pnlContainer.Children[i] as ResultItem;
if (resultItemControl != null && resultItemControl.Selected)
{
return i;
}
}
return -1;
}
public void UnSelectAll()
{
for (int i = 0; i < pnlContainer.Children.Count; i++)
{
var resultItemControl = pnlContainer.Children[i] as ResultItem;
if (resultItemControl != null && resultItemControl.Selected)
{
resultItemControl.Selected = false;
}
}
}
public void SelectNext()
{
int index = GetCurrentSelectedResultIndex();
if (index == pnlContainer.Children.Count - 1)
{
index = -1;
}
Select(index + 1);
}
public void SelectPrev()
{
int index = GetCurrentSelectedResultIndex();
if (index == 0)
{
index = pnlContainer.Children.Count;
}
Select(index - 1);
}
private void Select(int index)
{
if (pnlContainer.Children.Count > 0)
{
int oldIndex = GetCurrentSelectedResultIndex();
UnSelectAll();
var resultItemControl = pnlContainer.Children[index] as ResultItem;
if (resultItemControl != null)
{
resultItemControl.Selected = true;
double scrollPosition = 0;
Point newItemBottomPoint = resultItemControl.TranslatePoint(new Point(0, resultItemControl.ActualHeight), pnlContainer);
scrollPosition = newItemBottomPoint.Y;
if (index == 0)
{
sv.ScrollToTop();
return;
}
if (index == pnlContainer.Children.Count - 1)
{
sv.ScrollToBottom();
return;
}
if (index < oldIndex)
{
//move up and old item is at the top of the scroll view
var scrollPostionY = sv.VerticalOffset - sv.VerticalOffset%resultItemControl.ActualHeight +
resultItemControl.ActualHeight;
if (newItemBottomPoint.Y - scrollPostionY == 0)
{
scrollPosition = sv.VerticalOffset - resultItemControl.ActualHeight;
}
else
{
return;
}
}
else
{
//move down and old item is at the bottom of scroll view
double scrollPostionY = (sv.ActualHeight + sv.VerticalOffset) - (sv.ActualHeight + sv.VerticalOffset)%resultItemControl.ActualHeight;
if (scrollPostionY == newItemBottomPoint.Y - resultItemControl.ActualHeight)
{
scrollPosition = newItemBottomPoint.Y - sv.ActualHeight;
}
else
{
return;
}
}
sv.ScrollToVerticalOffset(scrollPosition);
}
}
}
public void SelectFirst()
{
Select(0);
}
public Result AcceptSelect()
{
int index = GetCurrentSelectedResultIndex();
if (index < 0) return null;
var resultItemControl = pnlContainer.Children[index] as ResultItem;
if (resultItemControl != null)
{
if (resultItemControl.Result.Action != null)
{
resultItemControl.Result.Action();
}
return resultItemControl.Result;
}
return null;
}
public ResultPanel()
{
InitializeComponent();
}
public void Clear()
{
pnlContainer.Children.Clear();
pnlContainer.Height = 0;
OnResultItemChangedEvent();
}
}
}

62
Wox/SettingWindow.xaml Normal file
View File

@@ -0,0 +1,62 @@
<Window x:Class="Wox.SettingWidow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Icon="Images\app.png"
Title="Wox Setting"
ResizeMode="NoResize"
WindowStartupLocation="CenterScreen"
Height="407.447" Width="843.989">
<TabControl Height="auto" >
<TabItem Header="Basic">
<StackPanel Orientation="Vertical" Margin="10">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Theme:" />
<ComboBox x:Name="themeComboBox" SelectionChanged="ThemeComboBox_OnSelectionChanged" HorizontalAlignment="Left" VerticalAlignment="Top" Width="120"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<CheckBox x:Name="cbReplaceWinR" />
<TextBlock Text="Replace Win+R:" />
</StackPanel>
</StackPanel>
</TabItem>
<TabItem Header="Web Search">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="50"></RowDefinition>
</Grid.RowDefinitions>
<ListView Grid.Row="0">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Header="Keyword" Width="180">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=OPERATOR}"></TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Website" Width="500">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=DDATE}"></TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Enable" Width="50" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=CONTENT}"></TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
<Button Grid.Row="1" HorizontalAlignment="Right" Click="ButtonBase_OnClick" Width="100" Margin="10">Add</Button>
</Grid>
</TabItem>
</TabControl>
</Window>

63
Wox/SettingWindow.xaml.cs Normal file
View File

@@ -0,0 +1,63 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using Wox.Helper;
namespace Wox
{
public partial class SettingWidow : Window
{
private MainWindow mainWindow;
public SettingWidow(MainWindow mainWindow)
{
this.mainWindow = mainWindow;
InitializeComponent();
Loaded += Setting_Loaded;
cbReplaceWinR.Checked += (o, e) =>
{
CommonStorage.Instance.UserSetting.ReplaceWinR = true;
CommonStorage.Instance.Save();
};
cbReplaceWinR.Unchecked += (o, e) =>
{
CommonStorage.Instance.UserSetting.ReplaceWinR = false;
CommonStorage.Instance.Save();
};
}
private void Setting_Loaded(object sender, RoutedEventArgs e)
{
foreach (string theme in LoadAvailableThemes())
{
string themeName = theme.Substring(theme.LastIndexOf('\\') + 1).Replace(".xaml", "");
themeComboBox.Items.Add(themeName);
}
themeComboBox.SelectedItem = CommonStorage.Instance.UserSetting.Theme;
cbReplaceWinR.IsChecked = CommonStorage.Instance.UserSetting.ReplaceWinR;
}
private List<string> LoadAvailableThemes()
{
string themePath = Directory.GetCurrentDirectory() + "\\Themes\\";
return Directory.GetFiles(themePath).Where(filePath => filePath.EndsWith(".xaml")).ToList();
}
private void ThemeComboBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
string themeName = themeComboBox.SelectedItem.ToString();
mainWindow.SetTheme(themeName);
CommonStorage.Instance.UserSetting.Theme = themeName;
CommonStorage.Instance.Save();
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
WebSearchSetting webSearch = new WebSearchSetting();
webSearch.Show();
}
}
}

117
Wox/Themes/Default.xaml Normal file
View File

@@ -0,0 +1,117 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<Style x:Key="QueryBoxStyle" TargetType="{x:Type TextBox}">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="FontSize" Value="25" />
<Setter Property="FontWeight" Value="Medium" />
<Setter Property="AllowDrop" Value="true" />
<Setter Property="Height" Value="46" />
<Setter Property="Background" Value="#616161" />
<Setter Property="Foreground" Value="#E3E0E3" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Stylus.IsFlicksEnabled" Value="False" />
</Style>
<Style x:Key="WindowStyle" TargetType="{x:Type Window}">
<Setter Property="Height" Value="80" />
<Setter Property="Width" Value="500" />
<Setter Property="Background" Value="#424242" />
</Style>
<Style x:Key="GridStyle" TargetType="{x:Type Grid}">
<Setter Property="Margin" Value="8 10 8 8" />
</Style>
<Style x:Key="PendingLineStyle" TargetType="{x:Type Line}">
<Setter Property="Stroke" Value="Blue" />
</Style>
<!-- Item Style -->
<Style x:Key="ItemTitleStyle" TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#FFFFF8" />
<Setter Property="FontSize" Value="16" />
<Setter Property="FontWeight" Value="Medium" />
</Style>
<Style x:Key="ItemSubTitleStyle" TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="#D9D9D4" />
</Style>
<Style x:Key="ItemStyle" TargetType="{x:Type UserControl}">
<Setter Property="Background" Value="Transparent" />
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Selected}" Value="true">
<Setter Property="Background" Value="#4F6180" />
</DataTrigger>
</Style.Triggers>
</Style>
<!-- ScrollViewer Style -->
<ControlTemplate x:Key="ScrollViewerControlTemplate" TargetType="{x:Type ScrollViewer}">
<Grid x:Name="Grid" Background="{TemplateBinding Background}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<!--content in the left of ScrollViewer, just default-->
<ScrollContentPresenter x:Name="PART_ScrollContentPresenter"
CanContentScroll="{TemplateBinding CanContentScroll}"
CanHorizontallyScroll="False"
CanVerticallyScroll="False"
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
Grid.Column="0"
Margin="{TemplateBinding Padding}"
Grid.Row="0" />
<!--Scrollbar in thr rigth of ScrollViewer-->
<ScrollBar x:Name="PART_VerticalScrollBar"
AutomationProperties.AutomationId="VerticalScrollBar"
Cursor="Arrow"
Grid.Column="1"
Margin="3 0 0 0"
Maximum="{TemplateBinding ScrollableHeight}"
Minimum="0"
Grid.Row="0"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"
Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"
ViewportSize="{TemplateBinding ViewportHeight}"
Style="{DynamicResource ScrollBarStyle}" />
</Grid>
</ControlTemplate>
<!-- button style in the middle of the scrollbar -->
<Style x:Key="ThumbStyle" TargetType="{x:Type Thumb}">
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="IsTabStop" Value="false"/>
<Setter Property="Focusable" Value="false"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Border CornerRadius="2" DockPanel.Dock="Right" Background="#616161" BorderBrush="Transparent" BorderThickness="0" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ScrollBarStyle" TargetType="{x:Type ScrollBar}">
<Setter Property="Stylus.IsPressAndHoldEnabled" Value="false" />
<Setter Property="Stylus.IsFlicksEnabled" Value="false" />
<!-- must set min width -->
<Setter Property="MinWidth" Value="0"/>
<Setter Property="Width" Value="5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ScrollBar}">
<DockPanel>
<Track x:Name="PART_Track" IsDirectionReversed="true" DockPanel.Dock="Right">
<Track.Thumb>
<Thumb Style="{DynamicResource ThumbStyle}"/>
</Track.Thumb>
</Track>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

126
Wox/Themes/Light.xaml Normal file
View File

@@ -0,0 +1,126 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="QueryBoxStyle" TargetType="{x:Type TextBox}">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="FontSize" Value="25"/>
<Setter Property="FontWeight" Value="Medium"/>
<Setter Property="AllowDrop" Value="true"/>
<Setter Property="Height" Value="46"/>
<Setter Property="Background" Value="#DEDEDE"/>
<Setter Property="Foreground" Value="#2E2F30" />
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
</Style>
<Style x:Key="WindowStyle" TargetType="{x:Type Window}" >
<Setter Property="Background" Value="#EDEDED"></Setter>
<Setter Property="Width" Value="520"></Setter>
<Setter Property="Height" Value="80"></Setter>
</Style>
<Style x:Key="GridStyle" TargetType="{x:Type Grid}" >
<Setter Property="Margin" Value="8 10 8 8"></Setter>
</Style>
<Style x:Key="PendingLineStyle" TargetType="{x:Type Line}" >
<Setter Property="Stroke" Value="Blue"></Setter>
</Style>
<!-- Item Style -->
<Style x:Key="ItemTitleStyle" TargetType="{x:Type TextBlock}" >
<Setter Property="Foreground" Value="#141411"></Setter>
<Setter Property="FontSize" Value="16"></Setter>
<Setter Property="FontWeight" Value="Medium"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=resultItemControl, Path=Selected}" Value="true">
<Setter Property="Foreground" Value="#F6F6FF"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
<Style x:Key="ItemSubTitleStyle" TargetType="{x:Type TextBlock}" >
<Setter Property="Foreground" Value="#B3B2B0"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=resultItemControl, Path=Selected}" Value="true">
<Setter Property="Foreground" Value="#F6F6FF"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
<Style x:Key="ItemStyle" TargetType="{x:Type UserControl}" >
<Setter Property="Background" Value="Transparent"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Selected}" Value="true">
<Setter Property="Background" Value="#543BFD"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
<!-- ScrollViewer Style -->
<ControlTemplate x:Key="ScrollViewerControlTemplate" TargetType="{x:Type ScrollViewer}">
<Grid x:Name="Grid" Background="{TemplateBinding Background}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<!--content in the left of ScrollViewer, just default-->
<ScrollContentPresenter x:Name="PART_ScrollContentPresenter"
CanContentScroll="{TemplateBinding CanContentScroll}"
CanHorizontallyScroll="False"
CanVerticallyScroll="False"
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
Grid.Column="0"
Margin="{TemplateBinding Padding}"
Grid.Row="0" />
<!--Scrollbar in thr rigth of ScrollViewer-->
<ScrollBar x:Name="PART_VerticalScrollBar"
AutomationProperties.AutomationId="VerticalScrollBar"
Cursor="Arrow"
Grid.Column="1"
Margin="2 0 0 0"
Maximum="{TemplateBinding ScrollableHeight}"
Minimum="0"
Grid.Row="0"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"
Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"
ViewportSize="{TemplateBinding ViewportHeight}"
Style="{DynamicResource ScrollBarStyle}" />
</Grid>
</ControlTemplate>
<!-- button style in the middle of the scrollbar -->
<Style x:Key="ThumbStyle" TargetType="{x:Type Thumb}">
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="IsTabStop" Value="false"/>
<Setter Property="Focusable" Value="false"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Border CornerRadius="2" DockPanel.Dock="Right" Background="#DEDEDE" BorderBrush="Transparent" BorderThickness="0" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ScrollBarStyle" TargetType="{x:Type ScrollBar}">
<Setter Property="Stylus.IsPressAndHoldEnabled" Value="false" />
<Setter Property="Stylus.IsFlicksEnabled" Value="false" />
<!-- must set min width -->
<Setter Property="MinWidth" Value="0"/>
<Setter Property="Width" Value="3.5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ScrollBar}">
<DockPanel>
<Track x:Name="PART_Track" IsDirectionReversed="true" DockPanel.Dock="Right">
<Track.Thumb>
<Thumb Style="{DynamicResource ThumbStyle}"/>
</Track.Thumb>
</Track>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

48
Wox/WebSearchSetting.xaml Normal file
View File

@@ -0,0 +1,48 @@
<Window x:Class="Wox.WebSearchSetting"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Icon="Images\app.png"
ResizeMode="NoResize"
WindowStartupLocation="CenterScreen"
Title="WebSearchSetting" Height="400" Width="674.766">
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition Height="40"></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition Height="24"></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition Height="24"></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition Height="24"></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Margin="10" FontSize="14" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right">Search URL:</TextBlock>
<TextBox Margin="10" Grid.Row="0" Width="400" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Left"></TextBox>
<TextBlock Margin="10 0 10 0" Foreground="Gray" VerticalAlignment="Top" Grid.Row="1" Grid.Column="1" TextWrapping="Wrap" HorizontalAlignment="Left">Perform a search on a website and copy the result URL. Replace your search term with {query} in curly brackets</TextBlock>
<TextBlock Margin="10" FontSize="14" Grid.Row="2" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right">Title:</TextBlock>
<TextBox Margin="10" Grid.Row="2" Width="400" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Left"></TextBox>
<TextBlock Margin="10 0 10 0" Foreground="Gray" VerticalAlignment="Top" Grid.Row="3" Grid.Column="1" TextWrapping="Wrap" HorizontalAlignment="Left">What to show in the Wox. The search query is automatically appended for clarity.</TextBlock>
<TextBlock Margin="10" FontSize="14" Grid.Row="4" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right">Keyword:</TextBlock>
<TextBox Margin="10" Grid.Row="4" Width="400" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Left"></TextBox>
<TextBlock Margin="10 0 10 0" Foreground="Gray" VerticalAlignment="Top" Grid.Row="5" Grid.Column="1" TextWrapping="Wrap" HorizontalAlignment="Left">What you type to use this shortcut.</TextBlock>
<TextBlock Margin="10" FontSize="14" Grid.Row="6" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Right">Validation:</TextBlock>
<StackPanel Grid.Row="6" Grid.Column="1" VerticalAlignment="Center" Orientation="Horizontal">
<TextBox Margin="10" Width="400" HorizontalAlignment="Left"></TextBox>
<Button x:Name="btnValidation" Width="60" Height="24">Test</Button>
</StackPanel>
<TextBlock Margin="10 0 10 0" Foreground="Gray" VerticalAlignment="Top" Grid.Row="7" Grid.Column="1" TextWrapping="Wrap" HorizontalAlignment="Left">Type some text and click test to check it works.</TextBlock>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Grid.Row="8" Grid.Column="1">
<Button x:Name="btnCancel" Click="BtnCancel_OnClick" Margin="10 0 10 0" Width="80" Height="25">Cancel</Button>
<Button Margin="10 0 10 0" Width="80" Height="25">Add</Button>
</StackPanel>
</Grid>
</Window>

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace Wox
{
public partial class WebSearchSetting : Window
{
public WebSearchSetting()
{
InitializeComponent();
}
private void BtnCancel_OnClick(object sender, RoutedEventArgs e)
{
Close();
}
}
}

291
Wox/Wox.csproj Normal file
View File

@@ -0,0 +1,291 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{DB90F671-D861-46BB-93A3-F1304F5BA1C5}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Wox</RootNamespace>
<AssemblyName>Wox</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages>
<TargetFrameworkProfile />
<PublishUrl>发布\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<UseVSHostingProcess>true</UseVSHostingProcess>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>app.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup>
<StartupObject>Wox.EntryPoint</StartupObject>
</PropertyGroup>
<ItemGroup>
<Reference Include="Accessibility" />
<Reference Include="log4net">
<HintPath>..\packages\log4net.2.0.3\lib\net35-full\log4net.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualBasic" />
<Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net35\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="PresentationUI, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
<Reference Include="ReachFramework" />
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Printing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="UIAutomationProvider" />
<Reference Include="UIAutomationTypes" />
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="WindowsInput">
<HintPath>..\packages\InputSimulator.1.0.4.0\lib\net20\WindowsInput.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="Commands\BaseCommand.cs" />
<Compile Include="Commands\CommandFactory.cs" />
<Compile Include="Commands\PluginCommand.cs" />
<Compile Include="Commands\SystemCommand.cs" />
<Compile Include="DispatcherExtensions.cs" />
<Compile Include="Helper\DwmDropShadow.cs" />
<Compile Include="Helper\KeyboardHook.cs" />
<Compile Include="Helper\Log.cs" />
<Compile Include="Helper\CommonStorage.cs" />
<Compile Include="Models\UserSetting.cs" />
<Compile Include="Models\WebSearch.cs" />
<Compile Include="Helper\WoxException.cs" />
<Compile Include="Helper\KeyboardListener.cs" />
<Compile Include="Msg.xaml.cs">
<DependentUpon>Msg.xaml</DependentUpon>
</Compile>
<Compile Include="PluginLoader\BasePluginLoader.cs" />
<Compile Include="PluginLoader\CSharpPluginLoader.cs" />
<Compile Include="Helper\IniParser.cs" />
<Compile Include="PluginLoader\Plugins.cs" />
<Compile Include="PluginLoader\PythonPluginLoader.cs" />
<Compile Include="PluginLoader\PythonPluginWrapper.cs" />
<Compile Include="Properties\Annotations.cs" />
<Compile Include="ResultPanel.xaml.cs">
<DependentUpon>ResultPanel.xaml</DependentUpon>
</Compile>
<Compile Include="ResultItem.xaml.cs">
<DependentUpon>ResultItem.xaml</DependentUpon>
</Compile>
<Compile Include="Models\UserSelectedRecords.cs" />
<Compile Include="SettingWindow.xaml.cs">
<DependentUpon>SettingWindow.xaml</DependentUpon>
</Compile>
<Compile Include="WebSearchSetting.xaml.cs">
<DependentUpon>WebSearchSetting.xaml</DependentUpon>
</Compile>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Page Include="Msg.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="ResultPanel.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="ResultItem.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="SettingWindow.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Themes\Light.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Themes\Default.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="WebSearchSetting.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="App.config" />
<None Include="packages.config">
<SubType>Designer</SubType>
</None>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<AppDesigner Include="Properties\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Pythonnet.Runtime\Python.Runtime.csproj">
<Project>{097b4ac0-74e9-4c58-bcf8-c69746ec8271}</Project>
<Name>Python.Runtime</Name>
</ProjectReference>
<ProjectReference Include="..\Wox.Plugin.System\Wox.Plugin.System.csproj">
<Project>{69ce0206-cb41-453d-88af-df86092ef9b8}</Project>
<Name>Wox.Plugin.System</Name>
</ProjectReference>
<ProjectReference Include="..\Wox.Plugin\Wox.Plugin.csproj">
<Project>{8451ECDD-2EA4-4966-BB0A-7BBC40138E80}</Project>
<Name>Wox.Plugin</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="Resources\app.ico" />
</ItemGroup>
<ItemGroup>
<None Include="Resources\ctrl.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="Images\ctrl.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="app.ico">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Resource>
</ItemGroup>
<ItemGroup>
<WCFMetadata Include="Service References\" />
</ItemGroup>
<ItemGroup>
<Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup>
<Resource Include="Images\app.png" />
<Resource Include="Images\bookmark.png" />
<Resource Include="Images\close.png" />
<Resource Include="Images\cmd.png" />
<Resource Include="Images\enter.png" />
<Resource Include="Images\exit.png" />
<Resource Include="Images\folder.png" />
<Resource Include="Images\lock.png" />
<Resource Include="Images\logoff.png" />
<Resource Include="Images\work.png" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<PropertyGroup>
<PostBuildEvent>xcopy /Y $(ProjectDir)Images\*.* $(TargetDir)Images\
xcopy /Y $(ProjectDir)app.ico $(TargetDir)
xcopy /Y $(ProjectDir)Themes\*.* $(TargetDir)Themes\</PostBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

BIN
Wox/app.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 KiB

BIN
Wox/app.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

6
Wox/packages.config Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="InputSimulator" version="1.0.4.0" targetFramework="net35" />
<package id="log4net" version="2.0.3" targetFramework="net35" />
<package id="Newtonsoft.Json" version="5.0.8" targetFramework="net35" />
</packages>