// MyDialog.cpp: 实现文件
//
#include "pch.h"
#include "Z3MFCLibrary.h"
#include "afxdialogex.h"
#include "MyDialog.h"
#include "zwapi_file.h"
#include "VxApi.h"
#include <windows.h>
#include <tlhelp32.h>
#include <oaidl.h>
#include <comdef.h>
#include <ocidl.h>
// 实现CreateClassEnumerator函数(解决链接错误)
HRESULT __stdcall CreateClassEnumerator(REFCLSID clsid, IEnumMoniker** ppenum, DWORD dwFlags)
{
if (ppenum == nullptr)
return E_INVALIDARG;
*ppenum = nullptr;
// 创建系统类枚举器
IEnumMoniker* pEnum = nullptr;
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, nullptr, CLSCTX_INPROC_SERVER,
IID_IEnumMoniker, (void**)&pEnum);
if (FAILED(hr))
return hr;
// 创建类枚举器
hr = pEnum->EnumClassesOfCategories(1, &clsid, 0, nullptr, ppenum);
pEnum->Release();
return hr;
}
IMPLEMENT_DYNAMIC(MyDialog, CDialogEx)
MyDialog::MyDialog(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_DIALOG1, pParent)
{
}
MyDialog::~MyDialog()
{
}
void MyDialog::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_BUTTON1, m_btn_export_import);
DDX_Control(pDX, IDC_COMBO1, m_cmbPMWindows);
}
BEGIN_MESSAGE_MAP(MyDialog, CDialogEx)
ON_BN_CLICKED(IDC_BUTTON1, &MyDialog::OnBnClickedExportAndImport)
END_MESSAGE_MAP()
// 对话框初始化
BOOL MyDialog::OnInitDialog()
{
CDialogEx::OnInitDialog();
RefreshPMInstances(); // 初始化时加载所有PowerMill实例
return TRUE;
}
// 枚举PowerMill窗口的回调函数(静态成员函数)
BOOL CALLBACK MyDialog::EnumPMWindowsProc(HWND hwnd, LPARAM lParam)
{
// 获取参数(实例信息向量的指针)
std::vector<PMInstanceInfo>* pInstances =
reinterpret_cast<std::vector<PMInstanceInfo>*>(lParam);
if (!pInstances) return TRUE;
// 检查窗口是否可见(使用全局API)
if (!::IsWindowVisible(hwnd)) return TRUE;
// 获取窗口标题(使用全局API)
TCHAR szTitle[256] = { 0 };
::GetWindowText(hwnd, szTitle, 255);
CString title = szTitle;
// 筛选标题包含"PowerMill"的窗口
if (title.Find(_T("PowerMill")) == -1) return TRUE;
// 获取进程ID(使用全局API)
DWORD processId = 0;
::GetWindowThreadProcessId(hwnd, &processId);
if (processId == 0) return TRUE;
// 添加到实例列表
PMInstanceInfo info;
info.index = pInstances->size() + 1; // 序号从1开始
info.processId = processId;
info.hwnd = hwnd;
info.title = title;
pInstances->push_back(info);
return TRUE;
}
// 刷新PowerMill实例列表(显示序号和进程ID)
void MyDialog::RefreshPMInstances()
{
m_pmInstances.clear();
m_cmbPMWindows.ResetContent();
// 枚举所有PowerMill窗口
::EnumWindows(EnumPMWindowsProc, reinterpret_cast<LPARAM>(&m_pmInstances));
// 添加到组合框(格式:序号 - PID:进程ID - 标题)
for (const auto& info : m_pmInstances) {
CString itemText;
itemText.Format(_T("%d - PID:%d - %s"),
info.index, info.processId, info.title.Left(30)); // 限制标题长度
m_cmbPMWindows.AddString(itemText);
}
// 默认选中第一个实例
if (m_pmInstances.size() > 0) {
m_cmbPMWindows.SetCurSel(0);
}
}
// 通过进程ID获取对应的PowerMill COM接口
IDispatch* MyDialog::GetPMInstanceByPID(DWORD pid)
{
// 初始化COM
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (FAILED(hr)) return nullptr;
// 获取PowerMill的CLSID
CLSID clsid;
hr = CLSIDFromProgID(L"PowerMILL.Application", &clsid);
if (FAILED(hr)) {
CoUninitialize();
return nullptr;
}
// 枚举所有正在运行的PowerMill实例
IEnumMoniker* pEnumMoniker = nullptr;
hr = CreateClassEnumerator(clsid, &pEnumMoniker, 0);
if (FAILED(hr) || !pEnumMoniker) {
CoUninitialize();
return nullptr;
}
IMoniker* pMoniker = nullptr;
IDispatch* pPMApp = nullptr;
ULONG fetched = 0;
// 遍历所有实例,匹配进程ID
while (pEnumMoniker->Next(1, &pMoniker, &fetched) == S_OK) {
// 获取实例的进程ID
DWORD instancePid = 0;
IBindCtx* pBindCtx = nullptr;
if (CreateBindCtx(0, &pBindCtx) == S_OK) {
ULONG len = 0;
LPOLESTR displayName = nullptr;
if (pMoniker->GetDisplayName(pBindCtx, nullptr, &displayName) == S_OK) {
// 从显示名称中提取进程ID(格式类似"PowerMILL.Application.19:1234")
CString displayStr(displayName);
int colonPos = displayStr.ReverseFind(':');
if (colonPos != -1) {
CString pidStr = displayStr.Mid(colonPos + 1);
instancePid = _ttoi(pidStr);
}
SysFreeString(displayName);
}
pBindCtx->Release();
}
// 匹配目标进程ID
if (instancePid == pid) {
// 获取该实例的COM接口
hr = pMoniker->BindToObject(nullptr, nullptr, IID_IDispatch, (void**)&pPMApp);
if (SUCCEEDED(hr)) {
pMoniker->Release();
break;
}
}
pMoniker->Release();
}
pEnumMoniker->Release();
CoUninitialize();
return pPMApp;
}
// 导出X_T文件
bool MyDialog::ExportXtFile(CString& filePath)
{
filePath = _T("C:\\Users\\Administrator\\Desktop\\Test.x_t");
svxPARAData exportData;
evxErrors result = cvxFileExportInit(VX_EXPORT_TYPE_PARA_TEXT, 0, &exportData);
if (result != ZW_API_NO_ERROR) {
AfxMessageBox(_T("初始化导出参数失败!"), MB_OK | MB_ICONERROR);
return false;
}
exportData.Coordinate = 0;
exportData.OutPut = 1;
exportData.FileVer = 19;
exportData.WriteFreeCrv = TRUE;
exportData.WriteFreePnt = FALSE;
exportData.HealErr = FALSE;
exportData.ExportType = 0;
exportData.ExcludeGeom = VX_EXCLUDE_BLANKED;
result = cvxFileExport(VX_EXPORT_TYPE_PARA_TEXT,
(LPCSTR)CStringA(filePath),
&exportData);
if (result != ZW_API_NO_ERROR) {
CString errMsg;
errMsg.Format(_T("X_T文件导出失败!错误代码: %d"), result);
AfxMessageBox(errMsg, MB_OK | MB_ICONERROR);
return false;
}
return true;
}
// 导入到选定的PowerMill实例
bool MyDialog::ImportToPowerMill(const CString& filePath)
{
// 检查文件是否存在
if (_taccess(filePath, 0) == -1) {
AfxMessageBox(_T("X_T文件不存在!"), MB_OK | MB_ICONERROR);
return false;
}
// 检查是否有选中的实例
int selectedIndex = m_cmbPMWindows.GetCurSel();
if (selectedIndex == CB_ERR || m_pmInstances.empty()) {
AfxMessageBox(_T("请先选择一个运行中的PowerMill实例!"), MB_OK | MB_ICONERROR);
return false;
}
// 获取选中实例的进程ID
DWORD targetPid = m_pmInstances[selectedIndex].processId;
// 获取对应实例的COM接口
IDispatch* pPMApp = GetPMInstanceByPID(targetPid);
if (!pPMApp) {
AfxMessageBox(_T("无法连接到选中的PowerMill实例!"), MB_OK | MB_ICONERROR);
return false;
}
// 执行导入命令
bool success = false;
try {
// 构造命令
CString command;
command.Format(_T("FORM RIBBON BACKSTAGE CLOSE IMPORT MODEL FILEOPEN \"%s\""), filePath);
// 获取命令执行方法ID(尝试常见方法名)
DISPID dispid;
LPOLESTR methodNames[] = { L"DoCommand", L"ExecuteCommand", L"RunCommand" };
HRESULT hr = E_FAIL;
for (auto methodName : methodNames) {
hr = pPMApp->GetIDsOfNames(IID_NULL, &methodName, 1, LOCALE_SYSTEM_DEFAULT, &dispid);
if (SUCCEEDED(hr)) break;
}
if (FAILED(hr)) {
throw _T("未找到可用的命令执行方法(DoCommand/ExecuteCommand/RunCommand)");
}
// 准备参数
VARIANT varArg;
VariantInit(&varArg);
varArg.vt = VT_BSTR;
varArg.bstrVal = SysAllocString(command);
DISPPARAMS dispParams = { &varArg, NULL, 1, 0 };
VARIANT result;
VariantInit(&result);
// 执行命令
hr = pPMApp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &dispParams, &result, NULL, NULL);
if (FAILED(hr)) {
throw _T("命令执行失败,可能是命令格式错误");
}
success = true;
VariantClear(&varArg);
VariantClear(&result);
}
catch (LPCTSTR errMsg) {
CString msg;
msg.Format(_T("导入失败:%s\n实例PID: %d"), errMsg, targetPid);
AfxMessageBox(msg, MB_OK | MB_ICONERROR);
}
// 释放资源
if (pPMApp) {
pPMApp->Release();
}
return success;
}
// 按钮点击事件
void MyDialog::OnBnClickedExportAndImport()
{
// 刷新实例列表(确保最新)
RefreshPMInstances();
// 检查是否有PowerMill实例在运行
if (m_pmInstances.empty()) {
AfxMessageBox(_T("未检测到运行中的PowerMill实例!"), MB_OK | MB_ICONERROR);
return;
}
// 导出X_T文件
CString xtFilePath;
if (!ExportXtFile(xtFilePath)) {
return;
}
// 导入到选定的PowerMill实例
if (ImportToPowerMill(xtFilePath)) {
CString msg;
msg.Format(_T("操作完成!\n已导入到PowerMill实例(PID: %d)"),
m_pmInstances[m_cmbPMWindows.GetCurSel()].processId);
AfxMessageBox(msg, MB_OK | MB_ICONINFORMATION);
}
}
严重性 代码 说明 项目 文件 行 抑制状态 详细信息
错误 C2039 "EnumClassesOfCategories": 不是 "IEnumMoniker" 的成员 Z3MFCLibrary C:\Users\Administrator\Desktop\Z3MFCLibrary\MyDialog.cpp 32
错误 C2065 “CLSID_SystemDeviceEnum”: 未声明的标识符 Z3MFCLibrary C:\Users\Administrator\Desktop\Z3MFCLibrary\MyDialog.cpp 26
错误(活动) E0020 未定义标识符 "CLSID_SystemDeviceEnum" Z3MFCLibrary C:\Users\Administrator\Desktop\Z3MFCLibrary\MyDialog.cpp 26
错误(活动) E0135 类 "IEnumMoniker" 没有成员 "EnumClassesOfCategories" Z3MFCLibrary C:\Users\Administrator\Desktop\Z3MFCLibrary\MyDialog.cpp 32
最新发布