프로젝트 새로 만들기

플러그인 프로젝트 선택
프로젝트 이름 및 플러그인실행대상 선택
기본 자바 실행버전(좀 낮게), UI 제공, RCP응용프로그램 작성여부 Yes
RCP 기본 템플릿 선택(3.x로 시작)
패키지 기본설정
RCP 기본템플릿 실행(plugin.xml선택, 개요탭에 Eclipse응용프로그램 실행)

ㅁ 기본구조 확인

기본적으로 RCP프로젝트를 생성하면 아래와 같은 기본 클래스들이 생긴다. 이 클래스들은 RCP프로그램에서 각자의 역할이 있으며, 구성하고있는 역할을 알고 있어면 훗날 개발을 진행할 때 진행이 수월하다.

  • Application

    RCP프로그램의 main routine으로 동작 및 프로그램의 컨트롤러 역할을 한다. 또한 Workbench와 다른 Workbench Advisor라고 불리는 다른 클래스들을 연결시키는 역할한다. 이때 Workbench는 프로그램 하나를 말한다. Workbench는 Worbench Window을 포괄하는 개념이며, 예를 들어 새로운 이클립스창이 띄워졌을때 New window를 하면 하나의 창이 더 띄워진다. 이때 각각의 창은 Workbench Window이고, 2개가 존재한다. 하지만 Workbench는 창이 늘어나도 하나로 존재하게된다.

  • WorkbenchAdvisor

    Workbench의 lifecycle에 대해 명시하고 있다. default perspective와 같은 중요한 파라미터들을 Workbench에 제공한다. 가장 중요한 점은 WorkbenchAdvisor의 메소드들은 오버라이드가 될 수 없다.

  • WorbenchWindowAdvisor

    상태 line, 툴바. 제목. 윈도우 사이즈 등 커스터마이즈 하길 원하는 것들이 들어간다.

  • Perspective

    view, editor, menu들의 위치와 사이즈를 갖고있음 적어도 하나의 perspective는 가지고 있어야 한다.

  • View

    화면을 담당하는 부분이다. 곧, 뷰어들을 생성하고 초기화를 진행한다. 화면을 Viewer의 컨트롤에 요청하는 setFocus()와 모든 구성 요소들을 활성화하는 CreatePartControl(Composite) 함수가 반드시 필요하다. 이 두 함수는 처음 실행될때 호출된다. setFocus() createPartControl(Composite)는 시키기 위해 선언하는 곳이다

 

10가지의 플러그인 중 큰 몇가지만 설명하고자 한다.

  • UI Workbench: UI Workbench는 editor, view, perspective 등을 포함하고 있다.
  • SWT: 운영체제의 네이티브 윈도우 환경과 긴밀하게 통합된 다양한 컴포넌트와 플랫폼 독립적인 API를 제공한다. 즉, 윈도우에서 정의한 위젯에 대한 접근을 제공한다.
  • JFACE: 범용 UI 개념을 위한 구조와 편의기능을 제공한다. SWT를 이용하여 사용자 인터페이스를 개발할 때 해야하는 많은 공통 작업들을 간단하게 해 주는 컴포넌트와 헬퍼 유틸리티 세트를 제공 데이터 뷰, 위저드, 다이얼로그 컴포넌트 등을 제공하기 위해 SWT를 확장하는 많은 유틸리티 클래스들을 포함하고 있다.
  • RUNTIME: 플러그인과 페이지 로딩 및 초기화 간에 확장 포인트 모델 기반의 느슨한 결합을 정의하고 있다.
  • OSGi: 이클립스에서 플러그인의 발견 및 애플리케이션의 재시작 없이 플러그인을 로딩 및 언로딩하는 것을 포함하여 플러그인의 라이프사이클 관리등을 위한 프레임워크이다.

※ (참고)워크벤치 어드바이저 생명주기



ㅁ RCP관련 참고 사이트 들

    www.eclipse.org/articles/

 

Eclipse Corner - Eclipsepedia

These following articles have been written by members of the various project development teams and other members of the Eclipse community. Eclipse setup instructions on a new Linux (or other OS) computer Getting started with Eclipse as a beginner is diffic

wiki.eclipse.org

    o7planning.org/en/10953/eclipse-rcp

 

Eclipse RCP

The small examples The small examples No examples

o7planning.org

    www.vogella.com/tutorials/eclipse.html

 

Eclipse, RCP, Plugin and OSGi Development

 

www.vogella.com

 

'IT > RCP' 카테고리의 다른 글

RCP 배포관련 문제  (0) 2022.12.26
[JFace] 뷰어와 뷰어 프레임 워크  (0) 2020.12.26
[RCP] 개발 환경설정  (0) 2020.12.20
[RCP] 사전 준비 및 주요 용어  (0) 2020.12.20
[SWT] 윈도우 레지스트리  (0) 2020.12.19

ㅁ SWT 다운로드

과거에는 바로 swt.jar만 가져올 수 있게 했는데, 여러단계를 거쳐야 들어갈 수 있게 되어 있다

먼저 SWT사이트를 접속해보자: http://www.eclipse.org/swt/

 

클릭하면

 

맨위에 이클립스는 swt까지 포함된 이클립스 버전인데 저는 기존 이클립스에 swt만 추가하기 위해 하단에 내리면 SWT Binary and source를 다운받는다 bit는 이클립스 기본bit에 따라 다운받음

클릭하면

맨위에 이클립스는 swt까지 포함된 이클립스 버전인데 저는 기존 이클립스에 swt만 추가하기 위해 하단에 내리면 SWT Binary and source를 다운받는다 bit는 이클립스 기본bit에 따라 다운받음

방식1) Java 빌드경로 직접추가

   Jar파일 직접 추가 : 외부Jar추가->해당파일(swt.jar) 직접 선택

방식2) 클래스환경변수로 설정

메뉴에서 창-> 환경설정-> Java->Build Path-> Classpath Variables -> New 버튼

Name : SWT_LIB
Path : workspace폴더/wt-3.3-win32-win32-x86/swt.jar
 
Name : JFACE_LIB
Path : eclipse폴더/plugins/org.eclipse.jface_xxxxx.jar
 
Name : BOOT_LIB  ※ 요건 없어진듯
Path : eclipse폴더/plugins/org.eclipse.core.boot_xxxxx.jar
 
Name : RUNTIME_LIB
Path : eclipse폴더/plugins/org.eclipse.core.runtime_xxxxx.jar
 
Name : JFACETEXT_LIB
Path : eclipse폴더/plugins/org.eclipse.jface.text_xxxxx.jar
 
Name : TEXT_LIB
Path : eclipse폴더/plugins/org.eclipse.text_xxxxx.jar
 
Name : OSGI_LIB
Path : eclipse폴더/plugins/org.eclipse.osgi_xxxxx.jar

※ 구방식이라 일부 안되는것도 있음 특히 BOOT_LIB

개발을 하기위해서는 SWT -> JFace -> RCP 순으로 되어 있는데,  환경설정구성에서는 RCP가 JFace, SWT를 포함하고 있기 때문에 RCP환경만 설정하면 모두 사용이 가능하다.(RCP환경설정으로 모두 사용가능)

 

RCP환경설정에 앞서 이클립스는 2000년도부터 무수히 많은 버전을 만들어왔는데 문제는 버전별로 처리 가능한지 하기 위해 이중구성(IDE 환경과 RCP환경) 

 

흔하게 Java를 개발하기 위해서 보통 IDE통합환경을 보통 다운을 받아 설치한다.

ㅁ Target 설정

    1) Java Project 추가 : 이름은 (임의)RCP_Indigo_Target

 

구버전 Indigo RCP환경

※ 현재 어느 플랫폼으로 선택되어 있는지 확인이 가능 

 

필요에 따라 환경을 변경하면 됨

IDE 통합툴이지만 RCP플랫폼의 요소들을 가져와 설정되었기 때문에 SWT, Jface, RCP환경이 이거 하나로 됨

 

ㅁ 참고로 이클립스 명칭별 버전 확인

배포판

배포일

플랫폼 버전

프로젝트명

참여 프로젝트

의미

Photon

2018 6 27

4.8

광양자

Oxygen

2017 6 28

4.7

Oxygen projects

산소(O2)

Neon

2016 6 22

4.6

Neon projects

네온(Ne), 그리스어로 새롭다를 뜻하는 'neos'를 어원

Mars

2015 6 24

4.5

Mars projects

79

화성(라틴어)

Luna

2014 6 25

4.4

Luna projects

76

(라틴어)

Kepler

2013 6 26

4.3

Kepler projects

미정

케플러(천문학자)

Juno

2012 6 27

4.2

Juno projects

미정

주노(로마신화에서 피터의 누이이자 아내)

Indigo

2011 6 22

3.7

Indigo projects

62

남색(H의 다음문자)

Helios

2010 6 23

3.6

Helios projects

39

태양신

Galileo

2009 6 24

3.5

Galileo projects

33

목성 4대 위성의 발견자명

Ganymede

2008 6 25

3.4

Ganymede projects

23

목성의 4대 위성 중 하나로 태양계 최대의 위성

Europa

2007 6 29

3.3

Europa projects

20

목성의 4대 위성 중 하나

Callisto

2006 6 30

3.2

Callisto projects

10

목성의 4대 위성 중 하나

Eclipse 3.1

2005 6 28

3.1

Eclipse 3.0

2004 6 21

3.0



※ 참고 : ko.wikipedia.org/wiki/%EC%9D%B4%ED%81%B4%EB%A6%BD%EC%8A%A4_(%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4)

 

ㅁ 구방식 SWT하나만 추가 방법

    참고 : dicws.tistory.com/118

 

[SWT] SWT만 설치사용(구방식)

ㅁ SWT 다운로드 과거에는 바로 swt.jar만 가져올 수 있게 했는데, 여러단계를 거쳐야 들어갈 수 있게 되어 있다 먼저 SWT사이트를 접속해보자: http://www.eclipse.org/swt/ 클릭하면 맨위에 이클립스는 swt

dicws.tistory.com

 

'IT > RCP' 카테고리의 다른 글

[JFace] 뷰어와 뷰어 프레임 워크  (0) 2020.12.26
[RCP] RCP 기본생성 방법  (0) 2020.12.20
[RCP] 사전 준비 및 주요 용어  (0) 2020.12.20
[SWT] 윈도우 레지스트리  (0) 2020.12.19
[SWT] Win32 OLE  (0) 2020.12.19

클립스는 개발툴로 매우 좋은 도구라 생각되어진다. 대규모 프로젝트시 현존하는 개발툴은

거의 이클립스 기반으로 이루어져 있다해도 과언이 아니라 생각되어진다.

이에 이클립스를 잘사용하는 방법말고 추가 나만의 도구를 개발하여 더욱더 좋은 빠른 개발을 하고자 정리하게 되었고 이에 정리과정을 한번 다시 적어볼까 합니다.

총 3개의 단개로 진행됩니다.

       SWT(Standard Widget Toolkit)->JFace(모델기반)->RCP(Platform)

궁극적 목적은 RCP(Rich Client Platform)으로 이클립스에 추가 도구를 만들기 위함으로 진행해보고자 합니다.

 SWT는 각 컴포넌트를 기본적으로 사용할줄 아는게 목적이고,  이를 JFace를 통하여 모델화시키고 RCP 플렛폼을 만들어 이클립스의 도구 또는 Stand-Alone 프로그램을 구현하고자 합니다.

 

ㅁ RCP 화면구성 

퍼스펙티브 : 일종에 작업책상으로 보면 된다. 여러 작업공간분리 하려고 한다.

                   예를 들면 C프로그램작성, 데이터베이스용, Java, PHP 등등 작업공간

-  : 특정 목적으로 처리할수 있는 공구라 생각하면 된다.

       예를 들면 파일목록을 보는 파일관리자, 프로젝트를 관리하는 프로젝트 관리자 기타 특성, 콘솔 등등이 다 사용할 수 있는 공구라 생각하면 된다.

 - 에디터 : 실제 뭔가를 작업하고 처리하는 부분이라 생각하면 된다. 주로 메인작업을 하는 공간

'IT > RCP' 카테고리의 다른 글

[RCP] RCP 기본생성 방법  (0) 2020.12.20
[RCP] 개발 환경설정  (0) 2020.12.20
[SWT] 윈도우 레지스트리  (0) 2020.12.19
[SWT] Win32 OLE  (0) 2020.12.19
[SWT] 클립보드  (0) 2020.12.19

레지스트 간단예제

package swt.registry;

import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;

public class RegistryUserTest {
	// 주어진 노드에 키를 포함하고 있는지 체크한다.
	public static boolean contains(Preferences node, String key) {
		return node.get(key, null) != null;
	}

	public static void main(String args[]) throws BackingStoreException {
		
		Preferences userRootPrefs = Preferences.userRoot();
		//레지스트리에 시스템 Root못건드림 Preferences systemRootPrefs = Preferences.systemRoot();
		
		String key = "xname";
		if (contains(userRootPrefs, key)) {
			String value = userRootPrefs.get(key, "");	//있으면 있는거 출력
			System.out.println("xname : " + value);
		} else {
			String value = "upark";
			userRootPrefs.put(key, value);	//없으면 만들어 set
			System.out.println("create uname : " + value);
		}
	}
}

HKEY_CLASSES_ROOT레지스트리에 http\\shell\\open\\command  에 보면 default 브라우저 설정

package swt.registry;

import java.util.Enumeration;

import com.ice.jni.registry.NoSuchValueException;
import com.ice.jni.registry.RegStringValue;
import com.ice.jni.registry.Registry;
import com.ice.jni.registry.RegistryException;
import com.ice.jni.registry.RegistryKey;

public class JNIRegistryTest {
	private static final String REG_SWT_PARAMS = "Software\\RnDClub\\Client\\Params";

	public static final String REG_AMS_KEY_CLASSNAME = "AMS";

	public static final String REG_AMS_KEY_ID = "id";

	public static final String REG_AMS_KEY_DIR_HOME = "home";

	public static final String REG_AMS_KEY_DB_DRIVER = "dbDriver";

	public static final String REG_AMS_KEY_DB_URL = "dbUrl";

	public static final String REG_AMS_KEY_DB_USER = "dbUser";

	public static final String REG_AMS_KEY_DB_PASS = "dbPass";

	private static RegistryKey amsClientParamsRkey = null;

	public static String getDefaultBrowserCommand() {
		String value = null;
		String name = "http\\shell\\open\\command";
		try {
			RegistryKey rkey = Registry.HKEY_CLASSES_ROOT.createSubKey(name,
					"", RegistryKey.ACCESS_ALL);
			// System.out.println("rkey : " + rkey);
			value = rkey.getStringValue("");
		} catch (RegistryException e) {
			e.printStackTrace();
		}
		return (value);
	}

	public static RegistryKey getCurrentUserRegistryKey(String name) {
		RegistryKey rkey = null;
		try {
			rkey = Registry.HKEY_CURRENT_USER.createSubKey(name,
					"", RegistryKey.ACCESS_ALL);
			if (rkey.wasCreated() == true) {
				System.out.println("'" + name + "' rkey was created...");
			}
		} catch (RegistryException e) {
			e.printStackTrace();
		}
		return (rkey);
	}

	public static String getAmsClientParameter(String name) {
		String value = null;
		try {
			if (amsClientParamsRkey == null) {
				amsClientParamsRkey = getCurrentUserRegistryKey(REG_SWT_PARAMS);
			}
			value = amsClientParamsRkey.getStringValue(name);
		} catch (RegistryException e) {
			e.printStackTrace();
		}
		return (value);
	}

	public static void putAmsClientParameter(String name, String str) {
		try {
			if (amsClientParamsRkey == null) {
				amsClientParamsRkey = getCurrentUserRegistryKey(REG_SWT_PARAMS);
			}
			RegStringValue value = new RegStringValue(amsClientParamsRkey,
					name, str);
			amsClientParamsRkey.setValue(name, value);
		} catch (NoSuchValueException e) {
			e.printStackTrace();
		} catch (RegistryException e) {
			e.printStackTrace();
		}
	}

	public static void test() {
		try {
			if (amsClientParamsRkey == null) {
				amsClientParamsRkey = getCurrentUserRegistryKey(REG_SWT_PARAMS);
			}
			System.out.println("getFullName : "
					+ amsClientParamsRkey.getFullName());
			System.out.println("getMaxSubkeyLength : "
					+ amsClientParamsRkey.getMaxSubkeyLength());
			System.out.println("getMaxValueDataLength : "
					+ amsClientParamsRkey.getMaxValueDataLength());
			System.out.println("getMaxValueNameLength : "
					+ amsClientParamsRkey.getMaxValueNameLength());
			System.out.println("getName : " + amsClientParamsRkey.getName());
			System.out.println("getNumberSubkeys : "
					+ amsClientParamsRkey.getNumberSubkeys());
			System.out.println("getNumberValues : "
					+ amsClientParamsRkey.getNumberValues());

			Enumeration e = amsClientParamsRkey.valueElements();
			while (e.hasMoreElements()) {
				String key = (String) e.nextElement();
				String val = amsClientParamsRkey.getStringValue(key);
				System.out.println("key : " + key + ", val : " + val);
			}
			/*
			 * System.out.println(); for (int i = 0; i <
			 * amsClientParamsRkey.getNumberValues(); i++) { String key =
			 * amsClientParamsRkey.regEnumValue(i); String val =
			 * amsClientParamsRkey.getStringValue(key); System.out.println("[" +
			 * i + "] key : " + key + ", val : " + val); }
			 */
		} catch (RegistryException e) {
			e.printStackTrace();
		}
	}

	public static void main(String args[]) {
		test();

		putAmsClientParameter("server", "127.0.0.1");
		String value = getAmsClientParameter("server");
		System.out.println("server : " + value);

		putAmsClientParameter("dbUrl",
				"jdbc:oracle:thin:@127.0.0.1:1521:opendb");
		value = getAmsClientParameter("dbUrl");
		System.out.println("dbUrl : " + value);

		putAmsClientParameter("workspace", "D:\\workspace");
		value = getAmsClientParameter("workspace");
		System.out.println("workspace : " + value);

		putAmsClientParameter("home", "D:\\Temp\\ams_client");
		value = getAmsClientParameter("home");
		System.out.println("home : " + value);

		putAmsClientParameter("id", "ywoopark");
		value = getAmsClientParameter("id");
		System.out.println("id : " + value);

		value = getDefaultBrowserCommand();
		System.out.println("ie : " + value);
	}
}

위 경우는 현재 32bit만 가능하며 32bit인경우 registry.jar,ICE_JNIRegistry.dll 가 필요하며

registry.jar에 Native에 ICE_JNIRegistry.dll를 추가 설정해주어야 가능하다.

'IT > RCP' 카테고리의 다른 글

[RCP] 개발 환경설정  (0) 2020.12.20
[RCP] 사전 준비 및 주요 용어  (0) 2020.12.20
[SWT] Win32 OLE  (0) 2020.12.19
[SWT] 클립보드  (0) 2020.12.19
[SWT] Drag & Drop  (0) 2020.12.19

이클립스에서 OLEFrame으로 OLE객체를 내장할 수 있다.

여기서 OLE란 Object Link Editer로 MS의 OCX, ActiveX 컨트롤를 말한다.

먼저 주요클래스를 확인하여 보자

 

[Win32 주요 클래스]

객체를 생성하는 방법, 그리고 객체를 사용하는 방법을 알아보자

먼저 간단하게 MS워드, 익스플로러, 엑셀, 미디어플레이어 을 띄우는 방법을 알아보자

참고로 oleviewer라고 Visual Studio에서 나온것이 있는데, OLE를 사용하기 위한 API문서처럼 메소드들을 제공한다.

oleview_setup&amp;dll.zip
0.66MB

OLE를 사용하기에 위해 주요클래스 중 몇가지를 살펴보자

OleClientSite : OLE 도큐먼트를 관리하기위함.
  -편집기 생성, 토큐먼트 활성/비활성, 변경내용저장
 OleControlSite : OleClientSite의 상속받아 액티브X컨트롤를 관리
  -컨트롤 이벤트 제공, 변경되었음을 제공, 폰트 배경색 등 변경가능
 OleAutomation : IDispatch 인터페이스 지원,메소드 사용(매개변수는 Variant형태 전달)
   setProperty
   invoke 
   invokeNoReply  

OLE를 사용하여 객체 생성예제

package swt.ole;

import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.ole.win32.OLE;
import org.eclipse.swt.ole.win32.OleClientSite;
import org.eclipse.swt.ole.win32.OleFrame;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class OLE_Test {

	public static void main(String[] args) {
		
		Display display = new Display();
		Shell shell = new Shell(display);
		shell.setLayout(new FillLayout());
		shell.setText("SWT Ole Test");
		OleClientSite clientSite;
		//OleControlSite oleControlSite;
		OleFrame frame = new OleFrame(shell, SWT.NONE);
		clientSite = new OleClientSite(frame, SWT.NONE,"Word.Document");
		clientSite.doVerb(OLE.OLEIVERB_INPLACEACTIVATE);
		//각 OLE객체를 생성하는 방법1~4
		/*
		//1.1 MS Word 띄우기:OLE객체 -ProgramID
		clientSite = new OleClientSite(frame, SWT.NONE,"Word.Document");
		*/
		/*
		//1.2 MS Word 띄우기-MS워드파일로 띄우기 
		clientSite = new OleClientSite(frame, SWT.NONE,new File("d:\\test.doc"));
		*/
		/*
		//2.MS Excel 띄우기-ProgramID
		clientSite = new OleClientSite(frame, SWT.NONE,"Excel.Sheet");
		*/
		/*
		//3.익스플로러 띄우기-ProgramID
		clientSite = new OleClientSite(frame, SWT.NONE,"Shell.Explorer");
		*/
		//4.미디어 플레이어 띄우기
		//clientSite = new OleClientSite(frame, SWT.NONE,"WMPlayer.OCX");
		
		System.out.println("clientSite : " + clientSite.getProgramID());
		
		shell.setSize(640, 480);
		shell.open();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
		
		//oleAuto.dispose();
		display.dispose();
	}
}

여기서 주석으로 각각 막아 놓은것은 주요 OLE객체에 임. 1.2에서 파일을 통하여 OLE객체를 생성할 수도 있다.

파일을 통해 OLE객체를 생성한경우 객체에 ProgID를 추가적으로 알수 있다.

clientSite.getProgramID()

 

그럼 OLE객체의 메소드, Property등을 oleview.exe외 자바에서 추출하는 예제를 확인해보자

OleControlSite를 통하여 메소드들을 알수 있다.(너무 많아 자세히 보기 어렵긴하네요)

package swt.ole;

import java.io.File;

import org.eclipse.swt.SWT;
import org.eclipse.swt.internal.ole.win32.TYPEATTR;
import org.eclipse.swt.ole.win32.OLE;
import org.eclipse.swt.ole.win32.OleAutomation;
import org.eclipse.swt.ole.win32.OleClientSite;
import org.eclipse.swt.ole.win32.OleControlSite;
import org.eclipse.swt.ole.win32.OleFrame;
import org.eclipse.swt.ole.win32.OleFunctionDescription;
import org.eclipse.swt.ole.win32.OlePropertyDescription;
import org.eclipse.swt.widgets.Shell;

public class getOLEMethod {

	public static void main(String[] args) {
		/*
		 * if (args.length == 0) { System.out.println("Usage: java Main "); return; }
		 */
		Shell shell = new Shell();

		OleFrame frame = new OleFrame(shell, SWT.NONE);
		OleClientSite oleControlSite = new OleClientSite(frame, SWT.NONE, new File("d:\\test.doc"));
		String progID = oleControlSite.getProgramID();

		// 컨트롤은 프로그램 id를 통하여만 가져올수 있다.
		OleControlSite site = new OleControlSite(frame, SWT.NONE, progID);
		OleAutomation auto = new OleAutomation(site); // 각 메소드의 사용

		TYPEATTR typeattr = auto.getTypeInfoAttributes();

		if (typeattr != null) {

			// function기술시작
			if (typeattr.cFuncs > 0) {
				System.out.println("Functions for " + progID + ":");
			}
			
			for (int i = 0; i < typeattr.cFuncs; i++) {
				
				OleFunctionDescription data = auto.getFunctionDescription(i);
				String argList = "";
				
				int firstOptionalArgIndex = data.args.length - data.optionalArgCount;
				
				for (int j = 0; j < data.args.length; j++) {
					argList += "[";
					//옵션 항목기술
					if (j >= firstOptionalArgIndex) {
						argList += "optional, ";
					}
					//function항목명, type기술
					argList += getDirection(data.args[j].flags) + "] " + getTypeName(data.args[j].type) + " "
							+ data.args[j].name;
					//다음항목 , 표시
					if (j < data.args.length - 1) {
						argList += ", ";
					}
				}
				
				System.out.println(getInvokeKind(data.invokeKind) + " (id = " + data.id + ") : " + "Signature : "
						+ getTypeName(data.returnType) + " " + data.name + "(" + argList + ")" + " Description : "
						+ data.documentation + "Help File : " + data.helpFile + "");
			}

			//속성값 기술 시작
			if (typeattr.cVars > 0) {
				System.out.println(" ");
				System.out.println(" Variables for " + progID + " : ");
			}
			
			//속성값 기술목록출력
			for (int i = 0; i < typeattr.cVars; i++) {
				OlePropertyDescription data = auto.getPropertyDescription(i);
				System.out.println("PROPERTY (id = " + data.id + ") :" + "Name : " + data.name + "Type : "
													 + getTypeName(data.type) + "");
			}
		}

		auto.dispose();
		shell.dispose();
	}

	private static String getTypeName(int type) {
		switch (type) {
		case OLE.VT_BOOL:
			return "boolean";
		case OLE.VT_R4:
			return "float";
		case OLE.VT_R8:
			return "double";
		case OLE.VT_I4:
			return "int";
		case OLE.VT_DISPATCH:
			return "IDispatch";
		case OLE.VT_UNKNOWN:
			return "IUnknown";
		case OLE.VT_I2:
			return "short";
		case OLE.VT_BSTR:
			return "String";
		case OLE.VT_VARIANT:
			return "Variant";
		case OLE.VT_CY:
			return "Currency";
		case OLE.VT_DATE:
			return "Date";
		case OLE.VT_UI1:
			return "unsigned char";
		case OLE.VT_UI4:
			return "unsigned int";
		case OLE.VT_USERDEFINED:
			return "UserDefined";
		case OLE.VT_HRESULT:
			return "int";
		case OLE.VT_VOID:
			return "void";

		case OLE.VT_BYREF | OLE.VT_BOOL:
			return "boolean *";
		case OLE.VT_BYREF | OLE.VT_R4:
			return "float *";
		case OLE.VT_BYREF | OLE.VT_R8:
			return "double *";
		case OLE.VT_BYREF | OLE.VT_I4:
			return "int *";
		case OLE.VT_BYREF | OLE.VT_DISPATCH:
			return "IDispatch *";
		case OLE.VT_BYREF | OLE.VT_UNKNOWN:
			return "IUnknown *";
		case OLE.VT_BYREF | OLE.VT_I2:
			return "short *";
		case OLE.VT_BYREF | OLE.VT_BSTR:
			return "String *";
		case OLE.VT_BYREF | OLE.VT_VARIANT:
			return "Variant *";
		case OLE.VT_BYREF | OLE.VT_CY:
			return "Currency *";
		case OLE.VT_BYREF | OLE.VT_DATE:
			return "Date *";
		case OLE.VT_BYREF | OLE.VT_UI1:
			return "unsigned char *";
		case OLE.VT_BYREF | OLE.VT_UI4:
			return "unsigned int *";
		case OLE.VT_BYREF | OLE.VT_USERDEFINED:
			return "UserDefined *";
		}
		return "unknown " + type;
	}

	private static String getDirection(int direction) {
		String dirString = "";
		boolean comma = false;
		if ((direction & OLE.IDLFLAG_FIN) != 0) {
			dirString += "in";
			comma = true;
		}
		if ((direction & OLE.IDLFLAG_FOUT) != 0) {
			if (comma)
				dirString += ", ";
			dirString += "out";
			comma = true;
		}
		if ((direction & OLE.IDLFLAG_FLCID) != 0) {
			if (comma)
				dirString += ", ";
			dirString += "lcid";
			comma = true;
		}
		if ((direction & OLE.IDLFLAG_FRETVAL) != 0) {
			if (comma)
				dirString += ", ";
			dirString += "retval";
		}

		return dirString;
	}

	private static String getInvokeKind(int invKind) {
		switch (invKind) {
		case OLE.INVOKE_FUNC:
			return "METHOD";
		case OLE.INVOKE_PROPERTYGET:
			return "PROPERTY GET";
		case OLE.INVOKE_PROPERTYPUT:
			return "PROPERTY PUT";
		case OLE.INVOKE_PROPERTYPUTREF:
			return "PROPERTY PUT BY REF";
		}
		return "unknown " + invKind;
	}
}

MS워드의 경우 OLEVIEW를 가지고 한번 메소드를 찾긴 했는데 찾는데 어려운듯

그럼 이걸가지고 특정파일을 열게 실행을 해보겠습니다.

'IT > RCP' 카테고리의 다른 글

[RCP] 사전 준비 및 주요 용어  (0) 2020.12.20
[SWT] 윈도우 레지스트리  (0) 2020.12.19
[SWT] 클립보드  (0) 2020.12.19
[SWT] Drag & Drop  (0) 2020.12.19
[SWT] 다이얼로그  (0) 2020.12.19

윈도우에서 흔히 사용하고 있는 클립보드를 예제를 보자

copy, paste, query(클립보드 내용및 분류)

package swt.clipboard;

import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

public class CopyAndPasteWithClipboard {
	
	Display display = null;
	Shell shell = null;
	Text text = null;
	Button copy = null;
	Button paste = null;
	Button clear = null;
	Button query = null;
	Clipboard cb = null;

	//Main시작
	public static void main(String[] args) {
		CopyAndPasteWithClipboard app = new CopyAndPasteWithClipboard();
		app.run();
	}	

	//run에서 화면 실행
	public void run() {
		shell.open();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
	}	
	
	public CopyAndPasteWithClipboard() {
		createUI();		//ui선언
		doLayout();		//layout
		addListener();	//이벤트 처리
	}

	public void createUI() {
		display = new Display();
		cb = new Clipboard(display);
		shell = new Shell(display);
		shell.setText("SWT Clipboard Test");

		text = new Text(shell, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL
				| SWT.H_SCROLL);

		copy = new Button(shell, SWT.PUSH);
		copy.setText("Copy");

		paste = new Button(shell, SWT.PUSH);
		paste.setText("Paste");

		clear = new Button(shell, SWT.PUSH);
		clear.setText("Clear");

		query = new Button(shell, SWT.PUSH);
		query.setText("Query");
	}

	public void doLayout() {
		shell.setLayout(new FormLayout());

		FormData data = new FormData();
		data.right = new FormAttachment(100, -5);
		data.top = new FormAttachment(0, 5);
		copy.setLayoutData(data);

		data = new FormData();
		data.right = new FormAttachment(100, -5);
		data.top = new FormAttachment(copy, 5);
		paste.setLayoutData(data);

		data = new FormData();
		data.right = new FormAttachment(100, -5);
		data.top = new FormAttachment(paste, 5);
		clear.setLayoutData(data);

		data = new FormData();
		data.right = new FormAttachment(100, -5);
		data.top = new FormAttachment(clear, 5);
		query.setLayoutData(data);

		data = new FormData();
		data.left = new FormAttachment(0, 5);
		data.top = new FormAttachment(0, 5);
		data.right = new FormAttachment(copy, -5);
		data.bottom = new FormAttachment(100, -5);
		text.setLayoutData(data);

		shell.setSize(320, 240);
	}

	public void addListener() {
		copy.addListener(SWT.Selection, new Listener() {
			public void handleEvent(Event e) {
				String textData = text.getSelectionText();
				if ((textData != null) && (!"".equals(textData))) {
					TextTransfer textTransfer = TextTransfer.getInstance();
					cb.setContents(new Object[]{textData},
							new Transfer[]{textTransfer});
				}
			}
		});
		paste.addListener(SWT.Selection, new Listener() {
			public void handleEvent(Event e) {
				TextTransfer transfer = TextTransfer.getInstance();
				String data = (String) cb.getContents(transfer);
				if (data != null) {
					text.insert(data);
				}
			}
		});
		clear.addListener(SWT.Selection, new Listener() {
			public void handleEvent(Event e) {
				cb.clearContents();
			}
		});
		query.addListener(SWT.Selection, new Listener() {
			public void handleEvent(Event e) {
				String names[] = cb.getAvailableTypeNames();
				text.insert("\n----------------------\n");
				for (int i = 0; (names != null) && (i < names.length); i++) {
					text.insert("names[" + i + "] : " + names[i] + "\n");
				}
				text.insert("----------------------\n");
			}
		});
	}

	public void dispose() {
		if (cb != null) {
			cb.dispose();
		}
		if (display != null) {
			display.dispose();
		}
	}
	

}

하나 중점으로 하나 볼것은 copy할때 Transfer 객체를 통하여 clipboard를 copy됨을 보면

앞전에 Drag&Drop과 같은 방식임을 알수 있다.

'IT > RCP' 카테고리의 다른 글

[SWT] 윈도우 레지스트리  (0) 2020.12.19
[SWT] Win32 OLE  (0) 2020.12.19
[SWT] Drag & Drop  (0) 2020.12.19
[SWT] 다이얼로그  (0) 2020.12.19
[SWT] Layout  (0) 2020.12.19

    드레그 와 드롭은 일상에서 많이 사용하고 있다. 근데 개발툴에서는 많이 사용하지 않았지만 앞으로 개발툴도 이러한 기능으로 소스코딩양을 줄여주는것이 좋을것 같다.

이기능은 사용하려면 드래그 하는 곳과 드롭하는 곳에 상호작용 및 순서가 필요하다.

    드래그소스->드롭타깃->드롭효과 ->트랜스

먼저 드레그 클래스 계층도를 살펴보자

ㅁ 드레그 소스

     드레그 소스에는 여러가지 형태가 있을수 있다

     가령 text, file, 워드와 같이 특정 문자에 색이나 강조등의 효과를 가지고 있는 RTP 형식 문서등이 있다.

여기서는 해당소스가 명칭을 TextTransfer, FileTransfer,HTML Transfer,RTF Transfer 라 하고 각

instance를 생성 전달하게 된다.

 여기서 간단한 예제로 Label에 소스를 드레그해서 이클립스 java editer에 드롭하면 move되는 소스를 참고 하여보자

package swt.drag_drop;

import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSource;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.DragSourceListener;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;

public class DragSourceTest {
	
	public static void main(String[] args) {
		Display display = new Display();
		Shell shell = new Shell(display);
		shell.setLayout(new FillLayout());
		shell.setText("SWT DragSource Test");

		// 레이블 위젯을 드래그 원본(Drag Source)으로 활성화 한다.
		final Label label = new Label(shell, SWT.BORDER);
		label.setText("text to be transferred");


		int operations = DND.DROP_MOVE | DND.DROP_COPY;
		DragSource source = new DragSource(label, operations);

		// 텍스트 포맷 내에 데이터를 제공한다.
		Transfer[] types = new Transfer[]{TextTransfer.getInstance()};
		source.setTransfer(types);

		source.addDragListener(new DragSourceListener() {
			public void dragStart(DragSourceEvent event) {
				// 레이블 내에 실제 텍스트가 있을 경우에만, 드래그를 시작한다.
				if (label.getText().length() == 0) {
					event.doit = false;
				}
			}

			public void dragSetData(DragSourceEvent event) {
				// 요청된 타입의 데이터를 제공한다.
				if (TextTransfer.getInstance().isSupportedType(event.dataType)) {
					event.data = label.getText();
				}
			}

			public void dragFinished(DragSourceEvent event) {
				// 만약, 데이터의 이동(MOVE) 작업이 수행되었다면,
				// 드래그 원본인 레이블 위젯에서 이동한 데이터를 제거한다.
				if (event.detail == DND.DROP_MOVE) {
					 label.setText("");
				}
			}
		});

		shell.setSize(640, 480);
		shell.open();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
		display.dispose();
	}
}

구현시 처리되는 동영상을 참고하세요

Drag 처리

 

ㅁ 드롭 타겟

   다음은 드롭소스를 예제로 생성해 보았다 반대로 드레그는 이클립스에 자바소스에서 드롭은 개발된 소스에서 받는걸로 예제를 처리했다.

package swt.drag_drop;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.DropTargetAdapter;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.FileTransfer;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.dnd.TransferData;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

public class DropTargetCopyTextFileTest {
	private static void open(Text text, String filename) {
		File file = new File(filename);
		try {
			text.setText("");
			FileReader reader = new FileReader(file);
			BufferedReader in = new BufferedReader(reader);
			String str = null;
			while ((str = in.readLine()) != null) {
				text.append(str + "\n");
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		Display display = new Display();
		Shell shell = new Shell(display);
		shell.setLayout(new FillLayout());
		shell.setText("SWT DropTarget Test");

		final Text text = new Text(shell, SWT.BORDER | SWT.MULTI);
		int operations = DND.DROP_DEFAULT | DND.DROP_COPY | DND.DROP_MOVE;
		DropTarget target = new DropTarget(text, operations);
		target.setTransfer(new Transfer[]{FileTransfer.getInstance(),
				TextTransfer.getInstance()});

		target.addDropListener(new DropTargetAdapter() {
			
			FileTransfer fileTransfer = FileTransfer.getInstance();
			TextTransfer textTransfer = TextTransfer.getInstance();
			public void dragEnter(DropTargetEvent e) {
				System.out.println("[dragEnter] e : " + e);
				TransferData data[] = e.dataTypes;
				for (int i = 0; i < data.length; i++) {
					System.out.println("[dragEnter] data[" + i + "] : "
							+ data[i]);
				}
				if (e.detail == DND.DROP_DEFAULT) {
					e.detail = DND.DROP_COPY;
				}
			}

			public void dragOperationChanged(DropTargetEvent e) {
				if (e.detail == DND.DROP_DEFAULT) {
					e.detail = DND.DROP_COPY;
				}
			}

			public void drop(DropTargetEvent e) {
				System.out.println("[drop] e : " + e);
				if (fileTransfer.isSupportedType(e.currentDataType)) {
					String[] files = (String[]) e.data;
					if (files != null && files.length > 0) {
						open(text, files[0]); // 파일을 연다
					}
				}
				if (textTransfer.isSupportedType(e.currentDataType)) {
					String str = (String) e.data;
					if (str != null) {
						text.setText(str); // 텍스트를 커서 위치에 삽입
					}
				}
			}
		});

//		shell.setLocation(display.getBounds().width - 320,
//				display.getBounds().height - 240);
		shell.setSize(320, 240);
		shell.open();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
		display.dispose();
	}
}

여기도 동영상을 보면 어떻게 구현했는지를 알수 있다.

 

Drop

ㅁ 사용자 포멧 드레그 엔 드롭

  개발하다보면 사용자 포멧에 데이터를 드레그 엔 드롭을 하고 싶을때가 있다

 ▶ MySimpleDragAndDrop에서 화면구성 및 Drag 소스를 MyType으로 Table TableItem 객체로 구성

 ▶ DragSource, DragSource TransferType MyTypeTransfer 인스턴스로 선언

 ▶ addDragListener에서 이벤트가 발생시 event.data MyTyp객체로 넘겨줌

 ▶ DropTarget에서도 TransferType MyTypeTransfer 인스턴스 선언

 ▶ addDropListener에서 이벤트 발생시 evnet.data Mytype변환하여 사용

 ※ MyTypeTransfer는 인스턴스로 ByteArrayTransfer 상속받아 byte로 짤라 전달

 

ㅁ 3가지 소스사용

 MyType.java(사용자Drag&Drop선언), MyTypeTransfer.java(인스턴스), MySimpleDragAndDrop(main)

 MyType.java : 내가 Drag & Drop할 객체

package swt.drag_drop;

public class MyType {
	public String fileName;
	public long fileLength;
	public long lastModified;
}

 MySimpleDragAndDrop.java : 화면구성 및 이벤트 선언 

package swt.drag_drop;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.ByteArrayTransfer;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSource;
import org.eclipse.swt.dnd.DragSourceAdapter;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.DropTargetAdapter;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.dnd.TransferData;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;

public class MySimpleDragAndDrop {

	//시작	
	public static void main(String[] args) {

		//화면구성
		Display display = new Display();
		Shell shell = new Shell(display);
		shell.setLayout(new FillLayout());
		
		//왼쪽에 테이블: LIST는 setData가 없어 TableItem의 setData를 사용함
		final Table tblDrgSrc = new Table(shell, SWT.BORDER | SWT.WRAP | SWT.MULTI);
		
		//아이템1 : abc.txt 파일명에  크기  lastModified라는 속성을 하나의 사용자 객체를 만들어 add
		TableItem item1 = new TableItem(tblDrgSrc,SWT.NONE);
		MyType myType1 = new MyType();
		myType1.fileName = "C:\\abc.txt";
		myType1.fileLength = 1000;
		myType1.lastModified = 12312313;
		item1.setText(myType1.fileName);
		item1.setData(myType1);
		
		//아이템2 : abc.txt 파일명에  크기  lastModified라는 속성을 하나의 사용자 객체를 만들어 add
		TableItem item2 = new TableItem(tblDrgSrc,SWT.NONE);
		MyType myType2 = new MyType();
		myType2.fileName = "C:\\xyz.txt";
		myType2.fileLength = 500;
		myType2.lastModified = 12312323;
		item2.setText(myType2.fileName);
		item2.setData(myType2);
		
		//두번째는 Drop할 객체로 Lable 선언
		final Label label2 = new Label(shell, SWT.BORDER | SWT.WRAP);
		label2.setText("Drop Target for MyData[]");

		//Drag Transfer 선언 : MyTransfer 인스턴스를 넘김선언
		DragSource source = new DragSource(tblDrgSrc, DND.DROP_COPY);
		source.setTransfer(new Transfer[] { MyTypeTransfer.getInstance() });
		
		//Drag 이벤트를 선언 Transfer로는 내가만든 MyTransfer라는 객체로 넘어감
		source.addDragListener(new DragSourceAdapter() {
			public void dragSetData(DragSourceEvent event) {
				
				int arr = tblDrgSrc.getSelectionCount();
				int cnt = 0; 
				MyType[] myType = new MyType[arr];
				//Drag시 내가 만든 객체 myType이란속성에 Object를 event.data로 넘김
				for(TableItem SelItem :tblDrgSrc.getSelection()) {
					myType[cnt] = (MyType)SelItem.getData(); 
					cnt++;
				}
				event.data = myType;
				System.out.println("drageSetData");
			}
		});
		
		//Drop Target 선언 : MyTransfer 인스턴스를 받으려 선언
		DropTarget target = new DropTarget(label2, DND.DROP_COPY | DND.DROP_DEFAULT);
		target.setTransfer(new Transfer[] { MyTypeTransfer.getInstance() });
		
		//Drop 이벤트로 받은경우 Data Object를 받아 MyType으로 변환하여 그중에 이름을 가져옴
		target.addDropListener(new DropTargetAdapter() {
			
			public void dragEnter(DropTargetEvent event) {
				if (event.detail == DND.DROP_DEFAULT) {
					event.detail = DND.DROP_COPY;
				}
			}

			public void dragOperationChanged(DropTargetEvent event) {
				
				if (event.detail == DND.DROP_DEFAULT) {
					event.detail = DND.DROP_COPY;
				}
			}

			public void drop(DropTargetEvent event) {

				if (event.data != null) {
					
					MyType[] myTypes = (MyType[]) event.data;
					if (myTypes != null) {
						String string = "";
						for (int i = 0; i < myTypes.length; i++) {
							string += myTypes[i].fileName + " ";
						}
						label2.setText(string);
					}
				}

			}

		});
		shell.setSize(200, 200);
		shell.open();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
		display.dispose();
	}

		
	static class MyTransfer extends ByteArrayTransfer {

		//인스턴스 객체를 생성하기 위해 Name과 ID가 필요함
		private static final String MYTYPENAME 	= "name_for_my_type";
		private static final int MYTYPEID 		= registerType(MYTYPENAME);
		private static MyTransfer _instance = new MyTransfer();

		public static MyTransfer getInstance() {
			return _instance;
		}

		//Drag소스를 Buffer전환하여 원 소스에 넘김
		public void javaToNative(Object object, TransferData transferData) {
			
			if (!checkMyType(object) || !isSupportedType(transferData)) {
				DND.error(DND.ERROR_INVALID_DATA);
			}
			MyType[] myTypes = (MyType[]) object;
			try {
				// write data to a byte array and then ask super to convert to
				// pMedium
				ByteArrayOutputStream out = new ByteArrayOutputStream();
				DataOutputStream writeOut = new DataOutputStream(out);

				for (int i = 0, length = myTypes.length; i < length; i++) {
					byte[] buffer = myTypes[i].fileName.getBytes();
					writeOut.writeInt(buffer.length);
					writeOut.write(buffer);
					writeOut.writeLong(myTypes[i].fileLength);
					writeOut.writeLong(myTypes[i].lastModified);
				}

				byte[] buffer = out.toByteArray();
				writeOut.close();
				super.javaToNative(buffer, transferData);
			} catch (IOException e) {
			}
		}

		//Drop시 받은것을소스를 Buffer전환하여 원 소스에 넘김
		public Object nativeToJava(TransferData transferData) {
			if (isSupportedType(transferData)) {
				byte[] buffer = (byte[]) super.nativeToJava(transferData);
				if (buffer == null)
					return null;

				MyType[] myData = new MyType[0];
				try {
					ByteArrayInputStream in = new ByteArrayInputStream(buffer);
					DataInputStream readIn 	= new DataInputStream(in);
					
					while (readIn.available() > 20) {
						MyType datum = new MyType();
						int size = readIn.readInt();
						byte[] name = new byte[size];
						readIn.read(name);
						
						datum.fileName = new String(name);
						
						datum.fileLength = readIn.readLong();
						datum.lastModified = readIn.readLong();
						
						MyType[] newMyData = new MyType[myData.length + 1];
						
						System.arraycopy(myData, 0, newMyData, 0, myData.length);
						
						newMyData[myData.length] = datum;
						myData = newMyData;
					}
					readIn.close();
				} catch (IOException ex) {
					return null;
				}
				return myData;
			}

			return null;
		}
		
		
		//기본생성자
		protected String[] getTypeNames() {
			return new String[] { MYTYPENAME };
		}

		//기본생성자
		protected int[] getTypeIds() {
			return new int[] { MYTYPEID };
		}

		boolean checkMyType(Object object) {
			if (object == null || !(object instanceof MyType[]) || ((MyType[]) object).length == 0) {
				return false;
			}
			MyType[] myTypes = (MyType[]) object;
			for (int i = 0; i < myTypes.length; i++) {
				if (myTypes[i] == null || myTypes[i].fileName == null || myTypes[i].fileName.length() == 0) {
					return false;
				}
			}
			return true;
		}

		protected boolean validate(Object object) {
			return checkMyType(object);
		}
	}

}

 MyTypeTransfer.java : 인스턴스 구성

package swt.drag_drop;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

import org.eclipse.swt.dnd.ByteArrayTransfer;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.TransferData;

public class MyTypeTransfer extends ByteArrayTransfer {
	
	//인스턴스 객체를 생성하기 위해 Name과 ID가 필요함
	private static final String MYTYPE_NAME = "my_type_name";
	private static final int MYTYPE_ID 		= registerType(MYTYPE_NAME);
	private static MyTypeTransfer INSTANCE 	= new MyTypeTransfer();

	
	public static MyTypeTransfer getInstance() {
		return INSTANCE;
	}

	//Drag소스를 Buffer전환하여 원 소스에 넘김
	public void javaToNative(Object object, TransferData transferData) {
		
		if (!checkMyType(object) || !isSupportedType(transferData)) {
			DND.error(DND.ERROR_INVALID_DATA);
		}
		
		System.out.println("test1 javaToNative:"+transferData);

		//if (isSupportedType(transferData)) {
			MyType[] myTypes = (MyType[]) object;
			try {
				// write data to a byte array and then ask super to convert to
				// pMedium
				ByteArrayOutputStream bout = new ByteArrayOutputStream();
				DataOutputStream out = new DataOutputStream(bout);
				for (int i = 0, length = myTypes.length; i < length; i++) {
					byte[] buffer = myTypes[i].fileName.getBytes();
					out.writeInt(buffer.length);
					out.write(buffer);
					out.writeLong(myTypes[i].fileLength);
					out.writeLong(myTypes[i].lastModified);
				}
				byte[] buffer = bout.toByteArray();
				out.close();

				super.javaToNative(buffer, transferData);
			} catch (IOException e) {
				e.printStackTrace();
			}
		//}
	}

	//Drop시 받은것을소스를 Buffer전환하여 원 소스에 넘김	
	public Object nativeToJava(TransferData transferData) {
		//System.out.println("test2"+transferData);
		System.out.println("test2 nativeToJava:"+transferData);
		
		if (isSupportedType(transferData)) {

			byte[] buffer = (byte[]) super.nativeToJava(transferData);
			if (buffer == null) {
				return null;
			}

			MyType[] myData = new MyType[0];
			try {
				ByteArrayInputStream bin = new ByteArrayInputStream(buffer);
				DataInputStream in = new DataInputStream(bin);
				while (in.available() > 20) {
					MyType datum = new MyType();

					int size = in.readInt();
					byte[] name = new byte[size];
					in.read(name);
					datum.fileName = new String(name);
					datum.fileLength = in.readLong();
					datum.lastModified = in.readLong();

					MyType[] newMyData = new MyType[myData.length + 1];
					System.arraycopy(myData, 0, newMyData, 0, myData.length);
					newMyData[myData.length] = datum;
					myData = newMyData;
				}
				in.close();
			} catch (IOException e) {
				e.printStackTrace();
				return null;
			}
			return myData;
		}

		return null;
	}

	protected String[] getTypeNames() {
		return new String[]{MYTYPE_NAME};
	}

	protected int[] getTypeIds() {
		return new int[]{MYTYPE_ID};
	}
	
	boolean checkMyType(Object object) {
		if (object == null || !(object instanceof MyType[]) || ((MyType[]) object).length == 0) {
			return false;
		}
		MyType[] myTypes = (MyType[]) object;
		for (int i = 0; i < myTypes.length; i++) {
			if (myTypes[i] == null || myTypes[i].fileName == null || myTypes[i].fileName.length() == 0) {
				return false;
			}
		}
		return true;
	}

	protected boolean validate(Object object) {
		return checkMyType(object);
	}	
}

'IT > RCP' 카테고리의 다른 글

[SWT] Win32 OLE  (0) 2020.12.19
[SWT] 클립보드  (0) 2020.12.19
[SWT] 다이얼로그  (0) 2020.12.19
[SWT] Layout  (0) 2020.12.19
[SWT] 이벤트  (0) 2020.12.19

  대화창은  흔히 쓰는 디렉토리 선택, 파일불러오기,파일저장하기, 색선택등등의 대화창을 말한다.

먼저 계층도를 살펴보자

Dialog의 세부 하위 구성

ㅁ ColorDialog

ColorDialog dialog = new ColorDialog(shell);
RGB color = dialog.open();
if (color != null){
	System.out.println("RGB color"+color.toString());			
}else {
	System.out.println("RGB color null");
}

DirectoryDialog

DirectoryDialog dialog = new DirectoryDialog(shell);
dialog.setMessage("Choose a save directory");
String savetarget= dialog.open();
if (savetarget != null){
	System.out.println("savetarget:"+savetarget);			
}else {
	System.out.println("savetarget null");
}	

File Open

FileDialog dialog = new FileDialog(shell,SWT.OPEN | SWT.MULTI);		//SWT.SAVE, SWT.OPEN,SWT.MULTI 등등 있다
dialog.setFilterExtensions(new String[] {"*.txt;*.doc"});
dialog.open();
String [] savetarget= dialog.getFileNames();
if (savetarget != null){
	System.out.println("OPEN FIle List:"+Arrays.toString(savetarget));			
}else {
	System.out.println("OPEN FIle List null");
}

ㅁ File SAVE

FileDialog dialog = new FileDialog(shell,SWT.SAVE | SWT.MULTI);
//SWT.SAVE, SWT.OPEN,SWT.MULTI 등등 있다
dialog.setFilterExtensions(new String[] {"*.txt;*.doc"});
//dialog.setFilterPath(string);
//dialog.setFileName(string);
dialog.open();
//dialog.getFileName();
String savetarget= dialog.getFileName();;
if (!savetarget.equals("")){
	System.out.println("SAVE FIle    :"+savetarget);			
	System.out.println("getFilterPath:"+dialog.getFilterPath());
	System.out.println("getOverwrite :"+dialog.getOverwrite());
}else {
	System.out.println("SAVE FIle null");
}

FontDialog

FontDialog dialog = new FontDialog(shell);		//SWT.SAVE, SWT.OPEN,SWT.MULTI 등등 있다
dialog.open();

if (dialog != null){
	System.out.println("getEffectsVisible:"+dialog.getEffectsVisible());
	System.out.println("getText :"+dialog.getText());			
	System.out.println("getStyle :"+dialog.getStyle());
	System.out.println("getFontData :"+dialog.getFontData());							
	System.out.println("getFontList :"+Arrays.toString(dialog.getFontList()));
}else {
	System.out.println("FontDialog null");
}

MessageBox

/* 버튼 타입
SWT.OK
SWT.OK | SWT.CANCEL
SWT.YES | SWT.NO
SWT.YES | SWT.NO | SWT.CANCEL
SWT.RETRY | SWT.CANCEL
SWT.ABORT | SWT.RETRY | SWT.IGNORE*/

/*아이콘타입
 SWT.ERROR_ICON
 SWT.ICON_INFOMATION
 SWT.ICON_QUESTION
 SWT.ICON_WARNING
 SWT.ICON_WORKING
 */

MessageBox dialog = new MessageBox(shell,SWT.YES | SWT.NO);
dialog.setMessage("내용부분");
dialog.setText("타이틀");
int returnVal = dialog.open();

System.out.println("returnVal :"+returnVal);	//각상수로 비교하여 사용한다
if (returnVal==SWT.YES) {
	//..
}

참고로 Jface에서는 Message Dialog많이 환경설정과 관련된 Dialog들이 추가로 제공해주고 있다

'IT > RCP' 카테고리의 다른 글

[SWT] 클립보드  (0) 2020.12.19
[SWT] Drag & Drop  (0) 2020.12.19
[SWT] Layout  (0) 2020.12.19
[SWT] 이벤트  (0) 2020.12.19
[SWT] 기본정보(구성,환경,위젯정보)  (0) 2020.12.19

레이아웃에 대해서는 잘되어 있는 사이트 먼저 공유하고자 합니다.

(참고 : https://www.eclipse.org/articles/Article-Understanding-Layouts/Understanding-Layouts.htm) 구글에 SWT layout하면 가장 많이 검색되는 화면입니다

 

 

ㅁ MarginLeft, MarginTop, MarginRight, MarginButton Vertical/Horizontal Spacing

 

그리고 layout은 SWT, JFACE 모두 동일하게 사용되어 집니다. 위젯들을 어떻게 배치하고 화면이 늘려짐에 따라 어떤것들이 늘어나고 고정되는지에 대한 얘기 입니다.

 

1. FillLayout

    FillLayout fillLayout = new FillLayout()

    fillLayout.type        = SWT.VERTICAL

    shell.setLayout(fillLayout)    적용하려는 Composite, Shell 등등에 적용

 

 

2. RowLayout

    RowLayout rowLayout = new RowLayout();

    rowLayout.wrap = false;

    rowLayout.pack = false;

    rowLayout.justify = true;

    rowLayout.marginLeft = 5;

    rowLayout.marginTop = 5;

    rowLayout.marginRight = 5;

    rowLayout.marginBottom = 5;

    rowLayout.spacing = 0;

    shell.setLayout(rowLayout);

    wrap(기본 true) : false한행 유지, 부모가 가시적으로 줄어들 때 안보이는게 발생

    pack(기본 true) : false인경우 본래 size사용

    justify(기본 false) : true인경우 균등하게 배치

 

3. GridLayout

   가장많이 사용되어집니다.

4. GridData

  setLayoutData메소드 사용

  Button button1 = new Button(shell, SWT.PUSH);

  button1.setText("B1");

  button1.setLayoutData(new GridData());

 

 

 

'IT > RCP' 카테고리의 다른 글

[SWT] 클립보드  (0) 2020.12.19
[SWT] Drag & Drop  (0) 2020.12.19
[SWT] 다이얼로그  (0) 2020.12.19
[SWT] 이벤트  (0) 2020.12.19
[SWT] 기본정보(구성,환경,위젯정보)  (0) 2020.12.19

   이벤트라 함은 버튼클릭, 텍스트 내용이 변경된경우 등등의 해당되며, 이와 SWT에서 이벤트

를 알아보고자 합니다.

먼저 이벤트 종류에 대해 알아봅시다.

 

1) 유형이벤트 : key클릭, 마우스 up 등등 특정이벤트
2) 무형이벤트 : 특정을 지칭하지 않은 이벤트들
3) 어뎁터 : 이벤트를 전부 구현하지 않고 필요한것만 구현토록 구조화
4) 이벤트를 받아 리스너에서 보통은 처리하는 메서드 구현 즉 연결관계에 있다 

참고로 자바 이벤트와 비슷하다.

1.1 이벤트 유형 리스너와 리스너 메소드

 

1.2 이벤트의 구현

이벤트 리스너의 구현방식 두가지 : 익명구현, 외부클래스

1) 익명구현방식 : 장)소스가 즉흥적 가능, 단)재활용이 안됨

helloBtn.addMouseListener(new MouseListener() {  //==>익명구현   
   @Override
   public void mouseUp(org.eclipse.swt.events.MouseEvent arg0) {
    // TODO Auto-generated method stub
    System.out.println("마우스 업");
    
   }
   
   @Override
   public void mouseDown(org.eclipse.swt.events.MouseEvent arg0) {
    // TODO Auto-generated method stub
    System.out.println("마우스 다운");
   }
   
   @Override
   public void mouseDoubleClick(org.eclipse.swt.events.MouseEvent arg0) {
    // TODO Auto-generated method stub
    System.out.println("마우스 더블클릭");
   }
  });

2) 외부클래스 구현방식 : 장)재활용가능

   
   MouseListener ExMouseListener = new MouseListener() {  //==>외부클래스구현
   @Override
   public void mouseDoubleClick(MouseEvent arg0) {
    // TODO Auto-generated method stub
    System.out.println("마우스 더블클릭");
   }
   @Override
   public void mouseDown(MouseEvent arg0) {
    // TODO Auto-generated method stub
    System.out.println("마우스 다운");
   }
   @Override
   public void mouseUp(MouseEvent arg0) {
    // TODO Auto-generated method stub
    System.out.println("마우스 업");
   }
   
  };

helloBtn.addMouseListener(ExMouseListener); //외부클래스 사용

1.3 어뎁터

 앞 이벤트에서는 특이한 것은 내부 메소드가 모두 @Override된 것을 알수 있다. 구현하지 않아도 선언되지 않으면 안되는 반면 어뎁터는 구현하고 싶은 것들만 구현하도록 되어 있다

즉 익명의 인터페이스를 사용하지 않고 또한 모든메소드를 구현하지 않기 위해 어댑터라 부르는 특별한 클래스로 사용하여 구현 :: 내부 메소드를 필요한것만 사용가능

1) 익명구현

helloBtn.addMouseListener(new MouseAdapter() {  //==>익명구현
  
   public void mouseDown(org.eclipse.swt.events.MouseEvent arg0) {
    // TODO Auto-generated method stub
    System.out.println("마우스 다운");
   }
 });

2) 외부클래스 구현

MouseListener ExMouseListener = new MouseAdapter() {  //==>외부클래스구현
   
   public void mouseDown(MouseEvent arg0) {
    // TODO Auto-generated method stub
    System.out.println("마우스 다운");
   }
   public void mouseUp(MouseEvent arg0) {
    // TODO Auto-generated method stub
    System.out.println("마우스 업");
   }   
  };

helloBtn.addMouseListener(ExMouseListener) ; //외부클래스 사용

1.4 어뎁터  종류

 

※ 참고 사항 Event에서 keyCode(KeyListne/KeyAdapter에서 사용)

 

1.5 무형이벤트

   특정이벤트가 아니라 모든 이벤트처리 대표로처리할수 있는 Listener 클래스이다

    ▶ JFaceTestMain.java작성

import org.eclipse.jface.window.ApplicationWindow;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
 
public class JFaceTestMain extends ApplicationWindow {
  
 public JFaceTestMain() {
  super(null);
  // TODO Auto-generated constructor stub
 }
 protected Control createContents(Composite parent) {
  System.out.println("test main createContents");
  new IntangibleEventTest(parent);
  parent.pack();
  return parent;
 }
 
 public static void main(String[] args) {
  JFaceTestMain obj = new JFaceTestMain();
  obj.setBlockOnOpen(true);
  obj.open();
   
  Display.getCurrent().dispose();
 }
}

 IntangibleEventTest.java작성

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
 
public class IntangibleEventTest extends Composite{
 
 Label output;
  
 public IntangibleEventTest(Composite parent) {
   
  super(parent, SWT.NULL);
  System.out.println("test IntangibleEventTest");
  Button typed = new Button(this,SWT.PUSH);
  typed.setText("Typed");
  typed.setLocation(2,10);
  typed.pack();
   
  typed.addKeyListener(new KeyAdapter() {
   public void keyPressed(KeyEvent e) {
    keyHandler();
   }
 
 
  });
   
  Button untyped = new Button(this,SWT.PUSH);
  untyped.setText("UnTyped");
  untyped.setLocation(80,10);
  untyped.pack();
  untyped.addListener(SWT.MouseEnter, UntypedListener);
  untyped.addListener(SWT.MouseExit, UntypedListener);
   
  output = new Label(this,SWT.SHADOW_OUT);
  output.setBounds(40,70,90,40);
  output.setText("No Event");
   
  pack();
   
 }
  
 Listener UntypedListener = new Listener(){
 
  @Override
  public void handleEvent(Event event) {
   System.out.println("handleEvent:"+event.widget.getClass().getSimpleName() );
   switch(event.type) {
    
   case SWT.MouseEnter:
    output.setText("Mouse Enter");
    break;
   case SWT.MouseExit:
    output.setText("Mouse Exit");
    break;
   }
    
  }
   
 };
 
 void keyHandler() {
  // TODO Auto-generated method stub
  output.setText("Key Event");
 }
}

'IT > RCP' 카테고리의 다른 글

[SWT] 클립보드  (0) 2020.12.19
[SWT] Drag & Drop  (0) 2020.12.19
[SWT] 다이얼로그  (0) 2020.12.19
[SWT] Layout  (0) 2020.12.19
[SWT] 기본정보(구성,환경,위젯정보)  (0) 2020.12.19

위젯 툴킷(Standard Widget Toolkit)으로 이클립스에서 사용하고 있는 자바기반의 위젯 툴킷(Widget Toolkit)

우리가 사용하는 이클립스에 ViewPart,EditorPart등 도구를 만들기 위한 기초입니다.

 

ㅁ 구성

    

   Display객체, Shell객체 그리고 그 하위에 위젯에 개념이 들어간다

   OS swt.jar에 따라 여러가지 운영체계 프로그램을 만들 수 있다

   위젯은 기본이다

 

ㅁ 환경설정

    Java 프로젝트 생성 

   

해당 프로젝트에 swt.jar만 있으면 된다.

ㅁ 참고사이트

    http://www.eclipse.org/swt/

    각종 위젯등에 대한 예시 가 소스하고 함께 잘되어 있음

 

ㅁ Widget의 구성요소

ㅁ 각 위젯에 요소

    위젯은 좀 프로그램을 해본 경험이 있는사람의 경우 쉽게 알수 있기 때문에 많은 설명을 하지않고 단지 기능 요약을 해보겠습니다.

 1) Control 메소드

Control메소드

기능

getSize()

위젯크기를 표시하는 Point 객체반환

setSize(int,int)

너비와 길이 값 설정

setSize(Point)

Point 객체에 따라 위젯크기 설정

computeSize()

위젯 내용을 모두 보여줄수 있는 면적을 반환

computeSize(int,int,boolean)

위젯내용을 모두 보여줄수 있는 면적을 반환하고, 위젯 특성이 바뀌었는지 알려줌

pack()

위젯을 선호하는 크기로 재조정한다

pack(boolean)

위젯을 선호하는 크기로 재조정하고, 특성이 바뀌었는지 알려줌

getLocation()

위젯의 부모에 대한 상대위치

setLocation(int,int)

위젯의 부모에 대한 상대위치 설정

getBounds()

위젯의 크기와 부모에 대한 상대 위치를 반환한다

setBounds(int,int,int,int)

위젯의 크기와 부모에 대한 상대위치 설정

toControl(int,int)

화면 기준 좌표를 컨트롤 기준 Point 값으로 바꾼다

toControl(Point)

화면 기준 Point값을 컨트롤을 기준 Point 값으로 바꾼다

toDisplay(int,int)

컨트롤 기준좌표를 컨트롤 기준 Point 값으로 바꾼다

toDisplay(Point)

컨트롤 기준 Point 값을 Point 값으로 바꾼다

※ setSize() 보다 pack() 컨테이너 크기를 알아서 조절

 

2) Label 메소드

     위치        : SWT.LEFT, SWT.RIGHT, SWT.CENTER,

     구분선     : SWT.SPARATOR

     수직/수평 : SWT.VERTICAL, SWT.HORIZONTAL

     그림자     : SWT.SHADOW_IN, SWT.SHADOW_OUT, SWT.SHADOW_NONE

     ==>SWT에는 열거형 정수형으로 많은 타입을 가지고 있다

Label메소드

기능

getText()

 Label 텍스트 읽기

setText(String)

 Label텍스트 쓰기

getAlignment()

 정렬가져오기

setAlignment(int)

 정렬 setting

getImage()

 이미지 set

setImage(Image)

이미지 get

 

3) Button

     SWT.PUSH,

     SWT.ARROW | SWT.RIGHT

     SWT.TOGGLE

     SWT.CHECK, SWT.RADIO

 

4) Composite

     각Control을 집합으로 구성가능하다

4.1) Composite 기본

Composite 메소드

기능

getChiendren()

Control 객체의 배열을 반환한다

getLayout()

Composite에 연결한 레이아웃을 반환한다

setLayout(Layout)

Composite에 연결한 레이아웃을 설정한다

getTabList()

탭 순서에 따른 Control 객체의 배열을 반환한다

setTabList(Control[])

Composite의 위젯의 탭 순서를 설정한다

 

4.2) Composite의 하위클래스로 Scrollable 속성을 추가 사용         

Scrollable 메소드

기능

getClientArea()

Scrollable 객체에 가능한 화면 표시 면적을 반환한다.

computeTrim(int,int,int,int)

기대하는 클라이언트 영역을 위한 Composite의 필요 면적을 반환한다

getHorizontalBar()

수평 ScrollBar 객체를 반환한다

getVerticalBar()

수직 ScrollBar 객체를 반환한다

 

5)  Group

  그림자 속성과 함께 추가적으로 식각(etching)을 표시한다.

  SWT.SHADOW_ETCHEND_IN SHADOW_ETCHEND_OUT

6) SashForm

7) TabFolder

    getItemCount : TabFolder  TabItem 수반환

    getItems() : TabItem 객체의 배열을 반환

    getSelection() : 사용자가 어떤 TabItem을 선택했는지

    setSelection(): 선택될 탭을 설정

 7) LIst

 8) Combo

   style : SWT.SIMPLE, SWT.DROP_DOWN, SWT.READ_ONLY

 9) Tree

    ▶ 트리에서 사용하는 메소드 : Scrollable의 확장기능임.

메소드

기능

addSelectionListener()

선택 이벤트의 통지

addTreeListener()

TreeListener 인터페이스는 +확장  축소 할 때

select()/deselect()

현재 선택/ 제외

getSelection()

현재 선택항목

 show()

 주어진 항목을 보일때까지 스크롤

  Style로는 SWT.SINGLE, SWT.MULT

 TreeItem 메소드

메소드

기능

getItem()

 Tree 하위를 각각 TreeItem이라하면 불러오기

getChecked()

체크

setExpanded(boolean)

 확장

 

예제) Widdget Window에서 Tab을 만들고 그안에 두개 Composite가 구성된 Composite를 추가

Composite에는 Group Composite, SashForm Composite구성해보았다

 

 

'IT > RCP' 카테고리의 다른 글

[SWT] 클립보드  (0) 2020.12.19
[SWT] Drag & Drop  (0) 2020.12.19
[SWT] 다이얼로그  (0) 2020.12.19
[SWT] Layout  (0) 2020.12.19
[SWT] 이벤트  (0) 2020.12.19

문제는 방화벽을 설정해서 도커내 컨테이너에서 외부 접속이 안되는 현상

제어판 ->보안->방화벽

기존에 192.168.0.1~192.168.0.255 ip외 접속허용 외로 하다 보니 도커가 172.17.0.1 영역을 사용해서 문제였음

허용으로 변경하고 가능함

'IT > 서버' 카테고리의 다른 글

Docker 명령어 정리  (0) 2020.11.21
리눅스 추가 설치 및 명령어, 주요경로  (0) 2020.11.16

원문 : coding-factory.tistory.com/71

 

[Jsp] MVC 패턴 게시판

저번 포스팅 MVC2 패턴으로 만드는 회원가입 및 로그인에 이어서 이번에는 MVC2 패턴으로 만드는 게시판을 공부해보겠습니다. 회원가입 , 로그인 기능과 마찬가지로 게시판도 어느 웹사이트에서

coding-factory.tistory.com

위 원문을 보고 Mysql로 한번 작성해보았고 나름대로 MVC 패턴을 정리하고자 함

 

ㅁ 테이블 생성

--테이블 생성
CREATE TABLE work.BOARD
(
BOARD_NUM		int(10)	 NOT NULL
,BOARD_NAME		varchar(20)	 NULL
,BOARD_PASS		varchar(15)	 NULL
,BOARD_SUBJECT		varchar(50)	 NOT NULL
,BOARD_CONTENT		text(65535)	 NULL
,BOARD_FILE		varchar(50)	 NULL
,BOARD_RE_REF		int(10)	 NULL
,BOARD_RE_LEV		int(10)	 NULL
,BOARD_RE_SEQ		int(10)	 NULL
,BOARD_READCOUNT		int(10)	 NULL
,BOARD_DATE		date	 NOT NULL
);

--PK설정
alter table work.BOARD add primary key(BOARD_NUM);

--테이블 설명
ALTER TABLE work.BOARD COMMENT = 'MVC게시판'; 

--컬럼 comment
ALTER TABLE work.BOARD MODIFY BOARD_NUM	 int(10)	 COMMENT '일련번호' 	 NOT NULL;
ALTER TABLE work.BOARD MODIFY BOARD_NAME	 varchar(20)	 COMMENT '작성자' 	 NULL;
ALTER TABLE work.BOARD MODIFY BOARD_PASS	 varchar(15)	 COMMENT '패스워드' 	 NULL;
ALTER TABLE work.BOARD MODIFY BOARD_SUBJECT	 varchar(50)	 COMMENT '제목' 	 NOT NULL;
ALTER TABLE work.BOARD MODIFY BOARD_CONTENT	 text(65535)	 COMMENT '내용' 	 NULL;
ALTER TABLE work.BOARD MODIFY BOARD_FILE	 varchar(50)	 COMMENT '파일명' 	 NULL;
ALTER TABLE work.BOARD MODIFY BOARD_RE_REF	 int(10)	 COMMENT '원문일련번호' 	 NULL;
ALTER TABLE work.BOARD MODIFY BOARD_RE_LEV	 int(10)	 COMMENT '레벨' 	 NULL;
ALTER TABLE work.BOARD MODIFY BOARD_RE_SEQ	 int(10)	 COMMENT '순서' 	 NULL;
ALTER TABLE work.BOARD MODIFY BOARD_READCOUNT	 int(10)	 COMMENT '조회건수' 	 NULL;
ALTER TABLE work.BOARD MODIFY BOARD_DATE	 date	 COMMENT '작성일자' 	 NOT NULL;

 

ㅁ DB연동하기 -JNDI,DBCP(커넥션풀) 이용 

더보기

▶ JNDI(Java Naming and Diectory Interface)  

    디렉토릭 서비스에서 제공하는 데이터 및 객체를 발견하고 참고(lookup)하기 위한 자바 API

DBCP(DataBase Connection Pool, 커넥션 풀)

    데이터베이스와 연결된 커넥션을 미리 만들어 저장하고 필요할때 저장된 공간에서 가져다 쓰는 기법

 ※ 사전작업

    WebContent\WEB-INF\lib에  해당 드라이버 mysql-connector-java-5.1.28-bin.jar 넣음

    tomcat-dbcp.jar 

 

 1) context.xml과 web.xml을 이용한 연결

  1-1) DBCP 정보설정

          context.xml 파일에 Context 태그 아래 Resource를 추가

 <Context> 
   <Resource 
	maxWait="-1" 
	maxIdle="10" 
	maxActive="20" 
	username="[아이디]" 
	password="[패스워드]" 
	url="jdbc:mysql://[ip]:3307/work" 
	type="javax.sql.DataSource" 
	driverClassName="com.mysql.jdbc.Driver" 
	auth="Container" 
	name="jdbc/MyBoard1"/> 
<!--
    auth : 컨테이너를 자원 관리자로 기술
    name : JDBC이름, 변경 가능
    driverClassName : JDBC 드라이버
    type : 웹에서 이 리소스를 사용할 때 DataSource로 리턴됨
    username : 접속계정
    password : 접속할 계정 비밀번호
    
    loginTimeout : 연결 끊어지는 시간
    maxActive : 최대 연결 가능한 Connection수 (기본 20개)
    maxIdle : Connection pool 유지를 위해 최대 대기 connection 숫자
    maxWait : 사용 가능한 커넥션이 없을 때 커넥션 회수를 기다리는 시간 (1000 = 1초)
    testOnBorrow : db에 test를 해볼 것인지
-->
    
 </Context>

    1-2) JNDI 리소스 사용설정

          WebContent\WEB-INF\에 web.xml 추가

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee                       http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> 	
	
	<servlet>
		<servlet-name>BoardController</servlet-name>
		<servlet-class>
		com.board.dicws.action.BoardController</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>BoardController</servlet-name>
		<url-pattern>*.bo</url-pattern>
	</servlet-mapping>

	<display-name>
	MyBoard1</display-name>
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
		<welcome-file>index.htm</welcome-file>
		<welcome-file>index.jsp</welcome-file>
		<welcome-file>default.html</welcome-file>
		<welcome-file>default.htm</welcome-file>
		<welcome-file>default.jsp</welcome-file>
	</welcome-file-list>
	
	<resource-ref>
		<description>Connection</description>
		<res-ref-name>jdbc/MyBoard1</res-ref-name>
		<res-type>javax.sql.DataSource</res-type>
		<res-auth>Container</res-auth>
	</resource-ref>
</web-app>

   ▶ JSP 연결테스트

   WebContent\test.jsp 만들고 실행 

<%@ page import="javax.naming.*, javax.sql.*, java.sql.*"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%
		Connection con = null;
		PreparedStatement stmt = null;

		Context initCtx = new InitialContext();
		Context envCtx = (Context) initCtx.lookup("java:comp/env");
		//resource명과 res-ref-name과 일치하는 이름
		DataSource ds = (DataSource) envCtx.lookup("jdbc/MyBoard1");
		con = ds.getConnection();

		String msg = "disconnection";

		if (con != null) {

			msg = "connection";

		}
%>		
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>
	Results =
	<%=msg%></h2>

</body>
</html>

   ▶ 자바사용

package com.board.dicws.lib;

import java.sql.Connection;
import java.sql.SQLException;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

public class DBConnection {
	
	public static Connection getConnection() throws SQLException, NamingException, ClassNotFoundException {
		Context initCtx = new InitialContext();

		// initCtx의 lookup메서드를 이용해서 "java:comp/env" 에 해당하는 객체를 찾아서 evnCtx에 삽입
		Context envCtx = (Context) initCtx.lookup("java:comp/env");

		// envCtx의 lookup메서드를 이용해서 "jdbc/MyBoard1"에 해당하는 객체를 찾아서 ds에 삽입
		DataSource ds = (DataSource) envCtx.lookup("jdbc/MyBoard1");

		// getConnection메서드를 이용해서 커넥션 풀로 부터 커넥션 객체를 얻어내어 conn변수에 저장
		Connection conn = ds.getConnection();
		return conn;

		/*
		 * 위의 코드를 아래와 같이 줄여서 작성 가능하다. Context context = new InitialContext(); DataSource
		 * dataSource = (DataSource) context.lookup("java:comp/env/jdbc/oracle");
		 * Connection con = dataSource.getConnection();
		 * 
		 */
	}
}

 2) server.xml과 context.xml을 이용한 연결

    1-1) DBCP 정보설정

          server.xml 편집 : GlobalNamingResources 테그에 Resource 추가

  <GlobalNamingResources>
    <!-- Editable user database that can also be used by
         UserDatabaseRealm to authenticate users
    -->
    <Resource auth="Container" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase" pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase"/>
   <Resource 
	maxWait="-1" 
	maxIdle="10" 
	maxActive="20" 
	username="[아이디]" 
	password="[패스워드]" 
	url="jdbc:mysql://[ip]:3307/work" 
	type="javax.sql.DataSource" 
	driverClassName="com.mysql.jdbc.Driver" 
	auth="Container" 
	name="jdbc/MyBoard1"/> 
<!--
    auth : 컨테이너를 자원 관리자로 기술
    name : JDBC이름, 변경 가능
    driverClassName : JDBC 드라이버
    type : 웹에서 이 리소스를 사용할 때 DataSource로 리턴됨
    username : 접속계정
    password : 접속할 계정 비밀번호
    
    loginTimeout : 연결 끊어지는 시간
    maxActive : 최대 연결 가능한 Connection수 (기본 20개)
    maxIdle : Connection pool 유지를 위해 최대 대기 connection 숫자
    maxWait : 사용 가능한 커넥션이 없을 때 커넥션 회수를 기다리는 시간 (1000 = 1초)
    testOnBorrow : db에 test를 해볼 것인지
-->

  </GlobalNamingResources>

   context.xml 편집 

 

 <Context> 
    <ResourceLink global="jdbc/MyBoard1" name="jdbc/MyBoard1" type="javax.sql.DataSource"/>
 </Context>

 

'IT > 기타 프로그램' 카테고리의 다른 글

[Tomcat] 구조 및 개념정리  (0) 2020.12.13
[Tomcat] 설치 및 환경설정  (0) 2020.12.13

ㅁ webapps의 구조

webapps의 구조

ㅁ 생명주기

ㅁ 서블릿 메소드 관련 

    서블릿은 HttpServlet을 상속받아 주로 service(request,response)로 사용

    호출방식에 따라 get/post로 나누어 질때 doPost와 doGet 메소드를 사용함

     

    service 메소드 사용 또는 doGet, doPost 메소드를 오버라이딩 해서 사용

 

JSP 주요 액션태그

   (1)useBean

   (2)setProperty

   (3)getProperty

 

※ Bean 와 서블릿의 차이

   공통점 : 서버에서 작성, 실행되는 자바"클래스"

   차이점 : 서블릿은 외부와 소통 가능, 자바 빈은 불가능 (=일반 자바)

   서블릿은 HTTPServlet을 상속받음, 자바빈은 상속받지 않음

   서블릿은 패키지 안써도됨, 자바빈은 써야함

 

 

'IT > 기타 프로그램' 카테고리의 다른 글

[Tomcat] MVC게시판 만들기  (0) 2020.12.14
[Tomcat] 설치 및 환경설정  (0) 2020.12.13

ㅁ 이클립스 환경설정 : UTF-8기준 변경

      Windows -> Preferences ->General - Workspace

        ==> Text file encoding에서 Other를 선택하고 UTF-8로 변경한다

 

                                         Web - CSS Files

        ==> Encoding을 ISO 10646/Unicode(UTF-8)로 변경한다.

     ※ Web - HTML Files, JSP Files도 동일하게 변경한다

   Windows - Preferences를 클릭한다.

 

ㅁ apache tomcat 다운로드

      다운로드 사이트 : tomcat.apache.org/download-90.cgi

 

Apache Tomcat® - Apache Tomcat 9 Software Downloads

Welcome to the Apache Tomcat® 9.x software download page. This page provides download links for obtaining the latest version of Tomcat 9.0.x software, as well as links to the archives of older releases. Unsure which version you need? Specification version

tomcat.apache.org

인스톨로 말고 압축파일로 해당 bit맞게 받고 압축을 푼다

   환경설정->Server->Runtime Enviroments 에서 add->Apache Tomcat v9.0 선택

아파치 버전선택
압축경로 선택후 완료

 

※  http://localhost:8080 접속시 404 에러

    문제는 Tomcat 설치위치에 webapps가 없어서 나는 에러였음

    해결방법은 webapps.dist에 내용을 모두 webapps로 옮겨놓고 재시작하니 정상

    리눅스 서버에서는 curl 을 이용하여

    $curl http://localhost:8080 으로 test

 

ㅁ Tomcat GUI 사용자 변경

    tomcat-users.xml 변경

 

    다음내용이 주석으로되어 있음

    <role rolename="tomcat"/>

    <role rolename="role1"/>

    <user username="tomcat" password="tomcat" roles="tomcat"/>

    <user username="both" password="tomcat" roles="tomcat,role1"/>

    <user username="role1" password="tomcat" roles="role1"/>

 

    다음을 추가해준다.

 

  <role rolename="manager-gui"/>

  <user username="[사용자명]" password="[패스워드]" roles="manager-gui"/>

 

ㅁmanager에  context.xml 수정

     경로: /설치경로/webapps/manager/META-INF/context.xml

     원격허용가능토록수정(위 룰을 해놓았어도 context.xml이 수정되지 않으면 접속불가)

 

변경전)
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
         allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" />
변경후1) 외부접속 전체허용         
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
         allow=".*" />
변경후2) 외부접속 내부ip허용
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
         allow="192\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" />

ㅁ log4j 추가 

    biz로그를 별도 처리 

    1) maven 으로 모듈 추가  

<dependency>
	<groupId>log4j</groupId>
	<artifactId>log4j</artifactId>
	<version>1.2.17</version>
</dependency>

    2) log4j.properties 생성

  ※ src 경로에  log4j.properties 파일생성, War파일생성시 webapp/패키지/WEB_INF/classes/에 log4j.properties 생김

# Root logger option

log4j.rootLogger=debug, stdout, logfile
#log4j.rootLogger=info, stdout, logfile

# Direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p (%C{2}:%L) - %m%n

# Direct log message to log file
log4j.appender.logfile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.logfile.DatePattern='.'yyyy-MM-dd
log4j.appender.logfile.File=E:\\Log/application.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss}] %5p (%C{2} - %M:%L) - %m%n
log4j.appender.logfile.Append=true

'IT > 기타 프로그램' 카테고리의 다른 글

[Tomcat] MVC게시판 만들기  (0) 2020.12.14
[Tomcat] 구조 및 개념정리  (0) 2020.12.13

ㅁ Java 환경설정 두가지

    1) eclipse.ini 파일에  맨위 JDK 경로 지정

-vm
C:/Program Files/Java/jdk-11.0.1/bin  
※ 버전 및 경로 맞게 설정 

    2) 환경변수 설정

 

부가설치 및 설정

 - jad : Java class 파일을 역컴파일해서 원문소스를 보여주는 기능

        간단 사용법

 - javaCC : 이놈이 좀 특이한데 컴파일러를 만드는것으로 역공학도구로 많이 사용되어 진다.

 - svn : 특정서버에 소스 버전관리

 - javaDocument 설정

 

  ▶ Jad

    1) Java에 컴파일된 모듈을 반대로 소스로 만드는 것

      jad.exe 다운: http://varaneckas.com/jad/     특정경로 저장 

    2) Jad 플러그인설치

      다운로드 :  http://sourceforge.net/projects/jadclipse/  다운

               net.sf.jadclipse_3.3.0.jar 파일을  이클립스에 plugins폴더에 복사해 넣으면 설치완료 환경설정에 JadClipse 

               메뉴가 보이고 설정을 하고 .class파일을 Jad로 연결

       

  설정1) Jad 설정

Jad 실행파일 등록 및 Decompile시 경로 설정
Decompile 대상 연결 설정

          참고로 모든 확장자에 대한 파일연결 기본설정은 해당 화면에서 처리한다.

 

   JavaCC

     역공학으로 소스분석을 하기위해 사용, 관계없으면 해당설치는 생략한다. 코볼역공학을 한번 활용해봤으나, 다른모듈에 대한 역공학도 가능하다.

   다운로드 : https://sourceforge.net/projects/eclipse-javacc/

   다운파일 : sf.eclipse.javacc-1.5.33-plugin.zip 압축을 풀고 하위에 features, plugins 폴더를

   이클립스에 features, plugins폴더에 복사해 넣으면 설치완료

 

  ▶ SVN설치

     Help  -> Eclipse Marketplace 실행

   검색어에 SVN 입력 검색하고 설치

   ※ 참고로 Marketplace는 이클립스에 플러그인을 어플깔듯 깔수있게 패키지로 되어 있는

      사이트이다.

 

   ▶JavaDocument 설정 

    Java라이브러리에 대한 설명들을 개발시 보여주어 효율적으로 개발할수 있다.

Java Document 설정 확인
Java Document(참고 로칼로 받고 경로 선택도 가능)

 

ㅁ 환경정보 저장/복원 방법

1. File > Export > General > Preference Next.

2. To preference file. 저장경로설정


1. File > Import > General > Preferences Next.

2. From preference file. 파일가져오기

※ 몇개는 해당 메뉴에서 개별로

ㅁ ObjectAid

    클래스 다이어그램를 보는 좋은 툴인데 아쉽게도 이클립스 2018-12-R버전이후 사용할수 없다

    

   ==>   objectaid-1.1.14.zip 파일을 구해서 이클립스 install에 아카이브로 설치 사용

 

    

 

'IT > 개발툴설치' 카테고리의 다른 글

MobaXterm 원격데스크톱 ssh 등등사용  (0) 2021.12.20
Oracle ODBC 설치  (0) 2021.02.28
[SWT] SWT만 설치사용(구방식)  (0) 2020.12.20
[이클립스] WindowBuilder 설치  (0) 2020.11.08
Maven 설치 및 기본사용법  (0) 2020.11.08

VB 참고 사이트

- 기본적인 문법이 잘되어 있음

https://docs.microsoft.com/ko-kr/dotnet/visual-basic/language-reference/

 

엑셀에서 다른 특이한거 하나는 행동을 코딩으로 나오는 매크로라 생각되어 진다.

행동을 기록하여 코딩으로 나온 소스를 보고 이해하고 이용하는것

엑셀도 하나의 좋은 DataBase 이다 .

엑셀파일을 DataBase 에 스키마와 동급이다

엑셀시트는 각각에 해당 테이블과 동급이다

그렇다면 엑셀시트를 query를 사용하여 쓸수 있을까? 쓸수 있다

사이트에서 일하다보면 엑셀로 무수히 많은 엑셀자료를 만들기는 하는데 이걸 참조해서 개발하는 개발자는 너무많은 자료에 치여사는경우가 많다 그래서 생각한것이 하나의 만들어놓은 엑셀에서 관련되어 있는 엑셀을 query를 실행하여 조회하는 메크로를 작성해보았다

전에 Database를 사용하기 위해서는 ODBC드라이버가 있어야된다고 했는데 ODBC드라이버를 확인해보자

 

1) ODBC설치 확인(기본으로 OFFICE를 설치하면 설치된는것을 알수 있다)

2) 참조에 Microsoft ActiveX DataObject 2.8 Library를 추가 : ADODB 객체를 사용하려구 

3) 일단 엑셀을 sql로 조회하기 위한 엑셀을 하나 준비한다

 

 

4) 엑셀을 DataBase처럼 Connection을 실행해서 잘 연결되는지 확인해보자

    특이하게 Provider를 사용하여 쓰고 뒤에 Properties가 더 붙는다

Public dbcon As ADODB.Connection

Public dbcon As ADODB.Connection 

Public Sub ExcelCon()    '=>실행시 문제가 없는지 확인

    Dim strCon  As String '연결String
    Dim driver, dsrc
   
    dsrc = "D:\엑셀DB테스트.xlsx"    '파일명
    
    '엑셀파일을 DataBase처럼 연결
    strCon = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & dsrc & ";Extended Properties=Excel 12.0;"
    Set dbcon = New ADODB.Connection
   
    dbcon.Open strCon      '연결

End Sub

 

5) 연결이 잘되었으면 RecordSet으로 받아 엑셀에 출력을 해보자

Public Sub getExcelEtcSel()

    Dim rs, sql, colCnt, wRow, i
   
    ExcelCon     
    sql = "select * from [Sheet2$] "  '->조건없이 전부 조회
    Debug.Print sql
   
    'Set rs = CreateObject("ADODB.RecordSet")
    Set rs = New ADODB.Recordset
   
    rs.Open sql, dbcon
   
    wRow = ActiveSheet.Range("B4")  '작성시작 row
    colCnt = rs.Fields.Count
    '컬럼에 head를 시작에 달아줌
      For i = 0 To colCnt - 1
          ActiveSheet.Cells(wRow, i + 1) = rs.Fields(i).Name
      Next
      setHeaderStyle wRow     'header 스타일 적용
      wRow = wRow + 1
   
    If rs.EOF = False Then
   

        Do While rs.EOF = False
       
            For i = 0 To colCnt - 1
                ActiveSheet.Cells(wRow, i + 1) = rs(rs.Fields(i).Name)    '레코드셋에 이름으로 매핑하여 표시
            Next
           
            wRow = wRow + 1
            rs.MoveNext
        Loop
    End If

End Sub

 

6) 엑셀에 특정영역중에 query를 사용할경우와 컬럼명을 기술할때 일반 query와 상이함

 sql = "select [컬럼1],[컬럼2] from [Sheet2$A2:G5] "

- 시트전체조회시 [시트명$]

- 시트에일부영역시 [Sheet2$A2:G5] -> sheet2에 A2:G5 영역중 조회

- 컬럼은 위처럼 중괄호를 해야되고 중복된 컬럼명이 있으면 임의로 넘버링을 붙임

 

중복컬럼이 있는경우

조회결과

 

엑셀에서 중요한 기능중 하나가 파일을 READ 하고 WRITE하고 이긴 한데

단독적으로 쓸일은 많지는 않았다 그보다 현재 많은 정보들이 있다보니 각종 소스들에 대해서 목록으로 처리해야될일이 많아졌다 생각 되어진다.

프로젝트에서 말하자면 현황파악

제일먼저 특정경로에 소스를 가져왔을때 해당 소스하위까지 포함하여 폴더에 목록을 엑셀로 작성해보자

 

1) 엑셀시트 화면 구성 

   B1에는 검색하려는 기본경로 기입

   B2에는 기존 목록을 삭제하고 다시 작성할건지 여부

   B3에는 전체작성된 건수를 엑셀함수를 써서 기입 =COUNT(A9:A1048576)

 

2) 소스작성

   먼저 파일을 사용하기 위해 참조를 하자

   직접 CreationObject를 사용하여도 되지만 ctrl+space로 자동완성기능을 사용하기 위하여

   참조를 통하여 객체를 넣는 작업을 한다

 

 

 

다음은 엑셀 코딩을 하자

Option Explicit   '명시적으로 항상 어떤변수를 사용했는지 확인하는게 신상에좋다

Dim wRow        '파일을 엑셀시트에 저장하기 위해 선언==> 말하자면 전역변수선언

Public Sub getFileList()   '==>실행하는 함수
    Dim rc
   
    wRow = 9        '기본은 9부터
    If ActiveSheet.Range("B2") = "Y" Then    '삭제여부를 보고 삭제작업
        rc = MsgBox("삭제해도 될까요?", vbYesNo, "삭제경고")
        If rc = vbYes Then
            Rows(wRow & ":" & wRow).Select
            Range(Selection, Selection.End(xlDown)).Select
            Range(Selection, Selection.End(xlDown)).Select
            Selection.Delete Shift:=xlUp
        Else
            Exit Sub
        End If

        '타이틀을 작성한다
        ActiveSheet.Cells(wRow, 1) = "NO"
        ActiveSheet.Cells(wRow, 2) = "파일명"
        ActiveSheet.Cells(wRow, 3) = "경로"
        ActiveSheet.Cells(wRow, 4) = "타입"
        ActiveSheet.Cells(wRow, 5) = "Size"
        ActiveSheet.Cells(wRow, 6) = "비고"
       
        '이건별도 나만에 함수로 생략 setHeaderStyle wRow     'header 스타일 적용
        wRow = wRow + 1
    Else
        wRow = ActiveSheet.Range("B3") + 10 '삭제를 안하고 추가하는경우 헤더포함하여 다음써야될행

    End If
    
    'b1에 입력된 기본 경로하위 폴더 및 파일목록을 작성시작
    FolderFile ActiveSheet.Range("B1")
   
End Sub


Function FolderFile(fn As String)


 Dim fs As FileSystemObject
 Set fs = New FileSystemObject

 Dim foldeer As Folder
 Dim fileinfo
 Dim Filnavn() As String
 Set foldeer = fs.GetFolder(fn)

 '해당폴더에 파일이 있는경우
 For Each fileinfo In foldeer.Files

        ActiveSheet.Cells(wRow, 1) = wRow - 9  '기본자릿수
        ActiveSheet.Cells(wRow, 2) = fileinfo.Name  '파일명
        ActiveSheet.Cells(wRow, 3) = Mid(fileinfo.path, 1, Len(fileinfo.path) - Len(fileinfo.Name)) 'path에 파일명까지 같이 들어오므로 파일명 길이만큼 잘라path만입력
        ActiveSheet.Cells(wRow, 4) = fileinfo.Type
        ActiveSheet.Cells(wRow, 5) = fileinfo.Size
        wRow = wRow + 1   '작성후 다음위치 + 1
        Debug.Print "F " & fileinfo
 Next

 For Each Folder In foldeer.SubFolders  'sub폴더가 있는경우

        Debug.Print "D " & Folder
        FolderFile (Folder)             '재귀함수로 자신을 다시 부름
 Next

End Function 

파일처리 목록완성 예시

 

3) 하이퍼링크를 활용하여 클릭시 자동열리게 하자

   요즘은 하도 참조하는 문서가 많아 헷갈리는경우가 많다 저같은경우 목록을 작성하고

뒤에 비고란에 확인한 내용 및 주요 참고내용등을 적어놓고 다시 열때는 클리하여 자동열기를 주로 사용하고 있다

파일을 write할때 하이퍼링크 코딩을 넣어주면 된다.

 

'#하이퍼 링크 추가
ActiveSheet.Cells(wRow, 2).Select     '해당위치를 select
'address에는 전체파일명포함 경로, textToDisplay는 파일명
ActiveSheet.Hyperlinks.Add Anchor:=Selection, Address:=fileinfo.path, TextToDisplay:=fileinfo.Name 

 

추가하고 처리시 하이퍼링크건은 파란색 밑줄로 표시가 되고 클리하면 해당소스를 바로 읽게 됨

 

 

+ Recent posts