cnCalc计算器论坛

 找回密码
 注册
搜索
查看: 74110|回复: 78

[fx-9860/9750] fx-9860G SDK开发从入门到实践

[复制链接]
发表于 2011-7-30 12:06:04 | 显示全部楼层 |阅读模式
第一章pdf整理版在19L
第二章 入门部分 pdf在22L

fx-9860G SDK开发从入门到实践

作者 Anderain Lewis (diameter)
QQ:1582163328
前言
首先说明,这个系列不会对C语言进行讲解,对于C的语法与工程文件结构,请自行查看有关书籍。
再次推荐几本书:
重点讲解C的书籍:
《K&R》(既《The C Programming Language》)
清华大学出版社的《C语言程序设计》
陈正冲的《C语言深度剖析》
林锐《高质量C/C++编程指南》
……
重点讲解数据结构、算法的书籍:
Mark Allen Weiss《Data Structures and Algorithm Analysis in C》
Beautiful Code》(作者好多的……)
……
对于不懂C的人,我的建议就一个:现在传统的IDE下把C的基本功练好,掌握标准库的用法,再来学SDK是很简单的。
推荐些IDE:
Visual C++ 6.0(不是很推荐.net版本的VC++)
TC 2.0 以上版本(3.0版本支持C++)
MinGW (GCC的一个Windows替代品)

好了,如果你觉得C的基础打好了,那么跟我一起踏上征途吧!

第一章:什么叫做——显示(Bdisp_)
首先你的手头应该有CASIO fx-9860G SDK与完整的说明文档(pdf文件)
里面应该有以下文件
C Standard Libraries.pdf 介绍C语言的标准库,灰色标注的部分是9860SDK不支持的函数
fx9860g_sdk_starters_guide.pdf 简单介绍SDK(如何安装,如何运行,模拟器的区别)
fx-9860G Character Set.pdf 介绍9860SDK的特殊字符集(与ASCII的区别),另外还有双字节字符
fx-9860G Key Code List.pdf 介绍9860SDK的按键宏
fx-9860G Libraries.pdf 介绍9860SDK的库函数
Installing_Add-in.pdf 介绍如何安装Add-in
SHC Manual.PDF 介绍9860SDK使用的编译器(如何使用C、C++以及汇编、代码优化等内容)(C++与汇编不在本文讨论范围之内)
我们目前只使用《fx-9860G Libraries》这一个参考手册
第一节 DD与VRAM
使用浏览工具打开fx-9860G Libraries,可以看到目录,前面有长长的一串以“Bdisp_”开头的函数。这些都是与绘图、显示有关的。这些函数顾名思义望文生义(某管理注:错用成语),很容易推断用途。我们这一节主要讨论这些函数名称的后缀——DD与VRAM
参看函数的说明,我们知道,DD(Display Driver)是显示驱动,VRAM是显存。
这两者之间有什么关联呢???
我们写一个程序来看一下。

  1. #include "fxlib.h"
  2. int AddIn_main(int isAppli, unsigned short OptionNum)
  3. {
  4.     unsigned int key;
  5.     int i;
  6.     Bdisp_AllClr_DDVRAM();
  7.     for (i=0;i<32;++i){
  8.         Bdisp_SetPoint_DD   (0,i,1);
  9.         Bdisp_SetPoint_VRAM (12,i,1);
  10.     }
  11.     Sleep(1000);
  12.     while(1){
  13.         GetKey(&key);
  14.     }
  15.     return 1;
  16. }
  17. #pragma section _BR_Size
  18. unsigned long BR_Size;
  19. #pragma section
  20. #pragma section _TOP
  21. int InitializeSystem(int isAppli, unsigned short OptionNum){
  22.     return INIT_ADDIN_APPLICATION(isAppli, OptionNum);
  23. }
  24. #pragma section
复制代码
这是一段可以完整编译的程序。其中Sleep函数让程序暂停(参数的单位是毫秒),SetPoint画点
运行效果很明显,现有一条直线,暂停一秒后变到了右边根据代码,我们知道,
Bdisp_SetPoint_DD   (0,i,1);  这个函数绘制的线条在左
Bdisp_SetPoint_VRAM (12,i,1); 这个函数绘制的线条在右
现在我们,就明白了VRAM与DD的关系了。
对DD的操作可以直接显示,对VRAM的操作不能直接显示。对VRAM的操作需要等系统强制刷新显存,将VRAM的内容送入DD才能显示。
我们可爱的GetKey(unsigned int*)函数就有清空显存并刷新DD的功能。
如果我们想让对VRAM的操作直接显示呢?老用GetKey不好吧,我们可以使用Bdisp_PutDisp_DD,来将VRAM里面的东西放到DD里面去,就显示出来啦。
稍作修改:

  1. for (i=0;i<32;++i){
  2.     Bdisp_SetPoint_DD   (0,i,1);
  3.     Bdisp_SetPoint_VRAM (12,i,1);
  4.     Bdisp_PutDisp_DD();
  5. }
复制代码
再运行一下,发现只有右边的线了(可怜的DD刚画出来就被清除了)
如果你觉得不保险,总想把东西画出来的话……使用带DDVRAM后缀的函数好了
好了,第一节到此结束。

评分

参与人数 11金钱 +124 专家 +2 贡献 +2 收起 理由
Wudy + 1
urill + 1 优秀文章
noivan + 3 支持!SDK就是效率高
月与映之皮丘 + 2 优秀文章
GWHBOB + 2 热心助人

查看全部评分

发表于 2011-7-30 12:10:39 | 显示全部楼层
顶起,支持diameter
 楼主| 发表于 2011-7-30 13:48:39 | 显示全部楼层
本帖最后由 diameter 于 2011-8-1 09:11 编辑

第三节:图形函数注解

图形的初级内容就到这里了,下面把fxlib.h提供的图形相关的库函数都注解一下吧

Bdisp_AllClr_DD/ Bdisp_AllClr_VRAM/ Bdisp_AllClr_DDVRAM
全部清除(DD、VRAM或DD VRAM一块)(见第一节)

Bdisp_AreaClr_DD/ Bdisp_AreaClr_VRAM/ Bdisp_AreaClr_DDVRAM
区域清除(DD、VRAM或DD VRAM一块)(见第一节)

可以使用封装的函数area_clear
sel取值:0.清除区域,1.画一个框,其他.清除区域+画框

  1. void area_clear (int left,int top,int right,int bottom,int sel)
  2. {
  3.     DISPBOX box;
  4.     box.left = left;box.top = top;box.right = right;box.bottom = bottom;
  5.     if (sel != 1)
  6.         Bdisp_AreaClr_DDVRAM (&box);
  7.     if (sel != 0){
  8.         Bdisp_DrawLineVRAM (box.left,box.top,box.right,box.top);
  9.         Bdisp_DrawLineVRAM (box.left,box.bottom,box.right,box.bottom);
  10.         Bdisp_DrawLineVRAM (box.left,box.top,box.left,box.bottom);
  11.         Bdisp_DrawLineVRAM (box.right,box.top,box.right,box.bottom);
  12.     }
  13. }
复制代码
Bdisp_AreaReverseVRAM
VRAM区域反色

Bdisp_GetDisp_DD/ Bdisp_GetDisp_VRAM
把DD的内容存入VRAM/把VRAM的内容存入DD

Bdisp_PutDisp_DD
强制将VRAM送入DD以显示

Bdisp_SetPoint_DD/ Bdisp_SetPoint_VRAM/ Bdisp_SetPoint_DDVRAM
画一个点(DD、VRAM或DD VRAM一块)(见第一节)
最后一个参数决定是画点还是清除点

Bdisp_GetPoint_VRAM
从VRAM获取一个点(1 or 0)

Bdisp_WriteGraph_DD/ Bdisp_WriteGraph_VRAM/ Bdisp_WriteGraph_DDVRAM
(见第一节)

Bdisp_ReadArea_DD / Bdisp_ReadArea_VRAM
将DD/VRAM的一部分读入一个字符数组

Bdisp_DrawLineVRAM
Bdisp_ClearLineVRAM
画线、清除线

locate
定位Print、PrintC、PrintRev、PrintRevC输出的位置(原文是光标???)

Print
PrintRev
输出/反色输出字符串

PrintC
PrintRevC
输出/反色输出字符串的首字符
附带一个Printf,需要stdarg.h
关于变参函数与参数堆栈后面章节讲解

  1. int Printf(char *cpFormat, ...)
  2. {
  3.     int len;
  4.     char cpBuffer[512];

  5.     va_list pArgList;
  6.     va_start(pArgList, cpFormat);
  7.     len = vsprintf(cpBuffer, cpFormat, pArgList);
  8.     va_end(pArgList);
  9.     Print((unsigned char*)cpBuffer);

  10.     return len;
  11. }
复制代码
PrintLine
PrintRLine
输出/反色输出一行字符串,最后一个参数决定行的最大字符数

PrintXY
在任意位置输出字符串,最后一个参数决定是否反色

PrintMini
在任意位置使用小字符输出字符串,最后一个参数决定绘制方式
MINI_OVER      覆盖
MINI_OR        不覆盖
MINI_REV       反色覆盖
MINI_REVOR     反色不覆盖

SaveDisp
RestoreDisp
保存/显示显示屏图
唯一的参数只能为
SAVEDISP_PAGE1
SAVEDISP_PAGE2
SAVEDISP_PAGE3

PopUpWin
画一个窗口(与系统弹出的相同)
唯一的参数决定窗口能包含的行数
 楼主| 发表于 2011-7-30 13:50:24 | 显示全部楼层
本帖最后由 diameter 于 2011-7-30 13:54 编辑

第一章入门部分完毕,大家可以提问了

(给个精吧~~~,毕竟花一个多小时写的)
发表于 2011-7-30 14:03:02 | 显示全部楼层
当前权限无法加分,但我能前排支持!
发表于 2011-7-30 15:44:24 | 显示全部楼层
直径V5。好东西。接了。谢。
发表于 2011-7-30 16:37:55 | 显示全部楼层
SDK教程非常有价值,希望能继续写下去。
发表于 2011-7-30 19:27:44 | 显示全部楼层
强烈要求管理员给加精!小饕强者,以后绝对是个出色的程序员!我一直跟着你学习
 楼主| 发表于 2011-7-30 19:57:16 | 显示全部楼层
我现在在纠结写不写SH ASM的内容……
发表于 2011-7-30 21:04:07 | 显示全部楼层
写完了建议置顶。
发表于 2011-7-30 21:38:44 | 显示全部楼层
太好了,学习学习!!
建议全写完后发布word版
发表于 2011-7-31 08:49:39 | 显示全部楼层
好东西,感谢楼主
发表于 2011-7-31 12:44:45 | 显示全部楼层
IMB_WRITEMODIFY_MESH    = 3 网格绘制(像素间隔点绘制)
请给个示范,谢谢

评分

参与人数 1金钱 +2 收起 理由
diameter + 2 见DPainter(在资源区)

查看全部评分

 楼主| 发表于 2011-7-31 13:31:05 | 显示全部楼层
第一章 实践部分

第一节 先从画个圆说起

fxlib.h中并没有提供画圆的函数,这样,我们自己写一个——借此也讨论一些技术的问题

首先我们应该知道圆的参数方程:

  1. x = r * cos(t) + h
  2. y = r * sin(t) + k

  3. (h,k)为圆心坐标,r为半径。t∈[0,2*pi)
复制代码
由此我们就可以写一个画圆的函数了

  1. void circle1(int cx,int cy,int r)
  2. {
  3.     const float PI = 3.1415926535,step = PI/48.0;
  4.     int x,y,px,py;
  5.     float t;
  6.     px = cx + r;
  7.     py = cy;
  8.     for (t = step;t<2 * PI;t += step){
  9.         x = cosf(t) * r + cx;
  10.         y = sinf(t) * r + cy;
  11.         Bdisp_DrawLineVRAM(x,y,px,py);
  12.         px = x,py = y;
  13.     }
  14.     x = cx + r;
  15.     y = cy;
  16.     Bdisp_DrawLineVRAM(x,y,px,py);
  17. }
复制代码
注意啊,我们这里用的自变量t是float类型的,所调用的函数不是sin、cos而是sinf与cosf,
所以你要包含的头文件是<mathf.h>而非<math.h>

运行一下,circle1(63,31,20);
效果貌似还可以(比PRGM的快多了,至少没有让人看见停顿),其实这个函数效率低的吓人
每次调用三角函数都要对浮点数进行压栈,效率很低(如果是double型的话会更慢)。只是
我们看不见而已。

所以在这里我们要讨论一个严肃的话题——要速度,还是要内存

(我原来是搞win32游戏编程的^_^)所以我知道一种省时间但是浪费内存的方法(win32平台
的话不算浪费),那就是使用查找表——如果你想多次使用查找表的话。
如此这般

  1. const float PI = 3.1415926535;
  2. float sin_table[360];
  3. float cos_table[360];
  4. void recalc_table()
  5. {
  6.     int t;
  7.     for (t = 0;t < 360 ;++t){
  8.         sin_table[t] = sinf(PI*t/180.0);
  9.         cos_table[t] = cosf(PI*t/180.0);
  10.     }
  11. }
  12. void circle2(int cx,int cy,int r)
  13. {
  14.     int x,y,px,py,t;
  15.     px = cx + r;
  16.     py = cy;
  17.     for (t = 0;t<360;t++){
  18.         x = cos_table[t] * r + cx;
  19.         y = sin_table[t] * r + cy;
  20.         Bdisp_DrawLineVRAM(x,y,px,py);
  21.         px = x,py = y;
  22.     }
  23.     x = cx + r;
  24.     y = cy;
  25.     Bdisp_DrawLineVRAM(x,y,px,py);
  26. }
复制代码
在程序初始化的时候调用一下recalc_table函数,以后所有的跟三角函数有关的都可以调用
查找表它(比如位图旋转、笛卡尔坐标转直角坐标……)
不过这个画的图有看起来有点粗是吧…………
好,改这一行

  1. for (t = 0;t<360;t+=4){
复制代码
这就差不多了哈。这个方法虽说有点浪费内存,但是——它很快,想想,在内存中取一个值
快还是函数反复压栈退栈快?

如果你不相信,可以测试一下

  1. int x = 63,y = 31,i;
  2. unsigned int key;
  3. recalc_table(); // 不要把这个忘了
  4. // loop 1
  5. for (i=0;i<80;++i){
  6.     circle1 (x,y,20+i);
  7.     Bdisp_PutDisp_DD();
  8. }
  9. GetKey(&key);
  10. Bdisp_AllClr_DDVRAM();
  11. // loop 2
  12. for (i=0;i<80;++i){
  13.     circle2 (x,y,20+i);
  14.     Bdisp_PutDisp_DD();
  15. }
  16. GetKey(&key);
复制代码
看看这两个loop哪一个快

其实说到浮点数的问题——你甚至可以使用定点数(超出范围不讨论)

好了这只是给我们的实践开了个小头,就是大家提个醒——有时候速度与内存不可兼得,要依
情况而定。
 楼主| 发表于 2011-7-31 13:33:36 | 显示全部楼层
第一章 实践部分
第二节 一个实心三角形

先不说别的,如果你想用9860 SDK把你的程序的图形界面写的很炫的话,有一样
东西是必须的——画一个实心(填充的)多边形。

看下图,好像做到这一点并不难
triangle1.bmp
图上垂直的红线的意思是按一个方向(比如从左向右)一路用直线填充过去,多
边形就成为实心的了。

上图看上去好像很简单,只要把四条边的解析式求出来不就行了么?那我只能说
你漏了凹四边形。那可就不好玩了。所以,我们把四边形分解成三角形来绘制。

triangle3.bmp
如图,两种四边形都可以分解为两个三角形
但是问题又来了——三角形也画不了啊,填充的时候还是没法计算填充线的位置
于是我们继续向下分割

triangle4.bmp
如图,三角形总能分解成有一条边是水平的两个三角形。这样问题就迎刃而解啦

triangle2.bmp
如图,水平边的两个端点约定为(x1,y1)与(x2,y2),两条非水平边的方程可设为

  1. 已知(x1,y1),(x2,y2),(x3,y3)
  2. 线段1:y = k1 * x + b1
  3. 线段2:y = k2 * x + b2
  4. 可以推出
  5. k1 = (y1 - y3)/(x1 - x3);
  6. k2 = (y2 - y3)/(x2 - x3);
  7. b1 = y1 - k1 * x1;
  8. b2 = y2 - k2 * x2;
复制代码


有人可能会问了,有一条边事垂直的怎么办?那样斜率算出来是±∞啊(在C里确实如此)。
很简单,垂直的话(x1=x3或x2=x3),那一部分就不绘制了,反正垂直了也那边的一部分也
就不存在了。
有人还问了,如果是一个钝角三角形怎么办?不好绘制吧?

看图:
triangle5.bmp
看到红色部分的那个扫描的直线l1没有?画这条直线的时候让x在区间[x2,x3]内不就行了
l的两个端点分别为 (x,k1*x+b1),(x,k2*x+b2)
钝角在左边的也是如此。
好了不多说了,把代码贴上


  1. void draw_horizontal_triangle
  2. (float x1,float y1,float x2,float y2,float x3,float y3)
  3. {
  4.     // (x1,y1)o------o(x2,y2)
  5.     //         \    /
  6.     //          \  /
  7.     //           \/
  8.     //            o(x3,y3)
  9.     float k1,k2,b1,b2;
  10.     int x,y,ty;
  11.     if (y1 != y2) return;
  12.     if (x1>x2){
  13.         float t;
  14.         t = x2;x2 = x1;x1 = t;
  15.     }
  16.     k1 = (y1 - y3)/(x1 - x3);
  17.     k2 = (y2 - y3)/(x2 - x3);
  18.     b1 = y1 - k1 * x1;
  19.     b2 = y2 - k2 * x2;
  20.     if (x1 < x3){
  21.         int t = x3 > x2 ? x2 : x3;
  22.         for (x = x1;x <= t;++x){
  23.             y = k1 * x + b1;
  24.             Bdisp_DrawLineVRAM(x,y1,x,y);
  25.         }
  26.     }else{
  27.         for (x = x3;x <= x1;++x){
  28.             y  = k1 * x + b1;
  29.             ty = k2 * x + b2;
  30.             Bdisp_DrawLineVRAM(x,ty,x,y);
  31.         }
  32.     }
  33.     if (x3 < x2){
  34.         for (x = x3 > x1 ? x3 : x1;x <= x2;++x){
  35.             y = k2 * x + b2;
  36.             Bdisp_DrawLineVRAM(x,y2,x,y);
  37.         }
  38.     }else{
  39.         for (x = x2;x <= x3;++x){
  40.             y  = k1 * x + b1;
  41.             ty = k2 * x + b2;
  42.             Bdisp_DrawLineVRAM(x,y,x,ty);
  43.         }
  44.     }
  45. }
复制代码


将Addin_main改为以下代码

  1. int AddIn_main(int isAppli, unsigned short OptionNum)
  2. {
  3.     unsigned int key;
  4.     Bdisp_AllClr_DDVRAM();
  5.     draw_horizontal_triangle   (24,12,   64,12,   32,32);
  6.     GetKey(&key);
  7.     Bdisp_AllClr_DDVRAM();
  8.     draw_horizontal_triangle   (24,12,   64,12,   0,32);
  9.     GetKey(&key);
  10.     Bdisp_AllClr_DDVRAM();
  11.     draw_horizontal_triangle   (24,12,   64,12,   100,32);
  12.     while(1){
  13.         GetKey(&key);
  14.     }
  15.     return 1;
  16. }
复制代码

测试效果
xtest1.bmp

而最后的任意三角实心三角形就很好写了

  1. void swap (int *a,int *b){int t;t = *a;*a = *b;*b = t;}
  2. void draw_triangle (int x1,int y1,
  3.                     int x2,int y2,
  4.                     int x3,int y3)
  5. {
  6.     if ((x1==x2 && x2==x3) || (y1==y2 && y2==y3)) return;
  7.     if (y2 < y1){
  8.         swap(&x1,&x2);swap(&y1,&y2);
  9.     }
  10.     if (y3 < y1){
  11.         swap(&x3,&x1);swap(&y3,&y1);
  12.     }
  13.     if (y3 < y2){
  14.         swap(&x3,&x2);swap(&y3,&y2);
  15.     }
  16.     if (y1==y2 || y2==y3)
  17.         draw_horizontal_triangle (x1,y1,x2,y2,x3,y3);
  18.     else{
  19.         int new_x = x1 + (int)((float)(y2-y1)*(float)(x3-x1)/(float)(y3-y1));
  20.         draw_horizontal_triangle (new_x,y2,x2,y2,x1,y1);
  21.         draw_horizontal_triangle (x2,y2,new_x,y2,x3,y3);
  22.     }
  23. }
复制代码

测试一下draw_triangle(32,32,127,0,63,63);

xtest2.bmp
好了,纯图形的东西暂时告一段落,下一节我们来一点实际的——一个自定义
的菜单。

评分

参与人数 1金钱 +10 专家 +1 收起 理由
chsi + 10 + 1 精品原创技术贴

查看全部评分

发表于 2011-7-31 15:35:35 | 显示全部楼层
可怜的DD刚画出来就被清除了
我邪恶了。

评分

参与人数 1金钱 +2 收起 理由
diameter + 2 别想歪了

查看全部评分

 楼主| 发表于 2011-8-1 11:26:27 | 显示全部楼层
第一章 实践部分

第三节 美观的菜单

一个美观的多选菜单需要什么呢?一个标题,几个选项,我觉得写这样一个选项数目是
定值的菜单对大家来说并不难。
1.bmp
所以,我们今天写一个可以处理选项数目不定的菜单函数

int pop_menu (char * context[],char *title,int max,int x,int y);
(看见context类型如果觉得眼晕的同学建议去查查“int main(int argc,char *argv[])”)

函数原型有了,我们需要一个画背景的函数,这样前面的area_clear就用上了。

可能有人会问了:菜单的边框大小怎么确定?要是让人一个个去算不是很麻烦么。所以我
们采用让函数自己算的方法:

  1. int width,height,i,l;
  2. height = (max+1) * 8;
  3. width = strlen(title);
  4. for (i=0;i<max;++i){
  5.     l = strlen(context);
  6.     if (l>width) width = l;
  7. }
  8. width *= 6;
复制代码
上面的片段中明显是在title与所有context之间寻找最长的字符串,然后乘以大字符的大小
(大字符尺寸:6*8)
标题要反色,来一个Bdisp_AreaReverseVRAM好了。

另外为了防止误按键导致屏幕无谓的刷新,再加一个变量redraw。

写好的函数如下

  1. int pop_menu (char *context[],char *title,int max,int x,int y)
  2. {
  3.     int width,height,i,l,redraw = 1,index = 0;
  4.     unsigned int key;
  5.     height = (max+1) * 8;
  6.     width = strlen(title);
  7.     for (i=0;i<max;++i){
  8.         l = strlen(context);
  9.         if (l>width) width = l;
  10.     }
  11.     width *= 6;
  12.     area_clear(x,y,x+width+2,y+height+1,2);
  13.     PrintXY (x+1,y+1,(unsigned char*)title,0);
  14.     Bdisp_AreaReverseVRAM (x+1,y+1,x+width+1,y+8);
  15.     while (1){
  16.         if (redraw){
  17.             redraw = 0;
  18.             area_clear(x+1,y+9,x+width+1,y+height,0);
  19.             for (i=0;i<max;++i)
  20.                 PrintXY(x+1,y+1+(i+1)*8,context,0);
  21.             Bdisp_AreaReverseVRAM (x+1,y+1+(index+1)*8,x+width+1,y+(index+2)*8);
  22.         }
  23.         GetKey(&key);
  24.         if (key==KEY_CTRL_UP){
  25.             index--;
  26.             if (index<0) index = max-1;
  27.             redraw = 1;
  28.         }
  29.         else if (key==KEY_CTRL_DOWN){
  30.             index++;
  31.             if (index>=max) index = 0;
  32.             redraw = 1;
  33.         }
  34.         else if (key==KEY_CTRL_EXIT) return -1;
  35.         else if (key==KEY_CTRL_EXE)  return  index;
  36.     }
  37. }
复制代码
在AddIn_main里面添加以下代码进行测试

  1. char *c[] = {"Hit","Throw","Pick up","Run away"};
  2. pop_menu (c,"Select Menu",4,4,4);
复制代码
效果图:
2.bmp
 楼主| 发表于 2011-8-1 11:29:56 | 显示全部楼层
第一章(Bdisp)的内容就到此结束了,中午整理pdf版本。
后面的章节介绍:
第二章 Bfile与控制函数
第三章 实例演练
第四章 SH汇编入门与SH C宏介绍
 楼主| 发表于 2011-8-1 15:00:32 | 显示全部楼层
第一章的pdf版本出炉

fx-9860GSDK开发从入门到实践(1).pdf

142.38 KB, 下载次数: 1250

评分

参与人数 2金钱 +6 收起 理由
l5h5t7 + 3 支持一下。
Cyvre + 3 一定要支持!

查看全部评分

发表于 2011-8-1 15:10:44 | 显示全部楼层
太感谢了!!学习了!!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|cnCalc计算器论坛

GMT+8, 2024-11-21 20:14 , Processed in 0.073693 second(s), 26 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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