Adding clicking on color in windows for picker
This commit is contained in:
parent
e192bc8ede
commit
65423aa813
3 changed files with 212 additions and 26 deletions
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (c) 2018, John Lewin
|
||||
Copyright (c) 2023, John Lewin, Lars Brubaker
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -29,7 +29,6 @@ either expressed or implied, of the FreeBSD Project.
|
|||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection.Metadata.Ecma335;
|
||||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.Image;
|
||||
using MatterHackers.Agg.Platform;
|
||||
|
|
@ -42,7 +41,7 @@ using MatterHackers.MatterControl.SlicerConfiguration;
|
|||
|
||||
namespace MatterHackers.MatterControl.PartPreviewWindow
|
||||
{
|
||||
public class ItemColorButton : PopupButton
|
||||
public class ItemColorButton : PopupButton
|
||||
{
|
||||
private ColorButton colorButton;
|
||||
private GuiWidget popupContent;
|
||||
|
|
@ -259,19 +258,27 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
|
|||
picker.SetColorWithoutChangeEvent(Color.White);
|
||||
};
|
||||
|
||||
if (getPickedColor != null)
|
||||
{
|
||||
var selectButton = rightContent.AddChild(new ThemedTextIconButton("Select".Localize(), StaticData.Instance.LoadIcon("eye_dropper.png", 16, 16).GrayToColor(theme.TextColor), theme)
|
||||
{
|
||||
Margin = 0,
|
||||
HAnchor = HAnchor.Fit | HAnchor.Left,
|
||||
VAnchor = VAnchor.Absolute
|
||||
});
|
||||
var selectButton = rightContent.AddChild(new ThemedTextIconButton("Select".Localize(), StaticData.Instance.LoadIcon("eye_dropper.png", 16, 16).GrayToColor(theme.TextColor), theme)
|
||||
{
|
||||
Margin = 0,
|
||||
HAnchor = HAnchor.Fit | HAnchor.Left,
|
||||
VAnchor = VAnchor.Absolute
|
||||
});
|
||||
|
||||
selectButton.Click += (s, e) =>
|
||||
// If there is a custom function to get a color, use it.
|
||||
if (getPickedColor == null)
|
||||
{
|
||||
// get a color picker for all of windows
|
||||
getPickedColor = new WindowsColorOnMouseDown().GetColor;
|
||||
}
|
||||
|
||||
selectButton.Click += (s, e) =>
|
||||
{
|
||||
getPickedColor((color) =>
|
||||
{
|
||||
getPickedColor((color) =>
|
||||
if (color.Alpha0To255 > 0)
|
||||
{
|
||||
// only run this code if we did get a color (the timeout will result in no color)
|
||||
update?.Invoke(color);
|
||||
if (transparent?.Checked == true)
|
||||
{
|
||||
|
|
@ -281,20 +288,20 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
|
|||
{
|
||||
picker.SelectedColor = color;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
if (selectButton.Width < resetButton.Width)
|
||||
{
|
||||
selectButton.HAnchor = HAnchor.Stretch;
|
||||
}
|
||||
else
|
||||
{
|
||||
resetButton.HAnchor = HAnchor.Stretch;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return content;
|
||||
if (selectButton.Width < resetButton.Width)
|
||||
{
|
||||
selectButton.HAnchor = HAnchor.Stretch;
|
||||
}
|
||||
else
|
||||
{
|
||||
resetButton.HAnchor = HAnchor.Stretch;
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
public override void OnLoad(EventArgs args)
|
||||
|
|
|
|||
|
|
@ -289,6 +289,12 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
|
|||
progress?.Invoke((UiThread.CurrentTimerMs - time) / 1000.0 / durationSeconds, null);
|
||||
}
|
||||
|
||||
// If the reason we exited the loop was due to a cancellation request, return no color
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
setColor?.Invoke(Color.Transparent);
|
||||
}
|
||||
|
||||
scene.SelectionChanged -= SelectionChanged;
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
|
|
|
|||
173
MatterControlLib/PartPreviewWindow/WindowsColorOnMouseDown.cs
Normal file
173
MatterControlLib/PartPreviewWindow/WindowsColorOnMouseDown.cs
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
Copyright (c) 2023, Lars Brubaker
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
The views and conclusions contained in the software and documentation are those
|
||||
of the authors and should not be interpreted as representing official policies,
|
||||
either expressed or implied, of the FreeBSD Project.
|
||||
*/
|
||||
|
||||
using MatterHackers.Agg;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace MatterHackers.MatterControl.PartPreviewWindow
|
||||
{
|
||||
public class WindowsColorOnMouseDown
|
||||
{
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool GetCursorPos(out POINT lpPoint);
|
||||
|
||||
[DllImport("gdi32.dll")]
|
||||
public static extern uint GetPixel(IntPtr hDC, int nXPos, int nYPos);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern IntPtr GetDC(IntPtr hWnd);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct POINT
|
||||
{
|
||||
public int X;
|
||||
public int Y;
|
||||
}
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
static extern IntPtr SetWindowsHookEx(int idHook, MouseProc callback, IntPtr hInstance, uint threadId);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
static extern bool UnhookWindowsHookEx(IntPtr hInstance);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
static extern IntPtr CallNextHookEx(IntPtr idHook, int nCode, int wParam, IntPtr lParam);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
static extern IntPtr LoadLibrary(string lpFileName);
|
||||
|
||||
private delegate IntPtr MouseProc(int nCode, int wParam, IntPtr lParam);
|
||||
|
||||
private const int WH_MOUSE_LL = 14;
|
||||
private static MouseProc mouseProc;
|
||||
private static IntPtr hookId = IntPtr.Zero;
|
||||
|
||||
public WindowsColorOnMouseDown()
|
||||
{
|
||||
}
|
||||
|
||||
private static IntPtr MouseHookCallback(int nCode, int wParam, IntPtr lParam)
|
||||
{
|
||||
if (nCode >= 0 && MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
|
||||
{
|
||||
return (IntPtr)1; // Indicates that we handle the message
|
||||
}
|
||||
|
||||
return CallNextHookEx(hookId, nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
private enum MouseMessages
|
||||
{
|
||||
WM_LBUTTONDOWN = 0x0201
|
||||
}
|
||||
|
||||
public void GetColor(Action<Agg.Color> setColor)
|
||||
{
|
||||
setColor?.Invoke(WaitForClick());
|
||||
}
|
||||
|
||||
public static void SetHook()
|
||||
{
|
||||
mouseProc = MouseHookCallback;
|
||||
using (Process curProcess = Process.GetCurrentProcess())
|
||||
using (ProcessModule curModule = curProcess.MainModule)
|
||||
{
|
||||
hookId = SetWindowsHookEx(WH_MOUSE_LL, mouseProc,
|
||||
LoadLibrary("user32"), 0);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ReleaseHook()
|
||||
{
|
||||
UnhookWindowsHookEx(hookId);
|
||||
}
|
||||
|
||||
public Agg.Color WaitForClick()
|
||||
{
|
||||
var clickWaitHandle = new AutoResetEvent(false);
|
||||
Timer timeoutTimer = null;
|
||||
|
||||
MouseProc clickProc = (nCode, wParam, lParam) =>
|
||||
{
|
||||
if (nCode >= 0 && MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
|
||||
{
|
||||
timeoutTimer?.Dispose();
|
||||
timeoutTimer = null;
|
||||
clickWaitHandle.Set();
|
||||
return (IntPtr)1; // Stop further processing
|
||||
}
|
||||
return CallNextHookEx(hookId, nCode, wParam, lParam);
|
||||
};
|
||||
|
||||
using (Process curProcess = Process.GetCurrentProcess())
|
||||
using (ProcessModule curModule = curProcess.MainModule)
|
||||
{
|
||||
hookId = SetWindowsHookEx(WH_MOUSE_LL, clickProc, LoadLibrary("user32"), 0);
|
||||
}
|
||||
|
||||
// Set a timer to release the hook after 20 seconds
|
||||
timeoutTimer = new Timer(_ =>
|
||||
{
|
||||
ReleaseHook();
|
||||
clickWaitHandle.Set();
|
||||
}, null, 20000, Timeout.Infinite);
|
||||
|
||||
clickWaitHandle.WaitOne();
|
||||
ReleaseHook();
|
||||
|
||||
// Check if the timer has been disposed, indicating a click occurred
|
||||
if (timeoutTimer != null)
|
||||
{
|
||||
timeoutTimer.Dispose();
|
||||
return Agg.Color.Transparent; // or another default value to indicate timeout
|
||||
}
|
||||
|
||||
return GetColorAtCursor();
|
||||
}
|
||||
|
||||
public Agg.Color GetColorAtCursor()
|
||||
{
|
||||
GetCursorPos(out POINT cursor);
|
||||
IntPtr desktopDC = GetDC(IntPtr.Zero);
|
||||
uint color = GetPixel(desktopDC, cursor.X, cursor.Y);
|
||||
ReleaseDC(IntPtr.Zero, desktopDC);
|
||||
|
||||
return new Agg.Color((int)(color & 0x000000FF),
|
||||
(int)(color & 0x0000FF00) >> 8,
|
||||
(int)(color & 0x00FF0000) >> 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue