如何把 Python 的 Console 窗口内嵌到我自己写的 MFC 程序窗口里边? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
lsj8924
V2EX    Python

如何把 Python 的 Console 窗口内嵌到我自己写的 MFC 程序窗口里边?

  •  
  •   lsj8924 2018-11-25 22:45:40 +08:00 4532 次点击
    这是一个创建于 2522 天前的主题,其中的信息可能已经有所发展或是发生改变。
    如题,因为我想在 mfc 里边和 py 交互,而且交互的过程又有实时的结果显示,所以想比较理想的就是嵌入一个 python 的 console 进去。
    自己实现了直接 createprocess 创建 cmd,但是同样的直接 createprocess python console 就卡死了。stdin 和 stdout 也没用。所以想干脆内嵌一个,不用 createprocess 了。
    有好的想法可以提一提。
    18 条回复    2018-11-26 15:58:19 +08:00
    darkcode
        1
    darkcode  
       2018-11-25 22:47:20 +08:00
    什么交互?
    lsj8924
        2
    lsj8924  
    OP
       2018-11-25 22:52:50 +08:00
    @darkcode 就是一条条的输入命令,然后一条条输出结果。
    ysc3839
        3
    ysc3839  
       2018-11-25 23:58:17 +08:00 via Android
    你需要实现的是 Pseudo Console,但是在 Win10 1809 才正式支持 Pseudo Console API。
    要在旧的系统中实现的话:
    要不然参照 ConEmu 去读取 Console 的内容。
    要不然直接将程序的 stdin 和 stdout 重定向到管道。
    不过管道这个方法可能会有问题,因为有的程序会调用 Console API 进行一些操作,重定向到管道之后这些操作会失败。
    ysc3839/td>
        4
    ysc3839  
       2018-11-26 00:01:05 +08:00 via Android   1
    我觉得更好的做法是通过别的途径进行交互,而不要使用 Console。
    Northxw
        5
    Northxw  
       2018-11-26 00:18:17 +08:00 via Android
    还有这种操作? 看来是我太 low 了
    watzds
        6
    watzds  
       2018-11-26 00:26:53 +08:00 via Android
    现在还用 mfc 的吗,我八年前学的时候就是老东西了,就是觉得复杂
    nifury
        7
    nifury  
       2018-11-26 01:03:34 +08:00   1
    404neko
        8
    404neko  
       2018-11-26 02:43:31 +08:00   1
    你想要的东西应该是 REPL

    首先你要会写一个 Shell {
    ` Shell 的本质是
    ` 从 stdin 按行读取用户输入
    ` 解析
    ` 做出反应
    ` 回到第一步
    }

    然后再在 Shell 基础上实现 REPL

    如何写一个 Python 的 REPL {
    ` 可以参考 Python 的官方[开发]文档 和 Python.h 中的定义
    ` 举个栗子
    ` PyObject *pModule,*pFunc;
    ` PyObject *pArgs, *pValue;
    `
    ` pModule = PyImport_Import(PyString_FromString("random")); //import random
    `
    ` pFunc = PyObject_GetAttrString(pModule, "random"); //获取 random.random
    `
    ` pArgs = NULL;
    `
    ` pValue = PyObject_CallObject(pFunc, pArgs); //调用 random.random()
    `
    ` res = PyInt_AsLong(pValue); //res 即是 random.random() 的返回值
    `
    ` 按照上边的
    ` 如果用户输出了 import string 那么就应该执行 pModule = PyImport_Import(PyString_FromString("string"));
    }

    其余的就算逻辑问题 就不多说了
    404neko
        9
    404neko  
       2018-11-26 02:44:57 +08:00
    V 站怎么还吞空格的
    devtk
        10
    devtk  
       2018-11-26 08:02:27 +08:00 via iPhone
    试试 PythonQt 我前一个月用过 和你的需求一模一样
    zwh2698
        11
    zwh2698  
       2018-11-26 08:06:00 +08:00 via Android   2
    直接将命令行的黑框的父窗体设置为 MFC 窗体,这个简单方便
    LokiSharp
        12
    LokiSharp  
       2018-11-26 08:16:08 +08:00 via iPhone
    用 PyQt 写吧 MFC 已经凉了很久了
    devtk
        13
    devtk  
       2018-11-26 08:23:32 +08:00
    @404neko 大佬~
    lsj8924
        14
    lsj8924  
    OP
       2018-11-26 12:04:54 +08:00
    统一回复:感谢楼上各位大佬。
    ksedz
        15
    ksedz  
       2018-11-26 14:22:10 +08:00
    不需要代码提示的话人工读入,然后按行 eval 就行。有更高的要求应该可以考虑从 ipython notebook 相关内容着手。
    arzterk
        16
    arzterk  
       2018-11-26 14:52:27 +08:00
    没那么复杂,我就搞过 mfc 嵌入 putty.exe ,代码如下:
    HANDLE hProcess = CreateProcess(...); // 用 cmd.exe /K python.exe 启动
    if (NULL == hProcess)
    {
    CMessageBox::Show(this, _T("FAILED TO START PUTTY"),
    CTextTraits::EMPTY_STRING, IDOK, MB_OK);
    return FALSE;
    }
    if (0 == ::WaitForInputIdle(hProcess, 1000))
    {
    m_wndTelnet = GetProcessMainWnd((DWORD)iProcessID);
    }
    CWnd *pWndPos = GetDlgItem(IDC_STATIC_POSITION); //嵌入的位置标识 ID
    if (NULL == pWndPos)
    {
    return FALSE;
    }
    CRect rcPos;
    pWndPos->GetWindowRect(&rcPos);
    ScreenToClient(&rcPos);
    rcPos.DeflateRect(1, 12, 1, 1);
    ::SetParent(m_wndTelnet, m_hWnd); // 窗口句柄 m_wndTelnet.
    ::SetWindowPos(m_wndTelnet, NULL, rcPos.left, rcPos.top
    , rcPos.Width(), rcPos.Height(), SWP_SHOWWINDOW);
    LONG lRet = ::SetWindowLong(m_wndTelnet, GWL_STYLE, 0x156B0000); // 这个魔术数字我也忘记啥意思了。
    直接就能在 cmd 里面输入参数了。。。。
    我还在外面搞了参数表格,拦截按钮事件把参数组好了往 m_wndTelnet 塞,
    ::SetForegroundWindow(hwndTelnet);
    for (int i = 0; i < strMsg.GetLength(); ++i)
    {
    TCHAR chKey = strMsg.GetAt(i);
    SHORT shTmp = VkKeyScan(chKey);
    BYTE byVKey = shTmp & 0xFF; // key
    bool bShift = (shTmp & 0x0100) == 0x0100 ? true : false;

    if (bShift)
    {
    keybd_event(VK_SHIFT, MapVirtualKey(VK_SHIFT, MAPVK_VK_TO_VSC), 0, 0);
    }

    keybd_eventbyVKey, MapVirtualKey(byVKey, MAPVK_VK_TO_VSC), 0, 0);
    keybd_event(byVKey, MapVirtualKey(byVKey, MAPVK_VK_TO_VSC), KEYEVENTF_KEYUP, 0);

    if (bShift)
    {
    keybd_event(VK_SHIFT, MapVirtualKey(VK_SHIFT, MAPVK_VK_TO_VSC), KEYEVENTF_KEYUP, 0);
    }
    }
    Sleep(100);
    keybd_event(VK_RETURN, MapVirtualKey(VK_RETURN, MAPVK_VK_TO_VSC), 0, 0);
    keybd_event(VK_RETURN, MapVirtualKey(VK_RETURN, MAPVK_VK_TO_VSC), KEYEVENTF_KEYUP, 0);
    arzterk
        17
    arzterk  
       2018-11-26 14:59:10 +08:00
    后来我用 Boost.python 自己弄 C++/PY 互相调用玩,
    搭建了一个简单的图形学绘制框架,支持用脚本绘制 D2D,由于太懒就没搞很复杂。

    lz 可以参考里面互相调用的部分,自己做个 repl 编辑器,然后 cpp/py 互相传数据。

    https://github.com/Liudx1985/D2DGraph/tree/master/DrawGraph
    zwh2698
        18
    zwh2698  
       2018-11-26 15:58:19 +08:00 via Android
    @arzterk 就那句 setparent 是核心
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     4113 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 20ms UTC 10:14 PVG 18:14 LAX 03:14 JFK 06:14
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86