[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[技术讨论] [探讨]Perl的Win32::Clipboard Set写入剪切板乱码问题

环境 Perl (v5.16.3) built for MSWin32-x86
单独开帖,涉及到修改XS文件

    乱码现象:Win32::Clipboard复制中文字符到剪切板乱码
    当时的解决办法就是设置系统默认输入法为中文。但是我不希望每次打开终端、所有应用程序都
  是默认中文。解决该问题的页面链接如下:
  https://www.mail-archive.com/libwin32%40perl.org/msg00605.html
  如果你不能翻墙,请看这里:
  https://rt.cpan.org/Public/Bug/Display.html?id=76042
  点击右下角的: 下载 Win32-Clipboard-0.57.diff.txt

  PO主增加了USet 函数 以及 UGet 函数,并且提供了一份由diff命令生成的对比文件 diff.txt ,
  上面显示是0.56 和0.57的对比,实际上CPAN 上的0.57版本是没有USet函数的,这个版本是
  作者自己加上去的,所以还是要自己改。

首先下载 Win32-Clipboard-0.56.tar.gz
解压后通过patch命令对文件进行修改,或者手工修改clipboard.xs:

在470行插入
  1. void
  2. USet(text)
  3.     SV *text
  4. PPCODE:
  5.     HANDLE myhandle;
  6.     HGLOBAL hGlobal;
  7.     STRLEN leng;
  8.     U8 *str = (U8*) SvPV(text, leng);
  9.     if ( hGlobal = GlobalAlloc(GMEM_DDESHARE, (leng+2)*sizeof(char)*2) ) {
  10.         /* here we encode UTF16-LE from UTF8, using perl API */
  11.         wchar_t *szString = (wchar_t *) GlobalLock(hGlobal);
  12.     if(SvUTF8(text)) {
  13.         /* indeed, we have utf8 data */
  14.         U8 * const send = str + leng;
  15.         STRLEN ulen;
  16.         while (str < send) {
  17.         *szString++ = (wchar_t)utf8_to_uvchr(str, &ulen);
  18.         str += ulen;
  19.         }
  20.     } else {
  21.         /* we have raw data, no encoding to UTF8, so converting
  22.          * binarily means appending waw '\0' to each char */
  23.         U8 * const send = str + leng;
  24.         while (str < send) {
  25.         *szString++ = (wchar_t) *str++;
  26.         }
  27.     }
  28.     *szString = '\0';
  29.         GlobalUnlock(hGlobal);
  30.         if ( OpenClipboard(NULL) ) {
  31.             EmptyClipboard();
  32.             myhandle = SetClipboardData(CF_UNICODETEXT, (HANDLE) hGlobal);
  33.             CloseClipboard();
  34.             if ( myhandle ) {
  35.                 XSRETURN_YES;
  36.             } else {
  37.                 XSRETURN_NO;
  38.             }
  39.         } else {
  40.             GlobalFree(hGlobal);
  41.             XSRETURN_NO;
  42.         }
  43.     } else {
  44.         XSRETURN_NO;
  45.     }
复制代码
  1. void
  2. UGet()
  3. PPCODE:
  4.     HANDLE myhandle;
  5.     if(OpenClipboard(NULL)) {
  6.     EXTEND(SP,1);
  7.     if(myhandle = GetClipboardData(CF_UNICODETEXT)) {
  8.         /* here we decode UTF16-LE into UTF8, using perl API */
  9.         wchar_t *wcmyh = (wchar_t*)myhandle;
  10.             int i, len = wcslen(wcmyh);
  11.             SV *sv = newSV(len * UTF8_MAXBYTES +1);
  12.         SvPOK_on(sv);
  13.             U8 *e = (U8*) SvPVX(sv), *e0 = e;
  14.         for (i=0; i<len; i++) {
  15.         e = uvuni_to_utf8(e, wcmyh[i]);
  16.         }
  17.         *e = 0;
  18.         SvCUR_set(sv, e-e0);
  19.         SvUTF8_on(sv);
  20.         ST(0) = sv_2mortal(sv);
  21.     } else
  22.         XST_mNO(0);
  23.     CloseClipboard();
  24.     XSRETURN(1);
  25.     } else {
  26.     XSRETURN_NO;
  27.     }
复制代码
  1. long
  2. IsText(...)
  3. CODE:
  4.         RETVAL = (long) IsClipboardFormatAvailable(CF_TEXT);
  5. OUTPUT:
  6.         RETVAL
复制代码
后面插入:
  1. long
  2. IsUText(...)
  3. CODE:
  4.     RETVAL = (long) IsClipboardFormatAvailable(CF_UNICODETEXT);
  5. OUTPUT:
  6.     RETVAL
复制代码
然后
>perl Makefile.pl
>dmake
>dmake test
>dmake install

即可使用 USet 函数,示例脚本1(保存为utf-8格式):
use Win32::Clipboard;
use utf8;
$str = "中文abc";
Win32::Clipboard::USet($str);

返回列表