diff --git a/InkCanvasForClass/InkCanvasForClass.csproj b/InkCanvasForClass/InkCanvasForClass.csproj
index ec48f94..4d931f9 100644
--- a/InkCanvasForClass/InkCanvasForClass.csproj
+++ b/InkCanvasForClass/InkCanvasForClass.csproj
@@ -73,6 +73,7 @@
bundled
False
AnyCPU
+ True
bin\$(Platform)\$(Configuration)\
diff --git a/InkCanvasForClass/MainWindow_cs/MW_Screenshot.cs b/InkCanvasForClass/MainWindow_cs/MW_Screenshot.cs
index af35d08..fdf95a3 100644
--- a/InkCanvasForClass/MainWindow_cs/MW_Screenshot.cs
+++ b/InkCanvasForClass/MainWindow_cs/MW_Screenshot.cs
@@ -1,8 +1,10 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
+using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
@@ -15,273 +17,606 @@ using PixelFormat = System.Drawing.Imaging.PixelFormat;
namespace Ink_Canvas
{
- public partial class MainWindow : Window
- {
- private void SaveScreenshot(bool isHideNotification, string fileName = null)
- {
- var bitmap = GetScreenshotBitmap();
- string savePath = Settings.Automation.AutoSavedStrokesLocation + @"\Auto Saved - Screenshots";
- if (fileName == null) fileName = DateTime.Now.ToString("u").Replace(":", "-");
- if (Settings.Automation.IsSaveScreenshotsInDateFolders)
- {
- savePath += @"\" + DateTime.Now.ToString("yyyy-MM-dd");
- }
- savePath += @"\" + fileName + ".png";
- if (!Directory.Exists(Path.GetDirectoryName(savePath)))
- {
- Directory.CreateDirectory(Path.GetDirectoryName(savePath));
- }
- bitmap.Save(savePath, ImageFormat.Png);
- if (Settings.Automation.IsAutoSaveStrokesAtScreenshot)
- {
- SaveInkCanvasStrokes(false, false);
- }
- if (!isHideNotification)
- {
- ShowNewToast("截图成功保存至 " + savePath, MW_Toast.ToastType.Success, 3000);
- }
- }
+ public partial class MainWindow : Window
+ {
+ private void SaveScreenshot(bool isHideNotification, string fileName = null)
+ {
+ var bitmap = GetScreenshotBitmap();
+ string savePath = Settings.Automation.AutoSavedStrokesLocation + @"\Auto Saved - Screenshots";
+ if (fileName == null) fileName = DateTime.Now.ToString("u").Replace(":", "-");
+ if (Settings.Automation.IsSaveScreenshotsInDateFolders)
+ {
+ savePath += @"\" + DateTime.Now.ToString("yyyy-MM-dd");
+ }
+ savePath += @"\" + fileName + ".png";
+ if (!Directory.Exists(Path.GetDirectoryName(savePath)))
+ {
+ Directory.CreateDirectory(Path.GetDirectoryName(savePath));
+ }
+ bitmap.Save(savePath, ImageFormat.Png);
+ if (Settings.Automation.IsAutoSaveStrokesAtScreenshot)
+ {
+ SaveInkCanvasStrokes(false, false);
+ }
+ if (!isHideNotification)
+ {
+ ShowNewToast("截图成功保存至 " + savePath, MW_Toast.ToastType.Success, 3000);
+ }
+ }
- #region MagnificationAPI 獲取屏幕截圖並過濾ICC窗口
+ #region MagnificationAPI 獲取屏幕截圖並過濾ICC窗口
- public static IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong)
- {
- if (IntPtr.Size == 8)
- return SetWindowLongPtr64(hWnd, nIndex, dwNewLong);
- else
- return new IntPtr(SetWindowLong32(hWnd, nIndex, dwNewLong.ToInt32()));
- }
+ public static IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong)
+ {
+ if (IntPtr.Size == 8)
+ return SetWindowLongPtr64(hWnd, nIndex, dwNewLong);
+ else
+ return new IntPtr(SetWindowLong32(hWnd, nIndex, dwNewLong.ToInt32()));
+ }
- [DllImport("user32.dll", EntryPoint="SetWindowLong")]
- private static extern int SetWindowLong32(IntPtr hWnd, int nIndex, int dwNewLong);
+ [DllImport("user32.dll", EntryPoint="SetWindowLong")]
+ private static extern int SetWindowLong32(IntPtr hWnd, int nIndex, int dwNewLong);
- [DllImport("user32.dll", EntryPoint="SetWindowLongPtr")]
- private static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
+ [DllImport("user32.dll", EntryPoint="SetWindowLongPtr")]
+ private static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
- [DllImport("user32.dll", EntryPoint="GetWindowLong")]
- static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex);
+ [DllImport("user32.dll", EntryPoint="GetWindowLong")]
+ static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex);
- [DllImport("user32.dll")]
- public static extern bool SetLayeredWindowAttributes(IntPtr hwnd, uint crKey, byte bAlpha, uint dwFlags);
+ [DllImport("user32.dll")]
+ public static extern bool SetLayeredWindowAttributes(IntPtr hwnd, uint crKey, byte bAlpha, uint dwFlags);
- [DllImport("user32.dll", SetLastError=true)]
- private static extern IntPtr CreateWindowEx(
- uint dwExStyle,
- string lpClassName,
- string lpWindowName,
- uint dwStyle,
- int x,
- int y,
- int nWidth,
- int nHeight,
- IntPtr hWndParent,
- IntPtr hMenu,
- IntPtr hInstance,
- IntPtr lpParam);
+ [DllImport("user32.dll", SetLastError=true)]
+ private static extern IntPtr CreateWindowEx(
+ uint dwExStyle,
+ string lpClassName,
+ string lpWindowName,
+ uint dwStyle,
+ int x,
+ int y,
+ int nWidth,
+ int nHeight,
+ IntPtr hWndParent,
+ IntPtr hMenu,
+ IntPtr hInstance,
+ IntPtr lpParam);
+ [DllImport("user32.dll")]
+ static extern bool DestroyWindow(IntPtr hWnd);
- public void SaveScreenshotToDesktopByMagnificationAPI(HWND[] excludedHwnds, Action callbackAction) {
+ Bitmap RemoveImageTransparancy(Bitmap src) {
+ Bitmap target = new Bitmap(src.Size.Width,src.Size.Height);
+ Graphics g = Graphics.FromImage(target);
+ g.DrawRectangle(new System.Drawing.Pen(new SolidBrush(System.Drawing.Color.White)), 0, 0, target.Width, target.Height);
+ g.DrawImage(src, 0, 0);
+ return target;
+ }
- if (OSVersion.GetOperatingSystem() < OperatingSystem.Windows8 && OSVersion.GetOperatingSystem() > OperatingSystem.Windows10) return;
- if (!Magnification.MagInitialize()) return;
+ public enum WindowStyles : uint
+ {
+ /// The window has a thin-line border.
+ WS_BORDER = 0x800000,
- // 創建宿主窗體
- var mainWinMag = new Window();
- mainWinMag.WindowState = WindowState.Maximized;
- mainWinMag.WindowStyle = WindowStyle.None;
- mainWinMag.ResizeMode = ResizeMode.NoResize;
- mainWinMag.Background = new SolidColorBrush(Colors.Transparent);
- mainWinMag.AllowsTransparency = true;
- mainWinMag.Show();
- var handle = new WindowInteropHelper(mainWinMag).Handle;
- SetWindowPos(handle, new IntPtr(1), 0, 0, System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width,
- System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height, 0x0080); // SWP_HIDEWINDOW
- SetWindowLongPtr(handle, -20, new IntPtr((int)GetWindowLongPtr(handle, -20) | 0x00080000));
- SetLayeredWindowAttributes(handle,0, 255, (byte)0x2);
+ /// The window has a title bar (includes the WS_BORDER style).
+ WS_CAPTION = 0xc00000,
- // 創建放大鏡窗體(使用Win32方法)
- var hwndMag = CreateWindowEx(0,"Magnifier", "ICCMagnifierWindow", (uint)(0x40000000L | 0x10000000L), 0, 0,
- System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width,
- System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height, handle, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
+ ///
+ /// The window is a child window. A window with this style cannot have a menu bar. This style cannot be used with the WS_POPUP style.
+ ///
+ WS_CHILD = 0x40000000,
- // 過濾窗口
- var hwnds = new List { new HWND(hwndMag) };
- hwnds.AddRange(excludedHwnds);
- if (!Magnification.MagSetWindowFilterList(new HWND(hwndMag),
- Magnification.MW_FILTERMODE.MW_FILTERMODE_EXCLUDE, hwnds.Count, hwnds.ToArray())) return;
+ ///
+ /// Excludes the area occupied by child windows when drawing occurs within the parent window. This style is used when creating
+ /// the parent window.
+ ///
+ WS_CLIPCHILDREN = 0x2000000,
- // 保存數據
- if (!Magnification.MagSetImageScalingCallback(new HWND(hwndMag),
- (hwnd, srcdata, srcheader, destdata, destheader, unclipped, clipped, dirty) => {
- Bitmap bm = new Bitmap((int)srcheader.width, (int)srcheader.height, (int)srcheader.width * 4,
- PixelFormat.Format32bppRgb, srcdata);
- callbackAction(bm);
- return true;
- })) return;
+ ///
+ /// Clips child windows relative to each other; that is, when a particular child window receives a WM_PAINT message, the
+ /// WS_CLIPSIBLINGS style clips all other overlapping child windows out of the region of the child window to be updated. If
+ /// WS_CLIPSIBLINGS is not specified and child windows overlap, it is possible, when drawing within the client area of a child
+ /// window, to draw within the client area of a neighboring child window.
+ ///
+ WS_CLIPSIBLINGS = 0x4000000,
- // 設置窗口Source
- if (!Magnification.MagSetWindowSource(new HWND(hwndMag),
- new RECT(0, 0, System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width,
- System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height))) return;
+ ///
+ /// The window is initially disabled. A disabled window cannot receive input from the user. To change this after a window has
+ /// been created, use the EnableWindow function.
+ ///
+ WS_DISABLED = 0x8000000,
- // 關閉宿主窗體
- mainWinMag.Close();
- }
+ ///
+ /// The window has a border of a style typically used with dialog boxes. A window with this style cannot have a title bar.
+ ///
+ WS_DLGFRAME = 0x400000,
- #endregion
+ ///
+ /// The window is the first control of a group of controls. The group consists of this first control and all controls defined
+ /// after it, up to the next control with the WS_GROUP style. The first control in each group usually has the WS_TABSTOP style so
+ /// that the user can move from group to group. The user can subsequently change the keyboard focus from one control in the group
+ /// to the next control in the group by using the direction keys. You can turn this style on and off to change dialog box
+ /// navigation. To change this style after a window has been created, use the SetWindowLong function.
+ ///
+ WS_GROUP = 0x20000,
- #region 窗口截图
+ /// The window has a horizontal scroll bar.
+ WS_HSCROLL = 0x100000,
- [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
- static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
- public static IntPtr GetClassLongPtr(IntPtr hWnd, int nIndex)
- {
- if (IntPtr.Size > 4)
- return GetClassLongPtr64(hWnd, nIndex);
- else
- return new IntPtr(GetClassLongPtr32(hWnd, nIndex));
- }
- [DllImport("user32.dll", EntryPoint = "GetClassLong")]
- public static extern uint GetClassLongPtr32(IntPtr hWnd, int nIndex);
+ /// The window is initially maximized.
+ WS_MAXIMIZE = 0x1000000,
+
+ ///
+ /// The window has a maximize button. Cannot be combined with the WS_EX_CONTEXTHELP style. The WS_SYSMENU style must also be specified.
+ ///
+ WS_MAXIMIZEBOX = 0x10000,
+
+ /// The window is initially minimized.
+ WS_MINIMIZE = 0x20000000,
+
+ ///
+ /// The window has a minimize button. Cannot be combined with the WS_EX_CONTEXTHELP style. The WS_SYSMENU style must also be specified.
+ ///
+ WS_MINIMIZEBOX = 0x20000,
+
+ /// The window is an overlapped window. An overlapped window has a title bar and a border.
+ WS_OVERLAPPED = 0x0,
+
+ /// The window is an overlapped window.
+ WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
+
+ /// The window is a pop-up window. This style cannot be used with the WS_CHILD style.
+ WS_POPUP = 0x80000000u,
+
+ ///
+ /// The window is a pop-up window. The WS_CAPTION and WS_POPUPWINDOW styles must be combined to make the window menu visible.
+ ///
+ WS_POPUPWINDOW = WS_POPUP | WS_BORDER | WS_SYSMENU,
+
+ /// The window has a sizing border.
+ WS_THICKFRAME = 0x40000,
+
+ /// The window has a window menu on its title bar. The WS_CAPTION style must also be specified.
+ WS_SYSMENU = 0x80000,
+
+ ///
+ /// The window is a control that can receive the keyboard focus when the user presses the TAB key. Pressing the TAB key changes
+ /// the keyboard focus to the next control with the WS_TABSTOP style. You can turn this style on and off to change dialog box
+ /// navigation. To change this style after a window has been created, use the SetWindowLong function. For user-created windows
+ /// and modeless dialogs to work with tab stops, alter the message loop to call the IsDialogMessage function.
+ ///
+ WS_TABSTOP = 0x10000,
+
+ ///
+ /// The window is initially visible. This style can be turned on and off by using the ShowWindow or SetWindowPos function.
+ ///
+ WS_VISIBLE = 0x10000000,
+
+ /// The window has a vertical scroll bar.
+ WS_VSCROLL = 0x200000,
+
+ ///
+ /// The window is an overlapped window. An overlapped window has a title bar and a border. Same as the WS_OVERLAPPED style.
+ ///
+ WS_TILED = WS_OVERLAPPED,
+
+ /// The window is initially minimized. Same as the WS_MINIMIZE style.
+ WS_ICONIC = WS_MINIMIZE,
+
+ /// The window has a sizing border. Same as the WS_THICKFRAME style.
+ WS_SIZEBOX = WS_THICKFRAME,
+
+ /// The window is an overlapped window. Same as the WS_OVERLAPPEDWINDOW style.
+ WS_TILEDWINDOW = WS_OVERLAPPEDWINDOW,
+
+ /// Same as the WS_CHILD style.
+ WS_CHILDWINDOW = WS_CHILD,
+ }
+
+ public enum WindowStylesEx : uint
+ {
+ /// Specifies a window that accepts drag-drop files.
+ WS_EX_ACCEPTFILES = 0x00000010,
+
+ /// Forces a top-level window onto the taskbar when the window is visible.
+ WS_EX_APPWINDOW = 0x00040000,
+
+ /// Specifies a window that has a border with a sunken edge.
+ WS_EX_CLIENTEDGE = 0x00000200,
+
+ ///
+ /// Specifies a window that paints all descendants in bottom-to-top painting order using double-buffering. This cannot be used if
+ /// the window has a class style of either CS_OWNDC or CS_CLASSDC. This style is not supported in Windows 2000.
+ ///
+ ///
+ /// With WS_EX_COMPOSITED set, all descendants of a window get bottom-to-top painting order using double-buffering. Bottom-to-top
+ /// painting order allows a descendent window to have translucency (alpha) and transparency (color-key) effects, but only if the
+ /// descendent window also has the WS_EX_TRANSPARENT bit set. Double-buffering allows the window and its descendents to be
+ /// painted without flicker.
+ ///
+ WS_EX_COMPOSITED = 0x02000000,
+
+ ///
+ /// Specifies a window that includes a question mark in the title bar. When the user clicks the question mark, the cursor changes
+ /// to a question mark with a pointer. If the user then clicks a child window, the child receives a WM_HELP message. The child
+ /// window should pass the message to the parent window procedure, which should call the WinHelp function using the HELP_WM_HELP
+ /// command. The Help application displays a pop-up window that typically contains help for the child window. WS_EX_CONTEXTHELP
+ /// cannot be used with the WS_MAXIMIZEBOX or WS_MINIMIZEBOX styles.
+ ///
+ WS_EX_CONTEXTHELP = 0x00000400,
+
+ ///
+ /// Specifies a window which contains child windows that should take part in dialog box navigation. If this style is specified,
+ /// the dialog manager recurses into children of this window when performing navigation operations such as handling the TAB key,
+ /// an arrow key, or a keyboard mnemonic.
+ ///
+ WS_EX_CONTROLPARENT = 0x00010000,
+
+ /// Specifies a window that has a double border.
+ WS_EX_DLGMODALFRAME = 0x00000001,
+
+ ///
+ /// Specifies a window that is a layered window. This cannot be used for child windows or if the window has a class style of
+ /// either CS_OWNDC or CS_CLASSDC.
+ ///
+ WS_EX_LAYERED = 0x00080000,
+
+ ///
+ /// Specifies a window with the horizontal origin on the right edge. Increasing horizontal values advance to the left. The shell
+ /// language must support reading-order alignment for this to take effect.
+ ///
+ WS_EX_LAYOUTRTL = 0x00400000,
+
+ /// Specifies a window that has generic left-aligned properties. This is the default.
+ WS_EX_LEFT = 0x00000000,
+
+ ///
+ /// Specifies a window with the vertical scroll bar (if present) to the left of the client area. The shell language must support
+ /// reading-order alignment for this to take effect.
+ ///
+ WS_EX_LEFTSCROLLBAR = 0x00004000,
+
+ /// Specifies a window that displays text using left-to-right reading-order properties. This is the default.
+ WS_EX_LTRREADING = 0x00000000,
+
+ /// Specifies a multiple-document interface (MDI) child window.
+ WS_EX_MDICHILD = 0x00000040,
+
+ ///
+ /// Specifies a top-level window created with this style does not become the foreground window when the user clicks it. The
+ /// system does not bring this window to the foreground when the user minimizes or closes the foreground window. The window does
+ /// not appear on the taskbar by default. To force the window to appear on the taskbar, use the WS_EX_APPWINDOW style. To
+ /// activate the window, use the SetActiveWindow or SetForegroundWindow function.
+ ///
+ WS_EX_NOACTIVATE = 0x08000000,
+
+ /// Specifies a window which does not pass its window layout to its child windows.
+ WS_EX_NOINHERITLAYOUT = 0x00100000,
+
+ ///
+ /// Specifies that a child window created with this style does not send the WM_PARENTNOTIFY message to its parent window when it
+ /// is created or destroyed.
+ ///
+ WS_EX_NOPARENTNOTIFY = 0x00000004,
+
+ ///
+ /// The window does not render to a redirection surface. This is for windows that do not have visible content or that use
+ /// mechanisms other than surfaces to provide their visual.
+ ///
+ WS_EX_NOREDIRECTIONBITMAP = 0x00200000,
+
+ /// Specifies an overlapped window.
+ WS_EX_OVERLAPPEDWINDOW = WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE,
+
+ /// Specifies a palette window, which is a modeless dialog box that presents an array of commands.
+ WS_EX_PALETTEWINDOW = WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST,
+
+ ///
+ /// Specifies a window that has generic "right-aligned" properties. This depends on the window class. The shell language must
+ /// support reading-order alignment for this to take effect. Using the WS_EX_RIGHT style has the same effect as using the
+ /// SS_RIGHT (static), ES_RIGHT (edit), and BS_RIGHT/BS_RIGHTBUTTON (button) control styles.
+ ///
+ WS_EX_RIGHT = 0x00001000,
+
+ /// Specifies a window with the vertical scroll bar (if present) to the right of the client area. This is the default.
+ WS_EX_RIGHTSCROLLBAR = 0x00000000,
+
+ ///
+ /// Specifies a window that displays text using right-to-left reading-order properties. The shell language must support
+ /// reading-order alignment for this to take effect.
+ ///
+ WS_EX_RTLREADING = 0x00002000,
+
+ ///
+ /// Specifies a window with a three-dimensional border style intended to be used for items that do not accept user input.
+ ///
+ WS_EX_STATICEDGE = 0x00020000,
+
+ ///
+ /// Specifies a window that is intended to be used as a floating toolbar. A tool window has a title bar that is shorter than a
+ /// normal title bar, and the window title is drawn using a smaller font. A tool window does not appear in the taskbar or in the
+ /// dialog that appears when the user presses ALT+TAB. If a tool window has a system menu, its icon is not displayed on the title
+ /// bar. However, you can display the system menu by right-clicking or by typing ALT+SPACE.
+ ///
+ WS_EX_TOOLWINDOW = 0x00000080,
+
+ ///
+ /// Specifies a window that should be placed above all non-topmost windows and should stay above them, even when the window is
+ /// deactivated. To add or remove this style, use the SetWindowPos function.
+ ///
+ WS_EX_TOPMOST = 0x00000008,
+
+ ///
+ /// Specifies a window that should not be painted until siblings beneath the window (that were created by the same thread) have
+ /// been painted. The window appears transparent because the bits of underlying sibling windows have already been painted. To
+ /// achieve transparency without these restrictions, use the SetWindowRgn function.
+ ///
+ WS_EX_TRANSPARENT = 0x00000020,
+
+ /// Specifies a window that has a border with a raised edge.
+ WS_EX_WINDOWEDGE = 0x00000100,
+ }
+
+ public void SaveScreenshotToDesktopByMagnificationAPI(bool isExcludeMode, HWND[] hwndsList, Action callbackAction) {
+
+ if (OSVersion.GetOperatingSystem() < OperatingSystem.Windows8 && OSVersion.GetOperatingSystem() > OperatingSystem.Windows10) return;
+ if (!Magnification.MagInitialize()) return;
+
+ // 創建宿主窗體
+ //var mainWinMag = new Window();
+ //mainWinMag.WindowState = WindowState.Maximized;
+ //mainWinMag.WindowStyle = WindowStyle.None;
+ //mainWinMag.ResizeMode = ResizeMode.NoResize;
+ //mainWinMag.Background = new SolidColorBrush(Colors.Transparent);
+ //mainWinMag.AllowsTransparency = true;
+ //mainWinMag.Show();
+
+ var mainWin = CreateWindowEx((uint)WindowStylesEx.WS_EX_TOPMOST | (uint)WindowStylesEx.WS_EX_LAYERED, "ICCMagnificationHostWinClass",
+ "ICCMagnificationHostWin",
+ (uint)WindowStyles.WS_SIZEBOX | (uint)WindowStyles.WS_SYSMENU | (uint)WindowStyles.WS_CLIPCHILDREN | (uint)WindowStyles.WS_CAPTION | (uint)WindowStyles.WS_MAXIMIZEBOX, 0, 0,
+ System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width,
+ System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero,
+ IntPtr.Zero);
+
+ Trace.WriteLine(mainWin);
+
+ //SetWindowPos(handle, new IntPtr(1), 0, 0, System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width,
+ // System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height, 0x0080); // SWP_HIDEWINDOW
+ //SetWindowLongPtr(handle, -20, new IntPtr((int)GetWindowLongPtr(handle, -20) | 0x00080000));
+ //SetLayeredWindowAttributes(handle,0, 255, (byte)0x2);
+ SetLayeredWindowAttributes(mainWin,0, 255, (byte)0x2);
+
+ // 創建放大鏡窗體(使用Win32方法)
+ var hwndMag = CreateWindowEx(0,"Magnifier", "ICCMagnifierWindow", (uint)WindowStyles.WS_CHILD | (uint)WindowStyles.WS_VISIBLE, 0, 0,
+ System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width,
+ System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height, mainWin, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
+
+ Trace.WriteLine(hwndMag);
+
+ // 過濾窗口
+ var hwnds = new List { new HWND(hwndMag) };
+ hwnds.AddRange(hwndsList);
+ if (!Magnification.MagSetWindowFilterList(new HWND(hwndMag),
+ isExcludeMode ? Magnification.MW_FILTERMODE.MW_FILTERMODE_EXCLUDE
+ : Magnification.MW_FILTERMODE.MW_FILTERMODE_INCLUDE, isExcludeMode ? hwnds.Count : hwndsList.Length, hwnds.ToArray())) return;
+
+ // 保存數據
+ // 不使用Callback,因為該方法已經被廢棄了
+ //if (!Magnification.MagSetImageScalingCallback(new HWND(hwndMag),
+ // (hwnd, srcdata, srcheader, destdata, destheader, unclipped, clipped, dirty) => {
+ // Bitmap bm = new Bitmap((int)srcheader.width, (int)srcheader.height, (int)srcheader.width * 4,
+ // PixelFormat.Format32bppRgb, srcdata);
+ // callbackAction(bm);
+ // return true;
+ // })) return;
+
+ // 設置窗口Source
+ if (!Magnification.MagSetWindowSource(new HWND(hwndMag),
+ new RECT(0, 0, System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width,
+ System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height))) return;
+
+
+ RECT rect;
+ GetWindowRect(hwndMag, out rect);
+ Bitmap bmp = new Bitmap(rect.Width, rect.Height);
+ Graphics memoryGraphics = Graphics.FromImage(bmp);
+ IntPtr hdc = memoryGraphics.GetHdc();
+ Trace.WriteLine("213423234234234234");
+ Trace.WriteLine(PrintWindow(hwndMag, hdc, 2));
+ Trace.WriteLine("2323232323321111111111111111111111");
+
+
+ // 關閉宿主窗體
+ if (!Magnification.MagUninitialize()) return;
+ DestroyWindow(mainWin);
+ }
+
+ #endregion
+
+ #region 窗口截图(復刻Powerpoint)
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
+ static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
+ public static IntPtr GetClassLongPtr(IntPtr hWnd, int nIndex)
+ {
+ if (IntPtr.Size > 4)
+ return GetClassLongPtr64(hWnd, nIndex);
+ else
+ return new IntPtr(GetClassLongPtr32(hWnd, nIndex));
+ }
+ [DllImport("user32.dll", EntryPoint = "GetClassLong")]
+ public static extern uint GetClassLongPtr32(IntPtr hWnd, int nIndex);
- [DllImport("user32.dll", EntryPoint = "GetClassLongPtr")]
- public static extern IntPtr GetClassLongPtr64(IntPtr hWnd, int nIndex);
- [DllImport("user32.dll", EntryPoint = "EnumDesktopWindows",
- ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = true)]
- public static extern bool EnumDesktopWindows(IntPtr hDesktop, Delegate lpEnumCallbackFunction, IntPtr lParam);
- [DllImport("user32.dll")]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool IsWindowVisible(IntPtr hWnd);
- [DllImport("user32.dll", EntryPoint = "GetWindowText",
- ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = true)]
- public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpWindowText, int nMaxCount);
- [DllImport("user32.dll", SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- static extern bool PrintWindow(IntPtr hwnd, IntPtr hDC, uint nFlags);
- [DllImport("user32.dll")]
- private static extern bool GetWindowRect(IntPtr handle, out RECT rect);
- [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
- static extern int GetWindowTextLength(IntPtr hWnd);
- [DllImport("user32.dll")]
- [return: MarshalAs(UnmanagedType.Bool)]
- static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);
+ [DllImport("user32.dll", EntryPoint = "GetClassLongPtr")]
+ public static extern IntPtr GetClassLongPtr64(IntPtr hWnd, int nIndex);
+ [DllImport("user32.dll", EntryPoint = "EnumDesktopWindows",
+ ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = true)]
+ public static extern bool EnumDesktopWindows(IntPtr hDesktop, Delegate lpEnumCallbackFunction, IntPtr lParam);
+ [DllImport("user32.dll")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool IsWindowVisible(IntPtr hWnd);
+ [DllImport("user32.dll", EntryPoint = "GetWindowText",
+ ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = true)]
+ public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpWindowText, int nMaxCount);
+ [DllImport("user32.dll", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ static extern bool PrintWindow(IntPtr hwnd, IntPtr hDC, uint nFlags);
+ [DllImport("user32.dll")]
+ private static extern bool GetWindowRect(IntPtr handle, out RECT rect);
+ [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
+ static extern int GetWindowTextLength(IntPtr hWnd);
+ [DllImport("user32.dll", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);
+ [DllImport("user32.dll", CharSet=CharSet.Unicode)]
+ public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string lclassName, string windowTitle);
+ [DllImport("user32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
+ public static extern IntPtr GetShellWindow();
+ [DllImport("dwmapi.dll")]
+ static extern int DwmGetWindowAttribute(IntPtr hwnd, int dwAttribute, out bool pvAttribute, int cbAttribute);
- public Icon GetAppIcon(IntPtr hwnd) {
- IntPtr iconHandle = SendMessage(hwnd,0x7F,2,0);
- if(iconHandle == IntPtr.Zero)
- iconHandle = SendMessage(hwnd,0x7F,0,0);
- if(iconHandle == IntPtr.Zero)
- iconHandle = SendMessage(hwnd,0x7F,1,0);
- if (iconHandle == IntPtr.Zero)
- iconHandle = GetClassLongPtr(hwnd, -14);
- if (iconHandle == IntPtr.Zero)
- iconHandle = GetClassLongPtr(hwnd, -34);
- if(iconHandle == IntPtr.Zero)
- return null;
- Icon icn = System.Drawing.Icon.FromHandle(iconHandle);
- return icn;
- }
+ public Icon GetAppIcon(IntPtr hwnd) {
+ IntPtr iconHandle = SendMessage(hwnd,0x7F,2,0);
+ if(iconHandle == IntPtr.Zero)
+ iconHandle = SendMessage(hwnd,0x7F,0,0);
+ if(iconHandle == IntPtr.Zero)
+ iconHandle = SendMessage(hwnd,0x7F,1,0);
+ if (iconHandle == IntPtr.Zero)
+ iconHandle = GetClassLongPtr(hwnd, -14);
+ if (iconHandle == IntPtr.Zero)
+ iconHandle = GetClassLongPtr(hwnd, -34);
+ if(iconHandle == IntPtr.Zero)
+ return null;
+ Icon icn = System.Drawing.Icon.FromHandle(iconHandle);
+ return icn;
+ }
- public struct WindowInformation {
- public string Title;
- public Bitmap WindowBitmap;
- public Icon AppIcon;
- public bool IsVisible;
- public int Width;
- public int Height;
- public RECT Rect;
- public WINDOWPLACEMENT Placement;
- }
+ public struct WindowInformation {
+ public string Title { get; set; }
+ public Bitmap WindowBitmap { get; set; }
+ public Icon AppIcon { get; set; }
+ public bool IsVisible { get; set; }
+ public int Width { get; set; }
+ public int Height { get; set; }
+ public RECT Rect { get; set; }
+ public WINDOWPLACEMENT Placement { get; set; }
+ public HWND hwnd { get; set; }
+ }
- public struct WINDOWPLACEMENT {
- public int length;
- public int flags;
- public int showCmd;
- public System.Drawing.Point ptMinPosition;
- public System.Drawing.Point ptMaxPosition;
- public System.Drawing.Rectangle rcNormalPosition;
- }
+ public struct WINDOWPLACEMENT {
+ public int length;
+ public int flags;
+ public int showCmd;
+ public System.Drawing.Point ptMinPosition;
+ public System.Drawing.Point ptMaxPosition;
+ public System.Drawing.Rectangle rcNormalPosition;
+ public static WINDOWPLACEMENT Default {
+ get {
+ WINDOWPLACEMENT result = new WINDOWPLACEMENT();
+ result.length = Marshal.SizeOf( result );
+ return result;
+ }
+ }
+ }
- public delegate bool EnumDesktopWindowsDelegate(IntPtr hWnd, int lParam);
+ public delegate bool EnumDesktopWindowsDelegate(IntPtr hWnd, int lParam);
- public WindowInformation[] GetAllWindows() {
- var windows = new List();
- if (!EnumDesktopWindows(IntPtr.Zero, new EnumDesktopWindowsDelegate((hwnd, param) => {
- var isvisible = IsWindowVisible(hwnd);
- if (!isvisible) return true;
- var icon = GetAppIcon(hwnd);
- var length = GetWindowTextLength(hwnd) + 1;
- var title = new StringBuilder(length);
- GetWindowText(hwnd, title, length);
- if (title.ToString().Length == 0) return true;
- RECT rect;
- WINDOWPLACEMENT placement = new WINDOWPLACEMENT();
- GetWindowPlacement(hwnd, ref placement);
- if (placement.showCmd == 2) return true;
- GetWindowRect(hwnd, out rect);
- var w = rect.Width;
- var h = rect.Height;
- if (w == 0 || h == 0) return true;
- Bitmap bmp = new Bitmap(rect.Width, rect.Height);
- Graphics memoryGraphics = Graphics.FromImage(bmp);
- IntPtr hdc = memoryGraphics.GetHdc();
- PrintWindow(hwnd, hdc, 2);
- windows.Add(new WindowInformation() {
- AppIcon = icon,
- Title = title.ToString(),
- IsVisible = isvisible,
- WindowBitmap = bmp,
- Width = w,
- Height = h,
- Rect = rect,
- Placement = placement,
- });
- memoryGraphics.ReleaseHdc(hdc);
- return true;
- }),
- IntPtr.Zero)) return new WindowInformation[]{};
- return windows.ToArray();
- }
+ public WindowInformation[] GetAllWindows(HWND[] excludedHwnds) {
+ var windows = new List();
+ IntPtr hShellWnd = GetShellWindow();
+ IntPtr hDefView = FindWindowEx(hShellWnd, IntPtr.Zero, "SHELLDLL_DefView", null);
+ IntPtr folderView = FindWindowEx(hDefView, IntPtr.Zero, "SysListView32", null);
+ IntPtr taskBar = FindWindowEx(IntPtr.Zero, IntPtr.Zero, "Shell_TrayWnd", null);
+ var excluded = new List() {
+ new HWND(hShellWnd), new HWND(hDefView), new HWND(folderView), new HWND(taskBar)
+ };
+ var excludedWindowTitle = new string[] {
+ "NVIDIA GeForce Overlay"
+ };
+ excluded.AddRange(excludedHwnds);
+ if (!EnumDesktopWindows(IntPtr.Zero, new EnumDesktopWindowsDelegate((hwnd, param) => {
+ if (excluded.Contains(new HWND(hwnd))) return true;
+ var isvisible = IsWindowVisible(hwnd);
+ if (!isvisible) return true;
+ var windowLong = (int)GetWindowLongPtr(hwnd, -20);
+ if ((windowLong & 0x00000080L) != 0) return true;
+ DwmGetWindowAttribute(hwnd, 14, out bool isCloacked, Marshal.SizeOf(typeof(bool)));
+ if (isCloacked) return true;
+ var icon = GetAppIcon(hwnd);
+ var length = GetWindowTextLength(hwnd) + 1;
+ var title = new StringBuilder(length);
+ GetWindowText(hwnd, title, length);
+ if (title.ToString().Length == 0) return true;
+ // 這裡懶得做 Alt Tab窗口的校驗了,直接窗體標題黑名單
+ if (excludedWindowTitle.Contains(title.ToString())) return true;
+ RECT rect;
+ WINDOWPLACEMENT placement = new WINDOWPLACEMENT();
+ GetWindowPlacement(hwnd, ref placement);
+ if (placement.showCmd == 2) return true;
+ GetWindowRect(hwnd, out rect);
+ var w = rect.Width;
+ var h = rect.Height;
+ if (w == 0 || h == 0) return true;
+ Bitmap bmp = new Bitmap(rect.Width, rect.Height);
+ Graphics memoryGraphics = Graphics.FromImage(bmp);
+ IntPtr hdc = memoryGraphics.GetHdc();
+ PrintWindow(hwnd, hdc, 2);
+ windows.Add(new WindowInformation() {
+ AppIcon = icon,
+ Title = title.ToString(),
+ IsVisible = isvisible,
+ WindowBitmap = bmp,
+ Width = w,
+ Height = h,
+ Rect = rect,
+ Placement = placement,
- #endregion
+ });
+ memoryGraphics.ReleaseHdc(hdc);
+ return true;
+ }),
+ IntPtr.Zero)) return new WindowInformation[]{};
+ return windows.ToArray();
+ }
- private void SaveScreenShotToDesktop() {
- var bitmap = GetScreenshotBitmap();
- string savePath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
- bitmap.Save(savePath + @"\" + DateTime.Now.ToString("u").Replace(':', '-') + ".png", ImageFormat.Png);
- ShowNewToast("截图成功保存至【桌面" + @"\" + DateTime.Now.ToString("u").Replace(':', '-') + ".png】", MW_Toast.ToastType.Success, 3000);
- if (Settings.Automation.IsAutoSaveStrokesAtScreenshot) SaveInkCanvasStrokes(false, false);
- }
+ #endregion
- private void SavePPTScreenshot(string fileName)
- {
- var bitmap = GetScreenshotBitmap();
- string savePath = Settings.Automation.AutoSavedStrokesLocation + @"\Auto Saved - PPT Screenshots";
- if (Settings.Automation.IsSaveScreenshotsInDateFolders)
- {
- savePath += @"\" + DateTime.Now.ToString("yyyy-MM-dd");
- }
- if (fileName == null) fileName = DateTime.Now.ToString("u").Replace(":", "-");
- savePath += @"\" + fileName + ".png";
- if (!Directory.Exists(Path.GetDirectoryName(savePath)))
- {
- Directory.CreateDirectory(Path.GetDirectoryName(savePath));
- }
- bitmap.Save(savePath, ImageFormat.Png);
- if (Settings.Automation.IsAutoSaveStrokesAtScreenshot)
- {
- SaveInkCanvasStrokes(false, false);
- }
- }
+ private void SaveScreenShotToDesktop() {
+ var bitmap = GetScreenshotBitmap();
+ string savePath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
+ bitmap.Save(savePath + @"\" + DateTime.Now.ToString("u").Replace(':', '-') + ".png", ImageFormat.Png);
+ ShowNewToast("截图成功保存至【桌面" + @"\" + DateTime.Now.ToString("u").Replace(':', '-') + ".png】", MW_Toast.ToastType.Success, 3000);
+ if (Settings.Automation.IsAutoSaveStrokesAtScreenshot) SaveInkCanvasStrokes(false, false);
+ }
- private Bitmap GetScreenshotBitmap()
- {
- Rectangle rc = System.Windows.Forms.SystemInformation.VirtualScreen;
- var bitmap = new Bitmap(rc.Width, rc.Height, PixelFormat.Format32bppArgb);
- using (Graphics memoryGrahics = Graphics.FromImage(bitmap))
- {
- memoryGrahics.CopyFromScreen(rc.X, rc.Y, 0, 0, rc.Size, CopyPixelOperation.SourceCopy);
- }
- return bitmap;
- }
- }
+ private void SavePPTScreenshot(string fileName)
+ {
+ var bitmap = GetScreenshotBitmap();
+ string savePath = Settings.Automation.AutoSavedStrokesLocation + @"\Auto Saved - PPT Screenshots";
+ if (Settings.Automation.IsSaveScreenshotsInDateFolders)
+ {
+ savePath += @"\" + DateTime.Now.ToString("yyyy-MM-dd");
+ }
+ if (fileName == null) fileName = DateTime.Now.ToString("u").Replace(":", "-");
+ savePath += @"\" + fileName + ".png";
+ if (!Directory.Exists(Path.GetDirectoryName(savePath)))
+ {
+ Directory.CreateDirectory(Path.GetDirectoryName(savePath));
+ }
+ bitmap.Save(savePath, ImageFormat.Png);
+ if (Settings.Automation.IsAutoSaveStrokesAtScreenshot)
+ {
+ SaveInkCanvasStrokes(false, false);
+ }
+ }
+
+ private Bitmap GetScreenshotBitmap()
+ {
+ Rectangle rc = System.Windows.Forms.SystemInformation.VirtualScreen;
+ var bitmap = new Bitmap(rc.Width, rc.Height, PixelFormat.Format32bppArgb);
+ using (Graphics memoryGrahics = Graphics.FromImage(bitmap))
+ {
+ memoryGrahics.CopyFromScreen(rc.X, rc.Y, 0, 0, rc.Size, CopyPixelOperation.SourceCopy);
+ }
+ return bitmap;
+ }
+ }
}
\ No newline at end of file
diff --git a/InkCanvasForClass/Popups/ScreenshotWindow.xaml.cs b/InkCanvasForClass/Popups/ScreenshotWindow.xaml.cs
index d954b4a..9a95788 100644
--- a/InkCanvasForClass/Popups/ScreenshotWindow.xaml.cs
+++ b/InkCanvasForClass/Popups/ScreenshotWindow.xaml.cs
@@ -126,7 +126,7 @@ namespace Ink_Canvas.Popups
}
private void CaptureFullScreen() {
- mainWindow.SaveScreenshotToDesktopByMagnificationAPI(new HWND[] {
+ mainWindow.SaveScreenshotToDesktopByMagnificationAPI(true, new HWND[] {
new WindowInteropHelper(mainWindow).Handle,
new WindowInteropHelper(this).Handle,
}, async bitmap => {
@@ -197,7 +197,9 @@ namespace Ink_Canvas.Popups
UpdateModeIconSelection();
if (selectedMode == 1) {
- _screenshotGridWindow = new WindowScreenshotGridWindow(mainWindow.GetAllWindows());
+ _screenshotGridWindow = new WindowScreenshotGridWindow(mainWindow.GetAllWindows(new HWND[] {
+ new HWND(new WindowInteropHelper(this).Handle), new HWND(new WindowInteropHelper(mainWindow).Handle)
+ }), mainWindow);
_screenshotGridWindow.Show();
} else if (_screenshotGridWindow != null) {
_screenshotGridWindow.Close();
diff --git a/InkCanvasForClass/Popups/WindowScreenshotGridWindow.xaml b/InkCanvasForClass/Popups/WindowScreenshotGridWindow.xaml
index c42377b..bad49b5 100644
--- a/InkCanvasForClass/Popups/WindowScreenshotGridWindow.xaml
+++ b/InkCanvasForClass/Popups/WindowScreenshotGridWindow.xaml
@@ -17,7 +17,7 @@
-
+
diff --git a/InkCanvasForClass/Popups/WindowScreenshotGridWindow.xaml.cs b/InkCanvasForClass/Popups/WindowScreenshotGridWindow.xaml.cs
index 5fc075b..4dfd56d 100644
--- a/InkCanvasForClass/Popups/WindowScreenshotGridWindow.xaml.cs
+++ b/InkCanvasForClass/Popups/WindowScreenshotGridWindow.xaml.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Drawing;
+using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
@@ -15,6 +16,8 @@ using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
+using iNKORE.UI.WPF.Modern.Controls;
+using Vanara.PInvoke;
namespace Ink_Canvas.Popups
{
@@ -43,21 +46,35 @@ namespace Ink_Canvas.Popups
private class Win {
public string Title { get; set; }
public BitmapImage Bitmap { get; set; }
+ public HWND Handle { get; set; }
+ public Bitmap OriginBitmap { get; set; }
}
+ private MainWindow mainWindow;
+
private ObservableCollection _windows = new ObservableCollection();
- public WindowScreenshotGridWindow(MainWindow.WindowInformation[] wins) {
+ public WindowScreenshotGridWindow(MainWindow.WindowInformation[] wins, MainWindow mainWindow) {
InitializeComponent();
_windows.Clear();
WindowsItemControl.ItemsSource = _windows;
foreach (var windowInformation in wins) {
_windows.Add(new Win() {
Title = windowInformation.Title,
- Bitmap = BitmapToImageSource(windowInformation.WindowBitmap)
+ Bitmap = BitmapToImageSource(windowInformation.WindowBitmap),
+ Handle = windowInformation.hwnd,
+ OriginBitmap = windowInformation.WindowBitmap,
});
Trace.WriteLine(windowInformation.Title);
}
+
+ this.mainWindow = mainWindow;
+ }
+
+ private void WindowItem_MouseUp(object sender, MouseButtonEventArgs e) {
+ var item = ((SimpleStackPanel)sender).Tag as Win;
+ string savePath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
+ item.OriginBitmap.Save(savePath + @"\" + DateTime.Now.ToString("u").Replace(':', '-') + ".bmp", ImageFormat.Bmp);
}
}
}