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

[개발/VC++] ATL Window Class 종류



ATL 은 COM을 지원하기 위해 디자인 되었지만 윈도우를 모델링 하는 클래스 영역도 포함한다고

한다. 그리고 ActiveX 같은 윈도우를 가지는 객체도 만들수 있다.

아래는 ATL 에서의 주요 윈도우 클래스들이다.

 

 CWindow - 윈도우를 조작하기 위한 Win32 APIs의 작은 랩퍼 클래스이다.

                    윈도우 핸들과 HWND 를 CWindow 로 변환하는 오퍼레이터를 포함한다.

                    그러므로 윈도우 핸들을 필요로하는 어떤 함수에 CWindow 오브젝트를

                    넘길수 있다.

 CWindowImpl - 이미 존재하는 윈도우를 서브클래싱 하거나 이미 존재하는 클래스를

                    수퍼클래싱 하거나 , 윈도우 베이스의 새로운 윈도우를 만들때

                    사용한다.
 CContainedWindow - 다른 클래스의 메세지 맵을 위한 메세지 경로를 구현한 윈도우

                    클래스이다. 이 클래스는 하나의 클래스에 메세지 처리를 집중하는 것을 허락한다.

 CAxWindow - 컨트롤을 만들거나 존재 하는 컨트롤에 붙임으로써 ActiveX control

                    호스트 윈도우 구현을 지원한다. 
 CDialogImpl - 모달이나 모달리스 다이얼로스를 구현한다. IDOK 나 IDCANCEL 같은

                    기본 메세지 경로를 지원한다.
 CSimpleDialog - 단순 모달 다이얼로그를 주어진 리소스 ID로 구현한다. IDOK나 IDCANCEL과

                    같은 기본 메세지 맵을 기지고 있다.
CAxDialogImpl - CDialogImpl 과 같이 모달과 모달리스를 를 구현하는 베이스 클래스로 사용되

                    며 상속된 클래스에 기본 메세지 맵을 제공한다.
                    추가로 ActiveX 컨트롤을 지원한다. ATL 오브젝트 위저드에서 CAxDialogImpl에

                    상속된 클래스를 프로젝트에 넣은 것을 지원한다.

CWndClassInfo -  새로운 윈도우 클래스의 정보를 보관한다.

                    특별히 WNDCLASSEX를 캡슐화한다.

CWndTraits and CWinTraitsOR - ATL 윈도우 오브젝트의 스타일을 캡슐화한다





Posted by SB패밀리

[VC] IE에 사용자 툴바를 설치후에 기본으로 보이게 하는 방법





IE에 새 툴바밴드를 설치하고 새 IE를 실행했을때 기본으로 툴바가 IE에 보여지도록 하는 방법에 대한 문서이다. 혹자는 이것이 왜 필요하냐고 물을수도 있는데, 한마디로 필요하다. 

왜냐하면 설치를 했다면 당연히 눈여보여서 동작하는 것이 사용자의 기대동작이기 때문이다. 만약 IE에서 툴바를 켜는 방법을 모르는 사용자가 있다면 어떨까? 설치를 한 의미가 없어진다. 사용을 촉진시키고, UI를 보여줌으로써 관심을 일으키는 것이 마케팅일것이다.

1 툴바 DLL의 기본 설정을 이용하는 방법 

이 방법을 알아낸다면 밑에 있는 방법은 다 없어도 된다. 이 방법은 웹 검색과 구글검색으로도 쉽게 알아내지 못했다. IE의 툴바 레이아웃은 
HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Toolbar
There are 3 sub keys: Explorer, ShellBrowser, WebBrowser'
In each of these sub-keys is the entry for ITBarLayout 
For IE Toolbars: The WebBrowser Sub-key directly affects IE.
For Windows Explorer Toolbars: The Explorer Sub-key directly affects Explorer.
The ShellBrowser sub-key may affect IE as well. Its effect on IE and Windows Explorer is unknown at this time, so if the first option doesn't work, delete the ITBarLayout value here as well.
Choose the relavent sub-key and right click where it says ITBarLayout and select Delete. 
The deleted value will automatically be recreated for you.

이런식으로 저장이 된다. 문제는 ITBarLayout에 레이아웃 구조체가 저장되는데 이 키를 지우면 모든 레이아웃 정보가 사라지고 IE가 디폴트로 툴바 레이아웃을 생성하는데, 이때 특정 툴바는 기본으로 뜬다는 것이다. 설치하고 나서 기본으로 뜨고 사용자가 안 보이게 하면 그때 부터 안 보인다. 이런 설정은 어떻게 하는 것일까? 만들때 어떤 옵션을 주는것 같기도 하고. 만약 방법을 찾게 되면 이 페이지에서 가장 강조되는 블럭으로 말들어 놓겠다.

2 html을 이용하는 방법 

이 방법은 해당 툴바를 Object 태그로 HTML에 삽입하는 방법이다. 다시 말해서 해당 COM객체를 IE에서 실행하라고 알리는 것이다. 설치가 끝나고 나서 인스톨러가 설치가 완료되었다는 깜찍하고 작은 IE를 띄우는것은 애교로 봐 줄만하다. 그 IE가 띄우는 페이지에 저 Object에 툴바의 클래스 아이디를 넣는다는 얘기이다. HTML에서는 COM객체를 로드할 것이고, 그 객체는 툴바DLL이기 때문에 당연히 IE에 리바영역에 나타날 것이다. 

문제점이있다. 어떤 툴바는 로드되지 않는다. 내가 뜨기를 원하는 툴바에서는 안 뜨고 다른 툴바는 성공적으로 뜨는 바람에 바로 다른 방법을 강구하기 시작했는데, 자기가 배포하려는 툴바가 이 방법으로 잘 되는지 확인해 볼 필요가 있다. 

주의할 점은 winxp sp2에서는 기본 보안설정으로는 DLL이 로드되지 않는다는 점이다., IE의 보안레벨에 의존적이다.

3 IE 메뉴를 이용하는 방법 

새로운 IE를 실행하면서 그 IE의 IEFrame핸들을 얻을 수 있는데 그 윈도우 핸들에 WM_COMMAND를 보내는 방법이다. 이 경우, 예를들면 Ctrl+N과 같은 IE의 기본적인 값은 spy++로 확인해 보면 항상 같다는 점을 알 수 있다. 그래서 테스트 결과 WM_COMMAND로 wParam에 그 값을 넣어서 보내면 정확히 그 메뉴가 실행된다. 이 점을 응용하면 보기-툴바에서 우리 툴바의 메뉴아이템의 ID를 구하기만 하면 되는 것이다. 그 ID는 항상 동적이다. 설치된 툴바의 갯수나 설치된 순서에 따라 다르기 때문이다. 그래서 IE의 메인메뉴를 HMENU를 구하고 거기서 모든 메뉴 아이템을 얻어서 우리가 원하는 메뉴 캡션을 찾아내면 그 메뉴 아이템의 ID가 우리가 찾는 ID가 되는 것이다.

[치명적 문제점]
메인메뉴의 HMENU 값을 구할 수가 없다? 일단 GetMenu(HWND) 는 메뉴가 없다. 왜 그럴까? IE의 메인메뉴는 메뉴바라고 하는 툴바에 올라가 있고, 팝업메뉴로 나타나기 때문이다. HMENU만 알아낸다면 확실히 효율적이고 안정적인 좋은 방법이다.

4 IWebBrowser2를 이용하는 방법 




STDMETHODIMP CShowBarObj::SetSite(IUnknown *pUnkSite)

(

 if (NULL != pUnkSite)

 {

  IWebBrowser2 *pBrowser = NULL;

  // Ensure that our site is an browser window

  HRESULT hr = pUnkSite->QueryInterface(IID_IWebBrowser2, (void **) &pBrowser);

  if (SUCCEEDED(hr))

  {

   // Display the band object (the Search bar in this case)

   VARIANT vtBandGUID, vtShow;

   vtBandGUID.vt = VT_BSTR;

   vtBandGUID.bstrVal = SysAllocString(OLESTR("{30D02401-6A81-11D0-8274-00C04FD5AE38}"));

   vtShow.vt = VT_BOOL;

   vtShow.boolVal = true;

   VARIANT vret;

   pBrowser->ShowBrowserBar(&vtBandGUID, &vtShow, &vret);

   SysFreeString(vtBandGUID.bstrVal);

   pBrowser->Release();

  }

 }

 return S_OK;

}




이 코드인데 이 코드를 툴바(툴바는 문제가 있는데 툴바는 켜지 않으면 DLL을 로드하지 않기 때문이다.)나 BHO에 넣으면 잘 동작한다. 그러나 IE를 실행하고 그 실행한 IE의 IWebBrowser2의 ShowBrowserBar를 호출하면 절대로 동작하지 않는다. 그것이 문제이다. 일단 그 이유를 모르겠다. 한가지 생각나는 이유라고는 TopLevel의 IWebBrowser2가 아니기 때문이 아닐까 싶기도 한데, 사실상 그런 이유때문은 아닌것 같다. 

아래 코드는 Activex에서 탑 레베의 IWebBrowser2를 얻는 코드이다. 나중에 참조해 볼 것.





#include <SHLGUID.h>

#define COMRELEASE(ptr)

if (ptr != NULL) 

{

ptr->Release();

   ptr = NULL;

}

IWebBrowser2 *browser = NULL;

STDMETHODIMP SetClientSite(IOleClientSite *pClientSite) 

{

  HRESULT hr = S_OK;

   IServiceProvider *isp, *isp2 = NULL;

    if (!pClientSite)

{

 COMRELEASE(browser);


else

{

hr = pClientSite->QueryInterface(IID_IServiceProvider, reinterpret_cast<void **>(&isp));

if (FAILED(hr)) 

{

hr = S_OK;

goto cleanup;

}

hr = isp->QueryService(SID_STopLevelBrowser, IID_IServiceProvider, reinterpret_cast<void **>(&isp2));

if (FAILED(hr))

{

hr = S_OK;

goto cleanup;

}

hr = isp2->QueryService(SID_SWebBrowserApp, IID_IWebBrowser2, reinterpret_cast<void **>(&browser));

if (FAILED(hr)) 

{

hr = S_OK;

goto cleanup;

}

cleanup:

// Free resources.

COMRELEASE(isp);

COMRELEASE(isp2);

return hr;

}

}


5 BHO를 이용하는 방법 

이 방법이 그나마 안정적이고 좋은방법 같다. ShowBrowserBar를 BHO에서 동작하도록 하는 것이다. BHO의 SetSite에서 우리가 원하는 툴바를 보이게 만들고 DLL을 등록해제해서 (레지스트리 삭제) 다음 IE에서는 이 DLL을 다시 로드하지 않도록 하는 방법이다. 

bho등록
IE를 안 보이게 실행
로드된 bho에서 우리가 원하는 툴바를 보이게 함
IE를 종료함 WM_CLOSE를 보내거나 ->Quit를 호출함
bho등록해제
bho dll삭제

와 같은 순서로 동작한다.

6 레이아웃 레지스트리를 조작하는 방법

레지스트리는 바이네리 데이타이다. 상식적으로 생각했을때 그건 IE내부에서만 사용되는 어떤 구조체일 것이고, 그 내막은 파악하기는 소스가 없다면 리버스엔지니어링이라고 불리는 삽질을 하는 수 밖에 없는 법이다. 당행스럽게도 나에겐 win2k src가 있었는데 없었다면 감히 삽질하려고 시도조차 하지 않았을 것이다. 그런데 그런 시도를 이미 한 사람이 있었으니 내가 감탄하지 않을 수 없었다. 구조체는


typedef struct tagCOOLBARSAVE
{
  UINT cbVer;
   UINT uiMaxTBWidth;
    UINT uiMaxQLWidth;
#ifdef UNIX
    BITBOOL fUnUsed : 28; // unused
#endif
  BITBOOL fVertical : 1; // The bar is oriented vertically
   BITBOOL fNoText :1; // "NoText"
    BITBOOL fList : 1; 
// toolbar is TBSTYLE_LIST (text on right) + TBSTYLE_EX_MIXEDBUTTONS
BITBOOL fAutoHide : 1; // Auto hide toolbar in theater mode
    BITBOOL fStatusBar : 1; // Status bar in theater mode
BITBOOL fSaveInShellIntegrationMode : 1; 
// Did we save in shell integration mode?
UINT uiVisible; // "Visible bands"
UINT cyRebar;
BANDSAVE bsCBANDSMAX;
CLSID aclsidExternalBands[ MAXEXTERNALBANDS ]; // Check classid
CLSID clsidVerticalBar; //clsid of bar persisted within vertical band
CLSID clsidHorizontalBar;
} COOLBARSAVE, *LPCOOLBARSAVE;




이렇다. 소스 코드를 분석해 본 결과 상당히 복잡한 방법으로 bs 멤버와 aclsidExternalBands에 저장되는 순서가 어떤 함수로 관계지어지고 uiVisible에 교묘한 방법으로 계산한 bit를 OR시켜야 한다. 등등 상당히 복잡한 방법으로 저장이 되고 있다는 점이다. 내가 수십시간에 걸쳐 분석하고 완성한 소스가 있지만 그것조차 100% 완벽하다고 장담하지 못하겠다. 솔직히 MS얘네들 간단한 내용을 왜 이렇게 복잡하게 만들었는지 모르겠다. 그냥 최대 15개의 툴바를 지원하므로 15개의 툴바에 구조체를 할당하고 보임 안보임 BOOL 변수와, 스타일 변수, 위치변수 3개만 있으면 다 될것 같은데, 뭐가 그리 복잡하게 만드어 놨는지. 간단하고 읽기좋고 단순한 알고리즘으로 충분히 리팩토링이 필요한 소스가 아닌가 하는 개인적인 불만이 있다.

7 가장 확실한 방법 



#include <mshtml.h>
void CDeletmeDlg::OnButton1()
{
 CoInitialize(NULL);
 IWebBrowser2 *pIE;
 HRESULT hr =  CoCreateInstance(CLSID_InternetExplorer, NULL,
  CLSCTX_LOCAL_SERVER,
  IID_IWebBrowser2,(void**)&pIE);
 pIE->put_Visible(VARIANT_TRUE);
 VARIANT vtBandGUID;
 VARIANT vtShow;
 VARIANT vtRet;
 vtBandGUID.vt = VT_BSTR;
 vtBandGUID.bstrVal = ::SysAllocString( L"{5258771B-ACBE-4974-8ABC-AE4969A2A5CD}" );
 vtShow.vt = VT_BOOL; 
 vtShow.boolVal = VARIANT_TRUE; //** 주의 true가 아니라 VARIANT_TRUE이다.
 vtRet.vt = VT_INT;
 vtRet.intVal = 1;
 //**주의 vtRet는 리턴값이므로 반드시 읽어야 한다.
 //NULL을 넣으면 제대로 동작하지 않는다..
 hr = pIE->ShowBrowserBar(&vtBandGUID, &vtShow, &vtRet); 
 SysFreeString(vtBandGUID.bstrVal);
 //주소바가 보이도록 설정되 있으면
 VARIANT_BOOL b;
 pIE->get_AddressBar(&b);
 if(b == VARIANT_TRUE)
 {    
  HWND hWnd=0;
  pIE->get_HWND((long*)&hWnd);
  if(::IsWindow(hWnd))
  {
   //수동으로 안 보이게한다.
   //put_AddressBar는 현재창에서는 되지만 종료하고 닫으면 주소바가 다시 보이게 되어 있다.
   //따라서 사용자가 메뉴를 누른것처럼 동작하도록 한 다면 리바의 위치정보를 즉시 다시 기록하게 된다.
   ::PostMessage(hWnd, WM_COMMAND, 41477, 0);
  }
 }
 pIE->Release();
}



내가 미처 몰랐는데 이 방식이 있다. 주의라고 표시되지 않은 부분에서 내가 실수를 해서 안 되었던 것이고, 이제 하니 잘 된다. 툴바를 새 줄로 놓는다면 그건 DLL에서 GetHostInfo인가 하는 함수에서 _BREAK을 제거하면 된다.




Posted by SB패밀리

MFC Active 생성





1. Workspace 생성

    MFC ActiveX control wizard를 선택.

2. Property 생성(메뉴 View > ClassWizard)

    1) ClassWizard의 Automation tab에서 선택
    2) Class name에서 Control class 선택(...Ctrl)
    3) (Add Property...) 버튼 클릭
    3) External name: ActiveX를 사용하는 프로그램에서 사용할 property name
    4) Type: property type
    5) Variable name: ActiveX 내부에서 사용할 property 변수명
    6) Notification function: property 값이 변경되면 실행되는 함수. 별로 사용하지 않는다.
    7) Implementation:
        - Member variable: 외부에서 ActiveX.propertyName = value 형태로 사용하는 방법
        - Get/Set methods: GetPropertyName(), SetPropertyName() 형태로 사용하는 방법

    ☞ 이렇게 하면,
        Conrol class에 해당 member 변수가 생성되는데, 변수명은
        Variable name에 설정된 이름으로 생성된다.

3. Method 생성

    1) ClassWizard의 Automation tab에서 선택
    2) Class name에서 Control class 선택(...Ctrl)
    3) (Add Method...) 버튼 클릭
    4) External name: ActiveX를 사용하는 프로그램에서 사용할 method 이름
    5) Internal name: ActiveX 내부에서 사용할 때 사용할 이름
    6) Return type: method를 호출했을 때, 결과로 넘겨줄 값의 type
    7) Parameter list: method에 넘겨줄 parameter와 그 type
    
    ☞ 이렇게 하면,
        Conrol class에 해당 method가 member함수로 생성되는데,
        함수 이름은 "Internal name"으로 생성된다.
        이 함수에 필요한 logic을 코딩하면 되며,
        ActiveX를 사용하는 프로그램에서 "External name"으로 설정된
        함수를 call하면, ActiveX에서는 "Internal name"으로 설정된
        함수가 실행된다.

4. Event 생성

    1) ClassWizard의 ActiveX Events tab 선택
    2) Class name: Control class 선택(...Ctrl)
    3) (Add Event...) 버튼 클릭
    4) External name: ActiveX를 사용하는 program에서 사용할 event name
    5) Internal name: ActiveX 내부에서 사용할 event name
    6) Parameter list: event도 하나의 함수다. 이 함수에 넘겨줄 parameter와
        그 type을 정의한다.

    ☞ 이렇게 하면,
        Conrol class의 Header file에 "Internal name"으로 설정된 void type의 함수가
        "AFX_EVENT(CSamAxCtrl)" event map으로 생성된다.
        ActiveX의 원하는 곳에서 이 함수를 call하면,
        ActiveX를 사용하는 프로그램에서 해당 event가 발생하게 된다.
    
5. 필요한 code 작성

    4번까지 하면, 기본적으로 ActiveX control이 작성된 것이다.
    여기에 필요한 logic을 작성한 다음 compile하면 ocx 파일이 생성된다.
    
6. CLSID 알아내기

    만들어진 ActiveX control을 웹에서 사용하기 위해서는 기본적으로 CLSID를 알아야 한다.
    이것은 VC++의 FileView에서 ".odl" 파일을 살펴보면 알 수 있다.
    ".odl" 파일의 맨 하단을 보면 다음과 같은 주석을 볼 수 있다.
    
         //  Class information for CExActiveX2Ctrl
    
    그리고, 그 밑에 아래와 같은 코드를 볼 수 있다.
    
        [ uuid(4AA8A54C-8F74-4F9F-8D3C-BD1079A73AD8),
          helpstring("ExActiveX2 Control"), control ]
    
    위 코드에서 "uuid"가 바로 CLSID 이다.

참고 : http://cafe.naver.com/swnara/145

Posted by SB패밀리

[개발/VC++] 유니코드 버전으로 된 프로젝트에서 CString 를 char* 로 바꾸는 방법





MFC에서 유니코드 버전으로 된 프로젝트에서 CString 를 char* 로 바꾸는 방법은
유니코드 상태에서 CString 을 바로 CHAR* 로 바꾸는 것이 안됩니다.

W2A 나 A2W 로 코드 변환을 하거나 wsprintf(); 함수를 이용 하면 됩니다.

유니코드는 사용 되는 바이트 수가 2바이트이고 1바이트 문자열로 변환하면 깨져 버리는 문자열 들이 있는데  처리를 해야 합니다. 

유니코드를 멀티바이트 코드로 변환 하려면 

char Text[80];
wsprintfA(Text, "%S", L"문자열" );

멀티바이트 코드를 유니코드로 변환 하려면 

WCHAR Text[80];
wsprintfW(Text, L"%S", "문자열" );


변환될 문자열을 %S(대문자)로 wsprintf()함수를 사용합니다.

※ 현재로써는 바로 CString 에서 char*(LPSTR , LPCSTR) 로 변환 할수 없습니다. 

참고로 더 설명을 하면 CString 기본 요소는 CStringBase<WCHAR>  , CStringBase<CHAR> 둘로 나누어집니다.
이 두 클래스 사이에서 바로 입력 변환이 불가능 합니다. 

변환시에는 API 함수로 코드 변환 후에 사용 해야 하며 
CStringBase<CHAR> 로 사용 한다면 유니코드 내에서 ANSI 코드를 사용 할 수 있습니다. 

또 다른 방법의 함수
-----------------------------
CString을 유니코드로

CString tmp("test");
WCHAR m_wPath[MAX_PATH];

wcscpy(wPath,tmp.GetBuffer(0));



Posted by SB패밀리

1. DC얻기

CClientDC dc(this);


2. Client 영역 구하기

GetClientRect(&rect);

WM_SIZE 메시지발생후 cx,cy 사용


3. 문자열 사각형안에 그리기

pDC->DrawText(문자열,사각형,Style);

Style : DT_BOTTOM - 문자열을 사각형 맨아래줄에배열 반드시DT_SINGLELINE과 함께사용

DT_CENTER - 문자열을 가로중앙에 배치

DT_VCENTER - 문자열을 세로중앙에 배치

DT_LEFT,RIGHT - 문자열을 좌,우로 배치

DT_SINGLELINE - 문자열을 한줄로만 쓴다


4. Brush 사용법

CBrush brushname(RGB(red,green,blue)); //브러쉬 생성

//이전Brush 저장, 새로운 Brush 선택

CBrush *oldBrush=pDC->SelectObject(&brushname);

pDC->SelectObject(oldBrush); //원래의 브러쉬로 반환


5. Pen사용법

CPen pen(Pen Style,RGB(red,green,blue)); //브러쉬생성

//Style: PS_SOLID,PS_DASH,PS_DOT,PS_DASHDOT,PS_GEOMETRIC,PS_COSMETRIC

- 펜종류

PS_ENDCAP_ROUND,PS_ENDCAP_SQUARE - 펜끝을 둥글게,각지게 설정

CPen *oldPen=pDC->SelectObject(&pen); //이전Pen저장, 새로운 Pen설정

pDC->SelectObject(oldPen); //펜반환


6. 화면다시그리기

View Class에서 - Invalidate(TRUE) : 화면을 지우고다시그린다

Invalidate(FALSE) : 화면을 덮어씌운다

UpdateAllViews(NULL); // Doc Class에서 View 의 OnDraw 호출

RedrawWindow();


7. 메시지,함수 수동으로 넣기 (EX)버튼클릭함수넣기

헤더파일의 AFX_MSG_MAP 부분에 함수를 정의

// .cpp파일의 AFX_MSG 부분에 메시지를 추가한다

EX) afx_msg void funcName();

// ID 등록: View 메뉴의 Resource Symbol 에 들어가서 메뉴 ID 를 등록해준다..

EX) ON_BN_CLICKED(ID_NAME,funcName).

// .cpp파일의 맨아래에서 함수를 정의한다

EX) void CClass::funcName() { ... }


8. 마우스커서 바꾸기

리소스탭에서 커서를 그리고 저장한뒤 ID값은 준다음

SetCapture(); //커서의입력을 클라이언트영역을 벗어나더라도 받아낸다

SetCursor(AfxGetApp()->LoadCursor(nIDResource));

//APP클래스의 LoadCursor View의 SetCursor 사용

ReleaseCapture(); //SetCursor()상태를 해제한다


9. 색상표 사용하기

CColorDialog dlg;

if(dlg.DoModal()==IDOK) //Dialog 를 띄운후 OK버튼을누르면 실행할부분

MemberFunc: GetColor() //선택된 색상을 받아온다 return 형은 COLORREF 형


10. 팝업메뉴 만들기

CMenu menu; //메뉴 객체생성

CMenu *pmenu; //메뉴 포인터생성

menu.LoadMenu(IDR_MAINFRAME); //메뉴를 불러온다

pmenu=menu.GetSubMenu(3); //메뉴의 3번째 메뉴를 가져온다

menu.CheckMenuItem(ID_MENU,m_kind==ID_MENU ? MF_CHECKED : MF_UNCHECKED); //메뉴 체크하기 (메뉴 ID, ID 체크조건)

pmenu->TrackPopupMenu(TPM_LEFTALIGN,point.x,point.y,this) //(TMP_Style,x좌표,y좌표,hWnd) 메뉴 띄우기


*주의사항*

[안내]태그제한으로등록되지않습니다-OnContextMenu(CWnd* pWnd, CPoint point) //여기서 point 는 스크린 기준이고,

OnRButtonDown(UINT nFlags, CPoint point) //여기서 point 는 클라이언트 기준이다!


11. 클라이언트 포인터를 스크린 포인터로 변경

ClientToScreen(&point);


12. 그림판기능

if(m_flag==FALSE) return; //m_falg=그리기 기능 참,거짓설정 그리기 아니면 빠져나간다

CClientDC dc(this);

CPen myPen(PS_SOLID,m_width,m_color);

CPen *pOldPen=dc.SelectObject(&myPen);

switch(m_shape)

{

case ID_FREELINE: //자유선그리기

dc.MoveTo(m_oldpt.x,m_oldpt.y); //지난포인터부터

dc.LineTo(point.x,point.y); //새포인터까지 그린다

break;

case ID_RECT: //사각형그리기

dc.SetROP2(R2_NOTXORPEN);

dc.Rectangle(m_spt.x,m_spt.y,m_oldpt.x,m_oldpt.y); //지워지는 효과

dc.Rectangle(m_spt.x,m_spt.y,point.x,point.y); //그려지는 효과

break;

case ID_ELLIPSE: //원그리기

dc.SetROP2(R2_NOTXORPEN);

dc.Ellipse(m_spt.x,m_spt.y,m_oldpt.x,m_oldpt.y); //지워지는 효과

dc.Ellipse(m_spt.x,m_spt.y,point.x,point.y); //그려지는 효과

break;

case ID_LINE: //선그리기

dc.SetROP2(R2_NOTXORPEN);

dc.MoveTo(m_spt.x,m_spt.y); //시작점부터

dc.LineTo(m_oldpt.x,m_oldpt.y); //지난점까지 그은선을 지운다

dc.MoveTo(m_spt.x,m_spt.y); //시작점부터

dc.LineTo(point.x,point.y); //새로운점까지 그린다

break;

}

m_oldpt=point; //바로이전값 보관

dc.SelectObject(pOldPen); //펜 반환


13. MessageBox

AfxMessageBox()->전역함수를 이용하영 메세지 박스를 출력한다. //어디서든지 사용할수 잇다

int CWnd::MessageBox("메세지","창제목","아이콘|버튼(상수값)"); //View클래스에서 사용한다

아이콘 상수값 MB_IC[안내]태그제한으로등록되지않습니다 - xxONERROR,

MB_ICONWARNING, MB_ICONQUESTION,MB_ICONINFOMATION

MB_SYSTEMMODAL //시스템모달 대화창 닫기전에 다른작업 못함

MB_APPLMODAL //응용모달

버튼 상수값 MB_OK, MB_OKCANCEL, MB_YESNO


14. OS 컨트롤

ExitWindowEx(EWX_SHUTDOWN,NULL); //Shut Down

ExitWindowsEx(EWX_FORCE,0); //강제종료

ExitWindowsEx(EWX_LOGOFF,0); //로그오프

ExitWindowsEx(EWX_POWEROFF,0); //Shut Down -> Turn Off

ExitWindowsEx(EWX_REBOOT); //Shut Down -> Reboot


15. DialogBox 메시지 교환

UpdateData(FALSE); // 컨트롤에 멤버변수의 내용을 표시해준다

UpdateData(TRUE); // 컨트롤 내용을 다이얼로그 클래스의 멤버변수로 저장


16. 자료변환

atoi,itoa - int <=> ASCII(char) 변환

str.Format(" %d %d",x,y); // int형을 문자열로 변환

atol,ltoa - ASCII <=> long 변환

atof - ACSII => float 변환

fcvt,gcvt - 실수를 text로 변환

LPtoDP, DPtoLP - 장치좌표 <=> 논리좌표 변환


17. CEdit Class 사용하기

CEdit e_str.SetSel(int StartChae, int EndChar); //처음문자부터 마지막까지 블록 지정

CEdit e_str.GetSel(int SChar,int EChar); //블럭 지정한 처음문자와 마지막문자 받기

CString str=m_str.Mid(SChar,EChar-SChar); //블럭지정한 부분을 가져온다


18. 컨트롤과 자료교환

SetDlgItemText(컨트롤 ID,문자열) //컨트롤에 문자열을 넣는다

GetDlgItemText(컨트롤 ID,문자열) //컨트롤의 내용을 문자열에 넣는다

GetDlgItem(컨트롤 ID); //컨트롤의 주소를 가져온다


19. 상태바조작

CMainFrame 생성자 위에

static UINT indicators[] = //이안에 새로운 ID를 넣고 그 ID의 갱신핸들러를 만든다음 코딩

pCmdUI->SetText("표시할내용“);


20. 수동으로 Bitmap 컨트롤 사용하기

CStatic bitmap; //bitmap 컨트롤변수

bitmap.SetBitmap(CBitmap m_bitmap); //컨트롤에 비트맵지정

GetDlgItem(IDC_BITMAP)->ShowWindow(SW_SHOW,HIDE); // 그림을 보이거나 숨긴다.

21. 응용프로그램 실행하기

WinExec("프로그램경로“,SW_SHOW,HIDE); //응용프로그램실행,경로는 \\로 구분한다


22. Bitmap 사용하기

CBitmap bitmap.LoadBitmap(IDC_BITMAP); //비트맵객체에 비트맵지정

CDC memDC; //그림그릴 메모리DC생성

MemDC.CreateCompatibleDC(pDC); //화면 DC와 메모리 DC 호환 생성

CBitmap *pOldBitmap=MemDC.SelectObject(&m_bitmap); //메모리에 그림을그린다.

pDC->BitBlt(int x, int y,int Width, int Height, CDC* pSrcDC, int xSrc, int ySrc, DWORD dwRop);

//BitBlt(그림x좌표,그림y좌표,그림넓이,그림높이,그림그려진메모리DC,그림시작x좌표,그림시작y좌표,스타일);

pDC->StretchBlt( int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop )

//StretchBlt(그림x좌표,그림y좌표,그림넓이,그림높이,그림그려진메모리DC,그림x좌표,그림y좌표,메모리그림넓이,메모리그림높이,스타일);

MemDC.SelectObject(pOldBitmap); // 메모리DC반환


23. Font 바꾸기

CFontDialog dlg;//폰트다이얼로그 생성

LOGFONT m_logFont; //폰트받을변수선언

if(dlg.DoModal()==IDOK) //폰트다이얼로그표시

{dlg.GetCurrentFont(&m_logFont)} //선택된 폰트받기

OnDraw()

CFont newFont,*pOldFont; //폰트 객체 만들기

newFont.CreateFontIndirect(&m_logFont); //폰트 생성

pOldFont=(CFont *)pDC->SelectObject(&newFont); //폰트 선택

OnCreate()

CClientDC dc(this); //DC 생성

CFont *pFont=dc.GetCurrentFont(); //클라이언트 영역의 폰트를

pFont->GetLogFont(&m_logFont); //로그폰트 멤버값으로 지정


24. Font 만들기

LOGFONT logfont; //폰트를 만든다

logfont.lfHeight=50; //문자열 높이

logfont.lfWidth=0; //너비

logfont.lfEscapement=0; //문자열기울기

logfont.lfOrientation=0; //문자개별각도

logfont.lfWeight=FW_NORMAL; //굵기

logfont.lfItalic=TRUE; //이탤릭

logfont.lfUnderline=TRUE; //밑줄

logfont.lfStrikeOut=FALSE; //취소선

logfont.lfCharSet=HANGUL_CHARSET; //필수

logfont.lfOutPrecision=OUT_DEFAULT_PRECIS;

logfont.lfClipPrecision=CLIP_DEFAULT_PRECIS; //가변폭폰트 고정폭폰트

logfont.lfPitchAndFamily=DEFAULT_PITCH|FF_SWISS; //글꼴이름

strcpy(logfont.lfFaceName,"궁서체");

CClientDC dc(this);

CFont newFont; //폰트객체생성

newFont.CreateFontIndirect(&logfont); //폰트지정

CFont *pOldFont=dc.SelectObject(&newFont); //폰트선택

dc.TextOut(100,100,m_text);

dc.SelectObject(pOldFont); //폰트반환


25. Font 만들기 2

CFont newFont;

newFont.CreateFont( int nHeight, int nWidth, int nEscapement, int nOrientation, int nWeight, BYTE bItalic, BYTE bUnderline, BYTE cStrikeOut, BYTE nCharSet, BYTE nOutPrecision, BYTE nClipPrecision, BYTE nQuality, BYTE nPitchAndFamily, LPCTSTR lpszFacename );

CFont *pOldFont=dc.SelectObject(&newFont);


26. ComboBox 사용하기

CComboBox combo; //콤보박스 선언

combo.Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID );

//Style - WS_CHILD|WS_VISIBLE

int n=combo.GetCurSel(); //선택된 아이템의 index를 가져온다

combo.AddString("문자열“); //문자열을 추가한다

combo.GetLBText(n,str); //n번째 아이템을 str에 저장


27. Spin 사용하기

Spin은 바로앞의 Tab Order에 따라 붙는다

m_spinr.SetRange(1900,3000); //스핀 범위 지정

m_spinr.SetPos(m_nYear); //스핀 위치 지정


28. CTime사용하기

CTime time; //시간객체생성

time=CTime::GetCurrentTime(); //현재시간을 저장

time.GetYear(),time.GetMonth();,time.GetDay(),time.GetHour(),time.GetMinute(),time.GetSecond()


29. CListBox 메소드

AddString("문자열"); //리스트에 문자열 추가

DeleteString(index); //리스트에서 항목 삭제

GetCount() //전체 항목 갯수를 얻는다.

GetSelcount() //선택된 항목 갯수 리턴

GetSel() //선택된 것인지 아닌지를 리턴한다 -> 양수 = TRUE , 음수 => FALSE

GetText(int index,문자열변수) //index 번째 문자열을 문자열 변수에 넣는다

FindStringExact(문자열) //지정 문자열의 index 값 리턴 -> 없으면 리턴값 LB_ERR 반환

FindString("a") //"a"로 시작하는 항목을 모두 찾는다.

ResetCountent() //모든 내용을 지운다.


30. 파일입출력

프로젝트생성시 Step4 => Advanced => 저장파일확장자지정

//이 클래스를 저장,로드가능한 클래스로 쓰겟다는 선언

.h 파일에 DECLARE_SERIAL(CSawon)

.cpp 파일에 IMPLEMENT_SERIAL(CSawon,CObject,1) //이거를 해야 저장이 가능하다

void CFileioDoc::Serialize(CArchive& ar)

if (ar.IsStoring())

{

ar< < //저장하기

}

else //열기

{

ar>>m_shape; //불러올걸 쓴다. 읽을때도순서대로읽어야한다

}


31. MicroSoft FlexGrid 사용하기!

CMSFlexGrid m_Grid; //FlexGrid 컨트롤 변수

CString strTitle[]={"고객코드","고객성명","고객포인트","신장","몸무게","고객등급","BMT지수","판정결과"}; // Grid 의 제목에 넣을문자배열

int Width[]={900,900,1100,800,800,900,1000,900}; // Grid 의 열넓이 지정할 배열

m_Grid.SetRows(m_cnt+2); //전체행수 지정

m_Grid.SetCols(8);//전체열수 지정

m_Grid.Clear(); //지우기

m_Grid.SetFixedCols(0); //고정열은 없다.

m_Grid.SetRow(0); // 행선택

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

{

m_Grid.SetColWidth(i,Width[i]); //열 넓이 설정

m_Grid.SetCol(i); //열 선택

m_Grid.SetText(strTitle[i]); // 선택된행, 선택된열에 Text 를 넣는다

}


32. 4대 Class간 참조

//각각 헤더파일 include

#include "MainFrm.h" //메인프레임 헤더파일

#include "ClassDoc.h" //Doc클래스 헤더파일

#include "ClassView.h" //View를 include 할때는 반드시 Doc 헤더파일이 위에잇어야한다

#include "Class.h" //APP Class 의 헤더파일


void CClassView::OnMenuView() //뷰클래스

CClassApp *pApp=(CClassApp *)AfxGetApp(); //View -> App
CMainFrame *pMain=(CMainFrame *)AfxGetMainWnd(); //View -> MainFrm

//View -> MainFrm -> Doc

CClassDoc *pDoc=(CClassDoc *)pMain->GetActiveDocument();

CClassDoc *pDoc=(CClassDoc *)GetDocument(); //View -> Doc


//MainFrame 클래스

CClassView *pView=(CClassView *)GetActiveView(); //MainFrm -> View

CClassDoc *pDoc=(CClassDoc *)GetActiveDocument(); //MainFrm -> Doc

CClassApp *pApp=(CClassApp *)AfxGetApp(); //MainFrm -> App


//Doc 클래스

CClassApp *pApp=(CClassApp *)AfxGetApp(); //Doc -> App

CMainFrame *pMain=(CMainFrame *)AfxGetMainWnd(); //Doc -> MainFrm

// Doc -> MainFrm -> View

CClassView *pView=(CClassView *)pMain->GetActiveView();

CClassView *pView=(CClassView *)m_viewList.GetHead(); // Doc -> View


//App 클래스

CMainFrame *pMain=(CMainFrame *)AfxGetMainWnd(); //App -> MainFrm

//App -> MainFrm -> View

CClassView *pView=(CClassView *)pMain->GetActiveView();

//App -> MainFrm -> Doc

CClassDoc *pDoc=(CClassDoc *)pMain->GetActiveDocument();


33. ToolBar 추가하기

CMainFrame 으로 가서 멤버변수 추가

CToolBar m_wndToolBar1;

OnCreate 로 가서 다음 내용을 추가해준다

(위의 toolbar 부분을 복사하고 이름만 바꾸면 된다.3군데..)

if (!m_wndToolBar1.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE |

CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY |

CBRS_SIZE_DYNAMIC) || !m_wndToolBar1.LoadToolBar(IDR_TOOLBAR1))

{

TRACE0("Failed to create toolbar\n");

return -1; // fail to create

}


그 함수내에서 //TODO 아래에 내용추가..역시..복사해서 이름만 바꾸면 된다.

m_wndToolBar1.EnableDocking(CBRS_ALIGN_TOP|CBRS_ALIGN_BOTTOM);

//DockControlBar(&m_wndToolBar1); <= 이부분 대신..

이거를 넣는다..

CRect toolRect; //툴바 영역을 얻을 사각형

this->RecalcLayout(); //현상태의 Client 영역을 구해서 저장한다

m_wndToolBar.GetWindowRect(&toolRect); //툴바영역을 저장한다

toolRect.left+=1; //사각형의 왼쪽을 1Pixel 줄인다

//ToolRect에 툴바를 붙인다

DockControlBar(&m_wndToolBar1,AFX_IDW_DOCKBAR_TOP,&toolRect);

return 0;


34. ToolBar에 ComboBox붙이기

CComboBox m_combo; //객체생성

ID 등록 => view 메뉴 => resource symbol => new => ID_COMBO

oncreate 에 내용 추가 (콤보를 만들고 표시하는 내용)

m_wndToolBar.SetButtonInfo(10,IDC_COMBO,TBBS_SEPARATOR,150);

//툴바의 10번째버튼을 편집한다

CRect itemRect; //콤보를넣을 사각형을 만든다

m_wndToolBar.GetItemRect(10,&itemRect); //툴바의 10번째 버튼을 사각형에 넣는다
itemRect.left+=5; //앞여백

itemRect.right+=5; //뒤여백

itemRect.bottom+=100; //콤보가열릴 공간확보

m_combo.Create(WS_CHILD|WS_VISIBLE|CBS_DROPDOWN,itemRect,&m_wndToolBar,IDC_COMBO);

//콤보박스를 툴바에 붙여준다

m_combo.AddString("이름"); //내용추가

m_combo.SetCurSel(0); //셀 선택


35. Toolbar에 수동으로넣은 ComboBox 사용하기

afx_msg void [안내]태그제한으로등록되지않습니다-xxOnSelectCombo(); //원형

ON_CBN_SELCHANGE(IDC_COMBO,[안내]태그제한으로등록되지않습니다-xxOnSelectCombo) //메세지맵에 추가

CMainFrame *pMain=(CMainFrame *)GetParent(); //메인프레임 주소참조

CComboBox *pCom=(CComboBox *)(pMain->m_wndToolBar.GetDlgItem(IDC_COMBO));

//콤보박스의 주소를 가져온다, 접근할 때 메인프레임 -> 툴바 -> 콤보박스 의 순서로 가야한다

int n=pCom->GetCurSel(); //현재선택된 셀의 인덱스를 가져온다

if(n==CB_ERR) return; //선택된셀이 없으면 중지한다

CString str;

pMain->m_combo.GetLBText(n,str); //선택된셀의 Text를 가져온다


36. UPDATE_COMMAND 사용하기

pCmdUI->Enable(TRUE); //버튼 활성화

pCmdUI->SetText((bAdd)?"취소":"신규"); //버튼의 text 설정

pCmdUI->SetCheck(TRUE);//버튼 체크


37. 프로그램정보저장

CWinApp::GetProfileString(섹션명,항목명,기본값); // 함수를 사용한다. (문자열)

CWinApp::GetProfileInt(섹션명,항목명,기본값); //불러올때사용 (숫자)

CWinApp::WriteProfileString(섹션명,항목명,값); //저장할때 사용 (문자열)

CWinApp::WriteProfileInt(섹션명,항목명,값); //저장할때 사용 (숫자)

//불러올때 사용할함수

void CMainFrame::ActivateFrame(int nCmdShow) //프로그램 실행후 프레임생성될때 실행

//저장할 때 WM_DESTROY 메시지 사용


38. 컨트롤바 표시하기

CMainFrame *pMain=(CMainFrame *)GetParent();//MainFrame 주소가져오기

//툴바를 bTool2 에따라 보이고 감춘다

pMain->ShowControlBar(&pMain->m_wndToolBar,bTool1,FALSE);


39. Window 창크기,위치정보 저장하기

MainFrame 의 WM_DESTROY 에

WINDOWPLACEMENT w;

this->GetWindowPlacement(&w); //윈도우의 정보를 저장한다.

CString strRect;

strRect.Format("%04d,%04d,%04d,%04d", //04d 는 4자리 확보하고 남은건 0으로 채워라

w.rcNormalPosition.left,w.rcNormalPosition.top,

w.rcNormalPosition.right,w.rcNormalPosition.bottom); //윈도우의 위치,크기 확보..

BOOL bMax,bMin; //윈도우의 상태를 저장하기위한 변수

//w.falg 는 이전상태의 정보를 가지고 잇다!!

if(w.showCmd==SW_SHOWMINIMIZED) //최소화 상태

{

bMin=TRUE;

if(w.flags==0) //falg 값이 0 이면 이전 상태가 보통상태이다!!

bMax=FALSE;

else //이전상태가 최대화 상태

bMax=TRUE;

}

else

{

if(w.showCmd==SW_SHOWMAXIMIZED) //최대화상태

{

bMax=TRUE;

bMin=FALSE;

}

else //보통 상태

{

bMax=FALSE;

bMin=FALSE;

}

}

AfxGetApp()->WriteProfileString("WinStatus","Rect",strRect);

AfxGetApp()->WriteProfileInt("WinStatus","Max",bMax);

AfxGetApp()->WriteProfileInt("WinStatus","Min",bMin);


//읽어올차례..

ActivateFrame 함수로 가서

WINDOWPLACEMENT w; //윈도우의 상태를 저장하는 구조체..

BOOL bMax,bMin; //최대,최소상태를 저장할 변수

CString strRect; //창크기를 받아올 변수

strRect=AfxGetApp()->GetProfileString("WinStatus","Rect","0000,0000,0500,0700");

bMin=AfxGetApp()->GetProfileInt("WinStatus","Min",FALSE);

bMax=AfxGetApp()->GetProfileInt("WinStatus","Max",FALSE);

int a=atoi(strRect.Left(4)); //문자열을 int 로 바꿔준다.

int b=atoi(strRect.Mid(5,4)); //atoi 아스키 값을 int형으로 바꿔준다..

int c=atoi(strRect.Mid(10,4));

int d=atoi(strRect.Mid(15,4));

w.rcNormalPosition=CRect(a,b,c,d);

if(bMin)

{

w.showCmd=SW_SHOWMINIMIZED;

if(bMax)

{

w.flags=WPF_RESTORETOMAXIMIZED ;

}

else

{

w.flags=0;

}

}

else

{

if(bMax)

{

w.showCmd=SW_SHOWMAXIMIZED;

}

else

{

w.showCmd=SW_SHOWNORMAL;

}

}

this->SetWindowPlacement(&w); //설정된 값으로 윈도우를 그리게 한다..

//CFrameWnd::ActivateFrame(nCmdShow); //이건 반드시 주석처리한다..


40. progress Bar 쓰기

m_progress.SetRange(m_first,m_last); //Progress 범위설정하기

m_progress.SetStep(m_step); //Progress Step설정하기

//m_progress.StepIt(); //스텝만큼 움직이기

//또는 다음을 사용한다

for(int a=m_first;a<=m_last;a+=m_step) //a가 처음부터 끝까지

{

m_progress.SetPos(a); // 위치를 a에 맞춘다

Sleep(50); //천천히 움직이게한다

}


41. 파일대화상자 FileDialog 사용하기

void CConDlg1::OnFileopen() //파일열기 버튼

{

CFileDialog *fdlg; //파일대화상자 객체 생성 // 포인터로 만든다..

static char BASED_CODE szFilter[] = "Animate Video Files (*.avi)|*.avi|All Files

(*.*)|*.*||";

//필터를 만들어 준다..이건 할줄 모름..

fdlg =new CFileDialog(TRUE, ".avi", NULL, OFN_HIDEREADONLY |

OFN_OVERWRITEPROMPT,szFilter);

//대화상자 만들기..이렇게 해야댄다..

if(fdlg->DoModal()==IDOK) //이제..대화상자를 띠우고..

{ //OK 누르면 실행될 부분..

m_filename=fdlg->GetPathName(); //대화상자에서 경로를 받아서 저장.

UpdateData(FALSE);

}

}

//파일 다이얼로그 만들기

CFileDialog fdlg(TRUE,"avi",".avi",OFN_OEVRWRITEPROMPT,"Vidoe Files(*.avi)

|*.avi|All Files(*.*)|*.*||");

42. Animate Control 사용하기

m_animate.Open(m_filename); //파일을 연다

m_animate.Play(0,-1,1); //(처음프레임,마지막프레임,반복횟수)

m_animate.Stop(); //정지시키기

m_ani.SetAutoStart(TRUE);//자동으로 시작한다

43. Control 의 Style 바꿔주기

Control.ModyfyStyle(제거할스타일,추가할스타일); //스타일은 MSDN내용 참조


44. 시스템 날자바꾸기 버튼

SetSystemTime(),GetSystemTime() //GMT 표준시를 가져온다.

GetLocalTime(),SetLocalTime() //현재 지역시간을 가져온다.


SYSTEMTIME st;

GetLocalTime(&st); //현재 시간, 날자를 넣는다.

st.wYear=m_date2.GetYear();

st.wMonth=m_date2.GetMonth();

st.wDay=m_date2.GetDay();

SetSystemTime(&st);


45. 시스템 시간 바꾸기 버튼

UpdateData(TRUE);

SYSTEMTIME st;

GetLocalTime(&st);

st.wHour=m_time.GetHour();

st.wMinute=m_time.GetMinute();

st.wSecond=m_time.GetSecond();

SetLocalTime(&st);


46.시스템의 드라이브 문자 얻기

char temp[50];

GetLogicalDriveStrings(sizeof(temp),temp);

CString str,str1;

int n=0;

while(*(temp+n)!=NULL)

{

str=temp+n;

str1+= " "+str.Left(2);

n+=4;

}


47. 현재 작업경로 얻기

char temp[MAX_PATH]; //MAX_PATH 는 경로길이의 최대를 define 해놓은것.

GetCurrentDirectory(sizeof(temp),temp); // 현작업하는 경로(경로 길이,문자형);


48. Tree Control 사용하기

HTREEITEM hmov,hmus; //핸들을받을 변수 이게 잇어야 하위 디렉토리 생성가능

hmov=m_tree.InsertItem("영화",TVI_ROOT,TVI_LAST); //,TVI_ROOT,TVI_LAST는 default

hm1=m_tree.InsertItem("외화",hmov); //hmov 아래 “외화”트리 생성

CImageList m_image; //그림을 사용하기 위한 클래스다!! 알아두자..

m_tree.SetImageList(&m_image,TVSIL_NORMAL); //Tree View Style Image List => TVSIL

hmov=m_tree.InsertItem("영화",0,1,TVI_ROOT,TVI_LAST);//TVI_ROOT,TVI_LAST는 default

hmus=m_tree.InsertItem("가요",1,2);//("문자열",처음그림번호,선택시그림)

hm1=m_tree.InsertItem("외화",2,3,hmov); //그림 번호는 default 로 0이 들어간다..


49. List Control 사용하기

m_list.ModifyStyle(LVS_TYPEMASK, LVS_ICON); //리스트를 큰아이콘형태로 보인다

m_list.ModifyStyle(LVS_TYPEMASK, LVS_SMALLICON);//리스트를 작은아이콘형태

m_list.ModifyStyle(LVS_TYPEMASK, LVS_LIST); //리스트를 리스트형태로 보인다

m_list.ModifyStyle(LVS_TYPEMASK, LVS_REPORT); //리스트를 자세히형태로 보인다

CImageList m_treeimage; //이미지리스트

CImageList m_small, m_large;

m_large.Create(IDB_LARGE,32,0,RGB(255,255,255)); //이거는 클래스에서 추가해준거다

m_small.Create(IDB_SMALL,16,0,RGB(255,255,255));// (bmp ID값,

m_list.SetImageList(&m_large,LVSIL_NORMAL);

m_list.SetImageList(&m_small,LVSIL_SMALL);

CString name[]={"홍길동","진달래","한국남","개나리"};

CString tel[]={"400-3759","304-7714","505-9058","700-9898"};

CString born[]={"1980-1-1","1981-12-20","1980-05-15","1981-08-31"};

CString sex[]={"남자","여자","남자","여자"};

m_list.InsertColumn(0,"이름",LVCFMT_LEFT,70);

m_list.InsertColumn(1,"전화번호",LVCFMT_LEFT,80);

m_list.InsertColumn(2,"생일",LVCFMT_LEFT,90);

m_list.InsertColumn(3,"성별",LVCFMT_LEFT,50);

LVITEM it; //리스트 구조체

char temp[100];

for(int a=0;a<4;a++)

{

int n=(sex[a]=="남자")?0:1;

m_list.InsertItem(a,name[a],n); //insert item 은 행을 만들고..

it.mask=LVIF_TEXT|LVIF_IMAGE; //마스크 설정

it.iItem=a;

it.iSubItem=1;//열 설정

strcpy(temp,tel[a]); //이거 모하는거냐..

it.pszText=temp;

m_list.SetItem(&it); // setitem 열에 정보를 넣는다.


it.iSubItem=2; //열 설정

strcpy(temp,born[a]); //이거 모하는거냐..

it.pszText=temp;

m_list.SetItem(&it); // setitem 열에 정보를 넣는다.


it.iSubItem=3; //열 설정

strcpy(temp,sex[a]); //이거 모하는거냐..

it.pszText=temp;

m_list.SetItem(&it); // setitem 열에 정보를 넣는다.

50. Bitmap Button 사용하기

CBitmapButton 을 사용한다! CButton 에서 상속 받는클래스임..

m_button1.Create(NULL, WS_CHILD|WS_VISIBLE|BS_OWNERDRAW,

CRect(310,20,370,50), this,IDC_MYBUTTON); //버튼만들기

m_button1.LoadBitmapsIDB_UP,IDB_DOWN,IDB_FOCUS,IDB_DISABLE);//버튼의 그림설정

m_button1.SizeToContent(); //버튼을 그림 크기로 맞춰 준다!!


//그냥 버튼을 비트맵버튼으로 바꾸기 -> 버튼을 만든다 속성에서 OWNERDRA 속성에 체크!!

m_button2.LoadBitmaps(IDB_UP,IDB_DOWN,IDB_FOCUS,IDB_DISABLE); //버튼 그림설정

m_button2.SizeToContent(); //버튼을 그림 크기로 맞춰 준다!!


51. 중복없는 난수발생하기

int su; //발생된 난수저장

int a,b;

BOOL bDasi; //숫자가중복될경우 다시하기위한 변수

for(a=0;a<9;a++) //난수 9개 발생

{

bDasi=TRUE;

while(bDasi)

{

bDasi=FALSE;

su=rand()%10; //난수발생

for(b=0;b

{

if(temp[b]==su) //중복이면

{

bDasi=TRUE; //중복이 잇으면 다시while 문을 실행한다

break;

}//if

}//for

}//while

temp[a]=su; //중복이 아니면 대입한다

52. 메뉴 범위로 사용하기

ON_COMMAND_RANGE(ID_LEVEL3,ID_LEVEL9,OnLevel); //범위메세지 발생

//메뉴 ID의 값이 연속된 숫자일 경우 범위로 지정해서 사용할수잇다


53. 한,영 전환함수

void CCustView::SetHangul(BOOL bCheck) //T:한글 F:영문 이건 외우자..

{

//뷰클래스의 윈도우 핸들포인터를 얻는다.

HIMC hm=ImmGetContext(this->GetSafeHwnd());

if(bCheck)

{

::ImmSetConversionStatus(hm,1,0);//1은 한글 0은 영문

}

else

{

::ImmSetConversionStatus(hm,0,0); //영문으로 바꿔준다

}

::ImmReleaseContext(this->GetSafeHwnd(),hm); //장치를 풀어준다

}

#include "imm.h" //헤더 반드시 추가하고

imm32.lib (라이브러리 파일)를 반드시 링크해주어야 한다!

**** 라이브러리 추가하기

프로젝트메뉴 -> 셋팅 -> 링크탭


54. DLL함수정의하기

임포트함수 : extern "C" __declspec(dllimport) 리터형 함수명(매개변수,...) ;

- 메인프로그램에서 DLL에 있는 함수를 호출할때 사용한다.


엑스포트함수 : extern "C" __declspec(dllexport) 리터형 함수명(매개변수,...)

{

내용;

}

출처: http://weezzle.net/1882
감사합니다.

Posted by SB패밀리


warning LNK4098: 'libcmt.lib' defaultlib가 다른 라이브러리와 충돌합니다. /NODEFAULTLIB:library를 사용하십시오.

경고 메시지 처리 

해당 프로젝트의 속성을 수정하여 경고를 대처할 수 있다.
아래의 프로젝트 속성 화면에서 링커-->입력 페이지로 이동한 후, 특정 라이브러리 무시 입력란에
해당 경고 메시지에 포함된 *.lib 파일을 입력한다.
다시 컴파일 해보면 경고 메세지가 발생하지 않는다.
 

Posted by SB패밀리

1. DC얻기

  CClientDC dc(this);


2. Client 영역 구하기

  GetClientRect(&rect);

  WM_SIZE 메시지발생후 cx,cy 사용


3. 문자열 사각형안에 그리기

  pDC->DrawText(문자열,사각형,Style);

  Style : DT_BOTTOM - 문자열을 사각형 맨아래줄에배열 반드시DT_SINGLELINE과 함께사용

            DT_CENTER - 문자열을 가로중앙에 배치

            DT_VCENTER - 문자열을 세로중앙에 배치

            DT_LEFT,RIGHT - 문자열을 좌,우로 배치

            DT_SINGLELINE - 문자열을 한줄로만 쓴다


4. Brush 사용법

  CBrush brushname(RGB(red,green,blue)); //브러쉬 생성

  //이전Brush 저장, 새로운 Brush 선택

  CBrush *oldBrush=pDC->SelectObject(&brushname); 

  pDC->SelectObject(oldBrush); //원래의 브러쉬로 반환


5. Pen사용법

  CPen pen(Pen Style,RGB(red,green,blue)); //브러쉬생성

  //Style: PS_SOLID,PS_DASH,PS_DOT,PS_DASHDOT,PS_GEOMETRIC,PS_COSMETRIC

                - 펜종류 

              PS_ENDCAP_ROUND,PS_ENDCAP_SQUARE - 펜끝을 둥글게,각지게 설정

  CPen *oldPen=pDC->SelectObject(&pen); //이전Pen저장, 새로운 Pen설정

  pDC->SelectObject(oldPen); //펜반환


6. 화면다시그리기

  View Class에서 - Invalidate(TRUE) : 화면을 지우고다시그린다

                            Invalidate(FALSE) : 화면을 덮어씌운다

  UpdateAllViews(NULL);  // Doc Class에서 View 의 OnDraw 호출

  RedrawWindow();


7. 메시지,함수 수동으로 넣기 (EX)버튼클릭함수넣기

  헤더파일의 AFX_MSG_MAP 부분에 함수를 정의

  // .cpp파일의 AFX_MSG 부분에 메시지를 추가한다

  EX) afx_msg void funcName();

  // ID 등록:  View 메뉴의 Resource Symbol 에 들어가서 메뉴 ID 를 등록해준다..

  EX) ON_BN_CLICKED(ID_NAME,funcName).

  // .cpp파일의 맨아래에서 함수를 정의한다

  EX) void CClass::funcName() { ... }


8. 마우스커서 바꾸기

  리소스탭에서 커서를 그리고 저장한뒤 ID값은 준다음

  SetCapture(); //커서의입력을 클라이언트영역을 벗어나더라도 받아낸다

  SetCursor(AfxGetApp()->LoadCursor(nIDResource));

  //APP클래스의 LoadCursor View의 SetCursor 사용

  ReleaseCapture(); //SetCursor()상태를 해제한다


9. 색상표 사용하기

  CColorDialog dlg;

  if(dlg.DoModal()==IDOK) //Dialog 를 띄운후 OK버튼을누르면 실행할부분

  MemberFunc: GetColor() //선택된 색상을 받아온다 return 형은 COLORREF 형


10. 팝업메뉴 만들기

  CMenu menu; //메뉴 객체생성

  CMenu *pmenu; //메뉴 포인터생성

  menu.LoadMenu(IDR_MAINFRAME); //메뉴를 불러온다

  pmenu=menu.GetSubMenu(3); //메뉴의 3번째 메뉴를 가져온다

  menu.CheckMenuItem(ID_MENU,m_kind==ID_MENU ? MF_CHECKED : MF_UNCHECKED); //메뉴 체크하기 (메뉴 ID, ID 체크조건)

  pmenu->TrackPopupMenu(TPM_LEFTALIGN,point.x,point.y,this) //(TMP_Style,x좌표,y좌표,hWnd) 메뉴 띄우기


  *주의사항*

  [안내]태그제한으로등록되지않습니다-OnContextMenu(CWnd* pWnd, CPoint point)  //여기서 point 는 스크린 기준이고,

  OnRButtonDown(UINT nFlags, CPoint point)  //여기서 point 는 클라이언트 기준이다!


11. 클라이언트 포인터를 스크린 포인터로 변경

  ClientToScreen(&point);


12. 그림판기능

  if(m_flag==FALSE)  return;   //m_falg=그리기 기능 참,거짓설정  그리기 아니면 빠져나간다

        CClientDC dc(this);

        CPen myPen(PS_SOLID,m_width,m_color);

        CPen *pOldPen=dc.SelectObject(&myPen);

        switch(m_shape)

        {

        case ID_FREELINE: //자유선그리기

                dc.MoveTo(m_oldpt.x,m_oldpt.y); //지난포인터부터

                dc.LineTo(point.x,point.y); //새포인터까지 그린다

                break;

        case ID_RECT: //사각형그리기

                dc.SetROP2(R2_NOTXORPEN);

                dc.Rectangle(m_spt.x,m_spt.y,m_oldpt.x,m_oldpt.y);  //지워지는 효과

                dc.Rectangle(m_spt.x,m_spt.y,point.x,point.y); //그려지는 효과

                break;

        case ID_ELLIPSE: //원그리기

                dc.SetROP2(R2_NOTXORPEN);

                dc.Ellipse(m_spt.x,m_spt.y,m_oldpt.x,m_oldpt.y);  //지워지는 효과

                dc.Ellipse(m_spt.x,m_spt.y,point.x,point.y); //그려지는 효과

                break;

        case ID_LINE: //선그리기

                dc.SetROP2(R2_NOTXORPEN);

                dc.MoveTo(m_spt.x,m_spt.y); //시작점부터

                dc.LineTo(m_oldpt.x,m_oldpt.y); //지난점까지 그은선을 지운다

                dc.MoveTo(m_spt.x,m_spt.y); //시작점부터

                dc.LineTo(point.x,point.y); //새로운점까지 그린다

                break;

        }

        m_oldpt=point;  //바로이전값 보관

        dc.SelectObject(pOldPen); //펜 반환


13. MessageBox

  AfxMessageBox()->전역함수를 이용하영 메세지 박스를 출력한다.   //어디서든지 사용할수 잇다

  int CWnd::MessageBox("메세지","창제목","아이콘|버튼(상수값)");   //View클래스에서 사용한다

  아이콘 상수값  MB_IC[안내]태그제한으로등록되지않습니다 - xxONERROR,  

                MB_ICONWARNING, MB_ICONQUESTION,MB_ICONINFOMATION

                MB_SYSTEMMODAL //시스템모달 대화창 닫기전에 다른작업 못함

                MB_APPLMODAL //응용모달

  버튼 상수값    MB_OK, MB_OKCANCEL, MB_YESNO


14. OS 컨트롤

  ExitWindowEx(EWX_SHUTDOWN,NULL); //Shut Down

  ExitWindowsEx(EWX_FORCE,0); //강제종료

  ExitWindowsEx(EWX_LOGOFF,0); //로그오프

  ExitWindowsEx(EWX_POWEROFF,0); //Shut Down -> Turn Off

  ExitWindowsEx(EWX_REBOOT); //Shut Down -> Reboot


15. DialogBox 메시지 교환

  UpdateData(FALSE); // 컨트롤에 멤버변수의 내용을 표시해준다

  UpdateData(TRUE);  // 컨트롤 내용을 다이얼로그 클래스의 멤버변수로 저장


16. 자료변환

  atoi,itoa - int <=> ASCII(char) 변환

  str.Format(" %d %d",x,y); // int형을 문자열로 변환

  atol,ltoa - ASCII <=> long 변환

  atof - ACSII => float 변환

  fcvt,gcvt  - 실수를 text로 변환

  LPtoDP, DPtoLP - 장치좌표 <=> 논리좌표 변환


17. CEdit Class 사용하기

  CEdit e_str.SetSel(int StartChae, int EndChar); //처음문자부터 마지막까지 블록 지정

  CEdit e_str.GetSel(int SChar,int EChar); //블럭 지정한 처음문자와 마지막문자 받기

  CString str=m_str.Mid(SChar,EChar-SChar); //블럭지정한 부분을 가져온다


18. 컨트롤과 자료교환

  SetDlgItemText(컨트롤 ID,문자열) //컨트롤에 문자열을 넣는다

  GetDlgItemText(컨트롤 ID,문자열) //컨트롤의 내용을 문자열에 넣는다

  GetDlgItem(컨트롤 ID); //컨트롤의 주소를 가져온다


19. 상태바조작

  CMainFrame 생성자 위에

  static UINT indicators[] = //이안에 새로운 ID를 넣고 그 ID의 갱신핸들러를 만든다음 코딩

  pCmdUI->SetText("표시할내용“);


20. 수동으로 Bitmap 컨트롤 사용하기

  CStatic bitmap; //bitmap 컨트롤변수

  bitmap.SetBitmap(CBitmap m_bitmap); //컨트롤에 비트맵지정

  GetDlgItem(IDC_BITMAP)->ShowWindow(SW_SHOW,HIDE);  // 그림을 보이거나 숨긴다.

  

21. 응용프로그램 실행하기

  WinExec("프로그램경로“,SW_SHOW,HIDE); //응용프로그램실행,경로는 \\로 구분한다


22. Bitmap 사용하기

  CBitmap bitmap.LoadBitmap(IDC_BITMAP); //비트맵객체에 비트맵지정

  CDC memDC; //그림그릴 메모리DC생성

  MemDC.CreateCompatibleDC(pDC); //화면 DC와 메모리 DC 호환 생성

  CBitmap *pOldBitmap=MemDC.SelectObject(&m_bitmap); //메모리에 그림을그린다.

  pDC->BitBlt(int x, int y,int Width, int Height, CDC* pSrcDC, int xSrc, int ySrc, DWORD dwRop);

//BitBlt(그림x좌표,그림y좌표,그림넓이,그림높이,그림그려진메모리DC,그림시작x좌표,그림시작y좌표,스타일);

  pDC->StretchBlt( int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop )

//StretchBlt(그림x좌표,그림y좌표,그림넓이,그림높이,그림그려진메모리DC,그림x좌표,그림y좌표,메모리그림넓이,메모리그림높이,스타일);

MemDC.SelectObject(pOldBitmap); // 메모리DC반환


23. Font 바꾸기

  CFontDialog dlg;//폰트다이얼로그 생성

  LOGFONT m_logFont; //폰트받을변수선언

  if(dlg.DoModal()==IDOK) //폰트다이얼로그표시

  {dlg.GetCurrentFont(&m_logFont)} //선택된 폰트받기

  OnDraw()

   CFont newFont,*pOldFont; //폰트 객체 만들기

   newFont.CreateFontIndirect(&m_logFont); //폰트 생성

   pOldFont=(CFont *)pDC->SelectObject(&newFont); //폰트 선택

   OnCreate()

   CClientDC dc(this); //DC 생성

   CFont *pFont=dc.GetCurrentFont();        //클라이언트 영역의 폰트를

   pFont->GetLogFont(&m_logFont); //로그폰트 멤버값으로 지정


24. Font 만들기

         LOGFONT logfont; //폰트를 만든다

        logfont.lfHeight=50;               //문자열 높이

        logfont.lfWidth=0;                 //너비

        logfont.lfEscapement=0;            //문자열기울기

        logfont.lfOrientation=0;             //문자개별각도

        logfont.lfWeight=FW_NORMAL;     //굵기

        logfont.lfItalic=TRUE;             //이탤릭

        logfont.lfUnderline=TRUE; //밑줄

        logfont.lfStrikeOut=FALSE; //취소선

        logfont.lfCharSet=HANGUL_CHARSET; //필수

        logfont.lfOutPrecision=OUT_DEFAULT_PRECIS;               

        logfont.lfClipPrecision=CLIP_DEFAULT_PRECIS;     //가변폭폰트 고정폭폰트

        logfont.lfPitchAndFamily=DEFAULT_PITCH|FF_SWISS; //글꼴이름

        strcpy(logfont.lfFaceName,"궁서체");

        CClientDC dc(this);

        CFont newFont; //폰트객체생성

        newFont.CreateFontIndirect(&logfont); //폰트지정

        CFont *pOldFont=dc.SelectObject(&newFont); //폰트선택

        dc.TextOut(100,100,m_text);

        dc.SelectObject(pOldFont); //폰트반환


25. Font 만들기 2

  CFont newFont;

  newFont.CreateFont( int nHeight, int nWidth, int nEscapement, int nOrientation, int nWeight, BYTE bItalic, BYTE bUnderline, BYTE cStrikeOut, BYTE nCharSet, BYTE nOutPrecision, BYTE nClipPrecision, BYTE nQuality, BYTE nPitchAndFamily, LPCTSTR lpszFacename );

 CFont *pOldFont=dc.SelectObject(&newFont);


26. ComboBox 사용하기

  CComboBox combo; //콤보박스 선언

  combo.Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID );

  //Style - WS_CHILD|WS_VISIBLE

  int n=combo.GetCurSel(); //선택된 아이템의 index를 가져온다

  combo.AddString("문자열“); //문자열을 추가한다

  combo.GetLBText(n,str); //n번째 아이템을 str에 저장


27. Spin 사용하기

  Spin은 바로앞의 Tab Order에 따라 붙는다

  m_spinr.SetRange(1900,3000); //스핀 범위 지정

  m_spinr.SetPos(m_nYear); //스핀 위치 지정


28. CTime사용하기

  CTime time; //시간객체생성

  time=CTime::GetCurrentTime(); //현재시간을 저장

  time.GetYear(),time.GetMonth();,time.GetDay(),time.GetHour(),time.GetMinute(),time.GetSecond()


29. CListBox 메소드

  AddString("문자열");             //리스트에 문자열 추가

  DeleteString(index);             //리스트에서 항목 삭제

  GetCount()                     //전체 항목 갯수를 얻는다.

  GetSelcount()                   //선택된 항목 갯수 리턴

  GetSel()                //선택된 것인지 아닌지를 리턴한다 -> 양수 = TRUE , 음수 => FALSE

  GetText(int index,문자열변수)     //index 번째 문자열을 문자열 변수에 넣는다

  FindStringExact(문자열)    //지정 문자열의 index 값 리턴 -> 없으면 리턴값 LB_ERR 반환

  FindString("a")               //"a"로 시작하는 항목을 모두 찾는다.

  ResetCountent()            //모든 내용을 지운다.


30. 파일입출력

  프로젝트생성시 Step4 => Advanced => 저장파일확장자지정

  //이 클래스를 저장,로드가능한 클래스로 쓰겟다는 선언

  .h 파일에       DECLARE_SERIAL(CSawon)  

  .cpp 파일에     IMPLEMENT_SERIAL(CSawon,CObject,1) //이거를 해야 저장이 가능하다

  void CFileioDoc::Serialize(CArchive& ar)

        if (ar.IsStoring()) 

        {

            ar< <             //저장하기

        }

        else    //열기

        {

             ar>>m_shape; //불러올걸 쓴다. 읽을때도순서대로읽어야한다

        }

 


31. MicroSoft FlexGrid 사용하기!

  CMSFlexGrid m_Grid; //FlexGrid 컨트롤 변수

  CString strTitle[]={"고객코드","고객성명","고객포인트","신장","몸무게","고객등급","BMT지수","판정결과"}; // Grid 의 제목에 넣을문자배열

  int Width[]={900,900,1100,800,800,900,1000,900}; // Grid 의 열넓이 지정할 배열

  m_Grid.SetRows(m_cnt+2); //전체행수 지정

  m_Grid.SetCols(8);//전체열수 지정

  m_Grid.Clear(); //지우기

  m_Grid.SetFixedCols(0); //고정열은 없다.

  m_Grid.SetRow(0); // 행선택

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

  {

     m_Grid.SetColWidth(i,Width[i]); //열 넓이 설정

     m_Grid.SetCol(i); //열 선택

     m_Grid.SetText(strTitle[i]); // 선택된행, 선택된열에 Text 를 넣는다

  }


32. 4대 Class간 참조

  //각각 헤더파일 include

  #include "MainFrm.h" //메인프레임 헤더파일

  #include "ClassDoc.h"   //Doc클래스 헤더파일

  #include "ClassView.h" //View를 include 할때는 반드시 Doc 헤더파일이 위에잇어야한다

  #include "Class.h" //APP Class 의 헤더파일


  void CClassView::OnMenuView() //뷰클래스

    CClassApp *pApp=(CClassApp *)AfxGetApp();   //View -> App
    CMainFrame *pMain=(CMainFrame *)AfxGetMainWnd();  //View -> MainFrm

    //View -> MainFrm -> Doc

    CClassDoc *pDoc=(CClassDoc *)pMain->GetActiveDocument();

    CClassDoc *pDoc=(CClassDoc *)GetDocument();        //View -> Doc


    //MainFrame 클래스

    CClassView *pView=(CClassView *)GetActiveView();  //MainFrm -> View

    CClassDoc *pDoc=(CClassDoc *)GetActiveDocument();  //MainFrm -> Doc

    CClassApp *pApp=(CClassApp *)AfxGetApp(); //MainFrm -> App


    //Doc 클래스

    CClassApp *pApp=(CClassApp *)AfxGetApp(); //Doc -> App

    CMainFrame *pMain=(CMainFrame *)AfxGetMainWnd(); //Doc -> MainFrm

    // Doc -> MainFrm -> View

    CClassView *pView=(CClassView *)pMain->GetActiveView();

    CClassView *pView=(CClassView *)m_viewList.GetHead();      // Doc -> View


    //App 클래스

    CMainFrame *pMain=(CMainFrame *)AfxGetMainWnd(); //App -> MainFrm

    //App -> MainFrm -> View

    CClassView *pView=(CClassView *)pMain->GetActiveView();

    //App -> MainFrm -> Doc

    CClassDoc *pDoc=(CClassDoc *)pMain->GetActiveDocument();


33. ToolBar 추가하기

  CMainFrame 으로 가서 멤버변수 추가

  CToolBar m_wndToolBar1;

  OnCreate 로 가서 다음 내용을 추가해준다

  (위의 toolbar 부분을 복사하고 이름만 바꾸면 된다.3군데..)

  if (!m_wndToolBar1.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE |

         CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY |

         CBRS_SIZE_DYNAMIC) || !m_wndToolBar1.LoadToolBar(IDR_TOOLBAR1))

        {

                TRACE0("Failed to create toolbar\n");

                return -1;      // fail to create

        }


  그 함수내에서 //TODO 아래에 내용추가..역시..복사해서 이름만 바꾸면 된다.

        m_wndToolBar1.EnableDocking(CBRS_ALIGN_TOP|CBRS_ALIGN_BOTTOM);

        //DockControlBar(&m_wndToolBar1);   <= 이부분 대신..

        이거를 넣는다..

        CRect toolRect; //툴바 영역을 얻을 사각형

        this->RecalcLayout(); //현상태의 Client 영역을 구해서 저장한다

        m_wndToolBar.GetWindowRect(&toolRect); //툴바영역을 저장한다

        toolRect.left+=1; //사각형의 왼쪽을 1Pixel 줄인다

        //ToolRect에 툴바를 붙인다

        DockControlBar(&m_wndToolBar1,AFX_IDW_DOCKBAR_TOP,&toolRect);

        return 0;


34. ToolBar에 ComboBox붙이기

  CComboBox m_combo; //객체생성

  ID 등록 => view 메뉴 => resource symbol => new => ID_COMBO

  oncreate 에 내용 추가 (콤보를 만들고 표시하는 내용)

        m_wndToolBar.SetButtonInfo(10,IDC_COMBO,TBBS_SEPARATOR,150); 

        //툴바의 10번째버튼을 편집한다

        CRect itemRect; //콤보를넣을 사각형을 만든다

        m_wndToolBar.GetItemRect(10,&itemRect); //툴바의 10번째 버튼을 사각형에 넣는다
        itemRect.left+=5; //앞여백

        itemRect.right+=5; //뒤여백

        itemRect.bottom+=100; //콤보가열릴 공간확보

        m_combo.Create(WS_CHILD|WS_VISIBLE|CBS_DROPDOWN,itemRect,&m_wndToolBar,IDC_COMBO);

        //콤보박스를 툴바에 붙여준다

        m_combo.AddString("이름"); //내용추가

        m_combo.SetCurSel(0); //셀 선택


35.  Toolbar에 수동으로넣은 ComboBox 사용하기

  afx_msg void [안내]태그제한으로등록되지않습니다-xxOnSelectCombo(); //원형

  ON_CBN_SELCHANGE(IDC_COMBO,[안내]태그제한으로등록되지않습니다-xxOnSelectCombo) //메세지맵에 추가

  CMainFrame *pMain=(CMainFrame *)GetParent(); //메인프레임 주소참조

  CComboBox *pCom=(CComboBox *)(pMain->m_wndToolBar.GetDlgItem(IDC_COMBO));

  //콤보박스의 주소를 가져온다, 접근할 때 메인프레임 -> 툴바 -> 콤보박스 의 순서로 가야한다

  int n=pCom->GetCurSel(); //현재선택된 셀의 인덱스를 가져온다

  if(n==CB_ERR) return; //선택된셀이 없으면 중지한다

  CString str;

  pMain->m_combo.GetLBText(n,str); //선택된셀의 Text를 가져온다


36. UPDATE_COMMAND 사용하기

  pCmdUI->Enable(TRUE); //버튼 활성화

  pCmdUI->SetText((bAdd)?"취소":"신규"); //버튼의 text 설정

  pCmdUI->SetCheck(TRUE);//버튼 체크


37. 프로그램정보저장

  CWinApp::GetProfileString(섹션명,항목명,기본값); // 함수를 사용한다. (문자열)

  CWinApp::GetProfileInt(섹션명,항목명,기본값); //불러올때사용 (숫자) 

  CWinApp::WriteProfileString(섹션명,항목명,값); //저장할때 사용 (문자열)

  CWinApp::WriteProfileInt(섹션명,항목명,값); //저장할때 사용 (숫자)

 //불러올때 사용할함수

  void CMainFrame::ActivateFrame(int nCmdShow) //프로그램 실행후 프레임생성될때 실행

  //저장할 때 WM_DESTROY 메시지 사용


38. 컨트롤바 표시하기

  CMainFrame *pMain=(CMainFrame *)GetParent();//MainFrame 주소가져오기

  //툴바를 bTool2 에따라 보이고 감춘다

  pMain->ShowControlBar(&pMain->m_wndToolBar,bTool1,FALSE);


39. Window 창크기,위치정보 저장하기

  MainFrame 의 WM_DESTROY 에

    WINDOWPLACEMENT w;

    this->GetWindowPlacement(&w); //윈도우의 정보를 저장한다.

    CString strRect;

    strRect.Format("%04d,%04d,%04d,%04d", //04d 는 4자리 확보하고 남은건 0으로 채워라

         w.rcNormalPosition.left,w.rcNormalPosition.top,

         w.rcNormalPosition.right,w.rcNormalPosition.bottom); //윈도우의 위치,크기 확보..

        

        BOOL bMax,bMin; //윈도우의 상태를 저장하기위한 변수

        //w.falg 는 이전상태의 정보를 가지고 잇다!!

        if(w.showCmd==SW_SHOWMINIMIZED)           //최소화 상태

        {

                bMin=TRUE;

                if(w.flags==0) //falg 값이 0 이면 이전 상태가 보통상태이다!!

                        bMax=FALSE;

                else   //이전상태가 최대화 상태

                        bMax=TRUE;

        }

        else                            

        {

                if(w.showCmd==SW_SHOWMAXIMIZED) //최대화상태

                {

                        bMax=TRUE;

                        bMin=FALSE;

                }

                else //보통 상태

                {

                        bMax=FALSE;

                        bMin=FALSE;

                }

        }

        AfxGetApp()->WriteProfileString("WinStatus","Rect",strRect);

        AfxGetApp()->WriteProfileInt("WinStatus","Max",bMax);

        AfxGetApp()->WriteProfileInt("WinStatus","Min",bMin);

 


//읽어올차례..

ActivateFrame 함수로 가서

        WINDOWPLACEMENT w;  //윈도우의 상태를 저장하는 구조체..

        BOOL bMax,bMin;               //최대,최소상태를 저장할 변수

        CString strRect; //창크기를 받아올 변수

        strRect=AfxGetApp()->GetProfileString("WinStatus","Rect","0000,0000,0500,0700");

        bMin=AfxGetApp()->GetProfileInt("WinStatus","Min",FALSE);

        bMax=AfxGetApp()->GetProfileInt("WinStatus","Max",FALSE);

        int a=atoi(strRect.Left(4)); //문자열을 int 로 바꿔준다.

        int b=atoi(strRect.Mid(5,4));     //atoi 아스키 값을 int형으로 바꿔준다..

        int c=atoi(strRect.Mid(10,4));

        int d=atoi(strRect.Mid(15,4));

        w.rcNormalPosition=CRect(a,b,c,d);

        if(bMin)

        {

                w.showCmd=SW_SHOWMINIMIZED;

                if(bMax)

                {

                        w.flags=WPF_RESTORETOMAXIMIZED  ;

                }

                else

                {

                        w.flags=0;

                }

        }

        else

        {

                if(bMax)

                {

                        w.showCmd=SW_SHOWMAXIMIZED;

                }

                else

                {

                        w.showCmd=SW_SHOWNORMAL;

                }

        }

        this->SetWindowPlacement(&w); //설정된 값으로 윈도우를 그리게 한다..

        

        //CFrameWnd::ActivateFrame(nCmdShow); //이건 반드시 주석처리한다..


40. progress Bar 쓰기

  m_progress.SetRange(m_first,m_last); //Progress 범위설정하기

  m_progress.SetStep(m_step); //Progress Step설정하기

  //m_progress.StepIt(); //스텝만큼 움직이기

  //또는 다음을 사용한다

  for(int a=m_first;a<=m_last;a+=m_step) //a가 처음부터 끝까지

  {

    m_progress.SetPos(a); // 위치를 a에 맞춘다

    Sleep(50); //천천히 움직이게한다

  }


41. 파일대화상자 FileDialog 사용하기

  void CConDlg1::OnFileopen()  //파일열기 버튼

  {

        CFileDialog *fdlg; //파일대화상자 객체 생성 // 포인터로 만든다..

        static char BASED_CODE szFilter[] = "Animate Video Files (*.avi)|*.avi|All Files

                                                                (*.*)|*.*||";

        //필터를 만들어 준다..이건 할줄 모름..

        fdlg =new CFileDialog(TRUE, ".avi", NULL, OFN_HIDEREADONLY |

                                               OFN_OVERWRITEPROMPT,szFilter);

        //대화상자 만들기..이렇게 해야댄다..

        if(fdlg->DoModal()==IDOK) //이제..대화상자를 띠우고..    

        {                               //OK 누르면 실행될 부분..

                m_filename=fdlg->GetPathName();        //대화상자에서 경로를 받아서 저장.

                UpdateData(FALSE);    

        }

  }

  //파일 다이얼로그 만들기

  CFileDialog fdlg(TRUE,"avi",".avi",OFN_OEVRWRITEPROMPT,"Vidoe Files(*.avi)

                                 |*.avi|All Files(*.*)|*.*||");

 

42. Animate Control 사용하기

  m_animate.Open(m_filename); //파일을 연다

  m_animate.Play(0,-1,1);  //(처음프레임,마지막프레임,반복횟수)

  m_animate.Stop(); //정지시키기

  m_ani.SetAutoStart(TRUE);//자동으로 시작한다

 

43. Control 의 Style 바꿔주기

  Control.ModyfyStyle(제거할스타일,추가할스타일); //스타일은 MSDN내용 참조


44. 시스템 날자바꾸기 버튼

  SetSystemTime(),GetSystemTime() //GMT 표준시를 가져온다.

  GetLocalTime(),SetLocalTime()  //현재 지역시간을 가져온다.


        SYSTEMTIME st;

        GetLocalTime(&st); //현재 시간, 날자를 넣는다.

        st.wYear=m_date2.GetYear();

        st.wMonth=m_date2.GetMonth();

        st.wDay=m_date2.GetDay();

        SetSystemTime(&st);


45. 시스템 시간 바꾸기 버튼

        UpdateData(TRUE);

        SYSTEMTIME st;

        GetLocalTime(&st);

        st.wHour=m_time.GetHour();

        st.wMinute=m_time.GetMinute();

        st.wSecond=m_time.GetSecond();

        SetLocalTime(&st);


46.시스템의 드라이브 문자 얻기

        char temp[50];

        GetLogicalDriveStrings(sizeof(temp),temp);

        CString str,str1;

        int n=0;

        while(*(temp+n)!=NULL)

        {

                str=temp+n;

                str1+= " "+str.Left(2);

                n+=4;

        }


47. 현재 작업경로 얻기

  char temp[MAX_PATH]; //MAX_PATH 는 경로길이의 최대를 define 해놓은것.

  GetCurrentDirectory(sizeof(temp),temp);  // 현작업하는 경로(경로 길이,문자형);


48. Tree Control 사용하기

  HTREEITEM hmov,hmus; //핸들을받을 변수 이게 잇어야 하위 디렉토리 생성가능

  hmov=m_tree.InsertItem("영화",TVI_ROOT,TVI_LAST); //,TVI_ROOT,TVI_LAST는 default

  hm1=m_tree.InsertItem("외화",hmov);  //hmov 아래 “외화”트리 생성

  CImageList m_image; //그림을 사용하기 위한 클래스다!! 알아두자..

  m_tree.SetImageList(&m_image,TVSIL_NORMAL); //Tree View Style Image List => TVSIL

  hmov=m_tree.InsertItem("영화",0,1,TVI_ROOT,TVI_LAST);//TVI_ROOT,TVI_LAST는 default

  hmus=m_tree.InsertItem("가요",1,2);//("문자열",처음그림번호,선택시그림)

  hm1=m_tree.InsertItem("외화",2,3,hmov); //그림 번호는 default 로 0이 들어간다..


49. List Control 사용하기

  m_list.ModifyStyle(LVS_TYPEMASK, LVS_ICON); //리스트를 큰아이콘형태로 보인다

  m_list.ModifyStyle(LVS_TYPEMASK, LVS_SMALLICON);//리스트를 작은아이콘형태

  m_list.ModifyStyle(LVS_TYPEMASK, LVS_LIST); //리스트를 리스트형태로 보인다

  m_list.ModifyStyle(LVS_TYPEMASK, LVS_REPORT); //리스트를 자세히형태로 보인다

 

  CImageList m_treeimage; //이미지리스트

  CImageList m_small, m_large;

  m_large.Create(IDB_LARGE,32,0,RGB(255,255,255)); //이거는 클래스에서 추가해준거다

  m_small.Create(IDB_SMALL,16,0,RGB(255,255,255));// (bmp ID값,

  m_list.SetImageList(&m_large,LVSIL_NORMAL);

  m_list.SetImageList(&m_small,LVSIL_SMALL);

  CString name[]={"홍길동","진달래","한국남","개나리"};

  CString tel[]={"400-3759","304-7714","505-9058","700-9898"};

  CString born[]={"1980-1-1","1981-12-20","1980-05-15","1981-08-31"};

  CString sex[]={"남자","여자","남자","여자"};

       

  m_list.InsertColumn(0,"이름",LVCFMT_LEFT,70);

  m_list.InsertColumn(1,"전화번호",LVCFMT_LEFT,80);

  m_list.InsertColumn(2,"생일",LVCFMT_LEFT,90);

  m_list.InsertColumn(3,"성별",LVCFMT_LEFT,50);

        LVITEM it; //리스트 구조체

        char temp[100];

        for(int a=0;a<4;a++)

        {       

                int n=(sex[a]=="남자")?0:1;

                m_list.InsertItem(a,name[a],n); //insert item 은 행을 만들고..

                it.mask=LVIF_TEXT|LVIF_IMAGE; //마스크 설정

                it.iItem=a;

                it.iSubItem=1;//열 설정

                strcpy(temp,tel[a]); //이거 모하는거냐..

                it.pszText=temp;

                m_list.SetItem(&it);                     // setitem 열에 정보를 넣는다.


                it.iSubItem=2; //열 설정

                strcpy(temp,born[a]); //이거 모하는거냐..

                it.pszText=temp;

                m_list.SetItem(&it);                      // setitem 열에 정보를 넣는다.


                it.iSubItem=3; //열 설정

                strcpy(temp,sex[a]); //이거 모하는거냐..

                it.pszText=temp;

                m_list.SetItem(&it);                      // setitem 열에 정보를 넣는다.

 

50. Bitmap Button 사용하기

  CBitmapButton 을 사용한다! CButton 에서 상속 받는클래스임..

  m_button1.Create(NULL, WS_CHILD|WS_VISIBLE|BS_OWNERDRAW,

                                 CRect(310,20,370,50), this,IDC_MYBUTTON); //버튼만들기

  m_button1.LoadBitmapsIDB_UP,IDB_DOWN,IDB_FOCUS,IDB_DISABLE);//버튼의 그림설정

  m_button1.SizeToContent(); //버튼을 그림 크기로 맞춰 준다!!


 //그냥 버튼을 비트맵버튼으로 바꾸기 -> 버튼을 만든다 속성에서 OWNERDRA 속성에 체크!!

  m_button2.LoadBitmaps(IDB_UP,IDB_DOWN,IDB_FOCUS,IDB_DISABLE); //버튼 그림설정

  m_button2.SizeToContent(); //버튼을 그림 크기로 맞춰 준다!!


51. 중복없는 난수발생하기

        int su; //발생된 난수저장

        int a,b;

        BOOL bDasi; //숫자가중복될경우 다시하기위한 변수

        for(a=0;a<9;a++)  //난수 9개 발생

        {

                bDasi=TRUE;

                while(bDasi)

                {

                        bDasi=FALSE;

                        su=rand()%10; //난수발생

                        for(b=0;b

                        {

                                if(temp[b]==su)  //중복이면

                                {

                                        bDasi=TRUE; //중복이 잇으면 다시while 문을 실행한다

                                        break;

                                }//if

                        }//for

                }//while

                temp[a]=su; //중복이 아니면 대입한다

 

52. 메뉴 범위로 사용하기

  ON_COMMAND_RANGE(ID_LEVEL3,ID_LEVEL9,OnLevel); //범위메세지 발생

  //메뉴 ID의 값이 연속된 숫자일 경우 범위로 지정해서 사용할수잇다


53. 한,영 전환함수

  void CCustView::SetHangul(BOOL bCheck) //T:한글 F:영문 이건 외우자..

  {

      //뷰클래스의 윈도우 핸들포인터를 얻는다.

      HIMC hm=ImmGetContext(this->GetSafeHwnd());

      if(bCheck)

      {

          ::ImmSetConversionStatus(hm,1,0);//1은 한글 0은 영문

      }

      else

      {

          ::ImmSetConversionStatus(hm,0,0); //영문으로 바꿔준다

      }

      ::ImmReleaseContext(this->GetSafeHwnd(),hm); //장치를 풀어준다

  }

  #include "imm.h" //헤더 반드시 추가하고

  imm32.lib (라이브러리 파일)를 반드시 링크해주어야 한다!

  **** 라이브러리 추가하기

  프로젝트메뉴 -> 셋팅 -> 링크탭


54. DLL함수정의하기

  임포트함수 :  extern "C"  __declspec(dllimport)   리터형  함수명(매개변수,...) ;

  - 메인프로그램에서 DLL에 있는 함수를 호출할때 사용한다.


  엑스포트함수 :  extern "C"  __declspec(dllexport)   리터형  함수명(매개변수,...)

                      {

                             내용;

                      }

출처: http://weezzle.net/1882
감사합니다.

Posted by SB패밀리




A Complete Scriptable ActiveX Web Control Tutorial using ATL

By Arif Zaman | 18 Dec 2007 | Unedited contribution
An article on Scriptable ActiveX Web Control using ATL
Is your email address OK? You are signed up for our newsletters but your email address is either unconfirmed, or has not been reconfirmed in a long time. Please click here to have a confirmation email sent so we can confirm your email address and start sending you newsletters again. Alternatively, you can update your subscriptions
Scriptable ActiveX Web Control

Introduction

ActiveX control is a term used to denote reusable software components that are based on Microsoft Component Object Model (COM) that allows the developer to create objects or controls that can be used to "activate" content on the World Wide Web.

I have read lots of stuffs over the internet but I have not find any complete guideline or example through the process I can build an ActiveX Control for web using ATL with VC++6.0. I wrote this article because I couldn't find a unified description of this process anywhere on the Web and also from my hurdles. I am going to present you a complete example with necessary stuffs. Hope this will help you to understand how we can build a Scriptable ActiveX control for web using ATL and also you will get the clear vision about the ActiveX security details. It's written with as much detail as possible, but with the assumption that the reader basically knows his stuff.

In this article, I have tried to present you an example of Scriptable ActiveX Web Control using ATL which will display a Label Control with the current Date and Time on your Internet Explorer. Also you will be guided step by step on creating the control using Microsoft VC++6.0 as safe for WEB.

Safety and security

The security concerns associated with ActiveX control is mainly due to the fact that ActiveX controls can do almost anything that a normal application can. Therefore, both malware and useful form ActiveX controls exists; thus the threat level of an ActiveX control can be associated with how trusted its author is.

However, there is one famous case of ActiveX controls safety concern: Internet Explorer. Internet Explorer has the ability to run ActiveX controls within a web page. This is both a blessing and a pain.

ActiveX controls like Adobe Reader, Adobe Flash Player, Apple QuickTime Player, Microsoft Windows Media Player, Real Networks RealPlayer, and Sun Java Virtual Machine are routinely used by Internet surfers every hour of a day all across the globe.

However, opening a web page that contains a harmful ActiveX control, and then allowing Internet Explorer to run that harmful control, would be same as running a malware on the computer. Fortunately, Internet Explorer 6 and Windows Vista have taken actions to reduce such risks.

Requirements for Scriptable ActiveX Controls

Microsoft has published a document that describes all aspects of component object safety with regard to scripting ActiveX controls.

Before registering your control as safe for scripting, you must ensure that your control does not take any actions that may be unsafe when used by a scripting client. Unsafe actions include exposing information normally kept private, such as passwords and other sensitive information, executing files, and making dangerous system calls.

Another type of object safety concerns the use of parameters and properties with the control. When used with a scripting client, a safe control must ensure that the control can continue to function with any possible combination of properties defined by the user.

Design a Scriptable ActiveX Controls

A scriptable ActiveX control is a control that is constructed so that it is appropriate for use by scripting clients. Scriptable controls are designed to be safe when used in a Web browser, such as Internet Explorer, or by scripts written for the Windows Scripting Host (WSH). Scriptable controls also support mechanisms to simplify passing parameters to the control via a scripting language.

By default, ActiveX controls are not considered safe for scriptable clients. If you have an ActiveX control that could be useful by scripting clients, taking a few simple steps can expand the usefulness of your control. If you're using ATL, these changes typically take just a few minutes.

To be scriptable, an ActiveX control must meet the following requirements:

  • Be safe when executed by an arbitrary scripting client.
  • Be registered as "Safe for Scripting".
  • Support the IPersistPropertyBag interface. This is technically not a requirement, but it simplifies the task of passing parameters to the control.
  • Creating a Scriptable ActiveX Control

    To create a Scriptable ActiveX control, use Microsoft Visual C++ 6.0 to perform the following steps:

    1. File->New->Projects.

    2. In the New Project dialog, as shown in Figure 1, select "ATL COM AppWizard".

    New Project dialog

    Figure 1. New Project Dialog

    3. Name the project ScriptableActiveX; for Location, enter the working folder for the project's source code, and then click the OK button.

    4. You will see a screen, as shown in Figure 2, that gives you several choices. The first choice is "Server Type". We are going to build a Server DLL, so make sure that the Server Type is set to "Dynamic Link Library".

    ATL COM AppWizard

    Figure 2. ATL COM AppWizard

    5. The other three checkboxes below do not concern us for this particular project, so we can ignore them. Press the finish button to have the Wizard generate to appropriate files for you.

    6. A "New Project Information" window, as shown in Figure 3, will appear to tell you what files are going to be created. Press the Ok button to accept this.

    New Project Information

    Figure 3. New Project Information

    Creating a new ATL object

    1. From the Insert menu, select "New ATL Object" menu item. The "ATL Object Wizard" window, as shown in Figure 4, will appear.

    ATL Object Wizard

    Figure 4. ATL Object Wizard

    2. Select Controls from the wizard's Category list box, and then select Full Control as the control type. Click Next to begin adding ScriptableLabel control to the project.

    3. The "ATL Object Wizard Properties" dialog, as shown in Figure 5, will appear so that you can define your control's properties. For full controls, such as ScriptableLabel, the dialog box offers four tabs.

    ATL Object Wizard Properties

    Figure 5. ATL Object Wizard Properties

    4. All component types present a Names property page that contains naming attributes for ATL components. You only need to fill in the Short Name property for ScriptableLabel and the other fields are filled in automatically.

    5. The second tab, as shown in Figure 6, for most component types is the Attributes property page, which is used to collect information about the component. All these values are the default options, except "Support Connection Points" properties for the component. Connection points are used to supply events to a control's container.

    ATL Object Wizard Properties (Attributes)

    Figure 6. ATL Object Wizard Properties (Attributes)

    6. The third tab, as shown in Figure 7, is the Miscellaneous tab. It contains attributes specific to ActiveX controls.

    ATL Object Wizard Properties (Miscellaneous)

    Figure 7. ATL Object Wizard Properties (Miscellaneous)

    7. The final tab, as shown in Figure 8, in the dialog box is Stock Properties. It contains a list of all stock properties that can be implemented by an ActiveX control.

    ATL Object Wizard Properties (Stock Properties)

    Figure 8. ATL Object Wizard Properties (Stock Properties)

    8. The ScriptableLabel control uses the following stock properties:

  • Background Color
  • Caption
  • Font
  • Foreground Color
  • After you select the stock properties listed here, click OK to close the dialog box. The ATL New Object Wizard then generates the necessary code and adds it to your project.

    Modify Control Attributes

    The default handler for OnCreate will superclass a default instance of the Windows CStatic class. Apply the following window styles changes to the OnCreate() member function to the ScriptableLabel control:

    Collapse | Copy Code
    
    m_ctlStatic.Create( m_hWnd,
                        rc, 
                        _T("Static"),
                        WS_CHILD|WM_PAINT);
    
    

    Retrieving Ambient Properties

    When the control is initially loaded, it collects the current foreground color, background color, and font from its container. A good time to collect ambient properties is when the control and its container negotiate the client site. Add the following source code to the ScriptableLabel.cpp source file. This function overrides the base class implementation of SetClientSite() and stores the ambient values of these three properties.
    Collapse | Copy Code
    
    STDMETHODIMP CScriptableLabel::SetClientSite(LPOLECLIENTSITE pSite)
    {
        HRESULT hr = CComControlBase::IOleObject_SetClientSite(pSite);
        if(!m_pFont && pSite)
        {
            hr = GetAmbientFontDisp(&m_pFont);
        }
        GetAmbientBackColor(m_clrBackColor);
        GetAmbientForeColor(m_clrForeColor);
        return hr;
    }
    
    

    Add the following member function declaration to the CScriptableLabel class:

    Collapse | Copy Code
    
    STDMETHOD(SetClientSite)(LPOLECLIENTSITE pSite);
    
    

    Drawing the Control

    The OnDraw() function is called by the ATL framework, passing in a structure that contains various bits of information needed to actually paint information on the screen. Our implementation isn�t much more complicated than it would be if we were simply displaying the current Date and Time. Add the following drawing code for the control to the ScriptableLabel.h header file.
    Collapse | Copy Code
    
    void DrawString( HDC hdc, RECT* rc, BSTR caption )
    {
    	USES_CONVERSION;		
    	TCHAR* pCaption = OLE2T(caption);
    
    	DrawText( hdc,
    			 pCaption,
    			 lstrlen( pCaption ),
    			 rc,
    			 DT_WORDBREAK );
    }
    
    HRESULT OnDraw(ATL_DRAWINFO& di)
    {
    	RECT& rc  = *(RECT*)di.prcBounds;
    	HDC   hdc = di.hdcDraw;
    
    	COLORREF clrFore, clrBack;
    	OleTranslateColor(m_clrForeColor, NULL, &clrFore);
    	OleTranslateColor(m_clrBackColor, NULL, &clrBack);
    	SetTextColor(hdc, m_clrForeColor);
    	HBRUSH hbrBtn = CreateSolidBrush(m_clrBackColor);
    
    	FillRect(hdc, &rc, hbrBtn);		
    	DrawString(hdc, &rc, m_bstrCaption);	
    
    	DeleteObject(hbrBtn);
    	return 0;
    }
    
    

    Implementing IPersistPropertyBag

    To simplify the use of ScriptableLabel in a scripting client, such as Internet Explorer, the control must support the IPersistPropertyBag interface. The ATL class library includes a class, IPersistPropertyBagImpl, that provides a default implementation of IPersistPropertyBag that is sufficient in most cases.

    1. Add the following line to your class derivation list:

    Collapse | Copy Code
    
    public IPersistPropertyBagImpl<CScriptableLabel>
    
    

    2. Add the following lines to your COM_MAP:

    Collapse | Copy Code
    
    COM_INTERFACE_ENTRY(IPersistPropertyBag)
    
    

    Marking the Control as Safe for Scriptable Clients

    You can easily add support for marking the Control as Safe for Scriptable Clients by implementing the IObjectSafety interfaces. This is done by deriving your control from the default ATL implementation, IObjectSafetyImpl.

    You can use two methods to mark a control as safe for scripting clients:

  • Make appropriate entries directly in the System Registry.
  • Implement the IObjectSafety interface.
  • Microsoft recommends that you use new controls to implement the IObjectSafety interface instead of making Registry entries. IObjectSafety enables the control to apply much finer-grained safety policies than possible using the Registry.

    ATL provides a default implementation of IObjectSafety that you easily can take advantage of by deriving your class from the IObjectSafetyImpl class.

    1. Add the following line to your class derivation list:

    Collapse | Copy Code
    
    public IObjectSafetyImpl<CScriptableLabel, 
                            INTERFACESAFE_FOR_UNTRUSTED_CALLER | 
                            INTERFACESAFE_FOR_UNTRUSTED_DATA>
    
    

    Two template arguments are passed to IObjectSafetyImpl:

  • The name of the class deriving from IObjectSafetyImpl.
  • The type of safety to be applied to the control.
  • Two values may be passed for the safety options:

    INTERFACESAFE_FOR_UNTRUSTED_CALLER specifies that your control can be used safely by a scripting client and does not violate any of Microsoft's security or safety guidelines. INTERFACESAFE_FOR_UNTRUSTED_DATA specifies that your control will work (or at least degrade gracefully) in the presence of any possible set of par

    2. Add the following lines to your COM_MAP:

    Collapse | Copy Code
    
    COM_INTERFACE_ENTRY(IObjectSafety)
    
    

    Compiling the Scriptable ActiveX Control

    Compile the ScriptableActiveX project. The compiler will register your new DLL in the registry so that other programs can make use of it. You can test the control in a variety of control containers, including Visual Basic and Visual C++. You will find lots of examples using Visual Basic and Visual C++. Better! we consider as web control.

    Because the ScriptableLabel control is scriptable, you can also use the control on an HTML page with Internet Explorer. Lets try it out.

    Building a Signed ActiveX Control

    To use your control on web pages, it is very convenient to distribute it as a .cab (cabinet file). This is a compressed archive - the classic use is to put the .cab file on a web server, and refer to it from web pages that host the control. Internet Explorer is smart enough to download and install the control if it is not already installed on the client machine, and to selectively update any files that are newer in the .cab file. Microsoft provides CABARC.EXE for creating and editing .cab files.

    The Contents of a CAB File

    A CAB file contains at least two files in the archive: an ActiveX component file (.EXE, .DLL or .OCX file), and an .INF file.

  • Component File (.EXE, .DLL or .OCX): The type of ActiveX component you create determines the file extension of the file included here. All ActiveX controls have a .OCX extension. Other ActiveX components either .EXEs or .DLLs. This file is your ActiveX component being installed.
  • .INF: This is the Information file that contains information about what other files your ActiveX component depends on (dependency files), where to get copies of those files, and how to install those files.
  • Creating a CAB File

    This section describes creating CAB files for distributing ATL and MFC controls over the Internet.

    To create a CAB file:

    1. Create an INF file.

    2. Run the CABARC utility.

    1. Creating an INF File

    The INF file is a text file that specifies the files (such as DLLs or other OCXs) that need to be present or downloaded for your control to run. An INF file allows you to bundle all the needed files in one compressed CAB file. By default, files with the same version numbers as existing files on the user's hard disk will not be downloaded.

    As an example, the following INF file will be used to create a CAB file for the ScriptableActiveX control.

    Collapse | Copy Code
    ; Sample INF file for SCRIPTABLEACTIVEX.DLL
    [version] 
    ; version signature (same for both NT and Win95) do not remove
    signature="$CHICAGO$"
    AdvancedINF=2.0  
    
    [Add.Code]
    ScriptableActiveX.dll=ScriptableActiveX.dll
    ScriptableActiveX.inf=ScriptableActiveX.inf
    
    [ScriptableActiveX.dll]
    file-win32-x86=thiscab
    clsid={B8748B60-E34D-42AA-9309-8012CA4964AC} 
    FileVersion=1,0,0,1 
    RegisterServer=yes
    
    [ScriptableActiveX.inf]
    file=thiscab
    ; end of INF file
    
    The clsid is the CLSID of the control to be installed.

    2. Running the CABARC Utility

    Once you have created an INF file, run the CABARC utility to create the CAB file. You should run CABARC in the directory that contains your source files. On the command line, put the source files in the order they appear in the INF and the INF file last. For example, to make a CAB file for the Polygon control from the INF above, use the following command:

    Collapse | Copy Code
    CABARC -s 6144 n ScriptableActiveX.cab ScriptableActiveX.dll ScriptableActiveX.inf
    
    The -s option reserves space in the cabinet for code signing. The n command specifies that you want to create a CAB file.

    Code Signing Tools

    Microsoft provides code signing tools as part of the "Microsoft .NET Framework software development kit (SDK) 1.1". To download the SDK, visit the following Microsoft Web site: .NET Framework SDK Version 1.1. After you install the SDK you will be able to find the code signing files in the following location on your PC: "\Program Files\Microsoft.NET\SDK\v1.1\Bin". From the many files found in the above BIN directory the following are of interest to us:

  • signcode.exe
  • makecert.exe
  • cert2spc.exe
  • chktrust.exe
  • Recently, with the introduction of "Studio 2005" Microsoft has released a new set of tools. The new set of tools is provided as part of the "Visual Studio 2005" and in the "Platform SDK". To download the "Platform SDK", visit the following Microsoft Web site: Platform SDK Full Download. After you install the SDK you will be able to find the code signing files in the following location on your PC: "\Program Files\Microsoft Platform SDK\Bin". From the many files found in the above BIN directory the following are of interest to us:

  • signtool.exe
  • makecert.exe
  • cert2spc.exe
  • All the above mentioned tools are actually small console programs that should be run from a command prompt. When run, each program expects command-line parameters in a special syntax. Now, we will demonstrate how to do it in this article.

    Signing a CAB File

    Security is becoming increasingly important for software and media developers. "Code Signing" enables end users of your software to verify that the code you provide comes from the rightful source and that it has not been maliciously altered or accidentally corrupted.

    Code signing technology is available for many years, but many software vendors refrained from using it because of the complexity involved in the process. However - since the release of "Windows XP Service Pack 2" - code signing can not be ignored any more.

    With XP SP2, when downloading an UN-SIGNED program with Internet Explorer and choosing to open it (or even if saved to a file and later opened via Windows Explorer), the browser will display the "Security Warning" dialog. BUT when downloading a SIGNED program the browser does not result in annoying error messages complaining that it is an unsigned or unsafe control.

    You have 2 options to sign your code:

    Option-1. Using Test Certificate

    Option-2. Using Public Certificate

    Option-1: Using Test Certificate

    Before you start with the process it is highly recommended that you create a "TEST certificate", and use it to sign your program as a test run. A program signed by this certificate must not be distributed on the net.

    Use the following steps to sign and validate the .cab file:

    1. Type the following at a command prompt to create a private key file, Mycert.pvk.

    Collapse | Copy Code
    makecert -sv "mycert.pvk" -n "CN=My Company" mycert.cer
    
    The file created in this step, Mycert.cer, is used to create an .spc file. Type the password in the dialog box.

    2. Create an .spc file from the certificate file with the correct password. To do so, type the following line at a command prompt:

    Collapse | Copy Code
    cert2spc mycert.cer mycert.spc
    
    Note that this step involves creation of a test private key. Alternatively, valid certificates can be created through Microsoft Certificate Server for Intranet use or purchased from external vendors for Internet use.

    3. Create a Personal Information Exchange file. This step is optional. You will need it only if you select to sign your code using SIGNTOOL.EXE as described above. The following command line may be used to create a "Personal Information Exchange" (PFX) file:

    Collapse | Copy Code
    pvk2pfx -pvk mycert.pvk -pi Pass1 -spc mycert.spc -pfx mycert.pfx -po Pass2 -f
    
    PVK2PFX.EXE expects 2 passwords:

    Pass1: - Provide the same password you used when creating the Private & Public keys.

    Pass2: - Provide a new password to protect the PFX file.

    Once signed you can distribute the ActiveX component to any user, BUT the user must install certificate chain. If you want users to install an ActiveX component without the Root and Intermediate certificates then buy a Public code-signing certificate.

    Option-2: Using Public Certificate

    To be able to sign your code you will need a certificate. Certificates are issued by special Internet organizations called CA (Certificate Authority). There are many such organizations, the most prominent ones are: verisign.com and tawthe.com.

    You can get a full list of CAs by going to: Microsoft Root Certificate Program Members

    However - acquiring a certificate is quite a tedious and time consuming process, (The CA has to identify you or your organization before it can issue a certificate) and you should expect to pay few hundred of dollars for the certificate.

    Finishing Touches

    Now, Use the key information to sign the .cab file:

    Collapse | Copy Code
    signcode -v mycert.pvk -spc mycert.spc ScriptableActiveX.cab -t [Timestamp server URL] 
    

    Or, the following commands may be used to sign your code using SIGNTOOL.EXE:

    Collapse | Copy Code
    signtool sign /f mycert.pfx /p Pass2 /v ScriptableActiveX.cab /t [Timestamp server URL]
    
    Pass2: Enter here the second password you used when creating the PFX file.

    Note Specify the timestamp server URL at this step. The timestamp server URL provides a place to enter or edit the location of a timestamp server. A timestamp server validates the date and time that the cabinet file was signed. Certificate files can expire after a certain period of time. Contact your certificate file provider (certificate authority) for the location of their timestamp server. The URL of a time stamping service provided for free by verisign.com http://timestamp.verisign.com/scripts/timstamp.dll

    Validate a CAB File

    Follow this procedure to validate a .cab file:

    Option-A: Using CHKTRUST

    a. Type the following at a command prompt to run SETREG.EXE on the client system with the TRUE value so that the test certificates are recognized:

    Collapse | Copy Code
    setreg -q 1 TRUE
    

    b. Run CHECKTRUST.EXE to ensure that the CAB file is signing correctly:

    Collapse | Copy Code
    chktrust ScriptableActiveX.cab
    
    Expected results:
    Collapse | Copy Code
    ScriptableActiveX.cab: Succeeded
    

    Option-B: Using SIGNTOOL

    Run SIGNTOOL.EXE to verify the signing:

    Collapse | Copy Code
    signtool verify /v /a ScriptableActiveX.cab
    
    Expected results:
    Collapse | Copy Code
    ScriptableActiveX.cab: Succeeded
    

    Option-C: Using Properties

    You can also use the following method to verify your digital signature:

  • Open Explorer.
  • Browse to the file you just signed.
  • Right Click the file name and select "Properties".
  • Explorer will present you with the properties dialog of the file. This properties dialog will include a new tab "Digital Signatures". You can now read the details of the signature in this tab.

    Embedding a Signed CAB File on a Web Page

    ATL and MFC controls are embedded in Web pages using the <OBJECT> tag. Within the <OBJECT> tag, you need to specify three attributes for the control:

    Collapse | Copy Code
    
    <OBJECT classid=B8748B60-E34D-42AA-9309-8012CA4964AC
    	id=ScriptableLabelControl
    	CODEBASE ="ScriptableActiveX.cab#version=1,0,0,1">
    </OBJECT>
    
    

    The ID parameter refers the name of the control. The CLASSID parameter refers the CLSID of the control. And the CODEBASE parameter refers the location from which to download the control. Note that CODEBASE can point at a number of different file types successfully.

    If you include the optional version number with a CAB file, the version number should refer to the control being downloaded. For example, since ScriptableActiveX.dll has a version number of 1, 0, 0, 1, the version for the CAB is also 1, 0, 0, 1.

    If you do not include the version number, older versions of the same control will not be replaced if they are found on the client machine.

    Testing the Scriptable ActiveX Web Control

    Adding controls by hand is not a simple process. The CLSID numbers are unwieldy to type, and it can be difficult to visualize the effects of the parameter settings on the control. To help with these difficulties, Microsoft created the ActiveX Control Pad, which can be obtained from their web site at Microsoft ActiveX Control Pad.

    To test the Scriptable ActiveX Web Control with JavaScript, you may use ActiveX Control Pad to create or you may find it easier to lay out your page in your preferred HTML editor as the following HTML code:

    Collapse | Copy Code
    
    <HTML>
    <HEAD>
    <TITLE>Scriptable ActiveX Web Control</TITLE>
    <SCRIPT LANGUAGE="JavaScript">
    	function NotifyActiveX(e)
    	{
    		if ( e.readyState != 4 ) return;
    		window.setInterval("document.all.ScriptableLabelControl.caption=(new Date()).toString()",1000);
    	}
    </SCRIPT>
    <STYLE TYPE="text/css">
    #ScriptableLabelControl {
    	width: 250px;
    	height: 27px;
    	padding: 10px;
    	border: thin solid #408080;
    	margin-left: 10em;
    }
    </STYLE>
    </HEAD>
    
    <BODY>
    <OBJECT 
      ID="ScriptableLabelControl"
      onReadyStateChange="NotifyActiveX(this)"
      CLASSID="CLSID:B8748B60-E34D-42AA-9309-8012CA4964AC"
      CODEBASE="ScriptableActiveX.cab">
    </OBJECT>
    </BODY>
    </HTML>
    
    

    Save this HTML code in your web server, and browse it!

    Internet Explorer will prompt the user before downloading and installing the ActiveX control. If Internet Explorer is attempting to install the Signed ActiveX control automatically it shows the prompt, as shown in Figure 9.

    Install ActiveX

    Figure 9. Install ActiveX

    When prompted with a certificate, please accept it. When downloading and installation process will be finished, the current date and time should appear, as shown in Figure 10.

    Scriptable ActiveX Control

    Figure 10. Scriptable ActiveX Control

    If you see the current date and time displayed properly in your browser, CONGRATULATIONS! ActiveX and scripting are working properly.

    Note:

  • If you see a date and time but it isn't the right time, your PC's clock is set wrong! Double-click the time in the system tray to correct it.
  • If you see a blank space, ActiveX is probably working properly, but not scripting.
  • If you see the message ActiveX is not supported, then your browser doesn't recognize ActiveX at all. Netscape, Opera, or other browsers usually do not support ActiveX.
  • When you think you've corrected any problem you are having with this, simply refresh the page [press F5] to try again.
  • Conclusion

    For a control to be scriptable, it must follow Microsoft's object safety guidelines and be marked as safe for scripting. In this article, you examined the IObjectSafety interface and learned how a control built using ATL can take advantage of IObjectSafety. An example of a safely scriptable ActiveX control helped you explore this topic.

    License

    This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

    출처: http://www.codeproject.com/KB/atl/ScriptableActiveX.aspx

    Posted by SB패밀리


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

    #pragma comment(lib, "User32.lib")

    #define BUFSIZE 256

    typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
    typedef BOOL (WINAPI *PGPI)(DWORD, DWORD, DWORD, DWORD, PDWORD);

    BOOL GetOSDisplayString( LPTSTR pszOS)
    {
       OSVERSIONINFOEX osvi;
       SYSTEM_INFO si;
       PGNSI pGNSI;
       PGPI pGPI;
       BOOL bOsVersionInfoEx;
       DWORD dwType;

       ZeroMemory(&si, sizeof(SYSTEM_INFO));
       ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));

       osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);

       if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
          return 1;

       // Call GetNativeSystemInfo if supported or GetSystemInfo otherwise.

       pGNSI = (PGNSI) GetProcAddress(
          GetModuleHandle(TEXT("kernel32.dll")),
          "GetNativeSystemInfo");
       if(NULL != pGNSI)
          pGNSI(&si);
       else GetSystemInfo(&si);

       if ( VER_PLATFORM_WIN32_NT==osvi.dwPlatformId &&
            osvi.dwMajorVersion > 4 )
       {
          StringCchCopy(pszOS, BUFSIZE, TEXT("Microsoft "));

          // Test for the specific product.

          if ( osvi.dwMajorVersion == 6 )
          {
             if( osvi.dwMinorVersion == 0 )
             {
                if( osvi.wProductType == VER_NT_WORKSTATION )
                    StringCchCat(pszOS, BUFSIZE, TEXT("Windows Vista "));
                else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2008 " ));
             }

             if ( osvi.dwMinorVersion == 1 )
             {
                if( osvi.wProductType == VER_NT_WORKSTATION )
                    StringCchCat(pszOS, BUFSIZE, TEXT("Windows 7 "));
                else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2008 R2 " ));
             }
            
             pGPI = (PGPI) GetProcAddress(
                GetModuleHandle(TEXT("kernel32.dll")),
                "GetProductInfo");

             pGPI( osvi.dwMajorVersion, osvi.dwMinorVersion, 0, 0, &dwType);

             switch( dwType )
             {
                case PRODUCT_ULTIMATE:
                   StringCchCat(pszOS, BUFSIZE, TEXT("Ultimate Edition" ));
                   break;
                case PRODUCT_PROFESSIONAL:
                   StringCchCat(pszOS, BUFSIZE, TEXT("Professional" ));
                   break;
                case PRODUCT_HOME_PREMIUM:
                   StringCchCat(pszOS, BUFSIZE, TEXT("Home Premium Edition" ));
                   break;
                case PRODUCT_HOME_BASIC:
                   StringCchCat(pszOS, BUFSIZE, TEXT("Home Basic Edition" ));
                   break;
                case PRODUCT_ENTERPRISE:
                   StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition" ));
                   break;
                case PRODUCT_BUSINESS:
                   StringCchCat(pszOS, BUFSIZE, TEXT("Business Edition" ));
                   break;
                case PRODUCT_STARTER:
                   StringCchCat(pszOS, BUFSIZE, TEXT("Starter Edition" ));
                   break;
                case PRODUCT_CLUSTER_SERVER:
                   StringCchCat(pszOS, BUFSIZE, TEXT("Cluster Server Edition" ));
                   break;
                case PRODUCT_DATACENTER_SERVER:
                   StringCchCat(pszOS, BUFSIZE, TEXT("Datacenter Edition" ));
                   break;
                case PRODUCT_DATACENTER_SERVER_CORE:
                   StringCchCat(pszOS, BUFSIZE, TEXT("Datacenter Edition (core installation)" ));
                   break;
                case PRODUCT_ENTERPRISE_SERVER:
                   StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition" ));
                   break;
                case PRODUCT_ENTERPRISE_SERVER_CORE:
                   StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition (core installation)" ));
                   break;
                case PRODUCT_ENTERPRISE_SERVER_IA64:
                   StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition for Itanium-based Systems" ));
                   break;
                case PRODUCT_SMALLBUSINESS_SERVER:
                   StringCchCat(pszOS, BUFSIZE, TEXT("Small Business Server" ));
                   break;
                case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
                   StringCchCat(pszOS, BUFSIZE, TEXT("Small Business Server Premium Edition" ));
                   break;
                case PRODUCT_STANDARD_SERVER:
                   StringCchCat(pszOS, BUFSIZE, TEXT("Standard Edition" ));
                   break;
                case PRODUCT_STANDARD_SERVER_CORE:
                   StringCchCat(pszOS, BUFSIZE, TEXT("Standard Edition (core installation)" ));
                   break;
                case PRODUCT_WEB_SERVER:
                   StringCchCat(pszOS, BUFSIZE, TEXT("Web Server Edition" ));
                   break;
             }
          }

          if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 )
          {
             if( GetSystemMetrics(SM_SERVERR2) )
                StringCchCat(pszOS, BUFSIZE, TEXT( "Windows Server 2003 R2, "));
             else if ( osvi.wSuiteMask & VER_SUITE_STORAGE_SERVER )
                StringCchCat(pszOS, BUFSIZE, TEXT( "Windows Storage Server 2003"));
             else if ( osvi.wSuiteMask & VER_SUITE_WH_SERVER )
                StringCchCat(pszOS, BUFSIZE, TEXT( "Windows Home Server"));
             else if( osvi.wProductType == VER_NT_WORKSTATION &&
                      si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64)
             {
                StringCchCat(pszOS, BUFSIZE, TEXT( "Windows XP Professional x64 Edition"));
             }
             else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2003, "));

             // Test for the server type.
             if ( osvi.wProductType != VER_NT_WORKSTATION )
             {
                if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_IA64 )
                {
                    if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
                       StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter Edition for Itanium-based Systems" ));
                    else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
                       StringCchCat(pszOS, BUFSIZE, TEXT( "Enterprise Edition for Itanium-based Systems" ));
                }

                else if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 )
                {
                    if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
                       StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter x64 Edition" ));
                    else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
                       StringCchCat(pszOS, BUFSIZE, TEXT( "Enterprise x64 Edition" ));
                    else StringCchCat(pszOS, BUFSIZE, TEXT( "Standard x64 Edition" ));
                }

                else
                {
                    if ( osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER )
                       StringCchCat(pszOS, BUFSIZE, TEXT( "Compute Cluster Edition" ));
                    else if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
                       StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter Edition" ));
                    else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
                       StringCchCat(pszOS, BUFSIZE, TEXT( "Enterprise Edition" ));
                    else if ( osvi.wSuiteMask & VER_SUITE_BLADE )
                       StringCchCat(pszOS, BUFSIZE, TEXT( "Web Edition" ));
                    else StringCchCat(pszOS, BUFSIZE, TEXT( "Standard Edition" ));
                }
             }
          }

          if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 )
          {
             StringCchCat(pszOS, BUFSIZE, TEXT("Windows XP "));
             if( osvi.wSuiteMask & VER_SUITE_PERSONAL )
                StringCchCat(pszOS, BUFSIZE, TEXT( "Home Edition" ));
             else StringCchCat(pszOS, BUFSIZE, TEXT( "Professional" ));
          }

          if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 )
          {
             StringCchCat(pszOS, BUFSIZE, TEXT("Windows 2000 "));

             if ( osvi.wProductType == VER_NT_WORKSTATION )
             {
                StringCchCat(pszOS, BUFSIZE, TEXT( "Professional" ));
             }
             else
             {
                if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
                   StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter Server" ));
                else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
                   StringCchCat(pszOS, BUFSIZE, TEXT( "Advanced Server" ));
                else StringCchCat(pszOS, BUFSIZE, TEXT( "Server" ));
             }
          }

           // Include service pack (if any) and build number.

          if( _tcslen(osvi.szCSDVersion) > 0 )
          {
              StringCchCat(pszOS, BUFSIZE, TEXT(" ") );
              StringCchCat(pszOS, BUFSIZE, osvi.szCSDVersion);
          }

          TCHAR buf[80];

          StringCchPrintf( buf, 80, TEXT(" (build %d)"), osvi.dwBuildNumber);
          StringCchCat(pszOS, BUFSIZE, buf);

          if ( osvi.dwMajorVersion >= 6 )
          {
             if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 )
                StringCchCat(pszOS, BUFSIZE, TEXT( ", 64-bit" ));
             else if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_INTEL )
                StringCchCat(pszOS, BUFSIZE, TEXT(", 32-bit"));
          }
         
          return TRUE;
       }

       else
       { 
          printf( "This sample does not support this version of Windows.\n");
          return FALSE;
       }
    }

    int __cdecl _tmain()
    {
        TCHAR szOS[BUFSIZE];

        if( GetOSDisplayString( szOS ) )
            _tprintf( TEXT("\n%s\n"), szOS );
    }

    Posted by SB패밀리

    닷넷 프레임워크 클래스 라이브러리에 있는 Trace 클래스를 이용하면 된다.


    String^ logFile = "C:\\service_log.txt";
        TextWriterTraceListener^ serviceTraceListener = nullptr;

        // Create a log file for trace output.
        // A new file is created each time.  If a
        // previous log file exists, it is overwritten.
        StreamWriter^ myFile = File::CreateText( logFile );

        // Create a new trace listener that writes to the text file,
        // and add it to the collection of trace listeners.
        serviceTraceListener = gcnew TextWriterTraceListener( myFile );
        Trace::Listeners->Add( serviceTraceListener );
        Trace::AutoFlush = true;
        Trace::WriteLine( DateTime::Now.ToLongTimeString() + " - Service main method starting...", "Main" );

        // Load the service into memory.
        System::ServiceProcess::ServiceBase::Run( gcnew SimpleService );
        Trace::WriteLine( DateTime::Now.ToLongTimeString() + " - Service main method exiting...", "Main" );

        // Remove and close the trace listener for this service.
        Trace::Listeners->Remove( serviceTraceListener );
        serviceTraceListener->Close();
        serviceTraceListener = nullptr;
        myFile->Close();



    Posted by SB패밀리

     MFC ActiveX를 만들기 할때 관련 DLL을 포함시켜야하는 경우가 있다.

     [App.Code]에 포함시킬 때 순서는 OCX 먼저 포함하고 DLL은 나중에 포함시켜야
    DLL먼저 설치되고 나중에 OCX 파일이 실행되어 문제가 없다

    AcitveX에 포함할 MFC 관련 DLL

    MFC42.DLL
    MSVCRT.DLL
    OLEPRO32.DLL


    참고로 ActiveX설치할 때 설치되는 OCX나 INF파일의 위치는
    웹상에서 설치된 파일들의 정보
    레지스트리는
    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Code Store Database\Distrbution Units
    폴더상에서는
    C:\Windows\Downloaded Program Files
    를 확인한다.

    별도의 언인스톨 프로그램이 없다면
    위의 레지스트리와 폴더상에서 해당 CLSID에 해당하는 파일이나 경로를 삭제하면 된다.

    Posted by SB패밀리