SMachineDlg.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. // SMachine.cpp: 实现文件
  2. //
  3. //#include <afx.h>
  4. #include "resource.h" // 主符号
  5. #include "stdafx.h"
  6. #include "SMachineDlg.h"
  7. //控件ID
  8. #define Dlg_Button_ManualTriggered 1 //手动触发事件按钮
  9. #define Dlg_Button_JumpToNext 2 //跳转至下一状态确认按钮
  10. #define Dlg_Edit_ManualEventName 101 //手动触发事件名称
  11. #define Dlg_Edit_NextStateName 102 //自动动触发事件名称
  12. #define Dlg_Edit_WaitEventList 103 //当前等待事件列表
  13. #define Dlg_Edit_RunHistory 104 //执行历史记录
  14. #define Dlg_Radio_GroupJump 301 //跳转方式
  15. #define Dlg_Radio_ManualJump 302 //手动跳转
  16. #define Dlg_Radio_AutoJump 303 //自动跳转
  17. #define Dlg_Check_1 201
  18. #define Dlg_Check_2 202
  19. SMachineDlg::CallMap SMachineDlg::g_HandleDlgMap; //消息处理窗口句柄集
  20. static int glo_BaseUnitX = LOWORD(GetDialogBaseUnits());
  21. static int glo_BaseUnitY = HIWORD(GetDialogBaseUnits());
  22. SMachineDlg::SMachineDlg(string title, string windowClass, SMDlgCallback object)
  23. {
  24. m_strTitle = title;
  25. m_strWindowClass = windowClass;
  26. m_DlgCallback = object;
  27. }
  28. SMachineDlg::~SMachineDlg()
  29. {
  30. if(m_hWnd)
  31. StopThread();
  32. }
  33. HWND SMachineDlg::GetWindowHandle()
  34. {
  35. return m_hWnd;
  36. }
  37. ATOM SMachineDlg::RegisterWindowClass(HINSTANCE hInstance)
  38. {
  39. WNDCLASSEX winDlg;
  40. memset(&winDlg, 0, sizeof(WNDCLASSEX));
  41. winDlg.lpszClassName = m_strWindowClass.c_str(); //设置类名称
  42. winDlg.cbSize = sizeof(WNDCLASSEX); //窗口类内存大小
  43. winDlg.cbClsExtra = 0; //为类额外分配内存,一般为0
  44. winDlg.cbWndExtra = 0; //为窗口额外分配内存,一般为0
  45. winDlg.style = CS_HREDRAW | CS_VREDRAW; //设置窗口格式,一般设置为水平重画与垂直重画:CS_HREDRAW | CS_VREDRAW
  46. winDlg.hIcon = LoadIcon(NULL, IDI_APPLICATION); //设置程序图标
  47. winDlg.hCursor = LoadCursor(NULL, IDC_ARROW); //设置程序光标
  48. winDlg.hbrBackground = (HBRUSH)GetStockObject(BLACK_PEN); //设置程序背景色:(HBRUSH)(COLOR_WINDOW + 1),(HBRUSH)GetStockObject(GRAY_BRUSH)
  49. //winDlg.lpszMenuName = MAKEINTRESOURCE(IDC_WIN32UI); //设置菜单名称
  50. //winDlg.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); //
  51. winDlg.lpfnWndProc = WndTotalProc; //窗口的回调函数,也就是窗口接收到消息后,交给哪个函数处理
  52. if (hInstance) //程序实例,这里就用到了WinMain函数的第一个参数hInstance
  53. winDlg.hInstance = hInstance;
  54. else
  55. winDlg.hInstance = GetModuleHandle(NULL);
  56. return RegisterClassEx(&winDlg); //填入要注册的窗口结构
  57. }
  58. HWND SMachineDlg::OpenWindow(int nCmdShow)
  59. {
  60. m_hWnd = CreateWindow(
  61. m_strWindowClass.c_str(), //窗口类名,也就是上面注册窗口类时填的类名
  62. m_strTitle.c_str(), //窗口名,也就是窗口显示时,左上角显示的名称
  63. WS_OVERLAPPED|WS_BORDER|WS_CAPTION|WS_SYSMENU, //窗口风格,一般填WS_OVERLAPPEDWINDOW即可,这样创建的窗口就有最大化,最小化等等等等属性
  64. CW_USEDEFAULT, //窗口最开始被创建位置,这里填X坐标,一般默认CW_USEDEFAULT即可
  65. CW_USEDEFAULT, //窗口最开始被创建位置,这里填Y坐标,一般默认CW_USEDEFAULT即可
  66. 100 * glo_BaseUnitX, //窗口创建的宽度,一般默认CW_USEDEFAULT即可
  67. 25 * glo_BaseUnitY, //窗口创建的高度,一般默认CW_USEDEFAULT即可
  68. NULL, //父窗口的句柄,没有,填NULL
  69. NULL, //菜单句柄,没有,填NULL
  70. GetModuleHandle(NULL), //应用程序实例,这里就又用到了WinMain的第一个参数
  71. NULL);//额外的数据,挺复杂的,咱们也不需要,填NULL就行了
  72. if (m_hWnd)
  73. {
  74. g_HandleDlgMap[m_hWnd] = this;
  75. ShowWindow(m_hWnd, nCmdShow); //显示窗口:SW_SHOWNORMAL
  76. if (UpdateWindow(m_hWnd)) //更新窗口客户区
  77. {
  78. m_ExitFlag = GetExitEvt();
  79. //添加界面元素
  80. CreateUIElement(m_hWnd);
  81. }
  82. }
  83. else
  84. {
  85. //mLog::FERROR("Create Window[{$}] failed", m_strTitle.c_str());
  86. }
  87. return m_hWnd;
  88. }
  89. void SMachineDlg::CreateUIElement(HWND& hMainWnd)
  90. {
  91. //创建元素
  92. auto FUN_CreateElement = [this, hMainWnd](int ID_Element) -> void
  93. {
  94. auto item = m_ElementMap.find(ID_Element);
  95. if (item != m_ElementMap.end())
  96. {
  97. if(nullptr == item->second.m_hHandle)
  98. item->second.m_hHandle = CreateWindow(
  99. item->second.m_strClassName.c_str(), item->second.m_strWindowName.c_str(),
  100. WS_CHILD | WS_VISIBLE | item->second.m_nStyle,
  101. item->second.m_nPosX * glo_BaseUnitX, item->second.m_nPosY * glo_BaseUnitY,
  102. item->second.m_nXsize * glo_BaseUnitX, item->second.m_nYsize * glo_BaseUnitY,
  103. hMainWnd,
  104. (HMENU)ID_Element,
  105. (HINSTANCE)GetWindowLongPtr(hMainWnd, GWLP_HINSTANCE),
  106. NULL);
  107. if (item->second.m_hHandle)
  108. {
  109. ShowWindow(item->second.m_hHandle, item->second.m_nShow);
  110. UpdateWindow(item->second.m_hHandle);
  111. }
  112. else
  113. {
  114. //mLog::FERROR("Create [{$}:{$}] failed", item->second.m_strClassName.c_str(), item->second.m_strWindowName.c_str());
  115. }
  116. }
  117. else
  118. {
  119. //mLog::FDEBUG("[{$}:{$}] already Create", item->second.m_strClassName.c_str(), item->second.m_strWindowName.c_str());
  120. }
  121. };
  122. m_ElementMap[Dlg_Button_ManualTriggered] = stuWindowElement("button", "ManualTriggered", BS_PUSHBUTTON, 1, 1, 20, 2, SW_SHOW);
  123. m_ElementMap[Dlg_Edit_ManualEventName] = stuWindowElement("edit", "ManualEventName", ES_MULTILINE, 27, 1, 20, 2, SW_SHOW);
  124. m_ElementMap[Dlg_Button_JumpToNext] = stuWindowElement("button", "JumpToNext", BS_PUSHBUTTON, 1, 4, 20, 2, SW_SHOW);
  125. m_ElementMap[Dlg_Edit_NextStateName] = stuWindowElement("edit", "NextStateName", ES_MULTILINE | ES_READONLY, 27, 4, 20, 2, SW_SHOW);
  126. m_ElementMap[Dlg_Radio_GroupJump] = stuWindowElement("button", "Auto or Manual Jump", BS_GROUPBOX, 0, 7, 48, 4, SW_SHOW);
  127. m_ElementMap[Dlg_Radio_ManualJump] = stuWindowElement("button", "AutoJump", BS_AUTORADIOBUTTON, 1, 8, 20, 2, SW_SHOW);
  128. m_ElementMap[Dlg_Radio_AutoJump] = stuWindowElement("button", "ManualJump", BS_AUTORADIOBUTTON, 27, 8, 20, 2, SW_SHOW);
  129. m_ElementMap[Dlg_Edit_WaitEventList] = stuWindowElement("edit", "WaitEventList", ES_MULTILINE | ES_READONLY | ES_AUTOVSCROLL, 49, 1, 48, 10, SW_SHOW);
  130. m_ElementMap[Dlg_Edit_RunHistory] = stuWindowElement("edit", "RunHistory", ES_MULTILINE | ES_READONLY | ES_AUTOVSCROLL, 1, 12, 96, 10, SW_SHOW);
  131. for (auto& item : m_ElementMap)
  132. {
  133. FUN_CreateElement(item.first);
  134. }
  135. }
  136. bool SMachineDlg::CloseWindow()
  137. {
  138. if (m_hWnd)
  139. {
  140. CallMap::iterator iter = g_HandleDlgMap.find(m_hWnd);
  141. if (iter != g_HandleDlgMap.end())
  142. {
  143. g_HandleDlgMap.erase(iter);
  144. }
  145. m_hWnd = nullptr;
  146. }
  147. return true;
  148. }
  149. bool SMachineDlg::OnStartThread()
  150. {
  151. //1.向系统注册一个窗体类
  152. RegisterWindowClass();
  153. //2.根据窗体类创建窗口
  154. return OpenWindow(SW_SHOW);
  155. }
  156. bool SMachineDlg::OnEndThread()
  157. {
  158. return CloseWindow();
  159. }
  160. bool SMachineDlg::Exec() //只会执行一次
  161. {
  162. MSG msg;
  163. while (WaitForSingleObject(m_ExitFlag, 0) == WAIT_TIMEOUT)
  164. {
  165. //3.进入消息循环
  166. if (GetMessage(&msg, //拿到的消息
  167. m_hWnd, //拿哪个窗口的消息,一般填NULL,即拿属于该线程所有窗口的消息
  168. 0, //过滤消息,最小值,一般填0
  169. 0) //过滤消息,最大值,一般填0,当两个均为0,则不进行过滤
  170. )
  171. {
  172. TranslateMessage(&msg); //消息转换,如将WMWM_KEYDOWN和WM_KEYUP翻译成一个WM_CHAR消息
  173. DispatchMessage(&msg); //该函数就是把消息派发给对应的窗口
  174. }
  175. else
  176. {
  177. return false;
  178. }
  179. }
  180. return false;
  181. }
  182. //窗口函数
  183. LRESULT SMachineDlg::WndTotalProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  184. {
  185. CallMap::iterator iter = g_HandleDlgMap.find(hWnd);
  186. if (iter != g_HandleDlgMap.end())
  187. {
  188. switch (message)//通过判断消息进行消息响应
  189. {
  190. case WM_CREATE: //应用程序创建一个窗口
  191. {
  192. return 0;
  193. }break;
  194. case WM_DESTROY: //一个窗口被销毁
  195. {
  196. PostQuitMessage(0); //发出WM_QUIT消息,结束消息循环
  197. iter->second->StopThread();
  198. return 0;
  199. }break;
  200. case WM_CLOSE: //当一个窗口或应用程序要关闭时发送一个信号
  201. {
  202. DestroyWindow(hWnd); //销毁窗口并发送WM_DESTROY消息,但是程序没有退出
  203. return 0;
  204. }break;
  205. //case WM_PAINT:
  206. //{
  207. // PAINTSTRUCT ps;
  208. // RECT rect;
  209. // HDC hdc = BeginPaint(hWnd, &ps);
  210. // SetRect(&rect, 10, 10, 300, 200);
  211. // FrameRect(hdc, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH));
  212. // GetClientRect(hWnd, &rect);
  213. // rect.left += 20;
  214. // rect.top += 2;
  215. // //SetTextColor(hdc, RGB(255,0,0)); //可以用RGB三原色设置文本颜色
  216. // DrawText(hdc, TEXT(" Hello, Dev-C++! "), -1, &rect, DT_SINGLELINE | DT_TOP | DT_LEFT);
  217. // EndPaint(hWnd, &ps);
  218. // return 0;
  219. //}break;
  220. case WM_COMMAND: //各控件的_click()事件
  221. {
  222. switch (LOWORD(wParam)) {
  223. case LOWORD(Dlg_Button_ManualTriggered):
  224. {
  225. if (iter->second->m_DlgCallback)
  226. {
  227. // 获取编辑控件的文本长度
  228. int length = GetWindowTextLength(iter->second->m_ElementMap[Dlg_Edit_ManualEventName].m_hHandle) + 1;
  229. // 创建一个字符串缓冲区
  230. std::vector<char> buffer(length);
  231. // 获取编辑控件的文本
  232. GetWindowText(iter->second->m_ElementMap[Dlg_Edit_ManualEventName].m_hHandle, buffer.data(), length);
  233. string temp = buffer.data();
  234. iter->second->m_DlgCallback("TriggerEvent", temp);
  235. }
  236. return 0;
  237. }break;
  238. case LOWORD(Dlg_Button_JumpToNext):
  239. {
  240. if (iter->second->m_DlgCallback)
  241. {
  242. iter->second->m_DlgCallback("SetRunningState", "");
  243. }
  244. return 0;
  245. }break;
  246. case LOWORD(Dlg_Radio_ManualJump):
  247. {
  248. iter->second->SetJumpMode(1);
  249. return 0;
  250. }break;
  251. case LOWORD(Dlg_Radio_AutoJump):
  252. {
  253. iter->second->SetJumpMode(0);
  254. return 0;
  255. }break;
  256. }
  257. }break;
  258. #if 0 //调试使用
  259. case WM_LBUTTONDOWN: // WM_LBUTTONDOWN是鼠标左键按下的事件
  260. {
  261. POINT mouse;
  262. RECT rect;
  263. GetCursorPos(&mouse);
  264. GetWindowRect(hWnd, &rect);
  265. int mX = mouse.x - rect.left;
  266. int mY = mouse.y - rect.top;
  267. char x[5]{ 0 }, y[5]{ 0 };
  268. _itoa(mX, x, 10);
  269. _itoa(mY, y, 10);
  270. string strXy = "坐标(" + string(x) + "," + string(y) + ")";
  271. SetWindowText(iter->second->m_ElementMap[Dlg_Edit_ManualEventName].m_hHandle, strXy.c_str());
  272. return 0;
  273. }break;
  274. #endif
  275. }
  276. }
  277. return DefWindowProc(hWnd, message, wParam, lParam); //对不感兴趣的消息进行缺省处理,必须有该代码,否则程序有问题
  278. }
  279. void SMachineDlg::SetJumpMode(int mode)
  280. {
  281. switch (mode)
  282. {
  283. case 0: //auto
  284. {EnableWindow(m_ElementMap[Dlg_Button_JumpToNext].m_hHandle, FALSE);
  285. EnableWindow(m_ElementMap[Dlg_Edit_NextStateName].m_hHandle, FALSE);
  286. SendMessage(m_ElementMap[Dlg_Radio_ManualJump].m_hHandle, BM_SETCHECK, 0, 0);
  287. SendMessage(m_ElementMap[Dlg_Radio_AutoJump].m_hHandle, BM_SETCHECK, 1, 0);
  288. }break;
  289. case 1: //manual
  290. {
  291. EnableWindow(m_ElementMap[Dlg_Button_JumpToNext].m_hHandle, TRUE);
  292. EnableWindow(m_ElementMap[Dlg_Edit_NextStateName].m_hHandle, TRUE);
  293. SendMessage(m_ElementMap[Dlg_Radio_ManualJump].m_hHandle, BM_SETCHECK, 1, 0);
  294. SendMessage(m_ElementMap[Dlg_Radio_AutoJump].m_hHandle, BM_SETCHECK, 0, 0);
  295. }break;
  296. default:
  297. break;
  298. }
  299. }
  300. void SMachineDlg::SetWaitEventList(string& text)
  301. {
  302. SetWindowText(m_ElementMap[Dlg_Edit_WaitEventList].m_hHandle, text.c_str());
  303. }
  304. void SMachineDlg::SetRunHistory(string& text)
  305. {
  306. SetWindowText(m_ElementMap[Dlg_Edit_RunHistory].m_hHandle, text.c_str());
  307. }