close

Trust Me!! Trust You!!


  • Blog
  • Local Log
  • Tag Cloud
  • Key Log
  • Guestbook
  • RSS Feed
  • Write a Post
  • Admin

혹시 블로그 스킨이 깨져 보이시나요? 최신버전의 Internet Explorer(Windows용), Opera, Firefox를 사용해보세요.

초보분들을 위한 ActiveX 컨트롤 컴포넌트

웹 프로그래밍
2009/04/16 15:46
 

음 솔직히 말씀드려서 이걸 쓸 생각이 전혀 없었읍니다. ㅠ.ㅠ


실력도 안되고 저도 아직 다 해석을 한것도 아니라서 누가 물어보면 대답할 자신도 없고... 또 이제는 Active-X를 사장시키는


쪽으로 다들 개발을 하셔서 이제 할 필요가 없지 않나 했읍니다만 근데 의외로 이런 질문이 많은거 같고 또한 밑의


이동진님... 우리 아버님 하고 이름도 같고 해서 그냥 필받아서 막 적습니다.



제가 몇차에 걸쳐 이걸 적을 수 있을지는 모르겠읍니다만 호응이 크면 계속 하지요 ^^


1. 개발환경


IDE : VC++ 6.0 <- 이거 말고는 할줄 모름 ㅠ.ㅠ 물어보지 마셈

OS : Windows XP

프로그램 형식 : MFC ActiveX Control Wizard

설명 : 이동진님을 따라하는 방식으로 키키키키


2. 개발목표

 우선 개개인이 Active-X로 만들고 싶은 어플이 있다는 가정에 시작하겟읍니다. 이 어플리케이션을 이미 만들었고 이를 Active-X로 변경하는 부분을 설명하는 것이 Actvie-X만 집중할수가 있겠고  또 설명이 어플리케이션 제작으로 흐르지 않을거 같아서요


3. 개발과정

 1) VS 6.0을 실행합니다.

 2) 메뉴 중 [File] 선택 - [New] 선택 - [프로젝트] 선택 (단축키 Ctrl+N)

 3) 아래 화면이 나타나면 왼쪽에서 MFC ActiveX Control Wizard선택  - 아래부분 [이름]에 원하는 프로젝트 이름 적고 [위치]에 프로젝트 관련된 파일이 저장될 폴더를 선택합니다.

[확인]을 누르면 다음 창으로 넘어갑니다.




4) 자 여기를 설명하자면 이 프로젝트 안에 몇개의 인터페이스를 만들것이냐를 먼저 물어보구여

 이건 함수 인터페이스가 아니고 밖으로 빠지는 컨트롤의 갯수입니다. 우선 한개로 만들겠읍니다만 여러개로 하면 더 재미있어요 한개의 ocx로 Object를 여러개 쓸수 있거든요

5)두번째 No runtime License와 그 밑은 통과하겠읍니다.



5) 자 밑에서 중요한것은 체크박스 5개인데 보통 첫번째것만 체크합니다. OCX에 About가 있는 것도 좀 그렇더라구여 그리고 맨 밑의 서브클래스 설정하는 것은 ocx가 버튼이나 다른 클래스를 상속받아서 그려야 할때 사용합니다.




6) 음냐 여기까지는 그냥 거저 먹기인데 이제부터 힘들겠군 ㅠ.ㅠ.  자 이제 Finish버튼을 누르면 기본 뼈다귀는 완성입니다. 물론 advanced가 있긴 하지만 이것도 소스에서 수정가능합니다. 첨에는 안되는줄 알고 다시 만들어서 복사했었던 뼈저린 기억이 ㅠ.ㅠ


7) 자 이제 안에 소스 부분을 다음에 조금 아주 조금 설명하지요


헉 쓰고 있는데 조회수가 팍 올라가네요 미안스럽게... 쩝


7) 자 전에 이어서 이제 안에 소스를 조금 보겠읍니다. Acitve-X는 Sample라는 이름으로 만들었구요. 중간 중간에 소스를 올리겠읍니다. 하다보니 소스를 안만들었다는 ^^


8) 우선은 확인차 컴파일을 해보십시요 아주 잘될겁니다. 우선 뼈다귀에서 중요한 부분만을 좀 보겠읍니다. 가장 중요한 부분이 Sample.odl, SampleCtl.cpp이렇게 2개의 파일입니다. 우선 뼈대에서는 말이죠


9) 우선 odl파일은 내용을 보시면 알겠지만 외부 인터페이스가 정의 되어 있는 부분입니다. 여기의 정보를 이용해서 외부에 OCX를 알려주고 함수도 알려주고 합니다만 이부분을 직접 손대는 것은 조금 나중에 하십시요. 좀 숙달되면 위저드보다는 직접하는게 속 편하긴 합니다. 근데 이중 가장 중요한 부분이 하나 있는데요. 바로


[ uuid(CC028E66-85EB-4242-98CA-3260E6F70196),
   helpstring("Sample Control"), control ]
 coclass Sample
 {
  [default] dispinterface _DSample;
  [default, source] dispinterface _DSampleEvents;
 };

이런 식으로 적혀있는 맨 밑으 것입니다....( 아 이것도 애기 해야 겠군요 위에 UUID로 되어 잇는 부분들은 손대지 마세요 ^^

이거 손대고 안된다는 분들이 가끔 있더군요가 아니라 내 부사수놈이 쩝..... 3일 고생했음다... 이건 임으로 손대는 것이 아니랍니당 ^^)

이게 뭐하는 거냐 하면 Html에서 쓸때 Object라고 등록하는 부분입니다 음 등록하는 것을 모르겠다구여 생각나면 맨마지막에 설명하져 ^^ 캡파일 등록하고 같이 ... 기대는 마삼 ^^


10) 그 다음으로 중요한 것이 SampleCtl.cpp 입니다. 여러분이 가장 많이 작업을 할 곳인데 여기에 외부 이벤트 및 인터페이스 함수, Property등을 선언하고 정의하는 곳입니다....


11) 레지스트리 등록 함수

자 이제 작업을 시작 합시다... 우선 처음에 해야 할것은 레지스트리 등록입니다. ocx는 특성상 레지스트리에 제대로 등록하면서 안전한 컨트롤이라고 등록을 해야만 브라우져에서 로딩할때 위에 틱(?)하고 나타나면서 뭐 안전하지 않은 ocx라고  뜨는것을 없앨수 있읍니다. 이건 cab파일 만들때 인증서 등록하는 것 하고는 또 틀립니다. 인증서는 서명된거 안된것을 가르키는 것이고 이건 레지스트리에 제대로 등록하는 것을 (아 설명이 이상타...) 애기합니다.


자 이제 함수

BOOL CSampleCtrl::CSampleCtrlFactory::UpdateRegistry(BOOL bRegister)
{
 if (bRegister)
  return AfxOleRegisterControlClass(
   AfxGetInstanceHandle(),
   m_clsid,
   m_lpszProgID,
   IDS_SAMPLE,
   IDB_SAMPLE,
   afxRegApartmentThreading,
   _dwSampleOleMisc,
   _tlid,
   _wVerMajor,
   _wVerMinor);
 else
  return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
}

을 봅시다. 이게 기본으로 적히는 함수인데... 이건 기본입니다 그냥... 자 여기에 추가를 하겟읍니다


 if (bRegister)
 {
  BOOL retval = AfxOleRegisterControlClass(
   AfxGetInstanceHandle(),
   m_clsid,
   m_lpszProgID,
   IDS_SAMPLE,
   IDB_SAMPLE,
   afxRegInsertable | afxRegApartmentThreading,
   _dwSampleOleMisc,
   _tlid,
   _wVerMajor,
   _wVerMinor);

  :: CoInitialize(NULL);

  // mark as safe for scripting--failure OK
  HRESULT hr = CreateComponentCategory(CATID_SafeForScripting,
   L"Controls that are safely scriptable");

  if (SUCCEEDED(hr))
   // only register if category exists
   RegisterCLSIDInCategory(m_clsid, CATID_SafeForScripting);
   // don't care if this call fails

  // mark as safe for data initialization
  hr = CreateComponentCategory(CATID_SafeForInitializing,
   L"Controls safely initializable from persistent data");

  if (SUCCEEDED(hr))
   // only register if category exists
   RegisterCLSIDInCategory(m_clsid, CATID_SafeForInitializing);
   // don't care if this call fails

  :: CoUninitialize();

  return retval;
 }
 else
 {
  // since unregistering the class automatically eliminates
  // the category registration and since we don't want to
  // remove the categories, we don't need to do anything special
  :: CoInitialize(NULL);

  HRESULT hr = UnRegisterCLSIDInCategory(m_clsid,CATID_SafeForScripting);

  if(SUCCEEDED(hr))
   hr = UnRegisterCLSIDInCategory(m_clsid,CATID_SafeForInitializing);

  if(SUCCEEDED(hr))
   hr = AfxOleUnregisterClass(m_clsid, m_lpszProgID);

  :: CoUninitialize();

   return SUCCEEDED(hr);
 }


좀 복잡하게 바뀌었지요????


뭐 이건 해석 필요없이 그냥 이렇다 하고 쓰십시요하고 싶을 뿐이고.. 단지 중간에

    IDS_SAMPLE,
   IDB_SAMPLE,
   afxRegInsertable | afxRegApartmentThreading,
   _dwSampleOleMisc,

부분은 각 ocx에 맞추어 바꾸셔야 합니다...


자 이제 다 됐다 하고 컴파일 하면 바로 에러 날겁니다 ^^


자 이제 각각의 함수에서 사용하는 것들중에


HRESULT CreateComponentCategory(CATID catid, WCHAR* catDescription);
HRESULT RegisterCLSIDInCategory(REFCLSID clsid, CATID catid);
HRESULT UnRegisterCLSIDInCategory(REFCLSID clsid,CATID catid);

이 함수들을 봅시당

이건 제가 인터넷에서 찾아서 쓰는건데 뭐 좀 편하지요 ^^ 이 함수들은 제 샘플의 Registry 안에 클래스로 있읍니다


자 그리고 컴파일 하면 또 에러 ^^


헤더 파일에

#include <objsafe.h>
#include <ComDef.h>

이 두개를 해줘야 합니다. 자 그럼 컴파일 해보십시요... ^^ 자 차이를 알수있을까요???


차이를 아실려면 Html파일을 만드셔야 합니다.


Html파일에


 <OBJECT ID="Test" width="600" height="1800" CLASSID="CLSID:CC028E66-85EB-4242-98CA-3260E6F70196">
 </OBJECT>

을 추가하시고 이 Html을 보시면 아실수 있읍니다. 여기서 clsid는 odl파일의  uuid(CC028E66-85EB-4242-98CA-3260E6F70196), 입니다 ^^


좀 대중없이 설명을 하고 있지요 ^^ 저녁에 다시 정리 해야 할거 같읍니다. 쓰다보니까 이거 정말 ...


밑에 쓰신분들 존경합니다... 첨 적는 거라 더 힘드네요 부사수한테 설명할때는 못알아듣는다고 구박했었는디....


자자 몇개의 답변에 힘을 얻어 3탄으로 갑니다 ^^

사실 이건 뭐 개념이고 이론이고 없읍니다. 거의 문서를 뒤져서 보고 해보고해서 경험반 뒤지기 반 정도입니다....

그래서 정확한 이론을 설명해 달라 하면 쩝 막막합니다...

자 이제까지 해본것은 우선 만들고 등록할때의 문제를 없애고 하는 부분입니다. 그럼 이번에 할부분은 인터페이스가 안전하다고 등록하는 것 입니다.


12) 인터페이스의 안전성 등록...

자 이건 어떤 것인가 하면 active-X컨트롤이 다른 컨트롤이나 어떤 부분과 상호작용하는데 안전하지 않을수 있읍니다.라고 경고가 뜨는 경우가 있는데 이럴경우에 이렇게 등록을 해야 하는 것입니다.

자 그럼 하는 방법을 설명해 봅시다.. 막무가내 식으로 이것도 해야 하는데...


우선 ctrl 헤더에


 //## ======== Safety Active-X로 등록
 DECLARE_INTERFACE_MAP()

 BEGIN_INTERFACE_PART(ObjSafe, IObjectSafety)
  STDMETHOD_(HRESULT, GetInterfaceSafetyOptions) (
            /* [in] */ REFIID riid,
            /* [out] */ DWORD __RPC_FAR *pdwSupportedOptions,
            /* [out] */ DWORD __RPC_FAR *pdwEnabledOptions
  );
       
        STDMETHOD_(HRESULT, SetInterfaceSafetyOptions) (
            /* [in] */ REFIID riid,
            /* [in] */ DWORD dwOptionSetMask,
            /* [in] */ DWORD dwEnabledOptions
  );
 END_INTERFACE_PART(ObjSafe);


 //## ======== Safety Object End

을 복사해 넣습니다. ^^


그리고 CPP파일에



BEGIN_INTERFACE_MAP( CSampleCtrl, COleControl )
 INTERFACE_PART(CSampleCtrl, IID_IObjectSafety, ObjSafe)
END_INTERFACE_MAP()

/////////////////////////////////////////////////////////////////////////////
// IObjectSafety member functions
ULONG FAR EXPORT CSampleCtrl::XObjSafe::AddRef()
{
    METHOD_PROLOGUE(CSampleCtrl, ObjSafe)
    return pThis->ExternalAddRef();
}

ULONG FAR EXPORT CSampleCtrl::XObjSafe::Release()
{
    METHOD_PROLOGUE(CSampleCtrl, ObjSafe)
    return pThis->ExternalRelease();
}

HRESULT FAR EXPORT CSampleCtrl::XObjSafe::QueryInterface(
    REFIID iid, void FAR* FAR* ppvObj)
{
    METHOD_PROLOGUE(CSampleCtrl, ObjSafe)
    return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);
}

const DWORD dwSupportedBits =
  INTERFACESAFE_FOR_UNTRUSTED_CALLER |
  INTERFACESAFE_FOR_UNTRUSTED_DATA;
const DWORD dwNotSupportedBits = ~ dwSupportedBits;


/////////////////////////////////////////////////////////////////////////////
// CAnyTreeCtrl::XObjSafe::GetInterfaceSafetyOptions
// Allows container to query what interfaces are safe for what. We're
// optimizing significantly by ignoring which interface the caller is
// asking for.
HRESULT STDMETHODCALLTYPE
 CSampleCtrl::XObjSafe::GetInterfaceSafetyOptions(
  /* [in] */ REFIID riid,
        /* [out] */ DWORD __RPC_FAR *pdwSupportedOptions,
        /* [out] */ DWORD __RPC_FAR *pdwEnabledOptions)
{
 METHOD_PROLOGUE(CSampleCtrl, ObjSafe)

 HRESULT retval = ResultFromScode(S_OK);

 IUnknown FAR* punkInterface;
 retval = pThis->ExternalQueryInterface(&riid,
     (void * *)&punkInterface);
 if (retval != E_NOINTERFACE) {
  punkInterface->Release();
 }
 
 *pdwSupportedOptions = *pdwEnabledOptions = dwSupportedBits;

 return retval;
}

/////////////////////////////////////////////////////////////////////////////
// CAnyTreeCtrl::XObjSafe::SetInterfaceSafetyOptions
// Since we're always safe, this is a no-brainer--but we do check to make
// sure the interface requested exists and that the options we're asked to
// set exist and are set on (we don't support unsafe mode).
HRESULT STDMETHODCALLTYPE
 CSampleCtrl::XObjSafe::SetInterfaceSafetyOptions(
        /* [in] */ REFIID riid,
        /* [in] */ DWORD dwOptionSetMask,
        /* [in] */ DWORD dwEnabledOptions)
{
    METHOD_PROLOGUE(CSampleCtrl, ObjSafe)
 
 IUnknown FAR* punkInterface;
 pThis->ExternalQueryInterface(&riid, (void * *)&punkInterface);
 if (punkInterface) {
  punkInterface->Release();
 }
 else {
  return ResultFromScode(E_NOINTERFACE);
 }

 if (dwOptionSetMask & dwNotSupportedBits) {
  return ResultFromScode(E_FAIL);
 }
 
 dwEnabledOptions &= dwSupportedBits;
 if ((dwOptionSetMask & dwEnabledOptions) !=
   dwOptionSetMask) {
  return ResultFromScode(E_FAIL);
 }        
 
 return ResultFromScode(S_OK);
}

이 부분을 넣고 컴파일 하면 ^^


이름을 저하고 틀리게 하신분들은 에러가 날겁니다. 그런 분들은 이름 부분만 바꾸어서 해주시면 됩니다.

뭐 이부분도 다음에 다중문서 형식으로 만들때는 클래스로 넘어가겠지만 ^^ 그부분은 먼 훗날이고 ^^

자 그럼 차이가 무엇인가... 컴파일 해서 실행해 보십시요....

아마 당장은 표가 안날겁니다. 저도 한참후에사 알았다는....

자 이걸로 거의 모든 기본은 만들어 졌읍니다. 이 것위에 모든 Actvie-X기능을 넣으면됩니다만...

이걸로 끝날수야 없겄지요 ????

여기에 더 들어가야 할게 있읍니다. 뭘까요 ^^


13) 백스페이스 기능,

14) 이벤트 등록

15) Property등록

16) 함수등록

등이 있을거고 시간이 더 되면 다이얼로그를 추가해서.. SDI방식을 구현 등도 해보고 싶기는 하군요...


이제까지 전주에서 이제 60일 된 제 딸 옆에서 쓰고 있었음다.. 우리딸 무쟈게 이쁩니다. 넘 늦게 첫딸을 보는 관계로 이거....

히히히히 - 잉 계산 미스였어요 ㅠ.ㅠ 왜이러냥 ㅠ.ㅠ

쩝 어제는 완전히 뻣어서 강좌를 못했읍니다..

혹 기다리신분들 한테는 대단히 죄송죄송 히 있으실거 같지 않지만서도 ^^

자 이전까지는 등록 문제를 다뤘읍니다. 뭐 거의 강제로 해라 하는 것이라서 좀 그렇긴 하지만

첫강좌후는 거의 해도 그만 안해도 그만이나 웹에서 사용할때는 한가지 한가지 찾기가 힘든것이라서 적었읍니다.

자 이제 백스페이스를 해보겟읍니다.


13) 백스페이스 기능

자 이게 왜 필요하느냐하면 웹 브라우져에서 백스페이스를 누르면 이전 페이지로 넘어갑니다. 심지어는 active-X에 포커스가 있을 때도 그렇게 되지요. 이 애기는 에디트 박스에서 글을 넣다가 백스페이스를 넣었다 하면 틱하고 뒤로 가는 경우가....

이걸 막기 위해 필요합니다.


자 이걸 하기 위해서는 OnActivateInPlace(TRUE, NULL);   이 함수를 잘 써야 합니다.

이 함수가 경우에 따라 그 작용을 합니다. 뭐 자세한 스펙은 구글에서 참조하시고 ^^

우선  OnCreate에 OnActivateInPlace(TRUE, NULL);를 해줍니다.

이걸로 끝입니다. ^^

간단하지요 근데 이걸로 끝나지는 않습니다.

이제 백스페이스를 했으니 다른 것도 해봐야지요. 이것과 비슷한게 있는데 그게 TAB key, arrow keys, accelerator keys등입니다.

자 이 키들은 우선 Active-X에는 들어오지 않습니다. 물론 백스페이스도 그렇지요

위에 함수로 이게 Active-X로 들어오게 한것인데 문제는 위에걸로 다 해결되는 것이 아닙니다.

자 이제 두번째 처리를 합시다.

이걸 처리하기 위해서는

BOOL m_bUIActive;   // TRUE if currently in uiacitve state

라는 변수를 사용해야 합니다. 영문 설명과 같이 이 변수는 활성화 되었을때 TRUE가 되는 변수이지요

자 그럼 어디서 사용하느냐

 OnMouseActivate에 OnActivateInPlace(TRUE, NULL);를 해줘야 합니다.

아래와 같이요

 if (!m_bUIActive)
  OnActivateInPlace(TRUE, NULL);


 그리고

PreTranslateMessage(MSG* pMsg) 에
 if(pMsg->message == WM_KEYDOWN)
 {
  ::SendMessage(pMsg->hwnd, WM_KEYDOWN, pMsg->wParam, pMsg->lParam);
 }

를 해주셔야 합니다.

^^ 자 그럼 그에대한 소스는 내일이나 ... 자 이제 퇴근퇴근 일도 안되고 죽갔당~~~~~

^^

첨부파일을 올릴까 했는데 그냥 이거 쓰면서 할까 합니다.

자 이제

14) 이벤트 등록

15) Property등록

16) 함수등록

가 남았네요 이번강좌로 전부 마무리 하기를 바라며 ^^

14) 이벤트 등록

이벤트 등록과 Property등록은 의외로 간단합니다. 문제는 변경시 문제인데 이것도 삭제후 다시 만들기 하면 편하긴 해여

근데 하다보면 직접해야 할 경우가 있는데 이부분을 같이 설명하고자 합니다.

이벤트 등록은 우선

     ㄱ) 클래스 위저드에서 activeX Event를 선택합니다.


 ㄴ) AddEvent를 선택하면 이벤트를 추가 할수 있읍니다 자 여기서 설명을 하자면

External Name은 Html에 오픈되는 이벤트 이름입니다. 여기서는 EventTest로 넣었읍니다.

Internal Name은 actvie-x에서 호출하는 이름입니다. 즉 fireEventTest로 호출했을 경우 Html이나 이 ocx를 포함한 APP에 이벤트가 발생하게 EventTest로 발생하게 됩니다.

그리고 세번째인 Parameter List가 문제인데요 이것은 이벤트 호출시에 인자로 컨테이너 즉 Html이나 APP에 넘어가는 인자입니다. 자 왜 이게 문제이냐하면 여기에 보면 BSTR형도 있고 LP형도 있고 즉 C++형이 다수 있지요 ^^

이게 다른 언어에서는 무소용 ㅠ.ㅠ 그래서 이부분은 잘 생각하고 타입을 정하셔야 합니다. 같이 쓸수있는 Variant형이라던가 int형이라던가.... 어디서 사용할것인지에 따라 조금 고민을 해봐야 합니다.


자 이제 이벤트 등록은 끝났읍니다. 그럼 이제 이를 좀 볼까요

여러분이 봐야할 부분은

sampleCtrl.h파일과  CPP파일

sample.odl파일입니다. 이벤트는 외부에 오픈 되는 것이라서 역시 odl에 등록되어 있읍니다.

우선 odl파일을 보시면 중간 부분에

//  Event dispatch interface for CSampleCtrl

[ uuid(9AC5717D-F2EA-49F8-BE5D-8B36C6E97632),
   helpstring("Event interface for Sample Control") ]
 dispinterface _DSampleEvents
 {
  properties:
   //  Event interface has no properties

  methods:
   // NOTE - ClassWizard will maintain event information here.
   //    Use extreme caution when editing this section.
   //{{AFX_ODL_EVENT(CSampleCtrl)
   [id(1)] void EventTest(short nKey);
   //}}AFX_ODL_EVENT
 };

이런식으로 있을 겁니다. ^^ UUID는 당연히 틀리겠지요

여기서 id(1) 이라고 있는데요 이걸 잘 봐두십시요 그리고 이름도 .. 이 이름이 외부에 오픈됩니다.

그리고

sampleCtrl.h을 봅시다..

보시면 밑에 부분에

// Event maps
 //{{AFX_EVENT(CSampleCtrl)
 void FireEventTest(short nKey)
  {FireEvent(eventidEventTest,EVENT_PARAM(VTS_I2), nKey);}
 //}}AFX_EVENT
 DECLARE_EVENT_MAP()

라고 선언된곳이 있읍니다. 여기서   {FireEvent(eventidEventTest,EVENT_PARAM(VTS_I2), nKey);} 이부분 잘 봐두십시요

그리고 밑에  eventidEventTest = 1L

그리고 CPP파일에 보면


BEGIN_EVENT_MAP(CSampleCtrl, COleControl)
 //{{AFX_EVENT_MAP(CSampleCtrl)
 EVENT_CUSTOM("EventTest", FireEventTest, VTS_I2)
 //}}AFX_EVENT_MAP
END_EVENT_MAP()


라고 있을 겁니다. 자 편의 상 각각에 번호를 매깁니당. 맨위것부터 빨간것만 1,2,3으로 간단히 ^^

자 여기서 1의 id를 보시면 eventidEventTest = 1L 과 뭔가가 같읍니다 ^^ 즉 이건 위자드에서 고유로 주는 것이긴 한데 이걸로 바꿀수가 있지요 그리고 2번을 보시면 eventid 하고 함수이름과 1, 3,에서의 함수이름들이 중복으로 나오는 것을 알수있읍니다. 바꿀때 같은 것은 다 같이 바꾸어주셔야 합니다.

그리고 2나 3을 보시면 VTS_12같은게 나오는데... 이게 인자입니다. 즉 파라미터이지요 ^^ 이걸 강제로 바꿀수도 있읍니다.

여러 타입으로 한번 만들어 보십시요

자 이제 HTML 쪽을 봅시다 이벤트를 만들었으면 이걸 사용해봐야 하니까요

음 APP쪽은 OCX를 인클루드하면 자동으로 생성되니 뭐 신경 끄고  HTml 에서는 어떻게 사용하는가

이건 의외로 간단간단

<SCRIPT for="Test" event="EventTest(MSG)" language="javascript">
</SCRIPT>

바로 이렇게 해주면 됩니다. 여기서 for는 ocx를 Object에 쓸때 사용된 ID입니다.

근데 왜 이렇게 하느냐 왜 OCX에서 자바스크립트를 직접호출하지 않느냐라고 하면 (이건 고민을 해보신분만 아는 문제인데) 이벤트 방식이 오류가 날 확률이 무쟈게 적습니다.... 뭐 OCX에서 자바스크립트를 직접 호출도 가능하긴 하지만요

 

자 이제 이벤트 함수는 설명이 끝났읍니다. 더 질문은 따로 하시고 ^^

이런 쓰고 나니 사용법을 설명을 안했군요

사용법은 간단합니다. fireEventTest("ddd");로 ctrl어디서든 호출하면 됩니다 ^^

 

15) Property등록

이벤트를 했기 때문에 이건 무척 쉽습니다.

                          ㄱ) 클래스 위저드에서 Automation을 선택합니다.



                     ㄴ) Add Property를 선택합니다.


자 이제 여기서 설명을 해야 겠군요

 - external Name은 짐작하시겠지만 외부 노출 변수입니다.

 - Type는 이 변수의 타입이 되겠구여

 - variable Name는 내부에서 사용하는 변수입니다.

 - Notification function은 변수의 값이 바뀌었을때 호출되는 함수입니다.

음 이걸로 짐작이 될까요???

자 다시 설명을 하자면 External Name은 Html이나 APP 에서 ocx에 데이타를 직접 넣고 싶을때 ocx에서 오픈 시켜주는 변수가 됩니다. 그리고 그 변수의 타입이 Type에 넣게 되구여 Variable는 ocx내부 즉 CTRL파일에서 외부노출된 변수명으로 들어오는 데이타를 넣어두는 변수의 이름입니다. 그리고 맨 마지막것이 외부에서 변수에 데이타를 넣어줄때 자동으로 호출되는 함수입니다. 자 이것은 변수의 타입을 Member variable로 선택했기 때문에 나오는 형식이구여 이제 Get/Set방식을 선택해 보세요 그부분은 해보시고 스스로 알아가시기를 ^^

자 그럼 소스를 보실까요

보실 부분은 역시 ODL과 sampleCtrl.h와 saplectrl.cpp입니다.

자 ODL파일은 보시면 대충 짐작이 가실거구 h파일에서는 m_propertyTest이 선언된것을 보시면 됩니다.

그리고 밑에 dispidPropertyTest = 1L라는 부분 과

중요한

 //{{AFX_DISPATCH(CSampleCtrl)
 CString m_propertyTest;
 afx_msg void OnPropertyTestChanged();

라는 부분 을 보셔야 합니다. 나중에 이름을 바꿀때 잘 찾아서 바꾸셔야 하거든요

그럼 이제 이를 사용해 봐야 하는데 HTML은 설명할게 없어서 그냥 소스를 올리겠읍니다.

<OBJECT ID="Test" width="600" height="1800" CLASSID="CLSID:CC028E66-85EB-4242-98CA-3260E6F70196">
  <param name="PropertyTest" value="1234">
 </OBJECT>

쩝 별거 없지요

나중에 사용할때 Test.PropertyTest = "ㅅㄷㅈ";

뭐 이렇게 써도 됩니다. 두개가 차이가 있긴 하지만 같이 설명하지요.

자 이제 이것을 ocx에서 받아 들이도록 합시다. 사실 아직은 선언만 되어 있고 이렇게 했을때  ocx에서 데이타를 인식하지는 못합니다.

자 그럼 sampleCTRL.cpp 파일로 가볼까요

ㄱ) 우선 DoPropExchange로 갑니다. 여기에 작업을 해야 하는데

PX_String(pPX, _T("PropertyTest"), m_propertyTest,"Set PropertyTest");

와 같이 해줍니다. 이를 설명하자면 _T()안에 것은 odl안의 이름이구여 저 이름으로 들어올때 m_property로 데이타를 넣어라 고 하는 것이고 Set Property Test는 디폴트 값입니다. 즉 저 변수의 디폴트가 되는 것이지요 자 이게 무슨 짓이냐

이건 <param name="PropertyTest" value="1234"> 했을 경우에 사용하는 것 입니다. 즉 저렇게 했을 경우 DoPropEx--로 들어와서 저기를 타고 변수로 데이타가 들어가구여 만약 html에서 Param선언을 안하면  저 디폴트 값이 변수에 들어가게 됩니다. 근데 이건 Test.PropertyTest = "ㅅㄷㅈ";했을 때는 문제가 틀립니다.. APP에서는 주로 Test.PropertyTest = "ㅅㄷㅈ";게 사용할건데 이건 저렇게 하면 데이타가 들어오지만 들어왔는지를 모르게되거든요


ㄴ) 그럼 Test.PropertyTest = "ㅅㄷㅈ";사용했을때는 어떻게 해야 하느냐

OnPropertyTestChanged() 이 함수를 기억하십니까...

자 여기를 보십시요. 이 함수가 관건입니다. Test.PropertyTest = "ㅅㄷㅈ";를 외부에서 하면 바로 이 함수가 호출됩니다.

이제 처리만 하시면 됩니다.

 

음 제가 마음이 조금 급했나요 얼렁 설렁 설명을 하고 있는 듯한 쩝

이제 마지막을 설명해야 하는 군요

16) 함수등록

이것은 뭐냐 함수만드는 것도 설명하냐 하시는 분도 있겄지만 그냥 함수가 아닙니다. OCX외부에서 호출하는 함수를 애기 하는 것입니다. 그렇다고 특별한 것은 아니구 이것은 Property의 함수버젼이라고 생각하시면 될거 같네요

만드는 것도 Property에서 Add Method로 만듭니다. 안에 보시면 뭐 리턴값 인자등을 설정하게 되어 있구여 ..

일반 함수 만드는 것과 너무 똑같아요

단지 이건 외부에서 호출해서 내부로 넘어오는 OCX에서 외부에 오픈한 클래스 함수정도라고 생각하면 됩니다.

쓰고 보니 별것도 없네요 ^^

 

원래 첨에 이거 뒤에 Dialog나 Sdi로 만드는 ocx를 추가로 할려고 했는데....

뭐 다들 반응도 별로고해서  ^^ 살짝쿵 넘어가는 방향이로 ^^ 히히히


샘플1 다운로드
샘플2 다운로드
샘플3 다운로드

이올린에 북마크하기
No received trackback. / No comment.

Trackback Address :: http://viper150.cafe24.com/trackback/83

You can also say.

Prev 1 ... 216 217 218 219 220 221 222 223 224 ... 298 Next
블로그 이미지
이것저것 불펌금지도 퍼다가 담습니다. 외부에 비공개된 페이지 입니다. By. 어른왕자

카테고리

  • 전체 (298)
    • 사는 이야기 (115)
    • 웹 프로그래밍 (102)
    • App 프로그래밍 (22)
    • IT 뉴스&기타 (22)
    • 박한별 (4)
    • 역사&기타지식 (9)

태그목록

  • 배치
  • 서비스
  • Dialog Base
  • 윈도우7
  • substr
  • 파코즈
  • 고전팝
  • 환상의 커플
  • 공무원
  • 오지호
  • 삼성
  • svn connector
  • 게임의자
  • 자본
  • 울트라에디터
  • 로딩중
  • I Got A Boy
  • 이미지버튼
  • 휴대폰
  • DB2
  • 제이퀴리
  • 커플
  • 과음
  • FilePathCheckerModuleExample.dll
  • sysdate
  • 부부관계
  • 광개토대왕
  • 운동
  • 비사
  • IIS

최근에 올라온 글

  • 보험사의 조정신청 대응방법.
  • 어느 천재의 앞선 시선.
  • [병맛더빙] 누구게..... (1)
  • 韓경제 `회색 코뿔소` 상황...
  • SVN Connector 설치 URL.
  • 군대를 가지 않는 서울대생.
  • “운은 하늘의 귀여움 받는...
  • 목장에서 알바하다가 캐스...
  • [펌]믿고 거르는 관상.
  • 하루에 1세트씩 하면 좋다...

최근에 달린 댓글

  • <p><img src="https://i.imgur... 브레드 01/22
  • <p><img src="https://i.imgur... 브레드 01/22
  • <p><img src="https://i.imgur... 브레드 01/22
  • <p><img src="https://i.imgur... 브레드 01/22
  • <p><img src="https://i.imgur... 브레드 01/22

최근에 받은 트랙백

  • công ty may đồng phục. công ty may đồng phục 01/08
  • Israelnightclub`s recent blo... Israelnightclub`s recent blo.. 01/06
  • Suggested Browsing. Suggested Browsing 01/06
  • similar site. similar site 01/06
  • לאתר הבית שלנו. לאתר הבית שלנו 01/06

글 보관함

  • 2019/03 (1)
  • 2018/12 (1)
  • 2018/09 (1)
  • 2018/08 (1)
  • 2018/02 (1)

달력

«   2021/01   »
일 월 화 수 목 금 토
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31            

링크

  • Total : 262062
  • Today : 49
  • Yesterday : 46
Tattertools
Eolin
rss

어른왕자's blog is powered byTattertools1.1.2.2 : Animato