CatchCulator






4.97/5 (69投票s)
一个用于捕获和合并不同应用程序输出值的工具。
引言
您是否曾有过这样的需求:在同一台机器上并行运行多个应用程序,同时需要监视它们的数值输出,有时还需要合并这些结果以得出重要结论?嗯,几周前我遇到了这种情况。我实际上在运行两个独立的应用程序,它们都在采集数据,并且都在屏幕上显示“大量”数值,这时我意识到我需要对这两个应用程序显示的某些值进行一些小计算。使用 MS 计算器并没有什么大问题,因为显示的值在不断变化,而且时不时地停止应用程序以便进行计算,结果却浪费了大量时间。
然后我问自己:如何在不一直停止和重启应用程序的情况下,在不需要一遍又一遍地在计算器上输入相同操作的情况下(很无聊,你知道吗?),甚至不需要查看那些应用程序显示的数值的情况下,获得我想要的结果?(有时,工程师确实喜欢数据充斥屏幕。)
这就是解决方案:CatchCulator。一个小型工具,具有巨大的改进潜力,能帮助我快速而干净地完成工作。
使用 CatchCulator
我编写了一个小型对话框应用程序,在两个编辑控件中显示两个值,以展示我的想法,并运行它的两个或更多实例。在实际应用中,您将使用任何您需要的应用程序,但有一点需要注意:输出值必须通过 CEdit
和/或 CStatic
派生对象输出。
现在假设您已经启动了需要监视的应用程序,您必须启动 CatchCulator。它会出现在屏幕上,伴随着一个“箭头”工具箱,您将使用它来精确定位您感兴趣的显示值。只需将箭头(蓝色箭头实际上是对话框标题栏的可见部分)拖到您感兴趣的值上方,然后单击“Try”按钮。CatchCulator 捕获的值将显示在该按钮下方。有可能您指向的 CEdit
或 CStatic
对象是创建在 CStatic
框架之上的,而实际上您捕获的是框架的标题。在这种情况下,单击“Hide”按钮,不需要的对象将被隐藏(别担心,包含该控件的应用程序不会出现任何问题)。再次单击“Try”按钮(在某些情况下可能需要重复此操作)。如果显示的值是您需要的,则单击“Catch”按钮,以便 CatchCalculator 了解您的选择。
捕获值后,先前隐藏的项目的可见性状态会自动恢复。一旦捕获了一个值,CatchCulator 就会为其分配一个名称,以便您以后可以将其作为变量引用。
您可以自行决定保留默认名称或将其重命名为更相关的名称。要重命名变量,请用鼠标单击选中其名称,过一会儿再单击一次(这是 CTreeCtrl
对象正常的行为,CatchCulator 代码实际使用了它)。完成变量捕获后,您可以继续告诉 CatchCulator 如何处理这些变量。这意味着您需要提供一些描述计算的脚本。您可能已经注意到,CatchCulator 配备了三个显示屏。每个显示屏都有一个指定的计算脚本。要编辑脚本,请按住 CTRL 键的同时右键单击所需的显示屏。脚本规则非常简单,并且只进行简单的语法检查。主要的是,您必须记住,每行脚本都必须有一个用尖括号括起来的名称和用操作符号分隔的两个操作数。对于当前版本的 CatchCulator,仅支持四个基本操作:*、/、+、-。根据对该工具的兴趣,我将提供对其他操作和函数的未来支持。分配给计算结果的名称可以进一步用作变量。每当您更改脚本时,请单击“Update script”按钮,以使修改生效。
默认情况下,任何计算结果都将显示为小数点后有 5 位数字的数字。您可以使用类似于 sprintf()
函数的语法指定自己的显示格式,但请注意,对于此工具,只有 %f
或 %lf
规范才有意义。
要更改显示格式,请按住 SHIFT 键的同时右键单击所需的显示屏。通过在格式规范中包含解释字符串,您可以使显示的結果更加清晰。要显示整数,请选择 %.0lf
规范。
分配给捕获值的变量名称可以随时修改,即使在脚本编辑完成后也可以。这些名称的任何更改都会自动反映在脚本中。如果您将名称留空,则在脚本中将显示为 NoName。请记住,您不必使用重复的变量名称,因为在这种情况下只有第一次出现的名称才会被考虑。
有两种模式可用于显示计算结果:手动模式和定时器模式。在手动模式下,每次单击相应的 D 按钮时,每个显示屏都会更新。D 按钮仅在手动模式下启用。要切换模式,请单击时钟按钮。在定时器模式下,显示屏会定期更新,无需您干预。默认更新时间为 100 毫秒。要更改此值,请单击带有问号 (?) 的时钟按钮,该按钮仅在定时器模式下启用。
其他可用命令包括
- 右键单击显示屏 - 清除显示屏
- 单击蓝色箭头按钮 - 显示捕获器(如果之前已关闭)
- 单击红色 X 按钮 - 移除所有捕获
- 单击带斜杠的 X 按钮 - 移除选定的捕获
定义脚本后,您可以将监视的应用程序发送到任务栏,以便在计算机显示器上只保留 CatchCulator 显示的信息。
背后的代码
捕获值
当捕获过程开始时,捕获器被定位在屏幕上箭头指向目标值的位置。包含该点的窗口的句柄通过调用 WindowFromPoint(ptAt)
来获取,其中 ptAt
是一个 CPoint
对象,存储了箭头点在屏幕坐标中的位置。然后使用该句柄 (hParent
) 来获取目标窗口的文本
HWND hParent; char chText[256]; ::GetWindowText(hParent, chText, 255);
如果返回的文本是空字符串,那么该窗口可能属于 CEdit
类(或其派生类)。因此,CatchCulator 会尝试读取此类控件的第一行(因为它可能是多行控件)
CEdit *pEdit; int N; pEdit = (CEdit *)FromHandle(hParent); N = pEdit->GetLine(0, chText, 255); chText[N] = 0; // null termination
生成的文本(如果存在)将显示在捕获器的“Try”按钮下方。
根据脚本进行计算
脚本的每一行都描述了一个计算单元,通过 Calculation
类实现
class Calculation { public: Calculation() { result = 0; opL = ""; opR = ""; } ~Calculation() {} CString resultName; CString operation; CString opL; // 1-opName, 2-opName (1 for caught var, 2 for computed value) CString opR; // or 3-value (for constant value) double result; };
分配给计算结果的名称存储在 resultName
中,而操作本身(*、/、+、-)则存储在 operation
中。根据操作数(左侧和右侧),需要考虑以下三种情况之一
- 操作数是已捕获的(被监视的变量)的名称
- 操作数是脚本中先前计算出的值的名称
- 操作数是常量值(一个数字)
每个操作的结果都存储在 result
中,该变量被初始化为 0。计算单元存储在一个 CList
对象中
CList <Calculation, Calculation> m_listToDo;
整个计算在 CCatchCulatorDlg::ProcessScript(CStaticDisplay *pDisplay)
函数中执行,该函数将指向相关显示屏的指针作为参数。操作数的值按以下方式获取:如果操作数是监视值的名称,则调用 CCatchCulatorDlg::ValueOf(char *varName)
并将该名称作为参数传递;如果名称已分配给计算出的值,则调用 CStaticDisplay::ComputedValue(char *varName)
并将该名称作为参数传递;或者如果操作数是数字的字符串表示形式,则调用 sscanf()
函数。将获得的值用作指定操作的操作数。操作结果存储在当前 Calculation
单元的 result
成员中。通过遍历 m_listToDo
列表,单元一个接一个地进行处理。最后一个单元在其 result
数据成员中包含最终结果,该结果实际上由相关显示屏显示。
历史
- 创建时间:2005 年 10 月。