На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Обратите внимание:
1. Прежде чем начать новую тему или отправить сообщение, убедитесь, что вы не нарушаете правил форума!
2. Обязательно воспользуйтесь поиском. Возможно, Ваш вопрос уже обсуждали. Полезные ссылки приведены ниже.
3. Темы с просьбой выполнить какую-либо работу за автора в этом разделе не обсуждаются.
4. Используйте теги [ code=cpp ] ...текст программы... [ /code ] для выделения текста программы подсветкой.
5. Помните, здесь телепатов нет. Старайтесь формулировать свой вопрос максимально грамотно и чётко: Как правильно задавать вопросы
6. Запрещено отвечать в темы месячной и более давности без веских на то причин.

Полезные ссылки:
user posted image FAQ Сайта (C++) user posted image FAQ Форума user posted image Наши Исходники user posted image Поиск по Разделу user posted image MSDN Library Online (Windows Driver Kit) user posted image Google

Ваше мнение о модераторах: user posted image B.V.
Модераторы: B.V.
  
> Эмуляция нажатия PrintScreen , И работа с буфером обмена
    Добрый день.
    Программа эмулирует нажатие клавиши PrintScreen и забирает картинку из буфера обмена.
    Между этими действиями нужно что- то сделать, а что- не знаю.
    Пытаюсь вызвать SendMessage(HWND_BROADCAST,WM_NULL,0,0) - зависает.
    SendMessageTimeout не дает эффекта.
    Картинка в буфере появляется после потери фокуса.

    ExpandedWrap disabled
      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;}
      Для получения изображения окна есть функция PrintWindow
        Способов получить снимок экрана не один, я хотел именно через принтскрин.
        Переместил нажатие клавиш в обработчик OnPopup того же попап меню.
        Работает, только если не выберется пункт, нажатие на который предполагает работу со снимком экрана, в буфер обмена бесполезно копируется скриншот.
        Сообщение отредактировано: gorbovsky -

        Прикреплённая картинка
        Прикреплённая картинка
          Цитата gorbovsky @
          Способов получить снимок экрана не один, я хотел именно через принтскрин.

          Чем обусловлено такое хотение? Это очевидный костыль
          Далее, по скриншоту, сущий кошмар. 6-й Билдер, давно устаревший, и вызов такой же устаревшей keybd_event, которую с Win2k заменила SendInput, зачем-то динамический вызов имеющейся абсолютно во всех редакциях Windows PrintWindow
          Не нравится PrintWindow? Есть готовый пример GDI: https://learn.microsoft.com/en-us/windows/w...turing-an-image
          Только для начала советую навести порядок с проектом, обновить RAD Studio до хотя бы 10-й версии
            Цитата B.V. @
            Чем обусловлено такое хотение? Это очевидный костыль


            Да ничего себе костыль.

            ExpandedWrap disabled
              Image1->Assign(Clipboard());


            И никаких BitBlt и прочих радостей. VCL предоставляет хорошие возможности сэкономить время, грех не воспользоваться.

            Цитата B.V. @
            6-й Билдер, давно устаревший

            ну, что нашлось в пыльных архивах.

            Цитата B.V. @
            имеющейся абсолютно во всех редакциях Windows PrintWindow

            Нет в BCB6 PrintWindow
            Прикреплённая картинка
            Прикреплённая картинка
              В общем, помыкался и так и сяк, ничего не получилось. В интернете тоже кто- то жаловался на похожую проблему, мол срабатывает "через раз".
              Сделал без буфера обмена, хотя изначально программа задумывалась как замена клавише PrntScrn на залитой внуком клавиатуре (не нести же ноутбук в ремонт, это слишком просто).
              Ну вот может кому пригодится.

              ExpandedWrap disabled
                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);
                 
                 
                }
              Сообщение отредактировано: gorbovsky -
                Цитата gorbovsky @
                В общем, помыкался и так и сяк, ничего не получилось.

                А у меня сразу получилось - всё по твоей идее.
                Вот так:
                ExpandedWrap disabled
                      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-ом.
                Сообщение отредактировано: ЫукпШ -
                  А ничего что буфер обмена в этот момент может содержать ещё что-то полезное?
                    Цитата macomics @
                    А ничего что буфер обмена в этот момент может содержать ещё что-то полезное?

                    Думаем ли мы об этом, нажимая клавишу "PrintScreen" ? ;)
                    Подозреваю, что нет.
                    И это легко проверить - что будет, если буфер точно не пуст,
                    а мы нажали на эту клавишу.
                    Сообщение отредактировано: ЫукпШ -
                      Цитата ЫукпШ @
                      Sleep(1000);

                      Жостко. Но в консольном приложении попробовал- да, срабатывает, и Sleep(200) достаточно.
                      а в VCL Form application- нет. :tong:

                      ExpandedWrap disabled
                        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!!!!!");
                        }


                      Картинка появляется после возврата из функции.
                      Сообщение отредактировано: gorbovsky -
                        Так чтобы объект Clipboard актуализировал своё состояние должна обработаться очередь сообщений (в VCL). Поставьте Application.ProcessMessages перед проверкой Clipboard.
                        И можно даже убрать Sleep
                        Сообщение отредактировано: macomics -
                          Цитата macomics @
                          Application.ProcessMessages


                          да!
                          Как же я мог забыть.
                          Спасибо за помощь.
                          0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                          0 пользователей:


                          Рейтинг@Mail.ru
                          [ Script execution time: 0,0401 ]   [ 21 queries used ]   [ Generated: 27.04.24, 12:35 GMT ]