천객만래 [千客萬來] (It has an interminable succession of visitors)

'vc++'에 해당되는 글 97건

  1. 2017.11.03 [개발/VC++] error C3861: '_bstr_t' : 식별자를 찾을 수 없습니다.
  2. 2016.02.04 [개발/VC++/MFC] CString ↔ char 변환
  3. 2016.02.04 [개발/VC++] CreateProcess 함수 예제 소스코드
  4. 2015.12.17 [개발/VC++] 익스플로러에서 새창이 생성될때 그 창의 포인터를 얻는 방법
  5. 2015.10.08 [개발/VC++] IE 보호 모드에서 비보호 모드 프로세스 실행
  6. 2015.10.08 [개발/VC++] UTF8Decoding, UTF8Encoding
  7. 2015.10.08 [개발/VC++] MultibyteToUTF8, UTF8ToMultibyte
  8. 2015.10.07 [개발/VC++] API를 이용한 ASCII와 UNICODE변환및 코드페이지를 이용한 변환방법
  9. 2015.10.07 [개발/VC++] URLEncode, URLDecode, 유니코드 변환 소스
  10. 2015.10.07 [개발/VC++] URLEncode, URLDecode, UTF8 변환 소스
  11. 2015.01.22 [개발/VC++] WebBrowser Control 이벤트 연결 - C++
  12. 2015.01.15 [개발/VC++] SubClassing 하는 방법
  13. 2015.01.15 [개발/VC] IE 서브클래싱(subclass)
  14. 2014.12.06 [개발/ATL] BHO 만들기에서 ATL 단순개체 마법사 옵션 설정화면
  15. 2014.10.10 [개발/VC++] Visual C++에 관련된 유용한 코드 팁
  16. 2014.09.10 [개발/VC++] 응용 프로그램 구성이 올바르지 않기 때문에 ...
  17. 2014.02.04 [개발/VC++] WebBrowser HTML Element Events 핸들링
  18. 2014.02.04 [개발/VC++] CreateThread(), _beginthread(), _beginthreadex() 에 관하여
  19. 2013.03.20 [개발/VC++] MFC 관리자권한 외부 프로세스 실행을 위한 소스
  20. 2013.03.20 [개발/VC++] 실행중인 IE의 URL 구하기

[개발/VC++] error C3861: '_bstr_t' : 식별자를 찾을 수 없습니다.




_bstr_t 데이터 타입을 사용하면 다음과 같은 컴파일 에러에 직면할 수 있다.

error C3861: '_bstr_t' : 식별자를 찾을 수 없습니다.
or
error C3861: '_bstr_t' : undeclared identifier

이 경우 다음과 같이 헤더를 인클루드시켜주면 된다.

#include <comutil.h>

위의 include만 추가하면 다음과 같은 링크 에러가 나오는데

xxx.obj : error LNK2019: unresolved external symbol "void __stdcall _com_issue_error(long)" (?_com_issue_error@@YGXJ@Z) referenced in function "public: __thiscall _bstr_t::_bstr_t(wchar_t const *)" (??0_bstr_t@@QAE@PB_W@Z)

이 경우 다음과 같이 설정을 변경해줌으로써 해결할 수 있다.

#pragma comment(lib, "comsuppw.lib")
#include <comutil.h>

거나

Properties -> Configuration Properties -> Linker -> Input -> Additional Dependencies

Debug 모드 시 다음을 추가한다.
comsuppwd.lib
Release 모드 시 다음을 추가한다.
comsuppw.lib

Posted by SB패밀리

CString ↔ char 변환




1. CString을 char으로 변환
CString csTest;
csTest = "I Love You";
char* cTest = LPSTR(LPCTSTR(csTest));
 
2. char을 CString으로 변환
char cTest[10] = "I Love You";
CString csTest;
csTest.Format("%s", cTest);

출처 : http://blog.daum.net/sjdody/5693925



Posted by SB패밀리

CreateProcess 함수 예제 소스코드





/*
 * 출처 : 
http://sosal.tistory.com/
 * made by so_Sal
 */


CreateProcess 라는 함수를 이용하여
Notepad를 실행시키는 간단한 소스입니다.
이해가 가지 않는 부분이 있다면
아래 링크를 참조하세요.
LINK_

====================== CreateProcess ======================

#include<stdio.h>
#include<windows.h>
#include<tchar.h>

#define DIR_LEN BUFSIZ
//BUFSIZ는 운영체제마다 다른 크기를 가지고 있습니다.
//한번 크기를 출력해보시는것도 좋겠네요.

int _tmain(int argc, TCHAR* argv[]){
 STARTUPINFO si = {0,};    //구조체 선언, 초기화
 PROCESS_INFORMATION pi;
 
 si.cb = sizeof(si);
 si.dwFlags = STARTF_USEPOSITION | STARTF_USESIZE;
 //Flags 값들이 여러가지가 있습니다.
 //STARTF_USEPOSITION :: dwX, dwY 위치 사용
 //STARTF_USESIZE     :: dwXSize, dwYSize 사용
 //Flags 값이 주어지지 않는 si구조체 값은
 //새로 만들어지는 프로세스에 영향을 주지 않습니다.
 si.dwX = 100;
 si.dwY = 100;
 si.dwXSize = 300;
 si.dwYSize = 300;  //dw ~ 는 사실 잘 쓰이지 않습니다.

 si.lpTitle = _T(" Child process! ");
 
 TCHAR command[] = _T("notepad 10 10");
 //10 10은 argv[]로 들어가겠죠, 아래 결과를 보시면
 //notepad의 이름으로 들어간다는걸 확인하실 수 있습니다.

 BOOL state;

 state = CreateProcess(
  NULL, //여기에 이름을 넣을 수 있습니다.
  command, // 경로를 System에 해줬기 때문에 notepad가 열릴 수 있죠!
  NULL,NULL, 
  TRUE, //부모프로세스중 상속가능한 핸들 상속
  CREATE_NEW_CONSOLE, //dwCreationFlags
  NULL,NULL,
  &si, //STARTUPINFO 구조체 정보를 위에서 만들어줬죠.
  &pi  //이젠 프로세스의 정보를 가져올때 이 구조체를 사용!
 );

 if(state!=0){
  _fputts(_T("Creation OK! \n"), stdout);
 }
 else{
  _fputts(_T("Creation Fail! \n"), stdout);
 }

 return 0;
}


=======================================================================================


프로세스 :: 시스템 자원들을 포함하는 하나의 주소공간

프로세스는 프로그램 코드, 자료, 변수들, 열린 파일들,
그리고 환경으로 구성됩니다.
하드 메모리에 저장되어 있는 프로그램을 시스템 메모리에 끌어와
하드메모리에 존재하는 하나의 복사본만 존재할 수 있도록
프로그램 코드와 시스템 라이브러리들을 여러 프로세스들이 공유하게 합니다.
더 자세한 내용은 이전에 쓴 '04. Windows 프로세스' 글을 참조하시고
여기서는 프로세스 생성 함수에 대해서 설명하겠습니다.
(프로세스가 새로운 프로세스를 실행시키는것)


프로세스의 생성

하나의 프로세스가 새로운 프로세스를 만든다면,(CreateProcess)
원래의 프로세스는 부모 프로세스라고 하고,
새로 만들어진 프로세스는 자식 프로세스라고 합니다.

그렇다면, 이것은 바탕화면에서 프로그램을 더블클릭하여
생성한 프로세스와 다른것인가?
아닙니다. 바탕화면을 보여주는것도 프로세스입니다.
바탕화면 관리자에서 보여지는 프로그램을 실행시킨다면 (더블클릭)
바탕화면 관리자는 부모프로세스, 실행된 프로세스는 자식 프로세스가 됩니다.
ㅇㅋ?



** :: CreateProcess :: **
MSDN :: 
http://msdn.microsoft.com/en-us/library/ms682425(VS.85).aspx ::
BOOL CreateProcess(
    LPCTSTR lpApplicationName,
             //생성될 프로세스의 이름 (NULL을 넣고 IpCommandLine로 전달 가능)
     
LPTSTR lpCommandLine,
        
   //argc. argv[] 인자로 전달할 문자 매개변수. 표준 검색 경로를 기준으로 찾는다.
     LPSECURITY_ATTRIBUTES lpProcessAttributes, //보안 속성을 지정하는 인자. 보통 NULL
     LPSECURITY_ATTRIBUTES lpThreadAttributes,
                           //쓰레드의 보안 속성 지정. NULL 입력시 기본 보안 속성지정
     BOOL bInheritHandles, // TRUE ::부모 프로세스가 소유하는 상속 가능한 핸들을 상속한다.
     DWORD dwCreationFlags, // 프로세스의 특성을 결정짓는 옵션. 사용 안할경우 0 입력
     LPVOID lpEnvironment, //환경변수 지정. NULL 전달시 부모는 자식에게 환경변수 복사
     LPCTSTR lpCurrentDirectory, //생성하는 프로세스의 현재 디렉터리 NULL시 자식위치 = 부모위치
     LPSTARTUPINFO lpStartupInfo, //STARTUPINFO 구조체 변수 초기화후 변수의 포인터를
               //매개변수 로 전달. STARTUPINFO 구조체 변수들은 프로세스의 속성 정보를 전달한다.
     
LPPROCESS_INFORMATION lpProcessInformation
            
//생성하는 프로세스의 정보를 얻기 위한 매개변수.
               //PROCESS_INFORMATION 구조체 변수의 주소값을 받음
);

9번째 인자 LPSTARTUPINFO 에 정보를 저장하여
CreateProcess를 통하여 프로세스를 생성합니다.
그럼 프로세스의 정보를 다시 가져올때는?
LPPROCESS_INFORMATION을 통해 가져오게 됩니다.

아.. 그런데 위에 CreateProcess 함수 하나에 매개변수가 10개고..
미친듯이 외워야 할거같고,.. 답답..합니다.
저거 다 외워서 쓰는사람... 아무도 없습니다.
공부할때 한번쯤 훑어주고..
중요하게 굵게 써놓은거 정도만 자세히 봐주고...
넘어갑시다!!!!
아주 많이 사용되는 함수도 아닐 뿐더러
책을 보던가 인터넷 조금만 뒤져봐도
상당히 자세히 나와있고, 예제도 널려있으니
그거 보고 프로그래밍 하시면 됩니다!

위 함수를 실행하면 새로운 프로세스가 생성되는데..
프로그램이 부모 프로세스가 되고, 프로그램 안에서 함수에 의해 새로 생성된 프로세스는
자식 프로세스라고 말합니다.

CreateProcess의 첫번째로 전달되는 인자를 통해서 실행파일의 이름이 전달하는 경우에는
현재 디렉터리를 기준으로 실행파일을 찾게 된다.
하지만 두번째 인자로 (첫번째에 NULL을 넣고) 전달되는 경우에는
표준 검색경로 순서대로 실행파일을 찾는다.

1.프로세스의 실행파일이 존재하는 풀더
2.실행중인 프로세스의 현재 풀더
3.windows의 시스템 풀더(system Directory)
4.windows풀더 (windows directory)
5.환경변수 PATH


함수 매개변수의 9번째 매개변수를 보면 STARTUPINFO 라는 구조체가 있다고 나오는데,
그 구조체에 대해서 살펴봅시답!
이것은 새롭게 생성할 프로세스에 정보를 입력하기 위한 구조체입니다.

LPSTARTUPINFO의 구조이다.
MSDN :: 
http://msdn.microsoft.com/en-us/library/ms686331(VS.85).aspx ::

typedef struct _STARTUPINFO {
  DWORD  cb;                           //구조체 변수 크기
  LPTSTR lpReserved;
  LPTSTR lpDesktop;
  LPTSTR lpTitle;                      // 타이틀 바 제목
  DWORD  dwX;                        // 시작될 프로세스 윈도우의 x좌표
  DWORD  dwY;                        // 시작될 프로세스 윈도우의 y좌표
  DWORD  dwXSize;                  // 윈도우의 가로길이
  DWORD  dwYSize;                  // 윈도우의 세로길이
  DWORD  dwXCountChars;
  DWORD  dwYCountChars;
  DWORD  dwFillAttribute;
  DWORD  dwFlags;                   // 설정된 멤버의 정보
  WORD   wShowWindow;
  WORD   cbReserved2;
  LPBYTE lpReserved2;
  HANDLE hStdInput;           // 이 글에서는 CreateProcess에 대해서
  HANDLE hStdOutput;         // 적당히 살펴보는 취지라..
  HANDLE hStdError;           // 핸들에 대한 내용은 넘기겠습니다.
} STARTUPINFO, *LPSTARTUPINFO;

첫번째 인자 DWORD cb가 중요한 이유는
CreateProcess 함수에서 9번째에 들어갈 프로세스 정보 구조체에 들어가는 구조체가
혹시나 다음에 바뀔 수도 있고, 다양한 구조체가 들어갈 수 있게 하기 위해서 둔것인데,
즉 정보를 전달하는 구조체가 무엇인지 구분짓겠다는 의도라고 생각하시면 되겠네요.


Posted by SB패밀리

익스플로러에서 새창이 생성될때 그 창의 포인터를 얻는 방법






익스플로러에서 새창이 생성되면 Newwindow2이벤트가 일어납니다. 새로 생성된 익스플로러창의 포인터를 얻는 방법이 있나요? 
제가 만든 브라우저가 포함된 다이얼로그 폼으로 Set하면 됩니다. 그러나 일반적으로 생성되는 새창의 포인터를 얻고 싶습니다. 즉, IWebBrowser2의 포인터를 얻고 싶습니다. 그 이유는 현재창에 이벤트를 sink시키고 새로운 창이 생기면 그 창도 이벤트를 sink시키려고 하는데 새로운 창의 IWebBrowser2포인터를 얻어 올 수가 없어요.. 
그래서, 브라우저 인스턴스를 만들고 그 브라우저의 IWebBrowser2포인터의 Get_Application()함수를 이용하여 ppDisp에 넘겼는데 새로운창도 뜨고, 인스턴스로 생성한 창도 떠서 두개가 뜨게 됩니다. 
다음은 브라우저컨트롤이 포함된 다이얼로그의 예제입니다.

void CMyIETestDlg::OnNewWindow2Explorer(LPDISPATCH FAR* ppDisp, BOOL FAR* Cancel) 

 // TODO: Add your control notification handler code here 
 CMyIETestDlg *m_dlgNewWB = new CMyIETestDlg; 
 m_dlgNewWB->Create(IDD_MYIETEST_DIALOG); 
 *ppDisp = m_dlgNewWB->m_pIE.GetApplication(); 
}

위와 같이 자기가 만든 다이얼로그폼안의 웹브라우저의 포인터를 ppDisp에 넘겨주면 되는데.. 다음과 같이 하면 되지 않아요.. 좋은 방법이 있으면 알려주세요.

void CMyIETestDlg::OnNewWindow2Explorer(LPDISPATCH FAR* ppDisp, BOOL FAR* Cancel) 

 IWebBrowser2 *m_pIE=NULL; 
 HRESULT hr = CoCreateInstance(CLSID_InternetExplorer, NULL, CLSCTX_LOCAL_SERVER, IID_IWebBrowser2, (void**)&m_pIE); 
 m_pIE->get_Application (ppDisp); 
}


void CMyIETestDlg::OnNewWindow2Explorer(LPDISPATCH FAR* ppDisp, BOOL FAR* Cancel)
{
 IWebBrowser2 *m_pIE=NULL;
 HRESULT hr = CoCreateInstance(CLSID_InternetExplorer, NULL,
 CLSCTX_LOCAL_SERVER, IID_IWebBrowser2, (void**)&m_pIE);
 m_pIE->get_Application (ppDisp);
}

여기에서 LPDISPATCH FAR* ppDisp 로 넘어온 포인터가 새로운
웹브라우져의 IDispatch 인터페이스 포인터를 받는 포인터입니다.
즉, 원하시는 포인터가 해당 파라미터로 넘어오고 이때 이벤트를
싱크시키면 됩니다.


출처 : 인터넷

Posted by SB패밀리

[개발/VC++] IE 보호 모드에서 비보호 모드 프로세스 실행




IE 보호 모드에서 비보호 모드 프로세스 실행


UAC 환경(Windows Vista, Windows 7)의 IE7, IE8 보호모드에서 동작하는 ActiveX에서 실행 파일을 실행할 경우(브로커 프로세스) 비보호 모드로 열린다는 보안 경고창이 나온다.
이 문제를 해결하려면 아래와 같이 자동 권한 상승 정책을 레지스트리에 등록해주어야 한다. {347DAD60-9849-4921-89B6-16FA1B7936CC}는 임의의 GUID값이다.

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Low Rights\ElevationPolicy\{347DAD60-9849-4921-89B6-16FA1B7936CC}]
"AppName"="실행 파일명"
"AppPath"="실행 파일 위치(디렉토리)"
"Policy"=dword:00000003

또 다른 문제는 이 자동 권한 상승 정책을 IE 프로세스가 아닌 외부에서 추가하는 경우 ieuser.exe(IE7), iexplore.exe(IE8)에서 권한 상승 정책을 캐싱하고 있기 때문에 바로 적용이 안 된다는 것이다. ieuser.exe나 iexplore.exe 프로세스를 종료해야만 적용할 수 있다. 하지만 설치 과정에서 프로세스를 종료하는 것은 부담스러운 일이다.

이 문제를 해결하기 위해서 2007년 6월에 배포된 IE 보안 업데이트에 아래와 같은 새로운 API가 추가되었다.

HRESULT IERefreshElevationPolicy(VOID);

자동 권한 상승 정책을 레지스트리를 등록하고 ieframe.dll에 있는 IERefreshElevationPolicy 함수를 호출해주면 추가된 자동 권한 상승 정책이 바로 적용된다.
주의할 점은 IERefreshElevationPolicy를 호출할 때 반드시 IE 프로세스가 실행 중인 계정에서 호출해야 한다는 것이다. 별도의 관리자 계정이나 시스템 계정(Windows Installer의 경우 서비스에서 설치를 수행해 시스템 계정으로 설치가 되는 것으로 보인다)에서 호출할 경우 보안 경고창이 뜰 수 있다.

아래는 공식 블로그에 있는 예제 코드이다.

HRESULT RefreshPolicies()
{
    HRESULT hr = E_NOTIMPL;

    HMODULE hDll = LoadLibrary(L"ieframe.dll");
    if (NULL != hDll)
    {
        typedef HRESULT (*PFNIEREFRESHELEVATIONPOLICY)();
        PFNIEREFRESHELEVATIONPOLICY pfnIERefreshElePol = (PFNIEREFRESHELEVATIONPOLICY) GetProcAddress(hDll, "IERefreshElevationPolicy");
        if (pfnIERefreshElePol)
        {
            hr = pfnIERefreshElePol();
        } else {
             DWORD error = GetLastError(); 
             hr = HRESULT_FROM_WIN32(error);
         }
        FreeLibrary(hDll);
    } else {
       DWORD error = GetLastError(); 
       hr = HRESULT_FROM_WIN32(error);
    }
    return hr;
}

출처 : 인터넷



Posted by SB패밀리

[개발/VC++] UTF8Decoding, UTF8Encoding


출처 : 인터넷

멀티바이트 환경에서 변환같음. 

char GetHexChar(LPCTSTR str)
{
 int i,num;
 char c[2];
 if(strlen(str)>2) return 0;
 for(i=0;i<2;i++)
 {
  num=toupper(str[i]) - 0x30;
  if(num<0 || num>9)
  {
   if(num>=0x11 && num<=0x16) num-=7;
   else num=0;
  }
  c[i]=(char)num;
 }
 return c[0]*16+c[1];
}
void ParseEscStr(LPCTSTR src, CString &dst, BOOL bEsc)
{
 int n,i;
 char buff[10];
 CString str;
 n = (int)strlen(src);
 dst.Empty();
 if(bEsc)
 {
  for(i=0;i<n;i++)
  {
   if(src[i]<0 || src[i]==0x20)
   {
    wsprintf(buff,"%c%.2x",'%',(unsigned char)src[i]);
    str=buff; str.MakeUpper();
    dst+=str;
   }
   else
    dst+=src[i];
  }
 }
 else
 {
  i=0;
  while(TRUE)
  {
   if(i>=n) break;
   if(src[i]=='%')
   {
    if(i+3>n) break;
    wsprintf(buff,"%c%c",src[i+1],src[i+2]);
    dst+=GetHexChar(buff);
    i+=3;
   }
   else
   {
    dst+=src[i];
    i++;
   }

  }
 }
}


BOOL UTF8Decoding(LPCTSTR src,CString& dst)
{
 CString str;
 ParseEscStr(src,str,FALSE);
 int len=MultiByteToWideChar(CP_UTF8,MB_ERR_INVALID_CHARS,str,-1,NULL,0);
 if(len==0) return FALSE;
 LPWSTR pwStr=new WCHAR[len];
 MultiByteToWideChar(CP_UTF8,MB_ERR_INVALID_CHARS,str,-1,pwStr,len);
 dst=pwStr;
 delete[] pwStr;
 return TRUE;
}
void UTF8Encoding(LPCTSTR src,CString& dst)
{
 CString str=src;
 BSTR bstr=str.AllocSysString();
 int len=WideCharToMultiByte(CP_UTF8,0,bstr,-1,NULL,0,NULL,NULL);
 if(len==0) { dst=src; ::SysFreeString(bstr); return; }
 LPTSTR pStr=new char[len];
 WideCharToMultiByte(CP_UTF8,0,bstr,-1,pStr,len,NULL,NULL);
 ParseEscStr(pStr,dst,TRUE);
 ::SysFreeString(bstr);
 delete[] pStr;
 return;
}




Posted by SB패밀리

[개발/VC++] MultibyteToUTF8, UTF8ToMultibyte



출처 : 인터넷


[utf8.h]

#ifndef UTF8_H
#define UTF8_H

int MultibyteToUTF8(const char* src,int nbyte,char** dest);
int UNICODE_encode(const char* src,int bytelen,unsigned short** unicode);
int UTF8_encode(const unsigned short* src,int srclen,char** multibyte);


int UTF8ToMultibyte(const char* src,int nbyte,char** dest);
int UNICODE_decode(const unsigned short* src,int srclen,char** multibyte);
int UTF8_decode(const char* src,int bytelen,unsigned short** unicode);

#endif


[utf8.cpp]

int MultibyteToUTF8(const char* src,int nbyte,char** dest)
{
    unsigned short* unicode=NULL;
    int strlen = UNICODE_encode(src,nbyte,&unicode);
    int ret = UTF8_encode(unicode,strlen,dest);
    delete[] unicode;
    return ret;
}

int UNICODE_encode(const char* src,int bytelen,unsigned short** unicode)
{
    if(src == NULL || bytelen == 0 || IsBadReadPtr(src,bytelen) == TRUE) 
    {
        *unicode = NULL;
        return 0;   
    }
    int nLen = MultiByteToWideChar(CP_ACP,0,src,bytelen,NULL,NULL);
    
    if(nLen == 0) 
    {
        *unicode = NULL;
        return 0;
    }

    *unicode = new unsigned short[nLen+1];
    if(*unicode == NULL || IsBadWritePtr(*unicode,(nLen+1)*sizeof(unsigned short)) == TRUE) 
    {
        *unicode = NULL;
        return 0;
    }

    ZeroMemory(*unicode,nLen*sizeof(unsigned short)+2);
    MultiByteToWideChar(CP_ACP,0,src,bytelen,*unicode,nLen);
    return nLen;
}

int UTF8_encode(const unsigned short* src,int srclen,char** multibyte)
{
    if(src == NULL || srclen == 0 || IsBadReadPtr(src,srclen*sizeof(unsigned short)) == TRUE) 
    {
        *multibyte = NULL;
        return 0;   
    }

    int nLen = WideCharToMultiByte(CP_UTF8,0,src,srclen,*multibyte,0,NULL,NULL);
    
    if(nLen == 0) 
    {
        *multibyte = NULL;
        return 0;
    }

    *multibyte = new char[nLen+1];

    if(*multibyte == NULL || IsBadWritePtr(*multibyte,nLen+1) == TRUE) 
    {
        *multibyte = NULL;
        return 0;
    }

    ZeroMemory(*multibyte,nLen+1);
    WideCharToMultiByte(CP_UTF8,0,src,srclen,*multibyte,nLen,NULL,NULL);
    return nLen;
}


int UTF8ToMultibyte(const char* src,int nbyte,char** dest)
{
    unsigned short* unicode=NULL;
    int strlen = UTF8_decode(src,nbyte,&unicode);
    int ret = UNICODE_decode(unicode,strlen,dest);
    delete[] unicode;
    return ret;
}


int UNICODE_decode(const unsigned short* src,int srclen,char** multibyte)
{
    if(src == NULL || srclen == 0 || IsBadReadPtr(src,srclen*sizeof(unsigned short)) == TRUE) 
    {
        *multibyte = NULL;
        return 0;   
    }
    
    int nLen = WideCharToMultiByte(CP_ACP,0,src,srclen,*multibyte,0,NULL,NULL);

    if(nLen == 0) 
    {
        *multibyte = NULL;
        return 0;
    }

    *multibyte = new char[nLen+1];

    if(*multibyte == NULL || IsBadWritePtr(*multibyte,nLen+1) == TRUE) 
    {
        *multibyte = NULL;
        return 0;
    }

    ZeroMemory(*multibyte,nLen+1);
    WideCharToMultiByte(CP_ACP,0,src,srclen,*multibyte,nLen,NULL,NULL);
    return nLen;
}


int UTF8_decode(const char* src,int bytelen,unsigned short** unicode)
{
    
    if(src == NULL || bytelen == 0 || IsBadReadPtr(src,bytelen) == TRUE) 
    {
        *unicode = NULL;
        return 0;   
    }

    int nLen = MultiByteToWideChar(CP_UTF8,0,src,bytelen,NULL,NULL);

    if(nLen == 0) 
    {
        *unicode = NULL;
        return 0;
    }

    *unicode = new unsigned short[nLen+1];

    if(*unicode == NULL || IsBadWritePtr(*unicode,(nLen+1)*sizeof(unsigned short)) == TRUE) 
    {
        *unicode = NULL;
        return 0;
    }

    ZeroMemory(*unicode,nLen*sizeof(unsigned short)+2);
    MultiByteToWideChar(CP_UTF8,0,src,bytelen,*unicode,nLen);
    return nLen;
}






Posted by SB패밀리

[개발/VC++] API를 이용한 ASCII와 UNICODE변환및 코드페이지를 이용한 변환방법



출처 : 인터넷


API를 이용한 ASCII와 UNICODE변환및 코드페이지를 이용한 변환방법 
 


[사용예제]

// 멀티바이트문자열 --> 와이드문자열
 char chText[100] = "abcdefg";  // 멀티바이트 문자열
 wchar_t* pszTmp = NULL; // 와이드만자열로 변경해서 저장될 주소
 int iLen = ::MultiByteToWideChar(CP_ACP, 0, pszText, -1, pszTmp, 0);
 pszTmp = new wchar_t[iLen+1];
 ::MultiByteToWideChar(CP_ACP, 0, pszText, -1, pszTmp, iLen);

 wchar_t tcResult[MAX_PATH] = _T("");
 wcscpy( tcResult, pszTmp ); 
 delete [] pszTmp;


// 와이드문자열 --> 멀티바이트문자열
wchar_t wcText[100] = _T("abcdefg");
char* pTemp = NULL;
int iLen = ::WideCharToMultiByte(CP_ACP, 0, wcText, -1, pTemp, 0, NULL, NULL);
pTemp = new char[iLen+1];
::WideCharToMultiByte(CP_ACP, 0, wcText, -1, pTemp, iLen, NULL, NULL);

char chResult[MAX_PAHT] = "";
strcpy( chResult, pszTemp );
delete [] pTemp;

 

 


 

 

 
Counter. 215

 

 
=========================================================
● API를 이용한 ASCII와 UNICODE의 변환방법
=========================================================
//////////////////////////////////////////////////
// 문자열을 유니코드 문자열(wide-character)로 매핑한다.
//
// 이 함수에 의해 매핑되는 문자열은 multibyte character set으로 부터 반드시 유래하는 건 아니다.
//////////////////////////////////////////////////
int MultiByteToWideChar (
UINT CodePage, // code page
DWORD dwFlags, // character-type options
LPCSTR lpMultiByteStr, // string to map
int cbMultiByte, // number of bytes in string
LPWSTR lpWideCharStr, // wide-character buffer
int cchWideChar // size of buffer
);
CodePage :
[in] 변환 수행에 사용될 code page를 기술한다.
이 파라메타는 설치되거나 또는 시스템에 유효한 어떤한 코드페이지가 될수 있다.
또는 아래에 기술된 값중 하나를 기술할 수 있다.

CP_ACP : ANSI 코드 페이지
CP_MACCP : Macintosh 코드 페이지
CP_OEMCP : OEB 코드 페이지

lpMultiByteStr :
[in] 변환 되어질 문자열 스트링 포인터

cbMultiByte
[in] lpMultiByteStr 파라메타에 의해 포인트된 문자열의 바이트 사이즈
lpWideCharStr
[out] 변환된 문자열을 수신할 버퍼 포인터
cchWideChar
[in] wide character로, lpWideCharStr파라메타에 의해 포인트된 버퍼의 크기
만약 이값이 0이면, 이함수는 wide character로 요구되어진 buffer size를 반환한다,
그리고 lpWideCharStr 버퍼의 사용을 하지 않는다.
Return Values

If the function succeeds, and cchWideChar is nonzero, the return value is the number of wide characters written to the buffer pointed to by lpWideCharStr.
If the function succeeds, and cchWideChar is zero, the return value is the required size, in wide characters, for a buffer that can receive the translated string.
If the function fails, the return value is zero. To get extended error information, call GetLastError. GetLastError may return one of the following error codes:
ERROR_INSUFFICIENT_BUFFER
ERROR_INVALID_FLAGS
ERROR_INVALID_PARAMETER
ERROR_NO_UNICODE_TRANSLATION
▷ASCII ==> UNICODE 변환방법
// sTime이란 ANSI 무낮열을 bstr이란 이름의 유니코드(BSTR타입) 변수로 변환
char sTime[] = '유니코드 변환 예제';
BSTR bstr;
// sTime을 유니코드로 변환하기에 앞서 먼저 그것의 유니코드에서의 길이를 알아야 한다.
int nLen = MultiByteToWideChar(CP_ACP, 0, sTime, lstrlen(sTime), NULL, NULL)
// 얻어낸 길이만큼 메모리를 할당한다.
bstr = SysAllocStringLen(NULL, nLen);
// 이제 변환을 수행한다.
MultiByteToWideChar(CP_ACP, 0, sTime, lstrlen(sTime), bstr, nLen);
▷UNICODE ==> ASCII 변환방법
// newVal이란 BSTR 타입에 있는 유니코드 문자열을 sTime이라는 ANSI 문자열로 변환
char sTime[128];
WideCharToMultiByte(CP_ACP, 0, newVal, -1, sTime, 127/*원래크기보다 1작게*/, NULL, NULL);

===================================================
● 코드 페이지를 이용하여 조합/완성/유니코드를 주무르자.
====================================================
윈도우즈 API에서 MultiByteToWideChar와 WideCharToMultiByte를 이용하면 완성,
조합에서 유니코드로 혹은 그 반대로 변환을 할 수 있습니다.
한글 95나 NT의 경우 기본적으로 조합형과 완성형의 코드페이지가 설치 되어있으므로 문제가 없으나
영문의 경우는 IE에서 한글 package를 설치하면 완성형은 설치가 되나 조합형은 없습니다.
코드페이지 설치.
'CP_XXX.nls'(WIN95) or 'C_XXX.nls'(WINNT)를 구하십시요. XXX 는 1361(조합) or 949(완성)입니다.
레지스트리에 다음의 값을 입력하십시요.
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage\XXX=CP_XXX.nls (WIN95)
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage\XXX=C_XXX.nls (WINNT)
조합형 코드를 보고자 할때는 cp_1361.nls(95용), c_1361.nls(nt용)을 구하셔서 시스템에 설치를 합니다.
95의 경우 system 디렉토리에, NT의 경우 system32 디렉토리에 설치하십시요.
=====================================================================
/*
* MultiByteToWideChar와 WideCharToMultiByte를 이용한 완성형, 조합형, 유니코드 변환.
*/
#include
#define CP_WANSUNG 949
#define CP_JOHAB 1361

void ConvertWansungToUnicode (LPCSTR szInput, int nInputSize, LPWSTR* szUnicode, int* nUnicodeSize)
{
// 유니코드의 크기를 구한다.
*nUnicodeSize = MultiByteToWideChar(CP_WANSUNG, 0,
szInput, nInputSize,
NULL, 0);
*szUnicode = (LPWSTR)malloc(nUnicodeSize*sizeof(WCHAR));
// 실제 유니코드로 변환.
MultiByteToWideChar(CP_WANSUNG, 0,
szInput, nInputSize,
*szUnicode, *nUnicodeSize);
}
void ConvertJohabToUnicode (LPCSTR szInput, int nInputSize, LPWSTR* szUnicode, int* nUnicodeSize)
{
// 유니코드의 크기를 구한다.
*nUnicodeSize = MultiByteToWideChar(CP_JOHAB, 0,
szInput, nInputSize,
NULL, 0);
*szUnicode = (LPWSTR)malloc(nUnicodeSize*sizeof(WCHAR));
// 실제 유니코드로 변환.
MultiByteToWideChar(CP_WANSUNG, 0,
szInput, nInputSize,
*szUnicode, *nUnicodeSize);
}
void ConvertWansungToJohab (LPCSTR szInput, int nInputSize, LPSTR* szOutput, int* nOutputSize)
{
int nUnicodeSize;
LPWSTR szUnicode;
// 1. 완성형을 유니코드로 변환
// 유니코드의 크기를 구한다.
nUnicodeSize = MultiByteToWideChar(CP_WANSUNG, 0,
szInput, nInputSize,
NULL, 0);
szUnicode = (LPWSTR)malloc(nUnicodeSize*sizeof(WCHAR));
// 실제 유니코드로 변환.
MultiByteToWideChar(CP_WANSUNG, 0,
szInput, nInputSize,
szUnicode, nUnicodeSize);
// 2. 유니코드를 조합형으로 변환.
// 조합형의 크기를 구한다.
*nOutputSize = WideCharToMultiByte(CP_JOHAB, 0,
szUnicode, nUnicodeSize,
NULL, 0, NULL,NULL);
*szOutput = (LPSTR)malloc(*nOutputSize);
// 실제 조합형으로 변환.
WideCharToMultiByte(CP_JOHAB, 0,
szUnicode, nUnicodeSize,
*szOutput, *nOutputSize, NULL,NULL);
free(szUnicode);
}
유니코드 문자열을 UTF8 문자열로 변환하는 방법

KB Article ID: K001368

--------------------------------------------------------------------------------

이 내용이 적용되는 제품:
- Platform SDK

[요 약]

한글 윈도우 95에서 유니코드 문자열을 UTF8 문자열로 변환해 주는 다음 함수를 실행하면, 리턴되는 UTF8 버퍼에 아무런 값도 리턴 되지 않습니다. RFC2044에 명시된 스펙에 의거하여 문자열 변환하는 방법을 소개합니다.

#include “winnls.h”
WideCharToMultiByte(CP_UTF8, 0, szUniBuf, nUniLen, szUTFBuf, sizeof(szUTFBuf), NULL, NULL);

[추가 정보]

한글 윈도우 95에서 WIN32 API인 WideCharToMultiByte(CP_UTF8, xxx) 함수에서 UTF8 버퍼에 아무런 값도 리턴하지 않으므로 다음과 같이 스펙에 의거한 변환 루틴을 이용하여 UTF8 문자열 값을 얻습니다.

char* UnicodeToUTF8(wchar_t uc, char* UTF8)
{
if (uc <= 0x7f)
{
UTF8[0] = (char) uc;
UTF8[1] = (char) '\0';
}
else if (uc <= 0x7ff)
{
UTF8[0] = (char) 0xc0 + uc / (wchar_t) pow(2, 6);
UTF8[1] = (char) 0x80 + uc % (wchar_t) pow(2, 6);
UTF8[2] = (char) '\0';
}
else if (uc <= 0xffff)
{
UTF8[0] = (char) 0xe0 + uc / (wchar_t) pow(2, 12);
UTF8[1] = (char) 0x80 + uc / (wchar_t) pow(2, 6) % (wchar_t) pow(2, 6);
UTF8[2] = (char) 0x80 + uc % (wchar_t) pow(2, 6);
UTF8[3] = (char) '\0';
}

return UTF8;
}

int WideStrToUTF8Str(wchar_t *szUni,char *szUTF8)
{
int i=0;
char TempUTF8[10];
for(i=0;szUni[i];i++) {
UnicodeToUTF8(szUni[i], TempUTF8);
strcat(szUTF8, TempUTF8);
}
return strlen(szUTF8);
}

실제 위 두 함수를 사용하는 예제

{
wchar_t szUniBuf[MAXBUF];
int nUniLen, nUTFLen;
char szUTFBuf[MAXBUF];

nUniLen = MultiByteToWideChar(CP_ACP, 0, szHello, strlen(szHello), szUniBuf, MAXBUF);
szUniBuf[nUniLen] = 0;
memset(szUTFBuf, 0, MAXBUF);
nUTFLen = WideStrToUTF8Str(szUniBuf, szUTFBuf);
//nUTFLen = WideCharToMultiByte(CP_UTF8, 0, szUniBuf, nUniLen, szUTFBuf, MAXBUF, NULL, NULL);
szUTFBuf[nUTFLen]=0x00;

}


한글 EBCIDIC 코드를 한글 ASCII 코드로 변환하는 방법

KB Article ID: K001143

--------------------------------------------------------------------------------

[요 약]

프로그래밍적으로, 한글 EBCIDIC 코드를 한글 ASCII 코드로 변환하는 방법을
여기에서 소개한다.

[추가 정보]

#include 'snanls.h'
function()
{
int ret;
LPCTSTR lpSrcStr, lpDestStr;
ret =SnaInit(CP_949);
printf('ret = %d', ret);
ret = SnaNlsMapString (lpSrcStr, lpDestStr, CP_933, CP_949, 2, 2,
SNA_MULTIBYTE, SNA_MULTIBYTE, 0x0);
printf('ret = %d', ret);
}


1. SnaInit(CP_949)는 현재 이 프로그램이 실행되는 환경의 코드 페이지를
지정한다.
2. lpSrcStr은 IBM 메인 프레임 컴퓨터 등으로부터 받은 한글 EBCIDIC 코드이며,
lpDestStr은 리턴되는 ASCII 코드값이다.
3. #define CP_933 933 /* EBCDIC Korean */
#define CP_949 949 /* Korean */
UTF-8 to Unicode / Unicode to UTF-8 transformation 


Posted by SB패밀리

[개발/VC++] URLEncode, URLDecode, 유니코드 변환 소스



[개발/VC++] URLEncode, URLDecode, UTF8 변환 소스


[유니코드 문자집합용]


CString Unicode_URLDecode( CString strEncodedText )
{
 CString strResult;
 wchar_t ch0, ch1, ch2;
 wchar_t wch;
 TCHAR tch;
 int i = 0;


 while( i<strEncodedText.GetLength() )
 {
  tch = strEncodedText.GetAt(i);
  
  if( tch != _T('%') )
  {
   // a character not encoded
   strResult += tch;
   i++;
  }
  else
  {
   // a character encoded !!
   ch0 = _tcstol( strEncodedText.Mid( i+1, 2 ), NULL, 16 );
   i += 3;


   if( ch0 < 0x80 )
    // 1 byte for UTF-8
    // 0xxx xxxx
    wch = ch0;
   else
   {
    if( strEncodedText.GetAt(i)!= _T('%') ) // Error!
     continue;


    ch1 = _tcstol( strEncodedText.Mid( i+1, 2 ), NULL, 16 );
    i += 3;


    if( ch0 < 0xe0 )
    {
     // 2 byte for UTF-8
     // 110x xxxx 10xx xxxx
     wch = ((ch0&0x1f)<<6)
      | (ch1&0x3f);
    }
    else
    {
     // 3 byte for UTF-8
     if( strEncodedText.GetAt(i)!= _T('%') ) // Error!
      continue;


     ch2 = _tcstol( strEncodedText.Mid( i+1, 2 ), NULL, 16 );
     i += 3;


     // 1110 xxxx 10xx xxxx 10xx xxxx
     wch = ((ch0&0x0f)<<12)
      | ((ch1&0x3f)<<6)
      | (ch2&0x3f);
    }
   }
   strResult += wch;
  }
 }


 return strResult;
}

 

-------------------------------------------------------------------------------------------
[멀티바이트 문자집합용]


inline BYTE CURLEncode::toHex(const BYTE &x) {
 return x > 9 ? x + 55: x + 48;
}


inline BYTE CURLEncode::toByte(const BYTE &x) {
 return x > 57? x - 55: x - 48;
}

CString CURLEncode::URLDecode(CString sIn)
{
    CString sOut;
    const int nLen = sIn.GetLength() + 1;
    register LPBYTE pOutTmp = NULL;
    LPBYTE pOutBuf = NULL;
    register LPBYTE pInTmp = NULL;
    LPBYTE pInBuf =(LPBYTE)sIn.GetBuffer(nLen);
    //alloc out buffer
    pOutBuf = (LPBYTE)sOut.GetBuffer(nLen);
    
    if(pOutBuf)
    {
        pInTmp   = pInBuf;
        pOutTmp = pOutBuf;
        // do encoding
        while (*pInTmp)
        {
            if('%'==*pInTmp)
            {
                pInTmp++;
                *pOutTmp++ = (toByte(*pInTmp)%16<<4) + toByte(*(pInTmp+1))%16;
                pInTmp++;
            }
            else if('+'==*pInTmp)
                *pOutTmp++ = ' ';
            else
                *pOutTmp++ = *pInTmp;
            pInTmp++;
        }
        *pOutTmp = '\0';
        sOut.ReleaseBuffer();
    }
    sIn.ReleaseBuffer();
    
    return sOut;
}


CString CURLEncode::URLEncode(CString sIn)
{
    CString sOut;
    const int nLen = sIn.GetLength() + 1;
    register LPBYTE pOutTmp = NULL;
    LPBYTE pOutBuf = NULL;
    register LPBYTE pInTmp = NULL;
    LPBYTE pInBuf =(LPBYTE)sIn.GetBuffer(nLen);
    //alloc out buffer
    pOutBuf = (LPBYTE)sOut.GetBuffer(nLen*3);
    
    if(pOutBuf)
    {
        pInTmp   = pInBuf;
        pOutTmp = pOutBuf;
        // do encoding
        while (*pInTmp)
        {
            if(isalnum(*pInTmp) || '-'==*pInTmp || '_'==*pInTmp || '.'==*pInTmp)
                *pOutTmp++ = *pInTmp;
            else if(isspace(*pInTmp))
                *pOutTmp++ = '+';
            else
            {
                *pOutTmp++ = '%';
                *pOutTmp++ = toHex(*pInTmp>>4);
                *pOutTmp++ = toHex(*pInTmp%16);
            }
            pInTmp++;
        }
        *pOutTmp = '\0';
        sOut.ReleaseBuffer();
    }
    sIn.ReleaseBuffer();
    
    return sOut;
}


 





Posted by SB패밀리

[개발/VC++] URLEncode, URLDecode, UTF8 변환 소스



아래 소스는 멀티바이트 문자집합 프로젝트 설정으로 작업해야 작동된다.

inline BYTE toHex(const BYTE &x)
{
       return x > 9 ? x + 55: x + 48;
}

CString URLEncode(CString sIn)
{
       CString sOut;
       const int nLen = sIn.GetLength() + 1;
       register LPBYTE pOutTmp = NULL;
       LPBYTE pOutBuf = NULL;
       register LPBYTE pInTmp = NULL;
       LPBYTE pInBuf =(LPBYTE)sIn.GetBuffer(nLen);
       BYTE b = 0;

       //alloc out buffer
       pOutBuf = (LPBYTE)sOut.GetBuffer(nLen*3 - 2);//new BYTE [nLen * 3];

       if(pOutBuf)
       {
             pInTmp   = pInBuf;
              pOutTmp = pOutBuf;

              // do encoding
              while (*pInTmp)
              {
                     if(isalnum(*pInTmp))
                            *pOutTmp++ = *pInTmp;
                     else
                            if(isspace(*pInTmp))
                                   *pOutTmp++ = '+';
                            else
                            {
                                   *pOutTmp++ = '%';
                                   *pOutTmp++ = toHex(*pInTmp>>4);
                                   *pOutTmp++ = toHex(*pInTmp%16);
                            }
                     pInTmp++;
              }
              *pOutTmp = '\0';
              //sOut=pOutBuf;
              //delete [] pOutBuf;
              sOut.ReleaseBuffer();
       }
       sIn.ReleaseBuffer();
       return sOut;
}


UrlDecode:
#define IsHexNum(c) ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'))

CString Utf8ToStringT(LPSTR str)
{
    _ASSERT(str);
    USES_CONVERSION;
    WCHAR *buf;
    int length = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
    buf = new WCHAR[length+1];
    ZeroMemory(buf, (length+1) * sizeof(WCHAR));
    MultiByteToWideChar(CP_UTF8, 0, str, -1, buf, length);

    return (CString(W2T(buf)));
}

CString UrlDecode(LPCTSTR url)
{
    _ASSERT(url);
    USES_CONVERSION;
    LPSTR _url = T2A(const_cast<LPTSTR>(url));
    int i = 0;
    int length = (int)strlen(_url);
    CHAR *buf = new CHAR[length];
    ZeroMemory(buf, length);
    LPSTR p = buf;
    while(i < length)
    {
        if(i <= length -3 && _url[i] == '%' && IsHexNum(_url[i+1]) && IsHexNum(_url[i+2]))
        {
            sscanf(_url + i + 1, "%x", p++);
            i += 3;
        }
        else
        {
            *(p++) = _url[i++];
        }
    }
    return Utf8ToStringT(buf);
}








Posted by SB패밀리

[개발/VC++] WebBrowser Control 이벤트 연결 - C++



WebBrowser Control
IDispatch 
IWebBrowser2
    .ReadyState
        READYSTATE_COMPLETE

    .Navigate2()
    .get_Document() // IDispatch -> IHTMLDocument2
    .get_StatusText()

    on DownloadBegin
    on DocumentComplete
    on DownloadComplete

IOleObject

 

IHTMLWindow2

IHTMLDocument2
    .get_all()
    .get_parentWindow() // IHTMLWindow2

IHTMLElementCollection
    .item()
    .tags // IHTMLElementCollection

IHTMLElement

a connectable object
    IConnectionPointContainer
        .FindConnectionPoint() // DHTMLElementEvents2

DHTMLElementEvents2
    .Advise()

outgoing HTMLElementEvents2 interface // event sink object // the client event sink 
    IDispatch
        .Invoke()

----------------------------------------------------------------------------------------


class CTryDlg : public CDialog
{
// Construction
public:
    CTryDlg(CWnd* pParent = NULL);    // standard constructor

// Dialog Data
    //{{AFX_DATA(CTryDlg)
    enum { IDD = IDD_TRY_081209_DIALOG };
    CWebBrowser2    m_webBrowser;
    //}}AFX_DATA
...
    // Generated message map functions
    //{{AFX_MSG(CTryDlg)
    ...
    afx_msg void OnDocumentCompleteExplorer1(LPDISPATCH pDisp, VARIANT FAR* URL);
    DECLARE_EVENTSINK_MAP()
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
};

BOOL CTryDlg::OnInitDialog()
{
    ...
    SetIcon(m_hIcon, FALSE);        // Set small icon
    
    // TODO: Add extra initialization here
// {
    COleVariant     szURL       = "http://www.google.com";
    m_webBrowser.Navigate2(szURL, NULL, NULL, NULL, NULL);
// }    
    return TRUE;  // return TRUE  unless you set the focus to a control
}
...
BEGIN_EVENTSINK_MAP(CTryDlg, CDialog)
    //{{AFX_EVENTSINK_MAP(CTryDlg)
    ON_EVENT(CTryDlg, IDC_EXPLORER1, 259 /* DocumentComplete */, OnDocumentCompleteExplorer1, VTS_DISPATCH VTS_PVARIANT)
    //}}AFX_EVENTSINK_MAP
END_EVENTSINK_MAP()

void CTryDlg::OnDocumentCompleteExplorer1(LPDISPATCH lpDisp, VARIANT FAR* URL) 
{
    // TODO: Add your control notification handler code here
   IUnknown*  pUnk;
   LPDISPATCH lpWBDisp;
   HRESULT    hr;

   pUnk = m_webBrowser.GetControlUnknown();
   ASSERT(pUnk);

   hr = pUnk->QueryInterface(IID_IDispatch, (void**)&lpWBDisp);
   ASSERT(SUCCEEDED(hr));

   if (lpDisp == lpWBDisp )
   {
      // Top-level Window object, so document has been loaded
      TRACE("Web document is finished downloading\n");
   }

  lpWBDisp->Release();
}
----------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------
m_pBrowser // IWebBrowser2

// DWebBrowserEvents2::DocumentComplete
void CMyClass::DocumentComplete(LPDISPATCH pDisp, VARIANT* URL)
{
    HRESULT hr;
    IUnknown* pUnkBrowser = NULL;
    IUnknown* pUnkDisp = NULL;
    IDispatch* pDocDisp = NULL;
    IHTMLDocument2* pDoc = NULL;

    // Is this the DocumentComplete event for the top frame window?
    // Check COM identity: compare IUnknown interface pointers.
    hr = m_pBrowser->QueryInterface(IID_IUnknown, (void**)&pUnkBrowser);

    if (SUCCEEDED(hr))
    {
        hr = pDisp->QueryInterface(IID_IUnknown, (void**)&pUnkDisp);

        if (SUCCEEDED(hr))
        {
            if (pUnkBrowser == pUnkDisp)
            {
                // This is the DocumentComplete event for the top frame.
                // This page is loaded, so we can access the DHTML Object Model.
                hr = m_pBrowser->get_Document(&pDocDisp);

                if (SUCCEEDED(hr))
                {
                    // Obtained the document object.
                    pDocDisp->QueryInterface(IID_IHTMLDocument2, (void**)&pDoc);
                    if (SUCCEEDED(hr))
                    {
                        // Obtained the IHTMLDocument2 interface for the document object
                        ProcessDocument(pDoc);
                    }

                    pDocDisp->Release();
                }
            }

            pUnkDisp->Release();
        }

        pUnkBrowser->Release();
    }
}

// IHTMLDocument2
void CMyClass::ProcessDocument(IHTMLDocument2* pDoc)
{
    IHTMLElementCollection* pElemColl = NULL;

    hr = pDoc->get_all(&pElemColl);
    if (SUCCEEDED(hr))
    {
        // Obtained element collection.
        ProcessElementCollection(pElemColl);
        pElemColl->Release();
    }
}

void CMyClass::ProcessElementCollection(IHTMLElementCollection* pElemColl)
{
    IDispatch* pElemDisp = NULL;
    IHTMLElement* pElem = NULL;
    _variant_t varID("myID", VT_BSTR);
    _variant_t varIdx(0, VT_I4);

    hr = pElemColl->item(varID, varIdx, &pElemDisp);

    if (SUCCEEDED(hr))
    {
        hr = pElemDisp->QueryInterface(IID_IHTMLElement, (void**)&pElem);

        if (SUCCEEDED(hr))
        {
            // Obtained element with ID of "myID".
            ConnectEvents(pElem);
            pElem->Release();
        }

        pElemDisp->Release();
    }
}


void CMyClass::ConnectEvents(IHTMLElement* pElem)
{
    HRESULT hr;
    IConnectionPointContainer* pCPC = NULL;
    IConnectionPoint* pCP = NULL;
    DWORD dwCookie;

    // Check that this is a connectable object.
    hr = pElem->QueryInterface(IID_IConnectionPointContainer, (void**)&pCPC);

    if (SUCCEEDED(hr))
    {
        // Find the connection point.
        hr = pCPC->FindConnectionPoint(DIID_HTMLElementEvents2, &pCP);

        if (SUCCEEDED(hr))
        {
            // Advise the connection point.
            // pUnk is the IUnknown interface pointer for your event sink
            hr = pCP->Advise(pUnk, &dwCookie);

            if (SUCCEEDED(hr))
            {
                // Successfully advised
            }

            pCP->Release();
        }

        pCPC->Release();
    }
}


STDMETHODIMP CEventSink::Invoke(DISPID dispidMember,
                                REFIID riid,
                                LCID lcid,
                                WORD wFlags,
                                DISPPARAMS* pdispparams,
                                VARIANT* pvarResult,
                                EXCEPINFO* pexcepinfo,
                                UINT* puArgErr)
{
    switch (dispidMember)
    {
        case DISPID_HTMLELEMENTEVENTS2_ONCLICK:
        OnClick();
        break;

        default:
        break;
    }

    return S_OK;
}

----------------------------------------------------------------------------------------

IOleInPlaceFrame
IOleClientSite
IOleInPlaceSite

EmbedBrowserObject()
    window handle
        _IOleClientSiteEx    // USERDATA
            IOleInPlaceFrame
            IOleClientSite
            IOleInPlaceSite
            IDocHostUIHandler

    CoCreateInstance()
        CLSID_WebBrowser
        IWebBrowser2
            .put_Left()
            .put_Top()
            .put_Width()
            .put_Height()
            .Navigate2()

        IOleObject
            .Close()
            .SetClientSite() // IOleClientSite
            .SetHostNames()
            .DoVerb()

UnEmbedBrowserObject()

ResizeBrowser()

DisplayHTMLPage()

DoPageAction()

GetWebPtrs()
    IHTMLDocument2

IHTMLElementCollection

GetWebElement()
    IHTMLElement

CreateWebEvtHandler()

FreeWebEvtHandler()

WaitOnReadyState()

더보기


extern "C" {

HINSTANCE        cwebdll;

long WINAPI EmbedBrowserObject(HWND hwnd);
void WINAPI UnEmbedBrowserObject(HWND hwnd);
long WINAPI DisplayHTMLPage(HWND hWnd, const char *url);
void WINAPI ResizeBrowser(HWND hWnd, DWORD x, DWORD y);

}

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
     // TODO: Place code here.
// {
    // Load our DLL containing the OLE/COM code. We do this once-only. It's named "cwebpage.dll"
    if (!(cwebdll = LoadLibrary("cwebpage.dll")))
    {
        MessageBox(0, "Can't open cwebpage.dll!", "ERROR", MB_OK);
        return(-1);
    }
// }
    MSG msg;
    HACCEL hAccelTable;

    // Initialize global strings
    LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    ...
}
...
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message) 
    {
// {
        case WM_CREATE:
            // Embed the browser object into our host window. We need do this only
            // once. Note that the browser object will start calling some of our
            // IOleInPlaceFrame and IOleClientSite functions as soon as we start
            // calling browser object functions in EmbedBrowserObject().
            if (EmbedBrowserObject(hWnd)) return(-1);
            DisplayHTMLPage(hWnd, "http://www.microsoft.com");
            break;
// }
        case WM_DESTROY:
// {
            // Detach the browser object from this window, and free resources.
            UnEmbedBrowserObject(hWnd);
// }
            PostQuitMessage(0);
            break;
        case WM_COMMAND:
            ...
            break;
        case WM_SIZE:
            // Resize the browser object to fit the window
            ResizeBrowser(hWnd, LOWORD(lParam), HIWORD(lParam));
            break;
        ...
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
   }
   return 0;
}


참조 사이트:

http://support.microsoft.com/kb/315617/en-us/
http://msdn.microsoft.com/en-us/library/bb508508(VS.85).aspx
http://support.microsoft.com/kb/194179/en-us/
http://www.codeproject.com/KB/shell/dlgdhtmlevents.aspx?display=Print
http://msdn.microsoft.com/en-us/library/aa293017(VS.71).aspx
http://urassa.tistory.com/entry/Web-Browser-Control-FAQ

http://www.codeproject.com/KB/COM/cwebpage.aspx?display=Print
http://jjjryu.tistory.com/entry/IE-1
http://support.microsoft.com/kb/196339/en-us/
http://jjjryu.tistory.com/entry/ActiveX-%EC%BB%A8%ED%8A%B8%EB%A1%A4-%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8
http://www.codeproject.com/KB/shell/AutomateShellWindow.aspx?display=Print
http://www.codeproject.com/KB/shell/iehelper.aspx?display=Print


출처 : http://jjjryu.tistory.com/333

Posted by SB패밀리





VC++ Source Code
// Subclassing.cpp : Defines the entry point for the application.
// #include "stdafx.h"#include <tchar.h> 
#define STRSAFE_NO_DEPRECATE 
WNDPROC g_pOldProc;
char szAppName[]="Subclassing Demo"; 
LRESULT CALLBACK SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{   
 if(uMsg == WM_CLOSE)    
 {        
  DestroyWindow(hWnd);        
  PostQuitMessage(0);        
  return 0;    
 }    
 return CallWindowProc(g_pOldProc, hWnd, uMsg, wParam, lParam);

int APIENTRY _tWinMain(HINSTANCE hInstance,                     
 HINSTANCE hPrevInstance,                     
 LPSTR     lpCmdLine,                     
 int       nCmdShow)
{    
 HWND hEdit = 0;        
 /*Create a top-level edit control*/    
 hEdit = CreateWindowEx(                0, 
   _T("EDIT"), _T(szAppName),                
   WS_OVERLAPPEDWINDOW,                 
   CW_USEDEFAULT,                 
   CW_USEDEFAULT,                 
   200,                 
   100,                 
   0,                 
   0,                 
   hInstance,                 
   0);        
 g_pOldProc = (WNDPROC)SetWindowLong(hEdit, GWL_WNDPROC, PtrToLong(SubclassProc));     
 ShowWindow(hEdit, SW_SHOWNORMAL);     
 
 MSG msg;    
 
 while(GetMessage(&msg, 0, 0, 0))    
 {        
  TranslateMessage(&msg);        
  DispatchMessage(&msg);    
 }    
 
 return 0;
}

Posted by SB패밀리




[VC] IE 서브클래싱(subclass)


WNDPROC g_pOldProc;

static LRESULT CALLBACK MyIEProc(HWND, UINT, WPARAM, LPARAM);

 

 

void CBand::SubClass(HWND hWnd)

{

     // 64bit 환경을 위해서 SetWindowLongPtr() 사용

    g_pOldProc = (WNDPROC) SetWindowLongPtr(hwndOfCallingComponent, GWLP_WNDPROC, (LONG_PTR)IEProc);

}

 

LRESULT CALLBACK CBand::MyIEProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
 BOOL bRes = false;

 if (Message == WM_SIZE)
  bRes = g_pBand->SetPosition();
 if (Message == WM_ERASEBKGND)
  bRes  = false;

 if (bRes == false)
  return CallWindowProc (g_pOldProc, hwnd, message, wParam, lParam);

}

// 위치 체크 및 이동
BOOL CBand::SetPosition()
{
 RECT rc;

 ::GetClientRect(m_BandWnd, &rc);
 if (rc.top == 0)
 {
  // 작업내용
 }

 return false;
}

 

 

참고 :

http://0x68.com/shorts/subclass.asp

http://social.msdn.microsoft.com/Forums/en/vclanguage/thread/7cd4b8b5-1cd6-4661-9f29-e0569156cea4

http://www.cyworld.com/soinho/1291233

Posted by SB패밀리

VC++ BHO 만들기에서 ATL 단순개체 마법사 옵션 설정화면
프로젝트 생성후 BHO(Browser Helper Objects)만들 때 유용하게 사용하기 바람





Posted by SB패밀리

[개발/VC++] Visual C++에 관련된 유용한 코드 팁







Visual C++에 관련된 유용한 코드 팁
내용


1.Link: Knowledge Base 
2.다이알로그에 스킨 입히기 
3.투명 윈도우 만들기 
4.내 IP 얻는 방법 
5.트레이 아이콘 
6.패스 분리하는 방법 
7.FTP 관련 
8.Downloaded Program Files 폴더의 OCX 삭제방법 
9.디버깅 용도의 실행시간 출력 코드 
10.Trace Tip 
11.모니터 끄기 
12.프로세스간 데이터 교환 
13.Log 함수 
14.Ctrl+Esc, Alt+Tab, and Alt+Esc를 막는 법 
15.About box에 URL 링크 걸기 
16.특정 파일 오픈시 바로 프로그램 불러오기 
17.드래그 앤 드롭으로 파일 오픈 
18.app가 트레이에만 띄우도록 하려면 
19.single thread 어플리케이션에 취소 버튼 구현 
20.PC시간 셋팅하기
1 Link: Knowledge Base
Knowledge base : MFC 및 Visual C++ 프로그래밍에 대한 방대한 tip과 know-how를 담고 있다.

 

2 다이알로그에 스킨 입히기
void CDlgPictureDlg::OnPaint()  

    if (IsIconic()) 
    { 
        CPaintDC dc(this); // device context for painting 
 
        SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); 
 
        // Center icon in client rectangle 
        int cxIcon = GetSystemMetrics(SM_CXICON); 
        int cyIcon = GetSystemMetrics(SM_CYICON); 
        CRect rect; 
        GetClientRect(&rect); 
        int x = (rect.Width() - cxIcon + 1) / 2; 
        int y = (rect.Height() - cyIcon + 1) / 2; 
 
        // Draw the icon 
        dc.DrawIcon(x, y, m_hIcon); 
    } 
    else 
    {     
        CWindowDC dc(this); 
        CDC memDC; 
        memDC.CreateCompatibleDC(&dc); 
        CBitmap bitmap; 
        BITMAP bm; 
        bitmap.LoadBitmap(IDB_BITMAP1);      <<-- 비트맵 이미지를 만들어야한다. 
        bitmap.GetBitmap(&bm); 
        CBitmap* pOld = memDC.SelectObject(&bitmap); 
        dc.BitBlt(5, 30, bm.bmWidth, bm.bmHeight, &memDC, 0, 0, SRCCOPY); 
        dc.SelectObject(pOld); 
        memDC.DeleteDC(); 
        CDialog::OnPaint(); 
    } 
  

3 투명 윈도우 만들기
BOOL CWin1Dlg::OnInitDialog() 

    CDialog::OnInitDialog(); 
  
    SLWA pSetLayeredWindowAttributes = NULL;     // 함수포인터 선언, 초기화. 
    HINSTANCE hmodUSER32 = LoadLibrary("USER32.DLL");  // 인스턴스 얻음. 
    pSetLayeredWindowAttributes=(SLWA)GetProcAddress(hmodUSER32,"SetLayeredWindowAttributes");   //함수포인터 얻음. 
    HWND hwnd = this->m_hWnd;                              //다이얼로그의 핸들 얻음. 
 
    SetWindowLong(hwnd, GWL_EXSTYLE,GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED); 
    pSetLayeredWindowAttributes(hwnd, 0, (255 * 70) / 100, LWA_ALPHA); 
 
    return TRUE;  // return TRUE  unless you set the focus to a control 

 
// 해당 다이알로그의 상단에 추가 
#define WS_EX_LAYERED           0x00080000 
#define LWA_COLORKEY            0x00000001 
#define LWA_ALPHA               0x00000002 
#define ULW_COLORKEY            0x00000001 
#define ULW_ALPHA               0x00000002 
#define ULW_OPAQUE              0x00000004 
  
typedef BOOL(WINAPI *SLWA)(HWND, COLORREF, BYTE, DWORD);

4 내 IP 얻는 방법
CString GetMyIPAddress() 

    char        chName[255]; 
    CString        sAddress; 
    PHOSTENT    pHostEntry; 
    IN_ADDR        inAddr; 
 
    if( gethostname( chName, 255 ) != 0 ) return ""; 
    else 
    { 
        if( ( pHostEntry = gethostbyname( chName ) ) == NULL ) return ""; 
        else 
        { 
            memcpy( &inAddr, pHostEntry->h_addr, 4 ); 
            sAddress.Format( "%s", inet_ntoa( inAddr ) ); 
            return sAddress; 
        } 
    } 
}

5 트레이 아이콘
void CWin1Dlg::OnButton1()  

            //일단 트레이아이콘 생성 
 
    NOTIFYICONDATA nid;     
                     
    nid.cbSize = sizeof(nid);  
    nid.hWnd = m_hWnd;         
    nid.uID = IDR_MAINFRAME;   
    nid.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP; 
    nid.uCallbackMessage = WM_ICON_NOTIFY; 
    //이 부분이 중요 - 트레이 아이콘에서 이벤트 발생시 발생되는 메세지 정의하는 부분..  
    nid.hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);  
    strcpy(nid.szTip,"Test"); 
    Shell_NotifyIcon(NIM_ADD,&nid);  
    SendMessage(WM_SETICON,(WPARAM)TRUE,(LPARAM)nid.hIcon); 
 
    //일단 아이콘 생성하기 전에 다이얼로그를 숨겨야 겠죠..^^ 
    ShowWindow(SW_HIDE); 

 
void CWin1Dlg::OnButton2()  

    //다음 트레이아이콘 삭제 
    NOTIFYICONDATA nid; 
 
    nid.cbSize = sizeof(nid); 
    nid.hWnd = m_hWnd; 
    nid.uID = IDR_MAINFRAME; 
    Shell_NotifyIcon(NIM_DELETE,&nid); 
 
    //글구 이젠 다이얼로그를 나타나게.. 
    ShowWindow(SW_SHOW); 

 
LRESULT CWin1Dlg::OnTrayNotification(WPARAM wParam, LPARAM lParam) 

    // 왼쪽 마우스 버튼이 더블 클릭되었을 경우 
   if (LOWORD(lParam) == WM_LBUTTONDBLCLK)  
   { 
                // 프로그램 정보 다이얼로그 박스 출력 
                SendMessage(WM_COMMAND, IDC_BUTTON2); 
   } 
   return 1; 
}

6 패스 분리하는 방법
void _splitpath( const char *path, char *drive, char *dir, char *fname, char *ext ); 
를 쓰면 됩니다. 다음은 MSDN에 나와있는 예제입니다


#include  
#include  
 
void main( void ) 

   char path_buffer[_MAX_PATH]; 
   char drive[_MAX_DRIVE]; 
   char dir[_MAX_DIR]; 
   char fname[_MAX_FNAME]; 
   char ext[_MAX_EXT]; 
 
   _makepath( path_buffer, "c", "\\sample\\crt\\", "makepath", "c" ); 
  
   printf( "Path created with _makepath: %s\n\n", path_buffer ); 
  
   _splitpath( path_buffer, drive, dir, fname, ext ); 
  
   printf( "Path extracted with _splitpath:\n" ); 
   printf( "  Drive: %s\n", drive ); 
   printf( "  Dir: %s\n", dir ); 
   printf( "  Filename: %s\n", fname ); 
   printf( "  Ext: %s\n", ext ); 
}

7 FTP 관련
#include"CFTPTrans.h" 
 
CFTPTrans::CFTPTrans() 


 
CFTPTrans::~CFTPTrans() 

    DisConnect(); 

 
BOOL CFTPTrans::Connect(char *serverName, int port, char *username, char *password) 

    hInternet = InternetOpen("File Transfer for FTP", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0); 
    if(hInternet == NULL) 
    { 
        errCode = GetLastError(); 
        return FALSE; 
    } 
  
    hFtpSession = InternetConnect(hInternet, serverName, port, username, password, INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0); 
    if (NULL == hFtpSession) 
    { 
        InternetCloseHandle(hInternet); 
        errCode = GetLastError(); 
        return FALSE; 
    } 
    return TRUE; 

 
CFTPTrans::DisConnect() 

    InternetCloseHandle(hFtpSession);  
    InternetCloseHandle(hInternet); 

  
BOOL CFTPTrans::ChangeDirectroy(char *dirName) 

    if(!FtpSetCurrentDirectory(hFtpSession, dirName)) 
    { 
        errCode = GetLastError(); 
        return FALSE; 
    } 
    return TRUE; 

  
BOOL CFTPTrans::PutFile(char *source, char *destination) 

    if(!FtpPutFile(hFtpSession, source, destination, FTP_TRANSFER_TYPE_BINARY | INTERNET_FLAG_RELOAD, 0)) 
    { 
        errCode = GetLastError(); 
        return FALSE; 
    } 
    return TRUE; 
}

8 Downloaded Program Files 폴더의 OCX 삭제방법
typedef HRESULT (WINAPI *REMOVECONTROLBYNAME) 

             LPCTSTR lpszFile, 
             LPCTSTR lpszCLSID, 
             LPCTSTR lpszTypeLibID, 
             BOOL bForceRemove, 
             DWORD dwIsDistUnit 
); 
 
int _tmain(int argc, _TCHAR* argv[]) 

    HMODULE                   hMod; 
    REMOVECONTROLBYNAME       pfn =  NULL; 
 
    hMod = LoadLibrary("OCCACHE.DLL"); 
    if (hMod == NULL) 
    {   // Error loading module -- fail as securely as possible 
        return 0; 
    } 
 
    HRESULT hr; 
    pfn = (REMOVECONTROLBYNAME)GetProcAddress(hMod, "RemoveControlByName"); 
    if (pfn)  
    { 
        hr = (*pfn)(_T("C:\\WINDOWS\\Downloaded Program Files\\teechart5.ocx"), 
            _T("{B6C10532-FB89-11D4-93C9-006008A7EED4}"), 0, TRUE, TRUE); 
    } 
    FreeLibrary(hMod); 
 
    return 0; 

위에서 빨간 글자는 레지스트리에서 아래의 위치와 같습니다. 
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Code Store Database\Distribution Units 위 값의 하위키를 보면 숫자로된 키가 그것입니다. 
파란색 글자는 빨간색 숫자로된 키 밑에 '\Contains\Files' 로 들어가서 오른쪽 값을 참고하면됩니다.

 

9 디버깅 용도의 실행시간 출력 코드
디버깅시 TRACE로 시간정보를 출력하고 싶을때 사용한다.


#include <sys/timeb.h> 
 
void printCurrentTime() 

    time_t ltime; 
    struct _timeb tstruct; 
    struct tm *gmt; 
 
    time(<ime); 
    gmt = localtime(<ime); 
    _ftime( &tstruct ); 
    TRACE2("called - %u(ms) %s", tstruct.millitm, asctime(gmt)); 

예)


while(1) 

    Sleep(10); 
    printCurrentTime(); 

 
<실행결과> 
... 
called - 92(ms) Tue Oct 01 17:44:28 2002 
called - 102(ms) Tue Oct 01 17:44:28 2002 
...

10 Trace Tip
출처: http://www.codeproject.com/debug/tracetips.asp 
디버그 창에서 trace 메시지를 더블클릭하면 에디터 커서를 해당 라인으로 위치시킨다.


TRACE(_T("%s(%i) : Please double click on me!\n"), __FILE__,__LINE__);

11 모니터 끄기
PostMessage( GetDesktopWindow(),WM_SYSCOMMAND, SC_MONITORPOWER, 2 ); 

12 프로세스간 데이터 교환
보통 서로 다른 프로세스끼리 데이터를 주고 받을 때는 shared memory나 clipboard를 이용하는데 간단한 데이터를 주고 받을 때는 사용하기에 부담스러운 면이 있다. 이때 간편하게 이용할 수 있는 프로세스간 데이터 교환 방법을 이용한다.


1. GlobalAddAtom()을 이용한 데이터 전송 
예)


서버측: 
 
ATOM atom = GlobalAddAtom("This is test!");  
 
HWND hWnd = ::FindWindow(NULL, "AtomClinet");  
 
::PostMessage(hWnd, WM_MYMSG, 0, atom); // atom값을 전송  
 
클라언트측: 
void CATOMClientDlg::OnGetMsg(WPARAM wParam, LPARAM lParam)  
{  
    char vc_b[256];  
 
    ATOM atom = (ATOM)lParam;  
 
    GlobalGetAtomName(atom, vc_b, 256);  // vc_b를 사용  
}  
2. WM_COPYDATA를 이용한 데이터 교환


// source window에서..  
void CSourceWnd::Write(const void* lpBuf, UINT nCount)  
{  
       CWnd *pTraceWnd = CWnd::FindWindow(TRACEWND_CLASSNAME, NULL);  
 
       if (pTraceWnd) {  
              COPYDATASTRUCT cds;  
 
              cds.dwData = ID_COPYDATA_TRACEMSG /* Flag 용도 */;  
              cds.cbData = nCount;  
              cds.lpData = (void*)lpBuf;  
 
              pTraceWnd->SendMessage(WM_COPYDATA,  
                     (WPARAM)AfxGetApp()->m_pMainWnd->GetSafeHwnd(),  
                     (LPARAM)&cds);  
       } else {  
              AfxMessageBox("윈도우를 찾을 수 없습니다.");  
       }  
}  
 
//////////////////////////////////////////////////////  
// target windows에서..  
 
// 메세지 핸들링 설치  
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)  
       //{{AFX_MSG_MAP(CMainFrame)  
       ON_MESSAGE(WM_COPYDATA, OnTraceMsg)  
       .  
       .  
       .  
       //}}AFX_MSG_MAP  
 
END_MESSAGE_MAP()  
 
LRESULT CMainFrame::OnTraceMsg(WPARAM wParam, LPARAM lParam)  
{  
       COPYDATASTRUCT* pcds = (COPYDATASTRUCT*)lParam;  
 
       // pcds 를 사용한다..  
 
       return 0;  
}  
3. Shared section을 이용한 global variable 공유


#pragma data_seg("Shared") 
volatile LONG g_lSharedData = 0;   // initialized data 
#pragma data_seg() 
또는,


__declspec(allocate("Shared")) int g_nSharedData1 = 0;  // initialized data 
__declspec(allocate("Shared")) int g_nSharedData2;      // uninitialized data 
이때 dll의 프로세스간 데이타 공유라면 dll의 def파일에 데이타 공유 섹션을 지정해 줘야 한다.


SECTIONS 
        .Shared Read Write Shared 
이렇게 하면 g_lSharedData은 이 dll을 로딩한 모든 프로세스에서 공유해서 사용할 수 있다


4. File Map을 이용한 메모리 공유


// 
// 파일을 매핑하는 함수 
 
LPVOID InitFileMapping( HANDLE *phFileMap, char *pszShareName ) 
{      
     LPVOID lpMapView; 
 
     // 파일맵 핸들을 생성한다 
     *phFileMap = CreateFileMapping( (HANDLE)0xFFFFFFFF, NULL, PAGE_READWRITE, 
                              0, sizeof(DWORD), pszShareName ); 
     if( INVALID_HANDLE_VALUE == *phFileMap ) 
          return NULL; 
 
     // 파일을 매핑한다 
     lpMapView = MapViewOfFile( *phFileMap, FILE_MAP_ALL_ACCESS, 0, 0, 0 ); 
     if( NULL == lpMapView ) 
          return NULL; 
 
     // 매핑한 데이터의 선두번지를 리턴 
     return lpMapView; 

 
.... 
 
// 
// 파일맵 데이터를 쓰는 부분(1번 프로세스) 
pdwShare = (DWORD*)InitFileMapping( &hFileMap, dszFileMapName ); 
 
DWORD dwCount = 0; 
 
while( !( GetKeyState( VK_ESCAPE ) & 0x8000 ) ) 

     *pdwShare = ++dwCount; 
 
     printf( "Write - [%3d] %3d\n", dwCount, *pdwShare ); 
 
     Sleep( 500 ); 

 
... 
 
// 
// 파일맵 데이터를 읽는 부분(2번 프로세스) 
DWORD dwCount = 0; 
 
while( !( GetKeyState( VK_ESCAPE ) & 0x8000 ) ) 

     printf( "Read - [%3d] %3d\n", ++dwCount, *pdwShare ); 
 
     Sleep( 500 ); 

 
... 
 
// 파일매핑 해제 
UnmapViewOfFile( pdwShare ); 
CloseHandle( hFileMap );

13 Log 함수
윈도우 프로그래밍을 하다보면 가끔 dll 소스코드를 디버깅해야할 때가 있는데 이때 MSDEV의 디버거를 이용할수도 없기 때문에 디버깅하기가 까다롭다. 때론 printf대용인 MessageBox를 사용하기도 했는데 아무래도 썩 좋은 방법은 아니다. 이때 로그 함수를 만들어서 로그 파일을 생성하는 방법도 유용한 대안이다. 
아래는 Nasser Remy Rowhani라는 외국 친구가 쓴 코드인데 써보니 쓸만한 코드라 생각되서 소개한다. 굳이 디버깅 용도뿐만 아니라 API를 후킹하는 응용에서도 유용하게 쓸 수 있다.


#define LogFile "d:\\Logs\\LOG.txt"                   // log파일이 생성되는 위치 
#define Append(text) AppendLog(text, strlen(text))    // log를 기록하는 함수 
 
HANDLE   hLogFile=0;                // log파일의 핸들 
BOOL     IsLogging=false;           // log파일이 제대로 open되었는지 체크하는 플래그 
 
HANDLE OpenLog(char *Filename);     
BOOL CloseLog(HANDLE h=hLogFile);    
DWORD AppendLog(char *str, DWORD uSize, HANDLE h=hLogFile); 
 
HANDLE OpenLog(char *Filename) 

        HANDLE hLogFile; 
 
        hLogFile = CreateFile( Filename, GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_ALWAYS,0,0); 
        if(hLogFile!=INVALID_HANDLE_VALUE) 
                IsLogging = true;//SetFilePointer(hLogFile, 0,0, FILE_END);//*/ 
         
        return hLogFile; 

 
BOOL CloseLog(HANDLE h) 

        IsLogging = false; 
        return CloseHandle(h); 

 
DWORD AppendLog(char *str, DWORD uSize, HANDLE h) 

        DWORD written; 
        if(!IsLogging) return 0; 
 
        SetFilePointer( h, 0, 0, FILE_END ); 
        WriteFile(h, str, uSize, &written, 0); 
 
        return written; 

용례:


hLogFile = OpenLog( LogFile );   // 처음엔 log파일을 open한다. 
   ... 
sprintf(buf, "Error Code: %d", dwErr); 
Append(buf); 
   ... 
CloseLog();                     // 프로그램에서 exit할 때 log를 close

14 Ctrl+Esc, Alt+Tab, and Alt+Esc를 막는 법
출처: http://msdn.microsoft.com/msdnmag/issues/0700/win32


/************************************************************************ 
Module:  DisableLowLevelKeys.cpp 
Notices: Written 2000 Jeffrey Richter 
**************************************************************************/ 
 
#define _WIN32_WINNT 0x0400 
#include <Windows.h> 
 
LRESULT CALLBACK LowLevelKeyboardProc(int nCode,  
   WPARAM wParam, LPARAM lParam) { 
 
   BOOL fEatKeystroke = FALSE; 
 
   if (nCode == HC_ACTION) { 
      switch (wParam) { 
      case WM_KEYDOWN:  case WM_SYSKEYDOWN: 
      case WM_KEYUP:    case WM_SYSKEYUP:  
         PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT) lParam; 
         fEatKeystroke =  
            ((p->vkCode == VK_TAB) && ((p->flags & LLKHF_ALTDOWN) != 0)) || 
            ((p->vkCode == VK_ESCAPE) &&  
            ((p->flags & LLKHF_ALTDOWN) != 0)) || 
            ((p->vkCode == VK_ESCAPE) && ((GetKeyState(VK_CONTROL) &  
             0x8000) != 0)); 
         break; 
      } 
   } 
   return(fEatKeystroke ? 1 : CallNextHookEx(NULL, nCode, wParam,  
          lParam)); 

 
int WINAPI WinMain(HINSTANCE hinstExe, HINSTANCE, PTSTR pszCmdLine, int) { 
 
   // Install the low-level keyboard & mouse hooks 
   HHOOK hhkLowLevelKybd  = SetWindowsHookEx(WH_KEYBOARD_LL,  
      LowLevelKeyboardProc, hinstExe, 0); 
 
   // Keep this app running until we're told to stop 
   MessageBox(NULL,  
      TEXT("Alt+Esc, Ctrl+Esc, and Alt+Tab are now disabled.\n") 
      TEXT("Click \"Ok\" to terminate this application and re-enable 
            these keys."), 
      TEXT("Disable Low-Level Keys"), MB_OK); 
   UnhookWindowsHookEx(hhkLowLevelKybd); 
 
   return(0); 
}

15 About box에 URL 링크 걸기
About 대화상자에 웹으로 가는 링크를 넣는 방법. 이것은 액티브X 컨트롤을 이용하는 것이 가장 손쉬운 방법이다. IE에서 제공하는 오브젝트중 '마이크로소프트 웹브라우저'라는 것이 있는데 다음과 같이 하면 프로젝트에 포함된다.

 


1.Project 선택

2.Add to Project 선택

3.컴포넌트와 컨트롤 선택

4.Registered ActiveX Controls 폴더를 선택

5.Microsoft Web 브라우저라는 오브젝트 선택

6.컴포넌트 클래스 대화 상자에서 확인

7.대화상자 편집 모드에서 컨트롤 툴바에 등록된 웹브라우저 컨트롤을 대화상자에 드래그해 화면 디자인을 한다.

8.Class Wizard를 사용해서 Member Variable 탭에서 IDC_WEBxxx에 대한 데이터 멤버를 지정한다. 이때 Add Member Variable 대화상자의 category 콤보를 컨트롤로 지정

9.이제는 OnInitDialog등 원하는 지점에서 m_Webxxx로 지정된 멤버 객체 데이터를 사용해 다음과 같이 작성한다.

 m_WebBrowser.Navigate("http://dasomnetwork.com/~leedw", NULL, NULL, NULL, NULL); 
 위와 같이 해주면 대화상자가 기동 시에 동우의 홈페이지가 대화 상자에 나타날 것이다. 참고로 원격 사이트가 아닌 로컬에 html 문서를 미리 작성해서 가지고 있다가 URL 부분에 "file:///c:/My Documents/DHTML/ftv20/ftexample.html"라고 해주면 html이 나타난다.

 

16 특정 파일 오픈시 바로 프로그램 불러오기
ACDSee라는 그래픽 뷰어 프로그램같이 해당 그림 파일을 더블클릭하면 프로그램이 실행되면서 그 데이타를 불러오는 것과 같은 기능을 볼 수 있다. 이런 임의 파일의 싨행은 WinExec, ShellExecute API를 사용하면 구현할 수 있다. 여기서 원하는 것은 실행 파일 및 문서 파일들이므로 ShellExecute를 사용해야 한다.


HINSTANCE ShellExecute( 
    HWND hwnd,  
    LPCTSTR lpOperation, 
    LPCTSTR lpFile,  
    LPCTSTR lpParameters,  
    LPCTSTR lpDirectory, 
    INT nShowCmd 
);       
자세한 것은 MSDN 참조

 

17 드래그 앤 드롭으로 파일 오픈
윈도우 탐색기나 바탕 화면에서 드래그 앤 드롭으로 파일을 불러서 처리하고자 할 경우. 응용 프로그램에서의 드래그 앤 드롭의 처리는 InitInstance() 처리 부분에서 DragAcceptFiles라는 멤버 함수 또는 API를 수행하면 된다. 그러면 윈도우는 드래그 앤 드롭되는 것이 존재할 때 WM_DROP_FILES라는 메시지를 받는다.(이 메시지는 OnDropFiles(..)라는 멤버 함수가 처리한다.) 이 메시지에서 적당히 처리해주면 된다. 이것은 OLE와는 다른 것이니 주의한다.

 

18 app가 트레이에만 띄우도록 하려면
winamp같은 어플리케이션이 실행될 때 윈도우가 뜨더라도 상태바에는 뜨지 않고 트레이에만 생기는 모습을 보았을 것이다. 이것을 구현하려면 다음의 코드를 사용한다


void HideApplication(HWND hwnd) 

   ShowWindow(hwnd, SW_HIDE); 
   ShowOwnedPopups(hwnd, FALSE); 
    
   SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0, 
                 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); 

CApp 클래스에 위와 같은 이름을 가진 멤버 함수가 존재하는데 그 함수를 사용해도 된다. 실제 응용 프로그램을 태스크 바에서 사라지도록 하는 것은 SetWindowPos API에 있다. 또한 Shell_NotifyIcon이란 API가 있는데 이것을 이용해봐도 될 것이다.


WINSHELLAPI BOOL WINAPI Shell_NotifyIcon( 
    DWORD dwMessage,  
    PNOTIFYICONDATA pnid 
);       
주의해야할 것은 응용 프로그램은 메인 프레임을 가져야 하나 메인 프레임을 활성화시키지는 않도록 한다. 활성화만 안시키면 <Alt-Tab>에서 나타나지 않을 것이다. 대신 별도의 윈도우를 WS_POS으로 만들어 이를 트레이에 등록해야 한다. 즉, 트레이에 등록된 팝업 스타일의 윈도우가 모든 메시지를 가로채도록 하기 위함이다.

 

19 single thread 어플리케이션에 취소 버튼 구현
출처: http://www.fhcf.net/misc/id_ws/database/essays/fboyjoe/cancel/cancel.html


어플리케이션을 개발하다가 간혹 processor-intensive한 루틴을 작성해야할 때가 있다. 단일 쓰레드로 이를 구현했을 때는 하나의 루틴이 프로세서 자원을 다 잡아 먹기 때문에 윈도우즈 메시지를 처리할 수 없는 문제에 부딪힌다. 그래서 이때는 processor 자원을 많이 요구하는 연산 부분은 thread로 구현해서 돌려 놓고 원래의 thread는 윈도우 메시지를 처리하는 방법으로 구현을 한다. 그런데 별도의 쓰레드를 만들지 않고 단일 쓰레드에서 processor 자원 요구량이 많은 모듈과 윈도우즈 메시지를 동시에 처리할 수 있는 기법이 있어 소개한다.


결론을 미리 말하자면, processor-intensive한 연산 안에 message pump를 두어 메시지를 처리하도록 하며 유저가 언제든 취소를 원할 때 연산을 취소할 수 있도록 플래그를 검사하도록 하는 것이다. 플래그는 "취소"버튼을 눌렀을 경우에 셋팅되도록 한다. 핵심 부분을 코드로 살펴보면 다음과 같다.


void StartProcessing() 

   hCancelDialog = CreateDialog (inst, MAKEINTRESOURCE(IDD_DIALOG2),    
                               hwnd, CancelDialog); 
   ShowWindow (hCancelDialog, TRUE);          // 취소 버튼이 있는 대화 상자 출력 
   cancelled = 0;       // 취소 버튼이 눌렸는지에 대한 플래그 
    
   for ( ...) {       // 여기부터가 processor-intensive한 연산 부분이다. 
        .... 
    
        if(!MessagePump()) { // 연산 수행중에도 메시지를 처리할 수 있도록 한다. 
             return;       // WM_QUIT 메시지를 받으면 루틴을 빠져나간다. 
        }  
 
        if(cancelled) { 
            // 취소 플래그가 셋팅되면 연산을 중지한다. 
    
         .... 
    
   } 
   DestroyWindow(hCancelDialog); 
   EnableWindow(hwnd, TRUE); 
    
   .... 
 
BOOL MessagePump()        // 메시지 펌프 

   MSG msg; 
    
   while(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {  // 메시지 큐에 메시지가 있는지 체크 
      if (!GetMessage(&msg, NULL, 0, 0)) {    // 메시지를 가져온다. 
         PostQuitMessage(0); 
         return FALSE; 
      } 
      TranslateMessage(&msg); 
      DispatchMessage(&msg); 
   } 
   return TRUE; 

예제 프로젝트 : CancelTestApp.zip

 

20 PC시간 셋팅하기
void CSetDateDlg::OnOK()  

        // TODO: Add extra validation here 
 
        CTime time( 2005, 1, 10, 22, 17, 43 );  
        SYSTEMTIME sysTime; 
 
        time.GetAsSystemTime(sysTime); 
 
        if (getSystemType() == VER_PLATFORM_WIN32_NT) 
        { // NT 계열이면 시간을 바꿀 수 있는 특권을 가져와야 한다. 
                HANDLE hToken; 
                TOKEN_PRIVILEGES tp; 
                LUID luid; 
 
                OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken); 
                LookupPrivilegeValue(NULL, "SeSystemtimePrivilege", &luid); 
 
                tp.PrivilegeCount = 1; 
                tp.Privileges[0].Luid = luid; 
                tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 
                AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL); 
        } 
 
        SetLocalTime(&sysTime); 
         
        CDialog::OnOK(); 

 
void CSetDateDlg::getSystemType() 

        OSVERSIONINFO osv; 
 
        osv.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); 
        GetVersionEx(&osv); 
 
        return osv.dwPlatformId; 
}

 


출처: http://www.dasomnetwork.com/~leedw/mywiki/moin.cgi/win32_2f_c4_da_b5_e5_c6_c1?action=highlight&value=VisualC%2B%2B%C6%C1%C1%F6%B5%B5 

Posted by SB패밀리


VC++ 개발을 하면서... 난감한 상황들이 한 두번이 아니다.

그 중 간단한 MFC 프로그램을 작성하는데 가상머신에서 실행하려니 에러가 난다.

"응용 프로그램 구성이 올바르지 않기 때문에 이 응용 프로그램을 시작하지 못했습니다. 이 문제를 해결하려면 응용 프로그램을 다시 설치하십시오."



이런 에러가 난다.
좀 당황스럽다. 
VC++이 설치 되어 있지 않는 곳에서 실행하려면 도대체 무엇을 해줘야 하는가.
델파이에서는 런타임 라이브러리 팩키지 포함 옵션만 체크하면 문제가 없었는데 
VC++에서는 그런 옵션이 없다...

알아보니 마이크로소프트에서는 manifest 관리를 위하여 debug/release 모드와 VC++버전별로 dll 파일을 별도로 하고 있다.
그런데... 이것을 함께 묶을 수 있다거나 함께 배포할 수 있다는 말이 없다.

따라서 재배포해야한다는 말을 쉽게 찾아볼 수가 없는 상황에서 vcredistribution 에 관련된 설치 파일이 있어서 이를 찾아서 해당 윈도우즈 환경에 먼저 설치를 해줘야 한다는 것이다.

c:\Program Files\Microsoft SDKs\Windows\v6.0A\Bootstrapper\vcredist_x86\vcredist_x86.exe

이 파일을 설치해야 한다. 이것도 꼭 이 위치에만 있는 것은 아니다.
위의 경우는 내 VC++ 2008을 설치하고 검색해서 찾은 위치이다.
VC++ 2005에서는 다음 경로라고 알려져 있다.

C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\BootStrapper\Packages\vcredist_x86\vcredist_x86.exe 

이다. 

이런 당황스런 문제로 고생하는 사람들이 꽤나 있는 듯 하다.

헌데... 난 이것을 설치하고도 문제가 해결되지 않는다. 초 난감하다.



Posted by SB패밀리

[개발/VC++] WebBrowser HTML Element Events  핸들링




IDispEventSimpleImpl 의 SinkEvent 관련

[[ C++ - Header ]]
extern _ATL_FUNC_INFO OnClickEventInfo;
class CEventSink : public IDispEventSimpleImpl<1, CVCMapEventSink, &DIID__EventInterface>
{
    BEGIN_SINK_MAP(CEventSink )
        SINK_ENTRY_INFO(1,DIID__EventInterface, 1, OnClickEvent, &OnClickEventInfo)
    END_SINK_MAP()

    ...


public:
    void Start()
    {
        DispEventAdvise((IUnkown*) pClass);
    }
    void Stop();
    {
        DispEventUnadvise((IUnknown*) pClass);
    }

    void __stdcall OnClickEvent(int ID, bool selected);

private:
    _COMClassPtr pClass;
    CWnd* m_pTargetWnd;
}

[[ C++ - Cpp ]] 
_ATL_FUNC_INFO OnClickEventInfo= {CC_STDCALL, VT_EMPTY, 2, {VT_INT,VT_BOOL}};

void CEventSink::OnSelectedTeacher(int ID, bool selected)
{
    ...
}

/// main
void main()
{
    ...

    CEventSink  sink = new CEventSink(this);
    sink->Start();
    
    ...

    /// release
    sink->Stop();
    delete sink;    
    ...
}

Posted by SB패밀리

아래 쓰레드 생성함수에 관한 비교가 참 명쾌하게 되어 있습니다.



A Backwards Glance at Knole!
A Backwards Glance at Knole! by antonychammond 저작자 표시비영리동일조건 변경허락



출처 : http://naiades.tistory.com/6

윈도우즈에서 스레드를 생성하는 API는 CreateThread(), _beginthread(), _beginthreadex() 이렇게 3개의 함수가 존재합니다. 

CreateThread()와 _beginthread(), _beginthreadex()의 차이점은 다음과 같습니다.

  • CreateThread()는 스레드를 생성하는 기능만 담당한다.
  • _beginthread(), _beginthreadex()는 내부적으로 CreateThread() 를 사용하여 스레드를 생성하고 C Runtime library에서 내부적으로 필요로 하는 메모리 영역을 초기화 해주는 역할을 하게 됩니다. 초기화 되는 메모리 영역은 각 스레드 마다 따로 관리되게 됩니다.

  • 그렇다면 _beginthread(), _beginthreadex()의 차이는 무엇일까요? 의외로 이 차이에 대해서 대답을 명쾌하게 해주는 분이 많지가 않습니다. 이제부터 그 차이를 설명해 보도록 하겠습니다.
     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
      
    uintptr_t _beginthread( 
       void( *start_address )( void * ),
       unsigned stack_size,
       void *arglist 
    );
    
    uintptr_t _beginthreadex( 
       void *security,
       unsigned stack_size,
       unsigned ( *start_address )( void * ),
       void *arglist,
       unsigned initflag,
       unsigned *thrdaddr 
    );
    

    함수 원형을 보고 알 수 있는 파라메터에 의한 차이점은 다음과 같습니다.

    • _beginthreadex()는 security를 이용하여 보안 관련 설정을 할 수 있다.
    • _beginthreadex()는 initflag를 이용하여 스레드의 초기 동작을 정의 할 수 있다.
    • _beginthreadex()는 thrdaddr을 이용하여 thread id를 받을 수 있다.
    • _beginthreadex()는 __stdcall 형식의 함수 포인터를 thread 실행 함수로 받는다.
    • _beginthreadex()는 함수 실행 실패시에 0을 리턴한다. (_beginthread는 -1을 리턴한다.)
    • 여기에 더해서 가장 중요하게 기억해야 할 한가지의 차이점이 더 존재합니다. (이 내용이 글을 쓰는 이유이기도 합니다. ^^)
      _beginthread()는 스레드가 생성되고 스레드 함수의 실행이 종료 되면 스레드의 정리 작업을 해주게 됩니다. 이러한 형태는 편리한 점이 있지만 단점도 존재하게 되는데 바로 스레드의 실행 완료후에 해당 스레드의 정보를 조회 할 수 있는 방법이 없다는 것입니다. 

      예를 들어 스레드의 종료시에 exit 코드가 무엇인지 알기 위해서 GetExitCodeThread()를 사용할 수 있습니다. 이때 첫번째 인자로 스레드의 핸들을 파라메터로 넘겨줘야 되는데 _beginthread()로 생성된 스레드의 핸들은 GetExitCodeThread()를 사용할 수 없습니다. 

      1
      2
      3
      4
      
      BOOL WINAPI GetExitCodeThread(
        HANDLE hThread,
        LPDWORD lpExitCode
      );
      

      왜 그럴까요? _beginthread()로 생성된 스레드 핸들은 스레드 함수의 실행이 종료될 때 _beginthread() 내부에서 CloseHandle()을 호출하기 때문에 프로그래머가 GetExitCodeThread()를 사용할 수 있는 시점에서는 이미 소멸된 핸들이 되기 때문입니다.

      _beginthreadex()는 위와 같은 문제를 해결하기 위해 스레드가 종료될때 내부적으로 CloseHandle()를 호출하지 않고 사용자가 명시적으로 해제하도록 변경되었습니다.

      결과적으로 내용을 정리하면 다음과 같습니다.

      • _beginthread()로 생성된 스레드 핸들은 스레드 종료시에 CloseHandle()이 내부적으로 호출되어 신경쓸 필요가 없지만 스레드 함수 완료 후 스레드 핸들을 이용한 어떠한 API 함수도 실행 시킬 수 없습니다.
      • _beginthreadex()로 생성된 스레드 핸들은 스레드가 실행완료된 후 내부적으로 CloseHandle()을 실행시키지 않기 때문에 스레드 핸들을 이용한 API 함수를 실행할 수 있지만 사용자가 명시적으로 CloseHandle()을 호출해 주어야 합니다. 만약 CloseHandle()을 해주지 않으면 핸들이 계속 쌓이게 되는 Resource leak이 생기게 됩니다.


Posted by SB패밀리

외부 프로세스 실행을 위한 소스
아래 함수는 Windows 7 에서 관리자 권한으로 실행이 가능하게 하는 코드이다.
MFC 개발하시분 분들에게는 많이 유용할 것이다.
쌈꼬쪼려 소백촌닭

=======================================================
사례1

// 프로세스 실행
BOOL SBRICH::ExecuteProcess(CString FilePath, CString Parameter)

 //TCHAR path[1024] = {0,};
 //::GetModuleFileName(NULL, path, 1024);
 BOOL bRes = FALSE;

 if(OSVersionXPOver())
 {
  // 관리자 모드로 실행
  SHELLEXECUTEINFO exeInfo = {0,};

  exeInfo.cbSize = sizeof(SHELLEXECUTEINFO);
  exeInfo.hwnd = NULL;
  exeInfo.fMask = SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI;
  exeInfo.lpVerb = _T("runas");
  exeInfo.lpFile = FilePath;
  exeInfo.lpParameters = Parameter;
  exeInfo.nShow = SW_SHOWNORMAL;

  bRes = ::ShellExecuteEx(&exeInfo);

 }
 else
 {
  //xp 이하이므로 그냥 호출.
  if( ::ShellExecute(NULL, _T("open"), FilePath, Parameter, NULL, SW_SHOW) == (HINSTANCE)HINSTANCE_ERROR)
   bRes = FALSE;
  else
   bRes = TRUE;
 }

 return bRes;
}


===================================================================
사례2

// 프로세스 실행
BOOL SBRICH::ExecuteProcess(CString FilePath, CString Parameter)

 //TCHAR path[1024] = {0,};
 //::GetModuleFileName(NULL, path, 1024);
 BOOL bRes = FALSE;

 if(OSVersionXPOver())
 {
  // 관리자 모드로 실행
  CString sRun;
  STARTUPINFO si;
  PROCESS_INFORMATION pi;
  ZeroMemory(&si, sizeof(si));
  si.cb = sizeof(si);
  si.lpDesktop = "winsta0\\default";
  ZeroMemory(&pi, sizeof(pi));

  sRun = FilePath;
  sRun += Parameter;
  // start the child process
  if (!CreateProcess(NULL, // no module name (use command line)
   (LPSTR)(LPCSTR)sRun, // Command line
   NULL, // Process handle not inheritate
   NULL, // Thread handle not inheritate
   FALSE, // Set handle inheritance to FALSE
   0, // No creation flags
   NULL, // Use parent's environment block
   NULL, // Use parent's starting directory
   &si, // Pointer STARTUPINFO structure
   &pi) // Pointer to PROCESS_INFORMATION structure
   )
  {
#ifdef _DEBBUG
   fprintf(Filelog, "CreateProcess Failed (%d)\n", GetLastError());
   Filelog.flush();
#endif
   return FALSE;
  }
  // wait until child process exits
  WaitForSingleObject(pi.hProcess, INFINITE);
  // Close process and thread handles;
  CloseHandle(pi.hProcess);
  CloseHandle(pi.hThread);   


 }
 else
 {
  //xp 이하이므로 그냥 호출.
  if( ::ShellExecute(NULL, _T("open"), FilePath, Parameter, NULL, SW_SHOW) == (HINSTANCE)HINSTANCE_ERROR)
   bRes = FALSE;
  else
   bRes = TRUE;
 }

 return bRes;
}

Posted by SB패밀리

실행중인 IE의 URL 구하기



IE 의 URL을 구하는 것은 생각보다 쉽습니다.

좋은 예제파일이 함께 있어서 올려봅니다.


따라해 보세요.


실행중인 IE의 URL 구하기


// URL을 추출합니다. ASSERT(m_spSHWinds != NULL);

long nCount = m_spSHWinds->GetCount();

IDispatchPtr spDisp;

for (long i = 0; i < nCount; i++)

 _variant_t va(i, VT_I4); 

 spDisp = m_spSHWinds->Item(va); 

 SHDocVw::IWebBrowser2Ptr spBrowser(spDisp);

 if (spBrowser != NULL)  

  m_ctrlUrlList.AddString(spBrowser->GetLocationURL());

 

출처 : 인터넷

Posted by SB패밀리