找回密码
 注册
Simdroid-非首页
查看: 1582|回复: 30

写了个MATLAB VC绘图类

[复制链接]
发表于 2007-5-19 17:01:50 | 显示全部楼层 |阅读模式 来自 湖北武汉
头文件
  1. /*-------------------------------------------------
  2. |    Created  :    2007/05/19
  3. |    Created  :    19:5:2007   16:58
  4. |    File base:    MatGraph
  5. |    File ext :    hpp
  6. |    Author   :  Shunfly   
  7. |   MATLAB   :  6.5.1
  8. |   By       :  Visual Assist
  9. |-------------------------------------------------*/
  10. #include "matlab.hpp"
  11. #include "libmwsglm.hpp"
  12. #include "libmatlbm.hpp"
  13. #include "libmmfile.hpp"
  14. #include "mex.h"
  15. #pragma comment(lib,"libmwsglm.lib")
  16. #pragma comment(lib,"libmatlb.lib")
  17. #pragma comment(lib,"libmmfile.lib")
  18. #pragma comment(lib,"libmatlbmx.lib")
  19. #pragma comment(lib,"sgl.lib")
  20. #pragma comment(lib,"libmx.lib")
  21. #pragma comment(lib,"libmatpm.lib")
  22. #pragma comment(lib,"libmwservices.lib")
  23. class CMatGraph
  24. {
  25. /*
  26.     系统函数-------构造析构
  27. */
  28.     public:
  29.         CMatGraph();
  30.         virtual ~CMatGraph();
  31. /*
  32.     成员函数
  33. */
  34. public:
  35.          mwArray       hFigure  ;    // 保存Figure 句柄
  36.           static int       NCount   ;    // 静态成员变量。保存对象个数
  37.           mexFunctionTableEntry  my_local_function;
  38.         _mexLocalFunctionTable  my_local_function_table;
  39. };
复制代码
类实现
  1. #include "stdafx.h"
  2. #include "MatGraph.hpp"
  3. #include <string.h>
  4. int    CMatGraph::NCount         = 0;
  5. void M_CallBack(mwArray hObject,
  6.                 mwArray eventdata,
  7.                 mwArray handles);
  8. void mlx_CallBack(int nlhs, mxArray * plhs[], int nrhs, mxArray * prhs[])
  9. {
  10.     MW_BEGIN_MLX();
  11.      mwArray mprhs[3];
  12.         int i;
  13.         for (i = 0; i < 3 && i < nrhs; ++i) {
  14.             mprhs = mwArray(prhs, 0);
  15.         }
  16.         for (; i < 3; ++i) {
  17.             mprhs.MakeDIN();
  18.         }
  19.         M_CallBack(mprhs[0], mprhs[1], mprhs[2]);
  20.     MW_END_MLX();
  21. }
  22. void M_CallBack(mwArray hObject,
  23.                 mwArray eventdata,
  24.                 mwArray handles)
  25. {
  26.       //   mwLocalFunctionTable save_local_function_table_
  27.       //     = &my_local_function_table_simwe;
  28.       /*
  29.          所有的Gui Callback的通用入口
  30.       */
  31. }
  32. CMatGraph::CMatGraph()// 类构造函数
  33. {   
  34.     // MATLAB C++图形库初始化
  35.     NCount++;
  36.     if(NCount==1)
  37.     // 仅仅需要调用一次  图形库初始化
  38.     {
  39.         libmmfileInitialize();
  40.         libmwsglmInitialize();
  41.          int argc;
  42.         argc=0;
  43.         const char *p = NULL;
  44.         mlfHGInitialize(&argc,&p);
  45.     }
  46.     hFigure=Nfigure(1,mwArray("name")        , mwArray("Figure"),
  47.                       mwArray("numbertitle") , mwArray("off"),
  48.                       mwArray("color")       , mwArray("w"),
  49.                       mwArray("visible")     , mwArray("off"));
  50.     mexFunctionTableEntry  my_local_function[1]
  51.         = { { "CallBack", mlx_CallBack, 3, 0, NULL } };
  52.     _mexLocalFunctionTable my_local_function_table
  53.         = { 1, my_local_function};
  54.    
  55. }   
  56. CMatGraph::~CMatGraph()
  57. {
  58.     // 类析构函数
  59.     // MATLAB C++图形库退出
  60.     if (tobool(ishandle(CMatGraph::hFigure)))
  61.     {
  62.            delete_func(mwVarargin(CMatGraph::hFigure));
  63.     }
  64.     if(NCount==1)
  65.     // 仅仅需要调用一次  图形库退出
  66.     {
  67.         mlfHGWaitForFiguresToDie();
  68.         mlfHGTerminate();
  69.         libmmfileTerminate();
  70.         libmwsglmTerminate();
  71.     }
  72.     NCount--;
  73. }
复制代码

[ 本帖最后由 shunfly 于 2007-5-20 10:47 编辑 ]

评分

1

查看全部评分

 楼主| 发表于 2007-5-19 17:21:42 | 显示全部楼层 来自 湖北武汉
Simdroid开发平台
现在有几个问题
    一个是,我将FIGURE镶嵌到视图VIEW后,由于FIGURE拦路抢劫,VIEW
无法响应鼠标等消息。
    而通过FIGURE的一个属性,MATLAB中截获鼠标按键消息并不好,居然还区分两键和三键鼠标。当然,这个应该通过WIN32 API可以完成。
    我想把FIGURE的以及我所有需要的MATLAB控件的CALLBACK放在
  1. void M_CallBack(mwArray hObject,
  2.                 mwArray eventdata,
  3.                 mwArray handles)
复制代码
里。但是,这个尝试了一个中午,无法嵌入到类中去。主要是
  1. mexFunctionTableEntry  my_local_function[1]
  2.         = { { "CallBack", mlx_CallBack, 3, 0, NULL } };
复制代码
这里面的mlx_CallBack函数原型是个函数指针。将mlx_CallBack等统统设置为类
成员函数后,无法识别。

现在的问题是:
1。MATLAB FIGURE嵌入VC的视图VIEW后,在FIGURE上是否还可以有办法响应
VIEW的鼠标等消息?
     实在是舍不的MFC给俺搭好的消息架子吧。
     我这完全是用C/C++库写,灵活一些
     所以,能在VC写的就不在MATLAB的这个类中写
2。能否有办法将
  1. void M_CallBack(mwArray hObject,
  2.                 mwArray eventdata,
  3.                 mwArray handles);
  4. void mlx_CallBack(int nlhs, mxArray * plhs[], int nrhs, mxArray * prhs[]) ;
  5. void M_CallBack(mwArray hObject,
  6.                 mwArray eventdata,
  7.                 mwArray handles);
复制代码
这几个函数放到类中去?
这样可以很方便VC MATLAB交互数据。而现在,我仅仅只能通过静态数据成员传递数据。

[ 本帖最后由 shunfly 于 2007-5-19 17:27 编辑 ]
回复 不支持

使用道具 举报

发表于 2007-5-19 17:57:38 | 显示全部楼层 来自 新加坡
我不是很清楚这种实现方法,不过看起来不错。

关于问题一,试试看给你的控件加上Notify属性,希望这样的话可以把Windows Messages传递给它的Parent,也就是你的View对象

关于问题二,你是像让你的实现更OO?有没有考虑国Functor,也就是实现了operator()的类?

纯属个人拙见

评分

1

查看全部评分

回复 不支持

使用道具 举报

 楼主| 发表于 2007-5-19 18:06:49 | 显示全部楼层 来自 湖北武汉
本帖最后由 shunfly 于 2009-11-12 20:40 编辑

MATLAB的FIGURE也可以如此加Notify属性?
我查查看(:)

我的FIGURE是直接以VIEW视图为父窗口
或者你是说,在VIEW上放置PICTURE类似的控件
设置Notify属性
把FIGURE的父窗口设置为该控件?

这样好处是不必考虑图形库的初始化和退出
而且我还封装了类似
  1. CMatGraph::CMatplot2D(double *datax,double *datay,int Ndatax,int Ndatay);
复制代码
这样的绘图
这样便于不会MATLAB的人直接当接口使用
“也就是实现了operator()的类”
这个如何理解?

[ 本帖最后由 shunfly 于 2007-5-19 18:30 编辑 ]
回复 不支持

使用道具 举报

发表于 2007-5-19 18:29:34 | 显示全部楼层 来自 新加坡
用“functor"为关键词搜索,应该有很多相关的讨论。如果你用boost的话,那里应该也有这样的东西(把c的callback用OO的形式实现)
回复 不支持

使用道具 举报

发表于 2007-5-19 21:42:40 | 显示全部楼层 来自 北京交通大学
呵呵,N久前也曾经尝试过写这样一个类,可后来一直未果
好好研究下:D
回复 不支持

使用道具 举报

 楼主| 发表于 2007-5-20 08:08:18 | 显示全部楼层 来自 湖北武汉
第一个问题好像不好直接解决
我试了个基类为CFormView的MFC EXE
在上面放置一STATIC,再以STATIC为父窗口放置FIGURE
消息还是被FIGURE抢劫了
也许因为FIGURE是个窗体而不是单单的一个控件,所以消息还是会被它通吃
回复 不支持

使用道具 举报

发表于 2007-5-20 09:05:19 | 显示全部楼层 来自 新加坡
试试看用spy++看消息处理,能不能有点线索。

SCIE兄对这个好像有研究,不知道他是怎么处理这个问题的。

[ 本帖最后由 taohe 于 2007-5-20 09:09 编辑 ]
回复 不支持

使用道具 举报

发表于 2007-5-20 09:31:28 | 显示全部楼层 来自 浙江舟山
第一个问题可以采取子类化的方式,将Figure窗口子类化,也就是重新指定Figure窗口的窗口处理函数(用SetWindowLong),在其中截获需要的消息传递给View的消息窗口处理函数进行处理,不需要截获的则仍由Figure窗口处理。

第二个问题是Callback的问题,由于这是给Matlab回调用的,所以它可能不支持functor。
我的实现方式是建立一个中间层,Matlab回调时调用中间层的函数,然后中间层的函数再调用合适的处理函数。中间层函数必须是一个全局函数,而中间层调用的处理函数则是一个类成员函数了。

你定义了M_Callback和mlxCallback,还有一个函数表,用来实现回调函数。但这样做可能有些复杂,有一组宏可以代替你做以上复杂的工作。参看下面这个帖子的关于“函数注册”的讨论。
http://www.simwe.com/forum/viewthread.php?tid=191076
那么由于中间层是个全局的函数,而Figure窗口可能有很多个,也就是CMatGraph会有很多个实例,怎样在中间层函数里区分调用哪个实例的处理函数呢?我们可以在设置回调函数的时候把当前CMatGraph实例的指针作为一个long型数值用setappdata存储到该对象中。中间层函数最好设置为没有任何输入参数的那种。

// 回调中间层函数
mwArray CallbackFcn()
{
    1. 获取当前的CallbackObject
    2. 用guidata 获取handles句柄结构体
    3. 用 getappdata 获取存储在CallbackObject中的CMatGraph实例指针
    4. 调用CMatGraph中的处理函数,将CallbackObject,EventData,handles作为参数传入
}
  
// 对函数 CallbackFcn 进行注册
DECLARE_FEVAL_TABLE
  FEVAL_ENTRY(CallbackFcn)
END_FEVAL_TABLE

设置回调函数的时候只需指定为字符串形式的“CallbackFcn”就行了。
Vset(hFigure, "WindowButtonDownFcn", "CallbackFcn");
然后再用setappdata存储当前CMatGraph实例指针

我以前写了个包装Matlab图形库的dll,在处理回调函数时用的就是类似的方法。这个库采用一对一封装Matlab库函数的形式,简化函数接口,使用普通的数据类型作为参数,还可以在VB,Delphi里用。这个库在MATLAB第二次研讨会上提到过,但是当时几乎没有人感兴趣。

[ 本帖最后由 SCIE 于 2007-5-20 10:02 编辑 ]

评分

1

查看全部评分

回复 不支持

使用道具 举报

 楼主| 发表于 2007-5-20 10:15:59 | 显示全部楼层 来自 湖北武汉
第一个我先Google下
第二个,我现在试试
PS:我这个和你那个Matlab图形库是一样的初衷:lol

我懂你的意思了
我一开始一直想将CALLBACK放到类里面
因为作为你说的全局函数后,我只能调用类静态成员函数
现在知道解决方案了

[ 本帖最后由 shunfly 于 2007-5-20 11:19 编辑 ]
回复 不支持

使用道具 举报

 楼主| 发表于 2007-5-21 10:33:05 | 显示全部楼层 来自 湖北武汉
SCIE
按照你提示的窗口子类化的想法
我Google尝试了一下,还学了下SPY++的用法
发现有这么个问题:
我自定义的CALLBACK消息处理函数无法得到WM_LBUTTONDOWN等常规消息
也就是以下程序的::MessageBox(NULL,"12","左键DOWN",MB_OK);部分无法响应
但在SPY|++中的的确确是看到了消息。
难道是因为MATLAB窗口不是标准的WIN32 窗口?
不过意外之喜就是,我捕捉到了WM_MOUSEWHEEL的鼠标滚轮消息,也就是说
在7.X以前的GUI编译中,改写一下,可以支持鼠标滚轮。这样免去了JAVA响应鼠标
滚轮无法支持7.X以前的编译的困扰。
相关函数如下:
  1. //定义CMatGraph类的静态成员函数static WNDPROC OldProc;
  2. HWND hWnd=FindWindow(NULL,"Figure");
  3.         if(!hWnd)
  4.         {
  5.                 ::MessageBox(NULL,"1","找不到窗口",MB_OK);
  6.                   return;
  7.         }
  8. CMatGraph::OldProc=(WNDPROC)SetWindowLong(hWnd,GWL_WNDPROC,(LONG)NewProc);
  9. LRESULT CALLBACK NewProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
  10. {
  11.   
  12.   if(Msg==WM_LBUTTONDOWN)
  13.   {
  14.      ::MessageBox(NULL,"12","左键DOWN",MB_OK);
  15.          return 1;      
  16.   }
  17.   if(Msg==WM_LBUTTONUP)
  18.   {
  19.      ::MessageBox(NULL,"12","左键UP",MB_OK);
  20.          return 1;      
  21.   }
  22.   if (Msg==WM_MOUSEWHEEL)
  23.   {
  24.           ::MessageBox(NULL,"12","鼠标滚轮",MB_OK);
  25.           return 1;
  26.   }
  27.   else
  28.   {
  29.           return CallWindowProc(CMatGraph::OldProc, hWnd, Msg, wParam, lParam);         
  30.       
  31.   }
  32. }
复制代码

[ 本帖最后由 shunfly 于 2007-5-21 11:58 编辑 ]

评分

1

查看全部评分

回复 不支持

使用道具 举报

发表于 2007-5-21 14:59:34 | 显示全部楼层 来自 浙江舟山
Matlab的Figure窗口有两层:

一个是Figure窗口的外框架,就是你用FindWindow直接查到的窗口,它包括外窗口边框和菜单,主要响应与框架有关的一些消息,典型的如WM_SIZING消息;

在Figure窗口之下有一个子窗口,其类名叫MatlabFigureClass,标题为空。它就是Figure窗口中通常显示图形和控件的地方,包括工具栏在内。它响应大多数的我们所关心的消息,如鼠标、键盘消息。查找这个窗口需要用FindWindowEx函数,使用类名MatlabFigureClass查找。

如果我们需要某种特定的消息,就需要子类化特定的窗口-Figure窗口还是其子窗口。注意这两个窗口会有一些共同的消息,如WM_SIZE消息。当然两个窗口的WM_SIZE消息的参数是不一样的,父窗口的WM_SIZE消息携带的参数是父窗口的大小,而子窗口的消息参数是子窗口的大小。

不过,我想大多数时候只需要关心子窗口的消息就可以了,按照你的想法是把Figure窗口潜入到View中,也就没有边框和菜单了。特别的时候可能需要处理只有父窗口才有的消息:比如WM_SIZING,父窗口在大小被改变之前发送此消息,可以截获此消息实现一些特殊的效果,比如一个只允许放大,不允许缩小的窗口。

祝你早日搞定!:victory:

关键就是要子类化MatlabFigureClass这个子窗口,因为它处理你想要的鼠标键盘消息!

[ 本帖最后由 SCIE 于 2007-5-21 15:51 编辑 ]

评分

1

查看全部评分

回复 不支持

使用道具 举报

 楼主| 发表于 2007-5-21 15:39:20 | 显示全部楼层 来自 湖北武汉
的确
由于用SetWindowLong去掉了标题栏等
我用到的是子窗口,类CLASS为MatlabFigureClass,CAPTION为空
  1. HWND hWnd=FindWindow(NULL,"Figure");
复制代码
这个查找的也就是子窗口
不过我出现的问题是在窗口子类化后的
  1. LRESULT CALLBACK NewProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
复制代码
新的消息处理函数里面
我无法截取到WM_LBUTTONDOWN等消息
MessageBox(NULL,"12","左键DOWN",MB_OK);没有弹出,程序直接跳过
相反,仅仅只能截获WM_MOUSEWHEEL消息
弹出::MessageBox(NULL,"12","鼠标滚轮",MB_OK);
哦,我明白你的意思了
我回实验室试试FindWindowEx看看

[ 本帖最后由 shunfly 于 2007-5-21 15:45 编辑 ]
回复 不支持

使用道具 举报

 楼主| 发表于 2007-5-21 16:17:51 | 显示全部楼层 来自 湖北武汉
查找搞定了
找到鼠标消息了
感谢SCIE:lol
下面开始滤掉被它抢劫的消息
待会贴报告上来
回复 不支持

使用道具 举报

 楼主| 发表于 2007-5-21 17:29:28 | 显示全部楼层 来自 湖北武汉
完全搞定
具体见附件
这样MATLAB FIGURE完全成了一个纯粹的绘图机器了:lol
不会在抢劫消息了
世界清静了
同时,根据截获的MOUSE_WHEEL消息
待会想个GUI中响应鼠标滚轮的东西出来

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
回复 不支持

使用道具 举报

发表于 2007-5-21 18:49:05 | 显示全部楼层 来自 浙江舟山
恭喜,恭喜,第一个下载,抢先试用:lol

效果不错,如果把OnInitialUpdate函数中设置子窗口以及去掉标题栏和边框的功能也封装到类里面,就更加方便了。

[ 本帖最后由 SCIE 于 2007-5-21 19:58 编辑 ]
回复 不支持

使用道具 举报

 楼主| 发表于 2007-5-22 11:19:12 | 显示全部楼层 来自 湖北武汉
起了怪了
想实现如下GUI

  1. function VCGui
  2. ezplot(@sin);
  3. set(gcf,'WindowButtonDownFcn',@Action,'DoubleBuffer','on');
  4. function Action(hObject,eventdata,handles)
  5.         hold on;
  6.         p=mean(get(gca,'currentpoint'));
  7.         plot(p(1),p(2),'o','MarkerSize',8,'MarkerFaceColor','r')
复制代码

VC实现如下:

  1. void VCTESTView::OnLButtonDown(UINT nFlags, CPoint point)
  2. {
  3.         CView::OnLButtonDown(nFlags, point);
  4.         if(mCMatGraph.DrawType==1)
  5.         {
  6.                 mwArray mPoint  = mean(get(gca(),mwArray("currentpoint")));
  7.                 hold(mwArray("on"));
  8.                 Vplot(mPoint(1),mPoint(2),"o","MarkerSize",8,"MarkerEdgeColor","g","MarkerFaceColor","r");
  9.                 drawnow(mwArray::DIN);
  10.         }       
  11. }
复制代码

居然得到的结果是有延迟?
画的始终是上一个点,而第一个点不知道从何方而来
设置一变量

  1. static int    DrawType  =0 ;
复制代码

改窗口子类化程序

  1.   if(Msg==WM_LBUTTONDOWN)
  2.   {
  3.         if(CMatGraph::DrawType==1)
  4.         {
  5.                 ::SendMessage(CMatGraph::ViewHandle,WM_LBUTTONDOWN,wParam,lParam);
  6.         }         
  7.         return 0;      
  8.   }
复制代码

添加一菜单

  1. void CCLTEM25DView::OnVCGui()
  2. {
  3.         mCMatGraph.DrawType=1;
  4. }
复制代码

改消息处理函数

  1. void VCTESTView::OnLButtonDown(UINT nFlags, CPoint point)
  2. {
  3.         CView::OnLButtonDown(nFlags, point);
  4.         if(mCMatGraph.DrawType==1)
  5.         {
  6.                 mwArray mPoint  = mean(get(gca(),mwArray("currentpoint")));
  7.                 hold(mwArray("on"));
  8.                 Vplot(mPoint(1),mPoint(2),"o","MarkerSize",8,"MarkerEdgeColor","g","MarkerFaceColor","r");
  9.                 drawnow(mwArray::DIN);
  10.         }       
  11. }
复制代码

结果还是如此。画的始终是上次鼠标按下的点?
起了怪了,吃饭先
回复 不支持

使用道具 举报

发表于 2007-5-22 11:28:58 | 显示全部楼层 来自 浙江舟山
注意,你在新的窗口处理函数中屏蔽了Figure窗口对鼠标按键的处理:
  1. LRESULT CALLBACK NewProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
  2. {
  3.   if(Msg==WM_LBUTTONDOWN)
  4.   {
  5.   // Figure窗口未能处理该消息
  6.   ::PostMessage(CMatGraph::ViewHandle,WM_LBUTTONDOWN,wParam,lParam);
  7.   return 0;      
  8.   }
  9.   if(Msg==WM_RBUTTONDOWN)
  10.   {
  11.   // Figure窗口未能处理该消息
  12.   ::PostMessage(CMatGraph::ViewHandle,WM_RBUTTONDOWN,wParam,lParam);
  13.   return 0;      
  14.   }
  15.   else
  16.   {
  17.    return CallWindowProc(CMatGraph::OldProc, hWnd, Msg, wParam, lParam);   
  18.   }
  19. }
复制代码
这样在 get(gca, 'CurrentPoint') 时无法取得正确的值了,这些消息还应该让Figure窗口继续处理。
至于第一个点,可能是有个默认的吧。

[ 本帖最后由 SCIE 于 2007-5-22 13:10 编辑 ]
回复 不支持

使用道具 举报

 楼主| 发表于 2007-5-22 11:37:37 | 显示全部楼层 来自 湖北武汉
如果真有一个默认点的话
那么,我回去试试
  1. LRESULT CALLBACK NewProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
  2. {
  3.   if(mCMatGraph.DrawType==0)
  4.      return CallWindowProc(CMatGraph::OldProc, hWnd, Msg, wParam, lParam);
  5.   if(Msg==WM_LBUTTONDOWN)
  6.   {
  7.          ::PostMessage(CMatGraph::ViewHandle,WM_LBUTTONDOWN,wParam,lParam);
  8.          return 1;      
  9.   }
  10.   else
  11.   {
  12.           return CallWindowProc(CMatGraph::OldProc, hWnd, Msg, wParam, lParam);               }
  13. }
复制代码
原来如此
既然如此,干脆,狠心不要CurrentPoint
直接根据point像素和axes的Position以及Xtick,Ytick自己转换坐标
或者,我可以在

  1. if(Msg==WM_LBUTTONDOWN)
  2.   {   
  3.          ::PostMessage(hWnd,WM_LBUTTONUP,wParam,lParam);
  4.          ::PostMessage(CMatGraph::ViewHandle,WM_LBUTTONDOWN,wParam,lParam);
  5.          return 1;      
  6.   }
复制代码

再处理一下,模拟鼠标Up,更新CurrentPoint

[ 本帖最后由 shunfly 于 2007-5-22 11:51 编辑 ]
回复 不支持

使用道具 举报

发表于 2007-5-22 13:09:41 | 显示全部楼层 来自 浙江舟山
刚才说错了,在鼠标按下和弹起时都更新CurrentPoint,只是刚才LButtonDown被你屏蔽了,我觉得应该先让MATLAB处理鼠标消息,再让View处理比较好,不需要模拟LButtonUp了。

  1. LRESULT CALLBACK NewProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
  2. {
  3.      LRESULT result = CallWindowProc(CMatGraph::OldProc, hWnd, Msg, wParam, lParam);
  4.     if(Msg==WM_LBUTTONDOWN)
  5.     {
  6.          ::PostMessage(CMatGraph::ViewHandle,WM_LBUTTONDOWN,wParam,lParam);
  7.     }
  8.    return result;
  9. }
复制代码
回复 不支持

使用道具 举报

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

本版积分规则

Archiver|小黑屋|联系我们|仿真互动网 ( 京ICP备15048925号-7 )

GMT+8, 2024-4-16 18:48 , Processed in 0.072783 second(s), 21 queries , Gzip On, MemCache On.

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

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