Hi all.
Есть String взятый из TMemo. Помещаю его в clipboard формат CF_TEXT. При копировании в блокнот - козябры (для символов русской раскладки). Для нормального функционирования так же в clipboard нужно поместить данные форматов CF_LOCALE и CF_UNICODE. Как мне string преобразовать в WideString? Для преобразования нужно CodePage (я так понимаю это и есть CF_LOCALE). Где мне взять данные для CF_LOCALE и от чего она зависит?
Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице. Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.
21-05-2010 14:48 | Вопрос к автору: запрос дополнительной информации
Вопросы дабы не поднимать новую тему:
Ситуация1. Открываем нашу программу (форма и мемо). переключаем раскладку на русский. пишем текст. переключаем обратно на англ. копируем в буфер. вставляем в блокнот. результат: "?" и абракадабра...
Ситуация2. Открываем блокнот Windows. переключаем раскладку на русский. пишем текст. переключаем обратно на англ. копируем в буфер. вставляем в мемо в нашу программу (форма и мемо). результат: "?" и абракадабра...
Требуется:
1. Корректное (не "?" и не абракадабра) копирование/вставка русского текста в Windows Vista, 7, 2008, 2000, XP в/из контролов (TEdit, TMemo, TCombobox) Delphi в/из буфер обмена Windows с помощью нажатий клавиш Ctrl+C (Ins), Ctrl+V(Shift+Ins).
2. Условия: нельзя переключать раскладки клавиатуры, нужно выполнение именно по нажанию комбинация системных клавиш Ctrl+C (Ins), Ctrl+V(Shift+Ins)
18-06-2009 02:55 | Комментарий к предыдущим ответам
>>> А я пользуюсь более коротким вариантом
Вы смешиваете вызовы API и высокоуровневой обертки - TClipboard. В данном случае ничего страшного не произойдет, но вообще лучше делать все на одном уровне. У меня, обратите внимание, все сделано на WinAPI. На базе TClipboard тот же код выглядел бы короче.
17-02-2008 01:47 | Вопрос к автору: запрос дополнительной информации
ув. Python, скажите пожалуста, как применять вашу процедуру PureClip чтобы получить в немецкой виндос русский текст? в ней ведь нет передаваемых параметров
спасибо
03-02-2006 02:48 | Комментарий к предыдущим ответам
To Сергей Рощин:
Это ты мне? Ну... строго говоря, ничего тут особенного в этом коде и нет, просто надоело копировать текст в Блокнот, чтобы удалить из него все форматирование...
Вот, довел функцию до конца. Вытаскивает чистые текстовые данные из любого буфера:
procedure PureClip;
function ValidText(P:PWideChar;Size:cardinal):boolean;
// проверяет, что текст не нуждается в перекодировке
var I:cardinal;
begin
Result:=false; // текст нуждается в перекодировке - умолчание
For I:=0 to pred(Size) do if PChar(P)[2*I+1]<>#0 then exit;
// если обнаружен не локальный символ, выходим
Result:=true; // если нелокальные символы не найдены -
// текст в перекодировке не нуждается
end;
var Data,NewSize,NewData,CodePage:integer;
DataPtr,NewPtr:pchar;
DataPtrW:PWideChar;
begin
if OpenClipboard(GetForegroundWindow) then begin // монопольно пользовать буфер
CodePage:=$419;
Data:=GetClipboardData(CF_UNICODETEXT); // сохранить прежние текстовые данные
if Data<>0 then begin // существуют текст в юникоде
DataPtrW:=GlobalLock(Data);
if ValidText(DataPtrW,GlobalSize(Data) div 2) then begin
// текст не нуждается в перекодировке
GlobalUnlock(Data);
Data:=GetClipboardData(CF_TEXT); // получаем обычный текст
if Data=0 then begin CloseClipboard;exit;end;
NewSize:=GlobalSize(Data);
DataPtr:=GlobalLock(Data);
NewData:=GlobalAlloc(GMEM_MOVEABLE+GMEM_DDESHARE,NewSize);
NewPtr:=GlobalLock(NewData);
MoveMemory(NewPtr,DataPtr,NewSize); // копируем на новое место
GlobalUnlock(Data);
end else begin
NewSize:=WideCharToMultiByte(0,WC_COMPOSITECHECK,DataPtrW,-1,nil,0,nil,nil);
Assert(NewSize<>0,'NewSize must not be zero!'); // ошибка?
NewData:=GlobalAlloc(GMEM_MOVEABLE+GMEM_DDESHARE,NewSize);
// узнали размер перекодированной строки
NewPtr:=GlobalLock(NewData);
if WideCharToMultiByte(0,WC_COMPOSITECHECK,DataPtrW,-1,NewPtr,NewSize,nil,nil)=0 then raiselastoserror;
// перекодировали
GlobalUnlock(Data);
end;
end else begin // не найдена юникодовая страница
Data:=GetClipboardData(CF_TEXT);
if Data=0 then begin CloseClipboard;exit;end; // текстовых данных нет
NewSize:=GlobalSize(Data);
DataPtr:=GlobalLock(Data);
NewData:=GlobalAlloc(GMEM_MOVEABLE+GMEM_DDESHARE,NewSize);
NewPtr:=GlobalLock(NewData);
MoveMemory(NewPtr,DataPtr,NewSize); // скопировали на новое место
GlobalUnlock(Data);
end;
GlobalUnlock(NewData); // разблокировали новые данные
EmptyClipboard; // убить буфер
Data:=GlobalAlloc(GMEM_MOVEABLE+GMEM_DDESHARE,4); // Назначить кодовую страницу для буфера обмена
DataPtr:=GlobalLock(Data);
MoveMemory(DataPtr,@CodePage,4);
GlobalUnlock(Data);
SetClipboardData(CF_LOCALE,Data); // записать кодовую страницу
SetClipboardData(CF_TEXT,NewData); // вернуть новые данные для буфера обмена
CloseClipboard; // закрыть буфер
end;
end;
Прошу обо всех глюках сообщать либо здесь, либо мне в СЛС.
28-01-2006 05:21 | Комментарий к предыдущим ответам
Ой, извините, автор вопроса писал мне в личную почту, что такое PasteOnPureClip, так это не нужно, прочто я выдрал код из рабочей программы. Надо так (это уже не автору, а для потомков):
procedure PureClip;
var Data,NewSize,NewData,CodePage:integer;
DataPtr,NewPtr:pchar;
begin
CodePage:=$419;
if OpenClipboard(GetForegroundWindow) then begin // монопольно пользовать буфер
Data:=GetClipboardData(CF_TEXT); // сохранить прежние текстовые данные
if Data=0 then begin CloseClipboard;exit;end;
NewSize:=GlobalSize(Data);
DataPtr:=GlobalLock(Data);
NewData:=GlobalAlloc(GMEM_MOVEABLE+GMEM_DDESHARE,NewSize);
NewPtr:=GlobalLock(NewData);
MoveMemory(NewPtr,DataPtr,NewSize);
EmptyClipboard; // убить буфер
Data:=GlobalAlloc(GMEM_MOVEABLE+GMEM_DDESHARE,4); // Назначить кодовую страницу для буфера обмена
DataPtr:=GlobalLock(Data);
MoveMemory(DataPtr,@CodePage,4);
GlobalUnlock(Data);
SetClipboardData(CF_LOCALE,Data);
GlobalUnlock(NewData);
SetClipboardData(CF_TEXT,NewData); // вернуть новые данные для буфера обмена
CloseClipboard; // закрыть буфер
end;
end;
Это для русской Windows. Для зарубежных надо скорее всего использовать Unicode.
Вот так я уничтожаю информацию о кодировке в имеющемся буфере:
procedure PureClip;
var Data,NewSize,NewData,CodePage:integer;
DataPtr,NewPtr:pchar;
begin
CodePage:=$419;
if OpenClipboard(GetForegroundWindow) then begin // монопольно пользовать буфер
Data:=GetClipboardData(CF_TEXT); // сохранить прежние текстовые данные
if Data=0 then begin CloseClipboard;exit;end;
NewSize:=GlobalSize(Data);
DataPtr:=GlobalLock(Data);
NewData:=GlobalAlloc(GMEM_MOVEABLE+GMEM_DDESHARE,NewSize);
NewPtr:=GlobalLock(NewData);
MoveMemory(NewPtr,DataPtr,NewSize);
EmptyClipboard; // убить буфер
Data:=GlobalAlloc(GMEM_MOVEABLE+GMEM_DDESHARE,4); // Назначить кодовую страницу для буфера обмена
DataPtr:=GlobalLock(Data);
MoveMemory(DataPtr,@CodePage,4);
GlobalUnlock(Data);
SetClipboardData(CF_LOCALE,Data);
GlobalUnlock(NewData);
SetClipboardData(CF_TEXT,NewData); // вернуть новые данные для буфера обмена
CloseClipboard; // закрыть буфер
if PasteOnPureclip then begin // вставить, если необходимо
Wait(DelayCopy,GetForegroundWindow);
SendHotkey(HotPaste);
Wait(1,GetForegroundWindow);
end;
end;
end;
Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter. Функция может не работать в некоторых версиях броузеров.