CTS성경타자통독
URL : https://bible.ctm.kr/
10년전 즈음 병원에 입원한적이 있었다.
멋있는 친구를 잃고 정말 말 그대로 몸도 마음도 아팠다. 병원에 입원해서 하루 하루 성경을 읽다가 타이핑 속도도 높혀볼 생각으로 CTM성경타자통독 사이트에 가입해서 열심히 타이핑을 쳤다.
정말 열심히 했다. 세벽같이 일어나서 저녁 12시까지 몸이 허락하는시간에 쉬지않고 타이핑을 쳤다.
그리고 ... 뿌듯한 마음음으로 기대하는 마음으로 당연하리란 생각으로 순위를 확인해 보았다.
켑쳐는 생략하겠다 ... 당시 켑쳐가 있을리도 없고 ... 지금 순위는 무의미하고 ...
일일 순위도 1등에 미치지 못했다. 주간 순위도 1등에 미치지 못했다. 납득할 수가 없었다.
이제 어느정도 회복이 되어간다. 신체는 놀랍다 삶에 목표가 생기자 정말 다 낳았다. 이제 마음도 몸도 아프지 않았다. 정말 열심히 쳤다.
이것이 신앙의 힘인가 ? 다음날은 정말 열심히 정말 미친듯이 죈종일 쳤다. 병원에 입원해서 병원 침대위에서 식판놓으라고 만들어놓은 식탁에 노트북을 올려놓고
정말 기도하며 쳤다.
...
그렇지만 결과는 역시나 1등이 아니였다.
천국과 지옥은 정말 종이한장 차이다.
선과악을 오가는 것은 정말 손바닥 뒤집기처럼 간단하다.
정말 선한 마음으로 시작했는데
10등 안에만 들었어도 오토프로그렘 만들리라 생각지 않았으리라
퇴원해서 나는 MFC 프로그렘 으로 단 2주만에 오토프로그렘을 만들었다.
그리고 그 후 쭈욱 1등 ...
당시엔 몇달돌안 일등했었는데 이번처럼 전화오는일은 없었다.
내가 타락한건지 사이트가 타락한건지 ...
그렇지만 1등 하면 무엇하리 ? 아무두 ... 알아주지 않는것을 ㅎㅎㅎ
처음부터 누구와 함께 한것도 교회에서 시킨것도 아닌 그냥 나혼자 사이트를 찾아서 가입하고 타이핑을 쳤던것이다.
ㅎㅎㅎ
그렇게 시간이 지나서 나는 당시기억을 나 자신만의 추억으로 간직하고 있었다.
당시 만들었던 MFC 프로그렘은 소스가 유실되어 이제 찾아볼 수가 없다. (언젠가 다시 찾게 되면 올리리라) 해서 다시 만들었다.
추억의 오토를 이번엔 JAVA로 다시 만들어 보리라 ㅎㅎ
서론이 길었다. 시작하자.
목표 : CTS성경타자통독 사이트 오토프로그렘 만들기
1. 브라우져는 어떠한 것을 사용할 것인가?
익스프로러나 크롬, 파이어폭스 등에서 사이트에 접속 한 후에 오토타이핑 하게 하는것은 브라우저 환경을 고려해야하기 때문에 곤란하다.
그래서 ... 내가 찾은 방법은 브라우져를 직접 만드는것이다. 헐! 브라우져라니 하고 놀랄 수도 있지만 정말 별거 아니다.
그리고 직접 한땀 한땀 만들 것이 아니라 최대한 인터넷 검색으로 내가 원하는 기능을 재공하는 소스를 찾아 작업할 것이다.
웹 브라우져 구동 소스 출처 : http://www.programkr.com/blog/MkTN3ADMwYTy.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 | package com.zuidaima; import org.eclipse.swt.SWT; import org.eclipse.swt.browser.Browser; import org.eclipse.swt.browser.CloseWindowListener; import org.eclipse.swt.browser.LocationAdapter; import org.eclipse.swt.browser.LocationEvent; import org.eclipse.swt.browser.OpenWindowListener; import org.eclipse.swt.browser.ProgressAdapter; import org.eclipse.swt.browser.ProgressEvent; import org.eclipse.swt.browser.StatusTextEvent; import org.eclipse.swt.browser.StatusTextListener; import org.eclipse.swt.browser.TitleEvent; import org.eclipse.swt.browser.TitleListener; import org.eclipse.swt.browser.WindowEvent; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; import org.eclipse.swt.widgets.ProgressBar; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.TabFolder; import org.eclipse.swt.widgets.TabItem; /** * 뭐 때문에..... * * @author www.zuidaima.com * */ public class Liulanqi {// 탭 브라우저 기반 식 private volatile String newUrl = null;// 최신 입력 링크 private volatile boolean loadCompleted = false;// 현재 페이지 표시 완전히 가져오기 private volatile boolean openNewItem = false;// 새 페이지 표시 새 창으로 열기 /* * 현재 탭 브라우저 사용하기 */ private TabItem tabItem_now;// 현재 탭 항목 private Browser browser_now;// 현재 기능 탐색기 /* * 브라우저 설정 매개 변수 */ private String homePage = "www.baidu.com";// 브라우저를 홈페이지 /* * 브라우저 외형의 배치 */ private Button button_back;// 뒤로 단추를 누르십시오 private Button button_forward;// 앞으로 단추 private Button button_go;// 앞으로 단추 private Button button_stop;// 정지 버튼을 private Combo combo_address;// 주소 표시줄 private Browser browser_default = null;// 탐색 창 private ProgressBar progressBar_status;// 페이지 열기 진행표 즉 페이지 가져오기 상황이 표시줄 private Label label_status;// 마지막 페이지 열기 과정 보이기 private TabFolder tabFolder;// Browser 용기 private Composite composite_tool;// 도구 모음 구역 private Composite composite_browser;// 탐색 창 구역 private Composite composite_status;// 상태 표시줄 구역 protected Display display; protected Shell shell_default; /** * Launch the application * * @param args */ public static void main(String[] args) { try { Liulanqi window = new Liulanqi(); window.open(); } catch (Exception e) { e.printStackTrace(); } } /** * Open the window */ public void open() { display = Display.getDefault(); shell_default = new Shell(display); createContents(); shell_default.open(); shell_default.layout(); while (!shell_default.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } } /** * Create contents of the window */ protected void createContents() { shell_default.setSize(649, 448); shell_default.setText("브라우저"); GridLayout gl_shell = new GridLayout(); gl_shell.marginWidth = 0;// 구성 요소 및 용기 가 수평 거리 gl_shell.marginHeight = 0;// 구성 요소 및 용기 가장자리 수직 거리 gl_shell.horizontalSpacing = 0;// 구성 요소 사이 수평 거리 gl_shell.verticalSpacing = 0;// 구성 요소 사이의 수직 거리 shell_default.setLayout(gl_shell); /* * 웹 인터페이스 생성 */ // createMenu();//실현되지 않았다 createTool(); createBrowser(); createStatus(); /* * 브라우저 관련 사건 들을 수 없습니다. */ runThread(); } /* * 기본 만들기 도구 모음 안 포함한 관련 사건 감청 */ private void createTool() { composite_tool = new Composite(shell_default, SWT.BORDER); // GridData()첫 번째 매개 변수, 수평 방식, 두 번째 매개 변수 는 수직 정렬 방식, 세 번째는 수준 선점 여부, // 네 번째 인자 수직이다 선점 여부 GridData gd_composite = new GridData(SWT.FILL, SWT.CENTER, true, false); gd_composite.heightHint = 30;// 고도, 폭 gd_composite.widthHint = 549; composite_tool.setLayoutData(gd_composite); GridLayout fl_composite = new GridLayout(); fl_composite.numColumns = 8; composite_tool.setLayout(fl_composite); button_back = new Button(composite_tool, SWT.NONE); button_back.setLayoutData(new GridData(27, SWT.DEFAULT));// 설정 크기 조정 및 형식 button_back.setText("<-"); button_forward = new Button(composite_tool, SWT.NONE); button_forward.setLayoutData(new GridData(24, SWT.DEFAULT)); button_forward.setText("->"); combo_address = new Combo(composite_tool, SWT.BORDER); final GridData gd_combo_3 = new GridData(SWT.FILL, SWT.LEFT, true, false); gd_combo_3.widthHint = 300;// 시작 너비 gd_combo_3.minimumWidth = 50;// 설정 최소 폭 combo_address.setLayoutData(gd_combo_3); button_go = new Button(composite_tool, SWT.NONE); button_go.setLayoutData(new GridData(25, SWT.DEFAULT)); button_go.setText("go"); button_stop = new Button(composite_tool, SWT.NONE); button_stop.setLayoutData(new GridData(24, SWT.DEFAULT)); button_stop.setText("stop"); final Label label = new Label(composite_tool, SWT.SEPARATOR | SWT.VERTICAL); label.setLayoutData(new GridData(2, 17)); } /* * 생성 브라우저 등 관련 사건 감청 않는다. */ private void createBrowser() { composite_browser = new Composite(shell_default, SWT.NONE); final GridData gd_composite = new GridData(SWT.FILL, SWT.FILL, true, true); gd_composite.heightHint = 273; composite_browser.setLayoutData(gd_composite); GridLayout gl_composite = new GridLayout(); gl_composite.marginHeight = 0;// 으로 구성 요소 상하 방향 용기 gl_composite.marginWidth = 0;// 으로 구성 요소 정도 방향 가득 용기 composite_browser.setLayout(gl_composite); tabFolder = new TabFolder(composite_browser, SWT.NONE); final GridData gd_tabFolder = new GridData(SWT.FILL, SWT.FILL, true, true); gd_tabFolder.heightHint = 312; gd_tabFolder.widthHint = 585; tabFolder.setLayoutData(gd_tabFolder); /* * 태그 추가하기 위해 오른쪽 버튼 기능 */ tabFolder.addMouseListener(new MouseAdapter() { @Override public void mouseUp(MouseEvent e) { if (e.button == 3) {// 오른쪽 단추 Menu menu_itemRightMouse = new Menu(shell_default, SWT.POP_UP); tabFolder.setMenu(menu_itemRightMouse); MenuItem menuItem_itemClose = new MenuItem(menu_itemRightMouse, SWT.NONE); menuItem_itemClose.setText("현재 탭 닫기"); menuItem_itemClose.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (tabFolder.getItemCount() != 1) {// 아니, 단지 한 탭 상황에서 browser_now.dispose(); tabItem_now.dispose(); tabFolder.redraw(); } else {// 오직 하나 탭 browser_now.setUrl(":blank"); browser_now.setText(""); } } }); MenuItem menuItem_itemCloseAll = new MenuItem(menu_itemRightMouse, SWT.NONE); menuItem_itemCloseAll.setText("모든 탭 닫기"); menuItem_itemCloseAll.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { shell_default.close(); } }); } } }); final TabItem tabItem_default = new TabItem(tabFolder, SWT.NONE); browser_default = new Browser(tabFolder, SWT.NONE); tabItem_default.setControl(browser_default); browser_default.setUrl(homePage);// 브라우저 메 인 화면 표시 /* * 그 초기화 탭 잡담 끝. 선택하십시오 */ tabFolder.setSelection(tabItem_default); } /* * 상태 표시줄 만들기 브라우저 하단에 안 포함한 관련 사건 감청 */ private void createStatus() { composite_status = new Composite(shell_default, SWT.NONE); final GridData gd_composite = new GridData(SWT.FILL, SWT.FILL, true, false); gd_composite.heightHint = 20; gd_composite.widthHint = 367; composite_status.setLayoutData(gd_composite); GridLayout gl_composite = new GridLayout(); gl_composite.numColumns = 2; gl_composite.marginBottom = 5; composite_status.setLayout(gl_composite); label_status = new Label(composite_status, SWT.NONE); GridData gd_status = new GridData(SWT.FILL, SWT.CENTER, true, false); gd_status.heightHint = 13; gd_status.widthHint = 525; label_status.setLayoutData(gd_status); progressBar_status = new ProgressBar(composite_status, SWT.BORDER | SWT.SMOOTH); progressBar_status.setLayoutData(new GridData(80, 12)); progressBar_status.setVisible(false);// 열 과정 시작 안 보인다 } private void runThread( ) { /* * 새 탭 브라우저 전진 · 뒤로 단추를 누르면 기본 접근성 위해 사용할 수 없습니다. */ button_back.setEnabled(false); button_forward.setEnabled(false); /* * 현재 탭 브라우저 가져오기 및 기능 Browser */ tabItem_now=tabFolder.getItem(tabFolder.getSelectionIndex()); browser_now=(Browser) tabItem_now.getControl(); /* * 선택한 사건 때 현재 탐색기 탭 수정 */ tabFolder.addSelectionListener(new SelectionAdapter(){ @Override public void widgetSelected(SelectionEvent e) { TabItem temp=(TabItem) e.item; if(temp!=tabItem_now){//재선거 한 탭 방지 예방 여러 차례 트리거 같은 사건 tabItem_now=temp; browser_now=(Browser)tabItem_now.getControl(); //System.out.println("현재 탭 변경된 '); // 디버그 문 /* * 지금 상응하는 탭으로, 전진하다, 뒤로 단추를 접근성 달라요. */ if(browser_now.isBackEnabled()){//뒤로 단추를 접근성 button_back.setEnabled(true); }else{ button_back.setEnabled(false); } if(browser_now.isForwardEnabled()){//앞으로 단추를 접근성 button_forward.setEnabled(true); }else{ button_forward.setEnabled(false); } } } }); /* * 추가 브라우저 뒤로, 앞으로, 전진하다, 정지 버튼을 사건 감청 */ button_back.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent arg0) { if (browser_now.isBackEnabled()){//이번 정말 뒤로 browser_now.back(); button_forward.setEnabled(true);//다음부터는 나아가다, 전진하다 단추를 사용할 수 없습니다. //System.out.println("근데 뒤로 '); // 디버그 문 } if(!browser_now.isBackEnabled()){//나중에 안 된다 뒤로, 뒤로 단추를 사용할 수 없습니다. button_back.setEnabled(false); } } }); button_forward.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent arg0) { if (browser_now.isForwardEnabled()){//이번 정말 전진하다 browser_now.forward(); button_back.setEnabled(true);//뒤로 단추를 사용할 수 없습니다. //System.out.println("근데 앞으로 '); // 디버그 문 } if(!browser_now.isForwardEnabled()){//나중에 안 된다. 앞으로 나아가다, 전진하다 단추를 사용할 수 없습니다. button_forward.setEnabled(false); } } }); button_stop.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent arg0) { browser_now.stop(); } }); combo_address.addKeyListener(new KeyAdapter() {// 수동 입력 주소 표시줄에 후 Enter 키를 누르면 상응하는 사이트 가기 @Override public void keyReleased(KeyEvent e) { if (e.keyCode == SWT.CR) {//리턴 키 트리거 이벤트 browser_now.setUrl(combo_address.getText()); } } }); /* * 1>지금 addOpenWindowListener () 아래 open () 쓰기 e.browser = browser_new 상황에서 책갈피를 새 하이퍼링크, * 오직 이 페이지에 링크를 누르면 또한 링크 안 새로운 페이지를 열 때 벌어진. * 2>지금 addOpenWindowListener () 아래 open () 쓰기 e.browser = browser_new 상황에서 책갈피를 새 하이퍼링크, * 오직 이 페이지에 링크를 누르면 또한 링크 새로운 페이지를 열 때 벌어진. * 이상 두 가지 말고 바깥 당연히 아직 browser.back (포함), browser.forward (), browser.go (), browser.setUrl () 발생 시 발동, * 하지만 changing () 는 쓰기 e.browser = browser_new 상황에서 지원되지 browser.setUrl () 트리거 */ browser_now.addLocationListener(new LocationAdapter() { @Override public void changing(LocationEvent e) {// 하이퍼링크 주소 바뀐 말했다 if(openNewItem==false){//새 페이지 같은 탭으로 열기 button_back.setEnabled(true);//뒤로 단추를 사용할 수 있습니다. 이 구절은 뒤로 단추를 사용할 수 있는 논리 시작 시 결정 } //System.out.println("location_changing");// 디버그 문 } @Override public void changed(LocationEvent e) {// 링크 주소 찾았다 페이지 combo_address.setText(e.location);// 링크 주소 변경 보이기 /* * 새 페이지 이미 열어서 browser 있는 LocationListener 이미 감청 완료, openNewItem 답장 기본값 */ if(openNewItem==true){ openNewItem=false; } //System.out.println("location_changed");// 디버그 문 } }); /* * 새로운 하이퍼링크 페이지 가져오기%, 책갈피를 새 페이지 발생, 이때 이미 링크 주소 */ browser_now.addProgressListener(new ProgressAdapter() { @Override public void changed(ProgressEvent e) {//이번 사건이 끊임없이 일어난 는 페이지 가져오기 과정에서 progressBar_status.setMaximum(e.total);// e.total 에서 가장 시작 페이지 끝까지 페이지 의 수치 progressBar_status.setSelection(e.current); if (e.current != e.total) {//페이지 아직 완전히 가져오기 loadCompleted = false; progressBar_status.setVisible(true);// 페이지 가져오기 상황이 표시줄을 보이는 } else { loadCompleted = true; progressBar_status.setVisible(false);// 페이지 가져오기 상황이 표시줄 안 보인다 } //System.out.println("progress_changed");//디버그 문 } @Override public void completed(ProgressEvent arg0) {//발생 한 번 가져오기 페이지 때 본 모니터 changed 사건 발생 전에 마지막으로 //System.out.println("progress_completed");//디버그 문 } }); /* * 페이지 내용 가져오는 addProgressListener 과정, 문자 보이기 () 과정 을 동시에 인지되었습니다 * 페이지 수 있는 슈퍼 링크 열기 이미 바로 간 기능 온 가져오기 * 새 링크 주소 */ browser_now.addStatusTextListener(new StatusTextListener() { public void changed(StatusTextEvent e) { if (loadCompleted == false) { label_status.setText(e.text); } else { newUrl = e.text;//페이지 가져오기 완료, 포착 페이지에 링크를 열 수 있다 } //System.out.println("statusText_changed");//디버그 문 } }); /* * 페이지 표시 문구 표시, 새로운 페이지 가져오기 발생 */ browser_now.addTitleListener(new TitleListener() { public void changed(TitleEvent e) { shell_default.setText(e.title); if (e.title.length() > 3) {//현재 페이지의 팁 표시 문자 탭에 tabItem_now.setText(e.title.substring(0, 3) + ".."); } else { tabItem_now.setText(e.title); } tabItem_now.setToolTipText(e.title);//탭 표시 프롬프트 } }); /* * 새 페이지 열기 현재 페이지 열기 새 링크 필요한 새 창 페이지 열기 발생.addOpenWindowListener 다음 open () 중 한 마디 * e.browser = browser_new;중요한 부분. 연락 addOpenWindowListener, addVisibilityWindowListener * 과 addDisposeListener 값 배달 중추. */ browser_now.addOpenWindowListener(new OpenWindowListener() {// 현재 페이지의 링크 페이지 열기 클릭 public void open(WindowEvent e) { Browser browser_new = new Browser(tabFolder, SWT.NONE); TabItem tabItem_new = new TabItem(tabFolder, SWT.NONE); tabItem_new.setControl(browser_new); tabFolder.setSelection(tabItem_new);//새 탭 열기 페이지 잡담 끝. tabFolder.redraw();//새로 고침 용기 browser_new.setUrl(newUrl);//새 탭으로 링크 설정 새로운 주소 openNewItem=true;//새 페이지 새 탭을 엽니다 /* * 관건이 되는 부분 알려 by browser_new 새로운 페이지 열기 하면 실현 이 말 안 팝업 운영 체제 기본 브라우저 되었다 */ e.browser = browser_new; //System.out.println("OpenWindowListener_open");//디버그 문 /* * 새 탭 브라우저 추가합니다 사건 감청 */ display.syncExec(new Runnable(){ public void run() { runThread(); } }); } }); /* * 브라우저 닫기 이벤트가 현재 기능 탐색기, 닫기, 아니면 브라우저 주 창 닫기, 실행, 그리고 프로세스 */ browser_now.addCloseWindowListener(new CloseWindowListener(){ public void close(WindowEvent e) { browser_now.dispose(); } }); } | cs |
주석이 좀 약간 이상하게 느껴지는 것이 외국 사이트에 있는 소스를 가져다 놓고 외국어로 되어있는 주석을 번역기 돌린 그런 느낌이다.
원본이 있다면 원본 URL 를 재공해 주셨으면 더 좋았을 것을 하는 아쉬움이 남는다.
SWT 프로젝트생성도 편하게 하는 방법이 있다.
요약해서 eclipse(에디터) 를 설치한다. java 를 설치한다. 위 링크를 따라 swt 용 프로젝트를 생성하기 위한 작업을 해준다.
2. 오토 타이핑은 어떻게 할것인가 ?
MFC로 만들때에는 키보드와 마우스이벤트를 이용해서 커서를 가져다 놓으면 해당 위치부터 시작해서 타이핑을 시작하도록 만들었었다.
당시 필자는 HTML 도 몰랐고 JavaScript 도 jQuery 의 존재도 몰랐다. 당연히 크롬도 몰랐고 익스플로러도 몰랐다.
익스플로러만 사용하는 것은 정말 마이크로소프트사가 원망스러울 정말 실망스러운 브라우져이다.
우리나라는 OS로 윈도우를 쓴다. 아 쉣! 좀더 다양한 OS를 쓰자 좀 ...
마이크로소프트사가 우리나라를 지원해 주었을거다 그래서 윈도우라는 OS를 쓰게 되었고 결과적으로 전국민이 윈도우에 얽매여있게 된 것이다.
정말 감사하지만 다른 한편으로 크롬에 대한 존재를 몰랐다는 이런 사실은 정말억울하기 까지 하다. 익스플로러가 브라우져의 전부인양 ... 아휴 ...
글이 또 딴길로 가고 있다. 그래! 브라우져를 만들었다. 위 사이트도 접속이 된다. 그렇다면 이제 어떻게 타이핑 하게 할 것인가 ?
당연해서 분석해서 html 을 읽도록 만들자
일전에 mfc 에서는 실제 키보드의 key event 를 발생시켜 입력했지만
이번에는 브라우져의 개발자 모드 consol 마냥 브라우져상에 명령어를 입력하여 이벤트발생시키도록 하자.
이것이 가능해지면 작성한 프로그렘을 띄우고도 다른 작업이 가능해 진다.
다음으로 넘어가기 위한 중간 정리
오토 타이핑 프로그렘을 만들것인데 나만의 브라우져를 만들고 그 안에서 스크립트를 이용해 오토를 돌릴 것이다.
스크립트 ?? 란 이런것이다.
설명을 위해 크롬브라우져를 이용 해 아래 사이트에 접속하자
CTS성경타자통독 URL : https://bible.ctm.kr/
접속 되었다면 F12를 눌러서 개발자 모드를 open 한다.
parent.ctmhome.document.getElementsByName('id')[0].parentNode.innerHTML = "<input type='TEXT' size='6' maxlength='15' name='id' value='USER_ID'>"
위의 스크립트를 그대로 복 붙 후 엔터
위 이미지와 같이 아이디 란에 USER_ID 가 박혔음을 확인할 수 있다.
위와 같은 방식으로 페스워드 또한 입력할 수 있으리라.
1 2 3 4 5 6 7 | executeScript("parent.ctmhome.document.getElementsByName('id')[0].parentNode.innerHTML = \"<input type='TEXT' size='6' maxlength='15' name='id' value='USER_ID'>\""); executeScript("parent.ctmhome.document.getElementsByName('pwd')[0].parentNode.innerHTML = \"<input value='USER_PASSWORD' type='password' size='7' maxlength='15' name='pwd'>\""); executeScript("window.top.ctmhome.document.getElementsByTagName('input')[5].click()"); | cs |
로그인은 위 소스로 가능하다.
노파심에 언급하지만 value='USER_ID' , value='USER_PASSWORD' 부분에는 본인 ID 와 PW 를 넣는부분인 것이다.
여기까지만 작성하고 바로 전체 소스를 공개 한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 | package com; import java.awt.Dimension; import java.awt.Toolkit; import java.util.ArrayList; import org.eclipse.swt.SWT; import org.eclipse.swt.browser.Browser; import org.eclipse.swt.browser.CloseWindowListener; import org.eclipse.swt.browser.LocationAdapter; import org.eclipse.swt.browser.LocationEvent; import org.eclipse.swt.browser.OpenWindowListener; import org.eclipse.swt.browser.ProgressAdapter; import org.eclipse.swt.browser.ProgressEvent; import org.eclipse.swt.browser.StatusTextEvent; import org.eclipse.swt.browser.StatusTextListener; import org.eclipse.swt.browser.TitleEvent; import org.eclipse.swt.browser.TitleListener; import org.eclipse.swt.browser.WindowEvent; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; import org.eclipse.swt.widgets.ProgressBar; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.TabFolder; import org.eclipse.swt.widgets.TabItem; public class Liulanqi {// 탭 브라우저 기반 식 private volatile String newUrl = null;// 최신 입력 링크 private volatile boolean loadCompleted = false;// 현재 페이지 표시 완전히 가져오기 private volatile boolean openNewItem = false;// 새 페이지 표시 새 창으로 열기 /* * 현재 탭 브라우저 사용하기 */ private TabItem tabItem_now;// 현재 탭 항목 private Browser browser_now;// 현재 기능 탐색기 /* * 브라우저 설정 매개 변수 */ private String homePage = "https://bible.ctm.kr";// 브라우저를 홈페이지 /* * 브라우저 외형의 배치 */ //--------------------------------------------------------------------- private Composite composite_tool;// 도구 모음 구역 private Button button_back;// 뒤로 단추를 누르십시오 private Combo combo_address;// 주소 표시줄 private Button button_forward;// 앞으로 단추 private Button button_go;// 앞으로 단추 private Button button_stop;// 정지 버튼을 //--------------------------------------------------------------------- private Composite composite_browser;// 탐색 창 구역 public Browser browser_default = null;// 탐색 창 private TabFolder tabFolder;// Browser 용기 //--------------------------------------------------------------------- private Composite composite_status;// 상태 표시줄 구역 private Label label_status;// 마지막 페이지 열기 과정 보이기 private ProgressBar progressBar_status;// 페이지 열기 진행표 즉 페이지 가져오기 상황이 표시줄 //--------------------------------------------------------------------- private Composite composite_auto; private Button button_login; private Button button_findWrite; private Button button_autoStart; private Button button_autoEnd; //--------------------------------------------------------------------- protected Display display; protected Shell shell_default; //loginCheck private int loginCheckCnt = 0; //loginCheck private int findCheck = 0; // 최대성경개수 private int maxBookCnt = 70; // 선택성경번호 private int curBookCnt = 0; private boolean typing = false; private boolean typingCompleted = false; // Thread 를 위한 변수 선언 ArrayList<Thread> threads = new ArrayList<Thread>(); int seq = 0; /** * Launch the application * * @param args */ public static void main(String[] args) { try { Liulanqi window = new Liulanqi(); window.open(); } catch (Exception e) { e.printStackTrace(); } } /** * Open the window */ public void open() { display = Display.getDefault(); shell_default = new Shell(display); createContents(); shell_default.open(); shell_default.layout(); while (!shell_default.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } } /** * Create contents of the window */ protected void createContents() { //전체 화면 사이즈 구하기 Dimension dimScreen = Toolkit.getDefaultToolkit().getScreenSize(); //shell_default.setSize(649, 448); shell_default.setSize(dimScreen.width - 100, dimScreen.height - 100); shell_default.setText("브라우저"); GridLayout gl_shell = new GridLayout(); gl_shell.marginWidth = 0;// 구성 요소 및 용기 가 수평 거리 gl_shell.marginHeight = 0;// 구성 요소 및 용기 가장자리 수직 거리 gl_shell.horizontalSpacing = 0;// 구성 요소 사이 수평 거리 gl_shell.verticalSpacing = 0;// 구성 요소 사이의 수직 거리 shell_default.setLayout(gl_shell); /* * 웹 인터페이스 생성 */ // createMenu();//실현되지 않았다 createTool(); createBrowser(); createStatus(); createAuto(); /* * 브라우저 관련 사건 들을 수 없습니다. */ runThread(); } /* * 기본 만들기 도구 모음 안 포함한 관련 사건 감청 */ private void createTool() { composite_tool = new Composite(shell_default, SWT.BORDER); // GridData()첫 번째 매개 변수, 수평 방식, 두 번째 매개 변수 는 수직 정렬 방식, 세 번째는 수준 선점 여부, 네 // 번째 인자 수직이다 선점 여부 GridData gd_composite = new GridData(SWT.FILL, SWT.CENTER, true, false); gd_composite.heightHint = 30;// 고도, 폭 gd_composite.widthHint = 549; composite_tool.setLayoutData(gd_composite); GridLayout fl_composite = new GridLayout(); fl_composite.numColumns = 8; composite_tool.setLayout(fl_composite); button_back = new Button(composite_tool, SWT.NONE); button_back.setLayoutData(new GridData(27, SWT.DEFAULT));// 설정 크기 조정 및 형식 button_back.setText("<-"); button_forward = new Button(composite_tool, SWT.NONE); button_forward.setLayoutData(new GridData(24, SWT.DEFAULT)); button_forward.setText("->"); combo_address = new Combo(composite_tool, SWT.BORDER); final GridData gd_combo_3 = new GridData(SWT.FILL, SWT.LEFT, true, false);// 창 변화가 있을 때 자동 확장 수평 방향의 크기 gd_combo_3.widthHint = 300;// 시작 너비 gd_combo_3.minimumWidth = 50;// 설정 최소 폭 combo_address.setLayoutData(gd_combo_3); button_go = new Button(composite_tool, SWT.NONE); button_go.setLayoutData(new GridData(25, SWT.DEFAULT)); button_go.setText("go"); button_stop = new Button(composite_tool, SWT.NONE); button_stop.setLayoutData(new GridData(24, SWT.DEFAULT)); button_stop.setText("stop"); final Label label = new Label(composite_tool, SWT.SEPARATOR | SWT.VERTICAL); label.setLayoutData(new GridData(2, 17)); } /* * 생성 브라우저 등 관련 사건 감청 않는다. */ private void createBrowser() { composite_browser = new Composite(shell_default, SWT.NONE); final GridData gd_composite = new GridData(SWT.FILL, SWT.FILL, true, true);// 가득 창 뿐만 아니라 수평과 수직으로 방향을 따라 창 때문에 변하다 gd_composite.heightHint = 273; composite_browser.setLayoutData(gd_composite); GridLayout gl_composite = new GridLayout(); gl_composite.marginHeight = 0;// 으로 구성 요소 상하 방향 용기 gl_composite.marginWidth = 0;// 으로 구성 요소 정도 방향 가득 용기 composite_browser.setLayout(gl_composite); tabFolder = new TabFolder(composite_browser, SWT.NONE); final GridData gd_tabFolder = new GridData(SWT.FILL, SWT.FILL, true, true); gd_tabFolder.heightHint = 312; gd_tabFolder.widthHint = 585; tabFolder.setLayoutData(gd_tabFolder); /* * 태그 추가하기 위해 오른쪽 버튼 기능 */ tabFolder.addMouseListener(new MouseAdapter() { @Override public void mouseUp(MouseEvent e) { if (e.button == 3) {// 오른쪽 단추 Menu menu_itemRightMouse = new Menu(shell_default, SWT.POP_UP); tabFolder.setMenu(menu_itemRightMouse); MenuItem menuItem_itemClose = new MenuItem(menu_itemRightMouse, SWT.NONE); menuItem_itemClose.setText("현재 탭 닫기"); menuItem_itemClose.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (tabFolder.getItemCount() != 1) {// 아니, // 단지 한 // 탭 // 상황에서 browser_now.dispose(); tabItem_now.dispose(); tabFolder.redraw(); } else {// 오직 하나 탭 browser_now.setUrl(":blank"); browser_now.setText(""); } } }); MenuItem menuItem_itemCloseAll = new MenuItem(menu_itemRightMouse, SWT.NONE); menuItem_itemCloseAll.setText("모든 탭 닫기"); menuItem_itemCloseAll.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { shell_default.close(); } }); } } }); final TabItem tabItem_default = new TabItem(tabFolder, SWT.NONE); browser_default = new Browser(tabFolder, SWT.NONE); tabItem_default.setControl(browser_default); browser_default.setUrl(homePage);// 브라우저 메 인 화면 표시 /* * 그 초기화 탭 잡담 끝. 선택하십시오 */ tabFolder.setSelection(tabItem_default); } /* * 상태 표시줄 만들기 브라우저 하단에 안 포함한 관련 사건 감청 */ private void createStatus() { composite_status = new Composite(shell_default, SWT.NONE); final GridData gd_composite = new GridData(SWT.FILL, SWT.FILL, true, false);// 매개 변수 true 때문에 상태 표시줄 자동으로 수준 신축 수 있다 gd_composite.heightHint = 20; gd_composite.widthHint = 367; composite_status.setLayoutData(gd_composite); GridLayout gl_composite = new GridLayout(); gl_composite.numColumns = 2; gl_composite.marginBottom = 5; composite_status.setLayout(gl_composite); label_status = new Label(composite_status, SWT.NONE); GridData gd_status = new GridData(SWT.FILL, SWT.CENTER, true, false); gd_status.heightHint = 13; gd_status.widthHint = 525; label_status.setLayoutData(gd_status); progressBar_status = new ProgressBar(composite_status, SWT.BORDER | SWT.SMOOTH); progressBar_status.setLayoutData(new GridData(80, 12)); progressBar_status.setVisible(false);// 열 과정 시작 안 보인다 } /* * AUTO */ private void createAuto() { composite_auto = new Composite(shell_default, SWT.NONE); final GridData gd_composite = new GridData(SWT.FILL, SWT.FILL, true, false);// 매개 변수 true 때문에 상태 표시줄 자동으로 수준 신축 수 있다 gd_composite.heightHint = 40; gd_composite.widthHint = 367; composite_auto.setLayoutData(gd_composite); GridLayout gl_composite = new GridLayout(); gl_composite.numColumns = 4; gl_composite.marginBottom = 5; composite_auto.setLayout(gl_composite); button_login = new Button(composite_auto, SWT.NONE); button_login.setLayoutData(new GridData(50, SWT.DEFAULT));// 설정 크기 조정 및 형식 button_login.setText("login"); button_findWrite = new Button(composite_auto, SWT.NONE); button_findWrite.setLayoutData(new GridData(50, SWT.DEFAULT));// 설정 크기 조정 및 형식 button_findWrite.setText("find"); button_autoStart = new Button(composite_auto, SWT.NONE); button_autoStart.setLayoutData(new GridData(50, SWT.DEFAULT));// 설정 크기 조정 및 형식 button_autoStart.setText("start"); button_autoEnd = new Button(composite_auto, SWT.NONE); button_autoEnd.setLayoutData(new GridData(50, SWT.DEFAULT));// 설정 크기 조정 및 형식 button_autoEnd.setText("end"); } private void runThread() { /* * 새 탭 브라우저 전진 · 뒤로 단추를 누르면 기본 접근성 위해 사용할 수 없습니다. */ button_back.setEnabled(false); button_forward.setEnabled(false); /* * 현재 탭 브라우저 가져오기 및 기능 Browser */ tabItem_now = tabFolder.getItem(tabFolder.getSelectionIndex()); browser_now = (Browser) tabItem_now.getControl(); /* * 선택한 사건 때 현재 탐색기 탭 수정 */ tabFolder.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { TabItem temp = (TabItem) e.item; if (temp != tabItem_now) {// 재선거 한 탭 방지 예방 여러 차례 트리거 같은 사건 tabItem_now = temp; browser_now = (Browser) tabItem_now.getControl(); // System.out.println("현재 탭 변경된 '); // 디버그 문 /* * 지금 상응하는 탭으로, 전진하다, 뒤로 단추를 접근성 달라요. */ if (browser_now.isBackEnabled()) {// 뒤로 단추를 접근성 button_back.setEnabled(true); } else { button_back.setEnabled(false); } if (browser_now.isForwardEnabled()) {// 앞으로 단추를 접근성 button_forward.setEnabled(true); } else { button_forward.setEnabled(false); } } } }); /* * 추가 브라우저 뒤로, 앞으로, 전진하다, 정지 버튼을 사건 감청 */ button_back.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent arg0) { if (browser_now.isBackEnabled()) {// 이번 정말 뒤로 browser_now.back(); button_forward.setEnabled(true);// 다음부터는 나아가다, 전진하다 단추를 사용할 수 없습니다. // System.out.println("근데 뒤로 '); // 디버그 문 } if (!browser_now.isBackEnabled()) {// 나중에 안 된다 뒤로, 뒤로 단추를 사용할 수 // 없습니다. button_back.setEnabled(false); } } }); button_forward.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent arg0) { if (browser_now.isForwardEnabled()) {// 이번 정말 전진하다 browser_now.forward(); button_back.setEnabled(true);// 뒤로 단추를 사용할 수 없습니다. // System.out.println("근데 앞으로 '); // 디버그 문 } if (!browser_now.isForwardEnabled()) {// 나중에 안 된다. 앞으로 나아가다, // 전진하다 단추를 사용할 수 없습니다. button_forward.setEnabled(false); } } }); button_stop.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent arg0) { browser_now.stop(); } }); combo_address.addKeyListener(new KeyAdapter() {// 수동 입력 주소 표시줄에 후 Enter // 키를 누르면 상응하는 사이트 가기 @Override public void keyReleased(KeyEvent e) { if (e.keyCode == SWT.CR) {// 리턴 키 트리거 이벤트 browser_now.setUrl(combo_address.getText()); } } }); /* * 1>지금 addOpenWindowListener () 아래 open () 쓰기 e.browser = browser_new * 상황에서 책갈피를 새 하이퍼링크, 오직 이 페이지에 링크를 누르면 또한 링크 안 새로운 페이지를 열 때 벌어진. 2>지금 * addOpenWindowListener () 아래 open () 쓰기 e.browser = browser_new 상황에서 * 책갈피를 새 하이퍼링크, 오직 이 페이지에 링크를 누르면 또한 링크 새로운 페이지를 열 때 벌어진. 이상 두 가지 말고 바깥 * 당연히 아직 browser.back (포함), browser.forward (), browser.go (), * browser.setUrl () 발생 시 발동, 하지만 changing () 는 쓰기 e.browser = * browser_new 상황에서 지원되지 browser.setUrl () 트리거 */ browser_now.addLocationListener(new LocationAdapter() { @Override public void changing(LocationEvent e) {// 하이퍼링크 주소 바뀐 말했다 if (openNewItem == false) {// 새 페이지 같은 탭으로 열기 button_back.setEnabled(true);// 뒤로 단추를 사용할 수 있습니다. 이 구절은 뒤로 // 단추를 사용할 수 있는 논리 시작 시 결정 } System.out.println("location_changing");// 디버그 문 } @Override public void changed(LocationEvent e) {// 링크 주소 찾았다 페이지 combo_address.setText(e.location);// 링크 주소 변경 보이기 /* * 새 페이지 이미 열어서 browser 있는 LocationListener 이미 감청 완료, * openNewItem 답장 기본값 */ if (openNewItem == true) { openNewItem = false; } System.out.println("location_changed : " + e.location); String location = e.location; if ( location.equals("https://bible.ctm.kr/") && findCheck != 0) { if ( loginCheckCnt == 0 ) { loginCheckCnt++; } else if ( loginCheckCnt == 1 ) { String script = "window.frames['ctmhome'].document.getElementsByTagName('form')[1].getElementsByTagName('table')[0].getElementsByTagName('table')[" + Integer.toString(curBookCnt) + "].click()"; executeScript(script); if(curBookCnt < maxBookCnt) curBookCnt++; } } else if(e.location.indexOf("complete_bible2") != -1 && findCheck != 0){ if (browser_now.isBackEnabled()) {// 뒤로 browser_now.back(); button_forward.setEnabled(true); } } } }); /* * 새로운 하이퍼링크 페이지 가져오기%, 책갈피를 새 페이지 발생, 이때 이미 링크 주소 */ browser_now.addProgressListener(new ProgressAdapter() { @Override public void changed(ProgressEvent e) {// 이번 사건이 끊임없이 일어난 는 페이지 가져오기 과정에서 progressBar_status.setMaximum(e.total);// e.total 에서 가장 시작 페이지 끝까지 페이지 의 수치 progressBar_status.setSelection(e.current); if (e.current != e.total) {// 페이지 아직 완전히 가져오기 loadCompleted = false; progressBar_status.setVisible(true);// 페이지 가져오기 상황이 표시줄을 보이는 } else { loadCompleted = true; progressBar_status.setVisible(false);// 페이지 가져오기 상황이 표시줄 안 보인다 } System.out.println("addProgressListener.changed : " + loadCompleted);//디버그 문 if(typing && typingCompleted && loadCompleted) { typingCompleted = false; typing(); } } @Override public void completed(ProgressEvent e) {// 발생 한 번 가져오기 페이지 때 본 모니터 changed 사건 발생 전에 마지막으로 System.out.println("addProgressListener.completed : progress_completed"); if(typing) { //completed 이후 addProgressListener.changed 가 발생한다. 이때 타이핑시킨다. typingCompleted = true; } } }); /* * 페이지 내용 가져오는 addProgressListener 과정, 문자 보이기 () 과정 을 동시에 인지되었습니다 페이지 수 * 있는 슈퍼 링크 열기 이미 바로 간 기능 온 가져오기 새 링크 주소 */ browser_now.addStatusTextListener(new StatusTextListener() { public void changed(StatusTextEvent e) { if (loadCompleted == false) { label_status.setText(e.text); } else { newUrl = e.text;// 페이지 가져오기 완료, 포착 페이지에 링크를 열 수 있다 } } }); /* * 페이지 표시 문구 표시, 새로운 페이지 가져오기 발생 */ browser_now.addTitleListener(new TitleListener() { public void changed(TitleEvent e) { shell_default.setText(e.title); if (e.title.length() > 3) {// 현재 페이지의 팁 표시 문자 탭에 tabItem_now.setText(e.title.substring(0, 3) + ".."); } else { tabItem_now.setText(e.title); } tabItem_now.setToolTipText(e.title);// 탭 표시 프롬프트 } }); /* * 새 페이지 열기 현재 페이지 열기 새 링크 필요한 새 창 페이지 열기 발생.addOpenWindowListener 다음 * open () 중 한 마디 e.browser = browser_new;중요한 부분. 연락 * addOpenWindowListener, addVisibilityWindowListener 과 * addDisposeListener 값 배달 중추. */ // 현재 페이지의 링크 페이지 열기 클릭 browser_now.addOpenWindowListener(new OpenWindowListener() { public void open(WindowEvent e) { Browser browser_new = new Browser(tabFolder, SWT.NONE); TabItem tabItem_new = new TabItem(tabFolder, SWT.NONE); tabItem_new.setControl(browser_new); tabFolder.setSelection(tabItem_new);// 새 탭 열기 페이지 잡담 끝. tabFolder.redraw();// 새로 고침 용기 browser_new.setUrl(newUrl);// 새 탭으로 링크 설정 새로운 주소 openNewItem = true;// 새 페이지 새 탭을 엽니다 /* * 관건이 되는 부분 알려 by browser_new 새로운 페이지 열기 하면 실현 이 말 안 팝업 운영 체제 * 기본 브라우저 되었다 */ e.browser = browser_new; // System.out.println("OpenWindowListener_open");//디버그 문 /* * 새 탭 브라우저 추가합니다 사건 감청 */ display.syncExec(new Runnable() { public void run() { runThread(); } }); } }); /* * 브라우저 닫기 이벤트가 현재 기능 탐색기, 닫기, 아니면 브라우저 주 창 닫기, 실행, 그리고 프로세스 */ browser_now.addCloseWindowListener(new CloseWindowListener() { public void close(WindowEvent e) { browser_now.dispose(); } }); //--------------------------------------------------------------------- /* * login */ button_login.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent arg0) { loginCheckCnt++; //System.out.println("로그인 !!!"); // jquery 가 먹지 않는다. 정말 ? executeScript("parent.ctmhome.document.getElementsByName('id')[0].parentNode.innerHTML = \"<input type='TEXT' size='6' maxlength='15' name='id' value='USER_ID'>\""); executeScript("parent.ctmhome.document.getElementsByName('pwd')[0].parentNode.innerHTML = \"<input value='USER_PASSWORD' type='password' size='7' maxlength='15' name='pwd'>\""); executeScript("window.top.ctmhome.document.getElementsByTagName('input')[5].click()"); } }); /* * find */ button_findWrite.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent arg0) { curBookCnt = 0; findCheck++; String script = "window.frames['ctmhome'].document.getElementsByTagName('form')[1].getElementsByTagName('table')[0].getElementsByTagName('table')[" + Integer.toString(curBookCnt) + "].click()"; executeScript(script); if(curBookCnt < maxBookCnt) curBookCnt++; } }); /* * autoStart */ button_autoStart.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent arg0) { System.out.println("========== typing start =========="); typing = true; if(typing) { typing(); } } }); /* * autoEnd */ button_autoEnd.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent arg0) { System.out.println("========== typing end =========="); typing = false; } }); } /** * --------------------------------------------------------------------- * * --------------------------------------------------------------------- */ final boolean executeScript(String script) { System.out.println("---------- excute script s ----------"); System.out.println(" value : " + script); boolean result = browser_default.execute(script); System.out.println(" result : " + result); System.out.println("---------- excute script e ----------"); return result; } final Object evaluateScript(String script) { System.out.println("---------- evaluate script s ----------"); Object obj = null; try { script = "return " + script + ";"; System.out.println(" value : " + script); obj = browser_default.evaluate(script); System.out.println(" result : " + obj); } catch (Exception e) { e.printStackTrace(); } System.out.println("---------- evaluate script e ----------"); return obj; } final int typing() { try { Thread.sleep(1); // TODO : Thread Object obj = null; String script = ""; int length = 0; //span 이 두개인 경우가 있어서 마지막것을 선택 하게끔 span 개수를 구해야한다. String doc = "top.document.getElementsByTagName('form')[0].getElementsByTagName('table')[0].getElementsByTagName('iframe')[0].contentWindow.document"; script = ""; script += doc + ".activeElement.parentNode.getElementsByTagName('span').length"; if(!executeScript(script)) { return -1; } obj = evaluateScript(script); double longLenght = 0.0; longLenght = (double)obj; length = (int)longLenght; //------------------------------------------------------------------------------------------- script = ""; script += doc + ".activeElement.parentNode.getElementsByTagName('span')[" + Integer.toString(length-1) + "].innerHTML"; // 복사할 대상 HTML obj = evaluateScript(script); //------------------------------------------------------------------------------------------- // targetHTML 그대로 복 붙 script = ""; script += doc + ".activeElement.value = "; // typing 대상 element script += doc + ".activeElement.parentNode.getElementsByTagName('span')[" + Integer.toString(length-1) + "].innerHTML"; // 복사할 대상 HTML executeScript(script); //------------------------------------------------------------------------------------------- //한절 모든 입력이 끝난 후 공백을 주면 다음절로 넘어간다. // 스페이스바는 32 keyboardEvent("32"); } catch(InterruptedException e) { System.out.println(e.getMessage()); } return 1; } final Object keyboardEvent(String key) { Object obj = null; String script = ""; String doc = "top.document.getElementsByTagName('form')[0].getElementsByTagName('table')[0].getElementsByTagName('iframe')[0].contentWindow.document"; /** function disEvt(doc, el, key) { var evt = doc.createEvent('event'); evt.keyCode = key; evt.initEvent('keydown',false,false); el.dispatchEvent(evt); }; disEvt(" + doc + "," + doc + ".activeElement, " + key + "); */ script = ""; script += "function disEvt(doc, el, key) {"; // key event 용 function 을 등록 script += " var evt = doc.createEvent('event');"; script += " evt.keyCode = key;"; script += " evt.initEvent('keydown',false,false);"; script += " el.dispatchEvent(evt);"; script += "};"; // 스페이스바는 32 script += "disEvt(" + doc + "," + doc + ".activeElement, " + key + ");"; obj = executeScript(script); return obj; } } | cs |
실행시키면 하단에 login, find, start, end 버튼 4개가 있을 것이다.
login 은 위에서 언급한 스크립트 상 value 에 id 와 password 를 입력해 놓으면 한번 클릭으로 바로 로그인 될 수 있겠다.
find 는 완료가 아닌 통독해야할 성경을 찾아 클릭이벤트를 발생시키는 건데, 한장 한장 클릭하며 확인 후 다음 성경으로 넘어가는 방식이여서 사용하지 않길 바란다.
수정해야하는데 귀찮이즘으로 안했다...
다음 start 는 타이핑해야할 화면
위와같은 상태에서 start 버튼을 누르면 쳐야할 구절을 카피해서 아래 input 에 붙여 넣는다.
그러면서 쭉쭉 넘어간다.
자세한 사항은 소스를 분석해 보기 바란다.
불필요한 소스도 있고 ... 그렇지만 타이핑하나 기똥차게 치고 넘어간다.
이상 끝
추신 : 부디 많은 사람들이 사이트를 위와같은 오토를 돌려 번갈아 가며 1위를 했으면 하는 바람이다. 소스상 sleep 를 최대한 크게 주어서 장시간 돌려주자.
개인적으로 몇일 1등 먹었더니 전화가 왔다... 매크로 돌리느냐고 ;; 난 왜 진짜 전화번호를 걸어놨을까;
1차 실망 - 성경을 타이핑하시면서 통독하시는 분들이 등수에 연연하시다니 ...
2차 실망 - 위 사이트이다. 거진 10년이 넘도록 변한게 없다.
HTML 까보면 이건 아니지 싶다. 이렇게 TABLE 안에 다시 TABLE 안에 ... 거기에 ID 도 거의 안달려있고 ...
3차 실망 - 전체적으로 광고가 좀 많아졌다. 후원링크라던지 후원전화라던지 불법은 아닌지 모르겠다.
기독교와 전쟁선포하는 그런거 아니다. 나도 주말이면 교회가는 교인이다.
부디 각성하고 초심으로 돌아가 나같은 허접한사람이 감히 메크로 돌릴 수 없는 그런 사이트로 발전하길 바라는 마음이 더 크다.
전화까지 한거 보니 ... 내 개인정보 입력해놓은것은 다 털린거나 마찬가지다. ㅎㅎㅎ 나도 참 순진하지.
만약 사이트 개정이 막히거나 하면 ... 후후 ... 다음 글 연재 되는거다. ㅎ
아... 차라리 EXE 를 만들어 배포할까? 그편이 더 낳을것 같다는 생각을 하며 ... 글을 마친다.
'DEV' 카테고리의 다른 글
2. Your First Java Application with OpenCV (OpenCV를 사용한 첫 번째 Java 응용 프로그램) (0) | 2017.12.09 |
---|---|
1.Installing OpenCV for Java (java 용 OpenCV 설치) (0) | 2017.12.08 |
장진만쌤의 Sung Kim 교수님의 모두의 RL 수업을 보고 나서 따라 하기 (0) | 2017.10.16 |
eclipse + SVN (subversion) 설치 (0) | 2017.08.03 |
eGov context-root 조작 (0) | 2017.08.02 |