[返回博客](/cn/blog) # Drawings SDK：在数据库视口对象中安全使用 OdGsView 指针

Andrew Markovich 十一月 22, 2018 [\#.dwg](/cn/blog/tag/dwg) [\#Example](/cn/blog/tag/example) [\#getting started](/cn/blog/tag/getting-started)

<a class="a2a_button_facebook"></a><a class="a2a_button_twitter"></a><a class="a2a_button_linkedin"></a>

OdDbViewportTableRecord（模型空间视口）和 OdDbViewport（图纸空间视口）对象存储当前内部图形设备的 OdGsView 指针。这些指针可通过以下方法访问：

```
OdGsView* OdDbViewportTableRecord::gsView() const;

```

和

```
OdGsView* OdDbViewport::gsView() const
```

OdGsView 指针表示当前图形设备内部视口的当前运行时表示（如果存在）。

但是，如果您的应用程序为一个数据库调用多个设备，这些指针该如何处理？对象中只有一个指针，它无法存储多个设备的指针。

#### 问题案例示例

这些 OdGsView 指针在布局助手构建期间安装在数据库视口对象中，如本例所示：

```
OdGsModulePtr pGs = ::odrxDynamicLinker()->loadModule(OdWinGDIModuleName);
OdGsDevicePtr pDevice = pGs->createDevice();
pDwgContext->setDatabase(pDatabase);
pDevice = OdDbGsManager::setupActiveLayoutViews(pDevice, pDwgContext);

```

本例中的 OdDbGsManager::setupActiveLayoutViews 调用会创建一个布局助手对象并返回它。此调用后，您可以直接从数据库视口对象或使用 OdDbAbstractViewportData 助手类访问相关的 OdGsView 对象，如本例所示：

```
OdDbObjectPtr pViewportObject = pDatabase->activeViewportId().safeOpenObject();
OdDbAbstractViewportDataPtr pVpData(pViewportObject);
OdGsView *pGsView = pVpData->gsView(pViewportObject);

```

pGsView 指向先前构建的图形设备内部的实际运行时视口数据表示。

例如，应用程序当前使用此图形设备在屏幕上绘制图形。但现在假设您还需要将这些图形发送到打印机或使用另一个图形设备绘制打印预览：

```
OdGsDevicePtr pPrintDevice = pGs->createDevice();
pPrintDwgContext->setDatabase(pDatabase);
pPrintDevice = OdDbGsManager::setupActiveLayoutViews(pPrintDevice, pPrintDwgContext);

```

在第二次 OdDbGsManager::setupActiveLayoutViews 调用之后，数据库视口对象内部的 OdGsView 指针将切换到新的（打印）设备指针。

例如，打印完成后，您可以销毁打印设备。但数据库视口对象仍可能包含指向打印设备视图的指针，因此即使您已正确检查返回的指针是否为空，以下代码也可能导致应用程序崩溃：

```
OdDbObjectPtr pViewportObject = pDatabase->activeViewportId().safeOpenObject();
OdDbAbstractViewportDataPtr pVpData(pViewportObject);
OdGsView *pGsView = pVpData->gsView(pViewportObject);
if (pGsView != NULL)
  pGsView->zoomExtents(OdGePoint3d(-10.0, -10.0, -10.0), OdGePoint3d(-10.0, -10.0, -10.0)); // <-- potential crash

```

当然，在删除期间，设备会安全地将调用的指针设置为零，但这些指针在辅助设备使用后对应用程序来说并非实际有效。

#### 解决方案

可以使用特殊的布局助手方法解决此问题，该方法可恢复数据库视口对象中实际图形设备的 OdGsView 指针：

```
virtual void OdGsLayoutHelper::restoreGsViewDbLinkState() = 0;

```

当您完成使用另一个设备（例如打印）并切换回使用上一个设备时，您可以简单地更新数据库中的所有 OdGsView 链接：

```
OdGsLayoutHelper::cast(pDevice)->restoreGsViewDbLinkState();

```

最终解决方案非常简单明了。只需记住这些步骤中的最后一点：

- 构建辅助设备。
- 使用辅助设备。
- 完成辅助设备的工作。
- 切换到主设备并更新 OdGsView 数据库链接。

您可以随时从一个图形设备切换到任何其他图形设备，但在使用它们之前务必更新 OdGsView 链接，以保持数据库状态的一致性和安全性。

## 今天就开始行动

**免费试用 ODA 软件 60 天。  
无风险，无需信用卡。**

[免费试用](https://www.opendesign.com/cn/free-trial)
