Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.146.255.127] |
|
Сообщ.
#1
,
|
|
|
Добрый день.
Программа эмулирует нажатие клавиши PrintScreen и забирает картинку из буфера обмена. Между этими действиями нужно что- то сделать, а что- не знаю. Пытаюсь вызвать SendMessage(HWND_BROADCAST,WM_NULL,0,0) - зависает. SendMessageTimeout не дает эффекта. Картинка в буфере появляется после потери фокуса. void __fastcall TForm1::N5Click(TObject *Sender) { keybd_event(VK_SNAPSHOT , 0, 0, 0); Sleep(20); keybd_event(VK_SNAPSHOT , 0, KEYEVENTF_KEYUP, 0); //::SendMessageTimeout(HWND_BROADCAST,WM_NULL,0,0,SMTO_BLOCK,20,NULL); TClipboard *cpb =Clipboard(); if(!cpb->HasFormat(CF_BITMAP)) {Tag =!Tag; return;} |
Сообщ.
#2
,
|
|
|
Для получения изображения окна есть функция PrintWindow
|
Сообщ.
#3
,
|
|
|
Способов получить снимок экрана не один, я хотел именно через принтскрин.
Переместил нажатие клавиш в обработчик OnPopup того же попап меню. Работает, только если не выберется пункт, нажатие на который предполагает работу со снимком экрана, в буфер обмена бесполезно копируется скриншот. Прикреплённая картинка
|
Сообщ.
#4
,
|
|
|
Цитата gorbovsky @ Способов получить снимок экрана не один, я хотел именно через принтскрин. Чем обусловлено такое хотение? Это очевидный костыль Далее, по скриншоту, сущий кошмар. 6-й Билдер, давно устаревший, и вызов такой же устаревшей keybd_event, которую с Win2k заменила SendInput, зачем-то динамический вызов имеющейся абсолютно во всех редакциях Windows PrintWindow Не нравится PrintWindow? Есть готовый пример GDI: https://learn.microsoft.com/en-us/windows/w...turing-an-image Только для начала советую навести порядок с проектом, обновить RAD Studio до хотя бы 10-й версии |
Сообщ.
#5
,
|
|
|
Цитата B.V. @ Чем обусловлено такое хотение? Это очевидный костыль Да ничего себе костыль. Image1->Assign(Clipboard()); И никаких BitBlt и прочих радостей. VCL предоставляет хорошие возможности сэкономить время, грех не воспользоваться. Цитата B.V. @ 6-й Билдер, давно устаревший ну, что нашлось в пыльных архивах. Цитата B.V. @ имеющейся абсолютно во всех редакциях Windows PrintWindow Нет в BCB6 PrintWindow Прикреплённая картинка
|
Сообщ.
#6
,
|
|
|
В общем, помыкался и так и сяк, ничего не получилось. В интернете тоже кто- то жаловался на похожую проблему, мол срабатывает "через раз".
Сделал без буфера обмена, хотя изначально программа задумывалась как замена клавише PrntScrn на залитой внуком клавиатуре (не нести же ноутбук в ремонт, это слишком просто). Ну вот может кому пригодится. void __GetScreen(TImage *img) { HDC hdcImage=img->Canvas->Handle; HDC hdcScreen = GetDC(NULL); HDC hdcMemDC = CreateCompatibleDC(hdcImage); RECT rcClient=img->ClientRect; if (!hdcMemDC) { ShowMessage("CreateCompatibleDC has failed"); goto done; } SetStretchBltMode(hdcImage, HALFTONE); if (!StretchBlt(hdcImage, 0, 0, rcClient.right, rcClient.bottom, hdcScreen, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), SRCCOPY)) ShowMessage( "StretchBlt has failed"); done: DeleteObject(hdcMemDC); ReleaseDC(NULL, hdcScreen); } |
Сообщ.
#7
,
|
|
|
Цитата gorbovsky @ В общем, помыкался и так и сяк, ничего не получилось. А у меня сразу получилось - всё по твоей идее. Вот так: keybd_event(VK_SNAPSHOT , 0, 0, 0); Sleep(20); keybd_event(VK_SNAPSHOT , 0, KEYEVENTF_KEYUP, 0); Sleep(1000); BOOL RetC=FALSE; RetC = ::OpenClipboard(NULL); if(!RetC) { DWORD dwLE = ::GetLastError(); _tprintf(_T("%s OpenClipboard error=%d"),_T(__FUNCTION__),dwLE); } HBITMAP hBmp = (HBITMAP) ::GetClipboardData(CF_BITMAP); if(!hBmp) { DWORD dwLE = ::GetLastError(); _tprintf(_T("%s GetClipboardData error=%d"),_T(__FUNCTION__),dwLE); } // ... ::CloseClipboard(); Никаких сбоев и ошибок зафиксировано не было. --- Причём, проверить правильность эмуляции нажатия клавиш можно посредством другого приложения. Т.е. запускаешь "нажимание" из своего приложения, а картинку из буфера читаешь например paint-ом. |
Сообщ.
#8
,
|
|
|
А ничего что буфер обмена в этот момент может содержать ещё что-то полезное?
|
Сообщ.
#9
,
|
|
|
Цитата macomics @ А ничего что буфер обмена в этот момент может содержать ещё что-то полезное? Думаем ли мы об этом, нажимая клавишу "PrintScreen" ? Подозреваю, что нет. И это легко проверить - что будет, если буфер точно не пуст, а мы нажали на эту клавишу. |
Сообщ.
#10
,
|
|
|
Цитата ЫукпШ @ Sleep(1000); Жостко. Но в консольном приложении попробовал- да, срабатывает, и Sleep(200) достаточно. а в VCL Form application- нет. void __fastcall TForm1::Button1Click(TObject *Sender) { KEYBDINPUT ki={ VK_SNAPSHOT, 0,0,NULL}; INPUT inp={}; inp.type=INPUT_KEYBOARD; memcpy(&inp.ki,&ki,sizeof(ki)); UINT retval=::SendInput(1,&inp,sizeof(inp)); Sleep(20); ki.dwFlags=KEYEVENTF_KEYUP; memcpy(&inp.ki,&ki,sizeof(ki)); SendInput(1,&inp,sizeof(inp)); Sleep(1000); TClipboard *cpb=Clipboard(); if(cpb->HasFormat(CF_BITMAP)) ShowMessage("BINGOOOOOO!!!!!"); } Картинка появляется после возврата из функции. |
Сообщ.
#11
,
|
|
|
Так чтобы объект Clipboard актуализировал своё состояние должна обработаться очередь сообщений (в VCL). Поставьте Application.ProcessMessages перед проверкой Clipboard.
И можно даже убрать Sleep |
Сообщ.
#12
,
|
|
|
Цитата macomics @ Application.ProcessMessages да! Как же я мог забыть. Спасибо за помощь. |