QuakeGod
2023-10-23 4cda72771765720a6a8721bd8844945c2403afe6
提交 | 用户 | age
0ed438 1 
Q 2 // MultiTerminal2.cpp: 定义应用程序的类行为。
3 //
4
5 #include "pch.h"
6 #include "framework.h"
7 #include "afxwinappex.h"
8 #include "afxdialogex.h"
9 #include "MTerm2.h"
10 #include "MainFrm.h"
11
12 #include "ChildFrm.h"
13 #include "MTerm2Doc.h"
14 #include "MTerm2View.h"
15 #include "MTerm2LdsView.h"
16 #include "MTerm2BldView.h"
17 #include "MTerm2BnlView.h"
18
19 #include "MTerm2CoilView.h"
20 #include "MTerm2DataView.h"
21
22 #include "MTerm2TestView.h"
23 #include "MTerm2CtrlView.h"
24 #include "MTerm2ProgTxt.h"
25
26
27
28 #include "MTerm2CommDevView.h"
29
30 #ifdef _DEBUG
31 #define new DEBUG_NEW
32 #endif
33
34 #include <devguid.h>
35 #include <SetupAPI.h>
36 //#include "HvSerialPort.h"
37 //#include "CAnsiParser.h"
38 //#include "CDataParser1.h"
39 //#include "KLink.h"
40
41 #include <eh.h>
42 #include <dbghelp.h>
43 #pragma comment(lib,"dbghelp.lib")
44 #pragma comment(lib,"SetupAPI.lib")
45 #pragma comment(lib,"gdiplus.lib")
46
418cb3 47 #include "../KLink1/KLink.h"
0ed438 48
418cb3 49 #pragma comment(lib,"KLink1.lib")
0ed438 50 MHash MyCfg1;
Q 51 Logger myLogger1;
52
53 // CMTerm2App
54
55 BEGIN_MESSAGE_MAP(CMTerm2App, CWinAppEx)
56     ON_COMMAND(ID_APP_ABOUT, &CMTerm2App::OnAppAbout)
57     // 基于文件的标准文档命令
58 //    ON_COMMAND(ID_FILE_NEW, &CWinAppEx::OnFileNew)
59     ON_COMMAND(ID_FILE_NEW, &OnFileNew)
60     ON_COMMAND(ID_FILE_OPEN, &CWinAppEx::OnFileOpen)
61     // 标准打印设置命令
62     ON_COMMAND(ID_FILE_PRINT_SETUP, &CWinAppEx::OnFilePrintSetup)
63 //    ON_COMMAND(ID_COMUNICATION_SET, &CMTerm2App::OnComunicationSet)
64     ON_COMMAND(ID_ENV_SET, &CMTerm2App::OnEnvSet)
65 END_MESSAGE_MAP()
66
67
68 // CMTerm2App 构造
69
70 CMTerm2App::CMTerm2App() noexcept
71 {
65f713 72     m_bHiColorIcons = TRUE;
0ed438 73     // 支持重新启动管理器
Q 74     m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_ALL_ASPECTS;
75 #ifdef _MANAGED
76     // 如果应用程序是利用公共语言运行时支持(/clr)构建的,则: 
77     //     1) 必须有此附加设置,“重新启动管理器”支持才能正常工作。
78     //     2) 在您的项目中,您必须按照生成顺序向 System.Windows.Forms 添加引用。
79     System::Windows::Forms::Application::SetUnhandledExceptionMode(System::Windows::Forms::UnhandledExceptionMode::ThrowException);
80 #endif
81
82     // TODO: 将以下应用程序 ID 字符串替换为唯一的 ID 字符串;建议的字符串格式
83     //为 CompanyName.ProductName.SubProduct.VersionInformation
84     SetAppID(_T("MultiTerminal2.AppID.NoVersion"));
85
86     // TODO: 在此处添加构造代码,
87     // 将所有重要的初始化放置在 InitInstance 中
88 }
89
90 // 唯一的 CMTerm2App 对象
91
92 CMTerm2App theApp;
93
94
95 // CMTerm2App 初始化
96
97 BOOL CMTerm2App::InitInstance()
98 {
99     // 如果一个运行在 Windows XP 上的应用程序清单指定要
100     // 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
101     //则需要 InitCommonControlsEx()。  否则,将无法创建窗口。
102     INITCOMMONCONTROLSEX InitCtrls;
103     InitCtrls.dwSize = sizeof(InitCtrls);
104     // 将它设置为包括所有要在应用程序中使用的
105     // 公共控件类。
106     InitCtrls.dwICC = ICC_WIN95_CLASSES;
107     InitCommonControlsEx(&InitCtrls);
108
109     CWinAppEx::InitInstance();
110
111     if (!AfxSocketInit())
112     {
113         AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
114         return FALSE;
115     }
116
117     // 初始化 OLE 库
118     if (!AfxOleInit())
119     {
120         AfxMessageBox(IDP_OLE_INIT_FAILED);
121         return FALSE;
122     }
123
124     AfxEnableControlContainer();
125
126     EnableTaskbarInteraction(FALSE);
127
128     // 使用 RichEdit 控件需要 AfxInitRichEdit2()
129      AfxInitRichEdit2();
130
131     // 标准初始化
132     // 如果未使用这些功能并希望减小
133     // 最终可执行文件的大小,则应移除下列
134     // 不需要的特定初始化例程
135     // 更改用于存储设置的注册表项
136     // TODO: 应适当修改该字符串,
137     // 例如修改为公司或组织名
138     SetRegistryKey(_T("应用程序向导生成的本地应用程序"));
139     LoadStdProfileSettings(4);  // 加载标准 INI 文件选项(包括 MRU)
140
141
142     // 注册应用程序的文档模板。  文档模板
143     // 将用作文档、框架窗口和视图之间的连接
144 //    CMultiDocTemplate* pDocTemplate;
145     pDocTemplate = new CMultiDocTemplate(IDR_MTerm2TYPE,
146         RUNTIME_CLASS(CMTerm2Doc),
147         RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架
148         RUNTIME_CLASS(CMTerm2View));
149     if (!pDocTemplate)
150         return FALSE;
151     AddDocTemplate(pDocTemplate);
152 ///*
153 //    CMultiDocTemplate * m_pNewDocTemplate;
154 ///*
155     m_pLdsViewTemplate = new CMultiDocTemplate(IDR_MTerm2TYPE,
156         RUNTIME_CLASS(CMTerm2Doc),
157         RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架
158         RUNTIME_CLASS(CMTerm2LdsView));
159     if (!m_pLdsViewTemplate)
160         return FALSE;
161     AddDocTemplate(m_pLdsViewTemplate);
162
163     m_pBldViewTemplate = new CMultiDocTemplate(IDR_MTerm2TYPE,
164         RUNTIME_CLASS(CMTerm2Doc),
165         RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架
166         RUNTIME_CLASS(CMTerm2BldView));
167     if (!m_pBldViewTemplate)
168         return FALSE;
169     AddDocTemplate(m_pBldViewTemplate);
170
171     m_pBnlViewTemplate = new CMultiDocTemplate(IDR_MTerm2TYPE,
172         RUNTIME_CLASS(CMTerm2Doc),
173         RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架
174         RUNTIME_CLASS(CMTerm2BnlView));
175     if (!m_pBnlViewTemplate)
176         return FALSE;
177     AddDocTemplate(m_pBnlViewTemplate);
178
179     m_pCommDevViewTemplate = new CMultiDocTemplate(IDR_MTerm2TYPE,
180         RUNTIME_CLASS(CMTerm2Doc),
181         RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架
182         RUNTIME_CLASS(CMTerm2CommDevView));
183     if (!m_pCommDevViewTemplate)
184         return FALSE;
185     AddDocTemplate(m_pCommDevViewTemplate);
186
187
188     m_pCtrlViewTemplate = new CMultiDocTemplate(IDR_MTerm2TYPE,
189         RUNTIME_CLASS(CMTerm2Doc),
190         RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架
191         RUNTIME_CLASS(CMTerm2CtrlView));
192     if (!m_pCtrlViewTemplate)
193         return FALSE;
194     AddDocTemplate(m_pCtrlViewTemplate);
195
196     m_pProgViewTemplate = new CMultiDocTemplate(IDR_MTerm2TYPE,
197         RUNTIME_CLASS(CMTerm2Doc),
198         RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架
199         RUNTIME_CLASS(CMTerm2ProgTxt));
200     if (!m_pProgViewTemplate)
201         return FALSE;
202     AddDocTemplate(m_pProgViewTemplate);
203
204     m_pCoilViewTemplate = new CMultiDocTemplate(IDR_MTerm2TYPE,
205         RUNTIME_CLASS(CMTerm2Doc),
206         RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架
207         RUNTIME_CLASS(CMTerm2CoilView));
208     if (!m_pCoilViewTemplate)
209         return FALSE;
210     AddDocTemplate(m_pCoilViewTemplate);
211
212     m_pDataViewTemplate = new CMultiDocTemplate(IDR_MTerm2TYPE,
213         RUNTIME_CLASS(CMTerm2Doc),
214         RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架
215         RUNTIME_CLASS(CMTerm2DataView));
216     if (!m_pDataViewTemplate)
217         return FALSE;
218     AddDocTemplate(m_pDataViewTemplate);
219
220
221
222
223
224     m_pNewDocTemplate = new CMultiDocTemplate(IDR_MTerm2TYPE,
225         RUNTIME_CLASS(CMTerm2Doc),
226         RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架
227         RUNTIME_CLASS(CMTerm2TestView));
228     if (!m_pNewDocTemplate)
229         return FALSE;
230     AddDocTemplate(m_pNewDocTemplate);
231 //*/
232     // 创建主 MDI 框架窗口
233     CMainFrame* pMainFrame = new CMainFrame;
234     if (!pMainFrame || !pMainFrame->LoadFrame(IDR_MAINFRAME))
235     {
236         delete pMainFrame;
237         return FALSE;
238     }
239     m_pMainWnd = pMainFrame;
240
241
242     // 分析标准 shell 命令、DDE、打开文件操作的命令行
243     CCommandLineInfo cmdInfo;
244     ParseCommandLine(cmdInfo);
245
246     if (cmdInfo.m_nShellCommand == CCommandLineInfo::FileNew)
247         cmdInfo.m_nShellCommand = CCommandLineInfo::FileNothing;
248
249     // 调度在命令行中指定的命令。  如果
250     // 用 /RegServer、/Register、/Unregserver 或 /Unregister 启动应用程序,则返回 FALSE。
251     if (!ProcessShellCommand(cmdInfo))
252         return FALSE;
253     // 主窗口已初始化,因此显示它并对其进行更新
254     pMainFrame->ShowWindow(m_nCmdShow);
255     pMainFrame->UpdateWindow();
256     return TRUE;
257 }
258
259 int CMTerm2App::ExitInstance()
260 {
261     //TODO: 处理可能已添加的附加资源
262     AfxOleTerm(FALSE);
263
264     return CWinAppEx::ExitInstance();
265 }
266
267 // CMTerm2App 消息处理程序
268
269
270 // 用于应用程序“关于”菜单项的 CAboutDlg 对话框
271
272 class CAboutDlg : public CDialogEx
273 {
274 public:
275     CAboutDlg() noexcept;
276
277 // 对话框数据
278 #ifdef AFX_DESIGN_TIME
279     enum { IDD = IDD_ABOUTBOX };
280 #endif
281
282 protected:
283     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
284
285 // 实现
286 protected:
287     DECLARE_MESSAGE_MAP()
288 };
289
290 CAboutDlg::CAboutDlg() noexcept : CDialogEx(IDD_ABOUTBOX)
291 {
292 }
293
294 void CAboutDlg::DoDataExchange(CDataExchange* pDX)
295 {
296     CDialogEx::DoDataExchange(pDX);
297 }
298
299 BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
300 END_MESSAGE_MAP()
301
302 // 用于运行对话框的应用程序命令
303 void CMTerm2App::OnAppAbout()
304 {
305     CAboutDlg aboutDlg;
306     aboutDlg.DoModal();
307 }
308
309 // CMTerm2App 消息处理程序
310
311 void CMTerm2App::OnFileNew()
312 {
313     // TODO: 在此添加命令处理程序代码
314     POSITION ps = m_pDocManager->GetFirstDocTemplatePosition();
315     CDocTemplate *pDocTemplate = m_pDocManager->GetNextDocTemplate(ps);
316     pDocTemplate->OpenDocumentFile(NULL);
317 }
318
319
320
321 void CMTerm2App::OnComunicationSet()
322 {
323     // TODO: 在此添加命令处理程序代码
324 }
325
326
327 void CMTerm2App::OnEnvSet()
328 {
329     // TODO: 在此添加命令处理程序代码
330 }
331
332
333 int SysLog(CString s, int channel)
334 {
335     myLogger1.LogTxt(s, channel);
336     return 1;
337 }
338
339 int DbgLog(CString s, int channel)
340 {
341     myLogger1.LogTxt(s, channel);
342     return 1;
343 }
344
345 int PopupMessage(CString Msg, int channel)
346 {
347     Msg.Trim(_T("\r\n"));
348     SysLog(_T("报警信息: ") + Msg + _T("\r\n"), channel);
349     return 0;
350 }
351
352 void DoEvents()
353 {
354     MSG msg;
355     while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
356     {
357         DispatchMessage(&msg);
358         TranslateMessage(&msg);
359     }
360 }
361
362 void dump_callstack(PCONTEXT pcontext, CString & infostr)
363 {
364 #ifdef _WIN64
365
366     STACKFRAME64 sf;
367     memset(&sf, 0, sizeof(STACKFRAME64));
368
369     sf.AddrPC.Offset = pcontext->Rip;
370     //context->
371     sf.AddrPC.Mode = AddrModeFlat;
372     sf.AddrStack.Offset = pcontext->Rsp;
373     sf.AddrStack.Mode = AddrModeFlat;
374     sf.AddrFrame.Offset = pcontext->Rbp;
375     sf.AddrFrame.Mode = AddrModeFlat;
376
377     DWORD machineType = //IMAGE_FILE_MACHINE_I386;
378         IMAGE_FILE_MACHINE_AMD64;
379 #elif defined _WIN32
380     STACKFRAME sf;
381     memset(&sf, 0, sizeof(STACKFRAME));
382
383     sf.AddrPC.Offset = pcontext->Eip;
384     //context->
385     sf.AddrPC.Mode = AddrModeFlat;
386     sf.AddrStack.Offset = pcontext->Esp;
387     sf.AddrStack.Mode = AddrModeFlat;
388     sf.AddrFrame.Offset = pcontext->Ebp;
389     sf.AddrFrame.Mode = AddrModeFlat;
390
391     DWORD machineType = //IMAGE_FILE_MACHINE_I386;
392         IMAGE_FILE_MACHINE_AMD64;
393 #endif
394     HANDLE hProcess = GetCurrentProcess();
395     HANDLE hThread = GetCurrentThread();
396
397     for (;;)
398     {
399         if (!StackWalk(machineType, hProcess, hThread, &sf, pcontext, 0, SymFunctionTableAccess, SymGetModuleBase, 0))
400         {
401             break;
402         }
403
404         if (sf.AddrFrame.Offset == 0)
405         {
406             break;
407         }
408         BYTE symbolBuffer[sizeof(SYMBOL_INFO) + 1024];
409         PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)symbolBuffer;
410
411         pSymbol->SizeOfStruct = sizeof(symbolBuffer);
412         pSymbol->MaxNameLen = 1024;
413
414         DWORD64 symDisplacement = 0;
415         if (SymFromAddr(hProcess, sf.AddrPC.Offset, 0, pSymbol))
416         {
417             printf("Function : %s\n", pSymbol->Name);
418             infostr.AppendFormat(_T("Function : %S \r\n"), pSymbol->Name);
419         }
420         else
421         {
422             printf("SymFromAdd failed!\n");
423             //    infostr.AppendFormat(_T("SymFromAdd failed \r\n"),pSymbol->Name);
424         }
425
426         DWORD dwLineDisplacement;
427 #ifdef _WIN64
428         IMAGEHLP_LINEW64 lineInfoW = { sizeof(IMAGEHLP_LINEW64) };
429         if (SymGetLineFromAddrW(hProcess, sf.AddrPC.Offset, &dwLineDisplacement, &lineInfoW))
430         {
431             //        printf( "[Source File : %s]\n", lineInfo.FileName ); 
432             //        printf( "[Source Line : %u]\n", lineInfo.LineNumber ); 
433             CString s1(lineInfoW.FileName);
434             infostr.AppendFormat(_T("File %s Line %d\r\n"), s1.Mid(s1.ReverseFind(_T('\\')) + 1, 99), lineInfoW.LineNumber);
435         }
436         else
437         {
438             printf("SymGetLineFromAddr failed!\n");
439             //    infostr.Append(_T("SymGetLineFromAddr failed!\r\n"));
440         }
441 #elif defined _WIN32
442         IMAGEHLP_LINE lineInfo = { sizeof(IMAGEHLP_LINE) };
443         if (SymGetLineFromAddr(hProcess, sf.AddrPC.Offset, &dwLineDisplacement, &lineInfo))
444         {
445             //        printf( "[Source File : %s]\n", lineInfo.FileName ); 
446             //        printf( "[Source Line : %u]\n", lineInfo.LineNumber ); 
447             CString s1(lineInfo.FileName);
448             infostr.AppendFormat(_T("File %s Line %d\r\n"), s1.Mid(s1.ReverseFind(_T('\\')) + 1, 99), lineInfo.LineNumber);
449         }
450         else
451         {
452             printf("SymGetLineFromAddr failed!\n");
453             //    infostr.Append(_T("SymGetLineFromAddr failed!\r\n"));
454         }
455 #endif
456
457     }
458 }
459 DWORD excep_filter(LPEXCEPTION_POINTERS lpEP)
460 {
461     /**//// init dbghelp.dll
462     CString s1;
463     if (SymInitialize(GetCurrentProcess(), NULL, TRUE))
464     {
465         printf("Init dbghelp ok.\n");
466     }
467
468     dump_callstack(lpEP->ContextRecord, s1);
469
470     if (SymCleanup(GetCurrentProcess()))
471     {
472         printf("Cleanup dbghelp ok.\n");
473     }
474
475     return EXCEPTION_EXECUTE_HANDLER;
476 }
477
478 void Trans_Tunc(unsigned int n, EXCEPTION_POINTERS* pExp)
479 {
480     //    pExp->ExceptionRecord.
481     //    throw SE_Exception(n);
482     CString s1;
483     if (SymInitialize(GetCurrentProcess(), NULL, TRUE))
484     {
485         printf("Init dbghelp ok.\n");
486         //        s1=_T("Init dbghelp ok.\r\n");
487     }
488
489     dump_callstack(pExp->ContextRecord, s1);
490
491     if (SymCleanup(GetCurrentProcess()))
492     {
493         printf("Cleanup dbghelp ok.\n");
494         //        s1.Append(_T("Cleanup dbghelp ok.\n"));
495     }
496     throw SE_Exception(n, pExp->ExceptionRecord->ExceptionAddress, s1);
497 }
498
499 int DisplayException(CString File, int Line, CString Func, CString Sentence, SE_Exception &e)
500 {
501     CString Serror;
502     CString s1;
503     s1.Format(_T("程序发生SE异常 代码 %08X 地址 %p \r\nFile: %s \r\nLine: %d \r\nFunc %s \r\n语句 %s \r\n 信息\r\n %s \r\n"), e.getSeNumber(), e.getAddress(), File, Line, Func, Sentence, e.getInfoStr());;
504     PopupMessage(s1);
505     return 0;
506 }
507 int DisplayException(CString File, int Line, CString Func, CString Sentence, CException *e)
508 {
509     CString Serror;
510     CString s1;
511     e->GetErrorMessage(Serror.GetBuffer(256), 256);
512     Serror.ReleaseBuffer();
513     s1.Format(_T("程序发生C++异常 %s 在File: %s Line: %d Func %s Sentence %s \r\n"), Serror, File, Line, Func, Sentence);
514     PopupMessage(s1);
515     return 0;
516 }
517 int DisplayException(CString File, int Line, CString Func, CString Sentence)
518 {
519     CString s1;
520     s1.Format(_T("程序发生未知错误 File: %s Line: %d Func %s Sentence %s \r\n"), File, Line, Func, Sentence);
521     PopupMessage(s1);
522     return 0;
523 }
524
525
526 int LoadMyConfig()
527 {
528     CString ConfigFilePathName;
529     ConfigFilePathName = _T("./Settings.ini");
530     int j = MyCfg1.LoadFromFile(ConfigFilePathName);
531     return j;
532 }
533
534 int SaveMyConfig()
535 {
536     CString ConfigFilePathName;
537     ConfigFilePathName = _T("./Settings.ini");
538     int j = MyCfg1.SaveToFile(ConfigFilePathName);
539     return j;
540 }
541
542
543 //得到COMx的名字
544 //namebuf:用于存放名字的缓冲区
545 //bufsize:缓冲区大小
546 //comx:要查找的COM编号.例如:COM1,COM2,COM3....
547 //返回值:0,成功找到了.
548 //       1,失败.
549 int get_com_name(CString comx, CString &namebuf)
550 {
551     HDEVINFO hdinfo;
552     int res = 0;
553     SP_DEVINFO_DATA   hddevinfo = { sizeof(SP_DEVINFO_DATA) };
554     hdinfo = SetupDiGetClassDevs(&GUID_DEVCLASS_PORTS, 0, 0, DIGCF_PRESENT);//获取PORTS类别的已安装设备信息
555     if (hdinfo != INVALID_HANDLE_VALUE)//获取成功
556     {
557         for (int i = 0; SetupDiEnumDeviceInfo(hdinfo, i, &hddevinfo); i++)//轮询所有已安装设备
558         {
559             SetupDiGetDeviceRegistryProperty(hdinfo, &hddevinfo, SPDRP_FRIENDLYNAME, 0, (PBYTE)(namebuf.GetBuffer(2048)), 2048, 0);//获得单个装置的详细资料
560             namebuf.ReleaseBuffer();
561             if (namebuf.Find(comx) != -1) {
562                 res = 1; break;
563             }
564             //char *t;
565             //t = strstr(namebuf, comx);
566             //if (t)
567             //{
568             //    t--;
569             //    *t = '\0';//添加结束符,作用就是把"(COMX)"这段字符去掉
570             //    res = 0;
571             //    break;//成功找到了COMx的名字
572             //}
573         }
574     }
575     return res;
576 }
577
578 CString & intToString(int num)
579 {
580     static CString Str1;
581     Str1.Format(_T("%d"), num);
582     int k = Str1.GetLength();
583     int j = (k - 1) / 3;    //逗号个数
584     int l = k - j * 3; //起始位置
585     for (int i = l; i < k + j; i += 4)
586     {
587         Str1.Insert(i, _T(","));
588     }
589
590     return Str1;
591 }
592
593 CString & intToBinString(int num, int digits)
594 {
595     static CString Str1;
596     Str1.Empty();
597     int mask = 1 << (digits - 1);
598
599     for (int i = 0; i < digits; i++)
600     {
601         if (num&mask) Str1.Append(_T("*"));
602         else Str1.Append(_T("."));
603         mask >>= 1;
604     }
605     return Str1;
606 }