Skip to content

Commit 0d53954

Browse files
committed
refactored the code. many bugfixes and performance improvements
1 parent 395362a commit 0d53954

14 files changed

+1313
-671
lines changed

SvgFileType/LayersMode.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
namespace SvgFileTypePlugin
22
{
3-
public enum LayersMode
3+
internal enum LayersMode
44
{
55
Flat,
66
Groups,

SvgFileType/MessageBoxEx.cs

Lines changed: 315 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,315 @@
1+
using System;
2+
using System.Drawing;
3+
using System.Runtime.InteropServices;
4+
using System.Threading.Tasks;
5+
using System.Windows.Forms;
6+
7+
namespace SvgFileTypePlugin
8+
{
9+
/// <summary>
10+
/// Parent centered MessageBox dialog in C#
11+
/// </summary>
12+
internal static class MessageBoxEx
13+
{
14+
private static IWin32Window _owner;
15+
private static readonly HookProc _hookProc = MessageBoxHookProc;
16+
private static IntPtr _hHook = IntPtr.Zero;
17+
18+
public static DialogResult Show(string text)
19+
{
20+
Initialize();
21+
return MessageBox.Show(text);
22+
}
23+
24+
public static DialogResult Show(string text, string caption)
25+
{
26+
Initialize();
27+
return MessageBox.Show(text, caption);
28+
}
29+
30+
public static DialogResult Show(string text, string caption, MessageBoxButtons buttons)
31+
{
32+
Initialize();
33+
return MessageBox.Show(text, caption, buttons);
34+
}
35+
36+
public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon)
37+
{
38+
Initialize();
39+
return MessageBox.Show(text, caption, buttons, icon);
40+
}
41+
42+
public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon,
43+
MessageBoxDefaultButton defButton)
44+
{
45+
Initialize();
46+
return MessageBox.Show(text, caption, buttons, icon, defButton);
47+
}
48+
49+
public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon,
50+
MessageBoxDefaultButton defButton, MessageBoxOptions options)
51+
{
52+
Initialize();
53+
return MessageBox.Show(text, caption, buttons, icon, defButton, options);
54+
}
55+
56+
public static DialogResult Show(IWin32Window owner, string text)
57+
{
58+
_owner = owner;
59+
Initialize();
60+
return MessageBox.Show(owner, text);
61+
}
62+
63+
public static DialogResult Show(IWin32Window owner, string text, string caption)
64+
{
65+
_owner = owner;
66+
Initialize();
67+
return MessageBox.Show(owner, text, caption);
68+
}
69+
70+
public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons)
71+
{
72+
_owner = owner;
73+
Initialize();
74+
return MessageBox.Show(owner, text, caption, buttons);
75+
}
76+
77+
public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons,
78+
MessageBoxIcon icon)
79+
{
80+
_owner = owner;
81+
Initialize();
82+
return MessageBox.Show(owner, text, caption, buttons, icon);
83+
}
84+
85+
public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons,
86+
MessageBoxIcon icon, MessageBoxDefaultButton defButton)
87+
{
88+
_owner = owner;
89+
Initialize();
90+
return MessageBox.Show(owner, text, caption, buttons, icon, defButton);
91+
}
92+
93+
public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons,
94+
MessageBoxIcon icon, MessageBoxDefaultButton defButton, MessageBoxOptions options)
95+
{
96+
_owner = owner;
97+
Initialize();
98+
return MessageBox.Show(owner, text, caption, buttons, icon,
99+
defButton, options);
100+
}
101+
102+
public delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
103+
104+
public const int WH_CALLWNDPROCRET = 12;
105+
public const int WH_CALLWNDPROC = 4;
106+
107+
public enum CbtHookAction
108+
{
109+
HCBT_MOVESIZE = 0,
110+
HCBT_MINMAX = 1,
111+
HCBT_QS = 2,
112+
HCBT_CREATEWND = 3,
113+
HCBT_DESTROYWND = 4,
114+
HCBT_ACTIVATE = 5,
115+
HCBT_CLICKSKIPPED = 6,
116+
HCBT_KEYSKIPPED = 7,
117+
HCBT_SYSCOMMAND = 8,
118+
HCBT_SETFOCUS = 9
119+
}
120+
121+
private static class NativeMethods
122+
{
123+
[DllImport("user32", SetLastError = true)]
124+
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
125+
126+
[DllImport("user32", SetLastError = true)]
127+
public static extern bool GetWindowRect(IntPtr hWnd, ref Rectangle lpRect);
128+
129+
[DllImport("user32", SetLastError = true)]
130+
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy,
131+
SetWindowPosFlags uFlags);
132+
133+
[DllImport("user32", SetLastError = true)]
134+
public static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, uint threadId);
135+
136+
[DllImport("user32", SetLastError = true)]
137+
public static extern int UnhookWindowsHookEx(IntPtr idHook);
138+
139+
[DllImport("user32", SetLastError = true)]
140+
public static extern IntPtr CallNextHookEx(IntPtr idHook, int nCode, IntPtr wParam, IntPtr lParam);
141+
}
142+
143+
[StructLayout(LayoutKind.Sequential)]
144+
public struct CWPRETSTRUCT
145+
{
146+
public IntPtr lResult;
147+
public IntPtr lParam;
148+
public IntPtr wParam;
149+
public uint message;
150+
public IntPtr hwnd;
151+
};
152+
153+
private static void Initialize()
154+
{
155+
if (_hHook != IntPtr.Zero)
156+
{
157+
throw new NotSupportedException("multiple calls are not supported");
158+
}
159+
160+
if (_owner == null)
161+
return;
162+
163+
IntPtr ptr = _owner.Handle;
164+
_hHook = NativeMethods.SetWindowsHookEx(WH_CALLWNDPROCRET, _hookProc, IntPtr.Zero,
165+
NativeMethods.GetWindowThreadProcessId(ptr, out uint _));
166+
}
167+
168+
private static IntPtr MessageBoxHookProc(int nCode, IntPtr wParam, IntPtr lParam)
169+
{
170+
if (nCode < 0)
171+
{
172+
return NativeMethods.CallNextHookEx(_hHook, nCode, wParam, lParam);
173+
}
174+
175+
CWPRETSTRUCT msg = (CWPRETSTRUCT)Marshal.PtrToStructure(lParam, typeof(CWPRETSTRUCT));
176+
IntPtr hook = _hHook;
177+
178+
if (msg.message == (int)CbtHookAction.HCBT_ACTIVATE)
179+
{
180+
try
181+
{
182+
CenterWindow(msg.hwnd);
183+
}
184+
finally
185+
{
186+
NativeMethods.UnhookWindowsHookEx(_hHook);
187+
_hHook = IntPtr.Zero;
188+
}
189+
}
190+
191+
return NativeMethods.CallNextHookEx(hook, nCode, wParam, lParam);
192+
}
193+
194+
private static void CenterWindow(IntPtr hChildWnd)
195+
{
196+
Rectangle recChild = new Rectangle(0, 0, 0, 0);
197+
bool success = NativeMethods.GetWindowRect(hChildWnd, ref recChild);
198+
199+
int width = recChild.Width - recChild.X;
200+
int height = recChild.Height - recChild.Y;
201+
202+
Rectangle recParent = new Rectangle(0, 0, 0, 0);
203+
success = NativeMethods.GetWindowRect(_owner.Handle, ref recParent);
204+
205+
if (!success ||
206+
(recParent.X == -32000 && recParent.Y == -32000))
207+
{
208+
// https://blogs.msdn.microsoft.com/oldnewthing/20041028-00/?p=37453
209+
NativeMethods.UnhookWindowsHookEx(_hHook);
210+
return;
211+
}
212+
213+
Point ptCenter = new Point
214+
{
215+
X = recParent.X + (recParent.Width - recParent.X) / 2,
216+
Y = recParent.Y + (recParent.Height - recParent.Y) / 2
217+
};
218+
219+
Point ptStart = new Point
220+
{
221+
X = ptCenter.X - width / 2,
222+
Y = ptCenter.Y - height / 2
223+
};
224+
225+
//ptStart.X = ptStart.X < 0 ? 0 : ptStart.X;
226+
//ptStart.Y = ptStart.Y < 0 ? 0 : ptStart.Y;
227+
228+
//int result = NativeMethods.MoveWindow(hChildWnd, ptStart.X, ptStart.Y, width, height, false);
229+
Task.Factory.StartNew(() =>
230+
{
231+
NativeMethods.SetWindowPos(hChildWnd, IntPtr.Zero, ptStart.X, ptStart.Y, width, height,
232+
SetWindowPosFlags.AsynchronousWindowPosition |
233+
SetWindowPosFlags.IgnoreResize |
234+
SetWindowPosFlags.DoNotActivate |
235+
SetWindowPosFlags.DoNotChangeOwnerZOrder |
236+
SetWindowPosFlags.IgnoreZOrder);
237+
});
238+
}
239+
240+
[Flags]
241+
private enum SetWindowPosFlags : uint
242+
{
243+
/// <summary>If the calling thread and the thread that owns the window are attached to different input queues,
244+
/// the system posts the request to the thread that owns the window. This prevents the calling thread from
245+
/// blocking its execution while other threads process the request.</summary>
246+
/// <remarks>SWP_ASYNCWINDOWPOS</remarks>
247+
AsynchronousWindowPosition = 0x4000,
248+
249+
/// <summary>Prevents generation of the WM_SYNCPAINT message.</summary>
250+
/// <remarks>SWP_DEFERERASE</remarks>
251+
DeferErase = 0x2000,
252+
253+
/// <summary>Draws a frame (defined in the window's class description) around the window.</summary>
254+
/// <remarks>SWP_DRAWFRAME</remarks>
255+
DrawFrame = 0x0020,
256+
257+
/// <summary>Applies new frame styles set using the SetWindowLong function. Sends a WM_NCCALCSIZE message to
258+
/// the window, even if the window's size is not being changed. If this flag is not specified, WM_NCCALCSIZE
259+
/// is sent only when the window's size is being changed.</summary>
260+
/// <remarks>SWP_FRAMECHANGED</remarks>
261+
FrameChanged = 0x0020,
262+
263+
/// <summary>Hides the window.</summary>
264+
/// <remarks>SWP_HIDEWINDOW</remarks>
265+
HideWindow = 0x0080,
266+
267+
/// <summary>Does not activate the window. If this flag is not set, the window is activated and moved to the
268+
/// top of either the topmost or non-topmost group (depending on the setting of the hWndInsertAfter
269+
/// parameter).</summary>
270+
/// <remarks>SWP_NOACTIVATE</remarks>
271+
DoNotActivate = 0x0010,
272+
273+
/// <summary>Discards the entire contents of the client area. If this flag is not specified, the valid
274+
/// contents of the client area are saved and copied back into the client area after the window is sized or
275+
/// repositioned.</summary>
276+
/// <remarks>SWP_NOCOPYBITS</remarks>
277+
DoNotCopyBits = 0x0100,
278+
279+
/// <summary>Retains the current position (ignores X and Y parameters).</summary>
280+
/// <remarks>SWP_NOMOVE</remarks>
281+
IgnoreMove = 0x0002,
282+
283+
/// <summary>Does not change the owner window's position in the Z order.</summary>
284+
/// <remarks>SWP_NOOWNERZORDER</remarks>
285+
DoNotChangeOwnerZOrder = 0x0200,
286+
287+
/// <summary>Does not redraw changes. If this flag is set, no repainting of any kind occurs. This applies to
288+
/// the client area, the nonclient area (including the title bar and scroll bars), and any part of the parent
289+
/// window uncovered as a result of the window being moved. When this flag is set, the application must
290+
/// explicitly invalidate or redraw any parts of the window and parent window that need redrawing.</summary>
291+
/// <remarks>SWP_NOREDRAW</remarks>
292+
DoNotRedraw = 0x0008,
293+
294+
/// <summary>Same as the SWP_NOOWNERZORDER flag.</summary>
295+
/// <remarks>SWP_NOREPOSITION</remarks>
296+
DoNotReposition = 0x0200,
297+
298+
/// <summary>Prevents the window from receiving the WM_WINDOWPOSCHANGING message.</summary>
299+
/// <remarks>SWP_NOSENDCHANGING</remarks>
300+
DoNotSendChangingEvent = 0x0400,
301+
302+
/// <summary>Retains the current size (ignores the cx and cy parameters).</summary>
303+
/// <remarks>SWP_NOSIZE</remarks>
304+
IgnoreResize = 0x0001,
305+
306+
/// <summary>Retains the current Z order (ignores the hWndInsertAfter parameter).</summary>
307+
/// <remarks>SWP_NOZORDER</remarks>
308+
IgnoreZOrder = 0x0004,
309+
310+
/// <summary>Displays the window.</summary>
311+
/// <remarks>SWP_SHOWWINDOW</remarks>
312+
ShowWindow = 0x0040,
313+
}
314+
}
315+
}

SvgFileType/PaintGroupBoundaries.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,17 @@
66
namespace SvgFileTypePlugin
77
{
88
// Used to determine boundaries of a group.
9-
public class PaintGroupBoundaries : SvgVisualElement
9+
internal class PaintGroupBoundaries : SvgVisualElement
1010
{
11-
public SvgGroup RelatedGroup { get; set; }
11+
public PaintGroupBoundaries(SvgGroup relatedGroup)
12+
{
13+
RelatedGroup = relatedGroup;
14+
}
15+
16+
public SvgGroup RelatedGroup { get; }
17+
1218
public bool IsStart { get; set; }
19+
1320
public override RectangleF Bounds => throw new NotImplementedException();
1421

1522
public override SvgElement DeepCopy()

SvgFileType/Properties/AssemblyInfo.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System.Reflection;
2-
using System.Runtime.CompilerServices;
32
using System.Runtime.InteropServices;
43

54
// General Information about an assembly is controlled through the following
@@ -10,7 +9,7 @@
109
[assembly: AssemblyConfiguration("")]
1110
[assembly: AssemblyCompany("")]
1211
[assembly: AssemblyProduct("SvgFileType")]
13-
[assembly: AssemblyCopyright("Copyright © 2019")]
12+
[assembly: AssemblyCopyright("Copyright © 2020")]
1413
[assembly: AssemblyTrademark("")]
1514
[assembly: AssemblyCulture("")]
1615

0 commit comments

Comments
 (0)