Total Commander Forum Index Total Commander
Форум поддержки пользователей Total Commander
Сайты: Все о Total Commander | Totalcmd.net | Ghisler.com | RU.TCKB
 
 RulesRules   SearchSearch   FAQFAQ   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Буфер обмена с++
Goto page Previous  1, 2
 
Post new topic   Reply to topic    Total Commander Forum Index -> Программное обеспечение printer-friendly view
View previous topic :: View next topic  
Author Message
MVV



Joined: 15 Oct 2009
Posts: 4811
Location: Ростов-Дон

Post (Separately) Posted: Sun Apr 25, 2010 13:49    Post subject: Reply with quote

VadiMGP wrote:
Еще одно, хотя тут голову на отсечение не дам, но насколько я помню нет необходимости сначала проверять CF_UNICODETEXT, а потом CF_OEMTEXT. Эти форматы автоматически конвертируются один в другой и всегда присутствуют вместе. И CF_TEXT тоже.

Это чисто пример работы с несколькими форматами. Одним из них спокойно может оказаться CF_BITMAP, зависит от задачи.

VadiMGP wrote:
Уточнение. Для вызова IsClipboardFormatAvailable не нужно вызывать OpenClipboard. Даже рекомендуется наоборот, сначала убедиться, что есть нужный нам формат, и только в этом случае открывать буфер.

Действительно, так даже лучше. Вначале определяем, есть ли в буфере формат, который нас устроит, а потом открываем буфер:

Code:
   static const UINT desired_formats[]={CF_TEXT, CF_BITMAP}; // перечисляем форматы, которые нам надо обработать
   int fmt=GetPriorityClipboardFormat(&desired_formats, TSIZE(desired_formats)); // возвращает первый подходящий формат из массива, или -1, если не подошел ни один, или 0, если буфер пуст

   if (!fmt) MessageBox(0, "Clipboard is empty.", "Clipboard viewer", MB_ICONINFORMATION);
   else if (fmt<0) MessageBox(0, "Clipboard contains data in unknown format.", "Clipboard viewer", MB_ICONINFORMATION);
   else if (OpenClipboard(0)) {
      if (fmt==CF_TEXT) {
         HANDLE hclip=GetClipboardData(CF_TEXT);
         // обрабатываем текст
         if (hclip) MessageBox(0, (char*)hclip, "Clipboard text (ANSI)", MB_ICONINFORMATION);
      }
      else if (fmt==CF_BITMAP) {
         // обрабатываем картинку
         MessageBox(0, "Clipboard contains bitmap", "Clipboard viewer", MB_ICONINFORMATION);
      }
      CloseClipboard();
   }


А для простого получения текста вполне достаточно такого кода:
Code:
   if (IsClipboardFormatAvailable(CF_TEXT)&&OpenClipboard(0)) {
      HANDLE hclip=GetClipboardData(CF_TEXT);
      if (hclip) MessageBox(0, (char*)hclip, "Clipboard text (ANSI)", MB_ICONINFORMATION);
      CloseClipboard();
   }

Само собой, делать это нужно при получении уведомления WM_DRAWCLIPBOARD. И вместо выдачи сообщения нужно скопировать текст во внутренний буфер, а после закрытия буфера обрабатывать данные.

Вот только рекомендации по проверке до открытия буфера следовало бы засунуть в описание функции открытия буфера в MSDN...


Я так и не понял, в чем дело, но у меня на одном компе указанный выше пример получения текста из буфера при указани 0 в качестве окна работает, на другом - нет. Тупо возвращает нулевой дескриптор, и ошибку 1418. Я уже думаю, может, там она чуяла, что у процесса уже есть окно, и цеплялась к нему?.. Во, нашел причину - почему-то при трассировке кода в Visual Studio 2008, если я ставлю брейкпоинт между вызовами OpenClipboard и GetClipboardData, первая буфер открывает, но последняя возвращает 0! Confused
_________________
TCFS2 + TCFS2Tools: Полноэкранный режим и многое другое (обсуждение)
WINCMD.RU: AskParam, CopyTree, NTLinks, Sudo, VirtualPanel…
Back to top
View user's profile Send private message
VadiMGP



Joined: 21 Mar 2007
Posts: 1625

Post (Separately) Posted: Sun Apr 25, 2010 21:39    Post subject: Reply with quote

Quote:
Code:
HANDLE hclip=GetClipboardData(CF_TEXT);
      if (hclip) MessageBox(0, (char*)hclip, "Clipboard text (ANSI)", MB_ICONINFORMATION);
Я бы не стал передавать в MessageBox переменную типа HANDLE. Иди знай, что у этих пчел на уме. Лучше так.

Code:
if (hclip)
{
   LPSTR txt=(LPSTR)GlobalLock(hclip);
   MessageBox(0, txt,"Clipboard text (ANSI)", MB_ICONINFORMATION);
   GlobalUnlock(hclip);
}


Last edited by VadiMGP on Sun Apr 25, 2010 22:03; edited 1 time in total
Back to top
View user's profile Send private message
MVV



Joined: 15 Oct 2009
Posts: 4811
Location: Ростов-Дон

Post (Separately) Posted: Sun Apr 25, 2010 21:51    Post subject: Reply with quote

Возможно, я так и делал бы, но в описании функции GetClipboardData нет ни слова о необходимости вызова GlobalLock для возвращаемого дескриптора. Единственный намек - указание, что дескриптор нельзя закрывать и оставлять заблокированным. Но так как между вызовами OpenClipboard и CloseClipboard его содержимое измениться не может, все должно работать и без блокировки.

Кстати, в твоем примере не хватает явного приведения возвращаемого функцией GlobalLock значения к типу LPSTR. И, кстати, сам по себе LPSTR - это уже указатель на символ, поэтому звездочка в объявлении переменной txt не нужна.
_________________
TCFS2 + TCFS2Tools: Полноэкранный режим и многое другое (обсуждение)
WINCMD.RU: AskParam, CopyTree, NTLinks, Sudo, VirtualPanel…
Back to top
View user's profile Send private message
VadiMGP



Joined: 21 Mar 2007
Posts: 1625

Post (Separately) Posted: Sun Apr 25, 2010 22:03    Post subject: Reply with quote

MVV
В явном виде там, действительно, такое не написано, но есть пример использования.

Quote:
Кстати, в твоем примере не хватает явного приведения возвращаемого функцией GlobalLock значения к типу LPSTR. И, кстати, сам по себе LPSTR - это уже указатель на символ, поэтому звездочка в объявлении переменной txt не нужна.
Это точно, второпях сглупил, сейчас поправлю.
Back to top
View user's profile Send private message
MVV



Joined: 15 Oct 2009
Posts: 4811
Location: Ростов-Дон

Post (Separately) Posted: Sun Apr 25, 2010 22:32    Post subject: Reply with quote

Забавно, в примере тоже явное приведение типов отсутствует. Ощущение, что пример никогда не пытались компилировать. Very Happy
_________________
TCFS2 + TCFS2Tools: Полноэкранный режим и многое другое (обсуждение)
WINCMD.RU: AskParam, CopyTree, NTLinks, Sudo, VirtualPanel…
Back to top
View user's profile Send private message
VadiMGP



Joined: 21 Mar 2007
Posts: 1625

Post (Separately) Posted: Sun Apr 25, 2010 22:44    Post subject: Reply with quote

MVV wrote:
Забавно, в примере тоже явное приведение типов отсутствует
А, всё нормально. GlobalLock возвращает LPVOID, а он приводится к любому типу. Smile
Back to top
View user's profile Send private message
MVV



Joined: 15 Oct 2009
Posts: 4811
Location: Ростов-Дон

Post (Separately) Posted: Sun Apr 25, 2010 23:25    Post subject: Reply with quote

А вот не должен.

Любой указатель приводится к типу LPVOID, так как указатель на что-то определенное является указателем вообще (очевидно). Но отсюда вовсе не следует, что указатель вообще является указателем на что-то конкретное. В условиях жесткой типизации молча компилить такое недопустимо. 6-я студия не компилит. 7, 8 - не знаю, лень виртуальную машину запускать для проверки.

Типо, адрес больницы есть адрес вообще. Но адрес вообще вовсе не всегда есть адрес больницы. Very Happy И если мы попытаемся, считая здание по указанному адресу больницей, войти в него там, где в больнице вход, можем запросто влипнуть в стену, если здание окажется, скажем, школой. Laughing
_________________
TCFS2 + TCFS2Tools: Полноэкранный режим и многое другое (обсуждение)
WINCMD.RU: AskParam, CopyTree, NTLinks, Sudo, VirtualPanel…
Back to top
View user's profile Send private message
VadiMGP



Joined: 21 Mar 2007
Posts: 1625

Post (Separately) Posted: Mon Apr 26, 2010 01:38    Post subject: Reply with quote

MVV
Что самое смешное ты и прав и не прав.
Во-первых, в 2008 тоже не компиляется, выдает ошибку 2440 (cannot convert from 'type1' to 'type2'). По крайней мере, с жесткой проверкой типов. В этом ты прав.
А во-вторых, оказывается, что
MVV wrote:
... адрес больницы есть адрес вообще.
не всегда верно. В MSDN написано
C2440 can be caused if you attempt to convert a pointer to member to void*. The following sample generates C2440.
Code:
// C2440.cpp
class B {
public:
   void  f(){;}

   typedef void (B::*pf)();

   void f2(pf pf) {
       (this->*pf)();
       void* pp = (void*)pf;   // C2440
   }

   void f3() {
      f2(f);
   }
};

Но с больницей трудно провести аналогию, поэтому воспользуемся классикой - морская свинка еще не значит, что свинка. Smile
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Total Commander Forum Index -> Программное обеспечение All times are GMT + 4 Hours
Goto page Previous  1, 2
Page 2 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group