'개발'에 해당되는 글 73건

  1. 2008.01.30 InstDrv - 드라이버 로딩 도구 6
  2. 2007.11.30 [GoF] Singleton pattern 싱글턴 패턴 2
  3. 2007.11.20 [VisualStudio] VS를 사용하여 변수가 참조되는 곳 찾기 (참조로이동)
  4. 2007.11.20 CAxWindow 사용시 주의사항 & ATL Containment BUG
  5. 2007.11.12 소개 - VPL(Visual Programming Language)
  6. 2007.11.12 URL 스트링으로 인코딩
  7. 2007.11.05 리틀엔디안(little endian) vs 빅엔디안(big endian)
  8. 2007.10.29 Internet Explorer에서 스크립트(script) 오류(error)창 않뜨게 하기
  9. 2007.10.26 네이버 위젯 개발하기
  10. 2007.10.18 비트필드 사용하기 1

InstDrv - 드라이버 로딩 도구

개발 2008. 1. 30. 18:16

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

저자 : hanburn

날짜 : 2008-01-30

 

 

드라이버를 개발할 때 필요한 유틸리티 중에 하나가 바로 InstDrv.exe 라는 녀석입니다. 개발된 드라이버를 테스트 해볼 때 INI파일 없이 간단하게 드라이버를 설치하고 실행해볼수 있도록 해주는 유틸입니다.

 

 

사용자 삽입 이미지

위의 경로에 전체경로를 적어주고 Install 버튼을 누르면 드라이버가 설치가 되고 Start를 누르면 드라이버가 로딩이 됩니다. (DriverEntry 호출되는 시점이 여기입니다. ^^)

참 편리한 프로그램인데 한가지 불편한 점은 전체경로를 적는 것입니다. 요즘 같은 환경에 누가 전체경로를 타이핑하고 있나~ 라는 생각에 이 프로그램에 파일다이얼로그를 추가해서 마우스 클릭으로 파일을 선택할수 있도록 해보자는 생각으로 아래처럼 만들어 봤습니다.

 

사용자 삽입 이미지

 

기능은 똑같구요 에디트 옆에 버튼을 하나 두어서 파일다이얼로그를 띄어서 드라이버 파일을 선택할수 있도록 하였습니다. ^^  원래 유틸은 파일 크기가 30KB인데 파일다이얼로그와 about 창이 추가되어서 44KB로 크기가 조금 늘었습니다. 이정도야 조금 편리해 지는데 따른 coast 치고는 싼편이죠.. 이것말고도 프로그램 개발하는데 들어간 시간이 있었지만요..

앞으로 파일 전체 경로를 쓰는 번거로움이 조금 사라지면 개발시간은 충분히 보상되리라 생각됩니다. (반나절 정도 걸렸네요 ^^)

 

드라이버 개발시에 유용한 Device Tree라는 도구도 있습니다. 현재 컴퓨터에 로딩되어 있는 드라이버들의 목록을 보여주는 것인데, DDK를 설치하면 그안에 포함되어 있습니다.

사용자 삽입 이미지
 

 

새로 만든 InstDriver.exe를 가지고 드라이버 로딩 테스트를 하니까 위의 Device Tree에서 잘 보입니다.

 

참고로 드라이버를 설치하고 실행시키는 방법을 코드로 작성시에는 SCManager(스컴매니져)를 이용하여 서비스로 드라이버를 실행시켜주는 방법을 사용하였습니다. OpenSCManager(), OpenService(), StartService(), ControlService(), DeleteService() 등의 함수를 사용하였습니다.

 

두개의 파일을 모두 올려봅니다.



:

[GoF] Singleton pattern 싱글턴 패턴

개발 2007. 11. 30. 15:38

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

날짜 : 2007-11-30

저자 : hanburn

 

1. Singleton 정의

  1.1 클래스 다이어그램

2. Singleton이 필요한곳

3. 구현

3.1 C++로 기본구현

3.2 Template 클래스화

3.3 template 화된 클래스 사용

4. FAQ

 

1. Singleton 정의

클래스의 인스턴스가 하나만 만들어 지고 어디서든지 그 인스턴스에 접근할 수 있도록 하기 위한패턴

 

  1.1 클래스 다이어그램

          

사용자 삽입 이미지

 

2. Singleton이 필요한 곳


스레드풀, 레지스트리 설정객체, 로그객체등

 

3. 구현

1.     ‘single instance’ 클래스에서 private static 멤버를 정의 한다.

2.     클래스에 static accessor를 정의한다.

3.     ‘lazy initialize(게으른 초기화 : 요청시 생성하는)’ accesor에 구현한다.

4.     생성자는 protected 또는 private로 정의한다.

 

 

  3.1 C++로 기본구현

class MyClass

{

public:

        static MyClass*        getInstance()          // 스레드의 안정성 문제가 있음

        {

               if( m_pInstance == 0 )

                       m_pInstance = new MyClass();

 

               return m_pInstance;

        }

 

        static releaseInstance()

        {

               delete m_pInstance;

               m_pInstance = 0;

        }

 

public:

        void print()

        {

               std::cout<< "print.." << std::endl;

        }

 

private:

        MyClass(){};           // private

 

        static MyClass*        m_pInstance;

};

 

MyClass* MyClass::m_pInstance = 0;

 

위의 C++로 구현된 부분에는 getInstance 부분에 멀티스레드에서 안정성이 보장이 않되는 문제가 있습니다. 멀티스레드를 고려해서 m_pInstance 를 포인터대신 m_Instance로 정적 변수로 사용하면 create on demand는 구현이 되지만 destroy on demand가 되지 않는 문제가 있습니다. 객체가 많은 리소스를 사용하고 시스템의 요구사항에 최소의 메모리 사용이 필요하다면 이것 또한 문제가 될 수 있습니다.

 

3.2 template 클래스화

 

template <class Obj>

class Singleton

{

public:

        static Obj*    getInstance()          // 스레드 안정성 문제 있음

        {

               if( m_pInstance == 0 )

               {

                       m_pInstance = new Obj();

               }

 

               return m_pInstance;

        }

 

        static releaseInstance()

        {

               delete m_pInstance;

               m_pInstance = 0;

        }

 

private:

        //Obj() {};            // 상속받는 곳에서 생성자를 private등으로 변경

 

        static Obj*    m_pInstance;

};

 

 

3.3 template화된 클래스 사용

 

#첫번째 방법

템플릿을 사용한 버전은 해당 클래스를 상속 받으면 Singleton 클래스로 된다. 한가지 상속을 받고 생성자를 private 또는 protected로 변경해주어야 한다. 이렇게 하면 컴파일시에 Singleton 템플릿 클래스의 getInstance()에서 new 부분에서 생성자가 private이라서 오류가 나므로 아래처럼 Singleton 클래스를 friend 클래스로 선언을 해주어야 한다.

 

<템플릿 클래스 상속을 통해서 정의>

class aa : public Singleton<aa>

{

friend class Singleton<aa>;   // 생성자가 private이므로

public:

        void print()

        {

               cout<< "aa::print" << endl;

        }

private:

        aa() {};       // 생성자는 private으로

};

 <사용시에는>

aa::getInstance()->print();   // getInstance 처음호출시 객체생성

// 기타작업

aa::releaseInstance(); // 자원을 해제할 경우 releaseInstance 호출

 

 # 두번째 방법

템플릿 버전을 아래처럼 사용하는 방법도 있다.


 <보통 정의된 클래스>

class bb

{

public:

        void print()

        {

               cout<< "bb::print" << endl;

        }

 

        int a;

};

 

 <사용시>

Singleton<bb>::getInstance()->print();

Singleton<bb>::getInstance()->a = 5;

int b = Singleton<bb>::getInstance()->a;

Singleton<bb>::releaseInstance();

 

두번째 방법은 기존에 정의되어 있는 클래스에 Singleton 템플릿 클래스가 Singleton 컨테이너(?)역할을 하게 된다. 물론 bb라는 클래스를 정의해서 사용할 수도 있게 되므로 bb 클래스자체가 Singleton이 되는 것은 아니다. 그저 사용시에 Singleton처럼 사용이 되는 것이다.

 

템플릿화된 클래스를 첫번째 방법처럼 상속을 통해서 사용할 수 있고, 두번째 방법처럼 사용할 수도 있다. 템플릿 정말 매력적이다.

 

 

4.  FAQ

Q : 정의대로 하나만 만들어 지고 어디서든지 접근 가능하다면 전역변수와의 차이점은 무엇인가요?

A : 전역변수는 프로그램이 시작될 때 객체가 생성되므로 객체의 라이프 싸이클(life-cycle)을 관리 할 수 없는 문제가 있음



:

[VisualStudio] VS를 사용하여 변수가 참조되는 곳 찾기 (참조로이동)

개발 2007. 11. 20. 12:00

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

날짜 : 2007-11-20

저자 : hanburn

 

Visual studio의 편리한 기능중에서 사용중인 변수에 마우스 오른쪽 클릭을 하면 해당 변수가 정의되어 있는 곳으로 이동하는 기능과 선언으로 이동하는 기능이 있어서 참 편리하게 사용하고 있습니다. 그런데 팝업메뉴에보면 참조로 이동이라는 메뉴에는 회색으로 disable 처리가 되어 있는 것을 볼 수 있습니다. 참조로 이동이라면 해당 변수가 사용되는 곳, 즉 참조하는 곳으로 이동한다는 것인데 상당히 유용한 기능이 될 수 있는 것 같은데, disable이라니..  실망하지 마세요.. 방법을 찾았습니다.

 

BSC파일이라는 브라우서 소스파일을 먼저 만들어야 됩니다. 아래에서 만드는 방법을 설명합니다.

 

1. .BSC 파일 만들기

 

.BSC파일을 만들기 위해서는 커맨드 라인에서 BSCMake.exe 툴을 이용하여 만들어야 되는데, 아래의 방법으로 IDE 환경에서 간단하게 생성할 수 있습니다.

 

Visual Studio의 프로젝트 속성에서 아래와 같이 하면 각 소스파일(cpp파일)에 대해서 찾아보기 정보 파일을 생성할 수 있습니다.

 

먼저, C/C++탭의 찾아보기 정보에서 찾아보기 정보 사용에서 ‘FR’ 옵션으로 변경합니다.

사용자 삽입 이미지


이렇게 하면 각각의 소스파일에 대해서 sbr 파일이 release/debug 폴더에 생성이 됩니다.

 

각각의 sbr 파일을 합쳐서 .BSC 파일을 생성하려면, 속성의 일반탭에서 브라우저 정보 빌드를 로 변경합니다.

사용자 삽입 이미지

이렇게 하고 다시 빌드를 해주면 release/debug 폴더에 .BSC 파일이 생성이 됩니다.

위의 과정을 해주면 아래그림처럼 마우스 오른쪽 버튼의 참조로 이동메뉴가 활성화가 됩니다.


사용자 삽입 이미지

2. 참조 이용하기

 

* 마우스 오른쪽을 클릭하여 참조로 이동을 선택하면 해당 기호의 첫번째 참조로 이동을 합니다. 이때 애매모호한 경우에 모호성 해결대화상자가 나타입니다. (많이보던 거죠 ^^)

* 다음 참조로 이동하고 싶으면 ‘Ctrl+Shift+1’ 단축키를 이용하면 됩니다.

* 기호찾기 대화상자에서 검색을 수행한 후에 표시되는 기호 찾기 결과 창에서 기호의 노드를 확장하여 기호의 참조를 탐색합니다.

 

기호찾기는 Alt+F12를 누르거나 메뉴의 편집->찾기및바꾸기->기호찾기에 있습니다.


관련자로 : http://msdn2.microsoft.com/ko-kr/library/95ws11cy(VS.80).aspx



:

CAxWindow 사용시 주의사항 & ATL Containment BUG

개발 2007. 11. 20. 11:24

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

날짜 : 2007-11-20

저자 : hanburn

 

 

ATL 프로그램으로 WebBrowser 컨트롤을 hosting 하는 역할로 CAxWindow를 많이 사용합니다. CAxWindow를 사용할때 주의를 기울이지 않으면 메모리릭(memory leak)이 발생할 수 있다고 합니다. 그리고 CAxWindow의 자체적인 버그도 있다고 합니다.

 

 

먼저, 다음은 메모리릭이 발생할 수 있는 잘못된  2가지 사용예입니다.

 

1번사용예

//Intialize ATL control containment.

AtlAxWinInit();

 

//Create container window.

HWND hWndCont = m_ax.Create(m_hWnd, rect, 0, WS_CHILD | WS_VISIBLE);

 

//Create & activate ActiveX control

HRESULT hr = m_ax.CreateControl("MSCAL.Calendar");

 

2번사용예

//Intialize ATL control containment.

AtlAxWinInit();

 

//Create container window

HWND hWndCont = m_ax.Create(m_hWnd, rect, 0, WS_CHILD | WS_VISIBLE);

 

// Create ActiveX control.

CComPtr<IUnknown> spunk;

HRESULT hr = CLSIDFromProgID(OLESTR("MSCAL.Calendar"), &clsid);

hr = CoCreateInstance(clsid, NULL, CLSCTX_ALL, IID_IUnknown, (void**)&spunk);

 

// Activate ActiveX control.

HRESULT hr = m_ax.AttachControl(spunk);

 

위의 두 경우에 Create()함수는 CAxHostWindow 객체를 생성합니다. CreateControl()함수나 AttachControl()함수 또한 CAxHostWindow 객체를 생성합니다. 따라서 처음에 Create() 함수로 생성된 CAxHostWindow 객체는 소멸이 않되게 됩니다.

 

 

다음으로 ATL Containment의 메모리릭 버그입니다.

 

증상 : ActiveXATL에서 hosting 할때에 메모리가 줄줄이 샘.

원인 : ATL내부에서 CreateAcceleratorTable 함수를 호출하는데 소멸시(release)시에 ATL에서 이것을 해제하지 않아서 발생함.

 

대책 :

1.     Atlhost.h파일의 복사본을 만들어서 Fixatlhost.h 파일을 만든다.

2.     FixAtlhost.h파일에 CAxHostWindow 클래스에 HACCEL타입의 멤버 변수를 하나 추가한다.

3.     IOleInPlaceSite::GetWindowContext 메소드에서 CreateAcceleratorTabel함수의 반환값을 저장해 둔다.

4.     IOleInPlaceSite::OnInPlaceDeactivate 메소드에서(Release되는 시점) DestroyAcceleratorTable함수를 호출해준다.

5.     FixAtlhost.h 파일을 저장하고 atlhost.h 파일대신 include를 한다.

 

메모리릭이 발생하는 것은 ATL 3.0 이라네요.. ㅎㅎ
 

 

참고자료 :

http://support.microsoft.com/kb/229904 : CAxWindow Members Can Cause a Memory Leak

http://support.microsoft.com/kb/258235 : Memory Leak with ATL Containment

 

 

 



:

소개 - VPL(Visual Programming Language)

개발 2007. 11. 12. 11:35

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

저자 : hanburn

날짜 : 2007-11-12

마이크로소프트에서 VPL(Visual Programming Language : 이하 VPL)이라는 것도 만들었내요(july 2007). 말 그대로 코딩을 할 줄 모르는 사람들도 쉽게 그림을 통해서 프로그램을 할 수 있도록 만든 것인데요, 개념적으로 보면 재미가 있습니다.

 

프로그래밍에 필요한 기본적인 요소가 무었일까요? 또는 최소한으로 필요한 것은 무엇일까요?  현재의 튜링머신 구조상에서는 상수, 변수, 제어구조(비교, 반복구조)등이 아닐까 생각됩니다. 보통 우리가 사용하는 C/C++ 같은 언어는 너무나 잘 되어 있는 프로그래밍 언어입니다. 어셈블리어로 시야를 변경해 보면, 변수에 해당하는 register 나 메모리가 존재하구요, 값이 이동시키는 move 명령어, 그리고 제어구조에 해당하는 jmp 값은 명령어 들이 있습니다.

 

프로그래밍의 본질은(?) 변수에 값을 대입하고, 연산과 흐름을 제어 하는 것입니다.

 

그럼 이런 기본적인 것을 Visual 적으로 어떻게 표현을 할 수 있을까요? 궁금하지 않습니까? 아래를 보기전에 잠시 생각을 해보시기 바랍니다. 여러분이라면 어떤 방식을 사용해서 이런 것을 표현 할지를요  때때로 발명은 재미로 시작하는 것들이 많습니다~

 

 

아래는 VPL의 모습입니다.

사용자 삽입 이미지


왼쪽상단에 Basic Activities에 기본적인 프로그래밍 요소들이 들어 있습니다. 변수에 해당하는 Variable, 상수에 해당하는 Data, 연산에 해당하는 Calculate, 제어구조에 해당하는 if, switch 등이죠.. ~ 반복문은 없나요? 네 없습니다. 연산과 if 블락을 이용해서 만들어야 합니다. 화면 가운에 Diagram 이라는 곳이 코딩(?)을 하는 공간입니다. 마우스로 해당 Activities를 드래그 하여 코딩을 하게 됩니다. 재미있죠~ ^^  위의 코딩은 2개의 값을 입력 받아서 같으면 같다아니면 다르다를 출력하는 간단한 프로그램 입니다. 개발자라면 직관적으로 알 수 있을 것입니다. 그럼 하나 더 보도록 할 까요?  어떤 동작을 하는 것인지 추측해 보세요~


사용자 삽입 이미지

.

.

.

.

 

이것은 0이라는 상수를 loopInd라는 변수에 대입을 하고(set) if 비교를 통해서 5가 될때까지 +1을 해주는 코딩(?)입니다. 즉 반복구문 이죠. 이게 직관적으로 알기는 쉬운데, 조금만 복잡해져도 그림이 난장판이 될 것 같은 예감이 들지 않나요?  아니라구요? 그럼 아래를 보시구 어떤 동작을 하는지 맞추어 보세요 ㅋㅋ


사용자 삽입 이미지



:

URL 스트링으로 인코딩

개발 2007. 11. 12. 10:54

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

저자 : hanburn

날짜 : 2007-11-09

웹서버와 통신을 할 때 GET 또는 POST method를 사용하여 통신을 하게 됩니다. 파라미터로 어떤 값을 보내야 할 때 한글이나 공백등이 있으면 URL 표현 규칙에 않맞게 되어 서버쪽에서 올바르게 인식을 못하게 됩니다. ‘Good’ 이나 김희선처럼 붙어 있는 단어는 상관이 없지만 김 희선’ ‘boy friend’ 처럼 중간에 공백이 있을때는 서버에서 인식을 못하게 됩니다.

 

이런 경우에 아래처럼 인코딩을 해서 보내주어야 합니다.

 

‘boy friend’ => ‘%62%6f%79%20%66%72%69%65%6e%64’

김 희선’ => ‘%b1%e8%20%c8%f1%bc%b1’

 

변환되는 규칙을 살펴보면 빈문자(스페이스) %20으로 변환 되는 것을 알 수 있고 ‘b’ %62로 변환되는 것을 알 수 있습니다. ~ 이건 바로 해당 문자의 아스키값을 16진수로 표현한 것에 앞에 %를 추가한 것임을 알 수 있습니다. 코드로는 간단하게 sprintf를 사용하여 16진수로 변환을 할 수도 있지만 직접 비트연산을 통해서 변환하는 함수를 만들어 보았습니다.

 

long TextToUrlString(TCHAR* szText, TCHAR* out, unsigned len)

{

        unsigned nSrcLen = lstrlen(szText);

 

        // check output buff

        if( nSrcLen*3 >= len)         return 0;

 

        int nIdx = 0;

        for( int i=0 ; i < nSrcLen ; ++i)

        {

               out[nIdx++] = '%';

               char src = szText[i];

 

               char leftI = src & 0x0f;

               char rightI = (src>>4) & 0x0f;

 

               char leftA[2] = {0}; 

               char rightA[2] = {0}; 

               itoa(leftI, leftA, 16);

               itoa(rightI, rightA, 16);

 

               out[nIdx++] = rightA[0];

               out[nIdx++] = leftA[0];              

        }

 

        out[nIdx] = 0;

 

        return nIdx;

}

 

텍스트 문자를 url스트링으로 변환을 했으면 반대로 url스트링을 텍스트로 변환하는 함수도 있어야 겠죠..  그래서..

 

long UrlStringToText(TCHAR* szUrlString, TCHAR* out, unsigned len)

{

        unsigned nSrcLen = lstrlen(szUrlString);

 

        // check output buff

        unsigned nTargetLen = nSrcLen/3;

        if( nTargetLen >= len)        return 0;

 

        int nSrcIdx = 0;

        int nTargetIdx=0;

        for( nTargetIdx=0 ; nTargetIdx < nTargetLen ; ++nTargetIdx)

        {

               //

               char ch[3];

               ch[0] = szUrlString[nSrcIdx++];              // %          

               ch[1] = szUrlString[nSrcIdx++];              //

               ch[2] = szUrlString[nSrcIdx++];              //

 

              

               ch[1] = tolower(ch[1]);

               ch[2] = tolower(ch[2]);

 

               // 16진수

               if( ch[1] > '9' )

                       ch[1] = ch[1] - 'a' + 10;

               else

                       ch[1] = ch[1] - '0';

 

               if( ch[2] > '9' )

                       ch[2] = ch[2] - 'a' + 10;

               else

                       ch[2] = ch[2] - '0';

 

               char target = (ch[1]<<4) | ch[2];

 

               out[nTargetIdx] = target;            

        }

 

        out[nTargetIdx] = 0;

 

        return nTargetIdx;

              

}

 



:

리틀엔디안(little endian) vs 빅엔디안(big endian)

개발 2007. 11. 5. 14:34

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

저자 : hanburn

날짜 : 2007-11-05


이번에는 CPU가 메모리를 읽는 순서에 대해서 살펴 보도록 하겠습니다. 먼저 엔디언이란 여러 바이트로 되어있는 자료를 하나의 데이터로 간주하여 어떤 바이트 순서로 데이터를 배열 할 것인지를 나타내는 것입니다. 주소가 낮은쪽에 최하위 바이트를 저장하는 방식을 리틀 엔디안(Little-endian) 이라 하고, 반대로 낮은쪽에 최상휘 바이트를 저장하는 방식을 빅 엔디안(Big-endian)이라고 합니다.

 

이해하기 쉽게 예를 들면, long 타입의(32bit 환경에서 4byte) 데이터를 메모리에 쓴다고 할때

long a = 0x1234;

 

리틀엔디안 에서는          0x0012FED4  34 12 00 00

빅엔디안 에서는             0x0012FED4  00 00 12 34

 

위와 같은 구조로 메모리에 저장이 되게 됩니다.

 

빅엔디안은 우리가 평소에 보던 방식으로 메모리에 쓴다고 생각하면 되구요, 리틀엔디안은 뒤집어 져서 쓴다고 생각하며 됩니다. 그럼 리틀엔디안은 왜 뒤집어서 쓰는 걸까요??

 

그것은 산술연산유닛(ALU)에서 메모리를 읽는 방식이 메모리 주소가 낮은 쪽에서부터 높은 쪽으로 읽기 때문에 산술 연산의 수행이 더 쉽기 때문이랍니다. (~ 그렇군~)

 

우리가 사용하는 인텔(Intel)x86 계열의 CPU등은 리틀엔디언 방식의 CPU이구요, Motorola, Sun, Sparc 같은 Risc 타입은 빅엔디안 방식입니다.

 

빅엔디안 방식의 장점이라면,

정수로 정렬된 수에대한 비교가 메모리에서 읽는 순서대로 바로 비교가 가능

정수와 숫자타입의 데이터를 같은 순서 방향으로 읽을수 있음.

등이 되겠습니다.

 

보통 IBM 호환 컴퓨터의 Windows 환경을 많이 사용하고 있는데, 이때는 리틀엔디안의 방법으로 사용되고 있습니다. 그런데 네트워크는 네트워크 오더링 이라고 하여서 빅엔디안 방식의 바이트 정렬 방법을 사용하고 있는습니다. 따라서 통신 프로그램을 할 때는 이 바이트 정렬을 맞추어 주어야 합니다. C 함수로 ntohs, htons, ntohl, htonl 등의 함수를 이용하면 리틀엔디안과 빅엔디안 사이의 변환을 수행 할 수 있습니다.

 

위의 htonl 함수를 호출하기 전/후 메모리를 찍어 보면 아래와 같습니다.

 

long a = 0x1234;

a = htonl(a);

 

호출전: 0x0012FED4  34 12 00 00

호출후: 0x0012FED4  00 00 12 34

 

htonl ntohl 함수는 같은 실제적으로 같은 역할을(바이트 순서 변경) 하는데, 의미상 이름을 host to network, network to host로 해서 제공하고 있습니다.

 



:

Internet Explorer에서 스크립트(script) 오류(error)창 않뜨게 하기

개발 2007. 10. 29. 12:19

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

저자 : hanburn

날짜 : 2007-10-26

 

인터넷익스플로러(Internet Explorer, 이하 IE)로 웹서핑을 하다보면 페이지에 스크립트 오류(script error)가 발생시에 오류창이 뜨게 되어 있습니다. 스크립트 오류가 발생하는 경우는 서핑중인 페이지에서 사용한 스크립트의 문제로 페이지 자체의 오류라고 할 수 있습니다. 사소한 오류의 경우에 IE 7.0에서 확인한 결과 오류창이 뜨지 않는데, WebBrowser Control을 사용하여 프로그램에서 해당 페이지를 서핑할 경우에 오류창이 아래와 같이 표시가 되었습니다.
사용자 삽입 이미지

이것은 네이버에서 OpenAPI를 이용하여 CNN 뉴스를 듣게 만든 위젯에서(iCNN) 발생하였는데, ‘아니오를 누르면 프로그램은 문제없이 실행 되지만 실행할 때 마다 오류메시지가 보이니까 프로그램이 버그를 가지고 있는 것 같아서 수정이 필요하였습니다. (실제적인 원인은 cnn에서 제공하는 스크립트 문제입니다~ ㅋㅋ) 이문제를 해결하기 위해서 검색을 해보니, IE에서 스크립트 오류시에 나오는 메시지 창을 핸들링 할 수 있는 방법이 있었습니다.

 

(How to handle script errors as a WebBrowser control host)

참고 : http://support.microsoft.com/kb/261003

 

WebBrowser control에서 에러가 발생하면 컨테이너에서 IOleCommandTarget 인터페이스가 구현되어 있으면 IOleCommandTarget::Exec 메소드를 호출하게 되어 있는데, 이때 nCmdID CGID_DocHostCommandHandler로 전달 된다고 합니다. 따라서 구현시에 nCmdID를 체크하여 CGID_DocHostCommandHandler인 경우에 S_OK를 반환해주면 오류창이 않뜬다고 합니다.

 

그래서 IOleCommandTarget을 아래처럼 가볍게 구현을 해주었습니다. 재사용성을 위해서 템플릿 클래스로 만들었는데, 중요 부분만 발췌하면 아래와 같습니다.

 

virtual HRESULT STDMETHODCALLTYPE QueryStatus(const GUID __RPC_FAR *pguidCmdGroup, ULONG cCmds, OLECMD __RPC_FAR prgCmds[], OLECMDTEXT __RPC_FAR *pCmdText)

{

        T* pT = static_cast<T*>(this);

 

        return m_spDefaultOleCommandTarget->QueryStatus(pguidCmdGroup, cCmds, prgCmds, pCmdText); 

 

}

 

virtual HRESULT STDMETHODCALLTYPE Exec(const GUID __RPC_FAR *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT __RPC_FAR *pvaIn, VARIANT __RPC_FAR *pvaOut)

{

        T* pT = static_cast<T*>(this);

        BOOL bCmdGroupFound = FALSE;

 

        if (nCmdID == OLECMDID_SHOWSCRIPTERROR)

        {

                // 요기가 중요

               (*pvaOut).vt = VT_BOOL;

               (*pvaOut).boolVal = VARIANT_TRUE;

                return S_OK;

        }

        return m_spDefaultOleCommandTarget->Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);             

}

 

참고로 이 방법이 동작하기 위해서는 IE인터넷 옵션 -> 고급에서 아래그림처럼 스크립트 디버깅 사용안함에 체크가 되어 있어야 합니다. 기본으로는 이 항목에 체크가 되어 있으니 별 문제가 없는데, 혹시라도 작동이 않된다면 이옵션을 체크해 보아야 합니다.

사용자 삽입 이미지


그리고 검색하면서 IE programming쪽을 조금 보게 되었는데, IE가 생각보다 잘 만들어진 것 같습니다. (사용자 입장이 아닌, 개발자 입장에서) IE도 윈도우의 탐색기(shell)처럼 여러가지 확장가능하도록 다양한 인터페이스를 노출하고 있더군요. IE에서 보여지는 UI를 변경하고 싶을때는 IDocHostShowUI, IDocHostUIHandler 등을 구현해주면 다음과 같은 것들을 할 수 있습니다.

 

* 마우스 오른쪽 클릭시 뜨는 메뉴를 커스터 마이징 : IDocHostUIHandler::ShowContextMenu

* IE에서 띄우는 메시지 박스 커스터 마이징 : IDocHostShowUI::ShowMessage

 

위의 두 인터페이스를 구현시 다음을 참고

MFC : http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/samples/internet/browser/driller/default.asp (Driller(MFC))

ATL : http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/samples/internet/browser/atlbrowser/default.asp (ATLBrowser)

 

 

그리고 팝업창 띄우는 것을 막으려면 http://www.codeproject.com/atl/popupblocker.asp



:

네이버 위젯 개발하기

개발 2007. 10. 26. 11:19

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

저자 : hanburn

날짜 : 2007-10-26

 

 개인적으로 네이버 데스크톱이 귀여운 면이 있어서 야후위젯에서 이쪽으로 건너 왔는데, 드디어 OpenAPI 제공으로 위젯을 제작할 수 있게 되었습니다. 네이버 데스크톱의 위젯을 개발 할 수 있는 interface를 노출 시켜주고 있는데, 한번 살펴 보도록 하겠습니다. 일단 네이버 데스크톱의 위젯 만들기로 가면 자세한 정보를 제공하고 있습니다. (http://desktop.naver.com/openapi/index.nhn) 개발자 가이드, key 발급, 카페, 위젯등록등 여러가지 정보를 제공하고 있습니다.

아래의 그림이 전체적인 개괄도인데요

사용자 삽입 이미지


COM 기반의 인터페이스를 노출하고 있군요..

 

그리고 문서다운로드에서 위젯 샘플로 mp3 player를 제공하고 있어서 위젯을 만들기에 별 어려움은 없었습니다. 참고로 저는 cnn의 뉴스를 편리하게 들을 수 있는 위젯을 만들었습니다. 이름하여 iCNN위젯~ ㅋㅋ

위젯을 만드는 과정은 잘 설명이 되어 있는데, 한가지 아쉬운 점이라면, 위젯 메이커에서 ‘step5 단계에서 [위젯 아이콘 등록하기] 과정이 있는데, 여기에서 아이콘 파일을 꼭 png로 만들어야 된다는 것입니다. ~ 평소 자주 사용하던 그림판에서 않되더군요..  png 말고 jpg도 사용할수 있게 해주면 좋을 것 같은 아쉬움이 남습니다. 참고로 위젯아이콘 제작에 대한 가이드도 마련되어 있더군요.. (http://desktop.naver.com/openapi/guide/index.nhn?menu=28)

 

Png 파일을 만들기 위해서 Paint.net이라는 프로그램을 사용하였습니다. 프로그램이 직관적이어서 그림판에 익숙한 사용자라면 10분 정도의 삽질을 통해서 바로 사용할수 있는 프로그램입니다. 삽질을 통해서 png 파일도 만들고 네이버에서 위젯 키도 발급받아서 위젯을 만드는데 완성하였습니다. 짬짬이 만드는데 몇일 걸리더군요.. 

 

만든 위젯과 발급 받은 키를 이용해서 위젯 등록하를 하면 1~2주 정도 지나니까 위젯이 등록되었다고 메일이 옵니다. 그래서 가서 확인해보니 제가 만든 위젯이 등록이 되었습니다~ ㅎㅎ 그래서 기념으로 갭쳐링~

사용자 삽입 이미지

오옷~ 벌써 581명이 다운을 받았네요~
평점은 8.0 이군요~ ㅎㅎ



:

비트필드 사용하기

개발 2007. 10. 18. 09:51

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

제목 : 비트필드 사용하기

저자 : hanburn

날짜 : 2007-10-17

 

 

앞에서 비트벡터에 대해서 알아 보았는데, 이번에는 비트필드에 대해서 알아보도록 하겠습니다. C/C++ 언어에서 비트연산을 제공하고 있지만 바이트의 값에서 원하는 비트의 값을 가지고 오기가 쉽지 않습니다. 예를 들면 윈도우에서 키보드가 눌렸을 때 발생하는 WM_KEYDOWN 메시지에서 LPARAM으로 넘어오는 값은 많은 정보를 가지고 있습니다.

 

0~15 : 키가 반복되는 정보

16~23 : 키 스캔코드(OEM 정보)

24 : 확장정보 오른쪽 ALT/CTRL 키에대한 확장정보

25~28 : 예약필드

29 : context code

30 : 이전 키의 상태 (previous key state)

31 : 변화 상태 (transition state)

 

여기에서 30번째 비트의 정보를 읽어 오려면, shift 연산과 & 연산 등으로 해당 값을 가지고 와야 하는데 너무 번거로운 코드가 들어가야 합니다. 반대로 4바이트의 데이터에 원하는 비트를 설정하려면 비슷한 류의 번거로운 코드가 들어가야 합니다.

 

이러한 번거로운 작업을 편하게 해주는 방법이 비트필드를 이용하는 코딩 방법입니다. 비트필드는 C/C++언어에서 지원을 해주는데 평소에 사용할 일이 없어서 모르는 경우가 많습니다. 비트필드는 바이트단위의 정보를 비트단위로 쪼개어 쉽게 사용할 수 있게 해주는 방법입니다. WM_KYEDOWN에서 사용할 비트필드를 만들어 보면,

 

typedef struct ST_KEYINFO_FIELD

{

        long    repeat:16;

        long    scancode:8;

        long    extendkey:1;

        long    reserved:4;

        long    contextcode:1;

        long    previous_keystate:1;

        long    transition_state:1;

};

 

스트럭처의 변수옆에 : 표현뒤에 오는 숫자는 비트의 크기를 나타냅니다. 숫자를 다 더해보면 16+8+1+4+1+1+1 = 32 가되어 4Byte의 크기로 바로 LPARAM의 크기와 같습니다. Long은 비트필드를 사용할 바이트의 정보로 총 4바이트의 크기의 공간을 예약하고 그 뒤에 오는 숫자로 비트필드의 수를 나타닙니다. 이렇게 구조체를 정의하면  다음과 같이 편하게 값을 읽어오고 쓸수가 있게 됩니다.

 

ST_KEYINFO_FIELD keyInfo;

int a = keyInfo.repeat;       // 반복정보(0~15비트) 읽기

keyInfo.extendkey = 1;        // 확장키정보(24번째비트에) 쓰기

 

 

해당비트의 값을 읽고/쓰기는 편해졌는데, 이렇게 정의된 ST_KEYINFO_FIELD 타입의 변수에 값을 넣기는 그냥 대입을 하면 않됩니다. 아니 그럼 memcpy 등으로 복사를 해야된다는 말인가? 당연히 아니죠~  위의 구조체와 union을 함께 사용하면 됩니다.

 

typedef union ST_KEYINFO

{

        LPARAM lParam;

        ST_KEYINFO_FIELD field;

};

 

공용체를 정의할때는 비트필드와 같은 키기의 변수를 잡는 것이 포인트입니다. 그래야 lparam의 값을 바로 할당 할 수가 있죠. 위에 정의된  ST_KEYINFO 공용체(union)을 사용하여 값을 읽는 코드는 아래와 같습니다.

 

CxxWnd::OnKeyDown(WPARAM wParam, LPARAM lParam)

{

        ST_KEYINFO keyInfo;

        keyInfo.lParam = lParam;

        int a = keyInfo.field.repeat; //

        bool b = keyInfo.field.previous_keystate;   

}

 

공용체(union)와 비트필드를 함께 사용하면 깔끔하게 일정메모리에서 복잡한 비트연산없이 비트단위의 정보를 읽고/쓰기 작업이 편리해 지는 방법입니다.

 

비트벡터보다 훨씬 유용하니까 많이많이 사용하세요



:
◀ PREV : [1] : [2] : [3] : [4] : [5] : [6] : [7] : [8] : NEXT ▶