레이블이 디지털인 게시물을 표시합니다. 모든 게시물 표시
레이블이 디지털인 게시물을 표시합니다. 모든 게시물 표시

2010년 11월 26일 금요일

에뮬레이터 스킨을 바꾸어보아용~

이클립스에서 보통 기본값으로 나오는 에뮬레이터가 아닌 다른 스킨으로

에뮬레이터를 돌려보는 방법입니다. 매우 간단해요~

어딘가 사이트를 보고 저도 한거 였는데.....기억이 나질 않아 패스하고 간략하게 설명하겠습니다 (__)

안드로이드를 설치하면 설치한 폴더가 어디있는지 아시죠??

저같은 경우는 "   C:\Android   "    <-- 요기에 있어요

폴더에 들어가시면



이런식으로 구성이 되어 있을텐데용  "  Platforms " 라는 곳에 들어갑니다

들어가게되면 아래와 같이 화면이 나옵니다.



현재 자신이 진행하고 있는 프로젝트 버전에 맞게 들어갑니다. 전 android-2.0버전이라 2.0으로 들어갈께용



화면을 보시면 Skins 라고 있지요? 그 화면에 들어가서 제가 올려놓은 압축파일을 풀기만 하면 됩니다.

완전 쉽죠??

그럼 이제 이클립스상에서 세팅하는 방법에 대해 보겠습니다.

이클립스 에뮬레이터 구동하기!!!



이클립스를 구동시키면 핸드폰 모양의 에뮬레이터기를 눌러 새롭게 추가를 합니다.

좌측 팝업창의 New 를 누르면 우측 팝업창이 나오는데


Name     :  여긴 구동하는 에뮬레이터의 이름을 씁니다. (아무거나 상관없어용)

Target    :  여긴 아까 스킨을 넣은 버전을 선택합니다. 전 2.0이었으니 2.0선택

SD Card  :  sd카드선택하기 (각자 해당하는 위치를 지정)

Skin       :  여기서 눌러보면 저처럼 NEXUS-ONE 이라는 영역이 하나 추가가 되어 있을꺼에요 요거 선택

마지막으로 Create AVD를 누르시면 생성이 되실 꺼에요

생성 후 실행해보기



좌측 팝업창에서 생성되어 있는 에뮬레이터를 선택하시고 Start를 누르시면

우측창과 같이 디스플레이 옵션이 나오는데용 보통 Screen Size는 3 Monitor dpi는 80으로

되어 있더라구용 근데 그렇게 하니까 너무 작게 나오는거 같아서 저는 6 에 80 으로 하는데

이건 사용자 취향에 따라 적당히 조절해서 쓰시면 될꺼 같습니다.

별거 없는 내용인데....이미지만 괜히 많아서 스크린 압박이 심하겠는데요 ㅎㅎ

이쁘게 잘 쓰시구용~~

마지막으로 인증샷~!



그림판 실력이라 사진이 후지네용 ㅋㅋ 그래도 깔끔하지용?

아... 가로 세로 바꾸는건  Ctrl+F11 키인거 아시죠?? [이 게시물은 카이로님에 의해 2010-03-22 07:31:48 강좌/학습에서 이동 됨]

2010년 3월 8일 월요일

Dialog를 작업표시줄(task bar)에서 숨기려면

Dialog기반 프로그램을 작업표시줄에서 감추고 싶다면, 간단하게 Window Style을 수정해 주면 된다.

  1. LRESULT CMainDlg::OnInitDialog(  
  2.     UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)  
  3. {  
  4.     ...  
  5.     ModifyStyleEx( WS_EX_APPWINDOW,WS_EX_TOOLWINDOW,0 );  
  6.     return TRUE;  
  7. }  

문제는!!
이렇게 되면 Alt+Tab으로는 이 window를 선택할 수 없다는 점이다. 어쩌다 포커스를 잃게되면, window를 다시 찾기 상당히 귀찮아진다.

두시간의 삽질-_-을 통해 꽁수를 부려봤다. 좀 더 좋은 방법이 있다면 알려주시길~
WTL기반으로 작업했지만, MFC라도 약간만 응용하면 적용할 수 있다. (오히려 더 쉽게)

한줄요약: 작업표시줄에서는 나타나지 않으면서, Alt + Tab을 통해 활성화 되는 Dialog를 만들어 보자.

1. 바보-_- 윈도를 하나 만들자. (MFC라면 CWnd를 쓰면 되므로 이 과정은 생략)

  1. class CInvisibleWnd : public CWindowImpl<CInvisibleWnd >  
  2. {  
  3. public:  
  4.     DECLARE_WND_CLASS(NULL);  
  5.  
  6.     BEGIN_MSG_MAP(CInvisibleWnd)  
  7.     END_MSG_MAP()  
  8. };  

2. WTL이라면 Run함수에서 Dialog를 생성할 것이다. (MFC라면 CWinApp::InitInstance)
이때, Dialog의 부모로 바보윈도를 설정해 준다. 눈치 채셨겠지만, 이 꽁수의 핵심은 Dialog의 부모로 설정한 바보윈도는 화면에 표시되면 안된다는 점이다.

  1. int Run(LPTSTR /*lpstrCmdLine*/ = NULL, int nCmdShow = SW_SHOWDEFAULT)  
  2. {  
  3.     ...  
  4.  
  5.     CInvisibleWnd wndInvisible;  
  6.     wndInvisible.Create( NULL, 0, NULL, WS_OVERLAPPEDWINDOW );  
  7.     CMainDlg dlgMain;  
  8.     if ( dlgMain.Create( wndInvisible ) == NULL )  
  9.     {  
  10.         ATLTRACE(_T("Main dialog creation failed!\n"));  
  11.         return 0;  
  12.     }  
  13.  
  14.     dlgMain.ShowWindow(nCmdShow);  
  15.     int nRet = theLoop.Run();  
  16.     _Module.RemoveMessageLoop();  
  17.  
  18.     if ( wndInvisible.IsWindow() )  
  19.         wndInvisible.DestroyWindow();  
  20.  
  21.  
  22.     return nRet;  
  23. }  

그렇다. 바보 윈도는 화면에 표시되지 않고 있으니 작업표시줄에 나타나지 않지만, 인스턴스가 있으므로 Alt + Tab을 치면 나타난다! 그 인스턴스를 활성화 시켜주면 자식윈도로 등록된 Dialog가 활성되는 원리.
중요한점은, 프로그램 종료 시점에서 바보윈도또한 소멸시켜 줘야 한다는 거!

MFC라면 좀 더 쉽다. CDialog를 생성할때, 바보 윈도를 생성자의 parameter로 넘겨주기만 하면된다.
(물론, 소멸은 신경써줘야 한다.)

  1. BOOL CComaApp::InitInstance()  
  2. {  
  3.     ...  
  4.  
  5.     CWnd wndInvisible;  
  6.     LPCTSTR pstrOwnerClass = AfxRegisterWndClass(0);  
  7.  
  8.     if (!wndInvisible.CreateEx(0,   
  9.                             pstrOwnerClass,   
  10.                             _T(""),  
  11.                             WS_OVERLAPPEDWINDOW ,   
  12.                             CW_USEDEFAULT,  
  13.                             CW_USEDEFAULT,  
  14.                             CW_USEDEFAULT,  
  15.                             CW_USEDEFAULT,  
  16.                             NULL,   
  17.                             0 ))  
  18.     {  
  19.         TRACE(_T("failed to create invisible window"));  
  20.         return FALSE;  
  21.     }  
  22.  
  23.     CMainDlg dlg(&wndInvisible);  
  24.     
  25.     m_pMainWnd = &dlg;  
  26.     dlg.DoModal();  
  27.  
  28.     if (wndInvisible.m_hWnd != NULL)  
  29.         wndInvisible.DestroyWindow();  
  30. }  

3. 이제 OnInitDialog에서 ModifyStyleEx( WS_EX_APPWINDOW,0 ); 해주면 된다.

꽁수 끄읏!

2010년 3월 4일 목요일

com 모듈을 웹에서 사용하는 방법

웹에서 com모듈을 바로 불러쓰는 형태는 바람직한 형태는 아닌거 같지만

ActiveX의 형태를 벗어나고, 크로스 브라우징의 측면에서 보면 꽤 괜찮은 선택인 것 같다..

우선 com모듈을 오류없이 불러 쓸려면 레지스터리 조작이 필수적이다.

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Ext\PreApproved


이 위치에 키값을 저장시키면 된다.


그리고 com모듈을 만들때 IObjectSafety interface를 추가해줘야 한다.
MFC와 ATL 방식이 있는데.. 난 ATL을 쓰므로 MFC는 패스~

 #include <atlctl.h>


class ATL_NO_VTABLE {customclass} :

...

public IObjectSafetyImpl<{customclass},

INTERFACESAFE_FOR_UNTRUSTED_CALLER |

INTERFACESAFE_FOR_UNTRUSTED_DATA>

....


BEGIN_COM_MAP({customclass})

...

COM_INTERFACE_ENTRY(IObjectSafety)

END_COM_MAP()

 이렇게 하면 된다

참!! com project에서 바로 레지스터리에 추가하는 것도 좋은 방법인거 같다.

2009년 12월 1일 화요일

socket error code

10049  요청한 주소는 해당 컨텍스트에서 유효하지 않습니다. 
10050  네트워크를 사용할 수 없기 때문에 소켓 작업을 진행할 수 없습니다. 
10051  연결할 수 없는 네트워크에서 소켓 작업을 시도했습니다. 
10052  해당 작업이 진행되는 동안 오류가 발생하여 연결이 끊겼습니다. 
10053  현재 연결은 사용자의 호스트 시스템의 소프트웨어의 의해 중단되었습니다. 
10054  현재 연결은 원격 호스트에 의해 강제로 끊겼습니다. 
10055  대기열이 또는 버퍼가 부족하여 소켓에서 해당 작업을 진행하지 못했습니다. 
10056  이미 연결된 소켓에서 다른 연결을 요청했습니다. 
10057  소켓이 연결되어 있지 않거나 Sendto 호출을 사용하여 데이터그램 소켓에 보내는 경우에 주소가 제공되지 않아서 데이터를 보내거나 받도록 요청할 수 없습니다. 
10058  해당 소켓이 종료되었으므로 데이터 보내거나 받을 수 없습니다. 
10059  일부 커널 개체에 대한 참조가 너무 많습니다. 
10060  연결된 구성원으로부터 응답이 없어 연결하지 못했거나, 호스트로부터 응답이 없어 연결이 끊어졌습니다. 
10061  대상 컴퓨터에서 연결을 거부했으므로 연결하지 못했습니다. 
10062  이름을 해석할 수 없습니다. 
10063  이름 또는 이름의 구성 요소가 너무 깁니다. 
10064  호스트가 작동하지 않기 때문에 소켓 작업을 진행할 수 없습니다. 
10065  연결할 수 없는 호스트로 소켓 작업을 시도했습니다.

 

소켓관련해서는
1005* ~ 1006* 사이에 주로 에러가 나는데요
10053 에러는  서버에서 연결이 갑자기 끊어졌을때 주로나는 에러입니다.

2009년 11월 24일 화요일

vcproj 파일의 구조?

하나씩 알아가야 할듯하다

 

이유는 Makefile 변환기를 만드는 정도??

 

xml로 되어 있고

 

VisualStudioProject => Configurations => Configuration 의 property에는

 

ConfigurationType{0:메이크파일, 1:응용프로그램, 2:동적라리브러리, 3:, 4:정적라이브러리, 10:유틸리티}

 

Files => Filter => File 태그가 있는데 이것을 Makefile의 OBJS로 잡으면 변환이 가능할 것 같다.

 

 

 

2009년 11월 18일 수요일

platform 별 define

_WIN32 : 윈도우용

 

__GNU_C__ : gcc 컴파일

 

OS별

linux : 리눅스

__OpenBSD__ : openBSD

__FreeBSD__ : FreeBSD

__APPLE__ : 애플

2009년 11월 15일 일요일

__FILEW__ 이 먼가 이상하다..

#include <altstr.h>를 include하고 나니 __FILEW__가 안 나온다..

 

에러가 난다.

2009년 10월 29일 목요일

가끔 디버그 모드에서 디버깅 정보 저장 안할때,

 

또는 exception dump메세지가 안 나올 경우..

 

 

'디버깅 정보를 찾을 수 없거나 정보가 일치하지 않습니다. 이진 파일이 디버그 정보를 사용하여 빌드되지 않았습니다.'

이런 문장을 보거나, 혹은 디버깅은 되는데 지역 변수를 조사하지 못할 때

일단 이렇게 하니깐 제대로 되더라..

구성 속성 -> 링커 -> 디버깅 -> 디버그 정보 생성 : 예(/DEBUG)

구성 속성 -> C/C++ -> 일반 -> 디버깅 정보 형식 -> 편집하며 계속하기를 위한 프로그램 데이터베이스(/ZI)

구성 속성 -> C/C++ -> 최적화 -> 최적화 : 사용 안 함(/Od)

 

 

2009년 10월 28일 수요일

CRegKey 사용 예제

레지스트리 사용예제는 많지만 대부분 API를 이용한 예제인지라 CRegKey 클래스 사용예제를 한번 만들어봤다. 아마 자주 사용하는 예제 중에 하나가 아닐까 싶다. 소스파일도 첨부해둔다.

#include <atlbase.h>

void CCRegKeyExDlg::OnBnClickedButton1()
{
 //DWORD 저장
 CRegKey RegKey;
 
 if(RegKey.Open(HKEY_LOCAL_MACHINE, L"SOFTWARE\\TestProg") == ERROR_SUCCESS) //키가 존재하면
 {
  RegKey.SetDWORDValue(L"DWORD", 1); //DWORD라는 네임으로 "1" 값을 저장.
 
  RegKey.Close(); //오브젝트를 닫는다.
 }
}
void CCRegKeyExDlg::OnBnClickedButton2()
{
 //String 저장
 CRegKey RegKey;
 //if(RegKey.Create(HKEY_LOCAL_MACHINE, L"SOFTWARE\\TestProg") == ERROR_SUCCESS) //(키 생성을 성공하면)키 생성과 동시에 값생성가능.
 if(RegKey.Open(HKEY_LOCAL_MACHINE, L"SOFTWARE\\TestProg") == ERROR_SUCCESS) //키가 존재하면
 {
  RegKey.SetStringValue(L"String", L"C:\\Program Files\\"); //String이라는 네임으로 지정한 문자저장 경로를 저장할때는 역슬레쉬 두개사용.
 
  RegKey.Close();
 }
}
void CCRegKeyExDlg::OnBnClickedButton3()
{
  //DWORD 읽기
 DWORD dwValue;
 DWORD dwSize = 1023;
 
 CRegKey RegKey;
  if(RegKey.Open(HKEY_LOCAL_MACHINE, L"SOFTWARE\\TestProg") == ERROR_SUCCESS) //키가 존재하면
  {
  if(RegKey.QueryDWORDValue(L"DWORD", dwValue) == ERROR_SUCCESS) //값이 존재하면 DWORD안에 데이타를 읽어온다.
  {
   RegKey.Close();//닫는다.
   CString strValue;
   strValue.Format(L"%d", dwValue);
   AfxMessageBox(strValue);
  }
  }
}
void CCRegKeyExDlg::OnBnClickedButton4()
{
  //String 읽기
 CString strValue;
 DWORD dwSize = 1023;
 
 CRegKey RegKey;
  if(RegKey.Open(HKEY_LOCAL_MACHINE, L"SOFTWARE\\TestProg") == ERROR_SUCCESS)
  {
  if(RegKey.QueryStringValue(L"String", strValue.GetBuffer(dwSize), &dwSize) == ERROR_SUCCESS)  //값(String)이 존재하면 GetBuffer를 사용하여 지정된 크기의 버퍼를 읽어온다.
  {
   RegKey.Close();//닫는다.
   strValue.ReleaseBuffer(); //읽어온 버퍼외에 필요없는 바이트를 버린다.
   AfxMessageBox(strValue); //최종적으로 리턴받은 strValue 값을 메시지박스에 출력한다.
  }
  }
}
void CCRegKeyExDlg::OnBnClickedButton5()
{
  //Value 삭제
 CRegKey RegKey;
 
 if(RegKey.Open(HKEY_LOCAL_MACHINE, L"SOFTWARE\\TestProg") == ERROR_SUCCESS)
  {
  RegKey.DeleteValue(L"DWORD");
  RegKey.DeleteValue(L"String");
  RegKey.Close();
 }
 
}
void CCRegKeyExDlg::OnBnClickedButton6()
{
 //Key 삭제
 CRegKey RegKey;
 
 if(RegKey.Open(HKEY_LOCAL_MACHINE, L"SOFTWARE") == ERROR_SUCCESS)
  {
  RegKey.DeleteSubKey(L"TestProg");
  RegKey.Close();
 }
}
void CCRegKeyExDlg::OnBnClickedButton7()
{
 //Key 생성
 CRegKey RegKey;
 
 if(RegKey.Create(HKEY_LOCAL_MACHINE, L"SOFTWARE\\TestProg") == ERROR_SUCCESS) //키 생성을 성공하면
 {
    RegKey.Close();
 }
}

2009년 10월 27일 화요일

VC 각 나라의 언어 코드


각 나라의 언어코드 입니다. 참조하세요..^^

  Language Name      Language ID
  -------------       -----------
                          
  No Language        0x0400
  Albanian            0x041c
  Arabic             0x0401
  Bahasa           0x0421
  Belgian Dutch        0x0813
  Belgian French        0x080c
  Brazilian Portuguese      0x0416
  Bulgarian          0x0402
  Catalan          0x0403
  Croato-Serbian (Latin)     0x041a
  Czech            0x0405
  Danish           0x0406
  Dutch           0x0413
  English (Aus.)         0x0c09
  English (U.K.)         0x0809
  English (U.S.)         0x0409
  Finnish          0x040b
  French           0x040c
  French (Canadian)     0x0c0c
  German           0x0407
  Greek            0x0408
  Hebrew          0x040d
  Hungarian          0x040e
  Icelandic          0x040f
  Italian            0x0410
  Japanese          0x0411
  Korean            0x0412
  Norwegian (Bokmal)     0x0414
  Norwegian (Nynorsk)    0x0814
  Polish           0x0415
  Portuguese          0x0816
  Rhaeto-Romanic         0x0417
  Romanian           0x0418
  Russian           0x0419
  Serbo-Croatian (Cyrillic)    0x081a
  Simplified Chinese      0x0804
  Slovak           0x041b
  Spanish (Castilian)     0x040a
  Spanish (Mexican)     0x080a
  Swedish          0x041d
  Swiss French         0x100c
  Swiss German        0x0807
  Swiss Italian        0x0810
  Thai            0x041e
  Traditional Chinese     0x0404
  Turkish          0x041f
  Urdu            0x0420

2009년 10월 25일 일요일

응용프로그램의 이벤트 로그 깔끔하게 저장하기

윈도즈의 서비스 프로그램에서 서비스 프로그램의 상태를 표시하는 방법으로 이벤트 로깅이 애용됩지요.

HANDLE hEventSource = RegisterEventSource(NULL, GetEventSource());

ReportEvent(hEventSource, EVENTLOG_INFORMATION_TYPE, 0, GS_INFO_GENERAL, NULL, 2, 0, lpszStrings, NULL);
DeregisterEventSource(hEventSource);

그런데, 이렇게만 호출한 후 이벤트 표시기를 통해 이벤트를 보면 지저분한 메시지들이 실제 메시지 앞에 표시됩니다.

The description for Event ID ( 258 ) in Source ( gsService ) cannot be found. The local computer may not have the necessary registry information or message DLL files to display messages from a remote computer. You may be able to use the /AUXSOURCE= flag to retrieve this description; see Help and Support for details. The following information is part of the event: GS Service Report: , Java Process started: Process Handle=0x7c, Process Id=3504.

RegisterEventSource에 사용한 이벤트명이 이벤트 소스로 등록되어 있지 않아서 생기는 문제인데, 이문제를 해결하기 위한 절차가 절차를 알아봅시다.

 

1. 메시지 파일의 생성

; // ***** GSMsg.mc *****
; // This is the header section.

SeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS
    Informational=0x1:STATUS_SEVERITY_INFORMATIONAL
    Warning=0x2:STATUS_SEVERITY_WARNING
    Error=0x3:STATUS_SEVERITY_ERROR
    )

FacilityNames=(System=0x0:FACILITY_SYSTEM
    Runtime=0x2:FACILITY_RUNTIME
    Stubs=0x3:FACILITY_STUBS
    Io=0x4:FACILITY_IO_ERROR_CODE
)

LanguageNames=(English=0x409:MSG00409)
;LanguageNames=(Korean=0x412:MSG00412)

; // The following are message definitions.
MessageIdTypedef=DWORD

MessageId=0x101
Severity=Error
Facility=Runtime
SymbolicName=GS_ERROR_GENERAL
Language=English
General Error: %1 %2

.

 

MessageId=0x102
Severity=Informational
Facility=Runtime
SymbolicName=GS_INFO_GENERAL
Language=English
Information: %1 %2
.

2. 메시지 파일을 메시지 컴파일러(mc)로 컴파일

mc -h $(InputDir) -r $(InputDir) $(InputPath)

-h dir: 헤더파일 출력폴더 지정
-r dir: 리소스파일 출력폴더 지정

-u: 메시지 파일이 유니코드 파일

-U: 출력 .bin파일을 유니코드 파일로 지정

이렇게 하면 GSMsg.h, GSMsg.rc, 그리고 MSG00409.bin (MSG00412.bin) 파일이 생성됩니다. 생성된 파일은 일반 헤더와 리소스처럼 VC 프로젝트에 추가해 컴파일 해줍니다. 그러면 생성된 EXE나 DLL에 메시지 정보가 포함됩니다.

 

3. 메시지 소스를 레지스트리에 등록

   메시지를 실행파일에 포함했으면, 이제 그 정보를 이벤트표시기에 그 정보를 알려줘야 하는데, 윈도즈의 레지스트리가 이용됩니다.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application\EventSourceName

EventMessageFile(REG_EXPAND_SZ): C:\Program Files\gsservice\GSService.exe

TypesSupported(REG_DWORD): 7 (EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE)

좀 번거롭나요? 그래도 완성도를 높이려면 좀 수고를 해야겠죠. 그러면 이벤트 메시지가 깔끔해집니다.

Information: GS Service Report:  Java Process started: Process Handle=0x7c, Process Id=3504

자바 프로그램을 윈도즈 서비스로 만들기에 첨부된 소스의 프로젝트 파일에는 메시지컴파일과 리소스컴파일과정이 포함되어 있습니다.

2009년 10월 15일 목요일

HttpAddRequestHeaders에 cookie값을 구울때 주의사항

HttpAddRequestHeaders에 cookie값을 넣을때 일반적으로 안되는 상황이 벌어진다..

 

그럴때

 

HttpOpenRequest에서 INTERNET_FALG_NO_COOKIES 옵션을 넣으면 바로 구울 수 있다.

 

 

 

2009년 10월 14일 수요일

DWebBrowserEvent2 처리하기


#include <exdispid.h>

#define _TBROWSER_NID_ 1

// Define the sWeb events to be handled:

static _ATL_FUNC_INFO StatusTextChangeInfo = {CC_STDCALL, VT_EMPTY, 1, {VT_BSTR}};
static _ATL_FUNC_INFO WindowResizeInfo = { CC_STDCALL, VT_EMPTY, 2, {VT_I4, VT_I4} };
static _ATL_FUNC_INFO DownloadBeginInfo = {CC_STDCALL, VT_EMPTY, 0, {NULL}};
static _ATL_FUNC_INFO WindowClosingInfo = { CC_STDCALL, VT_EMPTY, 2, { VT_BOOL, VT_BOOL } };
static _ATL_FUNC_INFO NewWindow2Info = {CC_STDCALL, VT_EMPTY, 2, {VT_BYREF|VT_BOOL,VT_BYREF|VT_DISPATCH}};
static _ATL_FUNC_INFO CommandStateChangeInfo = {CC_STDCALL, VT_EMPTY, 2, {VT_I4,VT_BOOL}};
static _ATL_FUNC_INFO BeforeNavigate2Info = {CC_STDCALL, VT_EMPTY, 7, {VT_DISPATCH,VT_BYREF|VT_VARIANT,VT_BYREF|VT_VARIANT,VT_BYREF|VT_VARIANT,VT_BYREF|VT_VARIANT,VT_BYREF|VT_VARIANT,VT_BYREF|VT_BOOL}};
static _ATL_FUNC_INFO ProgressChangeInfo = {CC_STDCALL, VT_EMPTY, 2, {VT_I4,VT_I4}};
static _ATL_FUNC_INFO NavigateComlete2Info = {CC_STDCALL, VT_EMPTY, 2, {VT_DISPATCH, VT_BYREF|VT_VARIANT}};
static _ATL_FUNC_INFO OnVisibleInfo = {CC_STDCALL, VT_EMPTY, 1, {VT_BOOL}};

 

template <class T/*, _ATL_FUNC_INFO* info*/>
class TBrowserEvents : public IDispEventSimpleImpl<_TBROWSER_NID_, TBrowserEvents<T>, &DIID_DWebBrowserEvents2>
{
protected:
 IWebBrowser2* mWebBrowser;
 BOOL     mInitial;
 //DECLARE_DYNCREATE( TBrowserEvents<T> )

 //DECLARE_EVENTSINK_MAP()

 void OnWindowClosing( BOOL bIsChildWindow, BOOL* pbCancel );

public:


 BEGIN_SINK_MAP(TBrowserEvents)

  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, 102, __StatusTextChange, &StatusTextChangeInfo)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, 108, __ProgressChange, &ProgressChangeInfo)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, DISPID_WINDOWRESIZE, __WindowResize, &ProgressChangeInfo)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, 105, __CommandStateChange, &CommandStateChangeInfo)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, 106, __DownloadBegin, &DownloadBeginInfo)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, 104, __DownloadComplete, &DownloadBeginInfo)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, 113, __TitleChange, &StatusTextChangeInfo)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, 252, __NavigateComplete2, &NavigateComlete2Info)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, 250, __BeforeNavigate2, &BeforeNavigate2Info)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, 112, __PropertyChange, &StatusTextChangeInfo)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, DISPID_NEWWINDOW2,/* 251,*/ __NewWindow2, &NewWindow2Info)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, 259, __DocumentComplete, &NavigateComlete2Info)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, DISPID_ONQUIT, __OnQuit, &DownloadBeginInfo)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, 254, __OnVisible, &OnVisibleInfo)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, 255, __OnToolBar, &OnVisibleInfo)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, 256, __OnMenuBar, &OnVisibleInfo)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, 257, __OnStatusBar, &OnVisibleInfo)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, 258, __OnFullScreen, &OnVisibleInfo)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, 260, __OnTheaterMode, &OnVisibleInfo)
  SINK_ENTRY_INFO(_TBROWSER_NID_, DIID_DWebBrowserEvents2, DISPID_WINDOWCLOSING, __OnWindowClosing, &WindowClosingInfo)
  SINK_ENTRY_EX( _TBROWSER_NID_, DIID_DWebBrowserEvents2, DISPID_QUIT, __Quit)

  END_SINK_MAP()

 T* mOwner;

 TBrowserEvents(T* Owner, IWebBrowser2* pWebBrowser)
 {
  initialize( Owner, pWebBrowser );
 }

 TBrowserEvents()
 {
 }

 void initialize( T* Owner, IWebBrowser2* pWebBrowser )
 {
  mWebBrowser = pWebBrowser;
  DispEventAdvise( dynamic_cast<IUnknown*>(mWebBrowser) );
  mInitial = TRUE;
  mOwner = Owner;
 }

 ~TBrowserEvents(void)
 {
  DispEventUnadvise( dynamic_cast<IUnknown*>(mWebBrowser) );
 }

 void __stdcall __StatusTextChange(/*[in]*/ BSTR bstrText) {  }

 void __stdcall __ProgressChange(/*[in]*/ long progress, /*[in]*/ long progressMax) {  }

 void __stdcall __WindowResize(/*[in]*/ long progress, /*[in]*/ long progressMax) {  }

 void __stdcall __CommandStateChange(/*[in]*/ long Command, /*[in]*/ VARIANT_BOOL Enable) {  }

 void __stdcall __DownloadBegin() {  }

  void __stdcall __DownloadComplete() {  }

 void __stdcall __TitleChange(/*[in]*/ BSTR bstrText) {  }

 void __stdcall __NavigateComplete2(/*[in]*/ IDispatch* pDisp, /*[in]*/ VARIANT* URL) {  }

 void __stdcall __BeforeNavigate2(/*[in]*/ IDispatch* pDisp, /*[in]*/ VARIANT* URL, /*[in]*/ VARIANT* Flags,
  /*[in]*/ VARIANT* TargetFrameName, /*[in]*/ VARIANT* PostData, /*[in]*/ VARIANT* Headers,
  /*[out]*/ VARIANT_BOOL* Cancel) {  }

 void __stdcall __PropertyChange(/*[in]*/ BSTR bstrProperty) {  }

 void __stdcall __NewWindow2(/*[out]*/ IDispatch** ppDisp, /*[out]*/ VARIANT_BOOL* Cancel) {  }

  void __stdcall __DocumentComplete(/*[in]*/ IDispatch* pDisp, /*[in]*/ VARIANT* URL) {  }

 void __stdcall __OnQuit() {  }

 void __stdcall __Quit() {  }

 //void __stdcall __OnWindowClosing() { }

 void __stdcall __OnVisible(/*[in]*/ VARIANT_BOOL Visible) { }

 void __stdcall __OnToolBar(/*[in]*/ VARIANT_BOOL ToolBar) { }

 void __stdcall __OnMenuBar(/*[in]*/ VARIANT_BOOL MenuBar) {  }

 void __stdcall __OnStatusBar(/*[in]*/ VARIANT_BOOL StatusBar) {  }

 void __stdcall __OnFullScreen(/*[in]*/ VARIANT_BOOL FullScreen) {  }

 void __stdcall __OnTheaterMode(/*[in]*/ VARIANT_BOOL TheaterMode) {  }

 void __stdcall __OnWindowClosing( VARIANT_BOOL IsChildWindow, VARIANT_BOOL* Cancel ) {  }


};

 

 

아공 만타..

 

함수 인자가 틀리면 에러 난다..

 

적용은 이런 식으로

TBrowserEvents<CMainDlg>* mEvent;

mEvent = new TBrowserEvents<CMainDlg>(this, pWB2);

 

pWB2 는 IWebBrowser2임..

 

이벤트 처리는 이런 식으로

 

void TBrowserEvents<CMainDlg>::__DocumentComplete(/*[in]*/ IDispatch* pDisp, /*[in]*/ VARIANT* URL)
{
 //< @ summary : 로그인 처리하는 부분을 넣어야 함..
 mOwner->documentCmpl(  );
}

void TBrowserEvents<CMainDlg>::__NewWindow2(/*[out]*/ IDispatch** ppDisp, /*[out]*/ VARIANT_BOOL* Cancel)
{
  mOwner->popup( ppDisp, Cancel );
}

IWebBrowser2 ctrl 동적 생성

CComQIPtr<IWebBrowser2> pWB2;

WebRenderCtrl mRender; // 웹 콘트롤 상속체 ( class WebRenderCtrl : public CWindowImpl<WebRenderCtrl, CAxWindow>

 

...

 

CComPtr<IUnkown> punkCtrl;

mRender.Create( m_hWnd, 0, 0, WS_CHILD|WS_VISIBLE, 0, 31011 );

mRender.CreateControlEx( _T("Shell.Explorer"), NULL, NULL, &punkCtrl );
pWB2 = punkCtrl;

 

이렇게 하면 동적으로 생성된다..