添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

Win7-8 OS, Russian locale (and format) set in OS Region settings, Delphi 7.

The problem is that it works only when I switch (shift+alt) to Russian keyboard layout when copying. Otherwise it will be pasted as "Ïðèâåò!" instead of "Привет!" .

How can I fix that?

I think that I need somehow convert text to Unicode and call Unicode clipboard copy function from WinAPI? But how to do that?

@MatheusFreitas I know. But I think it is possible to convert string to Unicode and call some winapi function? Alex P. Feb 11, 2014 at 16:21 @Alex11223 I would suggest to use only unicode strings in your programs. Not only when copying to clipboard. KonstantinL Feb 11, 2014 at 16:40

Convert the text to Unicode by whatever means you see fit. In Delphi 7 that typically involves using WideString .

Once you have the text encoded as UTF-16, for instance in a WideString , you need to call SetClipboardData using the CF_UNICODETEXT clipboard format. This is wrapped by Delphi as the SetAsHandle method of the global Clipboard object.

I've not tested it, but this function should set you on the way:

Windows, Clipbrd; procedure SetClipboardText(const Text: WideString); Count: Integer; Handle: HGLOBAL; Ptr: Pointer; begin Count := (Length(Text)+1)*SizeOf(WideChar); Handle := GlobalAlloc(GMEM_MOVEABLE, Count); Win32Check(Handle<>0); Ptr := GlobalLock(Handle); Win32Check(Assigned(Ptr)); Move(PWideChar(Text)^, Ptr^, Count); GlobalUnlock(Handle); Clipboard.SetAsHandle(CF_UNICODETEXT, Handle); Except GlobalFree(Handle); raise; I'm with @Sertac here. Check out the flow TClipboard.SetBuffer . It will never fail silently. Free Consulting Feb 11, 2014 at 17:12 @FreeConsulting If GlobalAlloc or GlobalLock fail then you will end up with an AV, invalid write to $00000000 , in the Move because DataPtr will be nil . So yes, it will not silently fail. That's not such a bad way to go. Protected hack is also not unreasonable. I personally don't find the code in my answer to be difficult to write or understand. David Heffernan Feb 11, 2014 at 17:16 @craig because you must only call GlobalFree if you were not able to pass ownership to the clipboard David Heffernan Feb 11, 2014 at 18:29

Thank you very much, by thees means you can also convert Encoding in the clipboard if you catch WM_CLIPBOARDUPDATE message - very usefull with old versions of delphi, e.g. for Russian Language. Here is a full working code:

(N.B. This buffer listening tecnique will only work for Windows Vista and newer OS, that's why I use dynamic WinAPI linking, see this article - http://delphidabbler.com/articles?article=9 )

TAddOrRemoveClipboardFormatListener = function (hWndNewViewer : HWND) : BOOL; stdcall; var _isClipboardChangeRequired : boolean; var _addClipboardFormatListener, _removeClipboardFormatListener : TAddOrRemoveClipboardFormatListener; procedure TDM.DataModuleCreate(Sender: TObject); begin _addClipboardFormatListener := GetProcAddress(GetModuleHandle('user32.dll'), 'AddClipboardFormatListener'); _removeClipboardFormatListener := GetProcAddress(GetModuleHandle('user32.dll'), 'RemoveClipboardFormatListener'); if (Assigned(_addClipboardFormatListener) AND NOT _addClipboardFormatListener(Application.Handle)) then begin _isClipboardChangeRequired := false; ShowMessage('Не удалось установить перехватчик изменения буфера обмена! Кодировка при вставке в контролы может быть неверной!' + sLineBreak + 'Код ошибки (' + IntToStr(GetLastError()) + '): ' + SysErrorMessage(GetLastError())); // WriteLog([ssWarn], ClassName, 'Не удалось установить перехватчик изменения буфера обмена! Кодировка при вставке в контролы может быть неверной!' + // sLineBreak + 'Код ошибки (' + IntToStr(GetLastError()) + '): ' + SysErrorMessage(GetLastError())); _isClipboardChangeRequired := true; procedure TDM.DataModuleDestroy(Sender: TObject); begin if Assigned(_removeClipboardFormatListener) then _removeClipboardFormatListener(Application.Handle); procedure TDM.ApplicationEvents_ClipboardChangeMessage(var Msg: tagMSG; var Handled: Boolean); const // WM_CLIPBOARDUPDATE is not defined in the Messages unit of all supported // versions of Delphi, so we defined it here for safety. // (взято отсюда: http://delphidabbler.com/articles?article=9) WM_CLIPBOARDUPDATE = $031D; MAX_CLIPBOARD_OPEN_ATTEMPTS = 3; textBuf : array[0..512] of WideChar; clipHandle : THandle; dataPtr: Pointer; dataSize : integer; str : string; attemptCount : integer; isClipboardOpened : boolean; begin // если система не поддерживает слежение за буфером обмена, прекращаем дальнейшие попытки это сделать if (NOT Assigned(_addClipboardFormatListener)) then begin ApplicationEvents_ClipboardChange.OnMessage := nil; Exit; if (Msg.message = WM_CLIPBOARDUPDATE) AND (Clipboard.HasFormat(CF_UNICODETEXT)) then if NOT _isClipboardChangeRequired then begin _isClipboardChangeRequired := true; Exit; begin attemptCount := 1; isClipboardOpened := false; repeat Clipboard.Open(); isClipboardOpened := true; except if (attemptCount >= MAX_CLIPBOARD_OPEN_ATTEMPTS) then begin OutputDebugString(PChar('Внимание: Нет доступа к буферу обмена - невозможно изменить его кодировку!')); Exit; inc(attemptCount); until isClipboardOpened; clipHandle := Clipboard.GetAsHandle(CF_UNICODETEXT); dataPtr := GlobalLock(clipHandle); if (dataPtr <> nil) then dataSize := GlobalSize(clipHandle); ZeroMemory(@textBuf, sizeof(textBuf)); CopyMemory(@textBuf, dataPtr, dataSize); SetString(str, textBuf, dataSize); str := Trim(str); Clipboard.AsText := str; _isClipboardChangeRequired := false; OutputDebugString(PChar('Clipboard encoding converted!')); finally GlobalUnlock(clipHandle); Clipboard.Close();

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question . Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers .