开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 6993|回复: 21
收起左侧

易语言windows开发从入门到死亡:第二章.

[复制链接]
结帖率:100% (1/1)
发表于 2016-12-21 15:05:27 | 显示全部楼层 |阅读模式   北京市北京市
本帖最后由 ockdieso 于 2016-12-21 15:20 编辑

易语言windows开发从入门到死亡:第二章.ASCII与Unicode
这章的内容主要是讲ASCIIUnicode.作为模块 死的一个铺垫.
上次写的被人吐槽.可是你们想过没有.模块是一行代码就能搞定了,winhttp缺需要很大的篇幅来讲.我估计就算真的写出来了.只要看到教程长度就懒得去看了.
不扯了,开讲.还是先搬内容过来!
几乎所有电脑系统都支持基本拉丁字母,并各自支持不同的其他编码方式。Unicode为了和它们相互兼容,其首256字符保留给ISO 8859-1所定义的字符,使既有的西欧语系文字的转换不需特别考量;并且把大量相同的字符重复编到不同的字符码中去,使得旧有纷杂的编码方式得以和Unicode编码间互相直接转换,而不会丢失任何信息。举例来说,全角格式区段包含了主要的拉丁字母的全角格式,在中文、日文、以及韩文字形当中,这些字符以全角的方式来呈现,而不以常见的半角形式显示,这对竖排文字和等宽排列文字有重要作用。
接下来是ASCII
在计算机中,所有的数据在存储和运算时都要使用二进制数表示(因为计算机用高电平和低电平分别表示1和0),例如,像a、b、c、d这样的52个字母(包括大写)、以及0、1等数字还有一些常用的符号(例如*、#、@等)在计算机中存储时也要使用二进制数来表示,而具体用哪些二进制数字表示哪个符号,当然每个人都可以约定自己的一套(这就叫编码),而大家如果要想互相通信而不造成混乱,那么大家就必须使用相同的编码规则,于是美国有关的标准化组织就出台了ASCII编码,统一规定了上述常用符号用哪些二进制数来表示。
美国标准信息交换代码是由美国国家标准学会(AmericanNational Standard Institute , ANSI )制定的,标准的单字节字符编码方案,用于基于文本的数据。起始于50年代后期,在1967年定案。它最初是美国国家标准,供不同计算机在相互通信时用作共同遵守的西文字符编码标准,它已被国际标准化组织(International Organization for Standardization, ISO)定为国际标准,称为ISO 646标准。适用于所有拉丁文字字母。

关于ASCIIUnicode到底是什么.自行百度,这里就不多讲.


本帖被以下淘专辑推荐:

  • · 666|主题: 11, 订阅: 0
结帖率:100% (1/1)
 楼主| 发表于 2016-12-21 15:07:27 | 显示全部楼层   北京市北京市
在易语言的环境中.所有API函数只要是有AW之分的.建议一律全部走A版本
我这样说你肯定会懵逼,看个实例
QQ截图20161221131739.png
VC++的环境中.你使用MessageBox函数,IDE会自动调整版本.我这里设置的是Unicode.所以直接默认走了Unicode.
但是.易语言却并不会默认走任何一个版本.先看段代码
QQ图片20161221150552.png
运行
QQ图片20161221150607.png
然后修改库中对应名
QQ图片20161221150635.png
QQ图片20161221150642.png

回复 支持 反对

使用道具 举报

结帖率:100% (1/1)
 楼主| 发表于 2016-12-21 15:10:06 | 显示全部楼层   北京市北京市
在我的印象中易语言貌似有一个默认的走A版本.但是我测试之后发现并没有,这里我还没有过多的去测试.但是我们不加A或者W无法找到该命令
这里有一个地方我需要详细讲一讲.实际上,MessageBox这个函数根本不存在.是的,这个函数压根就没有.有的只是一个MessageBoxAMessageBoxW.MessageBox是不存在的,我们上个软件瞅瞅就清楚了
QQ图片20161221150835.png
这里可以很清晰的看到
EX版本,A版本,W版本.但是就是没有MessageBox.到这里,就很清晰了.也就是说,微软这个 子压根就没有导出这个函数.这个函数实际上也并不存在,要么A.要么W.但是在VC++环境中.头文件直接宏定义了.在我们的易语言环境中,我们则需要手动加上AorW.但是我建议,一律走A.为什么?
QQ图片20161221150842.png
QQ图片20161221150848.png
QQ图片20161221150853.png
消息框成功的弹出了.但是却并没有显示应该显示的内容.原因也很简单你在易语言IDE环境下写的全是ASCII…你把ASCII字符丢给W版本去处理.当然会乱码
不过这个问题上有很多疑点.深究下去会非常麻烦而且意义不算很大.其问题就在于为什么ASCII版本能显示中文.大概比较能让人信服的观点是GBK或者2312等兼容ASCII,也就是前127位是一样的.所以易语言使用A版本不会出现乱码.而易语言无法显示UTF-8的字符.这点上也让人更加能相信一些.不过具体内部到底如何,我不想去做一个深究.因为意义并不是很大.这里对于新手来说,只需要知道.A一律用A版本即可,那么问题来了.如果没有A该肿么办???
这就是我们必须要讲的内容了.ASCIIUnicode转换
这里win提供了2API
MultiByteToWideChar
WideCharToMultiByte
精易模块的源码我看过.你们经常用到的ASCIIUNICODE来回转换.用的也是该函数
这次我来仔细给你们讲讲,2个函数到底如何使用

回复 支持 反对

使用道具 举报

结帖率:100% (1/1)
 楼主| 发表于 2016-12-21 15:11:29 | 显示全部楼层   北京市北京市
先由窄(ASCII)到宽(Unicode).我大概给你们翻译一下函数原型.后面翻译的易语言类型不是100%正确,但是一定是可用的
int MultiByteToWideChar(
  UINT CodePage, //整数型
  DWORD dwFlags, //整数型
  LPCSTR lpMultiByteStr,// 文本型
  int cbMultiByte,//整数型
  LPWSTR lpWideCharStr,//字节集
  int cchWideChar//整数型
);函数原型从MSDN搬的.百度百科有翻译.这个我们暂时先搬过来
CodePage:指定执行转换的字符集,这个参数可以为系统已安装或有效的任何字符集所给定的值。你也可以指定其为下面的任意一值:
CP_ACPANSI字符集;CP_MACCPMacintosh代码页;CP_OEMCPOEM代码页;
CP_SYMBOL:符号字符集(42);CP_THREAD_ACP:当前线程ANSI代码页;
CP_UTF7:使用UTF-7转换;CP_UTF8:使用UTF-8转换。
第一个参数.在易语言中.如果你只是需要宽窄转换.那么就填CP_ACP.这个位置可以直接写死,以后都不需要变.不过这个CP_ACPVC++宏定义.跟上次的内容一样.VS直接跟进去看 QQ图片20161221151104.png
OK.0
QQ图片20161221151109.png
dwFlags:一组位标记用以指出是否未转换成预作或宽字符(若组合形式存在),是否使用象形文字替代控制字符,以及如何处理无效字符。你可以指定下面是标记常量的组合,含义如下:
MB_PRECOMPOSED:通常使用预作字符——就是说,由一个基本字符和一个非空字符组成的字符只有一个单一的字符值。这是缺省的转换选择。不能与
MB_COMPOSITE值一起使用。
MB_COMPOSITE:通常使用组合字符——就是说,由一个基本字符和一个非空字符组成的字符分别有不同的字符值。不能与MB_PRECOMPOSED值一起使用。
MB_ERR_INVALID_CHARS:如果函数遇到无效的输入字符,它将运行失败,且GetLastErro返回ERROR_NO_UNICODE_TRANSLATION值。
MB_USEGLYPHCHARS:使用象形文字替代控制字符。
组合字符由一个基础字符和一个非空字符构成,每一个都有不同的字符值。每个预作字符都有单一的字符值给基础/非空字符的组成。在字符è中,e就是基础字符,而重音符标记就是非空字符。
函数的缺省动作是转换成预作的形式。如果预作的形式不存在,函数将尝试转换成组合形式。
标记MB_PRECOMPOSEDMB_COMPOSITE是互斥的,而标记MB_USEGLYPHCHARSMB_ERR_INVALID_CHARS则不管其它标记如何都可以设置。
直接填0(一般不使用这些标志,故取值为0时。)
后面4个是重点.也就是前面2个给0.只管后面这4
lpMultiByteStr:指向将被转换字符串的字符。
cchMultiByte:指定由参数lpMultiByteStr指向的字符串中字节的个数。如果lpMultiByteStr指定的字符串以空字符终止,可以设置为-1(如果字符串不是以空字符中止,设置为-1可能失败,可能成功),此参数设置为0函数将失败。
lpWideCharStr:指向接收被转换字符串的缓冲区。
cchWideChar:指定由参数lpWideCharStr指向的缓冲区的宽字符个数。若此值为零,函数返回缓冲区所必需的宽字符数,在这种情况下,lpWideCharStr中的缓冲区不被使用。

回复 支持 反对

使用道具 举报

结帖率:100% (1/1)
 楼主| 发表于 2016-12-21 15:13:07 | 显示全部楼层   北京市北京市
QQ图片20161221151104.png
该函数在Kernel32.DLL中被导出
QQ图片20161221151109.png
这个MSDN没写,我也有点懵逼去百度了一下才知道的
返回值:
如果函数运行成功,并且cchMultiByte不为零,返回值是由lpMultiByteStr指向的缓冲区中写入的字节数;重点就在这里了,这里会涉及到一个内存分配的问题.所以必须知道需要多大的长度.
如果函数运行成功,并且cchMultiByte为零,返回值是接收到待转换字符串的缓冲区所必需的字节数。(此种情况用来获取转换所需Char的个数)
接下来开始调用
QQ图片20161221151238.png
前两个填0没意见,第三个参数直接填要转换的ASCII文本即可.第四个参数-1.第五个参数为转换后的.最后一个参数填0.
这样调用的意义在于该函数的返回值,我们必须知道转换后的长度是多少.并且我们需要手动分配出该长度.VC++,也必须动态分配(new)或者提前分配.
然后,我们拿到返回值的长度后.我们才开始转换
QQ图片20161221151244.png

回复 支持 反对

使用道具 举报

结帖率:100% (1/1)
 楼主| 发表于 2016-12-21 15:15:08 | 显示全部楼层   北京市北京市
-------------------
    调用格式: 〈字节集〉 取空白字节集 (整数型 零字节数目)- 系统核心支持库->字节集操作
    英文名称:SpaceBin
    返回具有特定数目0 字节的字节集。本命令为初级命令。
    参数<1>的名称为“零字节数目”,类型为“整数型(int)”。
操作系统需求:WindowsLinux
这个命令是必须的.因为win提供的该函数比较扯.他需要你提供的其实是一个指针.然后他会去把转换后的字符串.memcpy拷贝过去.你必须提前申请这段内存.才有地方存放.而易语言这条命令干了2件事
第一.分配给你你需要的大小.也就是参数1.
第二.ZeroMemory.将申请的内存中.全部清零
所以此命令是必须的.我们第二次调用.前两个参数依旧是0.你就把这22B当做是占位符好了….
第三个参数.我们依旧填之前的文本.注意.这个文本不可有改动!你可以这样想想,老子帮你计算好了长度,还帮你分配好了内存.最后你跟老子说.之前的文本不要了.换一个???
第四个参数.依旧-1待会具体细讲
第五个参数.填刚刚分配好的字节集
第六个参数.填上我们刚刚计算出来的长度
OK.最后用W版本函数走一遍
QQ图片20161221151104.png
QQ图片20161221151109.png
QQ图片20161221151238.png
OK.完成了

回复 支持 反对

使用道具 举报

结帖率:100% (1/1)
 楼主| 发表于 2016-12-21 15:19:28 | 显示全部楼层   北京市北京市
本帖最后由 ockdieso 于 2016-12-21 15:30 编辑

这个时候回头讲一讲之前那4个参数.
记住.看我的教程,我在需要讲的时候.会很细很细.会很深很深.感觉有点 污 呢这话….
好吧.别小看那4个参数.里面还有不少内容.别觉得2个变量和-1就是固定的
我们先看另一段代码.
QQ图片20161221151104.png
QQ图片20161221151109.png
QQ图片20161221151238.png 这就有意思了 哈 哈 哈 . 字节集出现乱码了
这个时候.再把参数搬出来吧!
lpMultiByteStr:指向将被转换字符串的字符。
这个指向被转换的字符串.这个无需多言.但是之前我填的文本型.现在填字节集.但是到文本就出错了.为什么?
cchMultiByte:指定由参数lpMultiByteStr指向的字符串中字节的个数。如果lpMultiByteStr指定的字符串以空字符终止,可以设置为-1(如果字符串不是以空字符中止,设置为-1可能失败,可能成功),此参数设置为0函数将失败。
注意,这句指定的字符串以空字符终止,可以设置为-1.也就是说,我们可以直接设置为-1让他去自动计算.但前提是以空字符终止(MSDN原文为Ifthis value is –1, the string is assumed to be null terminated and the length iscalculated automatically.)
lpWideCharStr:指向接收被转换字符串的缓冲区。
这个上面已经说过了.必须提前分配内存.该函数不负责申请内存
cchWideChar:指定由参数lpWideCharStr指向的缓冲区的宽字符个数。若此值为零,函数返回缓冲区所必需的宽字符数,在这种情况下,lpWideCharStr中的缓冲区不被使用。
也就是说.该值为0的时候.返回缓冲区所必需的宽字符数.也就是我们需要的长度.所以我们第一次获取长度时.该函数填0
但是为什么乱码了?看上去好像一切都没错?
很简单.只需要一点点改动.这段代码就没事了
QQ图片20161221151244.png
到字节集之后.加上{0},就这么简单.但是为什么文本型就不需要加0.字节集就需要加个0?
这个问题留给你们自己思考吧 哈 哈 哈
等到下一章入门到死亡的时候.我会写出来为什么
我讲的应该是非常细致了.以至于WideCharToMultiByte这个函数都不需要讲解了
你们可以自己动动手吧.把转换完成的宽字符.再给丫转回去然后用A版本消息框输出试试看
最后.附带给你们一段精易模块中转换的源代码.有兴趣可以自行思考,其实他这么写.我也没太看懂.你们有兴趣可以@写这段代码的人,问问看为啥
QQ图片20161221151656.png
好了.这章就到这里结束了.下一期可能会做模块去 死系列的winhttp访问.那应该是个大篇幅.因为提供的函数还蛮多的winhttp必须以Unicode宽字符.所以这章的铺垫没办法少
回复 支持 反对

使用道具 举报

结帖率:100% (26/26)
发表于 2016-12-21 15:47:35 | 显示全部楼层   浙江省杭州市

936表示简体中文

标准的文本会以\0结尾   所以转换出来的unicode末尾会有2个\0    非标准也就是把这两个去掉的意思

    // 计算需要的宽字符数(MultiByteToWideChar的最后一个参数如果给0,则返回需要的宽字符数,包括末尾的'\0')  
    // 如果第四个参数给-1,那么MultiByteToWideChar会自动计算szAnsi的长度  

一个ansi占两个字节,所以返回长度乘以2
楼主加油    持续关注WINHTTP API。


回复 支持 反对

使用道具 举报

结帖率:85% (22/26)

签到天数: 15 天

发表于 2016-12-21 15:56:02 | 显示全部楼层   重庆市重庆市
真正的干货。。支持楼主。
回复 支持 反对

使用道具 举报

结帖率:100% (1/1)
 楼主| 发表于 2016-12-21 15:58:40 | 显示全部楼层   北京市北京市
junkboy 发表于 2016-12-21 15:47
936表示简体中文

标准的文本会以\0结尾   所以转换出来的unicode末尾会有2个\0    非标准也就是把这两 ...

你这写的人家都不需要思考了= =
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 诚聘英才| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报电话0663-3422125,QQ: 800073686,邮箱:800073686@b.qq.com
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备12094385号-1) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表