Форум: "Основная";
Текущий архив: 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