当前位置: 首页 > news >正文

泉州网站建站模板济南网站建设哪里便宜

泉州网站建站模板,济南网站建设哪里便宜,曲沃网站建设,官方重大项目建设库网站文章目录 libusb自动刷新程序Code目录结构Code项目文件usb包code包 效果描述重置reset热拔插使用 END libusb 在操作USB相关内容时#xff0c;有一个比较著名的库就是libusb。 官方网址#xff1a;libusb 下载#xff1a; 下载源码官方编好的库github#xff1a;Release… 文章目录 libusb自动刷新程序Code目录结构Code项目文件usb包code包 效果描述重置reset热拔插使用 END libusb 在操作USB相关内容时有一个比较著名的库就是libusb。 官方网址libusb 下载 下载源码官方编好的库githubReleases · libusb/libusb (github.com) 使用libusb: Application Programming Interface (sourceforge.io) FunctionsStructuresEnums 自动刷新程序Code 这里介绍一个基于libusb自动刷新usb的demo。 目录结构 3rdparty包 libusb的头文件和库这里采用官方编好的现成的库 usb包 基于C对libusb的封装此包为纯C代码 code包 基于Qt的ui和线程 E:. └─usbReset│ main.cpp│ usbReset.pro│├─3rdparty│ └─libusb│ ├─include│ │ └─libusb-1.0│ │ libusb.h│ ││ └─MinGW32│ ├─dll│ │ libusb-1.0.dll│ │ libusb-1.0.dll.a│ ││ └─static│ libusb-1.0.a│├─code│ THREAD_TimerUsb.cpp│ THREAD_TimerUsb.h│ WIDGET_Main.cpp│ WIDGET_Main.h│ WIDGET_Main.ui│└─usbusb.priUSB_Hotplug.cppUSB_Hotplug.hUSB_Reset.cppUSB_Reset.hCode 项目文件 usbReset.pro QT core QT widgets#CONFIG console CONFIG c17DESTDIR $$PWD/bininclude($$PWD/usb/usb.pri)INCLUDEPATH $$PWD/code HEADERS \code/THREAD_TimerUsb.h \code/WIDGET_Main.hSOURCES \main.cpp \code/THREAD_TimerUsb.cpp \code/WIDGET_Main.cppFORMS \code/WIDGET_Main.uiusb/usb.pri # 链接到libusb采用静态库 INCLUDEPATH $$PWD/../3rdparty/libusb/include HEADERS $$PWD/../3rdparty/include/libusb/libusb-1.0/libusb.h LIBS -L$$PWD/../3rdparty/libusb/MinGW32/static/ -llibusb-1.0# 当前封装的包 INCLUDEPATH $$PWD/.. HEADERS \$$PWD/USB_Hotplug.h \$$PWD/USB_Reset.hSOURCES \$$PWD/USB_Hotplug.cpp \$$PWD/USB_Reset.cppmain.cpp #include QApplication#include WIDGET_Main.hint main(int argc, char *argv[]) {QApplication app(argc, argv);MainWidget form;form.show();return app.exec(); }usb包 USB_Reset.h #ifndef MYUSB_H_1682212693 #define MYUSB_H_1682212693extern C { #include libusb-1.0/libusb.h } #include string #include vectornamespace USB {class Reset final { public:inline static const int EMPTY_POINTER_INT 114514;private:/// for init exitstatic libusb_context* context;static uint32_t obj_count;public:static int Reset_context();private:char str[1024]{};public:/// libusb_init()Reset();/// libusb_exit()~Reset();public:::std::vector::std::string Show_device();public:libusb_device_descriptor Find_descriptByidVendor(uint32_t Vendor);public:/*** vendor - device* - handle** handle* - reset* handle* - close*/libusb_device* Find_deviceByidVendor(uint32_t Vendor);libusb_device_handle* Get_handleByOpenDevice(libusb_device* device);int Reset_usbByHandle(libusb_device_handle* device_handle);void Close_deviceByHandle(libusb_device_handle* device_handle); };} // namespace USB #endif // MYUSB_H_1682212693USB_Reset.cpp #include USB_Reset.hnamespace USB { /*** brief UsbBase::context* static data* context: 所有对象共享这一个全局的上下文对象* obj_count: 引用计数*/ libusb_context* Reset::context nullptr; uint32_t Reset::obj_count 0;/*** brief UsbBase::Reset_context* return* static 重置上下文*/ int Reset::Reset_context() {/// 有实体对象才重置 contextif (0 ! obj_count) {if (nullptr ! context) {libusb_exit(context);context nullptr;}return libusb_init(context);}return LIBUSB_SUCCESS; }/*** brief UsbBase::UsbBase* constructor* 上下文的init* 维护引用计数*/ Reset::Reset() {/// 查看版本号const struct libusb_version* version libusb_get_version();printf(Libusb-Version:%s\n, version-describe);printf(Libusb-Version:%d.%d.%d.%d\n,version-major,version-minor,version-micro,version-nano);/// 第一个对象或者之前没有注册成功if (0 obj_count || nullptr context) {if (int res libusb_init(context); res ! 0) {sprintf(str, fail to init: %d\n, res);/// TODO/// 根据实际情况日志、断言、异常等/// TODO}}obj_count 1; }/*** brief UsbBase::~UsbBase* distructor* 维护引用计数* 上下文的退出*/ Reset::~Reset() {obj_count -1;if (0 obj_count) {if (nullptr ! context) {libusb_exit(context);context nullptr;}} }/*** brief UsbBase::show_device* just show device-list message*/ ::std::vector::std::string Reset::Show_device() {::std::vector::std::string messageList;messageList.push_back(********************** show device-list message BEGIN **********************);/// help datalibusb_device** deviceList nullptr;libusb_get_device_list(nullptr, deviceList);for (int i 0; deviceList[i] ! nullptr; i 1) {auto device deviceList[i];struct libusb_device_descriptor descript;int ret libusb_get_device_descriptor(device, descript);if (LIBUSB_SUCCESS ! ret) {continue;}sprintf(str,*idVendor:%6d idProduct:%6d bDeviceClass:%6d (bus:%3d, device:%3d)*,descript.idVendor, descript.idProduct, descript.bDeviceClass,libusb_get_bus_number(device),libusb_get_device_address(device));messageList.push_back(str);}messageList.push_back(********************** show device-list message END ************************);return messageList; }/*** brief MyUsb::Find_descriptByidVendor* param idVendor* return* 获取设备描述对象*/ libusb_device_descriptor Reset::Find_descriptByidVendor(uint32_t idVendor) {/// retlibusb_device_descriptor descriptor;/// help datalibusb_device_handle* deviceHandle nullptr;libusb_device** deviceList nullptr;libusb_get_device_list(nullptr, deviceList);for (int i 0; deviceList[i] ! nullptr; i 1) {auto device deviceList[i];int ret libusb_get_device_descriptor(device, descriptor);if (LIBUSB_SUCCESS ! ret) {continue;}if (descriptor.idVendor idVendor) {const int isOpen libusb_open(device, deviceHandle);if (LIBUSB_SUCCESS isOpen) {libusb_close(deviceHandle);break;}}}return descriptor; }/*** brief UsbBase::Find_deviceByidVendor* param Vendor* return* 获取device*/ libusb_device* Reset::Find_deviceByidVendor(uint32_t Vendor) {/// retlibusb_device* device nullptr;/// help datalibusb_device_handle* deviceHandle nullptr;libusb_device** deviceList nullptr;libusb_get_device_list(nullptr, deviceList);for (int i 0; deviceList[i] ! nullptr; i 1) {device deviceList[i];libusb_device_descriptor descriptor;int ret libusb_get_device_descriptor(device, descriptor);if (LIBUSB_SUCCESS ! ret) {continue;}if (descriptor.idVendor Vendor) {const int isOpen libusb_open(device, deviceHandle);if (LIBUSB_SUCCESS isOpen) {libusb_close(deviceHandle);break;} else {device nullptr;}} else {device nullptr;}}return device; }/*** brief UsbBase::Get_handleByOpenDevice* param device* return* 根据传入的设备指针* 通过open操作* 获取句柄指针*/ libusb_device_handle* Reset::Get_handleByOpenDevice(libusb_device* device) {if (nullptr device) {return nullptr;}libusb_device_handle* deviceHandle nullptr;const int isOpen libusb_open(device, deviceHandle);if (LIBUSB_SUCCESS isOpen) {return deviceHandle;} else {return nullptr;} }/*** brief UsbBase::Reset_usbByHandle* param device_handle* return* 通过句柄重置设备* 为0则表示成功*/ int Reset::Reset_usbByHandle(libusb_device_handle* device_handle) {if (nullptr device_handle) {return EMPTY_POINTER_INT;}const int isReset libusb_reset_device(device_handle);//! TODO if (isReset ? 0) logreturn isReset; }/*** brief UsbBase::Close_deviceByHandle* param device_handle* 手动通过句柄指针关闭设备*/ void Reset::Close_deviceByHandle(libusb_device_handle* device_handle) {if (nullptr device_handle) {return;}libusb_close(device_handle); } } // namespace USBUSB_Hotplug.h #ifndef HOTPLUG_H_27452998650 #define HOTPLUG_H_27452998650extern C { #include libusb-1.0/libusb.h }namespace USB { class Hotplug final { private:static libusb_device_handle *m_deviceHandle;private:static int LIBUSB_CALL usb_arrived_callback(struct libusb_context *ctx,struct libusb_device *dev,libusb_hotplug_event event,void *userdata);static int LIBUSB_CALL usb_left_callback(struct libusb_context *ctx,struct libusb_device *dev,libusb_hotplug_event event,void *userdata);private:char str[1024]{};private:libusb_hotplug_callback_handle usb_arrived_handle;libusb_hotplug_callback_handle usb_left_handle;libusb_context *context nullptr;private:uint32_t m_regiest_vendor LIBUSB_HOTPLUG_MATCH_ANY;uint32_t m_regiest_product LIBUSB_HOTPLUG_MATCH_ANY;uint32_t m_regiest_deviceClass LIBUSB_HOTPLUG_MATCH_ANY;private:Hotplug();public:Hotplug(uint32_t vendor, uint32_t product, uint32_t deviceClass);~Hotplug();public:int Register_arrived();int Register_left(); }; } // namespace USB#endif // HOTPLUG_H_27452998650USB_Hotplug.cpp #include USB_Hotplug.h#include iostreamnamespace USB { /*** brief Hotplug::m_deviceHandle* 主要用于静态的回调函数*/ libusb_device_handle *Hotplug::m_deviceHandle nullptr;/*** brief Hotplug::usb_arrived_callback* param ctx* param dev* param event* param userdata* return* 热拔插 arrive 的回调*/ int Hotplug::usb_arrived_callback(libusb_context *ctx, libusb_device *dev,libusb_hotplug_event event, void *userdata) {struct libusb_device_handle *handle;struct libusb_device_descriptor desc;unsigned char buf[512];int rc;libusb_get_device_descriptor(dev, desc);printf(Add usb device: \n);printf(\tCLASS(0x%x) SUBCLASS(0x%x) PROTOCOL(0x%x)\n, desc.bDeviceClass,desc.bDeviceSubClass, desc.bDeviceProtocol);printf(\tVENDOR(0x%x) PRODUCT(0x%x)\n, desc.idVendor, desc.idProduct);rc libusb_open(dev, handle);if (LIBUSB_SUCCESS ! rc) {printf(Could not open USB device\n);return 0;}memset(buf, 0, sizeof(buf));rc libusb_get_string_descriptor_ascii(handle, desc.iManufacturer, buf,sizeof(buf));if (rc 0) {printf(Get Manufacturer failed\n);} else {printf(\tManufacturer: %s\n, buf);}memset(buf, 0, sizeof(buf));rc libusb_get_string_descriptor_ascii(handle, desc.iProduct, buf,sizeof(buf));if (rc 0) {printf(Get Product failed\n);} else {printf(\tProduct: %s\n, buf);}memset(buf, 0, sizeof(buf));rc libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, buf,sizeof(buf));if (rc 0) {printf(Get SerialNumber failed\n);} else {printf(\tSerialNumber: %s\n, buf);}libusb_close(handle);return 0; }/*** brief Hotplug::usb_left_callback* param ctx* param dev* param event* param userdata* return* 热拔插left的回调*/ int Hotplug::usb_left_callback(libusb_context *ctx, libusb_device *dev,libusb_hotplug_event event, void *userdata) {struct libusb_device_descriptor desc;libusb_get_device_descriptor(dev, desc);const int isReset libusb_reset_device(m_deviceHandle);return isReset; }/*** brief Hotplug::Hotplug* 构造的时候init*/ Hotplug::Hotplug() {libusb_init(context); }/*** brief Hotplug::Hotplug* param vendor* param product* 委托构造*/ Hotplug::Hotplug(uint32_t vendor, uint32_t product, uint32_t deviceClass) : Hotplug() {/// data{m_regiest_vendor vendor;m_regiest_product product;m_regiest_deviceClass deviceClass;}/// find{libusb_device **m_deviceList;libusb_get_device_list(nullptr, m_deviceList);for (int i 0; m_deviceList[i] ! nullptr; i 1) {auto device m_deviceList[i];struct libusb_device_descriptor descript;int ret libusb_get_device_descriptor(device, descript);if (ret 0) {sprintf(str,Error libusb_get_device_descriptor idx %d res %d\n, i,ret);}if (descript.idVendor vendor descript.idProduct product) {const int isOpen libusb_open(m_deviceList[i], m_deviceHandle);if (LIBUSB_SUCCESS isOpen) {break;}}}} /// find/// test{Register_arrived();Register_left();} }/*** brief Hotplug::~Hotplug* 析构的时候注销和释放句柄*/ Hotplug::~Hotplug() {libusb_hotplug_deregister_callback(context, usb_arrived_handle);libusb_hotplug_deregister_callback(context, usb_left_handle);libusb_exit(context); }/*** brief Hotplug::Register_arrived* return* 注册热拔插arrive*/ int Hotplug::Register_arrived() {int res libusb_hotplug_register_callback(context, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, LIBUSB_HOTPLUG_NO_FLAGS,m_regiest_vendor, m_regiest_product, m_regiest_deviceClass,Hotplug::usb_arrived_callback, NULL, usb_arrived_handle);return res; }/*** brief Hotplug::Register_left* return* 注册热拔插left*/ int Hotplug::Register_left() {int res libusb_hotplug_register_callback(context, LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, LIBUSB_HOTPLUG_NO_FLAGS,m_regiest_vendor, m_regiest_product, m_regiest_deviceClass,Hotplug::usb_left_callback, NULL, usb_left_handle);return res; } } // namespace USBcode包 WIDGET_Main.h #ifndef FORM_H_27453073957 #define FORM_H_27453073957#include QScopedPointer #include QVector #include QWidget#include THREAD_TimerUsb.hnamespace Ui { class MainWidget; }class MainWidget : public QWidget {Q_OBJECTprivate:QScopedPointerUi::MainWidget ui;private:TimerUsb m_usb;public:explicit MainWidget(QWidget *parent nullptr);~MainWidget();private:void show_usbDeviceMsgAll();void start_work(); };#endif // FORM_H_27453073957WIDGET_Main.cpp #include WIDGET_Main.h#include QDebug #include QMutex #include QThread #include QTimer#include ui_WIDGET_Main.h #include usb/USB_Reset.hQWidget *g_widgetDisplayBoard nullptr; QtMessageHandler g_oldMessageHandler nullptr; QMutex g_dispalyMutex;/*** debug 重定向*/ void newDebugHandlerFunc(QtMsgType type, const QMessageLogContext context, const QString msg) {QMutexLocker locker(g_dispalyMutex);if (g_widgetDisplayBoard) {dynamic_castQTextEdit *(g_widgetDisplayBoard)-append(msg);} else {g_oldMessageHandler(type, context, msg);} }/*** brief MainWidget::MainWidget* param parent* 1. debug重定向* 2. connect*/ MainWidget::MainWidget(QWidget *parent) : QWidget(parent), ui(new Ui::MainWidget{}) {ui-setupUi(this);setWindowTitle(usb controller);/// debug - widget{g_widgetDisplayBoard ui-textEdit;g_oldMessageHandler qInstallMessageHandler(newDebugHandlerFunc);}/// connect{connect(ui-btn_showAll, QPushButton::clicked, this,MainWidget::show_usbDeviceMsgAll);connect(ui-btn_clear, QPushButton::clicked, ui-textEdit,QTextEdit::clear);connect(ui-btn_start, QPushButton::clicked, this,MainWidget::start_work);connect(m_usb, TimerUsb::signal_message, this,[](const QString msg) { qInfo() msg; });}/// before exe{ show_usbDeviceMsgAll(); } }/*** brief MainWidget::~MainWidget* 将线程安全关闭*/ MainWidget::~MainWidget() {if (m_usb.isRunning()) {m_usb.quit();m_usb.wait();} }/*** brief MainWidget::show_usbDeviceMsgAll* 展示所有usb设备的信息* 因为设计的是通用库* 因此返回的是std::vectorstd::string*/ void MainWidget::show_usbDeviceMsgAll() {for (auto s : USB::Reset().Show_device()) {qDebug() s.c_str();} }/*** brief MainWidget::start_work* 检测线程启动*/ void MainWidget::start_work() {uint vendor ui-edit_Vendor-text().toUInt();double time ui-edit_timeout-text().toDouble();m_usb.Set_usbDeviceVendor(vendor);m_usb.Set_timerInterval(time * 1000);m_usb.Set_timerStart();if (false m_usb.isRunning()) {qDebug() start before ;m_usb.start();qDebug() start after ;} }WIDGET_Main.ui ?xml version1.0 encodingUTF-8? ui version4.0classMainWidget/classwidget classQWidget nameMainWidgetproperty namegeometryrectx0/xy0/ywidth726/widthheight480/height/rect/propertyproperty namewindowTitlestringUsbForm/string/propertylayout classQVBoxLayout nameverticalLayoutitemwidget classQTextEdit nametextEditproperty namestyleSheetstring notrtrue//property/widget/itemitemwidget classQWidget namewidget nativetruelayout classQGridLayout namegridLayoutitem row0 column1widget classQLineEdit nameedit_Vendorproperty namefontfontpointsize12/pointsize/font/propertyproperty nametextstring8746/string/property/widget/itemitem row0 column0widget classQLabel namelabel_Vendorproperty namefontfontpointsize12/pointsize/font/propertyproperty nametextstring目标Vendor/string/property/widget/itemitem row1 column0widget classQLabel namelabel_timeoutproperty namefontfontpointsize12/pointsize/font/propertyproperty nametextstring倒计时秒/string/property/widget/itemitem row1 column1widget classQLineEdit nameedit_timeoutproperty namefontfontpointsize12/pointsize/font/propertyproperty nametextstring2/string/property/widget/itemitem row2 column0widget classQPushButton namebtn_showAllproperty namefontfontpointsize18/pointsize/font/propertyproperty nametextstring设备usb列表/string/property/widget/itemitem row2 column1widget classQPushButton namebtn_clearproperty namefontfontpointsize18/pointsize/font/propertyproperty nametextstring清空列表/string/property/widget/item/layout/widget/itemitemwidget classQPushButton namebtn_startproperty namefontfontpointsize18/pointsize/font/propertyproperty nametextstring开始/string/property/widget/item/layout/widgetresources/connections/ /ui THREAD_TimerUsb.h #ifndef THREADUSB_H_70403004403 #define THREADUSB_H_70403004403#include QThread #include QTimerclass TimerUsb : public QThread {Q_OBJECT private:uint32_t m_usbDeviceVendor 0;private:QTimer m_timer;int m_timerIntervalMsec 1500;public:TimerUsb();public:void Set_usbDeviceVendor(uint32_t vendor);public:void Set_timerInterval(int msec 1500);void Set_timerStart();void Set_timerStop();bool Is_timerRunning();protected:void run() override;signals:void signal_message(const QString); };#endif // THREADUSB_H_70403004403THREAD_TimerUsb.cpp #include THREAD_TimerUsb.h#include QDebug #include QTimer#include usb/USB_Reset.h#if 0 #define DEBUG_MODEL qInfo() #else #define DEBUG_MODEL emit this-signal_message #endif/*** brief ThreadUsb::ThreadUsb* construct*/ TimerUsb::TimerUsb() {Set_timerInterval(); }/*** brief ThreadUsb::Set_usbDeviceVendor* param vendor* 根据 vendor 查询设备*/ void TimerUsb::Set_usbDeviceVendor(uint32_t vendor) {this-m_usbDeviceVendor vendor; }/*** brief ThreadUsb::Set_timerInterval* param msec* 设置reset间隔*/ void TimerUsb::Set_timerInterval(int msec) {this-m_timerIntervalMsec msec;m_timer.setInterval(m_timerIntervalMsec); }/*** brief TimerUsb::Set_timerStart* 启动定时器但不启动线程*/ void TimerUsb::Set_timerStart() {this-m_timer.start(); }/*** brief TimerUsb::Set_timerStop* 关闭定时器但不关闭线程*/ void TimerUsb::Set_timerStop() {this-m_timer.stop(); }/*** brief TimerUsb::Is_timerRunning* return* 定时器是否运行*/ bool TimerUsb::Is_timerRunning() {return this-m_timer.isActive(); }/*** brief ThreadUsb::run* 定时器timeout一次usb-reset一次*/ void TimerUsb::run() {USB::Reset usb;libusb_device* device nullptr;/// 为了防止刚启动的时候没有获得/// 高强度轮询获取const size_t loopDeviceCount 1e5 10;const size_t loopContextPeriod 1e3;for (size_t i 0; i loopDeviceCount; i 1) {device usb.Find_deviceByidVendor(this-m_usbDeviceVendor);if (nullptr ! device) {break;} else {if (i % loopContextPeriod 0) {DEBUG_MODEL(device is null context resert);USB::Reset::Reset_context();}}}if (nullptr device) {DEBUG_MODEL(libusb_device is null Thread end!);return;} else {DEBUG_MODEL(libusb_device require ok!);}libusb_device_handle* handle usb.Get_handleByOpenDevice(device);if (handle nullptr) {DEBUG_MODEL(libusb_device require is null Thread end!);return ;} else {DEBUG_MODEL(libusb_device_handle require ok!);}auto con connect(this-m_timer, QTimer::timeout, []() {int res usb.Reset_usbByHandle(handle);if (LIBUSB_SUCCESS res) {DEBUG_MODEL(reset Success);} else {DEBUG_MODEL(reset Error; errorType QString::number(res));}/// 句柄不归还持续重置// usb.Close_deviceByHandle(handle);});/// 开启事件循环exec();this-m_timer.stop();disconnect(con); }效果 界面功能比较简单基本就是widget中的代码设置好vendor和倒计时后点击开始即可。 目前身边没有可以测试的usb设备因此不展示具体效果。 其中USB::Reset是经过测试可用的。 描述 本demo主要就是libusb的封装然后是对于封装的简单调用。 重置reset 基本思路vendor-device*-handle* 然后使用handle*进行reset和最后的close。 获取device* 获取设备序列libusb_get_device_list()遍历序列获取每个设备的描述信息libusb_get_device_descriptor()对比描述信息确认是哪个device*。并测试是否能正常open。 获取handle* 通过libusb_open()即测试打开的同时就能获取 使用handle*进行reset 使用libusb_reset_device() 关闭handle* 使用libusb_close() 注意有的vendor是一样的编号请根据实际的情景和需求改变具体的查找规则。 热拔插 热拔插部分没有测试不做重点描述。 但是基本原理就是注册拔插的回调函数。 libusb_hotplug_register_callback() 标记LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED标记LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT 使用 全在QThread::run()函数中。 在实际作用时可能因为物理设备实际问题导致设备指针和句柄的获取失败。 因此可以设置一个比较大的循环无脑获取多次直到获取成功但若多次获取失败则直接视为失败了。 然后启动一个定时器 注意请不要close句柄。因为设备的实际请款可能关闭后就再获取不到了只要不随便乱插设备标号和句柄是不会变的因此直接保留好。直到真正不需要时再关闭根据实际业务和逻辑需求。 END
http://www.dnsts.com.cn/news/174979.html

相关文章:

  • 北京公司网站制作十大在线编程网站
  • 建立网站模板动效设计师是什么专业出来的
  • seo外链群发网站手机网站 开发者模式
  • 网站建设 思路wordpress添加搜索关键字
  • 无锡华诚建设监理有限公司网站在线建站|网页制作|网站建设平台
  • 无锡网站优化方案网站动态图是怎么做的
  • redis做缓存的网站并发数如何查看vs中建设好的网站
  • 上海做网站优化服务器平台搭建
  • 做网站 备案wordpress 界面 阴影
  • 分析学生做网站网络工程师中级证书
  • 小语言网站建设wordpress电影源码
  • windows建立网站上海区域划分
  • 做英文兼职的网站有哪些wordpress主题域名授权破解版
  • 虚拟空间能建多个网站为什么要更新网站
  • 深圳做小程序网站开发网站建设与管理课程实训
  • 网站建设教学视频教程wordpress 4.7优化
  • 网站建设的频道是什么网站建设太金手指六六二七
  • 网站检测器长沙营销网站建设公司
  • 做pc端网站什么开头海南网站建设推广公司
  • 用wordpress建立学校网站大数据开发培训机构哪家好
  • 商城网站建设大连一个公司做两个网站有影响吗
  • 网站维护需要多少钱工信部个人网站备案
  • 石家庄做网站网络公司装修设计费多少钱一平
  • 网站文件夹没有权限佛山网站建设公司怎么选
  • 做搜狗手机网站排深圳手机网站建设联系电话
  • 平潭建设局网站首页网站建设电话销售不被挂断
  • 建设网站的基本流程是什么设计制作公司网站
  • 华硕固件做网站6青岛网站开发哪家服务专业
  • 网站建设都有什么栏目上海网站建设的价格
  • 政务网站建设目标wordpress主题背景图片