Skip to content

Commit 58f4df8

Browse files
committed
support single instance
1 parent 64cd2bc commit 58f4df8

File tree

7 files changed

+99
-20
lines changed

7 files changed

+99
-20
lines changed

src/XamlService/Events/TabEvents.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ public class CloseTabEvent : PubSubEvent<string> { }
77
public class UpdateTabStatusEvent : PubSubEvent<TabFlag> { }
88
public class InitWorkAreaEvent : PubSubEvent { }
99
public class SelectTabEvent : PubSubEvent<TabSelectInfo> { }
10+
public class OpenFilesEvent : PubSubEvent<string[]> { }
1011
}

src/XamlUtil/Common/Win32.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,17 @@ namespace XamlUtil.Common
66
public static class Win32
77
{
88
public const int WS_SHOWNORMAL = 1;
9+
public const int WM_COPYDATA = 0x004A;
10+
11+
[StructLayout(LayoutKind.Sequential)]
12+
public struct CopyData
13+
{
14+
public IntPtr dwData;
15+
public int cbData;
16+
17+
[MarshalAs(UnmanagedType.LPStr)]
18+
public string lpData;
19+
}
920

1021
[DllImport("User32.dll")]
1122
public static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow = WS_SHOWNORMAL);
@@ -14,6 +25,9 @@ public static class Win32
1425
public static extern bool SetForegroundWindow(IntPtr hWnd);
1526

1627
[DllImport("User32.dll")]
17-
private static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
28+
public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, ref CopyData lParam);
29+
30+
[DllImport("User32.dll")]
31+
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
1832
}
1933
}

src/XamlViewer/App.xaml.cs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,19 @@
99
using System.Windows;
1010
using System.Windows.Controls;
1111
using System.Windows.Threading;
12+
1213
using Prism.DryIoc;
1314
using Prism.Events;
1415
using Prism.Ioc;
1516
using Prism.Modularity;
1617
using Prism.Mvvm;
1718
using Prism.Regions;
19+
1820
using XamlUtil.IO;
21+
using XamlUtil.Common;
1922
using XamlService.Commands;
2023
using XamlService.Events;
2124
using XamlService.Utils;
22-
using XamlUtil.Common;
2325
using XamlViewer.Dialogs;
2426
using XamlViewer.Models;
2527
using XamlViewer.Regions;
@@ -101,15 +103,24 @@ protected override void OnStartup(StartupEventArgs e)
101103

102104
if (!isNew && process != null)
103105
{
104-
Win32.ShowWindowAsync(process.MainWindowHandle);
105-
Win32.SetForegroundWindow(process.MainWindowHandle);
106+
var hwnd = process.MainWindowHandle;
107+
108+
Win32.ShowWindowAsync(hwnd);
109+
Win32.SetForegroundWindow(hwnd);
106110

107111
if (e.Args.Length > 0)
108112
{
109113
var xamls = e.Args.Where(f => Path.GetExtension(f).ToLower() == ".xaml").ToArray();
110114
if (xamls != null && xamls.Length > 0)
111115
{
112-
//TODO:Send Message...
116+
var message = string.Join("|", xamls);
117+
var cds = new Win32.CopyData();
118+
119+
cds.dwData = IntPtr.Zero;
120+
cds.lpData = message;
121+
cds.cbData = System.Text.Encoding.Default.GetBytes(message).Length + 1;
122+
123+
Win32.SendMessage(hwnd, Win32.WM_COPYDATA, 0, ref cds);
113124
}
114125
}
115126

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"profiles": {
3+
"XamlViewer": {
4+
"commandName": "Project"
5+
}
6+
}
7+
}

src/XamlViewer/ViewModels/MainViewModel.cs

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
1-
using Prism.Commands;
2-
using Prism.Ioc;
3-
using Prism.Mvvm;
1+
using System;
2+
using System.IO;
3+
using System.Linq;
44
using System.ComponentModel;
55
using System.Windows;
6+
using System.Windows.Interop;
7+
8+
using Prism.Commands;
9+
using Prism.Ioc;
10+
using Prism.Mvvm;
11+
using Prism.Events;
12+
613
using XamlUtil.IO;
14+
using XamlUtil.Common;
715
using XamlViewer.Models;
816
using XamlService.Commands;
9-
using System.Linq;
10-
using System.IO;
11-
using Prism.Events;
1217
using XamlService.Events;
1318

1419
namespace XamlViewer.ViewModels
@@ -18,9 +23,13 @@ public class MainViewModel : BindableBase
1823
private AppData _appData = null;
1924
private IEventAggregator _eventAggregator = null;
2025

26+
private HwndSource _hwndSource = null;
27+
private HwndSourceHook _hwndSourceHook = null;
2128
private GridLength _lastDataSourceColumnWidth = new GridLength(1, GridUnitType.Star);
2229

2330
public DelegateCommand ExpandOrCollapseCommand { get; private set; }
31+
32+
public DelegateCommand<Window> LoadedCommand { get; private set; }
2433
public DelegateCommand ActivatedCommand { get; private set; }
2534
public DelegateCommand<DragEventArgs> DropCommand { get; private set; }
2635
public DelegateCommand<CancelEventArgs> ClosingCommand { get; private set; }
@@ -47,14 +56,16 @@ private void InitEvent()
4756
private void InitCommand()
4857
{
4958
ExpandOrCollapseCommand = new DelegateCommand(ExpandOrCollapse);
59+
60+
LoadedCommand = new DelegateCommand<Window>(Loaded);
5061
ActivatedCommand = new DelegateCommand(Activated);
5162
DropCommand = new DelegateCommand<DragEventArgs>(Drop);
5263
ClosingCommand = new DelegateCommand<CancelEventArgs>(Closing);
5364
}
5465

5566
private void InitStatus()
5667
{
57-
if(_appData.Config.IsOpenDataSource)
68+
if (_appData.Config.IsOpenDataSource)
5869
OnOpenDataSource(true);
5970
}
6071

@@ -92,6 +103,17 @@ private void ExpandOrCollapse()
92103
ExpandOrCollapse(_isExpandSetting);
93104
}
94105

106+
private void Loaded(Window win)
107+
{
108+
if (_hwndSourceHook == null)
109+
_hwndSourceHook = new HwndSourceHook(WndProc);
110+
111+
_hwndSource?.Dispose();
112+
113+
_hwndSource = PresentationSource.FromVisual(win) as HwndSource;
114+
_hwndSource?.AddHook(_hwndSourceHook);
115+
}
116+
95117
private void Activated()
96118
{
97119
if (_appCommands == null)
@@ -117,16 +139,17 @@ private async void Closing(CancelEventArgs e)
117139
await _appData.DealExistedFileAction?.Invoke();
118140

119141
var dataSourceFile = ResourcesMap.LocationDic[Location.DataSourceFile];
120-
121-
if(!string.IsNullOrWhiteSpace(_appData.Config.DataSourceJsonString))
142+
143+
if (!string.IsNullOrWhiteSpace(_appData.Config.DataSourceJsonString))
122144
FileHelper.SaveToFile(dataSourceFile, _appData.Config.DataSourceJsonString);
123-
else
124-
{
125-
if(FileHelper.Exists(dataSourceFile))
126-
File.Delete(dataSourceFile);
127-
}
128-
145+
else
146+
{
147+
if (FileHelper.Exists(dataSourceFile))
148+
File.Delete(dataSourceFile);
149+
}
150+
129151
FileHelper.SaveToJsonFile(ResourcesMap.LocationDic[Location.GlobalConfigFile], _appData.Config);
152+
_hwndSource?.RemoveHook(_hwndSourceHook);
130153
}
131154

132155
#endregion
@@ -187,6 +210,20 @@ private void ExpandOrCollapse(bool isExpand)
187210
SettingRowHeight = isExpand ? GridLength.Auto : new GridLength(0);
188211
}
189212

213+
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
214+
{
215+
if (msg == Win32.WM_COPYDATA)
216+
{
217+
var cds = (Win32.CopyData)System.Runtime.InteropServices.Marshal.PtrToStructure(lParam, typeof(Win32.CopyData));
218+
var xamlFiles = cds.lpData.Split("|".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).Select(f => Path.GetFullPath(f)).ToArray();
219+
220+
_eventAggregator.GetEvent<OpenFilesEvent>().Publish(xamlFiles);
221+
222+
}
223+
224+
return hwnd;
225+
}
226+
190227
#endregion
191228
}
192229
}

src/XamlViewer/ViewModels/TabsViewModel.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ private void InitEvent()
114114
{
115115
_eventAggregator.GetEvent<InitWorkAreaEvent>().Subscribe(OnInitWorkArea);
116116
_eventAggregator.GetEvent<SyncDataSourceEvent>().Subscribe(OnSyncDataSource);
117+
_eventAggregator.GetEvent<OpenFilesEvent>().Subscribe(OpenFiles);
117118
}
118119

119120
private void InitCommand()
@@ -402,6 +403,11 @@ private void OnSyncDataSource(string jsonString)
402403
IsSyncDataSource = !string.IsNullOrWhiteSpace(jsonString);
403404
}
404405

406+
private void OpenFiles(string[] xamlFiles)
407+
{
408+
Open(xamlFiles);
409+
}
410+
405411
#endregion
406412

407413
#region Func

src/XamlViewer/Views/MainWindow.xaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
Title="{Binding Title}" HideOriginalTitle="True" AllowDrop="True"
1616
WindowStartupLocation="CenterScreen" Height="600" Width="900" MinWidth="500" MinHeight="500">
1717
<behaviors:Interaction.Triggers>
18+
<behaviors:EventTrigger EventName="Loaded">
19+
<behaviors:InvokeCommandAction Command="{Binding LoadedCommand}" CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}"/>
20+
</behaviors:EventTrigger>
1821
<behaviors:EventTrigger EventName="Activated">
1922
<behaviors:InvokeCommandAction Command="{Binding ActivatedCommand}"/>
2023
</behaviors:EventTrigger>

0 commit comments

Comments
 (0)