Модераторы: Snowy, bartram, MetalFan, bems, Poseidon, Riply
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Работа с буфером обмена средствами WinAPI 
:(
    Опции темы
lollollollol
Дата 27.3.2013, 10:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 287
Регистрация: 12.3.2013

Репутация: нет
Всего: нет



Здравствуйте.

Есть задача - Сделать скриншот экрана.
Условие - Текстовое значение буфера обмена должно остаться неизменным.

Я решил сделать так:
Код

//Копирую значение буфера в string
CopyScreenToClipboard(GetSystemMetrics(0),GetSystemMetrics(1)); //делаю скриншот
//Сохраняю его
//Из переменной копирую значение в буфер обмена


Если добавить uses clipbrd, то решение задачи не занимает больше пяти минут. 
Но необходимо сделать это использую лишь uses windows. 

Пытался получить текст так:

Код

      while (GetOpenClipboardWindow>0) do sleep(50); //Жду пока буфер освободится, то есть с ним перестанет работать другое приложение
      OpenClipboard(GetCurrentProcess); //Начинаю работу с буфером. Формы у ехе нет, поэтому вместо Application.Handle использую GetCurrentProcess
      TextBuf:=''; //Обнуляю значение текстовой переменной типа String
      if (IsClipboardFormatAvailable(CF_TEXT)=True) then begin //Если в буфере текст
        h:=GetClipboardData(CF_TEXT); //Получаю хендл позиции блока данных 
        {Проблема! Не могу понять как теперь скопировать эти данные в переменную. Ведь я не знаю даже длины данных}
      end;
      CloseClipboard; //Заканчиваю работать с буфером


Прошу помочь с вопросом, спасибо

Добавлено @ 10:45
Заглянул в USES, выдрал оттуда код


Код

function GetAsText: string;
var
  Data: THandle;
begin
  OpenClipboard(GetCurrentProcess); //Это я поменял, было Open
  Data := GetClipboardData(CF_TEXT);
  try
    if Data <> 0 then
      Result := PChar(GlobalLock(Data))
    else
      Result := '';
  finally
    if Data <> 0 then GlobalUnlock(Data);
    CloseClipboard;
  end;
end;


Но к моему удивлению Data=0. Видимо нельзя передавать GetCurrentProcess. А как можно получить хендл процесса, без формы?

Это сообщение отредактировал(а) lollollollol - 27.3.2013, 10:45
PM MAIL   Вверх
Akella
Дата 27.3.2013, 12:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: нет
Всего: 329



Нужно обязательно через winapi?
PM MAIL   Вверх
Evjeny
Дата 27.3.2013, 13:06 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 88
Регистрация: 14.8.2006

Репутация: нет
Всего: 5



CF_TEXT - кодировка ANSI, каждая строка заканчивается CRLF, в конце буфера 0

по поводу OpenClipboard - исходя из документации надо передавать 0:
Код

hWndNewOwner [in, optional]

Type: HWND

A handle to the window to be associated with the open clipboard. If this parameter is NULL, the open clipboard is associated with the current task.

PM MAIL WWW   Вверх
lollollollol
Дата 27.3.2013, 18:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 287
Регистрация: 12.3.2013

Репутация: нет
Всего: нет



Цитата

Нужно обязательно через winapi? 

Обязательно без использования любых uses кроме windows

Цитата

CF_TEXT - кодировка ANSI, каждая строка заканчивается CRLF, в конце буфера 0

Да, вот это я стормозил. Передал ноль, и смог получить текст из буфера
Посмотрев повнимательней Clipbrd, удалось и записать текст в буфер


Остался финальный вопрос, как записать скриншот, который находится в буфере в переменные
buff: array[0..20971520] of byte; //Массив байт
buff_size:integer; //Размер изображения


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

Это сообщение отредактировал(а) lollollollol - 27.3.2013, 20:12
PM MAIL   Вверх
Evjeny
Дата 27.3.2013, 20:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 88
Регистрация: 14.8.2006

Репутация: нет
Всего: 5



Я в делфи не силен - CopyScreenToClipboard это функция делфи или самописаная?

как вариант узнать формат содержимого буфера обмена (GetClipboardFormatName), и уже от этого отталкиваться - найти описание формата и т.д.
PM MAIL WWW   Вверх
lollollollol
Дата 27.3.2013, 20:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 287
Регистрация: 12.3.2013

Репутация: нет
Всего: нет



Код

procedure CopyScreenToClipboard(x,y:integer);
var
  dx,dy: integer;
  hSourcDC, hDestDC, hBM, hbmOld: THandle;
begin
  dx := x;
  dy := y;
  hSourcDC := CreateDC('DISPLAY', nil, nil, nil);
  hDestDC := CreateCompatibleDC(hSourcDC);
  hBM := CreateCompatibleBitmap(hSourcDC, dx, dy);
  hbmold:= SelectObject(hDestDC, hBM);
  BitBlt(hDestDC, 0, 0, dx, dy, hSourcDC, 0, 0, SRCCopy);
  OpenClipBoard(0);
  EmptyClipBoard;
  SetClipBoardData(CF_Bitmap, hBM);
  CloseClipBoard;
  SelectObject(hDestDC,hbmold);
  DeleteObject(hbm);
  DeleteDC(hDestDC);
  DeleteDC(hSourcDC);
end;

Должно быть изображение BitMap, всё что есть для этого типа расчитано что я загружу его в TBitmap, но мне нельзя использовать это.
PM MAIL   Вверх
Evjeny
Дата 27.3.2013, 21:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 88
Регистрация: 14.8.2006

Репутация: нет
Всего: 5



да это HBITMAP, соответственно и работать с ним можно через win api...

здесь пример (правда на с++), как сохранить это все в файл....
PM MAIL WWW   Вверх
lollollollol
Дата 27.3.2013, 21:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 287
Регистрация: 12.3.2013

Репутация: нет
Всего: нет



А если за основу взять функцию которая копирует текст:

Код

function GetBitMap: string;
var
  Data: THandle;
begin
  OpenClipboard(0);
  Data := GetClipboardData(CF_BITMAP); //Тут указываю тип
  try
    if Data <> 0 then
     Result := PChar(GlobalLock(Data))  //А вот как прописать тут - не пойму. 
//Я ведь даже размера изображения не могу узнать, чтобы скопировать байты

    else
      ZeroMemory(@buff,sizeof(buffer)); //Если ничего в буфере нет, очищу и массив
  finally
    if Data <> 0 then GlobalUnlock(Data);
    CloseClipboard;
  end;
end;


Я верно мыслю? Указываю необходимый тип, теперь осталось получить информацию. Но не пойму как в массив записать BitMap, который сейчас в буфере

Это сообщение отредактировал(а) lollollollol - 27.3.2013, 21:49
PM MAIL   Вверх
Evjeny
Дата 27.3.2013, 22:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 88
Регистрация: 14.8.2006

Репутация: нет
Всего: 5



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

я бы помог кодом, но с делфи давно не общался, да и иде самой нету...
PM MAIL WWW   Вверх
lollollollol
Дата 28.3.2013, 07:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 287
Регистрация: 12.3.2013

Репутация: нет
Всего: нет



В любом случае это просто набор байт, нужно знать лишь начало, и размер. Так что думаю получится.

BMP это ведь просто формат где каждый пиксель это цвет, в формате RGP и занимает он 3 байта.

Значит размер изображения должен быть
Длина*Ширина*3. 
Хотя сомневаюсь, ведь в начале .bmp файла есть ряд символов которые уникальны для каждого формата
PM MAIL   Вверх
lollollollol
Дата 28.3.2013, 09:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 287
Регистрация: 12.3.2013

Репутация: нет
Всего: нет



Код

//len:=40+(GetSystemMetrics(0)*GetSystemMetrics(1)*3;
procedure SaveBitmap(buff:pointer;len:integer);
var
  Data: THandle;
  res:pointer;
begin
  OpenClipboard(0);
  Data := GetClipboardData(CF_BITMAP);
  try
    if (Data<>0) then begin
      res:=GlobalLock(Data); //res=nil, но в буфере точно есть изображение, без проблем вставляется в любой графический редактор
      if (res<>nil) then begin
        CopyMemory(buff,res,len);
      end;
    end;
  finally
    if Data <> 0 then GlobalUnlock(Data);
    CloseClipboard;
  end;
end;



Это сообщение отредактировал(а) lollollollol - 28.3.2013, 10:06
PM MAIL   Вверх
lollollollol
Дата 28.3.2013, 20:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 287
Регистрация: 12.3.2013

Репутация: нет
Всего: нет



Код

MessageBox(0,Pchar(SysErrorMessage(GetLastError)),'',0);

После res:=GlobalLock(Data); показало
Неверный дескриптор окна, непойму что ему не нравится, остальные функции без ошибок отработали, проверил этим же кодом
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: WinAPI и системное программирование"
Snowybartram
MetalFanbems
PoseidonRrader
Riply

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Delphi обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • 99% ответов по WinAPI можно найти в MSDN Library, оставшиеся 1% здесь

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, bartram, MetalFan, bems, Poseidon, Rrader, Riply.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: WinAPI и системное программирование | Следующая тема »


 




[ Время генерации скрипта: 0.0871 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.