打印
[应用相关]

GRAPH-图形控件

[复制链接]
2063|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Beckham_Owen|  楼主 | 2016-7-9 21:08 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本期教程讲解STemWin支持的绘图控件。
    45. 1 绘图件介绍
    45. 2 官方WIDGET_GraphYT实例
    45. 3 使用官方GUIBulder建立Graph控件
    45. 4 总结
45.1 图形控件介绍
    图形控件可用于可视化数据。图形控件的典型应用是显示测量值或函数图形的曲线,可同时显示多条曲线。可使用水平和垂直刻度来标记曲线。可在背景上显示具有不同水平和垂直间距的网格。如果数据阵列不能容纳进图形的可见区域,小工具可自动显示滚动条,从而可在大的数据阵列中进行滚动。
45.1.1 图形控件的结构
    图形控件由不同种类的对象组成:
l 图形控件自身,可以附加数据对象和刻度对象。
l 可选的一个或多个数据对象。
l 可选的一个或多个刻度对象。
    下图显示了图形控件的详细结构:
    截图中每个参数表示的含义如下:

参数
描述
Border
可选边框是图形小工具的一部分。
Frame
数据区四周的细线,是图形小工具的一部分。
Grid
显示在数据区的背景中,是图形小工具的一部分。
Data area
网格和数据对象的显示区域。
Data object(s)
对于每条曲线,应向图形小工具添加一个数据对象。
Appdefined graphic
应用程序定义的一种回调函数,可用于绘制任何应用程序定义的文本和/或图形。
Scrollbar(s)
如果数据对象的范围大于图形小工具的数据区,则图形小工具可自动显示水平和/或垂直滚动条。
Scale object(s)
可附加到图形小工具的水平和垂直刻度。
X-Size
数据区的X尺寸。
Y-Size
数据区的Y尺寸。
45.1.2 创建和删除图形小工具
    创建图形控件的过程如下:
l 创建图形控件并设置所需的属性。
l 创建数据对象。
l 将数据对象附加到图形控件。
l 创建可选的刻度对象。
l 将刻度对象附加到图形控件。
    附加到图形控件后,就不需要通过应用程序来删除数据和刻度对象,而由图形控件完成。
示例
GRAPH_DATA_Handle hData;
GRAPH_SCALE_Handle hScale;
WM_HWIN hGraph;
hGraph = GRAPH_CreateEx(10, 10, 216, 106, WM_HBKWIN, WM_CF_SHOW, 0, GUI_ID_GRAPH0);
hData = GRAPH_DATA_YT_Create(GUI_DARKGREEN, NumDataItems, aData0, MaxNumDataItems);
GRAPH_AttachData(hGraph, hData);
hScale = GRAPH_SCALE_Create(28, GUI_TA_RIGHT, GRAPH_SCALE_CF_VERTICAL, 20);
GRAPH_AttachScale(hGraph, hScale);
/*
Do something with the widget...
*/
WM_DeleteWindow(hGraph);


沙发
Beckham_Owen|  楼主 | 2016-7-9 21:09 | 只看该作者
45.1.3 绘制过程
    如前所述,图形控件由不同部分和 “子”对象组成。以下描述了绘制控件的顺序:
1. 用背景色填充背景。
2. 调用可选的回调例程。例如,这样就能绘制用户定义的网格。
3. 绘制网格 (如已启用)。
4. 绘制数据对象和边框区域。
5. 绘制刻度对象。
6. 调用可选的回调例程。例如,这样就能绘制用户定义的刻度,或一些其他的文本和/或图形。
45.1.4 支持的曲线类型
    显示测量值连续更新的曲线的要求不同于显示具有X/Y坐标的函数图形的要求。因此,控件当前支持2种数据对象,如下表所示:
GRAPH_DATA_XY:此数据对象用于显示由点阵列组成的曲线,对象数据绘制为折线。此数据对象的典型应用是绘制函数图形。
GRAPH_DATA_YT:此数据对象用于显示图形上每个X位置都具有一个Y值的曲线。此数据对象的典型应用是显示测量值连续更新的曲线。

使用特权

评论回复
板凳
Beckham_Owen|  楼主 | 2016-7-9 21:10 | 只看该作者
45.2 官方WIDGET_GraphYT实例
官方的这个实例很好的演示了GraphYT的使用,这个例子在模拟器中的位置:

源码如下(程序中进行了详细的注释):
----------------------------------------------------------------------
File : WIDGET_Graph.c
Purpose : Demonstrates the use of the GRAPH widget
----------------------------------------------------------------------
*/

#include <stdlib.h>
#include <string.h>

#include "DIALOG.h"
#include "GRAPH.h"

/*********************************************************************
*
* Defines
*
**********************************************************************
*/
#define MAX_VALUE 180

/*********************************************************************
*
* Static data
*
**********************************************************************
*/
static GRAPH_DATA_Handle _ahData[3]; /* 定义三种曲线的句柄 */
static GRAPH_SCALE_Handle _hScaleV; /* 垂直放缩的句柄 */
static GRAPH_SCALE_Handle _hScaleH; /* 水平放缩的句柄 */

static I16 _aValue[3];
static int _Stop;

/* 三种曲线的显示颜色 */
static GUI_COLOR _aColor[] = {GUI_RED, GUI_GREEN, GUI_LIGHTBLUE};

/* 对话框资源 */
static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = {
{ FRAMEWIN_CreateIndirect, "Graph widget demo", 0 , 0, 0, 320, 240, FRAMEWIN_CF_MOVEABLE },
{ GRAPH_CreateIndirect, 0, GUI_ID_GRAPH0 , 5, 5, 270, 175 },
{ TEXT_CreateIndirect, "Spacing X:", 0 , 10, 185, 50, 20 },
{ TEXT_CreateIndirect, "Spacing Y:", 0 , 10, 205, 50, 20 },
{ SLIDER_CreateIndirect, 0, GUI_ID_SLIDER0 , 60, 185, 60, 16 },
{ SLIDER_CreateIndirect, 0, GUI_ID_SLIDER1 , 60, 205, 60, 16 },
{ CHECKBOX_CreateIndirect, 0, GUI_ID_CHECK0 , 130, 185, 50, 0 },
{ CHECKBOX_CreateIndirect, 0, GUI_ID_CHECK1 , 130, 205, 50, 0 },
{ TEXT_CreateIndirect, "Border", 0 , 280, 5, 35, 15 },
{ CHECKBOX_CreateIndirect, 0, GUI_ID_CHECK2 , 280, 20, 35, 0 },
{ CHECKBOX_CreateIndirect, 0, GUI_ID_CHECK3 , 280, 40, 35, 0 },
{ CHECKBOX_CreateIndirect, 0, GUI_ID_CHECK4 , 280, 60, 35, 0 },
{ CHECKBOX_CreateIndirect, 0, GUI_ID_CHECK5 , 280, 80, 35, 0 },
{ TEXT_CreateIndirect, "Effect", 0 , 280, 100, 35, 15 },
{ RADIO_CreateIndirect, 0, GUI_ID_RADIO0 , 275, 115, 35, 0, 0, 3 },
{ CHECKBOX_CreateIndirect, 0, GUI_ID_CHECK6 , 180, 185, 50, 0 },
{ CHECKBOX_CreateIndirect, 0, GUI_ID_CHECK7 , 180, 205, 50, 0 },
{ BUTTON_CreateIndirect, "Full Screen", GUI_ID_BUTTON0 , 235, 185, 65, 18 },
{ CHECKBOX_CreateIndirect, 0, GUI_ID_CHECK8 , 235, 205, 70, 0 },
};

/*********************************************************************
*
* _AddValues
*
*/
static void _AddValues(WM_HWIN hGraph) {
int i;
int Add;
int Vz;

/* 通过for语句循环三次给三个数据对象_ahData[i]添加随机数数据 */
for (i = 0; i < GUI_COUNTOF(_aValue); i++) {
Add = rand() % (2 + i * i);
Vz = ((rand() % 2) << 1) - 1;
_aValue[i] += Add * Vz;
if (_aValue[i] > MAX_VALUE) {
_aValue[i] = MAX_VALUE;
} else if (_aValue[i] < 0) {
_aValue[i] = 0;
}

/*
下面的这个函数用于把给定的数据值添加到数据对象。如果该数据对象 “已满”,即意味着它包含的数据项与创建时在参
数MaxNumItems中指定的项数相同,在添加新值前会首先移动一个数据项。因此,向 “已满”对象添加数据项时,第一
个数据项被移出。
*/
GRAPH_DATA_YT_AddValue(_ahData[i], _aValue[i]);
}
}

/*********************************************************************
*
* _UserDraw
*
* 本函数的目的:
* 在绘制之前和绘制之后调用这个函数 ,此函数只是显示字母Temperature
*/
static void _UserDraw(WM_HWIN hWin, int Stage) {

/* 在绘制之后被调用 */
if (Stage == GRAPH_DRAW_LAST) {
char acText[] = "Temperature";
GUI_RECT Rect, RectInvalid;
int FontSizeY;

/* 设置字体 */
GUI_SetFont(&GUI_Font13_ASCII);
FontSizeY = GUI_GetFontSizeY();

/* 得到矩形框的大小 */
WM_GetInsideRect(&Rect);

/* Returns the invalid rectangle of a window in desktop coordinates */
WM_GetInvalidRect(hWin, &RectInvalid);
Rect.x1 = Rect.x0 + FontSizeY;
GUI_SetColor(GUI_RED);
GUI_DispStringInRectEx(acText, &Rect, GUI_TA_HCENTER, strlen(acText), GUI_ROTATE_CCW);
}

}

/*********************************************************************
*
* _ForEach
*
* 这个函数用于隐藏或者显示所有的窗口,除了button,graph和scroll控件
*
*/
static void _ForEach(WM_HWIN hWin, void * pData) {
int Id, FullScreenMode;
FullScreenMode = *(int *)pData;
Id = WM_GetId(hWin);
if ((Id == GUI_ID_GRAPH0) || (Id == GUI_ID_BUTTON0) || (Id == GUI_ID_VSCROLL) || (Id == GUI_ID_HSCROLL)) {
return;
}
if (FullScreenMode) {
WM_HideWindow(hWin);
} else {
WM_ShowWindow(hWin);
}
}

/*********************************************************************
*
* _ToggleFullScreenMode
*
* 这个函数用于设置进入全屏模式与否,进入相应的模式以后需要放大或者缩小控件
*/
static void _ToggleFullScreenMode(WM_HWIN hDlg) {
static int FullScreenMode;
static GUI_RECT Rect;
static unsigned ScalePos;
WM_HWIN hGraph, hButton;
hGraph = WM_GetDialogItem(hDlg, GUI_ID_GRAPH0);
hButton = WM_GetDialogItem(hDlg, GUI_ID_BUTTON0);

/* 取反 */
FullScreenMode ^= 1;

/* 全屏模式 */
if (FullScreenMode) {
/* 进入全屏模式 */
WM_HWIN hClient;
GUI_RECT RectInside;
hClient = WM_GetClientWindow(hDlg);
BUTTON_SetText(hButton, "Back");

/* 相对移动*/
WM_MoveWindow(hButton, 0, 11);
/* 隐藏标题 */
FRAMEWIN_SetTitleVis(hDlg, 0);
/* 得到用户区的坐标 */
WM_GetInsideRectEx(hClient, &RectInside);
/* 返回窗口大小 */
WM_GetWindowRectEx(hGraph, &Rect);
/* 遍历所有的子控件,并且将其隐藏 */
WM_ForEachDesc(hClient, _ForEach, &FullScreenMode); /* Hide all descendants */
/* 设置窗口位置 */
WM_SetWindowPos(hGraph, WM_GetWindowOrgX(hClient), WM_GetWindowOrgX(hClient), RectInside.x1, RectInside.y1);
/* 水平范围值,显示的位置 */
/* 返回的数值是以前的值 */
ScalePos = GRAPH_SCALE_SetPos(_hScaleH, RectInside.y1 - 20);
}
/* 进入正常模式 */
else {
/* 返回到正常模式 */
BUTTON_SetText(hButton, "Full Screen");
WM_MoveWindow(hButton, 0, -11);
WM_ForEachDesc(WM_GetClientWindow(hDlg), _ForEach, &FullScreenMode); /* Show all descendants */
WM_SetWindowPos(hGraph, Rect.x0, Rect.y0, Rect.x1 - Rect.x0 + 1, Rect.y1 - Rect.y0 + 1);
FRAMEWIN_SetTitleVis(hDlg, 1);
GRAPH_SCALE_SetPos(_hScaleH, ScalePos);
}
}

/*********************************************************************
*
* _cbCallback
*
* 对话框回调函数
*/
static void _cbCallback(WM_MESSAGE * pMsg) {
int i, NCode, Id, Value;
WM_HWIN hDlg, hItem;
hDlg = pMsg->hWin;
switch (pMsg->MsgId) {

/* 初始化窗口消息 */
case WM_INIT_DIALOG:

/* 得到相应的句柄 */
hItem = WM_GetDialogItem(hDlg, GUI_ID_GRAPH0);
/* 创建三个数据对象_ahData[i] */
for (i = 0; i < GUI_COUNTOF(_aColor); i++) {
_aValue[i] = rand() % 180;

/* 创建成功的话,返回数据句柄 */
/* 显示的曲线颜色,可以显示的最大数据个数,数据指针,要添加的数据个数 */
_ahData[i] = GRAPH_DATA_YT_Create(_aColor[i], 500, 0, 0);

/* 为绘图控件添加数据对象 */
GRAPH_AttachData(hItem, _ahData[i]);
}

/* 设置绘图属性 */
/* 设置垂直栅格的高度 */
GRAPH_SetGridDistY(hItem, 25);
/* 栅格是否可见 */
GRAPH_SetGridVis(hItem, 1);

/* 固定X轴的栅格 */
GRAPH_SetGridFixedX(hItem, 1);
GRAPH_SetUserDraw(hItem, _UserDraw);

/* 创建和增加垂直范围尺度标签 */
/* 离左边的尺度位置,*/
_hScaleV = GRAPH_SCALE_Create( 35, GUI_TA_RIGHT, GRAPH_SCALE_CF_VERTICAL, 35);
/* 设置标签字体颜色 */
GRAPH_SCALE_SetTextColor(_hScaleV, GUI_RED);
/* 将标签添加到垂直方向 */
GRAPH_AttachScale(hItem, _hScaleV);

/* 创建和增加水平范围尺度标签 */
_hScaleH = GRAPH_SCALE_Create(155, GUI_TA_HCENTER, GRAPH_SCALE_CF_HORIZONTAL, 50);
/* 设置字体颜色 */
GRAPH_SCALE_SetTextColor(_hScaleH, GUI_DARKGREEN);
/* 添加到水平方向 */
GRAPH_AttachScale(hItem, _hScaleH);

/* 下面的四个用来设置,上下左右四个边界 */
hItem = WM_GetDialogItem(hDlg, GUI_ID_CHECK2);
CHECKBOX_SetText(hItem, "L");
/* 注意,下面的函数将触发回调函数的执行 */
CHECKBOX_SetState(hItem, 1);
/* 上边界 */
hItem = WM_GetDialogItem(hDlg, GUI_ID_CHECK3);
CHECKBOX_SetText(hItem, "T");
/* 右边界 */
hItem = WM_GetDialogItem(hDlg, GUI_ID_CHECK4);
CHECKBOX_SetText(hItem, "R");
/* 低边界 */
hItem = WM_GetDialogItem(hDlg, GUI_ID_CHECK5);
CHECKBOX_SetText(hItem, "B");


hItem = WM_GetDialogItem(hDlg, GUI_ID_CHECK0);
CHECKBOX_SetText(hItem, "Stop");

hItem = WM_GetDialogItem(hDlg, GUI_ID_CHECK1);
CHECKBOX_SetText(hItem, "Grid");
CHECKBOX_SetState(hItem, 1);

hItem = WM_GetDialogItem(hDlg, GUI_ID_CHECK6);
CHECKBOX_SetText(hItem, "HScroll");
CHECKBOX_SetState(hItem, 1);

hItem = WM_GetDialogItem(hDlg, GUI_ID_CHECK7);
CHECKBOX_SetText(hItem, "VScroll");

hItem = WM_GetDialogItem(hDlg, GUI_ID_CHECK8);
CHECKBOX_SetText(hItem, "Left align");

/* 初始化滑动控件 */
hItem = WM_GetDialogItem(hDlg, GUI_ID_SLIDER0);
/* 设置范围 */
SLIDER_SetRange(hItem, 0, 10);

/* 特别注意,设置了此函数的话,将自动的触发执行回调 */
SLIDER_SetValue(hItem, 5);
/* tick的数目:没有实际的意义 */
SLIDER_SetNumTicks(hItem, 6);

hItem = WM_GetDialogItem(hDlg, GUI_ID_SLIDER1);
/* 设置范围 */
SLIDER_SetRange(hItem, 0, 20);
SLIDER_SetValue(hItem, 5);
/* tick的数目 */
SLIDER_SetNumTicks(hItem, 6);

/* 初始化单选按钮控件 */
hItem = WM_GetDialogItem(hDlg, GUI_ID_RADIO0);
RADIO_SetText(hItem, "3D", 0);
RADIO_SetText(hItem, "flat", 1);
RADIO_SetText(hItem, "-", 2);

/* 初始化按钮控件 */
hItem = WM_GetDialogItem(hDlg, GUI_ID_BUTTON0);

/* 保持一直在上层 */
WM_SetStayOnTop(hItem, 1);
break;
case WM_NOTIFY_PARENT:
Id = WM_GetId(pMsg->hWinSrc); /* 控件ID*/
NCode = pMsg->Data.v; /* 通知代码 */
switch (NCode) {
case WM_NOTIFICATION_CLICKED:
switch (Id) {
case GUI_ID_BUTTON0:
/* 进入全屏模式 */
_ToggleFullScreenMode(hDlg);
break;
}
break;
case WM_NOTIFICATION_VALUE_CHANGED:
switch (Id) {
case GUI_ID_CHECK0:
/* Toggle stop mode */
/* 翻转 */
_Stop ^= 1;
break;
case GUI_ID_CHECK1:

/* 得到GRAPH0的句柄 */
hItem = WM_GetDialogItem(hDlg, GUI_ID_GRAPH0);
/* 方格是否显示 */
GRAPH_SetGridVis(hItem, CHECKBOX_IsChecked(WM_GetDialogItem(hDlg, GUI_ID_CHECK1)));
break;
case GUI_ID_CHECK2:
case GUI_ID_CHECK3:
case GUI_ID_CHECK4:
case GUI_ID_CHECK5:

/* 设置上下左右的坐标的边界值 */
/* 这里需要注意上面3个没有break */
hItem = WM_GetDialogItem(hDlg, GUI_ID_GRAPH0);
/* 设置上,下,左,右边界 */
GRAPH_SetBorder(hItem,
CHECKBOX_IsChecked(WM_GetDialogItem(hDlg, GUI_ID_CHECK2)) * 40,
CHECKBOX_IsChecked(WM_GetDialogItem(hDlg, GUI_ID_CHECK3)) * 5,
CHECKBOX_IsChecked(WM_GetDialogItem(hDlg, GUI_ID_CHECK4)) * 5,
CHECKBOX_IsChecked(WM_GetDialogItem(hDlg, GUI_ID_CHECK5)) * 5);
break;
case GUI_ID_SLIDER0:
/* 设置水平方格间距 */
hItem = WM_GetDialogItem(hDlg, GUI_ID_GRAPH0);
Value = SLIDER_GetValue(pMsg->hWinSrc) * 10;
/* 设置方格的间距 */
GRAPH_SetGridDistX(hItem, Value);
/* 设置tick的数值 也就是水平的坐标尺度 */
GRAPH_SCALE_SetTickDist(_hScaleH, Value);
break;
case GUI_ID_SLIDER1:
/* 设置垂直方格间距 */
hItem = WM_GetDialogItem(hDlg, GUI_ID_GRAPH0);
Value = SLIDER_GetValue(pMsg->hWinSrc) * 5;
GRAPH_SetGridDistY(hItem, Value);
/* 设置tick的数值 也就是垂直坐标的尺度 */
GRAPH_SCALE_SetTickDist(_hScaleV, Value);
break;
case GUI_ID_RADIO0:
/* 设置空间效果 */
hItem = WM_GetDialogItem(hDlg, GUI_ID_GRAPH0);
switch (RADIO_GetValue(pMsg->hWinSrc)) {
case 0:
WIDGET_SetEffect(hItem, &WIDGET_Effect_3D);
break;
case 1:
WIDGET_SetEffect(hItem, &WIDGET_Effect_Simple);
break;
case 2:
WIDGET_SetEffect(hItem, &WIDGET_Effect_None);
break;
}
break;
case GUI_ID_CHECK6:
/* 由此来触发是否选择滚动条 */
hItem = WM_GetDialogItem(hDlg, GUI_ID_GRAPH0);
if (CHECKBOX_IsChecked(WM_GetDialogItem(hDlg, GUI_ID_CHECK6))) {
/* 设置滚动条 */
GRAPH_SetVSizeX(hItem, 500);
} else {
/* 这里设置为0,就是相当于不再显示滚动条 */
GRAPH_SetVSizeX(hItem, 0);
}
break;
case GUI_ID_CHECK7:
/* 同上,这里是设置垂直的滚动条 */
hItem = WM_GetDialogItem(hDlg, GUI_ID_GRAPH0);
if (CHECKBOX_IsChecked(WM_GetDialogItem(hDlg, GUI_ID_CHECK7))) {
GRAPH_SetVSizeY(hItem, 300);
} else {
GRAPH_SetVSizeY(hItem, 0);
}
break;
case GUI_ID_CHECK8:
/* 这里主要是设置对齐方式 */
hItem = WM_GetDialogItem(hDlg, GUI_ID_GRAPH0);
for (i = 0; i < GUI_COUNTOF(_aColor); i++) {
if (CHECKBOX_IsChecked(WM_GetDialogItem(hDlg, GUI_ID_CHECK8))) {
GRAPH_DATA_YT_SetAlign(_ahData[i], GRAPH_ALIGN_LEFT);
} else {
GRAPH_DATA_YT_SetAlign(_ahData[i], GRAPH_ALIGN_RIGHT);
}
}
break;
}
break;
}
break;
default:
WM_DefaultProc(pMsg);
}
}

/*********************************************************************
*
* Public code
*
**********************************************************************
*/
/*********************************************************************
*
* MainTask
*/
void MainTask(void) {
WM_HWIN hDlg, hGraph = 0,hGraph1 = 0;
GUI_Init();
GUI_CURSOR_Show();
WM_SetDesktopColor(GUI_BLACK);

#if GUI_SUPPORT_MEMDEV
/* 所以的窗体自动的使用内存设备 */
WM_SetCreateFlags(WM_CF_MEMDEV);
#endif

/* 创建对话框 */
hDlg = GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), &_cbCallback, 0, 0, 0);
while (1) {
#ifdef WIN32
GUI_Delay(10);
#endif

/* 是否设置暂停 */
if (!_Stop) {
/* 可以不需要这个,因为下面的添加数值函数没有使用这个句柄 */
if (!hGraph) {
hGraph = WM_GetDialogItem(hDlg, GUI_ID_GRAPH0);
}
/* 这里是在添加数值 */
_AddValues(hGraph);
}
GUI_Exec();
}
}

实际显示效果如下:
45.4.png (49.1 KB, 下载次数: 0)
下载附件
2015-3-3 12:04 上传



使用特权

评论回复
地板
Beckham_Owen|  楼主 | 2016-7-9 21:11 | 只看该作者
45.3 使用官方GUIBulder建立Graph控件
使用官方提供的GUIBulder5.22也可以建立Graph控件,但是不完善,只能将其添加到窗口上,下面的截图就是用GUIBulder5.22设计的。
添加了Graph控件以后,当前的GUIBulder5.22版本仅支持下面两个功能(在这个控件上鼠标右击即可显示):
下面我们将设置“Set boedr sizes”参数如下:
设置后的显示效果如下:
现在GUIBuder5.22仅支持这些功能。大家有兴趣的可以在这个的基础上面建立一个Graph控件并在模拟器或者开发板上显示出来。
45.4 总结
本期教程主要是跟大家讲解了绘图控件的使用,希望大家可以把本期教程中讲的这个例子跑跑,然后自己设计一个相关的例子进行试验学习。教程中只是使用了部分的绘图控件API,其它的API大家都可以试试。
官方还有一个WIDGET_GraphXY的实例,大家可以研究下。

使用特权

评论回复
5
mintspring| | 2016-7-10 17:58 | 只看该作者
有没有PDF的文档,方便收藏学习。脱机时候也可以。

使用特权

评论回复
6
billtest36| | 2016-7-10 23:48 | 只看该作者
好詳細  感謝分享

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

32

主题

234

帖子

1

粉丝