Форум программистов, компьютерный форум, киберфорум
C# Windows Forms
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.72/74: Рейтинг темы: голосов - 74, средняя оценка - 4.72
27 / 27 / 8
Регистрация: 30.03.2010
Сообщений: 380
Записей в блоге: 1

Скриншот с захватом курсора

01.03.2013, 03:23. Показов 15245. Ответов 51
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Уважаемые знатоки!
Собственно вопросов как сделать скрин - нет. Но есть вопрос, как сделать, чтобы был виден текущий курсор. На форуме находил вариант, что просто взять и наложить картинку курсора по координатам..это сделал, но в итоге если он меняется к примеру на руку, стрелочки или другой... то на скрине всё равно остаётся стандартный курсор.
К примеру создатели скайпа это как то решили в демонстрации экрана..
Надеюсь что есть способ захвата
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
01.03.2013, 03:23
Ответы с готовыми решениями:

Ошибка с динамическим захватом
Задача поставлена так: сформировать двумерный массив из данного одномерного, но размерности двумерного массива спросите у пользователя, а...

StringGrid скроллинг ЗАХВАТОМ
Доброе время! Есть грид со скроллбарами, потому что не помещается вся информация на экран. Как можно реализовать просмотр...

Помогите разобраться с захватом видео
Проблема такова: у меня есть простой ресивер, получающий телевизионный сигнал с параболлической антенны, как я понимаю, сигнал идет...

51
27 / 27 / 8
Регистрация: 30.03.2010
Сообщений: 380
Записей в блоге: 1
03.03.2013, 18:39  [ТС]
Студворк — интернет-сервис помощи студентам
Спасибо..только как получить дескриптор курсора, я так и не понял)..точнее как пользоваться этими функциями..
объясните пожалуйста)
и ещё такой вопрос...это будет работать на всех окнах..в любых приложениях где находится курсор, или только в том, которое указано в функции FindWindow()...?

Добавлено через 1 час 7 минут
вроде понял..дескриптор так
C#
1
IntPtr c = GetCursor();
правильно?..
но как получить ширину и высоту курсора?..как пользоваться GetCursorInfo()
0
979 / 874 / 350
Регистрация: 26.04.2012
Сообщений: 2,647
03.03.2013, 19:07
Короче проще самому написать Погуглив 30 минут, я нашел как это делается во всех подробностях, вот рабочий код:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
        [DllImport("user32.dll")]
        static extern bool GetIconInfo(IntPtr hIcon, out ICONINFO piconinfo);
 
        [StructLayout(LayoutKind.Sequential)]
        struct ICONINFO
        {
            public bool fIcon;
            public Int32 xHotspot;
            public Int32 yHotspot;
            public IntPtr hbmMask;
            public IntPtr hbmColor;
        }
 
        [DllImport("user32.dll")]
        static extern IntPtr GetCursor();
 
        [StructLayout(LayoutKind.Sequential)]
        struct POINT
        {
            public Int32 x;
            public Int32 y;
        }
 
        [StructLayout(LayoutKind.Sequential)]
        struct CURSORINFO
        {
            public Int32 cbSize;
            public Int32 flags;
            public IntPtr hCursor;
            public POINT ptScreenPos;
        }
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool GetCursorPos(out Point lpPoint);
 
        [DllImport("user32.dll")]
        static extern bool GetCursorInfo(out CURSORINFO pci);
 
 
 
        [DllImport("gdi32.dll", EntryPoint = "DeleteObject")]
        static extern IntPtr DeleteObject(IntPtr hDc);
 
        [DllImport("user32.dll")]
        public static extern IntPtr GetDC(IntPtr hwnd);
        [DllImport("user32.dll", EntryPoint = "ReleaseDC")]
        public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);
        public static IntPtr win3;
        [DllImport("gdi32.dll")]
        private static extern int BitBlt(
          IntPtr hdcDest, // handle to destination DC
          int nXDest,  // x-coord of destination upper-left corner
          int nYDest,  // y-coord of destination upper-left corner
          int nWidth,  // width of destination rectangle
          int nHeight, // height of destination rectangle
          IntPtr hdcSrc,  // handle to source DC
          int nXSrc,   // x-coordinate of source upper-left corner
          int nYSrc,   // y-coordinate of source upper-left corner
          UInt32 dwRop    // raster operation code
        );
        [DllImport("gdi32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool GetWindowRect(HandleRef hWnd, out RECT lpRect);
        [StructLayout(LayoutKind.Sequential)]
        private struct RECT
        {
            public int Left;        // x position of upper-left corner
            public int Top;         // y position of upper-left corner
            public int Right;       // x position of lower-right corner
            public int Bottom;      // y position of lower-right corner
        }
        [DllImport("user32.dll")]
        static extern bool DrawIcon(IntPtr hDC, int X, int Y, IntPtr hIcon);
        [DllImport("user32.dll")]
        public static extern IntPtr GetDesktopWindow();
        [DllImport("user32.dll")]
        public static extern IntPtr GetWindowDC(IntPtr hWnd);
        private const Int32 SRCCOPY = 13369376;
 
        private void button1_Click(object sender, EventArgs e)
        {
unsafe{
 CURSORINFO cursorInfo;
 cursorInfo.cbSize = sizeof(CURSORINFO);
if (GetCursorInfo(out cursorInfo))
 {
  ICONINFO inf;
  GetIconInfo(cursorInfo.hCursor,out inf);
  Bitmap eee = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
  Graphics loGraphics1 = Graphics.FromImage(eee);
  IntPtr lnDst1 = loGraphics1.GetHdc();
  Point poin;
  GetCursorPos(out poin);
  IntPtr dd = GetDesktopWindow();
  BitBlt(lnDst1, 0, 0, Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, GetWindowDC(dd), 0, 0, SRCCOPY);
  DrawIcon(lnDst1, poin.X - inf.xHotspot, poin.Y - inf.yHotspot, cursorInfo.hCursor);
  loGraphics1.ReleaseHdc(lnDst1);
  loGraphics1.Flush();
  loGraphics1.Dispose();
  pictureBox1.Image = (Bitmap)eee.Clone();
  pictureBox1.Size = eee.Size;
  }}}
Я с курсором дел не имел, оказалось его извлекают не так, как писали выше, но за 30 минут гугления и 15 минут тестов все проблемы решились
1
27 / 27 / 8
Регистрация: 30.03.2010
Сообщений: 380
Записей в блоге: 1
03.03.2013, 19:28  [ТС]
тут извлекается полностью экран с курсором..а можно ли вытащить только курсор?..
0
979 / 874 / 350
Регистрация: 26.04.2012
Сообщений: 2,647
03.03.2013, 19:34
Эммм.. ну так уберите ту часть кода, которая делает скриншот, просто в первом посте заявлена именно такая задача. Если вы прочитаете код-то увидите, что они извлекаются отдельно, а потом уже накладываются.
0
27 / 27 / 8
Регистрация: 30.03.2010
Сообщений: 380
Записей в блоге: 1
03.03.2013, 19:44  [ТС]
просто задача со скрином у меня была решена изначально...
а вот из за курсора пришлось создать тему.
и если честно не понимаю в каком месте вашего кода делается скрин....(((
0
979 / 874 / 350
Регистрация: 26.04.2012
Сообщений: 2,647
03.03.2013, 19:48
Этот способ быстрее шарповского в разы, да и все равно DC извлекать, так что лучше переделайте.
C#
1
2
IntPtr dd = GetDesktopWindow();
BitBlt(lnDst1, 0, 0, Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, GetWindowDC(dd), 0, 0, SRCCOPY);
Вот тут делается скрин. Вы бы почитали хоть о функциях этих-а то какой интерес копипастить, не понимая смысла?
0
27 / 27 / 8
Регистрация: 30.03.2010
Сообщений: 380
Записей в блоге: 1
03.03.2013, 19:53  [ТС]
Честное слово..читал про них несколько раз на разных сайтах..но никак не могу вникнуть)...
ага..я так и знал что её нужно убрать..
только почему то после этого не все виды курсора видно после удаления BitBlt..к примеру в виде разделителя, который появляется при наведении на текст.
0
979 / 874 / 350
Регистрация: 26.04.2012
Сообщений: 2,647
03.03.2013, 20:08
Кстати да, так не видно. Это по всей видимости не считается иконкой курсора, надо придумывать какой-то костыль. В скайпе и других прогах, где курсор передается, видно его в таком положении? Можно теоретически держать в памяти такую картинку, она же не меняется особо, и пихать, когда курсора не видно. Найду нормальный способ-отпишусь. А с изучением функций по-моему все просто, берешь, копипастишь код, и разбираешься как он работаешь при помощи сайтов и методом тыка, а потом юзаешь как хочешь
0
27 / 27 / 8
Регистрация: 30.03.2010
Сообщений: 380
Записей в блоге: 1
03.03.2013, 20:17  [ТС]
да..в скайпе видно..
у меня ещё один вопрос..
т.к. я делаю не просто отдельный скрин...а всё это по таймеру и непрерывно (как в том же скайпе)..то вылетает исключение..ругается на
C#
1
IntPtr lnDst1 = loGraphics1.GetHdc();
пишет Недопустимый параметр..
при том это происходит спустя несколько секунд после успешной работы
что это может быть?..
0
169 / 132 / 29
Регистрация: 16.02.2013
Сообщений: 867
03.03.2013, 20:20
где то в системе курсор меняется. иконка. вот в эту сторону и нужно копать.
0
979 / 874 / 350
Регистрация: 26.04.2012
Сообщений: 2,647
03.03.2013, 20:23
Да это я ступил, забыл ReleaseDC, сейчас скину код.
0
27 / 27 / 8
Регистрация: 30.03.2010
Сообщений: 380
Записей в блоге: 1
03.03.2013, 20:35  [ТС]
вот это добавить надо?
C#
1
ReleaseDC(dd, lnDst1);
0
979 / 874 / 350
Регистрация: 26.04.2012
Сообщений: 2,647
03.03.2013, 20:41
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
unsafe{
 CURSORINFO cursorInfo;
 cursorInfo.cbSize = sizeof(CURSORINFO);
if (GetCursorInfo(out cursorInfo))
 {
  ICONINFO inf;
  GetIconInfo(cursorInfo.hCursor,out inf);
  Bitmap eee = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
  Graphics loGraphics1 = Graphics.FromImage(eee);
  IntPtr lnDst1 = loGraphics1.GetHdc();
  IntPtr dd = GetDesktopWindow();
  IntPtr hdc = GetWindowDC(dd);
  BitBlt(lnDst1, 0, 0, Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, hdc, 0, 0, SRCCOPY);
  DrawIcon(lnDst1, cursorInfo.ptScreenPos.x - inf.xHotspot, cursorInfo.ptScreenPos.y - inf.yHotspot, cursorInfo.hCursor);
  loGraphics1.ReleaseHdc(lnDst1);
  loGraphics1.Flush();
  loGraphics1.Dispose();
  ReleaseDC(dd, hdc);
  pictureBox1.Image = (Bitmap)eee.Clone();
  pictureBox1.Size = eee.Size;
  }}
Вот так должно работать. Если нет-можно еще поудалять при помощи
C#
1
2
  DeleteObject(inf.hbmColor);
  DeleteObject(inf.hbmMask);
Но тут точно не знаю, вроде должно и так удалиться.

Добавлено через 3 минуты
где то в системе курсор меняется. иконка. вот в эту сторону и нужно копать.
Да вроде я именно то и делаю, что извлекаю иконку из текущего курсора, буду тестить.
0
27 / 27 / 8
Регистрация: 30.03.2010
Сообщений: 380
Записей в блоге: 1
03.03.2013, 20:42  [ТС]
теперь другое исключение
C#
1
Graphics loGraphics1 = Graphics.FromImage(eee);
Недостаточно памяти
Опять же через некоторое время после успешного выполнения...
только не понятно почему, ведь loGraphics1 в конце чиститься...
0
979 / 874 / 350
Регистрация: 26.04.2012
Сообщений: 2,647
03.03.2013, 20:49
Это с
C#
1
2
 DeleteObject(inf.hbmColor);
  DeleteObject(inf.hbmMask);
или без?
0
27 / 27 / 8
Регистрация: 30.03.2010
Сообщений: 380
Записей в блоге: 1
03.03.2013, 21:02  [ТС]
и с этим и без него вылетает
0
979 / 874 / 350
Регистрация: 26.04.2012
Сообщений: 2,647
03.03.2013, 21:21
Нашел кажись в чем дело, сборщик мусора не освобождает память, которую выделили вот тут.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
            unsafe
            {
                CURSORINFO cursorInfo;
                cursorInfo.cbSize = sizeof(CURSORINFO); // тут выделили память
                if (GetCursorInfo(out cursorInfo))
                {
                    Bitmap eee = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
                    ICONINFO inf;
                    GetIconInfo(cursorInfo.hCursor, out inf);
                    Graphics loGraphics1 = Graphics.FromImage(eee);
                    IntPtr lnDst1 = loGraphics1.GetHdc();
                    IntPtr dd = GetDesktopWindow();
                    IntPtr hdc = GetWindowDC(dd);
                    BitBlt(lnDst1, 0, 0, Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, hdc, 0, 0, SRCCOPY);
                    DrawIcon(lnDst1, cursorInfo.ptScreenPos.x - inf.xHotspot, cursorInfo.ptScreenPos.y - inf.yHotspot, cursorInfo.hCursor);
                    loGraphics1.ReleaseHdc(lnDst1);
                    loGraphics1.Flush();
                    loGraphics1.Dispose();
                    ReleaseDC(dd, hdc);
                    pictureBox1.Image = (Bitmap)eee.Clone();
                    pictureBox1.Size = eee.Size;
                    eee.Dispose();
                    GC.Collect(); //заставляем бездельника работать
                }
            }
Так и курсор отображается в любом виде, даже измененный
1
27 / 27 / 8
Регистрация: 30.03.2010
Сообщений: 380
Записей в блоге: 1
03.03.2013, 21:29  [ТС]
Отлично! Огромнейшее спасибо
Только жаль что не виден по прежнему тот самый курсор в виде разделителя на тексте, если удалять весь скрин.
и ещё такой вопрос..чисто для уточнения, по функции BitBlt
получается она копирует изображение из hdc в lnDst1, а потом с помощью ReleaseHdc(lnDst1) мы помещаем это всё в графикс..правильно я понял?
0
169 / 132 / 29
Регистрация: 16.02.2013
Сообщений: 867
03.03.2013, 21:38
EvilFromHell,
C#
1
//заставляем бездельника работать

Из МСДН:

IDisposible:
Осиновое назначение этого интерфейса заключается в высвобождении неуправляемых ресурсов. Сборщик мусора автоматически высвобождает память, выделенную для управляемого объекта, если этот объект уже не используется. Однако он не может предсказать момент выполнения сбора мусора. Кроме того, у сборщика мусора нет сведений о неуправляемых ресурсах, таких как дескрипторы окон, или открытые файлы и потоки.

Метод Dispose этого интерфейса используется вместе со сборщиком мусора для высвобождения неуправляемых ресурсов явным образом. Пользователь объекта может вызвать этот метод, когда объект ему больше не нужен.
, и еще почитать - http://qps.ru/jzqg9 . Можно просто заключать битмап в конструкцию using
0
979 / 874 / 350
Регистрация: 26.04.2012
Сообщений: 2,647
03.03.2013, 21:52
Ну почти, просто по-моему графикс(мое предположение, но скорее всего так и есть)-это обертка над этими контекстами устройства, ибо представляют из себя они примерно одно и то же-некую виртуальную поверхность для рисования(только в графиксе все эти освобождения должны делаться автоматически, и следить за ними не надо, а если обращаться к DC нарямую, то приходится заниматься этим вручную), соответственно графиксу принадлежит какой-то DC, и чтобы записать графикс на битмап, надо сначала его освободить. А битмап представляет из себя нечто вроде рамы, в которую эта картина пихается. Для более точной информации-надо залезть в соответствующие библиотеки и посмотреть.

Добавлено через 2 минуты
Цитата Сообщение от Winhttp22 Посмотреть сообщение
EvilFromHell,
Из МСДН:

, и еще почитать - http://qps.ru/jzqg9 . Можно просто заключать битмап в конструкцию using
А причем тут это? Не совсем понял, проблема была не в битмапе.

Добавлено через 7 минут
А на счет неотображения курсора отдельно от BitBlt-странно, логику поищу. Главное все другие отображаются, а такой нет, и только в этом случае.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
03.03.2013, 21:52
Помогаю со студенческими работами здесь

Split с захватом символа разделителя
Здравствуйте. Для работы с разделителями у меня есть две опций вкючая_разделитель/не включая , но пока работает только не включая ...

Регулярное выражение: сделать текст жирным с захватом даты
Здравствуйте, форумчане. Сделал простой код, где заменяет обычный текст на жирный. Ничего сложного. Ниже пример того, что получается: ...

Как изменить цвет курсора ввода и курсора мыши в элементе Edit
Всем Здравия. Проблема в следующем, задал цвет фона и цвет текста в Edit, тут все нормально, но обнаружилось что при некоторых цветах...

Нужна недорогая плата оцифровки видео или USB устройство, только с аппаратным захватом и без твтюнера.
Подскажите уважаемые. Нужна недорогая плата оцифровки видео или USB устройство, только с аппаратным захватом и без твтюнера. У кого есть...

Поиск частей внешнего контура по четырём сторонам с "захватом"
Вот так вот чудно я назвал тему =) Всем привет. В рамках проекта нужно придумать алгоритм поиска внешних стен с заходом на соседнюю...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Нейросеть на алгоритме "эстафета хвоста" как перспектива.
Hrethgir 06.05.2026
На десерт, когда запущу сервер. Статья тут https:/ / habr. com/ ru/ articles/ 1030914/ . Автор я сам, нейросеть только помогает в вопросах которые мне не известны - не знаю людей которые знали-бы. . .
Асинхронный приём данных из COM-порта
Argus19 01.05.2026
Асинхронный приём данных из COM-порта Купил на aliexpress термопринтер QR701. Он оказался странным. Поключил к Arduino Nano. Был очень удивлён. Наотрез отказывается печатать русские буквы. Чтобы. . .
попытка написать игровой сервер на C++
pyirrlicht 29.04.2026
попытка написать игровой сервер на плюсах с открытым бесконечным миром. возможно получится прикрутить интерпретатор питон для кастомизации игровой логики. что есть на текущий момент:. . .
Контроль уникальности выбранного документа-основания при изменении реквизита
Maks 28.04.2026
Алгоритм из решения ниже разработан на примере нетипового документа "ЗаявкаНаРемонтСпецтехники", разработанного в КА2. Задача: уведомлять пользователя, если указанная заявка (документ-основание). . .
Благородство как наказание
Maks 24.04.2026
У хорошего человека отношения с женщинами всегда складываются трудно. А я человек хороший. Заявляю без тени смущения, потому что гордиться тут нечем. От хорошего человека ждут соответствующего. . .
Валидация и контроль данных табличной части документа перед записью
Maks 22.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа, разработанного в КА2. Задача: контроль и валидация данных табличной части документа перед записью с учетом регламента компании. . .
Отчёт о затраченных материалах за определенный период с макетом печатной формы
Maks 21.04.2026
Отчёт из решения ниже размещён в конфигурации КА2. Задача: разработка отчёта по затраченным материалам за определённый период, с возможностью вывода печатной формы отчёта с шапкой и подвалом. В. . .
Отчёт о спецтехнике находящейся в ремонте
Maks 20.04.2026
Отчёт из решения ниже размещен в конфигурации КА2. Задача: отобразить спецтехнику, которая на данный момент находится в ремонте. Есть нетиповой документ "Заявка на ремонт спецтехники" который. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru