You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将HDevEngine窗口嵌入wxWidgets面板?

将HDevEngine窗口嵌入wxWidgets面板的调整方案

HDevEngine作为C++环境下的脚本解释器,默认会弹出独立窗口显示运行结果,要把它嵌入wxWidgets现有面板,得从几个关键地方调整现有代码:

核心修改点

  • 修正变量名笔误:代码里的hDevProgram是拼写错误,应该替换成my_program,否则会触发编译错误。
  • 延长实例生命周期:当前my_engine和my_program是构造函数里的局部变量,构造完成后就会销毁,必须改成类的成员变量,否则程序执行时会出现资源释放问题。
  • 绑定窗口尺寸同步:wxWidgets面板的初始尺寸可能还没完全确定,要绑定wxEVT_SIZE事件,在面板尺寸变化时同步调整HALCON窗口的大小,避免显示错位。
  • 自定义OperatorImpl控制窗口创建:默认HDevEngine会自动新建窗口,得在MyHDevOperatorImpl里重写OpenWindow方法,强制使用我们预先绑定到wxPanel的窗口,禁止新建独立窗口。
  • 异步执行避免UI阻塞:直接在构造函数里执行Execute()会卡死wxWidgets界面,要把HDev程序的执行放到单独线程里。

修改后的完整代码

#include <wx/wx.h>
#include "HalconCpp.h"
#include "HDevEngineCpp.h"
#include "HDevThread.h"
#include "my_error_output.h"
#include "my_hdevoperatorimpl.h"

using namespace HalconCpp;
using namespace HDevEngine;

class MyFrame : public wxFrame
{
private:
    HDevEngine m_engine;
    HDevProgram m_program;
    Htuple m_windowID;
    wxPanel* m_panel1;

    // 用于异步执行HDev程序的线程类
    class HDevExecutionThread : public wxThread
    {
    private:
        HDevProgram m_program;
        Htuple m_windowID;
    public:
        HDevExecutionThread(const HDevProgram& program, const Htuple& windowID) 
            : wxThread(wxTHREAD_JOINABLE), m_program(program), m_windowID(windowID) {}

        virtual ExitCode Run() override {
            // 指定当前线程使用的绘图窗口
            HDevWindowStack::Push(m_windowID);
            try {
                HDevProgramCall program_call(m_program);
                program_call.Execute();
            } catch (HDevEngineException& e) {
                // 捕获并显示执行错误
                wxMessageBox(wxString(e.GetErrorMessage().CStr()), "执行错误", wxOK | wxICON_ERROR);
            }
            HDevWindowStack::Pop();
            return nullptr;
        }
    };

public:
    MyFrame(const wxString& title) 
        : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(800, 600))
    {
        // 创建布局结构
        wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
        m_panel1 = new wxPanel(this, wxID_ANY);
        wxPanel* panel2 = new wxPanel(this, wxID_ANY);

        sizer->Add(m_panel1, 1, wxEXPAND | wxALL, 5);
        sizer->Add(panel2, 1, wxEXPAND | wxALL, 5);
        SetSizer(sizer);

        // 初始化HDevEngine,绑定自定义Operator实现
        MyHDevOperatorImpl op_impl;
        m_engine.SetHDevOperatorImpl(&op_impl);

        // 加载目标HDev程序
        std::string program_path = Data::get().getAppData().PathHdev;
        m_program.LoadProgram(program_path.c_str());

        // 绑定尺寸变化事件,同步调整HALCON窗口
        Bind(wxEVT_SIZE, &MyFrame::OnSize, this);

        // 初始化HALCON窗口
        CreateHalconWindow();

        // 启动异步线程执行HDev程序
        HDevExecutionThread* thread = new HDevExecutionThread(m_program, m_windowID);
        if (thread->Run() != wxTHREAD_NO_ERROR) {
            wxMessageBox("无法启动执行线程", "错误", wxOK | wxICON_ERROR);
            delete thread;
        }
    }

    ~MyFrame() {
        // 销毁时关闭HALCON窗口
        if (HDevWindowStack::IsOpen()) {
            CloseWindow(HDevWindowStack::Pop());
        }
    }

private:
    void CreateHalconWindow() {
        // 先关闭已存在的窗口
        if (HDevWindowStack::IsOpen()) {
            CloseWindow(HDevWindowStack::Pop());
        }
        // 获取面板的客户区尺寸创建窗口
        wxSize size = m_panel1->GetClientSize();
        OpenWindow(0, 0, size.GetWidth(), size.GetHeight(), (Hlong)m_panel1->GetHandle(), "visible", "", &m_windowID);
        HDevWindowStack::Push(m_windowID);
    }

    void OnSize(wxSizeEvent& event) {
        // 延迟执行窗口调整,确保面板尺寸已更新
        wxCallAfter([this]() {
            CreateHalconWindow();
        });
        event.Skip();
    }
};

class MyApp : public wxApp
{
public:
    virtual bool OnInit() override {
        MyFrame *frame = new MyFrame("wxWidgets嵌入HDevEngine示例");
        frame->Show(true);
        return true;
    }
};

wxIMPLEMENT_APP(MyApp);

自定义OperatorImpl的关键修改

要彻底阻止HDevEngine新建独立窗口,必须在MyHDevOperatorImpl中重写OpenWindow方法,确保所有绘图都在指定的wxPanel窗口内进行:

class MyHDevOperatorImpl : public HDevOperatorImpl
{
public:
    virtual void OpenWindow(const Htuple& Row, const Htuple& Column, const Htuple& Width, const Htuple& Height, 
                           const Htuple& ParentWindowHandle, const Htuple& Mode, const Htuple& Machine, 
                           Htuple* WindowHandle) override {
        // 直接基于传入的父窗口句柄(wxPanel的句柄)创建窗口
        HalconCpp::OpenWindow(Row, Column, Width, Height, ParentWindowHandle, Mode, Machine, WindowHandle);
        // 禁止自动创建独立窗口,强制复用指定的父容器
    }
};

内容的提问来源于stack exchange,提问作者juanlg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 00:50:57