Geant4 Cross Reference |
1 // 2 // ******************************************************************** 3 // * License and Disclaimer * 4 // * * 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. * 10 // * * 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitation of liability. * 17 // * * 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************************************** 25 // 26 // Original author: G.Barrand, 1998 27 // Rewrite: O.Pena-Rodriguez, March 2021 28 // -------------------------------------------------------------------- 29 30 #include "G4UIWin32.hh" 31 32 #include "G4MTcoutDestination.hh" 33 #include "G4StateManager.hh" 34 #include "G4UIcommand.hh" 35 #include "G4UIcommandTree.hh" 36 #include "G4UImanager.hh" 37 #include "G4Win32.hh" 38 39 #include <commctrl.h> 40 #include <windows.h> 41 #include <wingdi.h> 42 43 #include <cstring> 44 #include <utility> 45 46 /***************************************************************************/ 47 static char mainClassName[] = "G4UIWin32"; 48 static G4bool exitSession = true; 49 static G4bool exitPause = true; 50 static G4bool exitHelp = true; 51 static G4UIsession* tmpSession = nullptr; 52 53 // Original wndproc for the Combo Editor 54 static WNDPROC origComboEditorWindowProc; 55 56 static G4bool ConvertStringToInt(const char*, G4int&); 57 58 static G4int actionIdentifier = 0; 59 60 /****************************************************************************************************/ 61 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 62 G4UIWin32::G4UIWin32() 63 : fHWndMainWindow(nullptr), 64 fHWndEditor(nullptr), 65 fHWndToolBar(nullptr), 66 fHWndComboBox(nullptr), 67 fHWndComboEditor(nullptr), 68 fHWndHelpTree(nullptr), 69 fHWndStatus(nullptr), 70 menuBar(nullptr), 71 fHelp(false), 72 fHelpChoice(0), 73 fHistoryPos(-1) 74 { 75 G4UImanager* UI = G4UImanager::GetUIpointer(); 76 if (UI != nullptr) { 77 UI->SetSession(this); 78 UI->SetG4UIWindow(this); 79 } 80 81 // Ensure that the common control DLL is loaded 82 INITCOMMONCONTROLSEX commCtrls; 83 commCtrls.dwSize = sizeof(INITCOMMONCONTROLSEX); 84 commCtrls.dwICC = ICC_BAR_CLASSES | ICC_LISTVIEW_CLASSES; 85 // this loads list-view and toolbar classes. 86 InitCommonControlsEx(&commCtrls); 87 88 interactorManager = G4Win32::getInstance(); 89 90 static G4bool Done = false; 91 if (! Done) { 92 WNDCLASS wc; 93 wc.style = 0; 94 wc.lpfnWndProc = (WNDPROC)G4UIWin32::MainWindowProc; 95 wc.cbClsExtra = 0; 96 wc.cbWndExtra = 0; 97 wc.hInstance = ::GetModuleHandle(nullptr); 98 wc.hIcon = LoadIcon(nullptr, IDI_APPLICATION); 99 wc.hCursor = LoadCursor(nullptr, IDC_ARROW); 100 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); 101 wc.lpszMenuName = (PTSTR)mainClassName; 102 wc.lpszClassName = (PTSTR)mainClassName; 103 104 if (! RegisterClass(&wc)) { 105 MessageBoxA(nullptr, "G4UIWin32: Win32 window registration failed!", "Error!", 106 MB_ICONEXCLAMATION | MB_OK); 107 G4cout << "G4UIWin32: Win32 window registration failed!" << G4endl; 108 return; 109 } 110 111 Done = true; 112 } 113 114 menuBar = CreateMenu(); 115 116 // Add some initial options to the menu 117 HMENU hMenu = CreatePopupMenu(); 118 AppendMenuA(menuBar, MF_POPUP, (UINT_PTR)hMenu, "&Geant4"); 119 AddInteractor("Geant4", (G4Interactor)hMenu); 120 121 AppendMenuA(hMenu, MF_STRING, ID_OPEN_MACRO, "&Open macro..."); 122 AppendMenuA(hMenu, MF_STRING, ID_SAVE_VIEWER_STATE, "&Save viewer state..."); 123 AppendMenuA(hMenu, MF_SEPARATOR, -1, ""); 124 AppendMenuA(hMenu, MF_STRING, ID_RUN_BEAMON, "&Beam On"); 125 AppendMenuA(hMenu, MF_SEPARATOR, -1, ""); 126 AppendMenuA(hMenu, MF_STRING, ID_EXIT_APP, "E&xit"); 127 128 hMenu = CreatePopupMenu(); 129 AppendMenuA(menuBar, MF_POPUP, (UINT_PTR)hMenu, "&View"); 130 AddInteractor("View", (G4Interactor)hMenu); 131 132 AppendMenuA(hMenu, MF_STRING, ID_VIEW_SOLID, "S&olid"); 133 AppendMenuA(hMenu, MF_STRING, ID_VIEW_WIREFRAME, "&Wireframe"); 134 AppendMenuA(hMenu, MF_SEPARATOR, -1, ""); 135 AppendMenuA(hMenu, MF_STRING, ID_PROJ_ORTHOGRAPHIC, "&Orthographic"); 136 AppendMenuA(hMenu, MF_STRING, ID_PROJ_PERSPECTIVE, "P&erspective"); 137 AppendMenuA(hMenu, MF_SEPARATOR, -1, ""); 138 AppendMenuA(hMenu, MF_STRING, ID_ORIENTATION_XY, "&X-Y Plane"); 139 AppendMenuA(hMenu, MF_STRING, ID_ORIENTATION_XZ, "X-&Z Plane"); 140 AppendMenuA(hMenu, MF_STRING, ID_ORIENTATION_YZ, "&Y-Z Plane"); 141 AppendMenuA(hMenu, MF_STRING, ID_ORIENTATION_OBLIQUE, "&Oblique"); 142 143 hMenu = CreatePopupMenu(); 144 AppendMenuA(menuBar, MF_POPUP, (UINT_PTR)hMenu, "&Zoom"); 145 AddInteractor("Zoom", (G4Interactor)hMenu); 146 147 AppendMenuA(hMenu, MF_STRING, ID_ZOOM_IN, "Zoom &In"); 148 AppendMenuA(hMenu, MF_STRING, ID_ZOOM_OUT, "Zoom &Out"); 149 150 tmpSession = this; 151 char winName[] = "Geant4"; 152 fHWndMainWindow = ::CreateWindowEx(WS_EX_CLIENTEDGE, (PTSTR)mainClassName, (PTSTR)winName, 153 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 154 CW_USEDEFAULT, nullptr, menuBar, ::GetModuleHandle(nullptr), nullptr); 155 156 if (fHWndMainWindow == nullptr) { 157 MessageBoxA(nullptr, "Window Creation Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK); 158 return; 159 } 160 tmpSession = nullptr; 161 ::SetWindowLongPtr(fHWndMainWindow, GWLP_USERDATA, (LONG_PTR)this); 162 163 ::SetForegroundWindow(fHWndMainWindow); 164 ::ShowWindow(fHWndMainWindow, SW_SHOWDEFAULT); 165 ::UpdateWindow(fHWndMainWindow); 166 167 if (UI != nullptr) UI->SetCoutDestination(this); 168 169 // TODO: Manage multithreaded output 170 // #ifdef G4MULTITHREADED 171 // explicitly request that cout/cerr messages from threads are ALSO propagated to the master. 172 // masterG4coutDestination = this; 173 // #endif 174 } 175 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 176 /****************************************************************************************************/ 177 178 /****************************************************************************************************/ 179 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 180 G4UIWin32::~G4UIWin32() 181 { 182 G4UImanager* UI = G4UImanager::GetUIpointer(); 183 if (UI != nullptr) { 184 UI->SetSession(nullptr); 185 UI->SetG4UIWindow(nullptr); 186 UI->SetCoutDestination(nullptr); 187 } 188 189 // TODO: Manage multithreaded output 190 // #ifdef G4MULTITHREADED 191 // masterG4coutDestination = 0; // set to cout when UI is deleted 192 // #endif 193 194 if (fHWndStatus != nullptr) ::SetWindowLongPtr(fHWndStatus, GWLP_USERDATA, LONG(NULL)); 195 if (fHWndHelpTree != nullptr) ::SetWindowLongPtr(fHWndHelpTree, GWLP_USERDATA, LONG(NULL)); 196 if (fHWndComboBox != nullptr) ::SetWindowLongPtr(fHWndComboBox, GWLP_USERDATA, LONG(NULL)); 197 if (fHWndToolBar != nullptr) ::SetWindowLongPtr(fHWndToolBar, GWLP_USERDATA, LONG(NULL)); 198 if (fHWndEditor != nullptr) ::SetWindowLongPtr(fHWndEditor, GWLP_USERDATA, LONG(NULL)); 199 if (fHWndMainWindow != nullptr) { 200 ::SetWindowLongPtr(fHWndMainWindow, GWLP_USERDATA, LONG(NULL)); 201 ::DestroyWindow(fHWndMainWindow); 202 } 203 } 204 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 205 /****************************************************************************************************/ 206 207 /****************************************************************************************************/ 208 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 209 G4UIsession* G4UIWin32::SessionStart() 210 { 211 if (interactorManager != nullptr) { 212 Prompt("session"); 213 exitSession = false; 214 215 // TODO: Ensure that the list of commands is updated 216 // Load commands into Help Tree View 217 InitHelpTreeItems(); 218 219 interactorManager->DisableSecondaryLoop(); 220 void* event; 221 while ((event = interactorManager->GetEvent()) != nullptr) { 222 interactorManager->DispatchEvent(event); 223 if (exitSession) break; 224 } 225 interactorManager->EnableSecondaryLoop(); 226 return this; 227 } 228 else 229 return this; 230 } 231 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 232 /****************************************************************************************************/ 233 234 /****************************************************************************************************/ 235 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 236 void G4UIWin32::Prompt(const G4String& a_prompt) {} 237 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 238 /****************************************************************************************************/ 239 240 /****************************************************************************************************/ 241 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 242 void G4UIWin32::SessionTerminate() {} 243 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 244 /****************************************************************************************************/ 245 246 /****************************************************************************************************/ 247 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 248 void G4UIWin32::PauseSessionStart(const G4String& a_state) 249 { 250 if (a_state == "G4_pause> ") { 251 SecondaryLoop("Pause, type continue to exit this state"); 252 } 253 254 if (a_state == "EndOfEvent") { 255 // Picking with feed back in event data Done here !!! 256 SecondaryLoop("End of event, type continue to exit this state"); 257 } 258 } 259 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 260 /****************************************************************************************************/ 261 262 /****************************************************************************************************/ 263 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 264 void G4UIWin32::SecondaryLoop(const G4String& a_prompt) 265 { 266 if (interactorManager != nullptr) { 267 Prompt(a_prompt); 268 exitPause = false; 269 void* event; 270 while ((event = interactorManager->GetEvent()) != nullptr) { 271 interactorManager->DispatchEvent(event); 272 if (exitPause) break; 273 } 274 Prompt("session"); 275 } 276 } 277 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 278 /****************************************************************************************************/ 279 280 /****************************************************************************************************/ 281 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 282 G4int G4UIWin32::ReceiveG4debug(const G4String& a_string) 283 { 284 // Geant4 uses UNIX's style for new lines (\n) 285 // we must convert them to Windows' style (\r\n) 286 G4String str = ConvertNewLines(a_string); 287 288 AddText((LPSTR)str.data()); 289 290 return 0; 291 } 292 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 293 /****************************************************************************************************/ 294 295 /****************************************************************************************************/ 296 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 297 G4int G4UIWin32::ReceiveG4cout(const G4String& a_string) 298 { 299 // Geant4 uses UNIX's style for new lines (\n) 300 // we must convert them to Windows' style (\r\n) 301 G4String str = ConvertNewLines(a_string); 302 303 AddText((LPSTR)str.data()); 304 305 return 0; 306 } 307 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 308 /****************************************************************************************************/ 309 310 /****************************************************************************************************/ 311 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 312 G4int G4UIWin32::ReceiveG4cerr(const G4String& a_string) 313 { 314 // Geant4 uses UNIX's style for new lines (\n) 315 // we must convert them to Windows' style (\r\n) 316 G4String str = ConvertNewLines(a_string); 317 318 AddText((LPSTR)str.data()); 319 320 return 0; 321 } 322 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 323 /****************************************************************************************************/ 324 325 /****************************************************************************************************/ 326 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 327 G4bool G4UIWin32::GetHelpChoice(G4int& aInt) 328 { 329 fHelp = true; 330 331 if (interactorManager != nullptr) { 332 Prompt("Help"); 333 exitHelp = false; 334 void* event; 335 while ((event = interactorManager->GetEvent()) != nullptr) { 336 interactorManager->DispatchEvent(event); 337 if (exitHelp) break; 338 } 339 Prompt("session"); 340 // 341 if (! fHelp) return false; 342 aInt = fHelpChoice; 343 fHelp = false; 344 return true; 345 } 346 else 347 return false; 348 } 349 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 350 /****************************************************************************************************/ 351 352 /****************************************************************************************************/ 353 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 354 void G4UIWin32::ExitHelp() const {} 355 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 356 /****************************************************************************************************/ 357 358 /****************************************************************************************************/ 359 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 360 void G4UIWin32::AddMenu(const char* a_name, const char* a_label) 361 { 362 if (a_name != nullptr) { 363 HMENU hMenu = CreatePopupMenu(); 364 AppendMenuA(menuBar, MF_POPUP, (UINT_PTR)hMenu, a_label); 365 AddInteractor(a_name, (G4Interactor)hMenu); 366 DrawMenuBar(fHWndMainWindow); 367 } 368 } 369 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 370 /****************************************************************************************************/ 371 372 /****************************************************************************************************/ 373 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 374 void G4UIWin32::AddButton(const char* a_menu, const char* a_label, const char* a_command) 375 { 376 if ((a_menu != nullptr) && (a_label != nullptr) && (a_command != nullptr)) { 377 HMENU hMenu = (HMENU)GetInteractor(a_menu); 378 actionIdentifier++; 379 commands[actionIdentifier] = a_command; 380 AppendMenuA(hMenu, MF_STRING, actionIdentifier, a_label); 381 } 382 } 383 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 384 /****************************************************************************************************/ 385 386 /****************************************************************************************************/ 387 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 388 G4String G4UIWin32::GetCommand(G4int a_id) { return commands[a_id]; } 389 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 390 /****************************************************************************************************/ 391 392 /****************************************************************************************************/ 393 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 394 LRESULT CALLBACK G4UIWin32::MainWindowProc( 395 HWND aWindow, UINT aMessage, WPARAM wParam, LPARAM lParam) 396 { 397 switch (aMessage) { 398 case WM_CREATE: { 399 auto* This = (G4UIWin32*)tmpSession; 400 if (This != nullptr) { 401 if (! This->CreateComponents(aWindow)) { 402 MessageBoxA(aWindow, "Could not create components.", "Error", MB_OK | MB_ICONERROR); 403 return false; 404 } 405 } 406 } 407 return 0; 408 409 case WM_SIZE: { 410 auto* This = (G4UIWin32*)::GetWindowLongPtr(aWindow, GWLP_USERDATA); 411 if (This != nullptr) { 412 if (! This->ResizeComponents(aWindow)) { 413 MessageBoxA(aWindow, "Could not resize components.", "Error", MB_OK | MB_ICONERROR); 414 return false; 415 } 416 } 417 } 418 return 0; 419 420 case WM_CLOSE: 421 DestroyWindow(aWindow); 422 return 0; 423 424 case WM_DESTROY: 425 PostQuitMessage(0); 426 return 0; 427 428 case WM_SETFOCUS: { 429 auto* This = (G4UIWin32*)::GetWindowLongPtr(aWindow, GWLP_USERDATA); 430 if (This != nullptr) SetFocus(This->fHWndComboBox); 431 } 432 return 0; 433 434 case WM_NOTIFY: { 435 auto* This = (G4UIWin32*)::GetWindowLongPtr(aWindow, GWLP_USERDATA); 436 if (This != nullptr) { 437 switch (((LPNMHDR)lParam)->code) { 438 // Tooltip for Toolbar 439 case TTN_NEEDTEXT: { 440 auto lpttt = (LPTOOLTIPTEXT)lParam; 441 lpttt->hinst = nullptr; 442 UINT idButton = lpttt->hdr.idFrom; 443 lpttt->lpszText = (PTSTR)This->GetToolTips(idButton).c_str(); 444 } break; 445 446 // Tooltip for TreeView 447 case TVN_GETINFOTIP: { 448 auto pTip = (LPNMTVGETINFOTIP)lParam; 449 pTip->pszText = (PTSTR)This->GetHelpTreeToolTips(pTip->hItem).c_str(); 450 } break; 451 452 // Double click for TreeView 453 case NM_DBLCLK: { 454 auto lpnmh = (LPNMHDR)lParam; 455 auto item = TreeView_GetSelection(lpnmh->hwndFrom); 456 This->HelpTreeDoubleClick(item); 457 } break; 458 } 459 } 460 } 461 return 0; 462 463 case WM_COMMAND: { 464 auto* This = (G4UIWin32*)::GetWindowLongPtr(aWindow, GWLP_USERDATA); 465 if (This != nullptr) 466 if (! This->ProcessDefaultCommands(LOWORD(wParam))) 467 // If the command was not processed, do it now 468 switch (LOWORD(wParam)) { 469 case IDC_MAIN_EDIT: { 470 // We have to release some space when the buffer is full 471 if (HIWORD(wParam) == EN_ERRSPACE || HIWORD(wParam) == EN_MAXTEXT) { 472 G4int bufferSize = 473 SendMessage(This->fHWndEditor, EM_GETLIMITTEXT, (WPARAM)0, (LPARAM)0); 474 475 // Select the first third of the text 476 SendMessage(This->fHWndEditor, EM_SETSEL, (WPARAM)0, (LPARAM)bufferSize / 3); 477 // Delete it 478 SendMessage(This->fHWndEditor, EM_REPLACESEL, (WPARAM)0, (LPARAM) ""); 479 // Scroll to the bottom 480 SendMessage(This->fHWndEditor, WM_VSCROLL, SB_BOTTOM, NULL); 481 } 482 } break; 483 default: 484 if (! This->fHelp) { 485 G4String command = This->GetCommand(wParam); 486 This->ApplyShellCommand(command, exitSession, exitPause); 487 } 488 } 489 } 490 return 0; 491 default: 492 // For all the other cases, call the default window procedure. 493 return DefWindowProc(aWindow, aMessage, wParam, lParam); 494 } 495 } 496 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 497 /****************************************************************************************************/ 498 499 /****************************************************************************************************/ 500 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 501 LRESULT CALLBACK G4UIWin32::ComboEditorWindowProc( 502 HWND aWindow, UINT aMessage, WPARAM wParam, LPARAM lParam) 503 { 504 // We need to go two steps up: Editor -> ComboBox -> Window 505 HWND parent = GetParent(GetParent(aWindow)); 506 auto* This = (G4UIWin32*)::GetWindowLongPtr(parent, GWLP_USERDATA); 507 508 switch (aMessage) { 509 case WM_KEYDOWN: 510 switch (wParam) { 511 case VK_TAB: { 512 if (This != nullptr) { 513 if (This->fHelp) break; 514 515 This->ProcessTabKey(); 516 } 517 } 518 return 0; // Do not jump into origComboEditorWindowProc. 519 520 case VK_ESCAPE: { 521 if (This != nullptr) This->ProcessEscKey(); 522 } 523 return 0; // Do not jump into origComboEditorWindowProc. 524 525 case VK_RETURN: { 526 if (This != nullptr) This->ProcessEnterKey(); 527 } 528 return 0; // Do not jump into origComboEditorWindowProc. 529 530 case VK_UP: { 531 if (This != nullptr) This->ProcessUpKey(); 532 } 533 return 0; // Do not jump into origComboEditorWindowProc. 534 535 case VK_DOWN: { 536 if (This != nullptr) This->ProcessDownKey(); 537 } 538 return 0; // Do not jump into origComboEditorWindowProc. 539 } 540 break; 541 542 case WM_KEYUP: 543 case WM_CHAR: 544 switch (wParam) { 545 case VK_TAB: 546 case VK_ESCAPE: 547 case VK_RETURN: 548 case VK_UP: 549 case VK_DOWN: 550 return 0; // Do not jump into origComboEditorWindowProc. 551 } 552 } 553 554 // Call the original window procedure for default processing. 555 return CallWindowProc(origComboEditorWindowProc, aWindow, aMessage, wParam, lParam); 556 } 557 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 558 /****************************************************************************************************/ 559 560 /****************************************************************************************************/ 561 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 562 G4bool G4UIWin32::CreateComponents(HWND aWindow) 563 { 564 HFONT hfDefault; 565 TBBUTTON tbb[NUM_BUTTONS]; 566 TBADDBITMAP tbab; 567 RECT rcClient; // dimensions of client area 568 569 G4int statwidths[] = {100, -1}; 570 571 // Create Edit Control 572 char winName[] = "EDIT"; 573 char winParam[] = ""; 574 fHWndEditor = CreateWindowEx(WS_EX_CLIENTEDGE, (PTSTR)winName, (PTSTR)winParam, 575 WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | ES_MULTILINE | ES_AUTOVSCROLL | 576 ES_AUTOHSCROLL | ES_READONLY, 577 0, 0, 100, 100, aWindow, (HMENU)IDC_MAIN_EDIT, GetModuleHandle(nullptr), nullptr); 578 if (fHWndEditor == nullptr) 579 MessageBoxA(aWindow, "Could not create edit box.", "Error", MB_OK | MB_ICONERROR); 580 581 // Set editor font 582 // hfDefault = (HFONT) GetStockObject(DEFAULT_GUI_FONT); 583 hfDefault = CreateFontA(-10, -8, 0, 0, 0, false, 0, 0, OEM_CHARSET, OUT_RASTER_PRECIS, 584 CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FIXED_PITCH, "System"); 585 SendMessage(fHWndEditor, WM_SETFONT, (WPARAM)hfDefault, MAKELPARAM(false, 0)); 586 587 // Set editor's buffer size (the default value is too small) 588 SendMessage(fHWndEditor, EM_SETLIMITTEXT, (WPARAM)500000, (LPARAM)0); 589 590 // Create Toolbar 591 fHWndToolBar = CreateWindowEx(0, TOOLBARCLASSNAME, nullptr, 592 WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS, 0, 0, 0, 0, aWindow, 593 (HMENU)IDC_MAIN_TOOL, GetModuleHandle(nullptr), nullptr); 594 if (fHWndToolBar == nullptr) 595 MessageBoxA(aWindow, "Could not create tool bar.", "Error", MB_OK | MB_ICONERROR); 596 597 // Required for backward compatibility. 598 SendMessage(fHWndToolBar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), (LPARAM)0); 599 600 // Load standard images 601 tbab.hInst = HINST_COMMCTRL; 602 tbab.nID = IDB_STD_SMALL_COLOR; 603 SendMessage(fHWndToolBar, TB_ADDBITMAP, (WPARAM)0, (LPARAM)&tbab); 604 605 // Load history images 606 tbab.hInst = HINST_COMMCTRL; 607 tbab.nID = IDB_HIST_SMALL_COLOR; 608 SendMessage(fHWndToolBar, TB_ADDBITMAP, (WPARAM)0, (LPARAM)&tbab); 609 610 G4int btnBMP[NUM_BUTTONS] = {STD_FILEOPEN, STD_FILESAVE, -1, STD_FIND, STD_FIND, -1, 611 15 + HIST_FORWARD, -1, STD_HELP, -1, STD_FILENEW, STD_FILESAVE}; 612 G4int btnSTL[NUM_BUTTONS] = {TBSTYLE_BUTTON, TBSTYLE_BUTTON, TBSTYLE_SEP, TBSTYLE_BUTTON, 613 TBSTYLE_BUTTON, TBSTYLE_SEP, TBSTYLE_BUTTON, TBSTYLE_SEP, TBSTYLE_BUTTON, TBSTYLE_SEP, 614 TBSTYLE_BUTTON, TBSTYLE_BUTTON}; 615 G4int btnCMD[NUM_BUTTONS] = {ID_OPEN_MACRO, ID_SAVE_VIEWER_STATE, -1, ID_ZOOM_IN, ID_ZOOM_OUT, -1, 616 ID_RUN_BEAMON, -1, ID_HELP_ABOUT, -1, ID_LOG_CLEAN, ID_LOG_SAVE}; 617 ZeroMemory(tbb, sizeof(tbb)); 618 for (G4int i = 0; i < NUM_BUTTONS; i++) { 619 tbb[i].iBitmap = btnBMP[i]; 620 tbb[i].fsState = TBSTATE_ENABLED; 621 tbb[i].fsStyle = btnSTL[i]; 622 tbb[i].idCommand = btnCMD[i]; 623 } 624 625 SendMessage(fHWndToolBar, TB_ADDBUTTONS, sizeof(tbb) / sizeof(TBBUTTON), (LPARAM)&tbb); 626 627 // Create the Combobox 628 fHWndComboBox = CreateWindowEx(0, WC_COMBOBOX, TEXT(""), 629 CBS_DROPDOWN | CBS_HASSTRINGS | WS_CHILD | WS_OVERLAPPED | WS_VISIBLE, 150, 0, 200, 200, 630 aWindow, (HMENU)IDC_MAIN_COMBO, GetModuleHandle(nullptr), nullptr); 631 632 // Display an initial item in the selection field 633 SendMessage(fHWndComboBox, CB_SETCURSEL, (WPARAM)2, (LPARAM)0); 634 635 // Get aWindow of edit control in combobox created earlier. 636 fHWndComboEditor = FindWindowEx(fHWndComboBox, nullptr, WC_EDIT, nullptr); 637 638 // Change the window procedure for the edit windows to the subclass procedure. 639 origComboEditorWindowProc = 640 (WNDPROC)SetWindowLongPtr(fHWndComboEditor, GWLP_WNDPROC, (LONG_PTR)ComboEditorWindowProc); 641 642 // Create TreeView 643 644 // Get the dimensions of the parent window's client area, and create 645 // the tree-view control. 646 GetClientRect(aWindow, &rcClient); 647 fHWndHelpTree = CreateWindowEx(0, WC_TREEVIEW, TEXT("Tree View"), 648 WS_VISIBLE | WS_CHILD | WS_BORDER | TVS_INFOTIP | TVS_HASBUTTONS | TVS_HASLINES | 649 TVS_LINESATROOT, 650 0, 0, rcClient.right, rcClient.bottom, aWindow, (HMENU)IDC_MAIN_TREE_VIEW, 651 GetModuleHandle(nullptr), nullptr); 652 653 // Initialize the Help Tree View. 654 /* if (!InitHelpTreeItems()) { 655 DestroyWindow(fHWndHelpTree); 656 return false; 657 }*/ 658 659 // Create Status bar 660 fHWndStatus = CreateWindowEx(0, STATUSCLASSNAME, nullptr, WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP, 661 100, 100, 200, 200, aWindow, (HMENU)IDC_MAIN_STATUS, GetModuleHandle(nullptr), nullptr); 662 663 SendMessage(fHWndStatus, SB_SETPARTS, sizeof(statwidths) / sizeof(int), (LPARAM)statwidths); 664 // SendMessage(fHWndStatus, SB_SETTEXT, 0, (LPARAM) "Hi there :)"); 665 666 return true; 667 } 668 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 669 /****************************************************************************************************/ 670 671 /****************************************************************************************************/ 672 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 673 G4bool G4UIWin32::ResizeComponents(HWND aWindow) 674 { 675 RECT rcTool; 676 G4int iToolHeight, iToolWidth; 677 678 RECT rcStatus; 679 G4int iStatusHeight; 680 681 RECT rcComboBox; 682 G4int iComboBoxHeight; 683 684 G4int iTreeViewHeight, iTreeViewWidth; 685 G4int iEditHeight, iEditWidth; 686 687 RECT rcClient; 688 689 // Size toolbar and get height and width 690 SendMessage(fHWndToolBar, TB_AUTOSIZE, 0, 0); 691 692 GetWindowRect(fHWndToolBar, &rcTool); 693 iToolHeight = rcTool.bottom - rcTool.top; 694 iToolWidth = rcTool.right - rcTool.left; 695 696 // Size status bar and get height 697 SendMessage(fHWndStatus, WM_SIZE, 0, 0); 698 699 GetWindowRect(fHWndStatus, &rcStatus); 700 iStatusHeight = rcStatus.bottom - rcStatus.top; 701 702 // Size status the Combo Box and get height 703 SendMessage(fHWndComboBox, WM_SIZE, 0, 0); 704 705 GetWindowRect(fHWndComboBox, &rcComboBox); 706 iComboBoxHeight = rcComboBox.bottom - rcComboBox.top; 707 708 // Calculate remaining height and size edit 709 GetClientRect(aWindow, &rcClient); 710 711 iTreeViewHeight = rcClient.bottom - iToolHeight - iStatusHeight; 712 iTreeViewWidth = iToolWidth / 4; 713 714 iEditHeight = rcClient.bottom - iToolHeight - iComboBoxHeight - iStatusHeight; 715 iEditWidth = iToolWidth - iTreeViewWidth; 716 717 // TreeView location and size 718 SetWindowPos( 719 fHWndHelpTree, nullptr, 0, iToolHeight, iTreeViewWidth, iTreeViewHeight, SWP_NOZORDER); 720 721 // Editor location and size 722 SetWindowPos( 723 fHWndEditor, nullptr, iTreeViewWidth, iToolHeight, iEditWidth, iEditHeight, SWP_NOZORDER); 724 725 // ComboBox location and size 726 SetWindowPos( 727 fHWndComboBox, nullptr, iTreeViewWidth, iToolHeight + iEditHeight, iEditWidth, 200, 0); 728 729 return true; 730 } 731 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 732 /****************************************************************************************************/ 733 734 /****************************************************************************************************/ 735 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 736 void G4UIWin32::ProcessTabKey() 737 { 738 char buffer[256]; 739 740 // Only process the command it the user has written something 741 if (SendMessage(fHWndComboBox, WM_GETTEXT, (WPARAM)sizeof(buffer), (LPARAM)buffer) != 0) { 742 G4String command(buffer); 743 744 SetFocus(fHWndComboBox); 745 746 G4String cmd = Complete(command); 747 const char* d = cmd.data(); 748 G4int l = strlen(d); 749 Edit_SetText(fHWndComboEditor, (PTSTR)d); 750 Edit_SetSel(fHWndComboEditor, l, l); 751 } 752 else { 753 if (GetFocus() == fHWndComboEditor) 754 SetFocus(fHWndHelpTree); 755 else 756 SetFocus(fHWndComboBox); 757 } 758 } 759 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 760 /****************************************************************************************************/ 761 762 /****************************************************************************************************/ 763 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 764 void G4UIWin32::ProcessEscKey() 765 { 766 // Clear the current selection. 767 SendMessage(fHWndComboBox, CB_SETCURSEL, (WPARAM)(-1), (LPARAM)0); 768 // Set the focus to the Combo Box. 769 SetFocus(fHWndComboBox); 770 } 771 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 772 /****************************************************************************************************/ 773 774 /****************************************************************************************************/ 775 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 776 void G4UIWin32::ProcessEnterKey() 777 { 778 char buffer[256]; 779 DWORD dwIndex, numItems; 780 781 // Only process the command it the user has written something 782 if (SendMessage(fHWndComboBox, WM_GETTEXT, (WPARAM)sizeof(buffer), (LPARAM)buffer) != 0) { 783 SetFocus(fHWndComboBox); 784 785 // Read command 786 G4String command(buffer); 787 788 // Now clear the current selection. 789 SendMessage(fHWndComboBox, CB_SETCURSEL, (WPARAM)-1, (LPARAM)0); 790 791 if (fHelp) { 792 exitHelp = true; 793 fHelp = ConvertStringToInt(command.data(), fHelpChoice); 794 } 795 else { 796 fHistory.push_back(command); 797 fHistoryPos = -1; 798 ApplyShellCommand(command, exitSession, exitPause); 799 800 // Now update the history in the ComboBox 801 802 // Check if this command exists in the ComboBox 803 dwIndex = SendMessage(fHWndComboBox, CB_FINDSTRINGEXACT, (WPARAM)(-1), (LPARAM)buffer); 804 805 // Add the string, if necessary 806 if (dwIndex == CB_ERR) 807 dwIndex = SendMessage(fHWndComboBox, CB_INSERTSTRING, (WPARAM)0, (LPARAM)buffer); 808 // If the string exists, move it to the first position 809 if (dwIndex != CB_ERR) { 810 SendMessage(fHWndComboBox, CB_DELETESTRING, (WPARAM)dwIndex, (LPARAM)0); 811 dwIndex = SendMessage(fHWndComboBox, CB_INSERTSTRING, (WPARAM)0, (LPARAM)buffer); 812 } 813 814 numItems = SendMessage(fHWndComboBox, CB_GETCOUNT, (WPARAM)0, (LPARAM)0); 815 while (numItems > MAX_HISTORY_ITEMS) { 816 SendMessage(fHWndComboBox, CB_DELETESTRING, (WPARAM)(numItems - 1), (LPARAM)0); 817 numItems = SendMessage(fHWndComboBox, CB_GETCOUNT, (WPARAM)0, (LPARAM)0); 818 } 819 } 820 } 821 } 822 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 823 /****************************************************************************************************/ 824 825 /****************************************************************************************************/ 826 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 827 void G4UIWin32::ProcessUpKey() 828 { 829 G4int pos = fHistoryPos == -1 ? fHistory.size() - 1 : fHistoryPos - 1; 830 if ((pos >= 0) && (pos < (G4int)fHistory.size())) { 831 G4String command = fHistory[pos]; 832 const char* d = command.data(); 833 G4int l = strlen(d); 834 Edit_SetText(fHWndComboEditor, (PTSTR)d); 835 Edit_SetSel(fHWndComboEditor, l, l); 836 837 fHistoryPos = pos; 838 } 839 } 840 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 841 /****************************************************************************************************/ 842 843 /****************************************************************************************************/ 844 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 845 void G4UIWin32::ProcessDownKey() 846 { 847 G4int pos = fHistoryPos + 1; 848 if ((pos >= 0) && (pos < (G4int)fHistory.size())) { 849 G4String command = fHistory[pos]; 850 const char* d = command.data(); 851 G4int l = strlen(d); 852 Edit_SetText(fHWndComboEditor, (PTSTR)d); 853 Edit_SetSel(fHWndComboEditor, l, l); 854 855 fHistoryPos = pos; 856 } 857 else if (pos >= (G4int)fHistory.size()) { 858 char eName[] = ""; 859 Edit_SetText(fHWndComboEditor, (PTSTR)eName); 860 Edit_SetSel(fHWndComboEditor, 0, 0); 861 862 fHistoryPos = -1; 863 } 864 } 865 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 866 /****************************************************************************************************/ 867 868 /****************************************************************************************************/ 869 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 870 G4bool G4UIWin32::ProcessDefaultCommands(G4int idCommand) 871 { 872 switch (idCommand) { 873 case ID_EXIT_APP: 874 PostMessage(fHWndMainWindow, WM_CLOSE, 0, 0); 875 return true; 876 case ID_OPEN_MACRO: 877 DoOpenMacro(fHWndMainWindow); 878 return true; 879 case ID_SAVE_VIEWER_STATE: 880 DoSaveViewer(fHWndMainWindow); 881 return true; 882 case ID_RUN_BEAMON: 883 if (! fHelp) { 884 G4String command = "/run/beamOn 1"; 885 ApplyShellCommand(command, exitSession, exitPause); 886 } 887 return true; 888 case ID_RUN_CMD: 889 return true; 890 case ID_VIEW_SOLID: 891 if (! fHelp) { 892 G4String command = "/vis/viewer/set/style s"; 893 ApplyShellCommand(command, exitSession, exitPause); 894 } 895 return true; 896 case ID_VIEW_WIREFRAME: 897 if (! fHelp) { 898 G4String command = "/vis/viewer/set/style w"; 899 ApplyShellCommand(command, exitSession, exitPause); 900 } 901 return true; 902 case ID_PROJ_ORTHOGRAPHIC: 903 if (! fHelp) { 904 G4String command = "/vis/viewer/set/projection o"; 905 ApplyShellCommand(command, exitSession, exitPause); 906 } 907 return true; 908 case ID_PROJ_PERSPECTIVE: 909 if (! fHelp) { 910 G4String command = "/vis/viewer/set/projection p"; 911 ApplyShellCommand(command, exitSession, exitPause); 912 } 913 return true; 914 case ID_ZOOM_IN: 915 if (! fHelp) { 916 G4String command = "/vis/viewer/zoom 1.2"; 917 ApplyShellCommand(command, exitSession, exitPause); 918 } 919 return true; 920 case ID_ZOOM_OUT: 921 if (! fHelp) { 922 G4String command = "/vis/viewer/zoom 0.8"; 923 ApplyShellCommand(command, exitSession, exitPause); 924 } 925 return true; 926 case ID_ORIENTATION_XY: 927 if (! fHelp) { 928 G4String command = "/vis/viewer/set/viewpointThetaPhi 0. 0."; 929 ApplyShellCommand(command, exitSession, exitPause); 930 } 931 return true; 932 case ID_ORIENTATION_XZ: 933 if (! fHelp) { 934 G4String command = "/vis/viewer/set/viewpointThetaPhi 90. 0."; 935 ApplyShellCommand(command, exitSession, exitPause); 936 } 937 return true; 938 case ID_ORIENTATION_YZ: 939 if (! fHelp) { 940 G4String command = "/vis/viewer/set/viewpointThetaPhi 0. 90."; 941 ApplyShellCommand(command, exitSession, exitPause); 942 } 943 return true; 944 case ID_ORIENTATION_OBLIQUE: 945 if (! fHelp) { 946 G4String command = "/vis/viewer/set/viewpointThetaPhi 45. -45."; 947 ApplyShellCommand(command, exitSession, exitPause); 948 } 949 return true; 950 case ID_HELP_ABOUT: 951 return true; 952 case ID_LOG_CLEAN: 953 { 954 char eName[] = ""; 955 SetDlgItemText(fHWndMainWindow, IDC_MAIN_EDIT, (PTSTR)eName); 956 } 957 return true; 958 case ID_LOG_SAVE: 959 DoSaveLog(fHWndMainWindow); 960 return true; 961 default: 962 return false; 963 } 964 } 965 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 966 /****************************************************************************************************/ 967 968 /****************************************************************************************************/ 969 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 970 G4String G4UIWin32::GetToolTips(G4int idButton) 971 { 972 switch (idButton) { 973 case ID_OPEN_MACRO: 974 return "Open and execute macro file"; 975 976 case ID_SAVE_VIEWER_STATE: 977 return "Save viewer state"; 978 979 case ID_ZOOM_IN: 980 return "Zoom in"; 981 982 case ID_ZOOM_OUT: 983 return "Zoom out"; 984 985 case ID_RUN_BEAMON: 986 return "Beam on (one particle)"; 987 988 case ID_HELP_ABOUT: 989 return "About G4UIWin32"; 990 991 case ID_LOG_CLEAN: 992 return "Clean log"; 993 994 case ID_LOG_SAVE: 995 return "Save log"; 996 997 default: 998 return ""; 999 } 1000 } 1001 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 1002 /****************************************************************************************************/ 1003 1004 /****************************************************************************************************/ 1005 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 1006 G4String G4UIWin32::GetHelpTreeToolTips(HTREEITEM item) 1007 { 1008 // Tooltips for the help tree 1009 G4UImanager* UI = G4UImanager::GetUIpointer(); 1010 if (UI == nullptr) return ""; 1011 G4UIcommandTree* treeTop = UI->GetTree(); 1012 1013 G4String itemText = GetItemPath(item); 1014 1015 // Check if it is a command path 1016 if (TreeView_GetChild(fHWndHelpTree, item) != nullptr) itemText += "/"; 1017 1018 G4UIcommand* command = treeTop->FindPath(itemText.c_str()); 1019 1020 if (command) { 1021 // This is a command, return the first line of help 1022 return command->GetGuidanceLine(0).data(); 1023 } 1024 else { 1025 // This is not a command, but a sub directory, return the title 1026 G4UIcommandTree* path = treeTop->FindCommandTree(itemText.c_str()); 1027 if (path) return path->GetTitle().data(); 1028 } 1029 1030 return ""; 1031 } 1032 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 1033 /****************************************************************************************************/ 1034 1035 /****************************************************************************************************/ 1036 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 1037 G4String G4UIWin32::ConvertNewLines(const G4String& a_string) 1038 { 1039 // Geant4 uses UNIX's style for new lines (\n) 1040 // we must convert them to Windows' style (\r\n) 1041 G4String str = a_string; 1042 std::size_t index = str.find("\n", 0); 1043 while (index < str.length()) { 1044 str.replace(index, 1, "\r\n"); 1045 // Advance index forward so the next iteration doesn't pick it up as well. 1046 index = str.find("\n", index + 2); 1047 } 1048 return str; 1049 } 1050 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 1051 /****************************************************************************************************/ 1052 1053 /****************************************************************************************************/ 1054 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 1055 void G4UIWin32::HelpTreeDoubleClick(HTREEITEM item) 1056 { 1057 const char* item_path = GetItemPath(item); 1058 G4int l = strlen(item_path); 1059 Edit_SetText(fHWndComboEditor, (PTSTR)item_path); 1060 Edit_SetSel(fHWndComboEditor, l, l); 1061 1062 SetFocus(fHWndComboEditor); 1063 } 1064 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 1065 /****************************************************************************************************/ 1066 1067 /****************************************************************************************************/ 1068 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 1069 G4bool G4UIWin32::SaveLogFile(LPCTSTR fileName) 1070 { 1071 HANDLE hFile; 1072 G4bool bSuccess = false; 1073 1074 hFile = 1075 CreateFile(fileName, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); 1076 if (hFile != INVALID_HANDLE_VALUE) { 1077 DWORD dwTextLength; 1078 1079 dwTextLength = GetWindowTextLength(fHWndEditor); 1080 // No need to bother if there's no text. 1081 if (dwTextLength > 0) { 1082 LPSTR text; 1083 DWORD dwBufferSize = dwTextLength + 1; 1084 1085 text = (LPSTR)GlobalAlloc(GPTR, dwBufferSize); 1086 if (text != nullptr) { 1087 if (GetWindowTextA(fHWndEditor, text, dwBufferSize)) { 1088 DWORD dwWritten; 1089 1090 if (WriteFile(hFile, text, dwTextLength, &dwWritten, nullptr)) bSuccess = true; 1091 } 1092 GlobalFree(text); 1093 } 1094 } 1095 CloseHandle(hFile); 1096 } 1097 return bSuccess; 1098 } 1099 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 1100 /****************************************************************************************************/ 1101 1102 /****************************************************************************************************/ 1103 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 1104 void G4UIWin32::AddText(LPSTR text) 1105 { 1106 if ((fHWndEditor != nullptr) && (text != nullptr) && (text[0] != '\0')) { 1107 // Get current text length 1108 G4int ndx = GetWindowTextLength(fHWndEditor); 1109 1110 // Select the end of the text 1111 SendMessage(fHWndEditor, EM_SETSEL, (WPARAM)ndx, (LPARAM)ndx); 1112 // Add the new text 1113 SendMessage(fHWndEditor, EM_REPLACESEL, (WPARAM)0, (LPARAM)text); 1114 // Scroll to the bottom 1115 SendMessage(fHWndEditor, WM_VSCROLL, SB_BOTTOM, NULL); 1116 } 1117 } 1118 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 1119 /****************************************************************************************************/ 1120 1121 /****************************************************************************************************/ 1122 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 1123 void G4UIWin32::DoOpenMacro(HWND aWindow) 1124 { 1125 OPENFILENAME ofn; 1126 char szFileName[MAX_PATH] = ""; 1127 1128 ZeroMemory(&ofn, sizeof(ofn)); 1129 1130 ofn.lStructSize = sizeof(ofn); 1131 ofn.hwndOwner = aWindow; 1132 char fName[] = "Macro Files (*.mac)\0*.mac\0All Files (*.*)\0*.*\0"; 1133 ofn.lpstrFilter = (PTSTR)fName; 1134 ofn.lpstrFile = (PTSTR)szFileName; 1135 ofn.nMaxFile = MAX_PATH; 1136 ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; 1137 char dName[] = "mac"; 1138 ofn.lpstrDefExt = (PTSTR)dName; 1139 1140 if (GetOpenFileName(&ofn)) { 1141 G4String command = "/control/execute " + G4String(szFileName); 1142 ApplyShellCommand(command, exitSession, exitPause); 1143 1144 SendDlgItemMessage(aWindow, IDC_MAIN_STATUS, SB_SETTEXT, 0, (LPARAM) "Opened macro..."); 1145 SendDlgItemMessage(aWindow, IDC_MAIN_STATUS, SB_SETTEXT, 1, (LPARAM)szFileName); 1146 } 1147 } 1148 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 1149 /****************************************************************************************************/ 1150 1151 /****************************************************************************************************/ 1152 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 1153 void G4UIWin32::DoSaveViewer(HWND aWindow) 1154 { 1155 OPENFILENAME ofn; 1156 char szFileName[MAX_PATH] = ""; 1157 1158 ZeroMemory(&ofn, sizeof(ofn)); 1159 1160 ofn.lStructSize = sizeof(ofn); 1161 ofn.hwndOwner = aWindow; 1162 char fName[] = "Macro Files (*.mac)\0*.mac\0All Files (*.*)\0*.*\0"; 1163 ofn.lpstrFilter = (PTSTR)fName; 1164 ofn.lpstrFile = (PTSTR)szFileName; 1165 ofn.nMaxFile = MAX_PATH; 1166 char dName[] = "mac"; 1167 ofn.lpstrDefExt = (PTSTR)dName; 1168 ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT; 1169 1170 if (GetSaveFileName(&ofn)) { 1171 G4String command = "/vis/viewer/save " + G4String(szFileName); 1172 ApplyShellCommand(command, exitSession, exitPause); 1173 1174 SendDlgItemMessage(aWindow, IDC_MAIN_STATUS, SB_SETTEXT, 0, (LPARAM) "State saved..."); 1175 SendDlgItemMessage(aWindow, IDC_MAIN_STATUS, SB_SETTEXT, 1, (LPARAM)szFileName); 1176 } 1177 } 1178 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 1179 /****************************************************************************************************/ 1180 1181 /****************************************************************************************************/ 1182 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 1183 void G4UIWin32::DoSaveLog(HWND aWindow) 1184 { 1185 OPENFILENAME ofn; 1186 char szFileName[MAX_PATH] = ""; 1187 1188 ZeroMemory(&ofn, sizeof(ofn)); 1189 1190 ofn.lStructSize = sizeof(ofn); 1191 ofn.hwndOwner = aWindow; 1192 char fName[] = "Log Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0"; 1193 ofn.lpstrFilter = (PTSTR)fName; 1194 ofn.lpstrFile = (PTSTR)szFileName; 1195 ofn.nMaxFile = MAX_PATH; 1196 char dName[] = "txt"; 1197 ofn.lpstrDefExt = (PTSTR)dName; 1198 ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT; 1199 1200 if (GetSaveFileName(&ofn)) { 1201 if (SaveLogFile((PTSTR)szFileName)) { 1202 SendDlgItemMessage(aWindow, IDC_MAIN_STATUS, SB_SETTEXT, 0, (LPARAM) "Saved log file..."); 1203 SendDlgItemMessage(aWindow, IDC_MAIN_STATUS, SB_SETTEXT, 1, (LPARAM)szFileName); 1204 } 1205 } 1206 } 1207 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 1208 /****************************************************************************************************/ 1209 1210 /****************************************************************************************************/ 1211 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 1212 G4bool G4UIWin32::InitHelpTreeItems() 1213 { 1214 HTREEITEM newItem; 1215 1216 G4UImanager* UI = G4UImanager::GetUIpointer(); 1217 if (UI == nullptr) return false; 1218 G4UIcommandTree* treeTop = UI->GetTree(); 1219 1220 G4int treeSize = treeTop->GetTreeEntry(); 1221 G4String commandText; 1222 for (G4int a = 0; a < treeSize; a++) { 1223 // Creating new item 1224 commandText = treeTop->GetTree(a + 1)->GetPathName().data(); 1225 1226 // Add the item to the tree-view control. 1227 newItem = AddItemToHelpTree((PTSTR)GetShortCommandPath(commandText).c_str()); 1228 1229 if (newItem == nullptr) return false; 1230 1231 // Look for children 1232 CreateHelpTree(newItem, treeTop->GetTree(a + 1)); 1233 } 1234 1235 return true; 1236 } 1237 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 1238 /****************************************************************************************************/ 1239 1240 /****************************************************************************************************/ 1241 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 1242 void G4UIWin32::CreateHelpTree(HTREEITEM aParent, G4UIcommandTree* aCommandTree) 1243 { 1244 if ((aParent != nullptr) && (aCommandTree != nullptr)) { 1245 // Creating new item 1246 HTREEITEM newItem; 1247 1248 G4String commandText; 1249 // Get the Sub directories 1250 for (G4int a = 0; a < aCommandTree->GetTreeEntry(); a++) { 1251 commandText = aCommandTree->GetTree(a + 1)->GetPathName().data(); 1252 1253 // Add the item to the tree-view control. 1254 newItem = 1255 AddItemToHelpTree((PTSTR)GetShortCommandPath(commandText).c_str(), aParent); 1256 1257 // Look for children 1258 CreateHelpTree(newItem, aCommandTree->GetTree(a + 1)); 1259 } 1260 1261 // Get the Commands 1262 for (G4int a = 0; a < aCommandTree->GetCommandEntry(); a++) { 1263 commandText = aCommandTree->GetCommand(a + 1)->GetCommandPath().data(); 1264 1265 // Add the item to the tree-view control. 1266 AddItemToHelpTree((PTSTR)GetShortCommandPath(commandText).c_str(), aParent); 1267 } 1268 } 1269 } 1270 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 1271 /****************************************************************************************************/ 1272 1273 /****************************************************************************************************/ 1274 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 1275 HTREEITEM G4UIWin32::AddItemToHelpTree(LPTSTR lpszItem, HTREEITEM aParent) 1276 { 1277 TVITEM tvi; 1278 TVINSERTSTRUCT tvins; 1279 static auto hPrev = (HTREEITEM)TVI_FIRST; 1280 1281 tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM; 1282 1283 // Set the text of the item. 1284 tvi.pszText = lpszItem; 1285 tvi.cchTextMax = sizeof(tvi.pszText) / sizeof(tvi.pszText[0]); 1286 1287 // Save the heading level in the item's application-defined 1288 // data area. 1289 tvi.lParam = (LPARAM)aParent; 1290 tvins.item = tvi; 1291 tvins.hInsertAfter = hPrev; 1292 // Set the parent item. 1293 tvins.hParent = aParent; 1294 1295 // Add the item to the tree-view control. 1296 hPrev = (HTREEITEM)SendMessage( 1297 fHWndHelpTree, TVM_INSERTITEM, (WPARAM)0, (LPARAM)(LPTVINSERTSTRUCT)&tvins); 1298 1299 if (hPrev == nullptr) 1300 return nullptr; 1301 else 1302 return hPrev; 1303 } 1304 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 1305 /****************************************************************************************************/ 1306 1307 /****************************************************************************************************/ 1308 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 1309 G4String G4UIWin32::GetShortCommandPath(const G4String& commandPath) 1310 { 1311 G4String str = commandPath; 1312 1313 if (str.find_last_of("/") == (str.size() - 1)) str = str.erase(str.size() - 1, 1); 1314 1315 str = str.erase(0, str.find_last_of("/") + 1); 1316 1317 return str; 1318 } 1319 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 1320 /****************************************************************************************************/ 1321 1322 /****************************************************************************************************/ 1323 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 1324 LPSTR G4UIWin32::GetItemPath(HTREEITEM item) 1325 { 1326 // Get the text for the item. 1327 TVITEM tvitem; 1328 tvitem.mask = TVIF_TEXT; 1329 tvitem.hItem = item; 1330 TCHAR infoTipBuf[1024]; 1331 tvitem.pszText = infoTipBuf; 1332 tvitem.cchTextMax = sizeof(infoTipBuf) / sizeof(TCHAR); 1333 1334 std::string str = ""; 1335 while (item != nullptr) { 1336 TreeView_GetItem(fHWndHelpTree, &tvitem); 1337 str = "/" + std::string((PSTR)tvitem.pszText) + str; 1338 1339 item = TreeView_GetParent(fHWndHelpTree, item); 1340 tvitem.hItem = item; 1341 } 1342 1343 auto* result = new TCHAR[str.size() + 1]; 1344 result[str.size()] = 0; 1345 std::copy(str.begin(), str.end(), result); 1346 1347 return (LPSTR)result; 1348 } 1349 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 1350 /****************************************************************************************************/ 1351 1352 /****************************************************************************************************/ 1353 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 1354 G4bool ConvertStringToInt(const char* aString, G4int& aInt) 1355 { 1356 aInt = 0; 1357 if (aString == nullptr) return false; 1358 char* s; 1359 G4long value = strtol(aString, &s, 10); 1360 if (s == aString) return false; 1361 aInt = value; 1362 return true; 1363 } 1364 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 1365 /****************************************************************************************************/ 1366