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