View previous topic :: View next topic |
Author |
Message |
MVV
Joined: 15 Oct 2009 Posts: 4811 Location: Ростов-Дон
|
(Separately) Posted: Sun Apr 25, 2010 13:49 Post subject: |
|
|
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! _________________ TCFS2 + TCFS2Tools: Полноэкранный режим и многое другое (обсуждение)
WINCMD.RU: AskParam, CopyTree, NTLinks, Sudo, VirtualPanel… |
|
Back to top |
|
|
VadiMGP
Joined: 21 Mar 2007 Posts: 1625
|
(Separately) Posted: Sun Apr 25, 2010 21:39 Post subject: |
|
|
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 |
|
|
MVV
Joined: 15 Oct 2009 Posts: 4811 Location: Ростов-Дон
|
(Separately) Posted: Sun Apr 25, 2010 21:51 Post subject: |
|
|
Возможно, я так и делал бы, но в описании функции GetClipboardData нет ни слова о необходимости вызова GlobalLock для возвращаемого дескриптора. Единственный намек - указание, что дескриптор нельзя закрывать и оставлять заблокированным. Но так как между вызовами OpenClipboard и CloseClipboard его содержимое измениться не может, все должно работать и без блокировки.
Кстати, в твоем примере не хватает явного приведения возвращаемого функцией GlobalLock значения к типу LPSTR. И, кстати, сам по себе LPSTR - это уже указатель на символ, поэтому звездочка в объявлении переменной txt не нужна. _________________ TCFS2 + TCFS2Tools: Полноэкранный режим и многое другое (обсуждение)
WINCMD.RU: AskParam, CopyTree, NTLinks, Sudo, VirtualPanel… |
|
Back to top |
|
|
VadiMGP
Joined: 21 Mar 2007 Posts: 1625
|
(Separately) Posted: Sun Apr 25, 2010 22:03 Post subject: |
|
|
MVV
В явном виде там, действительно, такое не написано, но есть пример использования.
Quote: | Кстати, в твоем примере не хватает явного приведения возвращаемого функцией GlobalLock значения к типу LPSTR. И, кстати, сам по себе LPSTR - это уже указатель на символ, поэтому звездочка в объявлении переменной txt не нужна. | Это точно, второпях сглупил, сейчас поправлю. |
|
Back to top |
|
|
MVV
Joined: 15 Oct 2009 Posts: 4811 Location: Ростов-Дон
|
|
Back to top |
|
|
VadiMGP
Joined: 21 Mar 2007 Posts: 1625
|
(Separately) Posted: Sun Apr 25, 2010 22:44 Post subject: |
|
|
MVV wrote: | Забавно, в примере тоже явное приведение типов отсутствует | А, всё нормально. GlobalLock возвращает LPVOID, а он приводится к любому типу. |
|
Back to top |
|
|
MVV
Joined: 15 Oct 2009 Posts: 4811 Location: Ростов-Дон
|
(Separately) Posted: Sun Apr 25, 2010 23:25 Post subject: |
|
|
А вот не должен.
Любой указатель приводится к типу LPVOID, так как указатель на что-то определенное является указателем вообще (очевидно). Но отсюда вовсе не следует, что указатель вообще является указателем на что-то конкретное. В условиях жесткой типизации молча компилить такое недопустимо. 6-я студия не компилит. 7, 8 - не знаю, лень виртуальную машину запускать для проверки.
Типо, адрес больницы есть адрес вообще. Но адрес вообще вовсе не всегда есть адрес больницы. И если мы попытаемся, считая здание по указанному адресу больницей, войти в него там, где в больнице вход, можем запросто влипнуть в стену, если здание окажется, скажем, школой. _________________ TCFS2 + TCFS2Tools: Полноэкранный режим и многое другое (обсуждение)
WINCMD.RU: AskParam, CopyTree, NTLinks, Sudo, VirtualPanel… |
|
Back to top |
|
|
VadiMGP
Joined: 21 Mar 2007 Posts: 1625
|
(Separately) Posted: Mon Apr 26, 2010 01:38 Post subject: |
|
|
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);
}
};
|
Но с больницей трудно провести аналогию, поэтому воспользуемся классикой - морская свинка еще не значит, что свинка. |
|
Back to top |
|
|
|
|
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
|