비주얼 스튜디오에서 다이알로스 리소스를 편집하고 나서..
프로그램을 실행시키면 화면이 나오게 된다.

이 때 화면의 컨트롤끼리 이동을 할 때 TAB 및 shift + TAB를 이용하여 건너 다닐 수 있는데
여러번 수정하다 보면 순서가 바뀔때가 있다 이 때 어떻게 쉽게 원하는 순서대로 맞추어 줄 수 있는가?

리소스 편집상태에서 Ctrl + D를 눌러보자 그러면 다음과 같은 그림이 나올것이다.


이 상태에서 원하는 순서대로 마우스로 클릭하면 번호가 바뀌면서 1번부터 매겨지게 된다.
그럼 만사 오케~
가끔 다이알로그를 사용하다가, 참조된 소스를 보면,,,.
다이알로그에서는 볼수 없던 이벤트를 사용하는 것들이 보인다.

예를 들면
WM_ERAGEBKGND
WM_WINDOWSPOSCHANGED
WM_FONTCHANGE

이와 같은 메시지들을 다이알로그에서 자연스럽게 사용하려면
엄청난 고수가 되어 저걸 모두 외워서 사용해야하는가?

결론은 전혀 그렇지 않다이다.
저런 메시지가 존재한다는 것을 알고 있다면 일반 윈도우에서 사용하는 것과
별반다르지 않게 클래스 위저드를 이용하여 충분히 쉽게 사용이 가능하다.

1. 클래스 위저드를 띄운다.
2. Class name: 콤보에서 해당 원하는 다이알로그 클래스를 선택한다.
3. Class Info 탭을 선택한다.
그러면 하단부의 Advanced Options의 Message Filter란 항목이 보일 것이다.
이걸  Window로 변경하면 CWnd에 사용가능한 모든 메시지 항목이 메시지 맵에 보여지게 된다.



이렇게 메시지를 필터링해서 보여주는 이유는 너무 많은 메시지가 한번에 보여지게 되면..
시각적인 부담이 있고, 필요한 항목을 적절하게 검색하는데 시간이 걸리기도 하지만..
중요한 것은 각각의 옵션타입마다 그 클래스에서 고유하게 사용되는 이벤트들을 적절하게
필터링하여 보여주기 때문에 이런 기능이 존재하는거라 생각한다.

키워드 [Programming][VC++][Multimedia]
http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=51&MAEULNo=20&no=7518&ref=7518

응용 프로그램에서 간단하게 소리 효과를 낼 경우 가장 간단하게 사용할 수 있는 수준의 API중에
PlaySound라는 것이 제공된다.

장점 : 사용하기 쉽다.
단점 : 제어 할 수 있는 부분이 거의??? 없다.


PlaySound()는 아주 간단하게 리소스나 파일의 wav폼 파일을 읽어서 재생할 수 있는 함수입니다.
단점이 싱크모드와 어싱크 모드로 재생이 가능한데.. 싱크모드로 돌리면 제어가 불가능하고..
어싱크모드로 돌리면 종료시 점을 알수 없다는데 있습니다.
 
아래의 기법을 이용하면 어싱크모드로 재생하면서 종료 시점을 알수 있고요..
Sleep에 의한 오차 100ms가 있긴 하지만.. 어쨋든...
 
원하는 소리를 원하는 시점에서 재생 및 중지를 시킬 수 있다는게 장점입니다.
 
// 소리를 재생하는 스레드입니다.
DWORD CALLBACK AAA(void* param)
{
   // 임시로 aaa.wav란 넘을 어싱크모드로 플레이 합니다.
    PlaySound("aaa.wav", NULL, SND_FILENAME | SND_ASYNC);
 
    while(1)
    {
        Sleep(100);
       
        // 재생이 끝날 때 까지 대기 합니다.
        // SND_NOSTOP 옵션이 있어서 현재 재생중일 때는 아래의 함수가 FALSE를 리턴함다.
        if(PlaySound(NULL, NULL, SND_PURGE | SND_NOSTOP | SND_NOWAIT | SND_SYNC))
            break;
    }
 
    return 0;
}

 
// 아무 곳에서나 현재 재생중인 음악을 중지 하시고 싶으시면.
// 음악을 중지시키면 당연히 위의 스레드도 바로 종료하게 됩니다.
PlaySound(NULL, NULL, SND_PURGE | SND_NOWAIT | SND_ASYNC);

키워드 [Programming][VC++][Security][open ssl]
http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=51&MAEULNo=20&no=7598&ref=7598


윈도에서 OpenSSL을 사용할경우 인증서를 익스포트 시켜서
PEM 파일로 변환한 후 로드하는 과정이 필요하죠.

보통 제어판에서 인증서를 열어가지고 마우스로 콕콕 찍어서..
프라이빗 키 설정한 후 익스포트 하여 사용하곤 하는데..

귀찬죠.. 가끔 까먹기도 하죠.. 설명할라믄 메뉴얼 작성해야죠.. -_-
윈도 크립토 API를 사용하여 간단하게 샘플을 만들어 보았습니다.

//////////////////////////////////////////////////////////
#include <windows.h>
#include <wincrypt.h>
#include <cryptuiapi.h>
 
class CCertToPFX 
{
public:
    CCertToPFX();
    virtual ~CCertToPFX();
 
    void SetStoreName(CHAR* name);
    void SetCertName(CHAR* name);
    void SetSaveName(CHAR* name);
    void SetPrivatePassword(CHAR* name);
 
    BOOL Export();
 
    DWORD GetLastError();
 
protected:
    HCERTSTORE  m_hCertStore;       
    HCERTSTORE  m_hCertTemp;       
    CHAR        m_pszStoreName[256];
    CHAR        m_pszCertName[256];
    CHAR        m_pszSaveName[MAX_PATH];
    CHAR        m_pszPrivatePass[256];
    DWORD       m_dwLastError;
};


샘플 코드는 아래와 같습니다.
////////////////////////////////////////////////////
    CCertToPFX con;
    con.SetStoreName("MY");
    con.SetCertName("my_ssl");
    con.SetSaveName("C:\\test.pfx");
    con.SetPrivatePassword("my_password");
 
    if(!con.Export())
        con.GetLastError();

http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=51&MAEULNO=20&no=7621&page=1

요 에러는 새로운 플랫폼SDK가 VC 6.0을 지원하지 않아 발생하는 에러이다.
Platform SDK 2005년 4월 버전부터 전혀 6.0을 고려하지 않기 때문에, 우짤 수 없다.

머 VC2003이나 VC2005를 설치하고, 플랫폼SDK를 삭제하는 하나의 방법과
플랫폼 SDK의 uuid.lib를 삭제하거나 uuid.was_a_lib 로 이름을 일단 바까놓으면 문제없다.

키워드 [Programming][VC++][Icon][Merge]
http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=51&MAEULNo=20&no=265&ref=192

이번에 쓰는 팁은 아주 간단한 겁니다... 파일이나 폴더 브라우져를 만드시는 분에게
꼭 필요한 팁이 아닐까 생각합니다.
강좌를 중단한건 엄청 잘못했지만 그래도 관련된 자료나 팁은 계속 올리겠습니다.

이번에 사용되는 팁은 아이콘을 표시할 때 공유되는 폴더나 바로가기 아이콘 처럼
원래의 아이콘에 오버레이된 이미지를 사용하여 원하는 아이콘을 만들어 사용하는
팁입니다.
디바이스 컨텍스나 이미지 처리를 하지않고 사용할 수 있는 간단한 방법이지요... ^^;;;

여기서는 바로가기 아이콘을 흉내낸 처리루틴입니다.

// hiFolder는 원본 아이콘
HICON GetLinkedIcon(HICON hiFolder)
{
    // 리턴할 아이콘
    HICON hiShared;
    // 바로가기의 쪼그만 사각형에 화살표가 들은 아이콘을 저장할 핸들
    HICON hiHand;

    // 바로가기의 쪼그만 사각형 아이콘 핸들을 얻어온다.
    ExtractIconEx("shell32.dll", 29, &hiHand, NULL, 1);

    // 주어진 플래그대로 HIMAGELIST 를 만든다.
    HIMAGELIST himl = ImageList_Create(32, 32, ILC_MASK, 1, 0);

    // 아이콘의 Merge 처리를 위하여 이미지 리스트에 추가한다.
    ImageList_AddIcon(himl, hiFolder);
    ImageList_AddIcon(himl, hiHand);

    // 두개의 아이콘을 Merge 시킨다.
    HIMAGELIST himlNew = ImageList_Merge(himl, 0, himl, 1, 0, 0);

    // 이미지 리스트에서 Merge된 아이콘을 찾아낸다.
    hiShared = ImageList_ExtractIcon(0, himlNew, 0);

    // 다쓴 아이콘 지우기
    DestroyIcon(hiHand);

    // 다쓴 이미지 리스트 지우기
    ImageList_Destroy(himl);
    ImageList_Destroy(himlNew);

    // 완성된 아이콘 돌려주기
    return hiShared;
}

키워드 [Programming][VC++][Tip]
http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=51&MAEULNo=20&no=769&ref=450

오늘 작업을 하다가 또다시 precompiled error라는 넘과 부딭히는 불쌍사가
발생하였습니다.
갑자기 먼 이유로 이런 현상이 발생하는지는 잘 몰랐구여, 발생원인은
아직도 모릅니다.

지금까지 질문과 답변을 보면 프리컴파일을 하지 않는 다는 셑팅 옵션을 첵크해서
뛰어난 기능을 막아버리고 답답하게 쓰거나, 간단한 프로젝트라면 다시 만드는
경우도 많았습니다.

그러다 결국 오늘 자밨습니다. 푸하하하하

셑팅의 결과는 그림으로 화면을 캪쳐하여 올려 놓아습니다.

완벽하게 동작하더군여.. 푸헐..

프로젝트 셑팅과 각각의 파일 셑팅의 차이점을 그림으로 올려 놓았으니..

보시면 한방에 해결하실 수 있을겁니다..

푸하하.. 오늘은 푸근한 맘으로 잠들 수 있으려나.. ^^

다시 #########################################################################

이미지로 캡쳐해서 올려 놓았는데.. 파일을 볼 수가 없다는 군여.. --;;;

그래서, 간단하게 설명도 함께 올립니다. (그림 보면 한방인데 --;;;)

먼저 [프로젝트]-[셑팅]-[C/C++]

여기에서 Category - Precompiled Headers 를 선택합니다.

1. 먼저 왼쪽에 보이는 트리에서 프로젝트를 통채로 선택합니다.

그리고, use precompiled header file[.pch] 이 넘을 선택하고
에디터에 stdafx.h 를 써넣습니다.

2. 그리고 프로젝트 아이템을 열어서 각각의 파일을 하나씩 선택하여 위와 같이
동일하게 모두 선택해 줍니다.

3. 마지막으로 stdafx.cpp 란 넘은 이넘들과 다르게 처리해야 합니다.
이넘이 프리 컴파일헤더 파일을 만드는데 결정적인 영향을 미치는 파일입니다.

이것은 create precompiled header file[.pch] 를 선택합니다.
그리고 에디터에 stdafx.h 라구 쓰시면 됩니다.

이것 때문에 고생한적이 한두번이 아닌데..아주 속이 시원하군여.

그럼 즐푸하세여 ^^

키워드 [Programming][VC++][Security]
http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=51&MAEULNo=20&no=5736&ref=5736

사용 환경..
Windows NT/2000: Requires Windows 2000 (or Windows NT 4.0 SP6a or later with DSClient).
Windows 95/98: Requires Windows 95/98 (with IE 4.01 or later and DSClient). Not supported on Windows Me.
Header: Declared in Adshlp.h, Iads.h
Library: Use ActiveDS.Lib, ADSIid.Lib, Adptif.Lib


코드

#include <Iads.h>
#include <Adshlp.h>

HRESULT CheckUserGroups(IADsUser *pUser)
{
    IADsMembers *pGroups;
    HRESULT hr = S_OK;
    hr = pUser->Groups(&pGroups);
    pUser->Release();
    if (FAILED(hr)) return hr;

    IUnknown *pUnk;
    hr = pGroups->get__NewEnum(&pUnk);
    if (FAILED(hr)) return hr;
    pGroups->Release();

    IEnumVARIANT *pEnum;
    hr = pUnk->QueryInterface(IID_IEnumVARIANT,(void**)&pEnum);
    if (FAILED(hr)) return hr;

    pUnk->Release();

    // Now Enumerate
    BSTR bstr;
    VARIANT var;
    IADs *pADs;
    ULONG lFetch;
    IDispatch *pDisp;

    VariantInit(&var);
    hr = pEnum->Next(1, &var, &lFetch);
    while(hr == S_OK)
    {
        if (lFetch == 1)
        {
             pDisp = V_DISPATCH(&var);
             pDisp->QueryInterface(IID_IADs, (void**)&pADs);
             pADs->get_Name(&bstr);
             printf("Group belonged: %S\n",bstr);
             SysFreeString(bstr);
             pADs->Release();
        }
        VariantClear(&var);
        pDisp=NULL;
        hr = pEnum->Next(1, &var, &lFetch);
    };
    hr = pEnum->Release();
    return S_OK;
}

IADsUser *GetUserObject(LPWSTR uPath)
{
    IADsUser *pUser;
    HRESULT hr = ADsGetObject(uPath,IID_IADsUser,(void**)&pUser);
    if (FAILED(hr)) {return NULL;}
    BSTR bstr;
    hr = pUser->get_FullName(&bstr);
    printf("User: %S\n", bstr);
    SysFreeString(bstr);
    return pUser;
}

void main()
{
    HRESULT hr = CoInitialize(NULL);
    IADsUser *pUser = (IADsUser*)GetUserObject(
                      L"WinNT://KWONJH/Rkakr,user");
    pUser->AddRef();
    hr = CheckUserGroups(pUser);
    if(pUser) pUser->Release();
    CoUninitialize();
}

예제 설명..
위이 상단 두 함수는 MSDN을 참조하여 구성한 것이고..
아래의 main 문에서 실제 정보를 추출하는데 필요한 GetUserObject()에 전달되는 인자 타입에 대하여 설명한다.

IADsUser *pUser = (IADsUser*)GetUserObject( L"WinNT://KWONJH/Rkakr,user");

WinNT://KWONJH/Rkakr,user

여기서 WinNT는 NT커널임을 이야기 한다.
JWONJH는 컴터의 이름이다... 혹은 다른 컴터의 이름이나 도메인 이름이 될 수 있다.
Rkakr 는 사용자의 유저 이름이다.

혹시나 이것을 지금 로그온 한 사람의 유저 이름으로 할려면 간단하게..
char *logname =getenv("USERNAME");
이렇게 읽어 오면 된다.
user 요건은 사용자를 말하며.. 컴터를 찾을 경우는 computer라고 입력하면 된다.

실제로 위의 정보가 맞다면..

CheckUserGroups 함수 중간에 있는 프린트 문에서..
현 정보가 주어진 사용자가 속한 그룹의 리스트가 쭈~~욱 프린트 될것이다.

테스트 환경
Windows XP SP1/ Windows 2000 SP2,  VC++6.0 SP5

위의 코드를 돌려 보니 아래와 같은 결과가 나왔습니다.

User: Rkakr
Group belonged: Administrators
Group belonged: Remote Desktop Users
Group belonged: Users


그럼 즐거운 주말 되세욤 ^^;

키워드 [Programming][VC++][Base64]
걍 라이브러리로 만들어 놓은 것 중에서.. 일부를 뽑아 소스를 올린다.



/////////////////////////////////////////////////////////////
// base64 인코딩/디코딩 및 제거
// base64.h
K4LIB_BASIC_API unsigned char* base64_encode(const unsigned char *string, int length, int *ret_length);
K4LIB_BASIC_API unsigned char* base64_decode(const unsigned char *string, int length, int *ret_length);
K4LIB_BASIC_API void base64_free(unsigned char* data);




/////////////////////////////////////////////////////////////
// base64 인코딩/디코딩 및 제거
// base64.cpp
static char base64_table[] =
{ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '\0'
};
static char base64_pad = '=';

unsigned char *base64_encode(const unsigned char *string, int length, int *ret_length)
{
    const unsigned char *current = string;
    int i    = 0;
    int    wi    =    0;
    int        nAllocSize    =    ((length + 3 - length
  % 3) * 4 / 3 + 1) * sizeof(char);
    nAllocSize    +=    (nAllocSize/80+1)*2;
    unsigned char *result = new unsigned char[nAllocSize];
 
    while (length > 2)
    { /* keep going until we have less than 24 bits */
        result[i++] = base64_table[current[0] >> 2];
        result[i++] = base64_table[((current[0] & 0x03) <<  4)
   + (current[1] >> 4)];
        result[i++] = base64_table[((current[1] & 0x0f) <<  2)
   + (current[2] >> 6)];
        result[i++] = base64_table[current[2] & 0x3f];
 
        current += 3;
        length -= 3; /* we just handle 3 octets of data */
        wi+=4;
 
/*        if(wi%80 == 0)
        {
            result[i++] = '\r';
            result[i++] = '\n';
        }
*/    }
 
    /* now deal with the tail end of things */
    if (length != 0)
    {
        result[i++] = base64_table[current[0] >> 2];
        if (length > 1)
        {
            result[i++] = base64_table[((current[0] &
    0x03) <<  4) + (current[1] >> 4)];
            result[i++] = base64_table[(current[1] &
    0x0f) <<  2];
            result[i++] = base64_pad;
        }else
        {
            result[i++] = base64_table[(current[0] &
    0x03) <<  4];
            result[i++] = base64_pad;
            result[i++] = base64_pad;
        }
    }
    if(ret_length)
    {
        *ret_length = i;
    }
    result[i] = '\0';
    return result;
}

/* as above, but backwards. :) */
unsigned char *base64_decode(const unsigned char *string, int length, int *ret_length)
{
    const unsigned char *current = string;
    int ch, i = 0, j = 0, k;
    char *chp;
 
    unsigned char *result = new unsigned char[(length / 4 *3 + 1) * sizeof(char)];
    if (result == NULL) {
        return NULL;
    }
 
    /* run through the whole string, converting as we go */
    while ((ch = *current++) != '\0') {
        if (ch == base64_pad) break;
        chp = strchr(base64_table, ch);
        if (chp == NULL) continue;
        ch = chp - base64_table;
 
        switch(i % 4) {
        case 0:
            result[j] = (unsigned char)(ch <<  2);
            break;
        case 1:
            result[j++] |= ch >> 4;
            result[j] = (unsigned char)((ch & 0x0f) <<  4);
            break;
        case 2:
            result[j++] |= ch >>2;
            result[j] = (unsigned char)((ch & 0x03) <<  6);
            break;
        case 3:
            result[j++] |= ch;
            break;
        }
        i++;
    }
 
    k = j;
    /* mop things up if we ended on a boundary */
    if (ch == base64_pad) {
        switch(i % 4) {
        case 0:
        case 1:
            delete [] result;
            return NULL;
        case 2:
            k++;
        case 3:
            result[k++] = 0;
        }
    }
    if(ret_length) {
        *ret_length = j;
    }
    result[k] = '\0';
    return result;
}

void base64_free(unsigned char* data)
{
 delete[] data;
}


키워드 [Programming][VC++][MD5]
http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=51&MAEULNo=20&no=6446&ref=6446

많이 사용되는 MD5 기법을 MFC에서 사용하기 간단한 클래스로 구현한 자료를 올립니다..
편하게 사용하세요.. 라이센스?? 던주면 감사히 받구요..
 
MD5가 머냐고 의문이 생기시는 분은 관련분야에 종사하시면 레퍼런스를 참고하시구요, 관련 분야가 아니시면, 걍 암호화의 한 부분이라고 생각하시면 됩니다.... 복잡하게 생각하면 머리 터져요 ^^;
 
간단히 헤더만 정리해 보면...
 
// MD5.h: interface for the CMD5 class.
//
//////////////////////////////////////////////////////////////////////
 
#if !defined(AFX_MD5_H__1E84B7F9_E0C0_4075_9CB1_3366A8363F48__INCLUDED_)
#define AFX_MD5_H__1E84B7F9_E0C0_4075_9CB1_3366A8363F48__INCLUDED_
 
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
 
class CMD5 
{
    typedef struct
    {
        UINT state[4];                                   /* state (ABCD) */
        UINT count[2];        /* number of bits, modulo 2^64 (lsb first) */
        BYTE buffer[64];                         /* input buffer */
    } MD5_CTX;
 
public:
    CMD5();
    virtual ~CMD5();
    CString GetString(CString str);
 
protected:
    void MD5Init(MD5_CTX* ctx);
    void MD5Update(MD5_CTX* ctx, BYTE* input, UINT inputlen);
    void MD5Final(BYTE* digest, MD5_CTX* ctx);
};
 
#endif // !defined(AFX_MD5_H__1E84B7F9_E0C0_4075_9CB1_3366A8363F48__INCLUDED_)

코드를 보시면 알겠지만.. 걍 선언해놓구.. GetString() 함수만 호출하는 간한단 구조로 되어 있습니다..
샘플 코드

CMD5 md5;
TRACE("%s\n", md5.GetString("dfsafafadffsdfsfsf"));

Output : 9632F1DC3D8E35BFF71D1D86E3E1EB9D

그럼 즐프 하세요..

+ Recent posts