Как рассчитать высоту (ширину) между 2 пикселями на экране?

Меня попросили сделать приложение (желательно на C#), которое может делать что-то вроде этого:

  1. Я запускаю приложение (например, оно активно на моем активном мониторе)
  2. Затем я нажимаю 2 пикселя (не обязательно точно пиксель, эпсилон будет +-3 пикселя)
  3. Программа будет вычислять или показывать внизу высоту (ширину) между ними.

Что-то вроде «positionShower» в простом рисовании, за исключением того, что я выбираю 2 пикселя на весь экран (не имеет значения, находится ли он в активном окне или полностью вне его), но для этого не потребуется запускать какую-либо другую программу в то же самое время. время.

Любая помощь ? Я не мог найти ничего похожего.


person n0win0u    schedule 02.10.2014    source источник
comment
var height = Math.Abs(Point2.Y - Point1.Y); и var width = Math.Abs(Point2.X - Point1.X);   -  person Sani Singh Huttunen    schedule 02.10.2014
comment
@SaniHuttunen мне нужно будет закодировать какой-нибудь обработчик событий для щелчков мыши и реализовать визуализацию моего дисплея? Извините, если это звучит глупо, но я новичок в подобных проблемах.   -  person n0win0u    schedule 02.10.2014
comment
@SpikeX Я пытаюсь понять логику процесса, прежде чем что-то делать, потому что понятия не имею.   -  person n0win0u    schedule 02.10.2014
comment
@n0win0u: Да. Получите события кликов и запишите положение курсора для обоих кликов (Point1 и Point2), затем рассчитайте ширину и высоту.   -  person Sani Singh Huttunen    schedule 02.10.2014
comment
Когда вы говорите «приложение на С#», это Winforms, WPF, веб-приложение и т. д.?   -  person barrick    schedule 02.10.2014


Ответы (2)


Для этого необходимо глобально перехватывать низкоуровневые события мыши, см. LowLevelMouseProc, SetWindowsHookEx и другие функции, которые вы найдете ниже в примере кода.

Чтобы протестировать пример, создайте новый проект Windows Forms и добавьте три метки к основной форме, например:

дизайн формы

И замените код в Form1.cs следующим:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            _proc = HookCallback;

            _hookID = SetHook(_proc);

        }

        // This method is called for each global mouse event
        private IntPtr HookCallback(
            int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode >= 0 &&
                MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
            {
                MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
                if (isFirstClick)
                {
                    firstClickMouseStruct = hookStruct;
                    label1.Text = "First click: " + hookStruct.pt.x + ", " + hookStruct.pt.y;
                }
                else
                {
                    secondClickMouseStruct = hookStruct;
                    label2.Text = "Second click: " + secondClickMouseStruct.pt.x + ", " + secondClickMouseStruct.pt.y;
                    label3.Text = "Height: " + Math.Abs(secondClickMouseStruct.pt.y - firstClickMouseStruct.pt.y)
                        + ", Width: " + Math.Abs(secondClickMouseStruct.pt.x - firstClickMouseStruct.pt.x);
                }
                isFirstClick = !isFirstClick;
            }
            return CallNextHookEx(_hookID, nCode, wParam, lParam);
        }

        private MSLLHOOKSTRUCT firstClickMouseStruct;
        private MSLLHOOKSTRUCT secondClickMouseStruct;
        private bool isFirstClick = true;

        private LowLevelMouseProc _proc = null;
        private IntPtr _hookID = IntPtr.Zero;

        private IntPtr SetHook(LowLevelMouseProc proc)
        {
            using (Process curProcess = Process.GetCurrentProcess())
            using (ProcessModule curModule = curProcess.MainModule)
            {
                return SetWindowsHookEx(WH_MOUSE_LL, proc,
                    GetModuleHandle(curModule.ModuleName), 0);
            }
        }

        private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);

        private const int WH_MOUSE_LL = 14;

        private enum MouseMessages
        {
            WM_LBUTTONDOWN = 0x0201,
            WM_LBUTTONUP = 0x0202,
            WM_MOUSEMOVE = 0x0200,
            WM_MOUSEWHEEL = 0x020A,
            WM_RBUTTONDOWN = 0x0204,
            WM_RBUTTONUP = 0x0205
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct POINT
        {
            public int x;
            public int y;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct MSLLHOOKSTRUCT
        {
            public POINT pt;
            public uint mouseData;
            public uint flags;
            public uint time;
            public IntPtr dwExtraInfo;
        }

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr SetWindowsHookEx(int idHook,
            LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool UnhookWindowsHookEx(IntPtr hhk);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
            IntPtr wParam, IntPtr lParam);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr GetModuleHandle(string lpModuleName);

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            UnhookWindowsHookEx(_hookID);
        }
    }
}

Теперь вы можете щелкнуть левой кнопкой мыши внутри или за пределами формы (на рабочем столе или в других окнах), и приложение перехватит клики, проверит положение мыши и рассчитает высоту и ширину по мере необходимости:

результат

person Alexey    schedule 02.10.2014
comment
кажется, это ничего не делает для меня, я могу нажимать все, что хочу, ничего не происходит. Любой совет ? (этикетки остаются нетронутыми) - person n0win0u; 03.10.2014
comment
исправлено, Form1 не загружал событие самой загрузки. Теперь работает, еще раз спасибо - person n0win0u; 03.10.2014
comment
Возможно ли заставить окна не изменять mouseOverEffects, пока это приложение видно/включено? Я имею в виду, что я запускаю приложение, я могу щелкнуть дважды, но курсор везде остается по умолчанию (не только в форме). Я думал о наложении (с непрозрачностью 0), чтобы вызвать некоторый эффект onMouseOver, но пользователь не сможет, например: переключать вкладки в браузере. (форму я сделал самую верхнюю). Это возможно? Кроме того, есть ли способ создать небольшое увеличительное стекло вокруг курсора, сделав его по умолчанию. Но в приоритете однозначно курсор по умолчанию. ты - person n0win0u; 03.10.2014
comment
Я НЕ уверен, что переопределять системный курсор - это хорошая идея, лучше подумайте о наложении. В противном случае, пожалуйста, проверьте этот пост, возможно, он поможет: ссылка - person Alexey; 03.10.2014

person    schedule
comment
Это будет работать только в рамках формы заявки. Первоначальный вопрос касается всего рабочего стола, независимо от того, есть какое-либо активное окно или нет. - person Alexey; 02.10.2014
comment
нет, в вопросе четко указано, что у вас может быть полноэкранное активное окно. (неважно, находится ли он в активном окне или полностью вне его) - person boomoto; 02.10.2014
comment
...или совсем из него - person Alexey; 02.10.2014
comment
Я понял это, поскольку ему все равно, должны ли окна быть активными или нет. - person boomoto; 02.10.2014
comment
ваше решение лучше, просто может быть излишним :) - person boomoto; 02.10.2014
comment
ребята, спасибо вам обоим за помощь, @Alexey был прав, он понял именно то, что я имел в виду, но я думаю, что я также реализую ваше решение бумото, но по другой задаче, которую мне поручили. Мне еще многому предстоит научиться, особенно обработке событий. Еще раз спасибо. - person n0win0u; 02.10.2014