Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2012.03.25;
Скачать: [xml.tar.bz2];

Вниз

Как отловить нажатие VK_SNAPSHOT?   Найти похожие ветки 

 
antonn ©   (2010-11-14 00:46) [0]

В программе нужно поймать нажатие кнопки PrintScreen, ничего не подменять и прочего, работать только когда окно в фокусе (не "глобально"). Получить тот же функционал, что и в событиях OnKeyPress() - т.е. кнопка нажата и повторы нажатий (если они есть, как с буквами), т.е. GetAsyncKeyState() в каком нибудь таймере не подойдет.
Покопался в интернете, нашел раскопипащенный способ через хоткей ( http://www.delphimaster.ru/cgi-bin/faq.pl?look=1&id=988620866&n=15 ), но у меня этот способ работает "глобально" и при этом, видимо, "глушит" для остальных эту кнопку (по крайней мере в буфере все чисто, что уже не подходит). С хуками связываться не очень хочется... Реализация через другой раскопипащенный пример с обработкой в AppIdle() за одно быстрое нажатие выдает разом десяток "срабатываний" (ну там и GetAsyncKeyState()).
Есть ли какой проверенный способ узнать о нажатии этой кнопки, максимально независимый от всяких прав на действия (касперский спрашивает, хочу ли я позволить приложению установить ловушку :( ) и чтобы работало от win2k и выше?


 
sniknik ©   (2010-11-14 10:21) [1]

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

var
 HookHandle: hHook = 0;

function WMHotKey(Code: integer; wParam: WPARAM; lParam: LPARAM): LongInt; stdcall;
begin
 if Code >= 0 then begin
   if wParam = VK_SNAPSHOT then ShowMessage("GotIt");
   result:= 0;
 end else
   result:= CallNextHookEx(HookHandle, Code, wParam, lParam);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 //RegisterHotKey(Handle, id_SnapShot, 0, VK_SNAPSHOT);
 HookHandle:= SetWindowsHookEx(wh_Keyboard, @WMHotKey, hInstance, 0);
 if HookHandle = 0 then
   ShowMessage("Ошибка установки хука");
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
 //UnRegisterHotKey(Handle, id_SnapShot);
 if HookHandle <> 0 then
   UnhookWindowsHookEx(HookHandle);
end;


> при этом, видимо, "глушит"
этот, у меня (на моей машине - xp) не глушит, но что будет в win 7 не знаю.


 
antonn ©   (2010-11-14 14:20) [2]

А тот что в ФАКе не вставляет в буфер скриншот если хоткей повесить на окно? Хотелось бы знать это так и должно быть или у меня "что-то глючит" :)

С хуком касперский задает вопрос о допустимости установки ловушки. У меня программа может отправлять данные в интернет, и если такие сообщения будут вылезать - подозрительно будет выглядеть. Точнее я бы, если бы не знал что делает программа, не стал ей это разрешать :)


 
sniknik ©   (2010-11-14 18:20) [3]

> А тот что в ФАКе не вставляет в буфер скриншот если хоткей повесить на окно? Хотелось бы знать это так и должно быть или у меня "что-то глючит" :)
у меня не вставляет, т.что ... не знаю. инхеритед не помогает, результ другой возвращать тоже, только то что выше, или "в лоб", как ниже.

procedure SimulateKeystroke(Key : byte; extra : DWORD);
begin
 keybd_event(Key, extra, 0, 0);
 keybd_event(Key, extra, KEYEVENTF_KEYUP, 0);
end;

procedure TForm1.WMHotKey (var Msg: TWMHotKey);
begin
 if Msg.HotKey = id_SnapShot then begin
   ShowMessage("GotIt");

   UnRegisterHotKey(Handle, id_SnapShot);
   try
      SimulateKeystroke(VK_SNAPSHOT, 0);
   finally
     RegisterHotKey(Handle, id_SnapShot, 0, VK_SNAPSHOT);
   end;
 end;
end;


 
antonn ©   (2010-11-14 20:47) [4]

Волшебный костыль :))
Да, была идея самому делать "принтскрин" в это время, но постеснялся такое воротить :)

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


 
sniknik ©   (2010-11-14 21:29) [5]

> предложили в оконной проедуре ловить
стоп... ты же в [0] условие поставил, что не в окне(/форме)... нет?

> он ловится до тех пор, пока на форме нет других оконных компонент
в смысле? это уже на 17ю строку смахивает... подробнее нельзя?


 
sniknik ©   (2010-11-14 21:37) [6]

кажется будет к месту
http://www.gunsmoker.ru/2008/10/x-y-z.html


 
sniknik ©   (2010-11-14 21:38) [7]

> используя шаманский бубен, миелофон, шестое чувство, телепатор и прочие БС (Божественные Силы)
KeyPreview?


 
antonn ©   (2010-11-14 22:08) [8]


> sniknik ©   (14.11.10 21:29) [5]
>
> > предложили в оконной проедуре ловить
> стоп... ты же в [0] условие поставил, что не в окне(/форме).
> .. нет?

в данном случае форма есть


> кажется будет к месту

Нет, не к месту :)
Мне бы хотелось отлавливать принтскрин, будь хоть оконное приложение, хоть безоконное, иметь универсальный пример. Ну и как бы хотелось чтобы этому примеру было все равно есть ли окно в приложении или нет. Если это невозможно, и реализации с окном и без него "не пересекаются", то я думаю отвечающие (не только в этой теме) меня бы предупредили и давали советы "для окна" и "без него".
На данный момент у моего приложения есть окно, если это имело значение - надо было уточнить, извиняюсь :) Однако я же не зря привел ссылку на фак, там оконное приложение. Начал с малого :)

KeyPreview? Разумеется поставил св-во в true (в инспекторе, ну и в создании формы повторил, для проверки), но не доходит... Вообще ничего
type
 TForm1 = class(TForm)
   SpeedButton1: TSpeedButton;
   Button1: TButton;
   Memo1: TMemo;
   procedure FormCreate(Sender: TObject);
   procedure WndProc(var Message: TMessage); override;
 private
   { Private declarations }
 public
   { Public declarations }
 end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 KeyPreview:=true;
end;

procedure TForm1.WndProc(var Message: TMessage);
begin
 if(Message.msg=WM_KEYUP)and(Message.wParam=VK_SNAPSHOT) then begin
    memo1.Lines.Add(inttostr(random(65535)));
    caption:=inttostr(random(65535));
 end else
 if(Message.msg=WM_KEYUP)and(Message.wParam=VK_LEFT) then begin
    memo1.Lines.Add(inttostr(random(65535)));
    caption:=inttostr(random(65535));
 end;
 inherited WndProc(Message);
end;


 
antonn ©   (2010-11-14 22:13) [9]

вот идиот, не в FormKeyDown ловлю =)))


 
antonn ©   (2010-11-14 22:15) [10]

но все же хреново работает, на форме без контролов ввода (пара кнопок) опять же не отлавливается


 
sniknik ©   (2010-11-15 00:14) [11]

> вот идиот, не в FormKeyDown ловлю =)))
надо в FormKeyUp, даун занят принтскрином.

> WndProc
зачем усложнять (+ возможные ошибки вставлять), просто в событии формы достаточно.


 
antonn ©   (2010-11-15 00:51) [12]


> зачем усложнять (+ возможные ошибки вставлять), просто в
> событии формы достаточно.

она все равно перекрыта, но почему в событии срабатывает, а в WndProc нет?

И по моему разумнее делать скрин в момент нажатия, проще ловить момент, чем нажать и ждать отжатия :(


 
sniknik ©   (2010-11-15 07:55) [13]

>  почему в событии срабатывает, а в WndProc нет?
ошибка в твоей WndProc? почему бы не посмотреть как в vcl реализовано для того же события из формы.

> И по моему разумнее делать скрин в момент нажатия, проще ловить момент, чем нажать и ждать отжатия :(
а по моему разумнее делать так как работает в соответствии с системой.

и потом скрин как раз там и делается, в нажатии, это тебе предлагается ловить отжатие чтобы узнать, что он сделался...
или опять изменение планов? теперь ты уже ловишь чтобы делать скрин сам? тогда к чему тебе срабатывание системного? оно в первоначальном варианте как раз переопределяет нажатие и считает, что  на этом все скрин ты сделаешь и не нужно системный вызывать чтобы не перетереть твое.


 
antonn ©   (2010-11-15 09:02) [14]


> и потом скрин как раз там и делается, в нажатии, это тебе
> предлагается ловить отжатие чтобы узнать, что он сделался.
> ..
> или опять изменение планов? теперь ты уже ловишь чтобы делать
> скрин сам? тогда к чему тебе срабатывание системного? оно
> в первоначальном варианте как раз переопределяет нажатие
> и считает, что  на этом все скрин ты сделаешь и не нужно
> системный вызывать чтобы не перетереть твое.
>

Моя программа сохраняет в папку со скриншотами свой битмап, использование для этого системной кнопки лишь дань удобству и привычкам пользователям. Игра это


 
sniknik ©   (2010-11-15 09:41) [15]

вот вот, тогда зачем вообще тебе нужен системный вызов? раз уже сам "снял" скриншот, осталось только добавить его же в буфер обмена. а чтобы работал системный когда твоя игра не активна, то установку/снятие хука делать на активации/деактивации.


 
antonn ©   (2010-11-15 12:31) [16]


> раз уже сам "снял" скриншот, осталось только добавить его
> же в буфер обмена.

Нет, я не хочу вмешиваться в событие снятия скриншота. Юзер может сфотографировать какое нибудь AV (или банальный дефект от перерисовки на которое повлияла тема оформления, или вообще сделать снимок экрана, а не моего окна), а я ему буду подсовывать свой буфер? Тут есть один товарищ - он ведь и "морду набить" может за такое :)
Мне лишь была нужна реакция на кнопку, отловить ее нажатие.
Если бы я хотел, чтобы в буфер обмена помещался мой скриншот - я бы сделал поддержку Ctrl+C в своем окне.

Хук отлавливается всякими касперскими, я выше написал почему это может быть плохим методом. К тому же юзер может запретить один раз в этом самом касперском, а потом обратно разрешить задача не тривиальная для домашнего пользователя (речь конкретно об КИС8/9/10). А скрины сохраненные на диск сразу в png без не_клиентской части окна - удобно.


 
sniknik ©   (2010-11-15 13:02) [17]

> Мне лишь была нужна реакция на кнопку, отловить ее нажатие.
ты ее отлавливаешь в первом же -
> раскопипащенном способе через хоткей
сам же привел.

> не хочу вмешиваться в событие снятия скриншота.
в своей программе ты однозначно вмешиваешься, т.что добавить в буфер обмена то что уже есть меньшее зло, чем искать способ дать другим сделать дублирующуюся работу.
а чтобы не влиять на другие -
> а чтобы работал системный когда твоя игра не активна, то установку/снятие хука делать на активации/деактивации.

> а не моего окна
тогда ловить нужно Alt+PrintScreen, если окно.
по [3] аналог SimulateKeystroke(VK_SNAPSHOT, 1);

p.s. в общем проблема "высосана из пальца", в системе похоже специально ограничения на такой случай, типа "защиты от дурака", и делай либо правильно либо никак...


 
antonn ©   (2010-11-15 15:20) [18]


> > не хочу вмешиваться в событие снятия скриншота.
> в своей программе ты однозначно вмешиваешься

Нет, не вмешиваюсь, я даю пользователю возможность "щелкать" игровые скриншоты, предлагая делать это по стандартной (для игр, по крайней мере) клавише. Но так же пользователь может привычно для себя "фотографировать" экран в котором присутствует мое окно, в том случае если мое окно не "полноэкранное". Повторюсь так же, что если пользователь захочет сфотографировать окно, то он щелкнет Alt+PrintScreen, у меня же сохраняется в файл не окно, а только игровой контент.
Игровой скриншот<>Alt+PrintScreen, потому что содержит только битмап игровой сцены, без кепшенов и бордюров формы.

Отсюда мне требовалось лишь узнать о том, что был нажата кнопка, без каких либо перехватов (ууу, за одно упоминание такого мне бы уже "набили морду"..) и переопределений. Переназначить кнопку снятия игрового скриншота я могу, оставалась проблема узнать о ее нажатии. И сабжевую кнопку в качестве "скриноснимателя" выбирает подавляющее большинство игроков.

Могу так же порекомендовать глянуть другие продукты похожей направленности, так некий "ScreenshotCaptor" аналогично делает скрины всего экрана (или части) сохраняя их сразу в файл, и при этом в буфере обмена остается то, что должно было снято кнопкой printscreen. Никто ничего не заменяет в буфере, потому что это не их дело что туда занесли и кто.


 
sniknik ©   (2010-11-15 17:42) [19]

> так некий "ScreenshotCaptor" аналогично делает скрины
а как оно внутри работает? ты что ли его писал? то что видно "сверху" аналогично, не значит что "внутрях" все по твоим понятиям сделано (вот лично я бы попытался минимизировать работу, и не делать двойных действий).

> Никто ничего не заменяет в буфере, потому что это не их дело что туда занесли и кто.
а тебе что то другое предлагали? тебе предлагали вставлять туда только когда действия совпадают. активно твое приложение, и получается твой скриншот = тому что снимет система.

хотя ладно, не хочешь понимать, твое дело.


 
antonn ©   (2010-11-15 18:01) [20]


> активно твое приложение, и получается твой скриншот = тому
> что снимет система.

нет, мой скриншот сохраненный мною - игровая сцена. Которая выводится в обычное окно, которое не максимизировано. Без кепшенов и прочего, а принтскрином делается снимок окна (только моего или рабочего стола - не важно).
И так же работает в какй либо другой вменяемой игрушке, если игра идет в окне, то принтскрин делает скриншот экрана (окна), а игра сохраняет только буфер вывода.


> а как оно внутри работает?

отслеживает клавишу и снимает снимок, переводит в палитру pf24bit и дальше сохраняет в заранее выбранном формате в выбраную папку. В буфере остается исходное изображение (иногда с модифицированной палитрой, вставку которого из буфера не переваривает ни один из моих редакторов (палитра 256 цветов, вставляется черный квадрат, это тоже игра, но старая), а вот эта программа позволяет снять без геморроя).



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2012.03.25;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.53 MB
Время: 0.004 c
6-1253728722
kluben-hh
2009-09-23 21:58
2012.03.25
Правильное соединение клиента с сервером


2-1323521292
3asys
2011-12-10 16:48
2012.03.25
Открытие файлов в TWebBrowser


15-1322668217
Новый русский
2011-11-30 19:50
2012.03.25
Самая гнусная ошибка?


1-1273054167
Roman-555
2010-05-05 14:09
2012.03.25
Увеличение точности вычислений до 30-40 значащих цифр


2-1323120597
mnj
2011-12-06 01:29
2012.03.25
Использование TFileStream для текста и бинарного файла





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский