ActiveX/컨트롤
MFC
jjryu
2008. 12. 16. 01:16
AfxOleInit()
Ole초기화
스레드 마다?
액셀러레이터 키(화살표, 탭 키같은)를 ActiveX 컨트롤 컨테이너의 메시지 펌프가 가로채기 때문에, 컨트롤에 포커스가 있어도 키 메시지를 받지 못한다. MFC 액티브X 컨트롤은 PretranslateMessage 함수를 오버라이드함으로써 이러한 메시지들을 가로챌 수 있다.
그러나, MFC 액티브X 컨트롤의 PreTranslateMessage 함수가 항상 호출되는 것은 아니다.
PreTranslateMessage 함수는 컨트롤의 IOleInPlaceActiveObject 인터페이스의 TranslateAccelerator 메소드가 호출한다. 인터넷 익스플로러는 현재 UI-Active인 컨트롤에 한해서 이 메소드를 호출한다. 한번에 하나의 컨트롤 만이 UI-Active일 수 있다.
인터넷 익스플로러는 페이지가 로드될 때 자동으로 어떠한 컨트롤도 UI-Active하지 않는다. 인터넷 익스플로러는 사용자가 탭키를 눌러 해당 액티브X 컨트롤을 UI-Active할 때까지 기다린다.
COleControlModule -> CWinApp
COleControl -> CWnd
메소드
프로퍼티
이벤트
OnSetClientSite
OnDraw
.DoPropExchange() // virtural - 여기서 사용자 정의 프로퍼티를 파일로 저장한다. // ATL Property Map
1. [MFC ActiveX ControlWizard]를 이용해서 프로젝트를 생성하면 다음과 같은 세개의 클래스가 만들어진다.
COleControlModule( -> CWinApp )
COleControl( -> CWnd )
COleProertyPage( -> CDialog -> CWnd )
2. COleControl::OnDraw()를 수정한다.
3. 인터페이스의 컨텍스트 메뉴([Add Property..])에서 프로퍼티를 추가한다. // or 클래스 위저드의 자동화 탭에서 대상 자동화 클래스(Class name)를 선택
스톡 프로퍼티
사용자 정의 프로퍼티
void CCircleCtrl::DoPropExchange(CPropExchange* pPX)
{
ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
COleControl::DoPropExchange(pPX);
// TODO: Call PX_ functions for each persistent custom property.
if (pPX->GetVersion() == (DWORD)MAKELONG(_wVerMinor, _wVerMajor))
{
PX_Color(pPX, _T("FlashColor"), m_flashColor, RGB(255, 255, 0));
}
}
6. 안전성을 보장하는 clsid를 레지스트리에 등록하는 루틴을 추가 - 클래스 ID에 주의
기존 표준(?) 컨트롤을 서브클래싱하는 경우
모달리스 다이얼로그를 생성
Ole초기화
스레드 마다?
액셀러레이터 키(화살표, 탭 키같은)를 ActiveX 컨트롤 컨테이너의 메시지 펌프가 가로채기 때문에, 컨트롤에 포커스가 있어도 키 메시지를 받지 못한다. MFC 액티브X 컨트롤은 PretranslateMessage 함수를 오버라이드함으로써 이러한 메시지들을 가로챌 수 있다.
그러나, MFC 액티브X 컨트롤의 PreTranslateMessage 함수가 항상 호출되는 것은 아니다.
PreTranslateMessage 함수는 컨트롤의 IOleInPlaceActiveObject 인터페이스의 TranslateAccelerator 메소드가 호출한다. 인터넷 익스플로러는 현재 UI-Active인 컨트롤에 한해서 이 메소드를 호출한다. 한번에 하나의 컨트롤 만이 UI-Active일 수 있다.
인터넷 익스플로러는 페이지가 로드될 때 자동으로 어떠한 컨트롤도 UI-Active하지 않는다. 인터넷 익스플로러는 사용자가 탭키를 눌러 해당 액티브X 컨트롤을 UI-Active할 때까지 기다린다.
COleControlModule -> CWinApp
the server module (that is, the DLL) in which the control is housed
.InitInstance()
.ExitInstance()
.InitInstance()
.ExitInstance()
COleControl -> CWnd
메소드
프로퍼티
이벤트
OnSetClientSite
OnDraw
.DoPropExchange() // virtural - 여기서 사용자 정의 프로퍼티를 파일로 저장한다. // ATL Property Map
<PARAM>
PX_Bool()
PX_Short()
PX_UShort()
PX_Long()
PX_UShort()
PX_Float()
PX_Double()
PX_String()
PX_Color()
PX_Bool()
PX_Short()
PX_UShort()
PX_Long()
PX_UShort()
PX_Float()
PX_Double()
PX_String()
PX_Color()
.Ambient{XXX}
.Fire{XXX}() // 스톡 이벤트
.Fire{XXX}() // 스톡 이벤트
.Get{XXX}() // 스톡 프로퍼티
// 스톡 메소드
// 스톡 메소드
.DoClick()
.Refresh()
.InvalidateControl()
PreTranslateMessag() // virtual
OnLButtonUp // 활성화?
.PX_{XXX}() // 웹스크립트에서 사용자 정의 프로퍼티를 가져온다.(?)
.TranslateColor()
.SelectStockFont()
.GetDC()
.ReleaseDC()
.GetClientRect()
.IsSubclassedControl()
OnOcmCommand
IOleInPlaceActiveObject
CWnd::Invalidate()
.SetModifiedFlag()PreTranslateMessag() // virtual
OnLButtonUp // 활성화?
.PX_{XXX}() // 웹스크립트에서 사용자 정의 프로퍼티를 가져온다.(?)
.TranslateColor()
.SelectStockFont()
.GetDC()
.ReleaseDC()
.GetClientRect()
.IsSubclassedControl()
OnOcmCommand
IOleInPlaceActiveObject
TranslateAccelerator()
PreTranslateMessage()
1. [MFC ActiveX ControlWizard]를 이용해서 프로젝트를 생성하면 다음과 같은 세개의 클래스가 만들어진다.
COleControlModule( -> CWinApp )
COleControl( -> CWnd )
COleProertyPage( -> CDialog -> CWnd )
2. COleControl::OnDraw()를 수정한다.
3. 인터페이스의 컨텍스트 메뉴([Add Property..])에서 프로퍼티를 추가한다. // or 클래스 위저드의 자동화 탭에서 대상 자동화 클래스(Class name)를 선택
스톡 프로퍼티
사용자 정의 프로퍼티
// Dispatch maps
//{{AFX_DISPATCH(CCircleCtrl)
OLE_COLOR m_flashColor;
afx_msg void OnFlashColorChanged();
//}}AFX_DISPATCH
DECLARE_DISPATCH_MAP()
//{{AFX_DISPATCH(CCircleCtrl)
OLE_COLOR m_flashColor;
afx_msg void OnFlashColorChanged();
//}}AFX_DISPATCH
DECLARE_DISPATCH_MAP()
void CCircleCtrl::DoPropExchange(CPropExchange* pPX)
{
ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
COleControl::DoPropExchange(pPX);
// TODO: Call PX_ functions for each persistent custom property.
if (pPX->GetVersion() == (DWORD)MAKELONG(_wVerMinor, _wVerMajor))
{
PX_Color(pPX, _T("FlashColor"), m_flashColor, RGB(255, 255, 0));
}
}
BEGIN_DISPATCH_MAP
DISP_STOCKPROP_{XXX}()
DISP_PROPERTY_NOTIFY(CCircleCtrl, "FlashColor", m_flashColor, OnFlashColorChanged, VT_COLOR)
END_DISPATCH_MAP
3. 프라퍼티 페이지 다이얼로그에서 컨트롤의 멤버변수와 프로퍼티를 연결한다.
4. 인터페이스의 컨텍스트 메뉴([Add Method..])에서 메소드를 추가한다.
스톡 메소드
DISP_STOCKPROP_{XXX}()
DISP_PROPERTY_NOTIFY(CCircleCtrl, "FlashColor", m_flashColor, OnFlashColorChanged, VT_COLOR)
END_DISPATCH_MAP
3. 프라퍼티 페이지 다이얼로그에서 컨트롤의 멤버변수와 프로퍼티를 연결한다.
4. 인터페이스의 컨텍스트 메뉴([Add Method..])에서 메소드를 추가한다.
스톡 메소드
.DoClick()
.Refresh()
.Refresh()
// Dispatch maps
//{{AFX_DISPATCH(CCircleCtrl)
afx_msg void Flash();
//}}AFX_DISPATCH
DECLARE_DISPATCH_MAP()
//{{AFX_DISPATCH(CCircleCtrl)
afx_msg void Flash();
//}}AFX_DISPATCH
DECLARE_DISPATCH_MAP()
BEGIN_DISPATCH_MAP
DISP_FUNCTION(CCircleCtrl, "Flash", Flash, VT_EMPTY, VTS_NONE)
END_DISPATCH_MAP
5. 이벤트 인터페이스의 컨텍스트 메뉴([Add Event..])에서 이벤트를 추가한다.
스톡 이벤트
사용자 정의 이벤트
DISP_FUNCTION(CCircleCtrl, "Flash", Flash, VT_EMPTY, VTS_NONE)
END_DISPATCH_MAP
5. 이벤트 인터페이스의 컨텍스트 메뉴([Add Event..])에서 이벤트를 추가한다.
스톡 이벤트
사용자 정의 이벤트
// Event maps
//{{AFX_EVENT(CCircleCtrl)
void FireClickInside(OLE_XPOS_PIXELS x, OLE_YSIZE_PIXELS y)
{FireEvent(eventidClickInside,EVENT_PARAM(VTS_XPOS_PIXELS VTS_YSIZE_PIXELS), x, y);}
//}}AFX_EVENT
DECLARE_EVENT_MAP()
BEGIN_EVENT_MAP(CCircleCtrl, COleControl)
EVENT_CUSTOM("ClickInside", FireClickInside, VTS_XPOS_PIXELS VTS_YSIZE_PIXELS)
EVENT_STOCK_{XXX}()
END_EVENT_MAP()
//{{AFX_EVENT(CCircleCtrl)
void FireClickInside(OLE_XPOS_PIXELS x, OLE_YSIZE_PIXELS y)
{FireEvent(eventidClickInside,EVENT_PARAM(VTS_XPOS_PIXELS VTS_YSIZE_PIXELS), x, y);}
//}}AFX_EVENT
DECLARE_EVENT_MAP()
BEGIN_EVENT_MAP(CCircleCtrl, COleControl)
EVENT_CUSTOM("ClickInside", FireClickInside, VTS_XPOS_PIXELS VTS_YSIZE_PIXELS)
EVENT_STOCK_{XXX}()
END_EVENT_MAP()
6. 안전성을 보장하는 clsid를 레지스트리에 등록하는 루틴을 추가 - 클래스 ID에 주의
... const GUID CDECL BASED_CODE _ctlid = { .. }; ...
[MFC ActiveX ControlWizard]를 이용해서 프로젝트를 생성시 Step 2에서 서브클래싱할 윈도우 클래스를 선택
폼뷰 사용하기
Style를 Child로 Border를 None로 대화상자를 추가한다.
모달리스 다이얼로그를 생성
or
Base Class를 FormView로 대화상자 클래스를 생성한다.
윈도우 클래스(COleControl)의 WM_CREATE 메시지 핸들러에서 폼뷰 생성
Create() 가상 함수를 오버라이드 한다.
GetClientSite()
참조 사이트:
참조 사이트:
http://rnd.vitzro.com/Language/VisualC/SafityActiveXControl.htm
http://rnd.vitzro.com/Language/VisualC/ActiveXFormView.htm
http://debugjung.tistory.com/entry/%EC%95%A1%ED%8B%B0%EB%B8%8CX-%EC%83%9D%EC%84%B1%EC%97%90%EC%84%9C-%EB%B0%B0%ED%8F%AC%EA%B9%8C%EC%A7%80
http://sincerely.tistory.com/2
http://support.microsoft.com/kb/168777/en-us/
http://rnd.vitzro.com/Language/VisualC/ActiveXFormView.htm
http://debugjung.tistory.com/entry/%EC%95%A1%ED%8B%B0%EB%B8%8CX-%EC%83%9D%EC%84%B1%EC%97%90%EC%84%9C-%EB%B0%B0%ED%8F%AC%EA%B9%8C%EC%A7%80
http://sincerely.tistory.com/2
http://support.microsoft.com/kb/168777/en-us/
http://debugjung.tistory.com/205
http://blog.pages.kr/307
http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=51&MAEULNO=20&no=8187&page=2
http://support.microsoft.com/kb/167158/ko
http://msdn.microsoft.com/en-us/library/6hx27e5c(VS.80,printer).aspx
http://support.microsoft.com/kb/971131/
http://support.microsoft.com/kb/153582/en-us/
http://blog.pages.kr/307
http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=51&MAEULNO=20&no=8187&page=2
http://support.microsoft.com/kb/167158/ko
http://msdn.microsoft.com/en-us/library/6hx27e5c(VS.80,printer).aspx
http://support.microsoft.com/kb/971131/
http://support.microsoft.com/kb/153582/en-us/