使用VBNET创建应用程序_第1页
使用VBNET创建应用程序_第2页
使用VBNET创建应用程序_第3页
使用VBNET创建应用程序_第4页
使用VBNET创建应用程序_第5页
已阅读5页,还剩56页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、使用使用VB.Net创建一个应用程序创建一个应用程序 概述概述 使用我们之前保存的CogJobManager(CJM)可以在6个 简单的步骤中开发我们的应用程序。 每个步骤将教您VisionPro编程的一个方面的内容 q步骤1:创建并且运行最简单的应用程序。 q步骤2: 处理CJM“停止”事件。 q步骤3: 正确地处理CJM 事件。 q步骤4: 获取CJM结果。 q步骤5: 使用一个显示控件。 q步骤6: 执行自定义行为。 步骤步骤1 重要的事情先做重要的事情先做 打开VisualStudio 2005 创建一个VB.NET Windows应用程序并命名为 “VBSampleApp”。 添加参

2、数到.NET 集: qCognex.VisionPro 定义低级别对象 qCognex.VisionPro.Core 更多低级别的东西 qCognex.VisionPro.QuickBuild.Core CogJobManager 位于此处。 步骤步骤1 回顾参数回顾参数 我们为什么添加那些参数? 因为您必须明确地引用定义您想要使用的VisionPro类对象的任何集。 您需要知道哪些集包含哪些对象。 有两种方式可以帮助您了解: q文件:每个类页列出所需要的集。 q常识:用于斑点工具的对象在Cognex.VisionPro.Blob.dll中。用于斑点 的控件在Cognex.VisionPro.

3、Blob.Controls.dll中 步骤步骤1 名称空间名称空间 记住所有.NET对象在名称空间中定义 。 例如,低级别的VisionPro对象在 Cognex.VisionPro名称空间中。 CogJobManager 位于Cognex.VisionPro.QuickBuild名称空间中。 要了解VisionPro名称空间有多种方法: q文件:每个类页列出所有的名称空间。 qVisualStudio 对象浏览器显示所有的名称空间。 q常识:用于斑点类和控件的名称空间是Cognex.VisionPro.Blob。 步骤步骤1 导入您的名称空间导入您的名称空间 我们将“导入”我们想要使用的对象

4、的名称空间。 这会减少输入并且使得代码更清洁。 在VisualStudio中打开“Form1.vb”的代码窗口并在顶部 键入: Imports Cognex.VisionPro Imports Cognex.VisionPro.QuickBuild Public Class Form1 End Class 步骤步骤1 声明对象变量声明对象变量 另外在您的 “Form1”类中键入三个实例变量的声明: Public Class Form1 Private myJobManager As CogJobManager Private myJob As CogJob Private myIndepend

5、entJob As CogJobIndependent End Class 很快将使用到这些变量。 步骤步骤1 准备加载一个文件准备加载一个文件 复制AE_QBSample.vpp文件到您的“VBSampleApp”目 录下。 我们的应用程序将在开始时加载该文件并且萃取所保存 的CogJobManager。 以下为实现方法: q回到VisualStudio,切换标签到 GUI 设计器并在您的窗体上双 击。 q这会创建一个“Form1_Load()”方法,当首次加载您的应用程 序时会调用。 q在迅速复习事件操作者之后,我们会在该函数中加载我们 的.vpp文件。 步骤步骤1 复习事件操作者复习事件

6、操作者 记住 .NET事件允许对象在发生特殊事情时通知其他对象。 事件作为一个函数调用来执行。 要接受通知的对象必须: q定义一个方法在事件发生时调用。 q为该“操作者”提供一个指针指向发出通知的对象。 Form1_Load() 是一个事件操作者: 它处理窗体的加载事件。 当您在窗体上双击时,VisualStudio自动执行必要的动作: q定义Form1_Load()操作者,并且 q告知窗体在加载时调用该方法。 步骤步骤1 加载您的加载您的.vpp文件文件 现在让我们填写新的操作者。 将以下代码添加到Form1_Load: Depersist通过QuickBuild保存CogJobManage

7、r myJobManager = CType(CogSerializer.LoadObjectFromFile( _ .AE_QBSample.vpp), CogJobManager) 该代码使用CogSerializer加载给定的.vpp文件作为一 个.NET对象。 我们知道返回的对象实际上是一个CogJobManager,而 且我们在将其赋予我们的局部变量之前使用 “CType” 将其适当地强制转换。 步骤步骤1 变量初始化变量初始化 另外将以下代码也添加到Form1_Load: myJob = myJobManager.Job(0) myIndependentJob = myJob.Ow

8、nedIndependent 第一行初始化变量“myJob”引用CogJobManager中的 (并且只限)第一件工作。 第二行初始化一个参数引用包含更多关于 CogJobManager的信息的一个不同对象。 现在不必担心“独立的”东西。其为需要的但不是很重 要。 步骤步骤1 刷新所有刷新所有CJM队列队列 现在将以下代码添加到Form1_Load: 刷新队列 myJobManager.UserQueueFlush() myJobManager.FailureQueueFlush() myJob.ImageQueueFlush() myIndependentJob.RealTimeQueueF

9、lush() 这些行代码清空所有CogJobManager队列,刷新陈旧的 图像和结果。 将这些行作为样板代码处理:只是将它们逐字地添加到 使用所存储的CogJobManager的任何应用程序。 Form1_Load方法现在已经完成 。 步骤步骤1 完美地关闭完美地关闭 在窗体加载时我们只是初始化了我们的CJM,现在当关闭窗体时我 们也需要关闭CJM。 以下为操作步骤: q在VisualStudio中,从位于代码窗口顶部的右手下拉框中选择 “FormClosing”事件。 q这会创建一个Form1_FormClosing方法,在关闭窗体时调用。 q将以下代码添加到方法中: 确信关闭了CogJo

10、bManager! myJobManager.Shutdown() 将该代码添加到使用CogJobManager的任何应用程序。 步骤步骤1 无声的试验无声的试验 #1 现在您已经建立一个加载所保存的CogJobManager并且能适当地关 闭它的应用程序。 进行实验时: q在命令行中添加一个调用LoadObjectFromFile()的断点。 q运行您的应用程序。 q(现在可以是调整任何编译错误的最佳时间。) q当达到断点时,浏览“线程”窗口。 q有多少线程? q将调试程序进行到代码的下一行。 q现在您能看到多少线程? 步骤步骤1 为什么能完美地关闭?为什么能完美地关闭? 正如您所看到的,C

11、JM 建立了多个线程: CJM线程 您必须调用您必须调用CJM Shutdown()方法将它们适当地清除方法将它们适当地清除 掉。掉。 步骤步骤1 创建您的创建您的GUI 运行您的应用程序? 有点烦,嗯?决不要运行CJM。 停止运行应用程序,添加一个“运行一次(Run Once)”按钮。 以下为实现方法: q在VisualStudio中浏览 GUI设计器窗口。 q 将一按钮从工具箱的”常用控件”处拖到窗体上。 q将按钮的文本改为“运行一次”。 q修改按钮的名称为“运行一次按钮(RunOnceButton)”。 q在按钮上双击自动生成RunOnceButton_Click 方法。 步骤步骤1 添

12、加按钮代码添加按钮代码 我们想要RunOnceButton_Click运行的CogJobManager。 因此需要添加以下代码: Try myJobManager.Run() Catch ex As Exception MessageBox.Show(ex.Message) End Try 注意使用一个Try/Catch代码块以确保错误被适当地处理。 步骤步骤1 完成完成 我们现在已经完成了步骤1。 我们建立了一个简单的应用程序,使用我们保存的CJM并且可以自 行运行。 运行您的应用程序来测试它。点击“运行一次”按钮。享受成功带 来的喜悦吧。 现在尽可能快地点击运行一次按钮 注意您很快会从 “

13、CogJobManager1”得到一个错误。 享受够了吧。 在步骤2中,我们将学习这是什么样的错误,以及使用来自CJM的 事件来校正它。 步骤步骤2 校正错误校正错误 在步骤1中我们通过调用以下函数运行我们的CJM: myJobManager.Run() 问题在于我们忘记阅读一下手册: qRun() 是一个非同步方法:它开始运行我们的工作并且立即返回。 q如果您试图运行一个还没有完成的工作,Run() 会抛出一个错误。 校正方法:我们的应用程序应该使得“运行一次”按钮失效,直到 完成此前的运行。 要使得该按钮失效,在调用Run()之前需添加以下这行代码: RunOnceButton.Enabl

14、ed = False 步骤步骤2 CJM停止事件停止事件 当所有工作已经完成运行时,CJM启动一个“停止”事 件。 当该事件启动时我们将再次激活该按钮。 以下为实现方法: q在我们级别的最后,键入以下停止事件的操作者: Private Sub myJobManager_Stopped(ByVal sender As Object, _ ByVal e As CogJobManagerActionEventArgs) RunOnceButton.Enabled = True End Sub End Class 步骤步骤2 注册操作者注册操作者 除了声明我们的操作者之外,我们还必须确保我们的 CJ

15、M能调用它。 按照以下方法注册操作者: q在Form1_Load()的最后键入: 为停止事件注册操作者 AddHandler myJobManager.Stopped, _ AddressOf myJobManager_Stopped End Sub qAddHandler的第一个参数是我们想要处理的事件。 q其第二个参数是指向操作者的指针。 步骤步骤2 注销操作者注销操作者 在关闭之前注销CJM事件操作者总是个好主意。 按照以下方法注销操作者: q在Form1_FormClosing()的顶部键入: 为停止事件注销操作者 RemoveHandler myJobManager.Stopped,

16、 _ AddressOf myJobManager_Stopped 确保关闭CogJobManager! 步骤步骤2 关于关于VB.NET的一个警告的一个警告 一些VB用户不使用添加/删除操作者。 VisualStudio为VB应用程序中的事件提供不同的方法创建和注册操作者。 如果您声明一个变量为“WithEvents”,VisualStudio将显示该对象可用的 事件下拉列表。 从列表中选择一个事件将自动: q为其定义一个操作者,并且 q注册操作者和该对象。 这种技巧很“容易”但是不允许您控制注册或者注销操作者的时间。 在我们的应用程序中,停止事件必须在关闭CogJobManager之前注

17、销。 步骤步骤2 完成完成 现在我们完成了步骤2。 我们使用了CJM 停止事件确保用户不会运行工作,除非其已被停 止。 运行您的应用程序测试一下。点击“运行一次”按钮。 您会立即得到一个无效操作异常( InvalidOperationException )提 示“交叉线程运算无效” 。 开始对本课程的教员持有严重的怀疑。 在步骤3中我们将学习这是什么错误以及如何使用标准.NET函数来 校正它。 步骤步骤3 现在什么出错了呢?现在什么出错了呢? 我们又一次忘记阅读文件了。 这次我们需要看看微软的文件: 文件中说:每个Windows窗体控件只可以通过创建它的线程来访问。 还记得CJM创建的所有那些

18、线程吗? 它们没有在您的GUI上创建按钮,但是它们中的一个调用了您的停 止事件操作者。 并且您的事件操作者正在访问该按钮。 因此:出现一项错误。 步骤步骤3 校正大纲校正大纲 Microsoft有一个标准技巧用于校正该问题。以下为其工作的方法: q将其添加到您的停止事件操作者的顶部: If InvokeRequired Then 创建一个指针指向该函数 在正确的线程上调用同一个函数 Return End If q很快我们将使用真实代码替换注释。 q现在,注意“InvokeRequired”是每个控件的魔术属性。如果您处于 错误的线程上它会返回到“正确( True)”。 q如果我们处于错误的线程

19、上,其计划是切换到适当的线程并且递归 调用同一个函数。 步骤步骤3 创建一个委托创建一个委托 在.NET中有一个被称为“委托(delegate)”的函数指针。 在我们可以在正确的线程上调用我们的事件操作者之前,必须创建 一个指向它的委托。 以下为实现方法: q就在您的停止事件操作者之前添加该委托: 签名必须匹配CJM事件的委托。 Delegate Sub myJobManagerDelegate(ByVal sender As Object, _ ByVal e As CogJobManagerActionEventArgs) q这定义了一个有预期签名的委托。 q在您的事件操作者中适当的位置上

20、创建该委托的一个实例: 创建一个指向该函数的指针 Dim myDel As New myJobManagerDelegate( _ AddressOf myJobManager_Stopped) 步骤步骤3 使用适当的线程使用适当的线程 我们最终的方法是在适当的线程上调用我们的委托实例 (即我们的事件操作者)。 以下为实现方法:: q在您的事件操作者的正确地方添加以下这两行代码: 在正确的线程上调用同一个函数 Dim eventArgs() As Object = sender, e Invoke(myDel, eventArgs) q第一行为调用定义了一个数组参数。 q第二行使用控件的魔术“

21、调用( Invoke )”方法在GUI线程 上调用我们的委托。 步骤步骤3 完成完成 现在我们完成了步骤3。 我们使用不到10行的代码确保我们的按钮只可由创建它的线程访问。 我们使用的技巧是一个标准的微软做法。您应该彻底学习它,并且 在GUI项目可能被非适当线程调用的地方使用。 运行您的应用程序测试一下。点击“运行一次”按钮。注意不会有 更多的错误。 对本课程开始感觉好些了吧。 在步骤4中我们将开始让我们的GUI更加有意思。 步骤步骤4 优化优化GUI 在步骤4中我们将以两种方式更新GUI: q我们将添加一个“连续运行”按钮,并且 q我们将在我们工作运行时显示其运行状态。 我们先从“连续运行”

22、按钮开始。 我们想要该按钮在两个状态之间切换:“按下”和“未按”。 在“按下”状态我们的CJM应该处于运行中,而在“未按”状态我 们的CJM应该被停止。 得到这一动作的好办法是使用复选框控件来制作该按钮。 步骤步骤4 连续运行连续运行 以下为实现方法: 添加复选框: q在设计器中,将复选框拖放到您的窗体上。 q修改“外观”属性为“按钮”。 q修改按钮文本为“连续运行”。 q修改按钮名称为“运行内容检验盒( RunContCheckBox )”。 q在复选框上双击并且在其创建的“CheckedChanged”方法中键入下 列各行代码: If (RunContCheckBox.Checked) T

23、hen Try RunOnceButton.Enabled = False myJobManager.RunContinuous() Catch ex As Exception MessageBox.Show(ex.Message) End Try Else . . . 下页幻灯片继续. . . 步骤步骤4连续运行(续)连续运行(续) q继续键入: 另外 Try RunContCheckBox.Enabled = False myJobManager.Stop() Catch ex As Exception MessageBox.Show(ex.Message) End Try End If

24、该代码告诉我们CJM在复选框被勾选时,执行RunContinuous() 或 者Stop() 。 在我们开始运行时,它还使得“运行一次”按钮失效,而在我们等 待CJM停止时使得“连续运行”按钮失效。 步骤步骤4 连续运行(结束)连续运行(结束) 我们只需要再添加两行代码: q在停止事件操作者底部添加一行: RunOnceButton.Enabled = True RunContCheckBox.Enabled = True 在停止时激活 q在RunOnceButton_Clicked方法添加另一行如下代码: RunOnceButton.Enabled = False RunContCheckB

25、ox.Enabled = False 如果运行就失效 我们的新按钮已经完成。 花一分钟时间测试一下。 步骤步骤4避免死锁避免死锁 注意:我们现在可以在应用程序运行期间关闭它。 但很快如果用户关闭正在运行的应用程序,我们添加的 代码将会死锁。 要避免死锁,我们将防止用户在应用程序运行时关闭它。 在运行时,我们将删除允许用户关闭应用程序的“X” 按钮。 以下为实现方法:: q在RunOnceButton_Click() 中添加: ControlBox = False RunOnceButton.Enabled = False q在RunContCheckBox_CheckedChanged()中添

26、加: ControlBox = False RunOnceButton.Enabled = False q在myJobManager_Stopped()中添加: ControlBox = True RunOnceButton.Enabled = True “ControlBox”是您窗体的一个属性。它控件名称栏按 钮是否可见。 步骤步骤4 避免死锁(续)避免死锁(续) 步骤步骤4 显示运行状态(显示运行状态( RunStatus ) 现在我们将更新 GUI显示运行状态。 在您的窗体上添加一个文本框控件,将其命名为 “RunStatusTextBox”。 现在GUI 可能看起来有如下图: 步骤步

27、骤4 运行状态在使用者列队中运行状态在使用者列队中 步骤步骤4 事件和线程处理事件和线程处理 我们要从使用者列队中调取运行状态并在我们的新文本 框中显示。 这一切必须在我们将要编写的新事件操作者中将进行。 该操作者将用于UserResultAvailable事件。 什么线程会激活该事件? 什么线程被允许接触文本框? 没有关系。我们将不得不使用标准技巧避免交叉线程调 用。 步骤步骤4 编写操作者的代码编写操作者的代码 在我们级别的最后,添加一个新操作者: Private Sub myJobManager_UserResultAvailable( _ ByVal sender As Object,

28、 _ ByVal e As CogJobManagerActionEventArgs) If InvokeRequired Then 创建一个指针指向该函数 Dim myDel As New myJobManagerDelegate( _ AddressOf myJobManager_UserResultAvailable) 在正确的线程上调用同一个函数 Dim eventArgs() As Object = sender, e Invoke(myDel, eventArgs) Return End If End Sub End Class 这确保适当的线程处理(但是没有作用)。 现在给操作者

29、添加“真实”代码: Dim topRecord As Cognex.VisionPro.ICogRecord = _ myJobManager.UserResult RunStatusTextBox.Text = _ topRecord.SubRecords(UserResultTag).Content & : _ & topRecord.SubRecords(JobName).Content & - _ & topRecord.SubRecords(RunStatus).Content.ToString 在第一行调取下一个结果包。 注意您必须完全给予ICogRecord资格。 其他行代码创建

30、包含以下内容的字符串: q结果包的序列号, q公布该包的工作的名称,以及 q目标运行状态(作为一个字符串)。 该字符串被放置在文本框中。 步骤步骤4编写操作者的代码(续)编写操作者的代码(续) 步骤步骤4 注册操作者注册操作者 如以前一样,我们需要注册操作者: q在Form1_Load()的底部键入: 为UserResultAvailable事件注册操作者 AddHandler myJobManager.UserResultAvailable, _ AddressOf myJobManager_UserResultAvailable End Sub 按照以下方法注销操作者: q在Form1_F

31、ormClosing() 中键入: 为UserResultAvailable事件注销操作者 RemoveHandler myJobManager.UserResultAvailable, _ AddressOf myJobManager_UserResultAvailable 确保关闭CogJobManager! 现在我们完成了步骤4。 我们更新了我们的GUI使其更加“真实”。 我们学习了如何从使用者结果列队获得运行状态 (以及 其他信息)。 我们再次看到在编写GUI应用程序代码时必须细心考虑 线程。 运行您的应用程序测试一下。 在步骤5中,我们将使GUI更好。 步骤步骤4 完成完成 在步骤5

32、将通过添加一个显示图像的控件来改进我们应 用程序的GUI。 这将是我们第一个非微软的控件。 共有四个 VisionPro显示控件可供选择: CogToolDisplay CogRecordsDisplay CogRecordDisplay CogDisplay 1)让我们看看它们每个都能做些什么。 步骤步骤5 添加一个显示控件添加一个显示控件 CogToolDisplay: 这是您在QuickBuild中能够看见的“标准”控件。 它是四个控件中最复杂的一个。 它知道如何连接到VisionPro工具以及如何调取该工具的所有 检查记录。 它通过显示区上方的一个下列框允许用户选择浏览哪些图像 记录。

33、 步骤步骤5 CogToolDisplay CogRecordsDisplay: 该控件看起来与CogToolDisplay相同。 和CogToolDisplay一样,它允许用户通过下拉列表选择一个图 像记录。 而且和CogToolDisplay一样, 它显示所选图像的任何图形子记 录。 但是它对VisionPro工具一无所知。 该控件不能从相关的VisionPro工具获得一 个CogRecords树; 您必须使用编程的方法提供。 步骤步骤5 CogRecordsDisplay CogRecordDisplay: 该控件将显示单个图像记录及其图形的子记录。 该控件没有下拉列表框,不允许用户选择

34、图像。 CogRecordDisplay对 VisionPro 工具一无所知。 您必须为该控件提供一个包含单个图像的CogRecord树。 步骤步骤5 CogRecordDisplay CogDisplay: CogDisplay是最低级别的显示控件。 由所有其他显示控件来使用。 该控件对VisionPro工具或 CogRecords一无所知。 它不允许用户选择不同的图像。 该控件只显示一个图像和一组图形。 图像和图形必须通过编程来提供。 步骤步骤5 CogDisplay 对于我们自定义的应用程序我们将使用 CogRecordDisplay。 没有下拉框,因此我们的代码将控制在显示区显示的内

35、容。 我们将显示 “LastRun.CogFixtureTool1.OutputImage” 记录,因为它含有距离图形。 在VisualStudio中我们的第一步是引用包含我们控件的集: Cognex.VisionPro.Controls,和 Cognex.VisionPro.Display.Controls 步骤步骤5 选择选择CogRecordDisplay 步骤步骤5 添加添加CogRecordDisplay 现在: q将CogRecordDisplay拖放到窗体上。 q在它正下方放置CogDisplayStatusBar。 记住在关闭应用程序时要处理所有VisionPro控件 q在Fo

36、rm1_FormClosing() 底部添加: 明确地处理所有VisionPro控件 CogDisplayStatusBar1.Dispose() CogRecordDisplay1.Dispose() End Sub 连接CogDisplayStatusBar 到显示区: q在Form1_Load() 的底部键入: 连接状态栏 CogDisplayStatusBar1.Display = CogRecordDisplay1 End Sub 步骤步骤5 开始编码开始编码 在UserResultAvailable操作者的最后添加: Dim tmpRecord As Cognex.VisionPr

37、o.ICogRecord 假定所需记录存在并且取得。 tmpRecord = topRecord.SubRecords(ShowLastRunRecordForUserQueue) tmpRecord = tmpRecord.SubRecords(LastRun) tmpRecord = tmpRecord.SubRecords(CogFixtureTool1.OutputImage) CogRecordDisplay1.Record = tmpRecord CogRecordDisplay1.Fit(True) End Sub 这些代码进入结果包取得我们想要的图像记录。 然后记录被传递到显示

38、区。 步骤步骤5 完成编码完成编码 现在我们完成了步骤5。 我们学习了显示控件并在我们应用程序GUI中添加了一 个。 运行您的应用程序测试一下。 在步骤6中我们将添加更多的功能。 步骤步骤5 完成完成 步骤步骤6 定制您的应用程序定制您的应用程序 在VisualStudio中创建应用程序的主要原因在于提供自定 义动作。 我们将定制我们的应用程序这样用户可以从GUI中重新 训练PatMax 模型。 我们将添加一个复选框式按钮,允许用户看见训练图像 并操纵训练区域。 我们将添加一个单独的“重新训练”按钮,可以在显示 训练图像的时候按下。 您已经知道:每个Windows窗体控件只可以通过创建它的线程

39、来访 问。 在您执行自定义动作时您还必须记住:(几乎)每个VisionPro 对 象每次只能由一个线程使用。 例如,这意味着在视觉工具的工作运行期间您不得试图访问它。 您不可以读写属性或者调用方法。 这条规则的一个显著例外是:CogJob和CogJobManager中的队列可 以“同时”由多个线程使用。 步骤步骤6 再说说线程再说说线程 我们需要确保我们的应用程序遵守VisionPro的线程要求。 我们的计划是确保用户在应用程序运行期间不能重新训 练PatMax图案。 并且确保用户在他们重新训练图案时不能运行应用程序。 我们一次将只激活一组按钮。 步骤步骤6 关于线程关于线程 首先添加一个新的复选框到您的窗体上: q修改其“外观”属性为“按钮”。 q修改按钮的文本为“显示训练图像”。 q修改按钮名称为“显示训练检查盒 ( ShowTrainCheckBox )”。 另外还添加一个新按钮到您的窗体上: q修改按钮的文本为“重新训练”。 q修改按钮名称为“ 再训练按钮( RetrainButton )”。 q修改“激活”属性为“错误( False )”。 默认状态下我们已经使得我们的重新训练按钮失效。 步骤步骤6 添加自定义按钮添加自定义按钮 现在我们来添加一些代码,这样我们的复选框在运行 CJM时会失效: q在RunOnce

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论