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

2018-11-25 22:45:40 +08:00
 lsj8924
如题,因为我想在 mfc 里边和 py 交互,而且交互的过程又有实时的结果显示,所以想比较理想的就是嵌入一个 python 的 console 进去。
自己实现了直接 createprocess 创建 cmd,但是同样的直接 createprocess python console 就卡死了。stdin 和 stdout 也没用。所以想干脆内嵌一个,不用 createprocess 了。
有好的想法可以提一提。
3907 次点击
所在节点    Python
18 条回复
darkcode
2018-11-25 22:47:20 +08:00
什么交互?
lsj8924
2018-11-25 22:52:50 +08:00
@darkcode 就是一条条的输入命令,然后一条条输出结果。
ysc3839
2018-11-25 23:58:17 +08:00
你需要实现的是 Pseudo Console,但是在 Win10 1809 才正式支持 Pseudo Console API。
要在旧的系统中实现的话:
要不然参照 ConEmu 去读取 Console 的内容。
要不然直接将程序的 stdin 和 stdout 重定向到管道。
不过管道这个方法可能会有问题,因为有的程序会调用 Console API 进行一些操作,重定向到管道之后这些操作会失败。
ysc3839
2018-11-26 00:01:05 +08:00
我觉得更好的做法是通过别的途径进行交互,而不要使用 Console。
Northxw
2018-11-26 00:18:17 +08:00
还有这种操作? 看来是我太 low 了
watzds
2018-11-26 00:26:53 +08:00
现在还用 mfc 的吗,我八年前学的时候就是老东西了,就是觉得复杂
nifury
2018-11-26 01:03:34 +08:00
404neko
2018-11-26 02:43:31 +08:00
你想要的东西应该是 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
2018-11-26 02:44:57 +08:00
V 站怎么还吞空格的
kios
2018-11-26 08:02:27 +08:00
试试 PythonQt 我前一个月用过 和你的需求一模一样
zwh2698
2018-11-26 08:06:00 +08:00
直接将命令行的黑框的父窗体设置为 MFC 窗体,这个简单方便
LokiSharp
2018-11-26 08:16:08 +08:00
用 PyQt 写吧 MFC 已经凉了很久了
kios
2018-11-26 08:23:32 +08:00
@404neko 大佬~
lsj8924
2018-11-26 12:04:54 +08:00
统一回复:感谢楼上各位大佬。
ksedz
2018-11-26 14:22:10 +08:00
不需要代码提示的话人工读入,然后按行 eval 就行。有更高的要求应该可以考虑从 ipython notebook 相关内容着手。
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_event(byVKey, 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
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
2018-11-26 15:58:19 +08:00
@arzterk 就那句 setparent 是核心

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/511405

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX