MFC实现嵌入第三方exe程序到窗口中,显示StartProcess找不到标识符,如何改正;
参考一下链接
https://blog.csdn.net/m0_60352504/article/details/127062604
// MFCApplication1Dlg.cpp : 实现文件
//
#include "stdafx.h"
#include "MFCApplication1.h"
#include "MFCApplication1Dlg.h"
#include "afxdialogex.h"
#include "resource.h"
#include
#include "windows.h"
#include
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
class CAboutDlg : public CDialogEx
{
public:
CAboutDlg();
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_ABOUTBOX };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()
// CMFCApplication1Dlg 对话框
CMFCApplication1Dlg::CMFCApplication1Dlg(CWnd* pParent /*=NULL*/)
: CDialogEx(IDD_MFCAPPLICATION1_DIALOG, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CMFCApplication1Dlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CMFCApplication1Dlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON1, &CMFCApplication1Dlg::OnBnClickedButton1)
END_MESSAGE_MAP()
// CMFCApplication1Dlg 消息处理程序
BOOL CMFCApplication1Dlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 将“关于...”菜单项添加到系统菜单中。
// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
void InitStart();
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
void CMFCApplication1Dlg::InitStart()
{
///****************************************************/
HANDLE handle = StartProcess(_T("C:\\Windows\\system32\\notepad.exe"), _T(""));
Sleep(4000);//等待exe程序完全显示,酌情可删除
UpdateData(TRUE);
HWND m_hwnd = NULL;//.定义为全局
CRect rc;
//GetDlgItem(IDC_CRT)->GetClientRect(&rc);
GetDlgItem(IDC_STATIC)->GetWindowRect(&rc);//IDC_ECGVIEW静态文本控件ID
//m_EcgPic.GetWindowRect(&rc);
int nWidth = rc.Width();
int nHeight = rc.Height();
ScreenToClient(rc);
while (!m_hwnd)
{
//hwnd =::FindWindow("类名","窗口标题");
m_hwnd = ::FindWindow(NULL, _T("Develop"));//Develop Configuration
}
if (m_hwnd)
{
LONG style = GetWindowLong(m_hwnd, GWL_STYLE);// 14CF 0000
style &= ~WS_CAPTION;
style &= ~WS_THICKFRAME;
//style |=WS_CHILD;//*
SetWindowLong(m_hwnd, GWL_STYLE, style);
::SetParent(m_hwnd, this->m_hWnd);
::MoveWindow(m_hwnd, rc.left + 10, rc.top + 10, nWidth - 20, nHeight - 20, true); //将外部程序移到自自身窗口里//*
::SetWindowPos(m_hwnd, HWND_TOP, rc.left + 10, rc.top + 10, nWidth - 20, nHeight - 20, SWP_SHOWWINDOW | SWP_HIDEWINDOW);
// ::BringWindowToTop(m_hwnd);//*
// Invalidate();//*
//::UpdateWindow(m_hwnd);//*
::ShowWindow(m_hwnd, SW_SHOW);
}
/***************************************************************************/
}
void CMFCApplication1Dlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
}
// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。
void CMFCApplication1Dlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc() ), 0);
// 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CMFCApplication1Dlg::OnQueryDragIcon()
{
return static_cast(m_hIcon);
}
void CMFCApplication1Dlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
}
//program程序路径 args程序参数
HANDLE StartProcess(LPCTSTR program, LPCTSTR args)
{
HANDLE hProcess = NULL;
PROCESS_INFORMATION processInfo;
STARTUPINFO startupInfo;
::ZeroMemory(&startupInfo, sizeof(startupInfo));
startupInfo.cb = sizeof(startupInfo);
if (::CreateProcess(program, (LPTSTR)args,
NULL, // process security
NULL, // thread security
FALSE, // no inheritance
0, // no startup flags
NULL, // no special environment
NULL, // default startup directory
&startupInfo,
&processInfo))
return hProcess;
}
编译器是自上而下解析的,你在调用StartProcess函数时,这个函数的定义在调用处的下面,都还没解析,自然找不到.
在调用这个函数代码前面 加上 函数的声明
HANDLE StartProcess(LPCTSTR program, LPCTSTR args);
或者
你把函数的定义放到调用处的前面
等那个程序运行了,用findwindow找到handle
然后 setparent 即可
如果不要窗口边框,用 setwindowlong 去掉 captionbar 属性
在MFC应用程序中嵌入第三方EXE程序,可以使用MFC的CWnd类和Windows API的CreateProcess函数。在CreateProcess函数中,需要指定可执行文件的路径和命令行参数,以及启动进程的一些其他参数。然后,使用CWnd类的Create函数来创建一个窗口,并在窗口中嵌入刚刚创建的进程。
如果您遇到了“StartProcess找不到标识符”的错误,可能是因为您的代码中没有定义这个标识符。您需要确保在代码中正确地引用了该标识符。具体来说,StartProcess是一个函数或变量的名称,您需要在代码中定义这个函数或变量并初始化它,以便在程序运行时可以使用它。
以下是一个简单的示例代码,用于在MFC应用程序中嵌入Notepad程序:
// 定义命令行参数
LPCTSTR szCmdline = _T("notepad.exe");
// 启动进程
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
BOOL bSuccess = CreateProcess(NULL, (LPWSTR)szCmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
if (!bSuccess)
{
// 处理错误情况
return;
}
// 创建窗口并嵌入进程
CWnd* pWnd = new CWnd();
pWnd->CreateEx(0, AfxRegisterWndClass(0), NULL, WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, AfxGetMainWnd()->GetSafeHwnd(), NULL, NULL);
::SetParent(pi.hProcess, pWnd->GetSafeHwnd());
请注意,此代码仅适用于Windows操作系统,并且仅用于演示目的。实际应用程序中,您需要根据自己的需求进行适当的修改和调整。
基于最新版ChatGPT4的回答,望采纳!!!有其他问题也可以询问我哦、”(最新版更智能,功能更加强大)
在MFC中嵌入第三方exe程序到窗口中,可以通过使用CreateProcess
和SetParent
函数实现。首先创建一个新的进程来运行第三方exe程序,然后将该进程的主窗口嵌入到MFC应用程序的窗口中。
请注意,StartProcess
不是一个标准的Windows API函数。如果你遇到找不到标识符的错误,可能是因为你使用了错误的函数名。你应该使用CreateProcess
来启动新的进程。
以下是一个示例,演示如何在MFC应用程序中嵌入第三方exe程序:
#include <afxwin.h>
#include <iostream>
// 嵌入第三方exe程序到指定窗口
BOOL EmbedExternalApp(CWnd *pWndParent, const CString &strExePath)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
// 启动第三方exe程序
if (!CreateProcess(strExePath, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
{
std::cerr << "Failed to create process. Error code: " << GetLastError() << std::endl;
return FALSE;
}
// 等待进程创建窗口
Sleep(100);
// 获取第三方程序的主窗口句柄
HWND hWndExternalApp = ::FindWindow(NULL, _T("External App Window Title")); // 请将 External App Window Title 替换为第三方程序的窗口标题
if (hWndExternalApp == NULL)
{
std::cerr << "Failed to find external app window. Error code: " << GetLastError() << std::endl;
return FALSE;
}
// 将第三方程序的主窗口嵌入到MFC应用程序的窗口中
::SetParent(hWndExternalApp, pWndParent->m_hWnd);
return TRUE;
}
你可以将此EmbedExternalApp
函数添加到你的MFC应用程序中,并在适当的位置调用它。请确保提供正确的第三方exe程序路径和窗口标题。此外,根据需要,你可能需要调整Sleep
函数的参数以确保进程有足够的时间创建窗口。
例如,你可以在CMainFrame
类的OnCreate
方法中调用此函数,将第三方exe程序嵌入到MFC应用程序的主窗口中:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
// 嵌入第三方exe程序
EmbedExternalApp(this, _T("C:\\Path\\To\\Your\\ExternalApp.exe"));
return 0;
}
这个示例仅作为引导,你可能需要根据你的应用程序需求进行相应的调整。
参考GPT和自己的思路:在您提供的代码中,InitStart() 函数的声明是错误的,因为它包含在 BOOL CMFCApplication1Dlg::OnInitDialog() 函数内部。解决这个问题,您可以在头文件中声明 InitStart() 函数,然后在 .cpp 文件中定义它。此外,代码中使用了一个未定义的函数 StartProcess(),因此您需要确保该函数被正确定义和包含。
以下是代码的修改建议:
1 在头文件中声明 InitStart() 函数:
class CMFCApplication1Dlg : public CDialogEx
{
public:
CMFCApplication1Dlg(CWnd* pParent = nullptr);
virtual ~CMFCApplication1Dlg();
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_MFCAPPLICATION1_DIALOG };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
DECLARE_MESSAGE_MAP()
private:
void InitStart(); // 在此处声明函数
};
2 在 .cpp 文件中定义 InitStart() 函数:
void CMFCApplication1Dlg::InitStart()
{
CString strProgram = _T("C:\\Windows\\system32\\notepad.exe"); // 需要启动的程序的路径和文件名
PROCESS_INFORMATION processInfo = { 0 };
STARTUPINFO startupInfo = { 0 };
startupInfo.cb = sizeof(startupInfo);
// 启动程序
BOOL bSuccess = CreateProcess(strProgram, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInfo);
if (bSuccess)
{
// 延迟等待程序启动完全
Sleep(4000);
// 获取控件的位置和大小
CRect rc;
GetDlgItem(IDC_STATIC)->GetWindowRect(&rc); // 这里假设 IDC_STATIC 是要嵌入程序的控件 ID
ScreenToClient(rc);
// 查找程序的窗口句柄
HWND hWnd = NULL;
while (!hWnd)
{
hWnd = ::FindWindow(NULL, _T("Untitled - Notepad")); // 标题栏上显示的窗口标题
}
if (hWnd)
{
// 修改窗口样式
LONG style = GetWindowLong(hWnd, GWL_STYLE);
style &= ~WS_CAPTION;
style &= ~WS_THICKFRAME;
SetWindowLong(hWnd, GWL_STYLE, style);
// 将程序窗口嵌入到控件中
::SetParent(hWnd, GetDlgItem(IDC_STATIC)->m_hWnd);
::MoveWindow(hWnd, rc.left, rc.top, rc.Width(), rc.Height(), true);
::ShowWindow(hWnd, SW_SHOW);
}
}
}
请注意,FindWindow() 函数的第二个参数应该是您要嵌入的程序的窗口标题,而不是您的 MFC 对话框标题。在此代码中,我假设 Untitled - Notepad 是嵌入的程序的窗口标题。
3 修改 OnInitDialog() 函数,调用 InitStart() 函数:
BOOL CMFCApplication1Dlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 调用 InitStart() 函数
InitStart();
// 设置窗口图标
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
其中,InitStart() 函数可以是您定义的任何初始化函数,用于初始化对话框中的控件和数据。
参考GPT和自己的思路:
根据您的代码和问题描述,可能的原因是缺少定义或引用。在您的代码中,您声明了一个名为“InitStart”的函数,但是您没有实际定义它。因此,在您的OnInitDialog函数中调用此函数时,将出现未知标识符的错误。
为了解决此问题,您可以在C ++文件中实现InitStart函数。建议将它放在类的外部。此外,您可能还需要添加一些必要的头文件,如windows.h,afxwin.h和resource.h。
另外,您还需要定义StartProcess函数,或在代码中引用其定义,以便在初始化窗口时调用该函数执行第三方可执行文件。在您提供的代码中,StartProcess函数似乎只是返回“hProcess”,并没有实际完成任何其他操作。因此,您需要检查StartProcess函数的实现,以确保它正确执行。
最后,您可能还需要检查您的配置文件“resouces.h”,以确保您正确定义了STD_INCLUDES。如果您的代码中使用了此定义,则必须在resource.h文件中定义它。
在调试过程中,您可以查看VS调试器中的输出窗口以查看详细错误消息。这将有助于您确定是哪个文件、行或函数引发了错误,以及出错的具体原因。
参考GPT和自己的思路,你的代码中出现 "identifier not found" 的错误可能是因为你在 StartProcess 函数中使用了一个未定义的标识符 hProcess。你需要将 StartProcess 函数的返回语句改为返回 processInfo.hProcess,而不是 hProcess。
以下是已修正的 StartProcess 函数代码:
HANDLE StartProcess(LPCTSTR program, LPCTSTR args)
{
HANDLE hProcess = NULL;
PROCESS_INFORMATION processInfo;
STARTUPINFO startupInfo;
ZeroMemory(&startupInfo, sizeof(startupInfo));
startupInfo.cb = sizeof(startupInfo);
if (CreateProcess(program, (LPTSTR)args,
NULL, // 进程安全性
NULL, // 线程安全性
FALSE, // 不继承句柄
0, // 无启动标志
NULL, // 无特殊环境
NULL, // 默认启动目录
&startupInfo,
&processInfo))
hProcess = processInfo.hProcess;
return hProcess;
}
此外,你的代码中可能还存在以下问题:
1.在返回进程句柄之前,你应该检查 CreateProcess 函数调用是否成功。否则,你可能会得到一个无效的句柄。
2.hwnd 变量永远不会被设置为 NULL,因为 while(!hwnd) 循环会一直运行,直到找到一个窗口句柄。为了避免无限循环,你应该添加一个超时或限制循环的条件。
3.你使用 SWP_HIDEWINDOW 标志来设置窗口位置,这会在显示窗口后立即隐藏它。如果你想显示窗口,应该将此标志去掉。
希望这可以帮到你!
不知道你这个问题是否已经解决, 如果还没有解决的话:以下答案由GPT-3.5大模型与博主波罗歌共同编写:
在代码中调用了一个名为StartProcess
的函数,然而并未定义该函数,因此会报错“找不到标识符 StartProcess”。可以在代码中添加该函数的定义以解决此问题。同时,需要注意在定义该函数时,返回一个HANDLE
类型的句柄值。
以下是一个例子:
HANDLE StartProcess(LPCTSTR program, LPCTSTR args)
{
HANDLE hProcess = NULL;
PROCESS_INFORMATION processInfo;
STARTUPINFO startupInfo;
::ZeroMemory(&startupInfo, sizeof(startupInfo));
startupInfo.cb = sizeof(startupInfo);
if (::CreateProcess(program, (LPTSTR)args,
NULL, // process security
NULL, // thread security
FALSE, // no inheritance
0, // no startup flags
NULL, // no special environment
NULL, // default startup directory
&startupInfo,
&processInfo))
{
hProcess = processInfo.hProcess;
}
return hProcess;
}
此外,可以加入一些错误处理逻辑来检查CreateProcess
函数的返回值以及processInfo.hProcess
的值是否属于有效或正确的句柄值。例如:
HANDLE StartProcess(LPCTSTR program, LPCTSTR args)
{
HANDLE hProcess = NULL;
PROCESS_INFORMATION processInfo;
STARTUPINFO startupInfo;
::ZeroMemory(&startupInfo, sizeof(startupInfo));
startupInfo.cb = sizeof(startupInfo);
if (::CreateProcess(program, (LPTSTR)args,
NULL, // process security
NULL, // thread security
FALSE, // no inheritance
0, // no startup flags
NULL, // no special environment
NULL, // default startup directory
&startupInfo,
&processInfo))
{
if (processInfo.hProcess != NULL && processInfo.hProcess != INVALID_HANDLE_VALUE)
{
hProcess = processInfo.hProcess;
}
else
{
DWORD error = ::GetLastError();
TRACE(_T("Failed to get process handle: %d\n"), error);
}
}
else
{
DWORD error = ::GetLastError();
TRACE(_T("Failed to start process: %d\n"), error);
}
return hProcess;
}
如果我的回答解决了您的问题,请采纳!