소프트웨어 오디오 코덱 low-level document

1. 개요

1.1 오디오 부분의 동작

본 화상회의 애플리케이션에서 오디오 부분의 절차는 다음과 같다.

1) 오디오 출력 디바이스(Audio Output Device)를 연다.
세션(Session)에 참가하기 전에 이미 세션에 참가중인 다른 사람들의 음성 데이터를 받아 이를 디코딩하기 위해 오디오 출력 디바이스(Audio Output Device)가 열려있어야 한다.

2) 오디오 입력 디바이스(Audio Input Device)를 연다.
자신이 마이크로폰으로 말하는 음성을 인코딩하기 위한 오디오 입력 디바이스(Audio Input Device)가 열려있어야 할 것이다.

3) 세션에 참가
세션에서 음성의 송신과 수신을 위해 할당된 멀티캐스트 주소와 포트로 데이터그램(datagram) 소켓을 바인드(Bind)해 놓는다.

4) 디코딩
1-3의 초기화 과정을 마치면 그 소켓을 통해 참가한 세션에서 현재 말하고 있는 사람의 음성 데이터를 받게 되고, 이를 오디오 출력 디바이스를 통해 디코딩하여 음성을 듣게 된다.

5) 인코딩
1-3의 초기화 과정을 마친후 세션 제어에 의해 자신에게 발언권이 주어지게 되면 이제 내가 마이크로폰으로 말하는 음성이 오디오 입력 디바이스를 통해 샘플링 되고 이 음성 데이터를 위에서 말한 음성을 위한 소켓을 통해 네트워크로 전송한다.

이러한 절차들에 대해선 2절 오디오 코덱 구현에서 자세히 다루도록 한다.

1.2 오디오 데이터 형식 :

본 애플리케이션에는 사용하는 오디오 데이터 형식으로 8-bit PCM 방식을 사용하며 이 형식의 특징은 다음과 같다.

1) 초당 8000번을 샘플링
2) 각 샘플을 8bit로 나타냄
3) 이 형식을 사용하는 데이터는 0에서 255(0xFF)사이의 값을 갖게 된다.
4) 64Kbps 이상의 네트워크 대역폭(Bandwidth)을 요구 (초당 8000번을 샘플링하고, 한 샘플을 한 byte로 나타내므로 초당 8kbyte의 오디오 데이터가 생성된다고 할 수 있다. 따라서 초당 8kbyte, 즉 64kbit를 전송해야 하므로 헤더 부분을 고려하 면 64Kbps 이상의 네트워크 대역폭(Bandwidth)을 사용한다고 할 수 있다.)

1.3 오디오 데이터 교환 방식

본 애플리케이션에는 세션의 참가자의 수에 따라 오디오 데이터의 교환 방식이 full-duplex 방식에서 half-duplex 방식으로, 또는 역으로 전환된다.

1) Full-duplex 방식 : 2명만이 세션에 있게 될 때는 서로의 음성을 full-duplex방식으로 서로 주고받을 수 있다.
2) Half-duplex 방식 : 세션에 3명 이상이 있게 될 때는 세션 제어에 의해 한 사람에게만 발언권이 주어지는 Half-duplex 방식으로 전환된다.

1.4 오디오 서비스를 제공하는 window 95의 멀티미디어 API

Windows 95는 본 화상회의 애플리케이션에서 다루어야 하는 파형 오디오(Waveform Audio)를 사용하기 위한 여러 다양한 기능들을 포함한 멀티미디어와 관련된 기능들을 멀티미디어 API로 제공한다. Windows 95의 멀티미디어 API에서는 오디오 서비스의 여러 가지 타입과 레벨들을 제공한다. 오디오 서비스의 다른 타입들은 각기 다른 포맷과 다른 기술을 필요로 하는데, 제공하는 오디오 서비스의 타입들에는 파형(Waveform) 오디오 서비스, MIDI 오디오 서비스, 컴팩트 디스크 오디오 서비스가 있다. 본 화상회의 애플리케이션에서 다루는 파형 오디오 서비스는 디지털 오디오 하드웨어를 위한 디코딩과 인코딩을 지원한다. 오디오 서비스의 레벨에는 하이-레벨과 로우-레벨이 있다. 하이-레벨 오디오 서비스는 프로그래밍하기가 편하다는 장점이 있고, 로우-레벨 오디오 서비스는 오디오 디바이스 드라이버를 직접 억세스 하므로 복잡한 프로그래밍을 요구하지만 오디오 디코딩과 인코딩에 대해 미세한 제어까지 할 수 있는 장점이 있다. 오디오 서비스를 제공하는 window 95의 멀티미디어 API를 이용하는 애플리케이션의 구조는 <그림 2-1>과 같다.

 

2. 오디오 코덱 구현

2.1 구현 환경과 요구 사항

Windows 95 상에서 Visual C++ 4.0과 MFC, 그리고 로우-레벨(Low Level) 오디오 API를 이용하여 구현하였으며 팬트엄 166 이상의 프로세서를 가진 PC에서만 테스트해보았다. 요구 사항으로는 8-bit PCM 샘플링과 full-duplex를 지원하는 사운드 카드를 요구한다.

2.2 Low-Level 오디오 API를 이용하여 오디오를 인코딩/디코딩하는 절차

로우-레벨(Low Level) 오디오 API는 애플리케이션으로 하여금 직접 오디오 디바이스 드라이버와 통하게 함으로써 로우-레벨 오디오 서비스를 제공한다. 로우-레벨(Low Level) 오디오 API를 이용하여 파형 오디오(Waveform Audio)를 인코딩/디코딩하기 위한 절차를 간단히 기술하면 다음과 같다.

1) 원하는 오디오 데이터 형식이 사용가능한지를 아닌지를 검사한다.
2) 사용이 가능하다면 원하는 오디오 입출력 디바이스(Audio Input/Output Device)를 연다.
3) 디바이스로부터 파형 오디오(Waveform Audio) 샘플 데이터를 넘겨주고 받기 위해서 하나 이상의 데이터 버퍼 블록을 할당(Allocation)한다. 할당한 데이터 버퍼 블록은 처리를 기다리는 디바이스 큐(queue)로 보내져야 한다.
4) 디바이스가 데이터 버퍼 블록을 처리하면, 블록은 다른 처리(디코딩, 또는 전송) 또는 재사용을 위해서 애플리케이션에게 리턴 된다.

2.3 구현 내용

가. 초기화

1) 원하는 오디오 데이터 형식이 사용가능한지를 테스트

본 애플리케이션에서 사용하는 오디오 데이터 형식인 8-bit PCM 방식이 audio device를 통해 사용가능한지를 waveInOpen, waveOutOpen에 다음과 같은 parameter들로 호출하여 리턴되는 결과 값으로 알아낸다. (waveInOpen, waveOutOpen 대한 자세한 설명은 Visual C++의 Help를 참조) 관련된 코드는 다음과 같다.

< decl.h >

#define BLKS_PER_READ 4
#define READ_AHEAD 8
#define BLKS_PER_WRITE 4
#define WRITE_AHEAD 4

// 8-bit PCM format을 나타내는 WAVEFORMATEX 구조체
static const WAVEFORMATEX lin8fmt = {

    WAVE_FORMAT_PCM,
    1, // 1 is mono, 2 is streo
    8000,
    8000,
    1,
    8,
    0
};

< audioview.cpp의 audioview() 함수안에 있는 부분 >

int sts;

// 먼저 input audio device에 대해 알아본다.
sts = waveInOpen(0, WAVE_MAPPER, &lin8fmt, 0, 0, WAVE_FORMAT_QUERY);

if ( sts ) // 지원되지 않음을 알린다.

    AfxMessageBox("not support 8bit 8kHz PCM audio input");
else { // 지원되면 audio input device에서 사용되어질 버퍼를 new를 써 // 서 Heap memory에 할당한다.
    iformat_ = &lin8fmt; // input format을 8-bit PCM으로 지정
    iblen_ = len;
    len *= READ_AHEAD;
    ibufStart_ = new u_char[len]; // input buffer start를 지정
    ibufEnd_ = ibufStart_ + len; // input buffer end를 지정
    tmp = new u_char[len];
}

// 다음 output audio device에 대해 알아본다.
sts = waveOutOpen(0, WAVE_MAPPER, &lin8fmt, 0, 0, WAVE_FORMAT_QUERY);

if ( sts ) // 지원되지 않음을 알린다.

    AfxMessageBox("not support 8bit 8kHz PCM audio output");
else { // 지원되면 audio output device에서 사용되어질 버퍼를 new를 써 // 서 Heap memory에 할당한다.
    oformat_ = &lin8fmt; // output format을 8-bit PCM으로 지정
    len = blksize * BLKS_PER_WRITE;
    oblen_ = len;
    len *= WRITE_AHEAD;
    obufStart_ = new u_char[len]; // output buffer start를 지정
    obufEnd_ = obufStart_ + len; // output buffer end를 지정
}

2) 파형 오디오 입출력 디바이스 열기

오디오 디바이스를 여는 함수(waveInOpen, waveOutOpen)들은 디바이스 식별자, 메모리 위치에 대한 포인터, 각 디바이스 타입에 독특한 파라미터들을 지정한다. 지정된 메모리 위치에는 디바이스 핸들 값이 들어가게 된다. 다른 로우-레벨 오디오 API들(waveInStart, waveInStop, waveOutWrite 등)을 호출할 때 열려진 오디오 디바이스를 식별하기 위해서 이 디바이스 핸들을 사용하여야 한다. ( 자세한 설명은 Visual C++의 Help를 참조)

디코딩을 위해서는 waveOutOpen함수를 사용하여 파형 오디오 출력 디바이스를 열고, 인코딩을 위해서는 waveInOpen함수를 사용하여 파형 오디오 입력 디바이스를 연다. 이 함수들은 파라미터로 주어지는 디바이스 식별자와 관계된 디바이스를 열고 그 디바이스에 대한 핸들을 파라미터로 지정된 메모리 위치에 써놓음으로써 리턴 한다.

관련된 코드는 다음과 같다. 파형 오디오 입력 디바이스를 여는 부분은 CAudioView::OpenIn() 함수에 있으며 파형 오디오 출력 디바이스를 여는 부분은 CAudioView::OpenOut() 함수에 있다.

// audio input device를 8-bit PCM format으로 open
void CAudioView::OpenIn()
{

    int error; // waveInOpen()의 return 값을 저장

    if (in_ == 0) // in_ : decl.h안에 HWAVEIN in_로 선언되어 있다.

      error = waveInOpen(&in_, WAVE_MAPPER, iformat_, (DWORD)(VOID*)waveInProc, (long)GetSafeHwnd(), CALLBACK_FUNCTION);
    // error 가 났으면 어떤 error인지를 알아낸다.
    if ( error == MMSYSERR_ALLOCATED)
      AfxMessageBox("Specified resource is already allocated.");
    else if ( error == MMSYSERR_BADDEVICEID)
      AfxMessageBox("Specified device identifier is out of range.");
    else if ( error == MMSYSERR_NODRIVER)
      AfxMessageBox("No device driver is present.");
    else if ( error == MMSYSERR_NOMEM)
      AfxMessageBox("Unable to allocate or lock memory.");
    else if ( error == WAVERR_BADFORMAT)
      AfxMessageBox("Attempted to open with an unsupported waveform-audio format.");
    ........................................
    // 오디오 입력 장치를 여는데 성공한 후에는 오디오 입력 장치를 통해 인코딩 될
    // 데이터가 저장될 버퍼를 ( 지원한지를 검사한 후 위에서 미리 할당된)
    // waveInPrepareHeader를 사용하여 파형 오디오 입력 디바이스가 사용 할 수 있
    // 게끔 준비하고 waveInAddBuffer를 이용해 버퍼를 디바이스 드라이버에 보낸다.
    // waveInStart로 인코딩을 시작하기 전에는 반드시 위와 같은 방식대로 드라이버에
    // 버퍼를 보내야 한다. 그렇지 않으면 데이터를 잃어버리게 된다.
    // 위의 일을 하는 코드가 이 부분에 위치하며 이는 뒤의 파형 오디오 데이터 인코
    // 딩 부분에서 설명된다.
    ........................................
    return;
}

// audio output device를 8-bit PCM format으로 open
void CAudioView::OpenOut()
{

    int error = 0; // waveOutOpen()의 return 값을 저장

    if (out_ == 0) // in_ : decl.h안에 HWAVEIN in_로 선언되어 있다.

      error = waveOutOpen(&out_, WAVE_MAPPER, iformat_,(DWORD)(VOID*)waveInProc, (long)GetSafeHwnd(),CALLBACK_FUNCTION);
    ........................................

    // waveOutWrite함수에 보낼 파형 오디오 데이터 블록을 waveOutPrepareHeader함
    // 수를 사용해 준비한다. 이러한 일과 관계된 코드가 이 부분에 위치하며 이는 뒤
    // 의 파형 오디오 데이터 디코딩 부분에서 설명된다.
    ........................................
    return ;

}

3) 파형 오디오 입출력 데이터 타입

파형 오디오 입출력 함수들을 위해서 Windows 95의 멀티미디어 API에서 정의한 파형 오디오 데이터 타입들 중에서 본 애플리케이션에서 이용한 것들은 <표 2-1>과 같다. (자세한 사항은 VIsual C++의 Help를 참고)

<표 2- 1> 본 애플리케이션 구현에서 사용한 파형 오디오 데이터 타입
타입
설명
HWAVEOUT
열려진 파형 오디오 출력 디바이스에 대한 핸들
HWAVEIN
열려진 파형 오디오 입력 디바이스에 대한 핸들
WAVEHDR
파형 오디오 입력 또는 출력 데이터 블록에 대한 헤더로 쓰이는 구조체
WAVEFORMATEX
특정한 파형 오디오 입력 또는 출력 장치에 의해 지원되는 데이터 포맷을 명시하는 구조체
 

본 애플리케이션의 구현에서 사용되는 파형 오디오 데이터 타입들로 선언된 변수들의 정의에 관련된 코드는 다음과 같으며 decl.h에 정의되어 있다.

< decl.h >
const WAVEFORMATEX* iformat_; // input audio format
const WAVEFORMATEX* oformat_; // output audio format
HWAVEOUT out_; // 오디오 출력 장치에 대한 핸들
HWAVEIN in_; // 오디오 입력 장치에 대한 핸들
WAVEHDR iwhdr_[READ_AHEAD];
// 오디오 입력 데이터 블록에 대한 헤더에 대한 정의
WAVEHDR owhdr_[BLKS_PER_WRITE * WRITE_AHEAD];
// 오디오 출력 데이터 블록에 대한 헤더에 대한 정의

4) 파형 오디오 데이터 포맷 지정

waveOutOpen 또는 waveInOpen을 사용해 오디오 입출력 디바이스를 열 때 사용할 파형 오디오 데이터 포맷을 담은 WAVEFORMATEX 구조체에 대한 포인터를 파라미터로 전달한다. WAVEFORMATEX 구조체의 정의는 <표 2-2>와 같다. (자세한 사항은 VIsual C++의 Help를 참고)

<표 2- 2> WAVEFORMATEX 구조체
멤버 변수
설명
wFormatTag
파형 오디오 형식. PCM이면 WAVE_FORMAT_PCM
nChannels
파형 오디오 데이터의 채널의 개수. 1은 모노, 2는 스테레오를 의미한다.
nSamplesPerSec
샘플링율(Sampling rate). 파형 오디오 형식이 PCM이면 이 값은 8.0kHz, 11.025kHz, 22.05kHz, 44.1kHz 중의 하나여야 한다
nAvgBytesPerSec
요구되는 average data-transfer rate. 파형 오디오 형식이 PCM이면 이 값은 샘플링율과 block alignment의 곱과 같아야 한다.
nBlockAlign
block alignment. 파형 오디오 형식이 PCM이면 채널의 개수와 샘플당 비트 수를 8(bits per byte)로 나눈 값의 곱과 같아야 한다.
wBitsPerSample
Bits per sample. 파형 오디오 형식이 PCM이면 이 값은 8(모노 일 때) 또는 16(스테레오 일 때)이어야 한다.
cbSize
WAVEFORMATEX 구조체의 끝에 덧붙여질 추가 형식 정보의 크기
본 화상회의 애플리케이션에서는 음성의 샘플링(Sampling) 방식으로 PCM을 사용하였고, 초당 8000번을 샘플링하고, 각 샘플을 8비트로 나타내는 8-bit PCM 방식의 파형 오디오 데이터 형식을 사용하므로 본 애플리케이션에서 WAVEFORMATEX 구조체의 멤버 변수의 값은 <표 2-3>과 같다.
<표 2- 3> 본 애플리케이션에서 WAVEFORMATEX 구조체의 멤버 변수의 값
멤버 변수
사용한 값
wFormatTag
WAVE_FORMAT_PCM
nChannels
1(모노)
SamplesPerSec
8000(8kHz의 샘플링)
nAvgBytesPerSec
8000
nBlockAlign
1
wBitsPerSample
8(한 샘플을 8bit로 표현)
cbSize
0(추가 정보 없음)
 

나. 파형 오디오 데이터 인코딩과 디코딩

1) 파형 오디오 데이터 디코딩

파형 오디오 출력 디바이스를 열었으면 이제 waveOutWrite함수를 사용하여 음성 데이터 블록을 오디오 출력 디바이스로 보내면 오디오 출력 디바이스는 이를 디코딩한다. waveOutWrite함수에 보낼 파형 오디오 데이터 블록을 지정하기 위해서는 WAVEHDR 구조체를 사용한다. 이 구조체는 데이터 블록에 대한 포인터와 데이터 블록의 크기와 몇 가지의 플래그를 포함한다. ( 자세한 설명은 Visual C++의 Help를 참조) 이 데이터 블록은 사용 전에 파형 오디오 출력 디바이스가 사용 할 수 있게끔 waveOutPrepareHeader함수를 사용해 준비되어져야 한다.

waveOutPrepareHeader함수를 사용하여 미리 할당해 둔 데이터 블록을 오디오 출력 장치가 사용할 수 있도록 준비하는 코드는 아래와 같으며 이 부분은 CAudioView::OpenOut() 함수 안에 위치하며 오디오 출력 장치를 성공적으로 연 경우에만 수행된다.

// 파형 오디오 출력 디바이스를 열었으면 이제 waveOutWrite함수를 사용하여
// 음성 데이터 블록을 오디오 출력 디바이스로 보내면 오디오 출력 디바이스는
// 이를 디코딩한다. waveOutWrite함수에 보낼 파형 오디오 데이터
// 블록을 지정하기 위해서는 WAVEHDR 구조체를 사용한다. 이 구조체는
// 데이터 블록에 대한 포인터와 데이터 블록의 크기와 몇 가지의 플래그를 포
// 함한다. 이 데이터 블록은 사용 전에 파형 오디오 출력 디바이스가 사용 할
// 수 있게끔 waveOutPrepareHeader함수를 사용해 준비되어져야 한다.

if ( error == MMSYSERR_NOERROR ) {

    // waveOutOpen success
    /* (re-)initialize the output buffer descriptors */
    memset(owhdr_, 0, sizeof(owhdr_));
    u_char* bp = obufStart_;
    obuf_ = bp;
    u_int len = oblen_;
    int i;

    for (i = 0; i < WRITE_AHEAD; ++i) {

      WAVEHDR* whp = &owhdr_[(i + 1) * BLKS_PER_WRITE - 1];
      whp->dwFlags = 0;
      whp->dwBufferLength = oblen_;
      whp->lpData = (char*)bp;
      waveOutPrepareHeader(out_, whp, sizeof(*whp));
      whp->dwFlags |= WHDR_DONE;
      bp += len;
    }
}

데이터 블록을 waveOutWrite함수를 사용해 오디오 출력 디바이스에 보낸 후, 디바이스 드라이버가 그 데이터 블록에 대한 처리를 끝내고 나면 이 데이터 블록을 해제시킬 수 있다. WAVEHDR 구조의 멤버 변수인 lpData는 파형 오디오 데이터 샘플들에 대한 포인터이다.

본 애플리케이션의 구현에서는 오디오 데이터 블록의 디코딩은 세션에 참가 할 때 음성을 위해 바인드해놓은 소켓으로 데이터를 받을 때마다 수행한다. 더 자세한 설명은 뒤의 오디오 데이터의 전송 부분에서 다룬다. 디코딩을 마친 데이터 블록을 특별히 해제시키지 않고 이후의 받은 데이터에 의해 덮어 쓰여지도록 하였다. 좀 더 자세한 설명은 파형 오디오 데이터의 수신에서 언급한다. 오디오 데이터 블록의 디코딩에 해당하는 부분은 소켓으로 데이터를 받을 때마다 호출되는 ProcessPendingRead()에 있으며 다음과 같다.

void CAudioView::ProcessPendingRead()
{
WAVEHDR* cp = &owhdr_[(i + 1) * BLKS_PER_WRITE - 1];
// 현재 네트웍으로부터 받은 오디오 데이터 블록을 waveOutWrite함수를 사용
// 하여 디코딩하기 위해서는 WAVEHDR 구조체를 사용하여 그 오디오 데이터
// 블록을 지정해서 waveOutWrite함수의 파라미터로 사용해야 하므로 여기서
// OpenIn()에서 waveOutPrepareHeader함수를 사용해 오디오 출력 장치가 사
// 용할 수 있도록 준비해 둔 WAVEHDR 구조체 타입의 변수 array인 owhdr중
// 의 하나를 지정한다.
 

    i = ( i + 1 ) % WRITE_AHEAD ;
    // 다음 오디오 데어터 블록을 위해서는 owhdr array의 index를 하나 증가한다.

    int nBytes = m_pSocket->ReceiveFrom(Revpkt, PDU_SIZE, (CString&)m_strRevIP, (UINT&) m_Revport);

    if ( nBytes == -1 ) {
    // error를 처리하는 루틴
    }

    // 현재 받은 packet의 id 필드가 현재 발언권을 얻은 사람의 id와 같은지를
    // 검사한다. 또한 자신의 id와 같은지를 검사한다. 발언권을 얻지 않은 사람의
    // packet이거나 자신이 보낸 packet의 경우에는 디코딩을 하지 않는다.

    if ( (strcmp(Revpkt->id , m_CurrentSayingID ) != 0) || ( strcmp(Revpkt->id , m_ID) == 0) )
    return;

    // packet의 구조체의 정의는 decl.h에 다음과 같이 정의되어 있다.
    // typedef struct {
    // char id[9];
    // u_char data[8192];
    // } Packet;

    // 그러므로 순수한 오디오 데이터의 size는 packet size에서 id의 size 9를
    // 뺀 값이므로 이 값을 오디어 데이터 블록을 지정하는 WAVEHDR의 변수인
    // cp의 dwBufferLength에 넣는다.
    cp->dwBufferLength = nBytes - 9;

    // packet의 data를 오디어 데이터 블록을 지정하는 WAVEHDR의 변수인 cp의
    // lpData에 copy한다.
    memcpy(cp->lpData ,Revpkt->data ,cp->dwBufferLength);
    // ---> data copying problem : protocol overhead

    cp->dwFlags = WHDR_DONE ;
    // 네트웍으로부터 받은 packet의 오디오 데이터를 위와 같이 WAVEHDR의 변
    // 수인 cp로 변환한 후 waveOutWrite를 사용해 디코딩을 한다.

    waveOutWrite(out_, cp, sizeof(*cp));

}

2) 파형 오디오 디코딩을 관리하기 위한 Windows Message의 사용

파형 오디오 디코딩을 관리하도록 window procedure 함수 또는 애플리케이션에 의해 제공되는 파형 오디오 출력 장치에 대한 콜백 함수에는 <표 2-4>에서와 같은 메시지들이 올 수 있다. (괄호 안은 콜백 함수에게 전달되는 메시지임.)

<표 2- 4> 파형 오디오 디코딩 관리를 위한 Window Message들
message
설명
MM_WOM_CLOSE
(WOM_CLOSE)
waveOutClose함수를 사용하여 디바이스를 닫았을 때
MM_WOM_DONW
(WOM_DONE)
디바이스 드라이버가 waveOutWrite함수를 사용하여 보내진 데이터 블록에 대한 처리를 마쳤을 때
MM_WOM_OPEN
(WOM_OPEN)
waveOutOpen함수를 사용하여 디바이스를 열었을 때
이 메시지들에 대한 wParam은 항상 열려진 파형 오디오 디바이스에 대한 핸들 값이다. MM_WOM_DONE(WOM_DONE)의 경우에는 이 메시지의 파라미터로 전달받는 lParam의 값은 디코딩이 끝난 데이터 블록에 대한 WAVEHDR 구조체에 대한 포인터 값이다. 이를 가지고 디코딩이 끝난 데이터 블록을 해제(free)시킬 수 있다.

본 구현에서는 파형 오디오의 디코딩 관리를 특별히 하지 않고 디코딩이 끝난 데이터 블록은 이후의 소켓을 통해 받은 데이터로 overwrite되도록 하였다.

3) 파형 오디오 인코딩

파형 오디오 입력 디바이스를 연후에는 파형 오디오 데이터를 인코딩 할 수 있다. 파형 오디오 데이터는 애플리케이션에서 WAVEHDR 구조체로 지정해 놓은 버퍼에 인코딩 되어진다. 이 데이터 블록들은 미리 waveInPrepareHeader를 사용하여 파형 오디오 입력 디바이스가 사용 할 수 있게끔 준비되어져 있어야 한다.

멀티미디어 API에서 파형 오디오 녹음(waveform-audio recording)을 처리하기 위해 제공하는 함수들은 <표 2-5>와 같다.

<표 2- 5> 파형 오디오 인코딩을 처리하기 위해 제공하는 함수들
함수
설명
waveInAddBuffer
디바이스 드라이버에 버퍼를 보낸다. 그러면 이 버퍼에는 디바이스 드라이버에 의해 인코딩된 파형 오디오 데이터가 채워질 수 있게 된다.
waveInStart
파형 오디오 인코딩을 시작한다.
waveInStop
파형 오디오 인코딩을 멈춘다.
waveInAddBuffer 를 통해 디바이스 드라이버에 보내진 버퍼가 인코딩된 파형 오디오 데이터로 채워지면 애플리케이션은 콜백 메시지를 받아서 이를 알게 된다. waveInStart로 인코딩을 시작하기 전에는 반드시 드라이버에 버퍼를 보내야 한다. 그렇지 않으면 데이터를 잃어버리게 된다.

waveInPrepareHeader함수를 사용하여 미리 할당해 둔 데이터 블록을 오디오 출력 장치가 사용할 수 있도록 준비하는 코드와 waveInAddBuffer를 사용해 버퍼를 디바이스 드라이버에 보내는 코드는 아래와 같으며 이 부분은 CAudioView::OpenIn() 함수 안에 위치하며 오디오 입력 장치를 성공적으로 연 경우에만 수행된다.

// waveform audio data는 애플리케이션에서 WAVEHDR 구조체로 지정해 놓은
// 버퍼에 인코딩 되어진다. 이 데이터 블록들은 미리 waveInPrepareHeader를
// 사용하여 파형 오디오 입력 디바이스가 사용 할 수 있게끔 준비되어져 있어
// 야 한다. 다음은 waveInAddBuffer를 이용해 버퍼를 디바이스 드라이버에 버
// 낸다. waveInStart로 인코딩을 시작하기 전에는 반드시 위와 같은 방식대로
// 드라이버에 버퍼를 보내야 한다. 그렇지 않으면 데이터를 잃어버리게 된다.

/* (re-)initialize the input buffer descriptors */
memset(iwhdr_, 0, sizeof(iwhdr_));
// iwhdr_ : decl.h안에 WAVEHDR iwhdr_[READ_AHEAD]로 선언된어 있다.
ibindx_ = 0;
rbuf_ = rbufEnd_;
u_char* bp = ibufStart_;
u_int len = iblen_;
memset(bp, 0, len * READ_AHEAD);

// 사용되는 버퍼를 모두 초기화한다.
for (int i = 0; i < READ_AHEAD; ++i) {

    WAVEHDR* whp = &iwhdr_[i];
    whp->dwFlags = 0;
    whp->dwBufferLength = len;
    whp->lpData = (char*)bp;
    bp += len;
    waveInPrepareHeader(in_, whp, sizeof(*whp));
    if(MMSYSERR_NOERROR!=waveInAddBuffer(in_,whp,sizeof(*whp))) {
      AfxMessageBox("waveInAddBuffer error");
      return ;
    }
} // end of for loop

4) 파형 오디오 인코딩을 관리하기 위한 Windows Message의 사용

파형 오디오 인코딩을 관리하도록 window procedure 함수 또는 애플리케이션에 의해 제공되는 파형 오디오 출력 장치에 대한 콜백 함수에는 <표 2-4>에서와 같은 메시지들이 올 수 있다. (괄호 안은 콜백 함수에게 전달되는 메시지임. 자세한 사항은 Visual C++의 Help를 참조)

<표 2- 6> 파형 오디오 인코딩 관리를 위한 Window Message들
message
설명
MM_WIM_CLOSE
(WIM_CLOSE)
waveInClose함수를 사용하여 디바이스를 닫았을 때
MM_WIM_DATA
(WIM_DATA)
디바이스 드라이버가 waveInAddBuffer함수를 사용하여 보내어진 데이터 블록을 인코딩된 오디오 데이터로 채웠을 때
MM_WIM_OPEN
(WIM_OPEN)
waveInOpen함수를 사용하여 디바이스를 열었을 때
MM_WIM_DATA(WIM_DATA) 의 파라미터로 전달되는 lParam은 버퍼를 식별하는 WAVEHDR 구조체에 대한 포인터의 값을 가진다. 이 버퍼는 파형 오디오 데이터로 완전히 채워지지 않았을 수도 있다. 버퍼가 채워지기 전에 인코딩이 정지될 수도 있기 때문이다. 따라서 버퍼의 유용한 데이터의 양을 알아내기 위해 WAVEHDR 구조체의 멤버 변수인 dwBytesRecorded를 사용한다. lParam을 가지고 애플리케이션이 그 데이터 블록에 대한 사용(본 화상회의 애플리케이션의 경우 네트워크로 전송)을 끝마쳤을 때 그 데이터 블록을 해제할 수 있다.

본 애플리케이션의 구현에서 오디오 인코딩 관리를 위한 코드는 VOID CALLBACK waveInProc()에 있으며 다음과 같다.

VOID CALLBACK waveInProc(HWAVEIN hwi, UINT uMsg, long dwInstance, DWORD dwParam1, DWORD dwParam2 )
{

    switch (uMsg)
    {
      case WIM_DATA:
      // 디바이스 드라이버가 waveInAddBuffer함수를 사용하여 보내어진 데
      // 이터 블록을 인코딩된 오디오 데이터로 채웠을 때
      {
        // MM_WIM_DATA(WIM_DATA)의 파라미터로 전달되는 lParam은 버퍼
        // 를 식별하는 WAVEHDR 구조체에 대한 포인터의 값을 가진다.
        WAVEHDR *whp = (LPWAVEHDR)dwParam1;
        WAVEHDR* cp = &tmphdr_;

        // 이미 선언해 놓은 WAVEHDR 구조체에 대한 포인터인 tmphdr_로
        // 인코딩된 오디오 데이터 블록에 대한 WAVEHDR을 가리키는
        // dwParam1 ( WAVEHDR *whp = (LPWAVEHDR)dwParam1 ) 의 값
        // 들을 copy한다.
        cp->dwFlags = whp->dwFlags;
        cp->dwBufferLength = whp->dwBufferLength ;
        dwParam1 = (DWORD) cp;

        memcpy(cp->lpData,whp->lpData , cp->dwBufferLength );
        // copy가 끝난 WAVEHDR의 오디오 데이터 블록을 null로 만든다.
        memset(whp->lpData, 0, whp->dwBufferLength);
        // MY_WIM_DATA 메시지를 발생시킨다. MY_WIM_DATA 메시지를 처
        // 리하는 루틴에서는 역시 파라미터로 오는 WAVEHDR의 오디오 데이
        // 터 블록 부분을 네트웍으로 전송한다.

        if ( PostMessage ((HWND) dwInstance , MY_WIM_DATA ,0 , dwParam1 ) == FALSE)

          AfxMessageBox("PostMsg error");
        // 사용이 끝난 WAVEHDR을 다시 waveInPrepareHeader을 사용해 오
        // 디오 입력 장치가 사용할 수 있도록 준비한다.
        waveInPrepareHeader(hwi, whp, sizeof(*whp));

        // 다음 waveInAddBuffer를 사용해 디바이스 드라이버에 해당 버퍼를
        // 보낸다.
        if(MMSYSERR_NOERROR!=waveInAddBuffer(hwi,whp,sizeof(*whp))) {

          AfxMessageBox("waveInAddBuffer error");
          return ;
        }
        break;
      }
    } // end of switch
}

다. 파형 오디오 데이터의 전송과 수신

1) 파형 오디오 데이터 블록의 크기

본 화상회의 애플리케이션에서는 WAVEHDR의 멤버 변수인 lpData가 가리키는 데이터 블록의 크기를 8Kbyte로 하였다. 본 화상회의 애플리케이션에서는 음성의 인코딩 방식으로 PCM을 사용하므로 1초당 8000번을 샘플링하고, 한 샘플을 1byte로 나타낸다. 따라서 한 데이터 블록의 크기를 8Kbyte로 하였으므로 한 데이터 블록은 1초 동안의 음성 데이터를 나타낸다. 또한 한 데이터 블록의 크기를 8kbyte이므로 애플리케이션은 데이터 블록에 오디오 데이터를 채웠다는 MM_WIM_DATA(WIM_DATA) 메시지를 운영 체제로부터 1초에 한번씩 받게 된다.

본 애플리케이션의 구현에서는 MM_WIM_DATA(WIM_DATA) 메시지를 처리하는 루틴에서 음성 데이터 블록을 음성의 전송을 위해 만들어둔 소켓을 통해 네트워크로 내보낸다. 애플리케이션은 1초마다 한번씩 MM_WIM_DATA(WIM_DATA) 메시지를 받을 것이고, 이때 8Kbyte의 음성 데이터를 전송하므로 1초의 네트워크 지연이 추가되어진다고 볼 수 있다. 물론 데이터 블록의 크기를 1Kbyte로 조정하면 추가되는 네트워크 지연을 1초에서 0.125초로 줄일 수 있지만, 테스트 해본 결과 이때는 너무 잦은 MM_WIM_DATA(WIM_DATA)의 처리에 대한 오버헤드와 받는 쪽에서도 음성 전송을 위한 소켓을 통해 데이터가 왔음을 알리는 window message의 잦은 처리에 대한 오버헤드로 시스템이 부하를 견디지 못하고 다운되는 현상이 종종 있었다. 이를 해결하고 시스템을 안정적으로 동작하게 만들기 위해서 데이터 블록의 크기를 8Kbyte로 정하여 사용하였다. 또한, 초당 8Kbyte, 즉 64kbit를 전송해야 하므로 헤더 부분을 고려하면 64Kbps 이상의 네트워크 대역폭을 사용한다고 할 수 있다

2) 파형 오디오 데이터의 전송

본 애플리케이션에서는 세션 제어에 의해서 자신이 발언권을 얻으면 CAudioView::TriggerPlay()를 호출함으로써 파형 오디오 데이터를 인코딩하기 시작한다. 발언권이 세션의 다른 참가자에게 주어지면 CAudioView::TriggerStop()를 호출함으로써 파형 오디오 데이터의 인코딩을 중단한다. 관련된 코드는 다음과 같다.

void CAudioView::TriggerPlay()
{

    // PlayFlag는 현재 인코딩 중이면 TRUE, 아니면 FALSE로 setting한다.
    if ( PlayFlag == FALSE ) {
      waveInStart(in_);
      PlayFlag = TRUE;
      .......
    }
}

void CAudioView::TriggerStop()
{

    if ( PlayFlag == TRUE ) {
      waveInStop(in_);
      PlayFlag = FALSE;
      .......
    }
}

4) 파형 오디오 인코딩을 관리하기 위한 Windows Message의 사용에서 설명한데로 한 데이터 블록에 대한 처리가 끝났음을 애플리케이션에게 알리는 MM_WIM_DATA(WIM_DATA)를 받으면 애플리케이션에서 MY_WIM_DATA라고 정의해 놓은 메시지를 포스트하고 다시 이 메시지를 애플리케이션이 받으면 MY_WIM_DATA를 처리하는 프로시저로 메시지 맵핑(Message Mapping) 해놓은 OnWimData가 수행된다. OnWimData에서는 파라미터로 전달받은 lParam이 가리키는 WAVEHDR 구조체의 멤버 변수인 lpData가 가리키는 파형 오디오 데이터 블록과 다른 오디오 스트림과 구별되기 위한 식별자를 포함한 패킷을 구성하고 이를 음성 전송과 수신을 위한 소켓을 통해 네트워크로 보낸다. <그림 2-2>

패킷 구조체의 정의는 다음과 같으며 decl.h에 선언되어 있다.

typedef struct {

    char id[9];
    u_char data[8192];//2048];
} Packet;

음성 데이터의 전송과 관련된 코드는 CAudioView::OnWimData() 함수안에 있으며 다음과 같다.

long CAudioView::OnWimData(UINT wParam , LONG lParam)
{

    // 파라미터로 전달되는 lParam은 버퍼를 식별하는
    // WAVEHDR 구조체에 대한 포인터의 값을 가진다.
    WAVEHDR *whp = (LPWAVEHDR)lParam;

    struct sockaddr_in my_addr;
    my_addr.sin_family = PF_INET;
    my_addr.sin_port = htons(m_port);
    my_addr.sin_addr.s_addr = inet_addr(m_strPeerIP);

    // packet에 자신의 id를 집어 넣는다.
    strncpy ( Sndpkt->id , m_ID , 9 );

    // packet의 data 필드에 오디오 데이터 블록을 copy한다.
    memcpy(Sndpkt->data , whp->lpData, whp->dwBufferLength);

    // 사용이 끝난 WAVEHDR 구조체의 lpData를 null로 만든다.
    memset(whp->lpData, 0, whp->dwBufferLength);

    // packet을 전송한다.
    m_pSocket->SendTo(Sndpkt, PDU_SIZE, (LPSOCKADDR)&my_addr, sizeof(my_addr));

    return 0L;

}

3) 파형 오디오 데이터의 수신

음성 전송과 수신을 위한 소켓을 통해서 데이터를 받으면 일단 패킷 중에서 식별자 필드를 보고 이 패킷이 세션 제어에 의해서 발언권을 얻은 사람의 음성 데이터인지 아닌지를 판단한다. 판단한 결과 발언권을 얻은 사람의 것이면 이 데이터를 이미 선언해 놓은 WAVEHDR의 lpData로 복사하고 WAVEHDR의 다른 멤버 변수들의 값을 적절히 세팅한 후, waveOutWrite의 파라미터로 이 WAVEHDR을 넘겨주고 호출하면 받은 음성 데이터가 디코딩 되게된다. <그림 2-2>

해당하는 부분의 코드는 소켓으로 데이터를 받을 때마다 호출되는 ProcessPendingRead()에 있으며 이는 1) 파형 오디오 데이터 디코딩 부분에 함께 나와 있다.

Posted by 나비:D
:
CString 에서 Char* (배열)

UDP 소켓 통신하면서

CString으로 받은 값을 Char* 로 센드 시켰을때

길이는 맞게 오는데 자꾸 한글자만 나와 ㅠ.ㅠ

구글링 네이뇬 검색 하면 아래 와 비슷한 내용들 많이 나오는데...
방법은
1. (LPSTR)(LPCTSTR)로 강제 형변환
2. CString str;
   str.GetBuffer(str.GetLength());
   해주시면 char *을 리턴합니다.
ps. 위 두가지 방법중에 2번을 추천합니다.
      그리고 GetBuffer를 사용하시면 ReleaseBuffer()를 사용해서 해제해 주셔야합니다.

CString msg = "abcdefg";
char* tempchar;

tempchar = LPSTR(LPCTSTR(msg));
머 요런식으로 해서

strlen(tempchar) === 1
msg.getLength === 6

머냐고요~~~

strcpy
memcpy 다 1글자씩 밖에 안드감 ㅠ.ㅠ


다시 구글링


char Buffer[255];
CString szString;
size_t CharactersConverted = 0;

wcstombs_s(&CharactersConverted, Buffer, szString.GetLength()+1, szString, _TRUNCATE);

위방법 ㅠ.ㅠ

3시간 정도 찾은거 같아 ㅠ.ㅠ

비록 땃짓도 많이 했지만 C#은 간단하구 좋았는데..

VS2005 VC++ 대략 알고리즘 짜는데 시간이 가는게 아니라... 타입케스팅 하다가 시간이 다 가버림 ㅠ.ㅠ 쥘쥘쥘쥘 꺼우져!!!!!!!
Posted by 나비:D
:

C++ char 형변환

2009. 4. 23. 17:02
[CString → char *]
CString str;
str = "Hello";
char* ss = LPSTR(LPCTSTR(str));

[CString → TCHAR]
 _tcscpy( szValue, (LPCTSTR)strValue);

[CString → int]

CString str;
int i = 0;
i = atoi((LPCTSTR)str);

[char * → CString]
char ss[] = "Hello";
CString str;
str.Format("%s", ss);

[char * → int]
char ss[10] = "Hello";
int i = _ttoi((LPCTSTR)ss);
Posted by 나비:D
:

이전에 만들었던 DLL을 실제로 사용하는 방법에 대해서 포스팅한다 ..


두 가지 방법이 있다 ..

먼저 .LIB파일을 사용하는 암시적인 방법과 .. 명시적인 방법이 있다.


암시적인 방법은 .LIB파일을 링크옵션에 추가시켜주어서 링크하는 것인데 이 방법을 사용하기

위해서는 당연히 .LIB파일이 필수적으로 존재해야 한다.



위 스크린샷 처럼 dll.LIB를 추가시켜주고 실제 dll에 구현되어 있는 함수를 가져다가 쓰면 된다.

무척이나 간단한 방법이다 ..


명시적인 방법에 대해서 알아보자.

명시적인 방법은 .LIB가 없는 경우에 사용되면 좋다.

하지만 그러기 위해서는 먼저 dll에 구현되어 있는 정확한 함수의 이름 ..

그리고 함수의 리턴 타입.. 아규먼트 형식과 갯수등을 매우 정확하게 알고 있어야 한다.


명시적인 방법에서 사용되는 주요 함수가 LoadLibrary와 GetProcAddress이다..

첫 번째 함수는 dll을 로드해서 인스턴스를 반환하고 GetProcAddress 는 LoadLibrary를 통해서

받은 dll 인스턴스를 통해서 인자로 넘겨주는 심볼의 함수 주소를 가져온다.

즉 실제 구현된 함수의 포인터를 가져오는 것이다.


간단한 예제를 통해 알아보자.



위 코드는 함수 포인터를 선언하는 내용이다.

위에서 잠깐 말했듯이 명시적인 DLL사용방법을 쓰기 위해서는 DLL 에 구현되어 있는 함수의

리턴 타입과 아규먼트 타입을 잘 알아야 한다고 하였다 ..

위에서 처럼 함수 포인터를 선언할 때 꼭 DLL에서 구현된 함수와 같은 타입으로 해주어야

실제 사용할 때 에러가 없다.



위 코드에서는 LoadLibrary를 사용하고 있다. 인자로 로드할 dll의 파일명을 넘겨준다.

그런데 반환되는 타입을 보니 HMODULE이다. 위에서는 인스턴스라고 했는데?


HMODULE과 HINSTANCE는 각각 16비트 시절에 코드역역과 데이터영역을 나누는데에서 의미가

있었지만 32비트로 넘어오면서 이 두개의 차이가 없어졌다.


아무튼 .. 반환된 값은 hDll로 넘겨지게 되고 if 문을 사용해서 로드가 되었는지 안되었는지 먼저

확인을 한다 ..



이제 GetProcAddress를 사용해서 포인터를 구해오고 그 포인터를 해당 함수형으로 타입캐스팅을

한 다음 실제 사용할 함수 포인터에 넣어준다.


이때 GetProcAddress의 두 번째 인자는 실제 DLL의 Export 정보에 등록된 이름이어야 한다.

만약 조금이라도 틀리면 포인터를 얻어올 수 없다,


이렇게 얻어온 함수 포인터는 if문으로 평가되어서 로드가 되었는지 안되었는지 확인한다.



두 가지 방법을 알아보았는데 두 가지 모두 장단점이 있는것 같다..

먼저 .LIB를 사용하는 암시적인 방법은 실제 프로그램을 개발하는 입장에서는 사용하기 편리하다.

그러나 만약 DLL이 없거나 DLL 안에 구현된 함수를 얻어오지 못하는 등의 예외상황에서

유연한 대처가 힘들다 ..


그러나 명시적인 사용방법에서는 그러한 예외상황에 대해서 유연하게 대처가 가능하다

위에서 본 코드들 처럼 if 문을 사용해서 예외처리가 가능하기 때문이다 ..


그리고 해커적인 입장에서는 명시적인 사용방법에 대해서 잘 인지하고 있다면 리버싱등을 할때

좋은 힌트가 될 수 있을것 같다.

Posted by 나비:D
:


  강좌 최초 작성일 : 2003년 06월 15일
  강좌 최종 수정일 : 2004년 03월 17일

  작성자 : HOONS(박경훈) http://www.hoonsbara.com

  강좌 제목 :  응용프로그램 조이기1  
 


1. 이강좌는?

음;; 응용 프로그램 조이기란 무엇인가??-_-;;
한마디로 메크로 프로그램이라고 할수 있다.
그렇다면 메크로 프로그램이란 란 무엇이냐??
사람의 동작이 아닌 자동으로 어떠한 프로그램 제어한다는 것이다. 예를들어서
만약 슬롯 머신 프로그램이 있다면 사람 없이.. 자동으로
그 프로그램이 실행되고 자기가 알아서 게임을 한다는 것이다.
이런 프로그램은 실생활에서 많이 쓰이는 부분이고 앞으로도 쓸일이 많이 있을것이다.
음;; 예를들어서 자동 메신저 로그인 프로그램이라던지 (자기 멋대로 실행되서 로그인하고-_-),
등등 어떤 응용프로그램도 메크로프로그램으로 제어를 할수 있게된다.
닷넷으로 이쪽 프로그램을 만들기 시작한것이 어떠한 게임 중독자의 의뢰로 부터 시작했었다.
의뢰의 내용은 대충 N회사의 포커 게임을 5개의 컴퓨터가 메세지를 주고 받으며
컴퓨터가 자동으로 게임을 진행하면서 돈을 몰아 주는 프로그램을 만들어 달라는 것이였다.
쩝;; 그때 무자게 머리 아프게 작업했던 기억이-_-;;
음; 이제는 그 메크로 프로그램의 가장 기본적인 사항들을 강좌로나마 남겨보고자한다.

시작하기전에 알아둬야 할 몇가지를 기초 지식을 설명하려고 한다.
먼저 핸들값의 관한 지식이다.



2.윈도우에서 핸들값이란 무엇인가??

응용프로그램을 제어하려면 바로 핸들 이라는 배경지식을 필수로 알고 있어야한다.
자..그럼 핸들에 관한 지식을 예를 들어 설명해 보도록 하겠다.
자기 컴퓨터의 윈도우가 실행되고 msn메신저와
익스플로러등등의 프로그램이 응용 프로그램이 실행되어 있다고 가정하자
그렇다면 전체 핸들의 구조는 먼저 부팅했던 된 윈도우에 핸들 구조를 보면
[메신저,익스플로러,등등]의 핸들들을 자식으로 가지게 된다(트리구조와 유사하다.)

윈도우-익스플로러
         -메신저-로그인버튼
                    -친구추가 버튼
                    -로아웃버튼
         -메모장

깊이 들어 가서 메신저의 구조를 본다면..
메신저 안의 [로그인버튼,친구추가버튼,리스트뷰,리스트박스] 이런 컨트롤들이 각각의
핸들값들을 가지고 있는것이다
즉 이러한 버튼 하나하나의 것들도 다 핸들값을 가지고 있다는 개념이고,
핸들의 구조역시 트리구조로 되어져 있다는 것을 예측하실수 있을 것이다.

<그림> 나중에 설명할 SPY++에 나와있는 핸들의 구조를 캡쳐한것이다


3. 핸들값을 왜 알아야 하는것인가.. ??

만약 메신저에 있는 친구추가 버튼을 자동으로 누르게 하고싶다면
"버튼을 클릭했다"와 같은 이벤트를 바로 핸들값을 찾아서 주어야 하기 때문이다.
이핸들값에 클릭 메세지를 보내라 라는 프로그램 명령을 하게 되기 때문이다.
우리가 어떤 메크로 프로그램을 하기 위해서는 핸들값을 몰라서는 프로그램을 만들수 없다.
앞으로 다룰 내용이 핸들값을 가져오는 부분이 될 것이고 그후에 메세지를 보내고,,
등등!!의 프로그램을 만들어 보게 될것이다.

그럼 오늘은 여기까지^^





  강좌 최초 작성일 : 2003년 06월 19일
  강좌 최종 수정일 : 2004년 03월 17일

  작성자 : HOONS(박경훈) http://www.hoonsbara.com

  강좌 제목 :  응용프로그램 조이기2 (핸들값찾기)  
 


1. API함수를 이용한 핸들찾기

핸들을 찾기위해 알아야 할 기초적 API함수들을 알아 보도록 하겠다.

1_1.FindWindow()

가장 최상위의 핸들을 찾는 함수이며 인자값으로 클래스이름과 캡션값을 넘겨준다.

C#에서의 선언하기

[DllImport("user32.dll")]
public  static extern int  FindWindow(string  lpClassName,string  lpWindowName);

첫번째 인자값은 찾고자하는 클래스이름,두번째는 캡션값을 넘겨준다.
둘중 하나의 값만 주어도 찾을수 있지만 캡션명이 똑같은 프로그램이 실행중이라면,
클래스명이 필요할것이다.리턴값은 그 캡션명과 클래스 이름을 가지고 있는 핸들값이다.
이런 캡션명과 클래스명은 spy++프로그램을 통해서 알수 있다.
하지만 이함수는 단지 한프로그램의 최상위 핸들 값만 리턴해줄 뿐이고,
자식들의 핸들값들은 FindWindowEX()라는 함수를 통해 알 수가 있다.

참고자료:ms-help://MS.VSCC/MS.MSDNVS.1042/winui/windows_03sn.htm

1_2.FindWindowEX()

인자값으로 받은 핸들의 자식 핸들을 찾는 클래스이다.

[C#에서의 선언]

[DllImport("user32.dll")]
public  static extern int  FindWindowEx(int  hWnd1,int  hWnd2,string  lpsz1,string  lpsz2);

첫번째 인자값은 바로 위의 부모값을 주고, 두번째 인자값은 0이나 null을 주자.
세번째와 네번째 인자값에는 FindWindow와 마찬가지로 클래스명과 캡션명을 넘겨주면
첫번째 인자로 넘겨주었던 핸들자식중에 세번째 네번째 주었던 인자값의 해당하는 핸들을 찾는것이다.
만약 핸들을 찾으면 핸들값을 리턴해주고 그렇지 않으면 0을 리턴한다.

참고자료:ms-help://MS.VSCC/MS.MSDNVS.1042/winui/windows_1zjs.htm



2. SPY++따라하기

이 두개의 함수만으로도 일단 왠만한 핸들은 다 접근할수 있을거라 생각한다.
그렇다면 이제 SPY++을 통해 캡션명과 클래스이름을 알아 보는 방법을 보자.



[그림1]SPY++의 실행

 

[그림2] 기본 메뉴의 설명

 



[그림3] SPY++캡션명과 클래스명

 

[그림4] SPY++의 핸들 속성

 

 

이 SPY++을 주물럭 주물럭 하다보면 쉽게 익숙해 질것이다.
그렇다면 이제 한번 예제를 통해서 핸들값을 가져오는 연습을 한번 해보자
아래의 예제는 위에 [그림4] 에 나오는 필자의 msn메신저5.0버전을
FindWindow와 FindWindowEX를 통해서 한번 접근해 본것이다.

3. 핸들값 찾기 예제(ConSole Program)

using System;
using System.Runtime.InteropServices; //추가.. namespace _1_1Con
{
    class Class1
    {
        //API함수를 선언한다.
        [DllImport("user32.dll")]
        public  static extern int  FindWindow(string  lpClassName,string  lpWindowName);
        [DllImport("user32.dll")]
        public  static extern int  FindWindowEx(int  hWnd1,int  hWnd2,string  lpsz1,string  lpsz2);

        [STAThread]
        static void Main(string[] args)
        {
            Console.WriteLine("메신저의 핸들값은?");
            Console.WriteLine("캡션값만 입력한 핸들값 : "+FindWindow(null,"MSN Messenger").ToString());
            Console.WriteLine("클래스명만 입력한 핸들값 :"+FindWindow("MSNMSBLClass",null).ToString());
            //클래스명과 핸들값둘중 하나만 입력해도 값은 똑같이 리턴이 된다.
            //그렇다면 이제 부모핸들값을들 저장시키면서 한번 그림 4에 있는 대화상대 추가 핸들값을 알아내보자.             int hw1=FindWindow(null,"MSN Messenger");
            Console.WriteLine("핸들값1:"+hw1.ToString());
            int hw2=FindWindowEx(hw1,0,"PluginHostClass",null);
            Console.WriteLine("핸들값2:"+hw2.ToString());
            int hw3=FindWindowEx(hw2,0,"MSNMSBLGeneric",null);
            Console.WriteLine("핸들값3:"+hw3.ToString());
            //여기까지 눈으로 내려온것이 확인이 되었다면 밑에 클래스 명들을 살펴보자.
            //그러면 분면 클래스 이름 두개가 같은것이 확인이 될것이다.그러기에 반드시 여기에는 캡션명을 같이 해주어야한다.

            int hw4=FindWindowEx(hw3,0,"MSNMSBLGeneric","Task List");
            Console.WriteLine("핸들값4:"+hw4.ToString());
            int hw5=FindWindowEx(hw4,0,"Button","전화 걸기");
            Console.WriteLine("핸들값5:"+hw5.ToString());
            //여기까지 출력이 되었다면 버튼 핸들값까지 알아내는것이 성공!!         }
    }
}


[결과]
 

핸들값을 가져오는것이 성고했다면..다음과같은 숫자들이 출력될것이고,
실패하였을 경우 전부0을 리턴하게 될 것이다.
오늘은 핸들값을 가져오는 연습을 해봤고 이제
다음 강좌에서는 핸들에 이벤트를 발생시켜보도록 하겠다.

 





  강좌 최초 작성일 : 2003년 06월 22일
  강좌 최종 수정일 : 2004년 03월 17일

  작성자 : HOONS(박경훈) http://www.hoonsbara.com

  강좌 제목 :  응용프로그램 조이기3 (MSN 5.0 제어하기)
 


1. 이벤트 메세지 보내보기

이전 강좌에서 메신저의 핸들을 찾아내 봤을것이다.
만약 성공적으로 구하고자 하는 핸들값을 찾아 내 봤다면
이제 한번 그 버튼을 클릭하는 이벤트를 보내기 위해서는 이벤트를
보내는 API함수를 알아야할 것이다. 먼저 이벤트를 보내는 API함수
중에 SendMessage()대해 알아보도록 하겠다.

1.2 SendMessage() 이벤트 전달함수

C#에서의 함수 선언은 다음과 같이 한다.

[DllImport("user32.dll")]
public  static extern int  SendMessage(int hwnd,int wMsg,int wParam,int lParam);

첫번째 인자값은 이벤트를 보낼 핸들 값을 넣어주고, 두번째 인자값은 이벤트 메세지에 해당된다.
세번째와 네번째 인자값은 그에 따른 부수저인 메세지를 전달되는 것이다.
메세지에 대한 정의는 파일로 첨부 하였으니 상황에 따라 참고해서 쓰면 될 것이다.
이벤트 상황에 따라 SendMessage()함수가 다르게 쓰이므로 많은 연습이 필요할 것이다.


2. MSN메신저5.0 제어 해보기


먼저 바로 전 강좌에서 핸들값을 가져오는것이 성공하였다면 바로 이벤트 예제를 해보도록 하자.

2.1 핸들값의 구조파악

[그림1]예제핸들

 

그림1에 보이는 핸들 구조는 필자의 메신저의 즐겨쓰는버튼버튼까지의 핸들 구조를 열어 본것이다.
FindWindow함수와 FindwWindowEX로 버튼의 핸들값을 알아낸 후 클릭 이벤트를 줄것이다.

2.2 제어하기 예제 코드

using System;
using System.Runtime.InteropServices; //추가..

namespace _1_1Con
{
    class Class1
    {
        //API함수를 선언한다.        

        [DllImport("user32.dll")]
        public  static extern int  FindWindow(string  lpClassName,string lpWindowName);

        [DllImport("user32.dll")]
        public  static extern int  FindWindowEx(int  hWnd1,int  hWnd2,string  lpsz1,string  lpsz2);

        [DllImport("user32.dll")]
        public  static extern int  SendMessage(int  hwnd,int  wMsg,int  wParam,int  lParam);

        [STAThread]
        static void Main(string[] args)
        {
            //핸들값을 찾아보자
            int hw1=FindWindow(null,"MSN Messenger");
            Console.WriteLine("핸들값1:"+hw1.ToString());

            int hw2=FindWindowEx(hw1,0,"PluginHostClass",null);
            Console.WriteLine("핸들값2:"+hw2.ToString());

            int hw3=FindWindowEx(hw2,0,"MSNMSBLGeneric",null);
            Console.WriteLine("핸들값3:"+hw3.ToString());

            int hw4=FindWindowEx(hw3,0,"MSNMSBLGeneric","Task List");
            Console.WriteLine("핸들값4:"+hw4.ToString());

            int hw5=FindWindowEx(hw4,0,"Button","즐겨쓰는 메뉴");
            Console.WriteLine("핸들값5:"+hw5.ToString());

            //여기까지 출력이 되었다면 버튼 핸들값까지 알아내는것이 성공!!

            const int WM_LBUTTONDOWN = 0x0201;
            const int WM_LBUTTONUP = 0x0202;
            const int BM_CLICK = 0x00F5;

            //마우스 클릭이벤트이다
            SendMessage(hw5,BM_CLICK,0,1);

            //마우스 다운+업=클릭 이므로 이렇게 사용해도 무방하다
            SendMessage(hw5,WM_LBUTTONDOWN,0,1);
            SendMessage(hw5,WM_LBUTTONUP,0,1);        
        }
    }
}

[그림2] 실행 예제

 

실행 하면 두번 클릭 이벤트를 보냈으니 잽싸게 메뉴창이 오르락 내리락한 모습을 봤을거라 생각한다.
우선은 간단한 버튼 클릭 이벤트를 보내 보았다. 앞의 강의에 더 많은 이벤트를 보내 보도록 하면서..
오늘 강의는 여기서 마치도록 하겠다.

내일 강의는 핸들에 관련된 API함수들을 자세히 알아보도록 하겠다.그럼..




  강좌 최초 작성일 : 2003년 06월 22일
  강좌 최종 수정일 : 2004년 03월 17일

  작성자 : HOONS(박경훈) http://www.hoonsbara.com

  강좌 제목 :  응용프로그램 조이기4 (핸들값찾기2)
 


1. 찾기 힘든 핸들값?!

앞의 강좌에 삘(Feel)을 받아 이것저것 많은 이벤트 보내기 실습을 해본 사람이라면..
여러 응용프로그램의 핸들을 찾던 도중 안풀리는 몬가의 문제거리를 발견 했을거라 생각한다.
물론 이강좌를 이해하려면 앞의 예제를 다른 프로그램에 많이 응용을 해봐야 한다.
그리고 어떤 문제거리를 받아 보아야만 이 강좌가 엄청의 감동의 물결을 가져다 줄것이다.
그렇다면 몬가 안풀리는 문제거리를 그림을 통해서 살펴보도록 하자.

그림1(몬가 이상한 핸들구조)

위에서 본 그림을 살펴보면..
한 응용프로그램의 핸들아래 세개의 핸들이 있는 구조이다..(색칠한 부분)
그리고 자기가 이벤트를 보내고자하는 부분은 그 핸들들의 첫번째핸들에 속해있는 버튼인 것이다.
근데 세개의 핸들이 클래스명 자리에 #32770 이라는 클래스명이 들어가있다.
이것은 MFC에서 개발을 할때 클래스 명을 숨겨버렸기에 #32770이라는 결과가 나오는 것이다.
캡션값도 없고..클래스명도 없고 이럴 때는 어떻게 핸들을 찾아 갈것인가??
대략 난감하다.._-_
만약 #32770이 한개라면 findwindowEx()함수에 클래스명을 #32770이라고 써주면 잘 찾게 되지만.
위와같은 구조에서는 자기가 얻고자하는 핸들을 정확히 가지고 올수 없다..
이것을 해결하기 위해서는 트리구조의 원리를 가지고 접근을 해야한다는 것이다.
윈폼에서 작업했던 트리노드를 생각해보자. 자식의 부모의..모 이런식의 개념인 것이다.
그렇다면 여기서 알아야할 API함수가 있다..바로 GetWindow() 라는 함수이고
이함수가 이문제의 해결을 해줄수 있는 해결책이다.

2. GetWindow()함수를 이용하여 핸들값 찾기

C#에서의 선언은 다음과 같다.

[DllImport("user32.dll")]
public static extern IntPtr GetWindow(IntPtr hWnd, int uCmd);

첫번째 인자는 대상이 되는 핸들값이고 바로 두번째가 그 대상핸들의 자식,혹은 바로 아래 핸들.
부모핸들..이런 식으로0~5까지 값으로 구별하여 접근할수가 있는것이다.

const int GW_HWNDFIRST = 0;
const int GW_HWNDLAST = 1;
const int GW_HWNDNEXT = 2;
const int GW_HWNDPREV = 3;
const int GW_OWNER = 4;
const int GW_CHILD = 5;

정의는 다음과 같다.대충 보면 어떤 값들인지 알것이다.
위의 그림을 보자..최상위 핸들값을 hwnd_main이라고 하고
한번 두번째 자식의 값을 가져오고 싶다면 다음과 같이 접근하면될것이다.

int hwnd_first=GetWindow(hwnd_main,GW_CHILD); //첫번째 자식의 핸들값->바로 자식의 핸들값을 가져오므로

int hwnd_second=GetWindow(hwnd_first,GW_HWNDNEXT); //첫번째 아래에 있는 핸들값 바로 두번째 핸들값

이런식으로 접근을 하면 두번째 핸들을 정확히 접근할수 있을 것이다.
이부분의 예제는 생략하겠다. 나중에 핸들을 찾다가 다음과 같이 접근이 불가능 한 상황이 되었다면
GetWindow()함수를 사용하라는 것만 전해주고 싶다.
그럼 핸들에 관련된 여러 API함수를 알아 보도록 하겠다.

3.여러가지 핸들 관련 함수들

*GetWindowText()

[DllImport("user32.dll")]
private static extern int GetWindowText(int hWnd, StringBuilder title, int size);

이 함수는 핸들값을 넘겨주면 그 핸들값이 가지고 있는 캡션값을 반환하여준다.
첫번째 인자는 알아내고자하는 핸들대상이고..그 윈도우의 캡션값은 두번재 인자값으로
반환하여 준다. 세번째는 받을 텍스트값의 최대 크기를 정해주는 것이다.


*ShowWindowAsync()

[DllImport("user32.dll")]
private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);

이 함수는 윈도우의 창의 상태를 변경시킨다. 두번째 인자값을 어떻게 넘겨주느냐에 따라서 상태가 변하고.
첫번째는 변화시키고자 하는 핸들값이다.
상태에 대한 값은 아래 값들을 참고하길..

private const int SW_HIDE = 0;
private const int SW_SHOWNORMAL = 1;
private const int SW_SHOWMINIMIZED = 2;
private const int SW_SHOWMAXIMIZED = 3;
private const int SW_SHOWNOACTIVATE = 4;
private const int SW_RESTORE = 9;
private const int SW_SHOWDEFAULT = 10;

이밖에도 핸들에 관련된 함수는 많이 있지만 가장 많이 사용하는 함수 두개만 뽑아봤다.

http://www.hoonsbara.com/hoons/lecture/2_1/WindowHiderSource.zip

그리고 이주소는 한 외국 사이트에 있는 api관련 핸들 예제이다. 이 예제를 참고하여 살펴보기를 바라면서.
오늘의 강좌는 여기서 마치도록 하고 내일(혹은 내일모레) 에 강좌에서는 SendMessage()에 관한
자세한 이벤트에 대해서 몇글자 끄적거려 보려고 한다.그럼..


WM_NULL = 0x0000,

        WM_CREATE = 0x0001,

        WM_DESTROY = 0x0002,

        WM_MOVE = 0x0003,

        WM_SIZE = 0x0005,

        WM_ACTIVATE = 0x0006,

        WM_SETFOCUS = 0x0007,

        WM_KILLFOCUS = 0x0008,

        WM_ENABLE = 0x000A,

        WM_SETREDRAW = 0x000B,

        WM_SETTEXT = 0x000C,

        WM_GETTEXT = 0x000D,

        WM_GETTEXTLENGTH = 0x000E,

        WM_PAINT = 0x000F,

        WM_CLOSE = 0x0010,

        WM_QUERYENDSESSION = 0x0011,

        WM_QUERYOPEN = 0x0013,

        WM_ENDSESSION = 0x0016,

        WM_QUIT = 0x0012,

        WM_ERASEBKGND = 0x0014,

        WM_SYSCOLORCHANGE = 0x0015,

        WM_SHOWWINDOW = 0x0018,

        WM_WININICHANGE = 0x001A,

        WM_SETTINGCHANGE = 0x001A,

        WM_DEVMODECHANGE = 0x001B,

        WM_ACTIVATEAPP = 0x001C,

        WM_FONTCHANGE = 0x001D,

        WM_TIMECHANGE = 0x001E,

        WM_CANCELMODE = 0x001F,

        WM_SETCURSOR = 0x0020,

        WM_MOUSEACTIVATE = 0x0021,

        WM_CHILDACTIVATE = 0x0022,

        WM_QUEUESYNC = 0x0023,

        WM_GETMINMAXINFO = 0x0024,

        WM_PAINTICON = 0x0026,

        WM_ICONERASEBKGND = 0x0027,

        WM_NEXTDLGCTL = 0x0028,

        WM_SPOOLERSTATUS = 0x002A,

        WM_DRAWITEM = 0x002B,

        WM_MEASUREITEM = 0x002C,

        WM_DELETEITEM = 0x002D,

        WM_VKEYTOITEM = 0x002E,

        WM_CHARTOITEM = 0x002F,

        WM_SETFONT = 0x0030,

        WM_GETFONT = 0x0031,

        WM_SETHOTKEY = 0x0032,

        WM_GETHOTKEY = 0x0033,

        WM_QUERYDRAGICON = 0x0037,

        WM_COMPAREITEM = 0x0039,

        WM_GETOBJECT = 0x003D,

        WM_COMPACTING = 0x0041,

        WM_COMMNOTIFY = 0x0044,

        WM_WINDOWPOSCHANGING = 0x0046,

        WM_WINDOWPOSCHANGED = 0x0047,

        WM_POWER = 0x0048,

        WM_COPYDATA = 0x004A,

        WM_CANCELJOURNAL = 0x004B,

        WM_NOTIFY = 0x004E,

        WM_INPUTLANGCHANGEREQUEST = 0x0050,

        WM_INPUTLANGCHANGE = 0x0051,

        WM_TCARD = 0x0052,

        WM_HELP = 0x0053,

        WM_USERCHANGED = 0x0054,

        WM_NOTIFYFORMAT = 0x0055,

        WM_CONTEXTMENU = 0x007B,

        WM_STYLECHANGING = 0x007C,

        WM_STYLECHANGED = 0x007D,

        WM_DISPLAYCHANGE = 0x007E,

        WM_GETICON = 0x007F,

        WM_SETICON = 0x0080,

        WM_NCCREATE = 0x0081,

        WM_NCDESTROY = 0x0082,

        WM_NCCALCSIZE = 0x0083,

        WM_NCHITTEST = 0x0084,

        WM_NCPAINT = 0x0085,

        WM_NCACTIVATE = 0x0086,

        WM_GETDLGCODE = 0x0087,

        WM_SYNCPAINT = 0x0088,

        WM_NCMOUSEMOVE = 0x00A0,

        WM_NCLBUTTONDOWN = 0x00A1,

        WM_NCLBUTTONUP = 0x00A2,

        WM_NCLBUTTONDBLCLK = 0x00A3,

        WM_NCRBUTTONDOWN = 0x00A4,

        WM_NCRBUTTONUP = 0x00A5,

        WM_NCRBUTTONDBLCLK = 0x00A6,

        WM_NCMBUTTONDOWN = 0x00A7,

        WM_NCMBUTTONUP = 0x00A8,

        WM_NCMBUTTONDBLCLK = 0x00A9,

        WM_NCXBUTTONDOWN = 0x00AB,

        WM_NCXBUTTONUP = 0x00AC,

        WM_NCXBUTTONDBLCLK = 0x00AD,

        WM_INPUT = 0x00FF,

        WM_KEYFIRST = 0x0100,

        WM_KEYDOWN = 0x0100,

        WM_KEYUP = 0x0101,

        WM_CHAR = 0x0102,

        WM_DEADCHAR = 0x0103,

        WM_SYSKEYDOWN = 0x0104,

        WM_SYSKEYUP = 0x0105,

        WM_SYSCHAR = 0x0106,

        WM_SYSDEADCHAR = 0x0107,

        WM_UNICHAR = 0x0109,

        WM_KEYLAST_NT501 = 0x0109,

        UNICODE_NOCHAR = 0xFFFF,

        WM_KEYLAST_PRE501 = 0x0108,

        WM_IME_STARTCOMPOSITION = 0x010D,

        WM_IME_ENDCOMPOSITION = 0x010E,

        WM_IME_COMPOSITION = 0x010F,

        WM_IME_KEYLAST = 0x010F,

        WM_INITDIALOG = 0x0110,

        WM_COMMAND = 0x0111,

        WM_SYSCOMMAND = 0x0112,

        WM_TIMER = 0x0113,

        WM_HSCROLL = 0x0114,

        WM_VSCROLL = 0x0115,

        WM_INITMENU = 0x0116,

        WM_INITMENUPOPUP = 0x0117,

        WM_MENUSELECT = 0x011F,

        WM_MENUCHAR = 0x0120,

        WM_ENTERIDLE = 0x0121,

        WM_MENURBUTTONUP = 0x0122,

        WM_MENUDRAG = 0x0123,

        WM_MENUGETOBJECT = 0x0124,

        WM_UNINITMENUPOPUP = 0x0125,

        WM_MENUCOMMAND = 0x0126,

        WM_CHANGEUISTATE = 0x0127,

        WM_UPDATEUISTATE = 0x0128,

        WM_QUERYUISTATE = 0x0129,

        WM_CTLCOLORMSGBOX = 0x0132,

        WM_CTLCOLOREDIT = 0x0133,

        WM_CTLCOLORLISTBOX = 0x0134,

        WM_CTLCOLORBTN = 0x0135,

        WM_CTLCOLORDLG = 0x0136,

        WM_CTLCOLORSCROLLBAR = 0x0137,

        WM_CTLCOLORSTATIC = 0x0138,

        WM_MOUSEFIRST = 0x0200,

        WM_MOUSEMOVE = 0x0200,

        WM_LBUTTONDOWN = 0x0201,

        WM_LBUTTONUP = 0x0202,

        WM_LBUTTONDBLCLK = 0x0203,

        WM_RBUTTONDOWN = 0x0204,

        WM_RBUTTONUP = 0x0205,

        WM_RBUTTONDBLCLK = 0x0206,

        WM_MBUTTONDOWN = 0x0207,

        WM_MBUTTONUP = 0x0208,

        WM_MBUTTONDBLCLK = 0x0209,

        WM_MOUSEWHEEL = 0x020A,

        WM_XBUTTONDOWN = 0x020B,

        WM_XBUTTONUP = 0x020C,

        WM_XBUTTONDBLCLK = 0x020D,

        WM_MOUSELAST_5 = 0x020D,

        WM_MOUSELAST_4 = 0x020A,

        WM_MOUSELAST_PRE_4 = 0x0209,

        WM_PARENTNOTIFY = 0x0210,

        WM_ENTERMENULOOP = 0x0211,

        WM_EXITMENULOOP = 0x0212,

        WM_NEXTMENU = 0x0213,

        WM_SIZING = 0x0214,

        WM_CAPTURECHANGED = 0x0215,

        WM_MOVING = 0x0216,

        WM_POWERBROADCAST = 0x0218,

        WM_DEVICECHANGE = 0x0219,

        WM_MDICREATE = 0x0220,

        WM_MDIDESTROY = 0x0221,

        WM_MDIACTIVATE = 0x0222,

        WM_MDIRESTORE = 0x0223,

        WM_MDINEXT = 0x0224,

        WM_MDIMAXIMIZE = 0x0225,

        WM_MDITILE = 0x0226,

        WM_MDICASCADE = 0x0227,

        WM_MDIICONARRANGE = 0x0228,

        WM_MDIGETACTIVE = 0x0229,

        WM_MDISETMENU = 0x0230,

        WM_ENTERSIZEMOVE = 0x0231,

        WM_EXITSIZEMOVE = 0x0232,

        WM_DROPFILES = 0x0233,

        WM_MDIREFRESHMENU = 0x0234,

        WM_IME_SETCONTEXT = 0x0281,

        WM_IME_NOTIFY = 0x0282,

        WM_IME_CONTROL = 0x0283,

        WM_IME_COMPOSITIONFULL = 0x0284,

        WM_IME_SELECT = 0x0285,

        WM_IME_CHAR = 0x0286,

        WM_IME_REQUEST = 0x0288,

        WM_IME_KEYDOWN = 0x0290,

        WM_IME_KEYUP = 0x0291,

        WM_MOUSEHOVER = 0x02A1,

        WM_MOUSELEAVE = 0x02A3,

        WM_NCMOUSEHOVER = 0x02A0,

        WM_NCMOUSELEAVE = 0x02A2,

        WM_WTSSESSION_CHANGE = 0x02B1,

        WM_TABLET_FIRST = 0x02c0,

        WM_TABLET_LAST = 0x02df,

        WM_CUT = 0x0300,

        WM_COPY = 0x0301,

        WM_PASTE = 0x0302,

        WM_CLEAR = 0x0303,

        WM_UNDO = 0x0304,

        WM_RENDERFORMAT = 0x0305,

        WM_RENDERALLFORMATS = 0x0306,

        WM_DESTROYCLIPBOARD = 0x0307,

        WM_DRAWCLIPBOARD = 0x0308,

        WM_PAINTCLIPBOARD = 0x0309,

        WM_VSCROLLCLIPBOARD = 0x030A,

        WM_SIZECLIPBOARD = 0x030B,

        WM_ASKCBFORMATNAME = 0x030C,

        WM_CHANGECBCHAIN = 0x030D,

        WM_HSCROLLCLIPBOARD = 0x030E,

        WM_QUERYNEWPALETTE = 0x030F,

        WM_PALETTEISCHANGING = 0x0310,

        WM_PALETTECHANGED = 0x0311,

        WM_HOTKEY = 0x0312,

        WM_PRINT = 0x0317,

        WM_PRINTCLIENT = 0x0318,

        WM_APPCOMMAND = 0x0319,

        WM_THEMECHANGED = 0x031A,

        WM_HANDHELDFIRST = 0x0358,

        WM_HANDHELDLAST = 0x035F,

        WM_AFXFIRST = 0x0360,

        WM_AFXLAST = 0x037F,

        WM_PENWINFIRST = 0x0380,

        WM_PENWINLAST = 0x038F,

        WM_APP = 0x8000,

        WM_USER = 0x0400,

        EM_GETSEL = 0x00B0,

        EM_SETSEL = 0x00B1,

        EM_GETRECT = 0x00B2,

        EM_SETRECT = 0x00B3,

        EM_SETRECTNP = 0x00B4,

        EM_SCROLL = 0x00B5,

        EM_LINESCROLL = 0x00B6,

        EM_SCROLLCARET = 0x00B7,

        EM_GETMODIFY = 0x00B8,

        EM_SETMODIFY = 0x00B9,

        EM_GETLINECOUNT = 0x00BA,

        EM_LINEINDEX = 0x00BB,

        EM_SETHANDLE = 0x00BC,

        EM_GETHANDLE = 0x00BD,

        EM_GETTHUMB = 0x00BE,

        EM_LINELENGTH = 0x00C1,

        EM_REPLACESEL = 0x00C2,

        EM_GETLINE = 0x00C4,

        EM_LIMITTEXT = 0x00C5,

        EM_CANUNDO = 0x00C6,

        EM_UNDO = 0x00C7,

        EM_FMTLINES = 0x00C8,

        EM_LINEFROMCHAR = 0x00C9,

        EM_SETTABSTOPS = 0x00CB,

        EM_SETPASSWORDCHAR = 0x00CC,

        EM_EMPTYUNDOBUFFER = 0x00CD,

        EM_GETFIRSTVISIBLELINE = 0x00CE,

        EM_SETREADONLY = 0x00CF,

        EM_SETWORDBREAKPROC = 0x00D0,

        EM_GETWORDBREAKPROC = 0x00D1,

        EM_GETPASSWORDCHAR = 0x00D2,

        EM_SETMARGINS = 0x00D3,

        EM_GETMARGINS = 0x00D4,

        EM_SETLIMITTEXT = EM_LIMITTEXT,

        EM_GETLIMITTEXT = 0x00D5,

        EM_POSFROMCHAR = 0x00D6,

        EM_CHARFROMPOS = 0x00D7,

        EM_SETIMESTATUS = 0x00D8,

        EM_GETIMESTATUS = 0x00D9,

        BM_GETCHECK= 0x00F0,

        BM_SETCHECK= 0x00F1,

        BM_GETSTATE= 0x00F2,

        BM_SETSTATE= 0x00F3,

        BM_SETSTYLE= 0x00F4,

        BM_CLICK = 0x00F5,

        BM_GETIMAGE= 0x00F6,

        BM_SETIMAGE= 0x00F7,

        STM_SETICON = 0x0170,

        STM_GETICON = 0x0171,

        STM_SETIMAGE = 0x0172,

        STM_GETIMAGE = 0x0173,

        STM_MSGMAX = 0x0174,

        DM_GETDEFID = (WM_USER+0),

        DM_SETDEFID = (WM_USER+1),

        DM_REPOSITION = (WM_USER+2),

        LB_ADDSTRING = 0x0180,

        LB_INSERTSTRING = 0x0181,

        LB_DELETESTRING = 0x0182,

        LB_SELITEMRANGEEX= 0x0183,

        LB_RESETCONTENT = 0x0184,

        LB_SETSEL = 0x0185,

        LB_SETCURSEL = 0x0186,

        LB_GETSEL = 0x0187,

        LB_GETCURSEL = 0x0188,

        LB_GETTEXT = 0x0189,

        LB_GETTEXTLEN = 0x018A,

        LB_GETCOUNT = 0x018B,

        LB_SELECTSTRING = 0x018C,

        LB_DIR = 0x018D,

        LB_GETTOPINDEX = 0x018E,

        LB_FINDSTRING = 0x018F,

        LB_GETSELCOUNT = 0x0190,

        LB_GETSELITEMS = 0x0191,

        LB_SETTABSTOPS = 0x0192,

        LB_GETHORIZONTALEXTENT = 0x0193,

        LB_SETHORIZONTALEXTENT = 0x0194,

        LB_SETCOLUMNWIDTH = 0x0195,

        LB_ADDFILE = 0x0196,

        LB_SETTOPINDEX = 0x0197,

        LB_GETITEMRECT = 0x0198,

        LB_GETITEMDATA = 0x0199,

        LB_SETITEMDATA = 0x019A,

        LB_SELITEMRANGE = 0x019B,

        LB_SETANCHORINDEX = 0x019C,

        LB_GETANCHORINDEX = 0x019D,

        LB_SETCARETINDEX = 0x019E,

        LB_GETCARETINDEX = 0x019F,

        LB_SETITEMHEIGHT = 0x01A0,

        LB_GETITEMHEIGHT = 0x01A1,

        LB_FINDSTRINGEXACT = 0x01A2,

        LB_SETLOCALE = 0x01A5,

        LB_GETLOCALE = 0x01A6,

        LB_SETCOUNT = 0x01A7,

        LB_INITSTORAGE = 0x01A8,

        LB_ITEMFROMPOINT = 0x01A9,

        LB_MULTIPLEADDSTRING = 0x01B1,

        LB_GETLISTBOXINFO= 0x01B2,

        LB_MSGMAX_501 = 0x01B3,

        LB_MSGMAX_WCE4 = 0x01B1,

        LB_MSGMAX_4 = 0x01B0,

        LB_MSGMAX_PRE4 = 0x01A8,

        CB_GETEDITSEL = 0x0140,

        CB_LIMITTEXT = 0x0141,

        CB_SETEDITSEL = 0x0142,

        CB_ADDSTRING = 0x0143,

        CB_DELETESTRING = 0x0144,

        CB_DIR = 0x0145,

        CB_GETCOUNT = 0x0146,

        CB_GETCURSEL = 0x0147,

        CB_GETLBTEXT = 0x0148,

        CB_GETLBTEXTLEN = 0x0149,

        CB_INSERTSTRING = 0x014A,

        CB_RESETCONTENT = 0x014B,

        CB_FINDSTRING = 0x014C,

        CB_SELECTSTRING = 0x014D,

        CB_SETCURSEL = 0x014E,

        CB_SHOWDROPDOWN = 0x014F,

        CB_GETITEMDATA = 0x0150,

        CB_SETITEMDATA = 0x0151,

        CB_GETDROPPEDCONTROLRECT = 0x0152,

        CB_SETITEMHEIGHT = 0x0153,

        CB_GETITEMHEIGHT = 0x0154,

        CB_SETEXTENDEDUI = 0x0155,

        CB_GETEXTENDEDUI = 0x0156,

        CB_GETDROPPEDSTATE = 0x0157,

        CB_FINDSTRINGEXACT = 0x0158,

        CB_SETLOCALE = 0x0159,

        CB_GETLOCALE = 0x015A,

        CB_GETTOPINDEX = 0x015B,

        CB_SETTOPINDEX = 0x015C,

        CB_GETHORIZONTALEXTENT = 0x015d,

        CB_SETHORIZONTALEXTENT = 0x015e,

        CB_GETDROPPEDWIDTH = 0x015f,

        CB_SETDROPPEDWIDTH = 0x0160,

        CB_INITSTORAGE = 0x0161,

        CB_MULTIPLEADDSTRING = 0x0163,

        CB_GETCOMBOBOXINFO = 0x0164,

        CB_MSGMAX_501 = 0x0165,

        CB_MSGMAX_WCE400 = 0x0163,

        CB_MSGMAX_400 = 0x0162,

        CB_MSGMAX_PRE400 = 0x015B,

        SBM_SETPOS = 0x00E0,

        SBM_GETPOS = 0x00E1,

        SBM_SETRANGE = 0x00E2,

        SBM_SETRANGEREDRAW = 0x00E6,

        SBM_GETRANGE = 0x00E3,

        SBM_ENABLE_ARROWS = 0x00E4,

        SBM_SETSCROLLINFO = 0x00E9,

        SBM_GETSCROLLINFO = 0x00EA,

        SBM_GETSCROLLBARINFO= 0x00EB,

        LVM_FIRST = 0x1000,// ListView messages

        TV_FIRST = 0x1100,// TreeView messages

        HDM_FIRST = 0x1200,// Header messages

        TCM_FIRST = 0x1300,// Tab control messages

        PGM_FIRST = 0x1400,// Pager control messages

        ECM_FIRST = 0x1500,// Edit control messages

        BCM_FIRST = 0x1600,// Button control messages

        CBM_FIRST = 0x1700,// Combobox control messages

        CCM_FIRST = 0x2000,// Common control shared messages

        CCM_LAST =(CCM_FIRST + 0x200),

        CCM_SETBKCOLOR = (CCM_FIRST + 1),

        CCM_SETCOLORSCHEME = (CCM_FIRST + 2),

        CCM_GETCOLORSCHEME = (CCM_FIRST + 3),

        CCM_GETDROPTARGET = (CCM_FIRST + 4),

        CCM_SETUNICODEFORMAT = (CCM_FIRST + 5),

        CCM_GETUNICODEFORMAT = (CCM_FIRST + 6),

        CCM_SETVERSION = (CCM_FIRST + 0x7),

        CCM_GETVERSION = (CCM_FIRST + 0x8),

        CCM_SETNOTIFYWINDOW = (CCM_FIRST + 0x9),

        CCM_SETWINDOWTHEME = (CCM_FIRST + 0xb),

        CCM_DPISCALE = (CCM_FIRST + 0xc),

        HDM_GETITEMCOUNT = (HDM_FIRST + 0),

        HDM_INSERTITEMA = (HDM_FIRST + 1),

        HDM_INSERTITEMW = (HDM_FIRST + 10),

        HDM_DELETEITEM = (HDM_FIRST + 2),

        HDM_GETITEMA = (HDM_FIRST + 3),

        HDM_GETITEMW = (HDM_FIRST + 11),

        HDM_SETITEMA = (HDM_FIRST + 4),

        HDM_SETITEMW = (HDM_FIRST + 12),

        HDM_LAYOUT = (HDM_FIRST + 5),

        HDM_HITTEST = (HDM_FIRST + 6),

        HDM_GETITEMRECT = (HDM_FIRST + 7),

        HDM_SETIMAGELIST = (HDM_FIRST + 8),

        HDM_GETIMAGELIST = (HDM_FIRST + 9),

        HDM_ORDERTOINDEX = (HDM_FIRST + 15),

        HDM_CREATEDRAGIMAGE = (HDM_FIRST + 16),

        HDM_GETORDERARRAY = (HDM_FIRST + 17),

        HDM_SETORDERARRAY = (HDM_FIRST + 18),

        HDM_SETHOTDIVIDER = (HDM_FIRST + 19),

        HDM_SETBITMAPMARGIN = (HDM_FIRST + 20),

        HDM_GETBITMAPMARGIN = (HDM_FIRST + 21),

        HDM_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT,

        HDM_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT,

        HDM_SETFILTERCHANGETIMEOUT = (HDM_FIRST+22),

        HDM_EDITFILTER = (HDM_FIRST+23),

        HDM_CLEARFILTER = (HDM_FIRST+24),

        TB_ENABLEBUTTON = (WM_USER + 1),

        TB_CHECKBUTTON = (WM_USER + 2),

        TB_PRESSBUTTON = (WM_USER + 3),

        TB_HIDEBUTTON = (WM_USER + 4),

        TB_INDETERMINATE = (WM_USER + 5),

        TB_MARKBUTTON = (WM_USER + 6),

        TB_ISBUTTONENABLED = (WM_USER + 9),

        TB_ISBUTTONCHECKED = (WM_USER + 10),

        TB_ISBUTTONPRESSED = (WM_USER + 11),

        TB_ISBUTTONHIDDEN = (WM_USER + 12),

        TB_ISBUTTONINDETERMINATE = (WM_USER + 13),

        TB_ISBUTTONHIGHLIGHTED = (WM_USER + 14),

        TB_SETSTATE = (WM_USER + 17),

        TB_GETSTATE = (WM_USER + 18),

        TB_ADDBITMAP = (WM_USER + 19),

        TB_ADDBUTTONSA = (WM_USER + 20),

        TB_INSERTBUTTONA = (WM_USER + 21),

        TB_ADDBUTTONS = (WM_USER + 20),

        TB_INSERTBUTTON = (WM_USER + 21),

        TB_DELETEBUTTON = (WM_USER + 22),

        TB_GETBUTTON = (WM_USER + 23),

        TB_BUTTONCOUNT = (WM_USER + 24),

        TB_COMMANDTOINDEX = (WM_USER + 25),

        TB_SAVERESTOREA = (WM_USER + 26),

        TB_SAVERESTOREW = (WM_USER + 76),

        TB_CUSTOMIZE = (WM_USER + 27),

        TB_ADDSTRINGA = (WM_USER + 28),

        TB_ADDSTRINGW = (WM_USER + 77),

        TB_GETITEMRECT = (WM_USER + 29),

        TB_BUTTONSTRUCTSIZE = (WM_USER + 30),

        TB_SETBUTTONSIZE = (WM_USER + 31),

        TB_SETBITMAPSIZE = (WM_USER + 32),

        TB_AUTOSIZE = (WM_USER + 33),

        TB_GETTOOLTIPS = (WM_USER + 35),

        TB_SETTOOLTIPS = (WM_USER + 36),

        TB_SETPARENT = (WM_USER + 37),

        TB_SETROWS = (WM_USER + 39),

        TB_GETROWS = (WM_USER + 40),

        TB_SETCMDID = (WM_USER + 42),

        TB_CHANGEBITMAP = (WM_USER + 43),

        TB_GETBITMAP = (WM_USER + 44),

        TB_GETBUTTONTEXTA = (WM_USER + 45),

        TB_GETBUTTONTEXTW = (WM_USER + 75),

        TB_REPLACEBITMAP = (WM_USER + 46),

        TB_SETINDENT = (WM_USER + 47),

        TB_SETIMAGELIST = (WM_USER + 48),

        TB_GETIMAGELIST = (WM_USER + 49),

        TB_LOADIMAGES = (WM_USER + 50),

        TB_GETRECT = (WM_USER + 51),

        TB_SETHOTIMAGELIST = (WM_USER + 52),

        TB_GETHOTIMAGELIST = (WM_USER + 53),

        TB_SETDISABLEDIMAGELIST = (WM_USER + 54),

        TB_GETDISABLEDIMAGELIST = (WM_USER + 55),

        TB_SETSTYLE = (WM_USER + 56),

        TB_GETSTYLE = (WM_USER + 57),

        TB_GETBUTTONSIZE = (WM_USER + 58),

        TB_SETBUTTONWIDTH = (WM_USER + 59),

        TB_SETMAXTEXTROWS = (WM_USER + 60),

        TB_GETTEXTROWS = (WM_USER + 61),

        TB_GETOBJECT = (WM_USER + 62),

        TB_GETHOTITEM = (WM_USER + 71),

        TB_SETHOTITEM = (WM_USER + 72),

        TB_SETANCHORHIGHLIGHT = (WM_USER + 73),

        TB_GETANCHORHIGHLIGHT = (WM_USER + 74),

        TB_MAPACCELERATORA = (WM_USER + 78),

        TB_GETINSERTMARK = (WM_USER + 79),

        TB_SETINSERTMARK = (WM_USER + 80),

        TB_INSERTMARKHITTEST = (WM_USER + 81),

        TB_MOVEBUTTON = (WM_USER + 82),

        TB_GETMAXSIZE = (WM_USER + 83),

        TB_SETEXTENDEDSTYLE = (WM_USER + 84),

        TB_GETEXTENDEDSTYLE = (WM_USER + 85),

        TB_GETPADDING = (WM_USER + 86),

        TB_SETPADDING = (WM_USER + 87),

        TB_SETINSERTMARKCOLOR = (WM_USER + 88),

        TB_GETINSERTMARKCOLOR = (WM_USER + 89),

        TB_SETCOLORSCHEME = CCM_SETCOLORSCHEME,

        TB_GETCOLORSCHEME = CCM_GETCOLORSCHEME,

        TB_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT,

        TB_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT,

        TB_MAPACCELERATORW = (WM_USER + 90),

        TB_GETBITMAPFLAGS = (WM_USER + 41),

        TB_GETBUTTONINFOW = (WM_USER + 63),

        TB_SETBUTTONINFOW = (WM_USER + 64),

        TB_GETBUTTONINFOA = (WM_USER + 65),

        TB_SETBUTTONINFOA = (WM_USER + 66),

        TB_INSERTBUTTONW = (WM_USER + 67),

        TB_ADDBUTTONSW = (WM_USER + 68),

        TB_HITTEST = (WM_USER + 69),

        TB_SETDRAWTEXTFLAGS = (WM_USER + 70),

        TB_GETSTRINGW = (WM_USER + 91),

        TB_GETSTRINGA = (WM_USER + 92),

        TB_GETMETRICS = (WM_USER + 101),

        TB_SETMETRICS = (WM_USER + 102),

        TB_SETWINDOWTHEME = CCM_SETWINDOWTHEME,

        RB_INSERTBANDA = (WM_USER + 1),

        RB_DELETEBAND = (WM_USER + 2),

        RB_GETBARINFO = (WM_USER + 3),

        RB_SETBARINFO = (WM_USER + 4),

        RB_GETBANDINFO = (WM_USER + 5),

        RB_SETBANDINFOA = (WM_USER + 6),

        RB_SETPARENT = (WM_USER + 7),

        RB_HITTEST = (WM_USER + 8),

        RB_GETRECT = (WM_USER + 9),

        RB_INSERTBANDW = (WM_USER + 10),

        RB_SETBANDINFOW = (WM_USER + 11),

        RB_GETBANDCOUNT = (WM_USER + 12),

        RB_GETROWCOUNT = (WM_USER + 13),

        RB_GETROWHEIGHT = (WM_USER + 14),

        RB_IDTOINDEX = (WM_USER + 16),

        RB_GETTOOLTIPS = (WM_USER + 17),

        RB_SETTOOLTIPS = (WM_USER + 18),

        RB_SETBKCOLOR = (WM_USER + 19),

        RB_GETBKCOLOR = (WM_USER + 20),

        RB_SETTEXTCOLOR = (WM_USER + 21),

        RB_GETTEXTCOLOR = (WM_USER + 22),

        RB_SIZETORECT = (WM_USER + 23),

        RB_SETCOLORSCHEME = CCM_SETCOLORSCHEME,

        RB_GETCOLORSCHEME = CCM_GETCOLORSCHEME,

        RB_BEGINDRAG = (WM_USER + 24),

        RB_ENDDRAG = (WM_USER + 25),

        RB_DRAGMOVE = (WM_USER + 26),

        RB_GETBARHEIGHT = (WM_USER + 27),

        RB_GETBANDINFOW = (WM_USER + 28),

        RB_GETBANDINFOA = (WM_USER + 29),

        RB_MINIMIZEBAND = (WM_USER + 30),

        RB_MAXIMIZEBAND = (WM_USER + 31),

        RB_GETDROPTARGET = (CCM_GETDROPTARGET),

        RB_GETBANDBORDERS = (WM_USER + 34),

        RB_SHOWBAND = (WM_USER + 35),

        RB_SETPALETTE = (WM_USER + 37),

        RB_GETPALETTE = (WM_USER + 38),

        RB_MOVEBAND = (WM_USER + 39),

        RB_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT,

        RB_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT,

        RB_GETBANDMARGINS = (WM_USER + 40),

        RB_SETWINDOWTHEME = CCM_SETWINDOWTHEME,

        RB_PUSHCHEVRON = (WM_USER + 43),

        TTM_ACTIVATE = (WM_USER + 1),

        TTM_SETDELAYTIME = (WM_USER + 3),

        TTM_ADDTOOLA = (WM_USER + 4),

        TTM_ADDTOOLW = (WM_USER + 50),

        TTM_DELTOOLA = (WM_USER + 5),

        TTM_DELTOOLW = (WM_USER + 51),

        TTM_NEWTOOLRECTA = (WM_USER + 6),

        TTM_NEWTOOLRECTW = (WM_USER + 52),

        TTM_RELAYEVENT = (WM_USER + 7),

        TTM_GETTOOLINFOA = (WM_USER + 8),

        TTM_GETTOOLINFOW = (WM_USER + 53),

        TTM_SETTOOLINFOA = (WM_USER + 9),

        TTM_SETTOOLINFOW = (WM_USER + 54),

        TTM_HITTESTA = (WM_USER +10),

        TTM_HITTESTW = (WM_USER +55),

        TTM_GETTEXTA = (WM_USER +11),

        TTM_GETTEXTW = (WM_USER +56),

        TTM_UPDATETIPTEXTA = (WM_USER +12),

        TTM_UPDATETIPTEXTW = (WM_USER +57),

        TTM_GETTOOLCOUNT = (WM_USER +13),

        TTM_ENUMTOOLSA = (WM_USER +14),

        TTM_ENUMTOOLSW = (WM_USER +58),

        TTM_GETCURRENTTOOLA = (WM_USER + 15),

        TTM_GETCURRENTTOOLW = (WM_USER + 59),

        TTM_WINDOWFROMPOINT = (WM_USER + 16),

        TTM_TRACKACTIVATE = (WM_USER + 17),

        TTM_TRACKPOSITION = (WM_USER + 18),

        TTM_SETTIPBKCOLOR = (WM_USER + 19),

        TTM_SETTIPTEXTCOLOR = (WM_USER + 20),

        TTM_GETDELAYTIME = (WM_USER + 21),

        TTM_GETTIPBKCOLOR = (WM_USER + 22),

        TTM_GETTIPTEXTCOLOR = (WM_USER + 23),

        TTM_SETMAXTIPWIDTH = (WM_USER + 24),

        TTM_GETMAXTIPWIDTH = (WM_USER + 25),

        TTM_SETMARGIN = (WM_USER + 26),

        TTM_GETMARGIN = (WM_USER + 27),

        TTM_POP = (WM_USER + 28),

        TTM_UPDATE = (WM_USER + 29),

        TTM_GETBUBBLESIZE = (WM_USER + 30),

        TTM_ADJUSTRECT = (WM_USER + 31),

        TTM_SETTITLEA = (WM_USER + 32),

        TTM_SETTITLEW = (WM_USER + 33),

        TTM_POPUP = (WM_USER + 34),

        TTM_GETTITLE = (WM_USER + 35),

        TTM_SETWINDOWTHEME = CCM_SETWINDOWTHEME,

        SB_SETTEXTA = (WM_USER+1),

        SB_SETTEXTW = (WM_USER+11),

        SB_GETTEXTA = (WM_USER+2),

        SB_GETTEXTW = (WM_USER+13),

        SB_GETTEXTLENGTHA = (WM_USER+3),

        SB_GETTEXTLENGTHW = (WM_USER+12),

        SB_SETPARTS = (WM_USER+4),

        SB_GETPARTS = (WM_USER+6),

        SB_GETBORDERS = (WM_USER+7),

        SB_SETMINHEIGHT = (WM_USER+8),

        SB_SIMPLE = (WM_USER+9),

        SB_GETRECT = (WM_USER+10),

        SB_ISSIMPLE = (WM_USER+14),

        SB_SETICON = (WM_USER+15),

        SB_SETTIPTEXTA = (WM_USER+16),

        SB_SETTIPTEXTW = (WM_USER+17),

        SB_GETTIPTEXTA = (WM_USER+18),

        SB_GETTIPTEXTW = (WM_USER+19),

        SB_GETICON = (WM_USER+20),

        SB_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT,

        SB_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT,

        SB_SETBKCOLOR = CCM_SETBKCOLOR,

        SB_SIMPLEID = 0x00ff,

        TBM_GETPOS = (WM_USER),

        TBM_GETRANGEMIN = (WM_USER+1),

        TBM_GETRANGEMAX = (WM_USER+2),

        TBM_GETTIC = (WM_USER+3),

        TBM_SETTIC = (WM_USER+4),

        TBM_SETPOS = (WM_USER+5),

        TBM_SETRANGE = (WM_USER+6),

        TBM_SETRANGEMIN = (WM_USER+7),

        TBM_SETRANGEMAX = (WM_USER+8),

        TBM_CLEARTICS = (WM_USER+9),

        TBM_SETSEL = (WM_USER+10),

        TBM_SETSELSTART = (WM_USER+11),

        TBM_SETSELEND = (WM_USER+12),

        TBM_GETPTICS = (WM_USER+14),

        TBM_GETTICPOS = (WM_USER+15),

        TBM_GETNUMTICS = (WM_USER+16),

        TBM_GETSELSTART = (WM_USER+17),

        TBM_GETSELEND = (WM_USER+18),

        TBM_CLEARSEL = (WM_USER+19),

        TBM_SETTICFREQ = (WM_USER+20),

        TBM_SETPAGESIZE = (WM_USER+21),

        TBM_GETPAGESIZE = (WM_USER+22),

        TBM_SETLINESIZE = (WM_USER+23),

        TBM_GETLINESIZE = (WM_USER+24),

        TBM_GETTHUMBRECT = (WM_USER+25),

        TBM_GETCHANNELRECT = (WM_USER+26),

        TBM_SETTHUMBLENGTH = (WM_USER+27),

        TBM_GETTHUMBLENGTH = (WM_USER+28),

        TBM_SETTOOLTIPS = (WM_USER+29),

        TBM_GETTOOLTIPS = (WM_USER+30),

        TBM_SETTIPSIDE = (WM_USER+31),

        TBM_SETBUDDY = (WM_USER+32),

        TBM_GETBUDDY = (WM_USER+33),

        TBM_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT,

        TBM_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT,

        DL_BEGINDRAG = (WM_USER+133),

        DL_DRAGGING = (WM_USER+134),

        DL_DROPPED = (WM_USER+135),

        DL_CANCELDRAG = (WM_USER+136),

        UDM_SETRANGE = (WM_USER+101),

        UDM_GETRANGE = (WM_USER+102),

        UDM_SETPOS = (WM_USER+103),

        UDM_GETPOS = (WM_USER+104),

        UDM_SETBUDDY = (WM_USER+105),

        UDM_GETBUDDY = (WM_USER+106),

        UDM_SETACCEL = (WM_USER+107),

        UDM_GETACCEL = (WM_USER+108),

        UDM_SETBASE = (WM_USER+109),

        UDM_GETBASE = (WM_USER+110),

        UDM_SETRANGE32 = (WM_USER+111),

        UDM_GETRANGE32 = (WM_USER+112),

        UDM_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT,

        UDM_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT,

        UDM_SETPOS32 = (WM_USER+113),

        UDM_GETPOS32 = (WM_USER+114),

        PBM_SETRANGE = (WM_USER+1),

        PBM_SETPOS = (WM_USER+2),

        PBM_DELTAPOS = (WM_USER+3),

        PBM_SETSTEP = (WM_USER+4),

        PBM_STEPIT = (WM_USER+5),

        PBM_SETRANGE32 = (WM_USER+6),

        PBM_GETRANGE = (WM_USER+7),

        PBM_GETPOS = (WM_USER+8),

        PBM_SETBARCOLOR = (WM_USER+9),

        PBM_SETBKCOLOR = CCM_SETBKCOLOR,

        HKM_SETHOTKEY = (WM_USER+1),

        HKM_GETHOTKEY = (WM_USER+2),

        HKM_SETRULES = (WM_USER+3),

        LVM_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT,

        LVM_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT,

        LVM_GETBKCOLOR = (LVM_FIRST + 0),

        LVM_SETBKCOLOR = (LVM_FIRST + 1),

        LVM_GETIMAGELIST = (LVM_FIRST + 2),

        LVM_SETIMAGELIST = (LVM_FIRST + 3),

        LVM_GETITEMCOUNT = (LVM_FIRST + 4),

        LVM_GETITEMA = (LVM_FIRST + 5),

        LVM_GETITEMW = (LVM_FIRST + 75),

        LVM_SETITEMA = (LVM_FIRST + 6),

        LVM_SETITEMW = (LVM_FIRST + 76),

        LVM_INSERTITEMA = (LVM_FIRST + 7),

        LVM_INSERTITEMW = (LVM_FIRST + 77),

        LVM_DELETEITEM = (LVM_FIRST + 8),

        LVM_DELETEALLITEMS = (LVM_FIRST + 9),

        LVM_GETCALLBACKMASK = (LVM_FIRST + 10),

        LVM_SETCALLBACKMASK = (LVM_FIRST + 11),

        LVM_FINDITEMA = (LVM_FIRST + 13),

        LVM_FINDITEMW = (LVM_FIRST + 83),

        LVM_GETITEMRECT = (LVM_FIRST + 14),

        LVM_SETITEMPOSITION = (LVM_FIRST + 15),

        LVM_GETITEMPOSITION = (LVM_FIRST + 16),

        LVM_GETSTRINGWIDTHA = (LVM_FIRST + 17),

        LVM_GETSTRINGWIDTHW = (LVM_FIRST + 87),

        LVM_HITTEST = (LVM_FIRST + 18),

        LVM_ENSUREVISIBLE = (LVM_FIRST + 19),

        LVM_SCROLL = (LVM_FIRST + 20),

        LVM_REDRAWITEMS = (LVM_FIRST + 21),

        LVM_ARRANGE = (LVM_FIRST + 22),

        LVM_EDITLABELA = (LVM_FIRST + 23),

        LVM_EDITLABELW = (LVM_FIRST + 118),

        LVM_GETEDITCONTROL = (LVM_FIRST + 24),

        LVM_GETCOLUMNA = (LVM_FIRST + 25),

        LVM_GETCOLUMNW = (LVM_FIRST + 95),

        LVM_SETCOLUMNA = (LVM_FIRST + 26),

        LVM_SETCOLUMNW = (LVM_FIRST + 96),

        LVM_INSERTCOLUMNA = (LVM_FIRST + 27),

        LVM_INSERTCOLUMNW = (LVM_FIRST + 97),

        LVM_DELETECOLUMN = (LVM_FIRST + 28),

        LVM_GETCOLUMNWIDTH = (LVM_FIRST + 29),

        LVM_SETCOLUMNWIDTH = (LVM_FIRST + 30),

        LVM_CREATEDRAGIMAGE = (LVM_FIRST + 33),

        LVM_GETVIEWRECT = (LVM_FIRST + 34),

        LVM_GETTEXTCOLOR = (LVM_FIRST + 35),

        LVM_SETTEXTCOLOR = (LVM_FIRST + 36),

        LVM_GETTEXTBKCOLOR = (LVM_FIRST + 37),

        LVM_SETTEXTBKCOLOR = (LVM_FIRST + 38),

        LVM_GETTOPINDEX = (LVM_FIRST + 39),

        LVM_GETCOUNTPERPAGE = (LVM_FIRST + 40),

        LVM_GETORIGIN = (LVM_FIRST + 41),

        LVM_UPDATE = (LVM_FIRST + 42),

        LVM_SETITEMSTATE = (LVM_FIRST + 43),

        LVM_GETITEMSTATE = (LVM_FIRST + 44),

        LVM_GETITEMTEXTA = (LVM_FIRST + 45),

        LVM_GETITEMTEXTW = (LVM_FIRST + 115),

        LVM_SETITEMTEXTA = (LVM_FIRST + 46),

        LVM_SETITEMTEXTW = (LVM_FIRST + 116),

        LVM_SETITEMCOUNT = (LVM_FIRST + 47),

        LVM_SORTITEMS = (LVM_FIRST + 48),

        LVM_SETITEMPOSITION32 = (LVM_FIRST + 49),

        LVM_GETSELECTEDCOUNT = (LVM_FIRST + 50),

        LVM_GETITEMSPACING = (LVM_FIRST + 51),

        LVM_GETISEARCHSTRINGA = (LVM_FIRST + 52),

        LVM_GETISEARCHSTRINGW = (LVM_FIRST + 117),

        LVM_SETICONSPACING = (LVM_FIRST + 53),

        LVM_SETEXTENDEDLISTVIEWSTYLE = (LVM_FIRST + 54),

        LVM_GETEXTENDEDLISTVIEWSTYLE = (LVM_FIRST + 55),

        LVM_GETSUBITEMRECT = (LVM_FIRST + 56),

        LVM_SUBITEMHITTEST = (LVM_FIRST + 57),

        LVM_SETCOLUMNORDERARRAY = (LVM_FIRST + 58),

        LVM_GETCOLUMNORDERARRAY = (LVM_FIRST + 59),

        LVM_SETHOTITEM = (LVM_FIRST + 60),

        LVM_GETHOTITEM = (LVM_FIRST + 61),

        LVM_SETHOTCURSOR = (LVM_FIRST + 62),

        LVM_GETHOTCURSOR = (LVM_FIRST + 63),

        LVM_APPROXIMATEVIEWRECT = (LVM_FIRST + 64),

        LVM_SETWORKAREAS = (LVM_FIRST + 65),

        LVM_GETWORKAREAS = (LVM_FIRST + 70),

        LVM_GETNUMBEROFWORKAREAS = (LVM_FIRST + 73),

        LVM_GETSELECTIONMARK = (LVM_FIRST + 66),

        LVM_SETSELECTIONMARK = (LVM_FIRST + 67),

        LVM_SETHOVERTIME = (LVM_FIRST + 71),

        LVM_GETHOVERTIME = (LVM_FIRST + 72),

        LVM_SETTOOLTIPS = (LVM_FIRST + 74),

        LVM_GETTOOLTIPS = (LVM_FIRST + 78),

        LVM_SORTITEMSEX = (LVM_FIRST + 81),

        LVM_SETBKIMAGEA = (LVM_FIRST + 68),

        LVM_SETBKIMAGEW = (LVM_FIRST + 138),

        LVM_GETBKIMAGEA = (LVM_FIRST + 69),

        LVM_GETBKIMAGEW = (LVM_FIRST + 139),

        LVM_SETSELECTEDCOLUMN = (LVM_FIRST + 140),

        LVM_SETTILEWIDTH = (LVM_FIRST + 141),

        LVM_SETVIEW = (LVM_FIRST + 142),

        LVM_GETVIEW = (LVM_FIRST + 143),

        LVM_INSERTGROUP = (LVM_FIRST + 145),

        LVM_SETGROUPINFO = (LVM_FIRST + 147),

        LVM_GETGROUPINFO = (LVM_FIRST + 149),

        LVM_REMOVEGROUP = (LVM_FIRST + 150),

        LVM_MOVEGROUP = (LVM_FIRST + 151),

        LVM_MOVEITEMTOGROUP = (LVM_FIRST + 154),

        LVM_SETGROUPMETRICS = (LVM_FIRST + 155),

        LVM_GETGROUPMETRICS = (LVM_FIRST + 156),

        LVM_ENABLEGROUPVIEW = (LVM_FIRST + 157),

        LVM_SORTGROUPS = (LVM_FIRST + 158),

        LVM_INSERTGROUPSORTED = (LVM_FIRST + 159),

        LVM_REMOVEALLGROUPS = (LVM_FIRST + 160),

        LVM_HASGROUP = (LVM_FIRST + 161),

        LVM_SETTILEVIEWINFO = (LVM_FIRST + 162),

        LVM_GETTILEVIEWINFO = (LVM_FIRST + 163),

        LVM_SETTILEINFO = (LVM_FIRST + 164),

        LVM_GETTILEINFO = (LVM_FIRST + 165),

        LVM_SETINSERTMARK = (LVM_FIRST + 166),

        LVM_GETINSERTMARK = (LVM_FIRST + 167),

        LVM_INSERTMARKHITTEST = (LVM_FIRST + 168),

        LVM_GETINSERTMARKRECT = (LVM_FIRST + 169),

        LVM_SETINSERTMARKCOLOR = (LVM_FIRST + 170),

        LVM_GETINSERTMARKCOLOR = (LVM_FIRST + 171),

        LVM_SETINFOTIP = (LVM_FIRST + 173),

        LVM_GETSELECTEDCOLUMN = (LVM_FIRST + 174),

        LVM_ISGROUPVIEWENABLED = (LVM_FIRST + 175),

        LVM_GETOUTLINECOLOR = (LVM_FIRST + 176),

        LVM_SETOUTLINECOLOR = (LVM_FIRST + 177),

        LVM_CANCELEDITLABEL = (LVM_FIRST + 179),

        LVM_MAPINDEXTOID = (LVM_FIRST + 180),

        LVM_MAPIDTOINDEX = (LVM_FIRST + 181),

        TVM_INSERTITEMA = (TV_FIRST + 0),

        TVM_INSERTITEMW = (TV_FIRST + 50),

        TVM_DELETEITEM = (TV_FIRST + 1),

        TVM_EXPAND = (TV_FIRST + 2),

        TVM_GETITEMRECT = (TV_FIRST + 4),

        TVM_GETCOUNT = (TV_FIRST + 5),

        TVM_GETINDENT = (TV_FIRST + 6),

        TVM_SETINDENT = (TV_FIRST + 7),

        TVM_GETIMAGELIST = (TV_FIRST + 8),

        TVM_SETIMAGELIST = (TV_FIRST + 9),

        TVM_GETNEXTITEM = (TV_FIRST + 10),

        TVM_SELECTITEM = (TV_FIRST + 11),

        TVM_GETITEMA = (TV_FIRST + 12),

        TVM_GETITEMW = (TV_FIRST + 62),

        TVM_SETITEMA = (TV_FIRST + 13),

        TVM_SETITEMW = (TV_FIRST + 63),

        TVM_EDITLABELA = (TV_FIRST + 14),

        TVM_EDITLABELW = (TV_FIRST + 65),

        TVM_GETEDITCONTROL = (TV_FIRST + 15),

        TVM_GETVISIBLECOUNT = (TV_FIRST + 16),

        TVM_HITTEST = (TV_FIRST + 17),

        TVM_CREATEDRAGIMAGE = (TV_FIRST + 18),

        TVM_SORTCHILDREN = (TV_FIRST + 19),

        TVM_ENSUREVISIBLE = (TV_FIRST + 20),

        TVM_SORTCHILDRENCB = (TV_FIRST + 21),

        TVM_ENDEDITLABELNOW = (TV_FIRST + 22),

        TVM_GETISEARCHSTRINGA = (TV_FIRST + 23),

        TVM_GETISEARCHSTRINGW = (TV_FIRST + 64),

        TVM_SETTOOLTIPS = (TV_FIRST + 24),

        TVM_GETTOOLTIPS = (TV_FIRST + 25),

        TVM_SETINSERTMARK = (TV_FIRST + 26),

        TVM_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT,

        TVM_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT,

        TVM_SETITEMHEIGHT = (TV_FIRST + 27),

        TVM_GETITEMHEIGHT = (TV_FIRST + 28),

        TVM_SETBKCOLOR = (TV_FIRST + 29),

        TVM_SETTEXTCOLOR = (TV_FIRST + 30),

        TVM_GETBKCOLOR = (TV_FIRST + 31),

        TVM_GETTEXTCOLOR = (TV_FIRST + 32),

        TVM_SETSCROLLTIME = (TV_FIRST + 33),

        TVM_GETSCROLLTIME = (TV_FIRST + 34),

        TVM_SETINSERTMARKCOLOR = (TV_FIRST + 37),

        TVM_GETINSERTMARKCOLOR = (TV_FIRST + 38),

        TVM_GETITEMSTATE = (TV_FIRST + 39),

        TVM_SETLINECOLOR = (TV_FIRST + 40),

        TVM_GETLINECOLOR = (TV_FIRST + 41),

        TVM_MAPACCIDTOHTREEITEM = (TV_FIRST + 42),

        TVM_MAPHTREEITEMTOACCID = (TV_FIRST + 43),

        CBEM_INSERTITEMA = (WM_USER + 1),

        CBEM_SETIMAGELIST = (WM_USER + 2),

        CBEM_GETIMAGELIST = (WM_USER + 3),

        CBEM_GETITEMA = (WM_USER + 4),

        CBEM_SETITEMA = (WM_USER + 5),

        CBEM_DELETEITEM = CB_DELETESTRING,

        CBEM_GETCOMBOCONTROL = (WM_USER + 6),

        CBEM_GETEDITCONTROL = (WM_USER + 7),

        CBEM_SETEXTENDEDSTYLE = (WM_USER + 14),

        CBEM_GETEXTENDEDSTYLE = (WM_USER + 9),

        CBEM_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT,

        CBEM_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT,

        CBEM_SETEXSTYLE = (WM_USER + 8),

        CBEM_GETEXSTYLE = (WM_USER + 9),

        CBEM_HASEDITCHANGED = (WM_USER + 10),

        CBEM_INSERTITEMW = (WM_USER + 11),

        CBEM_SETITEMW = (WM_USER + 12),

        CBEM_GETITEMW = (WM_USER + 13),

        TCM_GETIMAGELIST = (TCM_FIRST + 2),

        TCM_SETIMAGELIST = (TCM_FIRST + 3),

        TCM_GETITEMCOUNT = (TCM_FIRST + 4),

        TCM_GETITEMA = (TCM_FIRST + 5),

        TCM_GETITEMW = (TCM_FIRST + 60),

        TCM_SETITEMA = (TCM_FIRST + 6),

        TCM_SETITEMW = (TCM_FIRST + 61),

        TCM_INSERTITEMA = (TCM_FIRST + 7),

        TCM_INSERTITEMW = (TCM_FIRST + 62),

        TCM_DELETEITEM = (TCM_FIRST + 8),

        TCM_DELETEALLITEMS = (TCM_FIRST + 9),

        TCM_GETITEMRECT = (TCM_FIRST + 10),

        TCM_GETCURSEL = (TCM_FIRST + 11),

        TCM_SETCURSEL = (TCM_FIRST + 12),

        TCM_HITTEST = (TCM_FIRST + 13),

        TCM_SETITEMEXTRA = (TCM_FIRST + 14),

        TCM_ADJUSTRECT = (TCM_FIRST + 40),

        TCM_SETITEMSIZE = (TCM_FIRST + 41),

        TCM_REMOVEIMAGE = (TCM_FIRST + 42),

        TCM_SETPADDING = (TCM_FIRST + 43),

        TCM_GETROWCOUNT = (TCM_FIRST + 44),

        TCM_GETTOOLTIPS = (TCM_FIRST + 45),

        TCM_SETTOOLTIPS = (TCM_FIRST + 46),

        TCM_GETCURFOCUS = (TCM_FIRST + 47),

        TCM_SETCURFOCUS = (TCM_FIRST + 48),

        TCM_SETMINTABWIDTH = (TCM_FIRST + 49),

        TCM_DESELECTALL = (TCM_FIRST + 50),

        TCM_HIGHLIGHTITEM = (TCM_FIRST + 51),

        TCM_SETEXTENDEDSTYLE = (TCM_FIRST + 52),

        TCM_GETEXTENDEDSTYLE = (TCM_FIRST + 53),

        TCM_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT,

        TCM_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT,

        ACM_OPENA = (WM_USER+100),

        ACM_OPENW = (WM_USER+103),

        ACM_PLAY = (WM_USER+101),

        ACM_STOP = (WM_USER+102),

        MCM_FIRST = 0x1000,

        MCM_GETCURSEL = (MCM_FIRST + 1),

        MCM_SETCURSEL = (MCM_FIRST + 2),

        MCM_GETMAXSELCOUNT = (MCM_FIRST + 3),

        MCM_SETMAXSELCOUNT = (MCM_FIRST + 4),

        MCM_GETSELRANGE = (MCM_FIRST + 5),

        MCM_SETSELRANGE = (MCM_FIRST + 6),

        MCM_GETMONTHRANGE = (MCM_FIRST + 7),

        MCM_SETDAYSTATE = (MCM_FIRST + 8),

        MCM_GETMINREQRECT = (MCM_FIRST + 9),

        MCM_SETCOLOR = (MCM_FIRST + 10),

        MCM_GETCOLOR = (MCM_FIRST + 11),

        MCM_SETTODAY = (MCM_FIRST + 12),

        MCM_GETTODAY = (MCM_FIRST + 13),

        MCM_HITTEST = (MCM_FIRST + 14),

        MCM_SETFIRSTDAYOFWEEK = (MCM_FIRST + 15),

        MCM_GETFIRSTDAYOFWEEK = (MCM_FIRST + 16),

        MCM_GETRANGE = (MCM_FIRST + 17),

        MCM_SETRANGE = (MCM_FIRST + 18),

        MCM_GETMONTHDELTA = (MCM_FIRST + 19),

        MCM_SETMONTHDELTA = (MCM_FIRST + 20),

        MCM_GETMAXTODAYWIDTH = (MCM_FIRST + 21),

        MCM_SETUNICODEFORMAT = CCM_SETUNICODEFORMAT,

        MCM_GETUNICODEFORMAT = CCM_GETUNICODEFORMAT,

        DTM_FIRST = 0x1000,

        DTM_GETSYSTEMTIME = (DTM_FIRST + 1),

        DTM_SETSYSTEMTIME = (DTM_FIRST + 2),

        DTM_GETRANGE = (DTM_FIRST + 3),

        DTM_SETRANGE = (DTM_FIRST + 4),

        DTM_SETFORMATA = (DTM_FIRST + 5),

        DTM_SETFORMATW = (DTM_FIRST + 50),

        DTM_SETMCCOLOR = (DTM_FIRST + 6),

        DTM_GETMCCOLOR = (DTM_FIRST + 7),

        DTM_GETMONTHCAL = (DTM_FIRST + 8),

        DTM_SETMCFONT = (DTM_FIRST + 9),

        DTM_GETMCFONT = (DTM_FIRST + 10),

        PGM_SETCHILD = (PGM_FIRST + 1),

        PGM_RECALCSIZE = (PGM_FIRST + 2),

        PGM_FORWARDMOUSE = (PGM_FIRST + 3),

        PGM_SETBKCOLOR = (PGM_FIRST + 4),

        PGM_GETBKCOLOR = (PGM_FIRST + 5),

        PGM_SETBORDER = (PGM_FIRST + 6),

        PGM_GETBORDER = (PGM_FIRST + 7),

        PGM_SETPOS = (PGM_FIRST + 8),

        PGM_GETPOS = (PGM_FIRST + 9),

        PGM_SETBUTTONSIZE = (PGM_FIRST + 10),

        PGM_GETBUTTONSIZE = (PGM_FIRST + 11),

        PGM_GETBUTTONSTATE = (PGM_FIRST + 12),

        PGM_GETDROPTARGET = CCM_GETDROPTARGET,

        BCM_GETIDEALSIZE = (BCM_FIRST + 0x0001),

        BCM_SETIMAGELIST = (BCM_FIRST + 0x0002),

        BCM_GETIMAGELIST = (BCM_FIRST + 0x0003),

        BCM_SETTEXTMARGIN = (BCM_FIRST + 0x0004),

        BCM_GETTEXTMARGIN = (BCM_FIRST + 0x0005),

        EM_SETCUEBANNER     = (ECM_FIRST + 1),

        EM_GETCUEBANNER     = (ECM_FIRST + 2),

        EM_SHOWBALLOONTIP = (ECM_FIRST + 3),

        EM_HIDEBALLOONTIP = (ECM_FIRST + 4),

        CB_SETMINVISIBLE = (CBM_FIRST + 1),

        CB_GETMINVISIBLE = (CBM_FIRST + 2),

        LM_HITTEST = (WM_USER + 0x300),

        LM_GETIDEALHEIGHT = (WM_USER + 0x301),

        LM_SETITEM = (WM_USER + 0x302),

        LM_GETITEM = (WM_USER + 0x303)

Posted by 나비:D
:

출처 : http://cafe.naver.com/hitommy.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=330

  1. DOS의 CHOICE 명령 대용으로 Y/N 선택 묻기 방법

    to batch ... 3 days ago
  2. 배치파일에서 줄 띄우기; Batch File 빈줄 넣기 방법; empty line

    to batch ... 5 days ago
  3. CMD 콘솔 색깔 변경하는 명령어; 도스창 명령프롬프트 글자색 바꾸기; DOS Color

    to windows batch ... on oct 27
  4. 영어 도스 실행 방법; 영문 DOS 사용하기; Eng

    to batch ... on oct 15
  5. 현재 위치에서 도스창 열기, 현재 폴더에서 명령프롬프트(CMD) 실행하는 법

    to windows batch ... on oct 13
  6. BAT 메세지 출력, 배치파일 메시지 프린트 방법; Batch File Message

    to batch ... on oct 06
  7. 디렉터리가 비어 있지 않습니다, 라는 에러 해결 방법은? The directory is not empty

    to batch ... on sept 30
  8. 도스 디렉토리 바꾸기 명령, DOS에서 드라이브, 폴더 이동 명령어; Change Directory 사용법

    to batch ... on sept 30
  9. 배치파일로 디렉토리 생성 명령어, 폴더 만들기 방법; BAT Make Directory, Folder

    to batch ... on sept 25
  10. AUTOEXEC.BAT CONFIG.SYS 파일 작성 방법 예제, 도스(MS-DOS)용 고전게임

    to games batch ... on sept 16
  11. PKZIP 폴더 압축 옵션, 디렉토리까지 압축하기 방법; Folder Directory

    to batch ... on sept 14
  12. 도스창 CMD 에서 파일명 변경 방법, 파일, 폴더 이름 바꾸기 명령; Rename File

    to batch ... on sept 11
  13. 베이직 언어의 종류와 차이점; BASIC

    to office batch ... on sept 06
  14. 도스에서 텍스트 파일 보기 명령어; DOS Text File Viewer

    to windows batch ... on sept 06
  15. BAT 파일 엔터 키 치는 명령은? 배치파일에서 Enter Key 로 빈줄 출력 명령어

    to batch ... on sept 01
  16. Find 파일 속성, 속성으로 파일 찾기 명령어; Find File Attribute

    to batch ... on aug 31
  17. 배치파일에서 파일 행번호, 줄번호 붙이기; Batch File, Print Line Number

    to batch ... on aug 30
  18. BAT 환경변수 사용 방법, 배치파일에서 환경변수; ENV

    to batch ... on aug 30
  19. 파일에 출력하는 배치 파일 작성법; BAT으로 Text File 만들기

    to batch ... on aug 29
  20. 배치파일 함수 구현, BAT에서 GOSUB 문 서브루틴, 고급 BATCH 테크닉

    to batch ... on aug 28
  21. 배치파일 문자열 함수는? 스트링 추출 출력 방법; Batch String

    to batch ... on aug 28
  22. DOS 명령어 / 모든 도스 명령 목록; MS-DOS Command

    to batch ... on aug 28
  23. BAT 실행창, 배치파일 실행하는 창은? Batch Window

    to batch windows ... on aug 25
  24. 24비트 32 bit 자동 전환, 구글어스 실행 배치파일; Google Earth BAT

    to earth batch ... on aug 24
  25. 숫자 무작위 생성; 윈도우 도스창에서; DOS 랜덤 Random

    to batch windows ... on aug 19
  26. 메모장으로 BAT 파일 만들기, 배치파일 작성하기; Windows Notepad Batch File

    to batch windows ... on aug 17
  27. BAK 파일 삭제 배치 파일; 백업파일 지우기 BAT

    to batch windows ... on aug 17
  28. 4DOS 무료로 전환, 16비트 MS-DOS용 포도스 사도스

    to batch software ... on aug 11
  29. chkdsk 하는 법; 체크디스크 명령으로 하드 검사 하는법

    to windows batch ... on aug 03
  30. 도스 TREE 명령어 파일로 저장하기, DOS 명령 결과, 텍스트파일로 저장하는 법

    to batch ... on aug 02
  31. 배치파일에서 return 구현 방법; BAT 리턴 반환 C언어처럼

    to batch ... on aug 01
  32. 도스 DOS 명령, 파일 속성 바꾸기 명령어; File Attribute ATTRIB

    to batch windows ... on july 31
  33. 배치파일 에디터로 좋은 것은? BAT File 편집기 Editor 종류

    to batch ... on july 28
  34. 배치파일 만들기 기초; BAT 파일 작성법

    to batch windows ... on july 22
  35. DOS / Windows Batch 파일의 주석 처리 방법; 주석문 Remarks

    to batch windows ... on july 12
  36. 메세지박스 만들기 예제; Msg Box

    to batch ... on july 10
  37. VBS, 비베 스크립트로 메모장 실행하기 소스; Run Notepad

    to batch ... on july 05
  38. 배치파일에서 시스템경로 구하기; 패스 환경변수 Path Batch File

    to batch ... on june 24
  39. 배치 파일에서, 숫자 계산하기, set 명령으로 더하기 빼기; Batch File Calc

    to batch ... on may 31
  40. 배치파일 무한루프 구현, 루프 탈출, 빠져 나오기 예제; Batch File Infinity Loop

    to batch ... on may 31
  41. 파일 개수 세기 도스 명령어; File Counter DOS Command

    to batch ... on march 23
  42. 배치파일 BAT] 현재 년월일 시분초 구하기, 한국식 시간 문자열; YYYY-MM-DD hh:mm:ss

    to batch ... on march 17
  43. 현재 시간으로 된 파일명 만들기 BAT 배치 파일; Time To File Name

    to batch ... saved by 2 other people ... on march 15
  44. 윈도우용 MD5SUM, SHA1SUM 윈도우 버전 다운로드; md5sum.exe sha1sum.exe Download

    to linux batch software ... on march 14
  45. 오늘 날짜로 된 디렉토리명, 폴더명 만들기 BAT 배치 파일; Date To Directory Name

    to batch ... saved by 1 other person ... on march 14
  46. CMD 아스키 코드표 보기; 도스창에서 아스키코드(ASCII Code) 출력하는 법, 명령

    to batch ... on march 13
  47. 날짜 BAT, 현재 시간 출력 배치파일; Batch File

    to batch ... on march 13
  48. Excel/엑셀 VBA] 세제곱근, 네제곱근, 거듭제곱근 구하기 함수, 기호; Cube Root

    to office batch ... on march 11
  49. Excel/엑셀 VBA] 제곱 기호, 함수 거듭제곱(세제곱,네제곱), 몇 승 구하기 방법; Power, Pow

    to office batch ... on march 11
  50. 도스용 윈집(WinZip) 실행 배치 파일; DOS WZZIP-WZUNZIP Batch File

    to batch ... on feb 18
  51. 도스(DOS)에서, ZIP 파일 압축하기, 압축 풀기 프로그램, 옵션; Add Extract Zip File

    to batch ... on feb 18
  52. 도스용 ZIP 프로그램; DOS윈집 다운로드,사용법; WinZip Command Line Support Add-On

    to batch windows software ... on feb 18
  53. 배치 파일 실행 결과 보기 명령어; Batch File Result View Command

    to batch windows ... on feb 12
  54. 배치 파일] 여러 파일 이름 한꺼번에 바꾸기; 파일명 일괄 변경; Batch File Rename

    to batch windows ... saved by 1 other person ... on feb 03
  55. 배치 파일 안에서, EXE 파일 실행 법; Batch File에서 실행파일 호출

    to batch ... saved by 1 other person ... on jan 26
  56. CMD 확장자 파일 만들기, CMD.EXE로, 파일(File) 만들기/저장(Save)하기

    to batch windows ... on jan 03
  57. XCOPY.EXE 프로그램/명령어 다운로드(Download) 받는 곳은? : 크로스 카피/엑스 카피

    to windows batch ... on dec 31
  58. 윈도우용 wget.exe 사용법; 명령행 다운로드 프로그램; wget Command for MS-Windows

    to linux batch ... on dec 28
  59. 도스(DOS)용 RAR 로 압축하기, 파일 압축 풀기; 텍스트 모드 압축

    to software batch ... on dec 27
  60. 도스(DOS, CMD)창, 영문 Code Page (코드 페이지)로 변경하는 명령어: CHCP

    to batch windows ... on dec 26
  61. RAR 도스 창(DOS)/명령프롬프트/텍스트 모드; WinRAR(윈라) 콘솔 버전; RAR.EXE

    to software batch ... on dec 26
  62. 배치파일] 엔터 키/줄바꿈/개행문자 넣기; Batch File Enter Key

    to batch ... on dec 26
  63. 도스(DOS)에서, Program Files 폴더 지정/입력하는 법은?

    to batch windows ... on dec 23
  64. 비베-VBA-VBS-VB] sqrt 제곱근/루트 근사값 함수 사용법은? Sqr()

    to office batch ... on dec 20
  65. 윈도우] 시스템 파일 복사하는 명령어. 히든파일 카피 명령; Copy Command, System Hidden File

    to batch windows ... on dec 18
  66. 도스에서 빠져 나오는 방법, 도스창 종료 명령어; DOS Exit

    to windows batch ... on dec 17
  67. VBA-VBS-비주얼 베이직에서, 특수문자 사용법; Visual Basic Special Char

    to office batch ... on dec 16
  68. 도스(DOS)에서, 연월일(년월일)/시분초, 현재 날짜 구하기; get Date Time

    to batch windows ... on dec 15
  69. 도스로 빠져 나가기, 윈도우에서 도스로; How To Exit To DOS

    to windows batch games ... on dec 15
  70. 배치파일] 랜덤 숫자 발생, 1~10 난수 생성; Random Number Batch File

    to batch ... on dec 15
  71. 배치파일] 요일 출력, 오늘 현재 요일만 구하기; Get DAY OF THE WEEK String

    to batch ... on dec 14
  72. 배치파일] 요일 삭제, 날짜 문자열에서 요일 지우기; Remove DAY OF THE WEEK from Date String

    to batch ... on dec 14
  73. 배치파일/Batch File] args / argc, argv 파라미터(인수; 매개변수) 사용 방법; DOS BAT

    to batch ... on dec 13
  74. 텍스트 브라우저, 리눅스/윈도우용; Text Browse LYNX

    to linux batch software ... on dec 13
  75. 도스박스/도스창 전체 화면 모드 핫키; DOSBox, DOS Full-Screen Hot Key

    to games windows batch ... on dec 13
  76. 배치파일 텍스트 출력 방법. 글자,문자열 쓰기, 프린트 함수; Batch File Print String

    to batch ... on dec 12
  77. 배치파일 예약어, 키워드 목록; Batch File Keyword List

    to batch ... on dec 12
  78. 윈도우/도스] 현재 디렉토리 환경변수, Current Directory (CWD) Environment Variable

    to batch ... on dec 08
  79. 윈도우 SORT 명령, 숫자 크기순 정렬(소팅) 문제 해결, Perl(펄)로

    to windows perl batch ... on dec 07
  80. 비베 VB, VBA] 난수 발생 함수; 랜덤 숫자 생성 Random Number Generator

    to office batch ... on dec 05
  81. 환경변수 저장 하는 법; 윈도우2000 / XP 환경 변수 저장법; Set Environment Variable

    to windows batch ... on dec 05
  82. 윈도우에서 파이썬(python.exe) 실행 배치파일; PYTHON.BAT

    to python batch ... on dec 04
  83. 탐색기 폴더에서, 도스창 실행 레지스트리: '여기에 명령 프롬프트' Command Line Here Registry

  84. 비베(VB, VBA, VBS)에서 엔터키(Enter Key) 표현; 줄바꿈 문자 넣기

    to office batch ... on nov 30
  85. 윈도우] 텍스트 파일 합치기 명령어; Text File (.TXT) 문서 병합 방법; TXT Merge DOS

    to batch editor ... on nov 30
  86. 배치파일] 윈도우 환경변수를 echo 로 출력 하는 법; PRINT Environment Variable DOS

    to batch ... on nov 29
  87. 배치파일] %1 %2 %3 퍼센트 일,이,삼 기호의 의미; DOS BAT Argument

    to batch ... on nov 29
  88. 도스용 V3.EXE 실행 배치파일; 도스창에서 백신III 실행 DOS BAT

    to security batch ... on nov 24
  89. 윈도우] BAT 파일 실행 하는 법; MS-DOS 배치 파일 실행법

    to batch ... on nov 21
  90. DOS 배치파일] IF ELSE 문 사용법 예제; 도스 BAT 강좌

    to batch ... on nov 21
  91. 배치파일(.BAT) IF 조건문 사용법 기초 강좌; DOS Batch File IF

    to batch ... on nov 18
  92. VBS] 메시지 박스 자동 닫기, 메세지 상자 자동으로 없애기/끄기; MsgBox Popup Auto Close

    to batch ... on nov 18
  93. Java/자바] 소스 컴파일 + 실행하기, 자동 배치파일(BAT)

    to java batch z.cool ... on nov 15
  94. DOS 배치파일] 다른 배치 파일로 GOTO 명령; 다른 파일 라벨로 이동 BAT

    to batch ... on nov 15
  95. 배치파일(.BAT)로, 파일 출력, 텍스트 파일(Text File) 만드는 방법

    to batch ... on nov 14
  96. Excel/엑셀] MsgBox, Yes No Cancel 버튼 대화상자 만든 후, 결과 값 처리

    to office batch ... on nov 14
  97. 비베-VBS-VBA-QBasic 주석 기호; 코멘트 Comment, Remark

    to office batch ... on nov 09
  98. 배치파일] 옵션 문자열 얻기, 실행시 매개변수 활용 DOS-NT Batch File Option

    to batch ... on nov 08
  99. 배치파일] 사용자 문자열 입력받기, 입력을 변수에 저장: DOS-NT Batch File Input String

    to batch ... on nov 08
  100. 비베-VBS-VBA] 문자열 합치기; 여러개의 문자열 하나로 연결/병합; Merge String

  101. DOS/도스창/배치파일] 파일 복사 명령어 사용법: File Copy Command

    to batch windows ... on nov 07
  102. 도스 도스창] 텍스트 파일 읽기 명령어, 보기 명령; DOS Text File View Command

    to batch windows ... on nov 07
  103. 윈도우 환경변수 복사하여 파일로 저장/만들기: Windows Environment Variable To File

    to windows batch ... on nov 06
  104. 배치파일, 도스(DOS)에서 파일 삭제, 디렉토리 지우기 명령어; Delete File

    to batch windows ... on oct 30, 2006
  105. 배치 파일] 변수에 현재 시간/날짜 넣기; 날짜/시간 출력, DATE TIME DOS BATCH

    to batch ... on oct 26, 2006
  106. 윈도우] VBS, VBScript 실행하는 법: 비베 스크립트 실행법

    to batch windows ... on oct 23, 2006
  107. 이진파일을 텍스트파일로 변환, 바이너리를 아스키로, Convert Binary File to Text File

    to editor linux perl batch ... saved by 1 other person ... on oct 23, 2006
  108. 도스/도스창(cmd.exe)용 실행파일/명령어 만드는, 언어/프로그램은? Creating New Commands

    to cpp batch windows ... on oct 21, 2006
  109. 반복되는 명령 실행: 윈도우 도스창 / 리눅스 - Repeat Commands

    to batch linux ... on oct 19, 2006
  110. 도스 명령] 하위 디렉토리까지 복사, Copy 디렉토리: XCOPY, DOS 배치 파일

    to batch windows ... on oct 19, 2006
  111. 윈도우] 파일 찾기 명령, 도스창에서 디렉토리 찾기, File Find Command

    to batch windows ... on oct 18, 2006
  112. 도스.BAT] 경로(Path) 알아내기/ 패스 문자열 얻어 오기: DOS 배치 파일

    to batch ... on oct 17, 2006
  113. 배치파일] 현재 폴더, 현재 디렉토리 의미하는 특수 문자] DOS Batch File, Current Directory

    to batch ... on oct 12, 2006
  114. C언어] cl.exe: 소스 파일 여러개 한꺼번에 컴파일하는 배치파일: Multiple Source Files Compile at Once

    to cpp batch ... on oct 09, 2006
  115. 윈도우] 리눅스 히든파일명으로 리네임, 파일명 앞에 마침표(.)넣기: Rename Linux Hidden File, Windows

    to windows linux batch ... on oct 08, 2006
  116. VBScript/비베] MsgBox 줄바꿈(행갈이) 방법, 멀티라인 메시지: Visual Basic, VBA

    to batch office ... on oct 05, 2006
  117. 도스 화면에, 글자 출력(프린트) 명령어는? - DOS Bat Print String

    to batch ... on oct 01, 2006
  118. 배치파일] FOR문으로, 텍스트 파일 행 처리 - 도스 DOS Bat File 강좌

    to batch ... on sept 28, 2006
  119. 배치파일] FOR 문 예제. for in do 사용법 - 도스 DOS Bat File 강좌

    to batch ... on sept 28, 2006
  120. VBS 팁] IE에서 여러 사이트 동시에 열기, 비베 스크립트 (VBScript) 로

    to batch windows ... on sept 27, 2006
  121. 배치파일] 도스창 닫기 명령 / 명령프롬프트창 종료 명령어 - .BAT DOS Batch File

    to batch windows ... on sept 26, 2006
  122. 윈도우 도스창에서 정규식 사용법 - Windows XP regex FINDSTR

    to batch regex ... on sept 25, 2006
  123. 윈도우] SORT 명령 사용법, 문자열/텍스트파일 정렬(소팅)하기 - Windows XP

    to batch windows ... on sept 21, 2006
  124. 배치파일] 탈출코드(에러레벨;반환값) 강제로 설정하기 - ERRORLEVEL, Exit Code, Batch File

    to batch cpp perl ... on sept 13, 2006
  125. 자바 팁] 자바(Java)컴파일과 실행을 한꺼번에 하는 명령, 윈도우에서 - Java Tip: Quick Compile

    to java batch ... on sept 10, 2006
  126. 배치파일] Yes / No 선택 묻기, 도스의 CHOICE 명령 대용, 사용자 입력 받기 - DOS-Windows Batch File

    to batch ... on sept 07, 2006
  127. [QnA] 도스창에서, 파일 이름의 빈 칸은 어떻게 입력합니까? - LFN, Long File Name

    to windows batch ... on sept 03, 2006
  128. 윈도우XP] 도스창 실행 / 도스 프롬프트 있는 곳 - Windows DOS Prompt

    to windows batch ... on sept 01, 2006
  129. 배치파일] BAT파일 안에서, 다른 BAT파일 실행/호출 - Batch File - 일괄 파일

    to batch ... on sept 01, 2006
  130. 윈도우XP] 기존의 패스(Path) 환경변수에, 새 경로(디렉토리; 폴더) 추가하는 법

    to windows batch ... on aug 28, 2006
  131. 도스창(명령프롬프트창) 제목줄(타이틀) 변경하는 도스 명령 - TITLE

    to batch ... on aug 26, 2006
  132. 배치파일에서, 문자열 비교 판단 / 문자열이 동일한지 다른지 - Compare Strings in Batch File

    to batch ... on aug 23, 2006
  133. 도스(DOS) 배치파일 명령어 목록

    to batch windows ... on aug 21, 2006
  134. 비베/VBScript] Chr() / Asc() 함수. MsgBox 에서, Chr(13) 함수의 의미 - VBS

    to batch office ... on aug 19, 2006
  135. 도스 화면, 잠시 정지시키는 키는? 도스창 스크롤 일시 중지시키는 키는? - DOS Pause Break Key

    to windows batch ... on aug 16, 2006
  136. 디스크 라벨(볼륨 레이블) 변경하는 법 - LABEL - VOL

    to windows batch ... on aug 13, 2006
  137. '환경변수'란 무엇인가요? 환경변수 변경/추가/삭제하는 법은? - Environment Variable

    to windows batch ... on aug 13, 2006
  138. 화면 출력 일시 정지시키는 명령어는? 도스창(윈도우 명령프롬프트)/배치파일에서 - pause

    to batch windows ... on aug 12, 2006
  139. 화면 글자 모두 지우는 명령어는? 도스창(윈도 명령프롬프트)/배치파일에서 - cls

    to batch windows ... on aug 12, 2006
  140. [QnA] 윈도우 .bat 파일은 무엇인가요? 배치 파일 (Batch File) 이란?

    to batch windows ... on aug 12, 2006
  141. 도스 명령에서, 백슬래쉬(\, ₩)와 슬래쉬(/) 차이점은? - 리눅스에서는? - Back Slash [QnA]

    to windows batch linux ... on aug 10, 2006
  142. [grep.exe] 유닉스/리눅스의 grep 을 윈도우에서 사용하기: 문자열 찾기

    to linux batch software ... on aug 10, 2006
  143. VBS(VBScript)의 PRINT 함수는? 문자열 출력은?

    to batch ... on aug 06, 2006
  144. 도스창 한글/영문으로 변경 방법: 명령 프롬프트 코드 페이지 전환 - CHCP, Code Page

    to windows batch ... on aug 05, 2006
  145. 배치 파일에서의 변수 사용 [배치 파일 작성법] - DOS Batch Variable

    to batch windows ... on aug 01, 2006
  146. 배치파일 종료시 변수 자동으로 지우기, 변수 충돌 방지, 변수 지역화: SETLOCAL / ENDLOCAL

    to batch windows ... on aug 01, 2006
  147. [배치 파일] 윈도의 .cmd 확장자를 가진 파일에 대해

    to batch windows ... on july 29, 2006
  148. [배치 파일 팁] echo문 행갈이 / 빈 줄 넣기/ 한 줄 띄어쓰기: Batch File Tip

    to batch windows ... on july 29, 2006
  149. [윈도우2000/XP] 탭(Tab)키로, 파일명 자동완성 - 명령 프롬프트 - File/Directory Name Auto-Completion

    to windows batch ... on july 28, 2006
  150. [배치 파일] '컴퓨터 이름' 알아내기 / 출력하기: Get Computer Name

    to batch windows ... on july 27, 2006
  151. [VBS] 몇 초 후에, Popup, MsgBox 대화상자 저절로 사라지게 - VBScript

    to batch windows ... on july 26, 2006
  152. 윈도우 XP에서, 도스로 가려면? 도스창이 있는 곳은? [QnA]

    to windows batch games ... on july 25, 2006
  153. [윈도우용 grep] find 보다 더 강력한 findstr 명령

    to windows batch ... on july 24, 2006
  154. [윈도우] 공백이 들어간 폴더명/파일명의 파일 실행하기 - Windows

    to windows batch ... on july 24, 2006
  155. 배치 파일(Batch File), 주석문/주석 처리 방법; 코멘트,설명 문 달기; Comment

    to batch windows ... on july 24, 2006
  156. [배치 파일] 프로그램 실행의 성공 여부를 Error Level 로 확인/판단하기: ERRORLEVEL

    to batch ... on july 15, 2006
  157. [리눅스/Cygwin] 프로그램 실행이 안돼요. 배치 파일(Batch File) 실행법은?

    to linux batch ... on july 13, 2006
  158. [QnA] 도스창이 그냥 닫혀 버립니다. 안 닫히게 하는 법은? pause 명령으로, 화면 정지시키기

    to windows batch ... on july 07, 2006
  159. 도스창 화면 저장 / 명령프롬프트(콘솔 창) 결과를 파일로 저장하는 방법

    to windows batch ... on july 07, 2006
  160. 재지향(Redirection)이란? / 파이핑(Piping)이란? - [도스창/명령 프롬프트 커맨드 라인/리눅스 셀]

    to batch linux perl windows ... on july 07, 2006
  161. 리눅스 명령어를 윈도우에서 사용하기; 시그윈(Cygwin) 없이 Win32로; GnuWin32

    to linux windows software batch ... on july 06, 2006
  162. command.com / cmd.exe 에 내장되어 있지 않아 별도의 파일이 있어야 실행되는 명령어는?

    to windows batch ... on june 27, 2006
  163. [배치파일 강좌] 배치파일 만드는 법 / .BAT 파일; 일괄 파일(Batch File)이란?

    to batch windows ... saved by 1 other person ... on june 16, 2006
  164. [배치파일 강좌] GOTO 명령 / 라벨(레이블; Label)에 대해서

    to batch ... on june 16, 2006
  165. 윈도우 도스창에서의, 파일 비교 명령은? ; 텍스트 파일 / 이진 파일 비교

    to windows batch editor ... on june 15, 2006
  166. 도스(DOS) 환경변수 보기 [컴퓨터 초보자를 위한 강좌]

    to windows batch ... saved by 1 other person ... on june 13, 2006
  167. [배치파일:도스/윈도우] echo 명령 사용법 / echo (에코) 란?

    to batch ... on june 12, 2006
  168. 윈도우에서 배치파일(Batch File) 실행하기 [컴퓨터 초보자를 위한 강좌]

    to batch windows ... on june 10, 2006
  169. [VBS-VBScript] 'Exec 메서드'로, 외부 배치파일(.bat / Batch File)이 실행되지 않아요 [QnA]

    to batch ... on june 10, 2006
  170. [VBS-VBScript] 외부 프로그램 실행 함수 / 문서 열기 함수는? : Run 메서드

    to batch ... on june 10, 2006
  171. 비주얼베이직에서, 큰따옴표/작은따옴표 출력 [VB/VBS/VBScript/VBA]

    to batch office ... on june 08, 2006
  172. 모든 '도스 명령' 목록 보기, 윈도우2000 윈도우XP 에서

    to windows batch ... on june 06, 2006
  173. [QnA] 2개 이상의 도스 명령어를 한꺼번에 실행하는 법은?

    to windows batch ... on june 03, 2006
  174. 배치 파일에서, PC스피커로, 비프음(Beep; 삑 하는 소리) 내기

    to batch ... on june 01, 2006
  175. [배치 파일] echo 명령에서, 쌍따옴표, 꺾은 괄호(부등호) 등 특수문자 표현하기

    to batch ... on may 31, 2006
  176. 배치 파일 (Batch File) 실행시에, 인수(파라미터; 옵션; 매개변수) 주기

    to batch ... on may 30, 2006
  177. 도스(DOS)/윈도우의, 배치 파일에서 echo off 란?

    to batch ... on may 30, 2006
  178. 배치 파일의 옵션(인수; 파라미터; 매개변수) 해석하여 조건문 만들기 예제: 도움말(Help) 옵션 넣기

    to batch ... on may 30, 2006
  179. [QnA] 윈도우의 '명령 프롬프트'가, '도스창'인가요?

    to windows batch ... on may 29, 2006
  180. 명령 프롬프트란? Command Processor [컴퓨터 초보자를 위한 강좌

    to windows batch perl cpp ... on may 29, 2006
  181. chkdsk /F 옵션으로, 부팅 때 하드 디스크 검사하는 배치 파일 - Batch

    to batch windows ... on may 27, 2006
  182. 모든 하드디스크(HDD)를 한꺼번에 검사하는 배치(Batch) 파일

    to batch windows ... on may 27, 2006
  183. [VBScript-VBS] 하드디스크 남은 용량을, 퍼센트로 표시하는, 비주얼 베이직 스크립트

    to batch windows ... on may 26, 2006
  184. 비주얼 베이직 스크립트 (VBS / VBScript) 의 기초: 간단한 메시지 박스 예제

    to windows batch ... on may 23, 2006
  185. [QnA] VBS (VBScript) 란? / VBS 는 바이러스 파일인가요?

    to windows security batch ... on may 23, 2006
  186. 자신의 IP주소(아이피 주소; IP Address) 손쉽게 알아보기

    to windows batch ... on may 02, 2006
  187. [Perl] 특정 펄 모듈이 이미 설치되어 있는지 확인하는 배치 파일

Posted by 나비:D
:
출처 : http://jwmx.tistory.com/272

PuTTY와 TuTTY 모두 OpenSSH 서버로부터 만들어진 인증키를 이용하여 로그인할 수 있습니다. 또한 개인 키를 암호없이 만들면 암호 입력없이 로그인할 수 있습니다.

  우선 텔넷으로 서버에 접속합니다. 인증키에 대한 암호를 입력해야 함으로, 당연히 ssh 를 이용한 텔넷을 이용하는 것이 안전하겠지요. ssh-keygen을 이용하여 ssh 인증키를 생성합니다.

사용자 삽입 이미지

  인증키를 담는 파일 생성 위치와 파일 이름을 묻게 되는데, 기본 값을 사용하기 위해 엔터키를 누릅니다.
사용자 삽입 이미지

  다음은 인증키를 보호하기 위한 암호를 입력할 차례입니다. 여기서 입력하는 암호는 인증키를 위한 암호이지 텔넷에 접속할 때 사용하는 암호가 아닙니다. 아래 글에서 PuttyGen을 사용하여 개인키를 만들 때 이해가 되실 것입니다.
사용자 삽입 이미지

  암호 입력이 옳바른지 다시 한번 암호를 입력합니다.
사용자 삽입 이미지

  아래와 같이 fingerprint까지 출력되었다면 정상 적으로 인증키가 만들어진 것입니다.
사용자 삽입 이미지

  생성된 인증키 파일은 .ssh에 있습니다. .ssh로 이동합니다.
사용자 삽입 이미지

  파일이 정상적으로 생성이 되었지요.
사용자 삽입 이미지

  id_rsa는 개인키이고 서버에 접속하는 클라이언트쪽에서 필요한 파일입니다. id_rsa.pub는 공개키로 서버가 가지고 있어야 하는데, 파일 이름을 반드시 authorized_keys 로 변경해 주어야합니다.
사용자 삽입 이미지

  텔넷이나 VNC나 SSH를 이용하여 프로그램이 (1) 서버에 접속하게 되면 (2) 프로그램은 개인키를 서버에 제시하게되고, (3) 서버는 .ssh 에 있는 authorized_keys 파일 값을 비교 확인하여 로그인을 허가하게 됩니다.

  서버에서 할 일은 모두 끝났습니다. 이제 이 서버에 접속하려는 클라이언트쪽에서 해야할 일입니다.

  생성된 개인키, id_rsa를 ftp나 기타 방법으로 컴퓨터에 복사합니다. 이제 이 개인키를 가지고 PuTTY 나 TuTTY에서 로그인할 때 사용하는 인증키를 만들겠습니다.

 
PuTTY 홈페이지다운로드 페이지에서 PuTTYgen을 내려받습니다. 설치파일이 아니므로 바로 실행하시면 됩니다.

  [Load]
버튼을 클릭합니다. 그리고 서버로부터 복사한 id_rsa 파일을 선택합니다.
사용자 삽입 이미지
 

  그러면 암호를 물어 오는데, 인증키를 생성했을 때 사용한 암호를 입력합니다.
사용자 삽입 이미지

  키를 이상없이 읽어 들였다면 아래와 같이 설명 글이 출력됩니다.
사용자 삽입 이미지


  이제 텔넷 접속에 사용할 암호를 공백으로 수정해 줍니다. 개인키만 확인하면 로그인이 되도록 수정한다는 말씀이 되겠습니다.
사용자 삽입 이미지

  화살표가 가르키는 암호를 모두 삭제합니다. 그리고 Save private key를 이용하여 적당한 곳에 개인키를 저장합니다.
사용자 삽입 이미지


이제 PuTTY나 TuTTY를 실행합니다. 이전 서버 접속에 대한 정보를 Load 합니다.
사용자 삽입 이미지


  [Connection/Data]로 이동해서 로그인 ID를 입력합니다.
사용자 삽입 이미지


  이제 [Connection/SSH/Auth]로 이동한 후 PuTTYgen에서 저장한 개인크를 선택하여 줍니다.
사용자 삽입 이미지


  다음 사용을 위해 이 정보를 저장합니다.
사용자 삽입 이미지

  이제 [Open]버튼으로 텔넷을 접속하여 보십시오. 이전과는 달리 암호 확인 없이 로그인이되지요.
사용자 삽입 이미지

  PuTTYgen에서 만들어진 개인키는 매우 조심해야 합니다. 암호 확인 없이 텔넷에 접속할 수 있기 때문에 잘못 관리하셨다가는 큰 낭패를 보실 수 있습니다.

  긴 글 읽어 주셔서 감사합니다.
Posted by 나비:D
:
출처 : http://blog.naver.com/zzini0472?Redirect=Log&logNo=60056153395

1.adduser


   adduser ID 옵션 경로
  이것은 슈퍼 유저만이 사용할 수 있다.
  명령을 입력하면 로그온 이름 등을 차례로 물어오며,
  그에따라서 알맞게 입력해 나가면 된다.
  ex) adduser aaa /home/aaa 
      adduser aaa - /home/hakwon/aaa /home/hakwon/aaa
      adduser aaa -s /bin/false add user aaa -s /usr/bin/passwd -s 옵션은 계정을
      발급할때 로그인을 허락하지 않고 일반 메일계정으로만 사용할수 있다.
      텔넷이나 FTP로 로그인 할 수 없는 계정이 만들어집니다

2. alias


alias 또는 alias 명령='바꿀이름' 명령어 이름이 길거나 할때 별명을 만들어서 간단히 사용할 때 쓴다..


[linux22@ns linux22]$ alias
alias cp='cp -i'
alias l='ls -l'
alias l.-='ls .[a-zA-Z]* --color-tty'
alias ll='ls -al'
alias ls='ls -F --show-control-chars --color=tty'
alias mv='mv -i'
alias rm='rm -i'
alias tarc='tar cvvzf'
alias tart='tar xvvzf'
alias tarx='tar xvvzf'
alias which='type -path'

 

3.ami, ami_applet


 내가 누구인지를 나타내 준다.


4. arch


 현재 사용하고 있는 cpu의 모델을 출력(i686- 인텔 펜티엄),기계 아키텍쳐를 출력한다.  arch 는 uname -m 과 같다.
       현재 리눅스 시스템에서, arch 는 "i386", "i486", "i586","alpha", "sparc", "arm",              "m68k","mips", "ppc"과 같은 것을 출력한다.

5. cat


 텍스트 파일의 내용을 화면에 출력한다. DOS의 'type' 명령과 유사하다.
       ex] cat [options] <file1> <file2> . <fileN>
 -n : 행번호를 붙여서 출력시킨다.
 cat에서 내용을 입력 후 저장하고 나올때는 ctrl+d, 그냥 무시할때는 ctrl+c
         cat a > b (a에 내용을 b에 입력)
         cat a >> b (a에 내용을 b에 추가)
         cat -b : 공백라인 외의 글자가 있는 모든 행의 맨앞에 행번호를 추가
         cat -n : 공백라인을 포함한 모든 행의 맨앞에 행번호를 추가
         cat -s : 중복된 공백라인은 하나의 공백라인으로 처리


6. chkconfig


 특정 실행 레벨에서 서비스를 실행/중지 시키기 위해 필요한 다양한 심볼릭        링크를 관리하는 데 사용되며, /etc/rc.d/init.d 디렉토리에 있는 모든 스크립트에 대한
      실행 레벨 설정을 관리한다. 다음과 같이 하면 무엇이 실행레벨에 있는지 알수 있다.
[root@sulinux htdocs]# chkconfig --list
gpm 0:끔 1:끔 2:켬 3:켬 4:켬 5:켬 6:끔
crond 0:끔 1:끔 2:켬 3:켬 4:켬 5:켬 6:끔
mysql 0:끔 1:끔 2:끔 3:켬 4:켬 5:끔 6:끔
keytable 0:끔 1:끔 2:켬 3:켬 4:켬 5:켬 6:끔
syslog 0:끔 1:끔 2:켬 3:켬 4:켬 5:켬 6:끔
netfs 0:끔 1:끔 2:끔 3:켬 4:켬 5:켬 6:끔
network 0:끔 1:끔 2:켬 3:켬 4:켬 5:켬 6:끔
numlock 0:끔 1:끔 2:끔 3:켬 4:켬 5:켬 6:끔
--list다음에 서비스 항목 데몬을 적어주면 서비스에 대한 실행레벨 설정을 볼수 있다.
새로운 실행레벨을 추가 하려면 다음과 같이 하면 된다.
chkconfig --add service_name [--level runlevel]
예를 들어 다음과 같이 하면 된다.
chkconfig --add httpd
     서비스를 제거하려면 --add 대신 --del을 적어주면 된다.



7. df


 디스크의 용량을 확인할 수 있는 명령어입니다..
-a 전체를 나누어서 각 디렉토리와 파일의 크기를 보여준다.
-s 총 사용량을 출력해 준다.
-k kb단위로 출력해 준다.
     df [-aikPv] [-t fstype] [-x fstype] [--all] [--inodes] [--type=fstype] [--exclude-type=fstype] [--kilobytes][--portability] [--print-type] [--help] [--version] [filename...]

ex)[root@ns /test]# df
     Filesystem           1k-blocks      Used Available Use% Mounted on
     /dev/hda6              1517920     48244   1392568   3% /
     /dev/hda1                23302      2551     19548  12% /boot
     /dev/hda5              2419256   1118368   1177996  49% /home
     /dev/hda10              497829     32423    439704   7% /tmp
     /dev/hda7              1517920    837292    603520  58% /usr
     /dev/hda9               497829      5405    466722   1% /var
     /dev/hda8              1517920     10192   1430620   1% /var/lib


 

8. Du 


 디렉터리의 사용량을 보여주는 명령어. 옵션은 -s, -a, -m

      du -b : 파일의 내용을 바이트 단위로 표시(가장 흔히 사용하는 명령어)
      du : 킬로바이트 단위로 내용을 보여줌
[pump@sulinux pump]$ du
28      ./.e-conf
4       ./.enlightenment/backgrounds
328     ./.enlightenment/gnome_icons
20      ./.enlightenment/menus_gnome/Settings
60      ./.enlightenment/menus_gnome
24      ./.enlightenment/menus_kde/Settings
60      ./.enlightenment/menus_kde
4       ./.enlightenment/themes
496     ./.enlightenment
8       ./.gnome/accels



9. dnslookup

DNS를 조회하는 명령어이다.

[root@sulinux pump]# nslookup
*** Can't find server name for address 211.60.198.62: Non-existent host/domain
Default Server:  ns.dacom.co.kr
Address:  164.124.101.2
> yahoo,co,kr
Unrecognized command: yahoo,co,kr
> empas.com
Server:  ns.dacom.co.kr
Address:  164.124.101.2
Non-authoritative answer:
Name:    empas.com
Address:  211.115.211.8



10. eject


 마운트된 시디롬을 뺄때 유용하다.


11. fdformat


 디스켓을 퍼멧 할때 사용한다. 단 마운트 시킬 필요는 없다.
             fdformat [ -n ] 장치이름
      ex)fdformat /dev/fd0H1440 <--첫번째 플로피 디스크를 1.44MB 퍼맷하는 명령어 



12. file


 파일이 어떠한 형태의 파일인지 알아낸다. 
file [-czL ][ -fm 파일명 ] 파일명(들)
-c : 매직 파일의 파싱된 형태를 보여준다.
-z : 압축되어 있는 파일의 형태를 검사한다.
-L : 뒤따르는 심볼릭 링크를 야기시킨다.
-f 파일명 : 검사한 파일에 대해 리포트를 만들 파일의 이름을 지정한다.
        -m 파일명 : 파일의 형태를 결정하는 데에 사용되는 매직 파일을 정한다.
ex)[root@ns /test]# ll
     합계 28
     drwxr-xr-x    4 root     root         4096  3월 28 16:36 ./
     drwxr-xr-x   21 root     root         4096  3월 28 16:18 ../
     drwxr-xr-x    2 root     root         4096  3월 28 16:21 aaa/
     -rw-r--r--    1 root     root           27  3월 28 16:31 file
     -rw-r--r--    1 root     root           27  3월 28 16:36 file1
     -rw-r--r--    1 root     root           12  3월 28 16:32 file2
     drwx------    2 tomato   root         4096  3월 28 16:20 melon/
    [root@ns /test]# file file2
     file2: International language text


13. free


 현재 메모리 사용량을 보여줍니다. 옵션은 -k, -t 등이 있습니다
ex)[root@ns /test]# free
                total       used       free     shared    buffers     cached
   Mem:     127796      75736      52060    52468     23908      28444
-/+ buffers/cache:23384   104412
  Swap:      48152       0      48152



14. fsck


 파일 시스템의 상태가 올바른지 검사하고, 잘못된 것이 있으면 바로 잡는다.
    -a : 검사 도중 발견된 에러를 자동적으로 복구한다.
    -r : 검사 도중 에러가 발견되면 복구 여부를 물어본다(사실 사용되지 않는다)
    -s : 순차적인 방법으로 검색한다.
   -V : 검색 중 각종 정보를 자세하게 보여준다.
    -N : 실제로 검사 작업을 하지는 않도록 한다.


15. grep


 지정한 패턴을 하나나 그 이상의 파일들에서 찾고 그 결과를 표준 출력 장치로 출력하는데 쓰이는 명령어
 -b : 찾은 각 줄의 앞에 블록번호를 표시
 -c : 찾은 줄들의 내용은 표시하지 않고 그 수만 세서 표시
 -E : grep를 egrep처럼 동작하도록 지시
 -F : grep를 fgrep처럼 동작하도록 지시
 -f : 지정한 파일의 내용과 일치하는 부분들을 찾음
 -h : 여러개의 파일에서 찾을 때 결과에 파일의 이름은 포함하지 않은
 -i : 대소문자 구분 없이 찾음 grep -l : 결과를 출력 할 때 지정한 패턴이 있는 파일의 이름만 출력
 -n : 출력할 때 찾은 각 줄의 앞에 파일 내에서 행 번호를 붙임
 -q : 출력을 하지않음
 -s : 에러가 발생하면 에러메세지 출력
  -v : 지정한 패턴이 없는 행들만 출력
 -w : 지정한 패턴을 하나의 단어로 보고 검색
  -x : 한 줄의 전체 내용이 패턴과 같은 줄만을 찾음


16. gunzip 


 zip로 된 압축을 푸는 명령어입니다..

        gunzip -c 파일명.zip



 

17. gzip 


 zip보다 더 압축을 하고자 할때 사용하는 명령어입니다.


       gzip 압축명.tar.gz    대상파일명
       -c, --stdout : 표준 출력 이용
       -d, --decompress : 복구/풀기
       -f, --force : 링크화일도 압축
       -h, --help : 도움말
       -r, --recurse : 디렉토리 내의 화일들도 모두 처리
       -t, --test : 압축파일의 완전성 검사
       -v, --verbose : 파일 이름과 압축률 출력
       -V, --version : 버젼과 편집 사항 출력
       -#, --fast, --best : 압축 시간의 지정                 
       -1, --fast는 가장빨리 압축하나 압축률은 떨어지고 -9, --best는 가장느리나   압축률은 가장 좋다. 지정하지 않으면 -5가 사용된다.


18. Halt 


 시스템을 끌때사용. = shutdown



19. Head


파일의 앞부분만 보기 아무 옵션이 없으면 10줄을 나타내 준다. head -n 20 파일이름 ---> 20줄을 나타내준다.


head [-count | -n number] filename
ex)[root@ns /test]# ll
     합계 28
     drwxr-xr-x    4 root     root         4096  3월 28 16:36 ./
     drwxr-xr-x   21 root     root         4096  3월 28 16:18 ../
     drwxr-xr-x    2 root     root         4096  3월 28 16:21 aaa/
     -rw-r--r--    1 root     root           27  3월 28 16:31 file
     -rw-r--r--    1 root     root           27  3월 28 16:36 file1
     -rw-r--r--    1 root     root           12  3월 28 16:32 file2
     drwx------    2 tomato   root         4096  3월 28 16:20 melon/
    [root@ns /test]# head file
     hello welcome to my server


20. hostname


 컴퓨터 이름을 확인하는 명령어입니다..
           

 예]  


 [linux22@ns linux22]$ hostname
 ms.pubnet.ne.kr
 [linux22@ns linux22]$


21. netstat : 로컬 시스템의 네트워크 연결상태를 보여주는 프로그램이다.



22. jobs


 현 터미널에서 수행된 작업들을 간략하게 나열해준다


23. last


 /var/log/wtmp가 만들어진 후 사용자가 로그인한 목록을 출력한다. 예를 들어
         last pump라 하면 pump가 몇번 로그인 했는지 출력한다.
         last [-number][username][reboot]
[root@ns /test]# last -5
linux13  pts/0        211.57.165.71    Wed Mar 28 18:25   still logged in
linux22  pts/1        211.57.165.61    Wed Mar 28 18:10 - 18:15  (00:04)
linux13  pts/0        211.57.165.71    Wed Mar 28 18:00 - 18:23  (00:22)
linux13  pts/0        211.57.165.71    Wed Mar 28 17:46 - 17:56  (00:10)
linux13  pts/0        211.57.165.71    Wed Mar 28 16:08 - 17:37  (01:29)
wtmp begins Sat Feb 24 14:05:58 2001
-num : num 만큼의 줄만 보여준다.
-n num : 윗 기능과 같음.
-R : hostname 필드를 보여주지 않음.
-a: hostname 필드를 마지막에 보여줌.이 옵션은 다음 옵션과 함께 요용하게 쓰임.
-d : 다른 호스트에서 접속한 것만 보여줌.
-x : shutdown이 일어난 상태나, run level이 바뀐 상태도 보여줌.


24. ln


 링크파일을 만드는 명령어입니다..

    ln -s 원본파일 링크될파일명  : 소프트 링크입니다.
    ln : 하드링크입니다. 하드 링크는 생성된 후에는 일반파일과 동일하게 보여진다 (완전하게 똑 같은 파일이다.)
     ln pathname... directory원본 파일에 대한 하드/심볼릭 링크화일을 만든다.
    -f : 디렉토리에 대한 하드링크 생성(수퍼유저만 가능)
    -s : 심볼릭 링크 생성
in [-s] soucefile target
ex)[root@ns /test]# ll
     합계 28
     drwxr-xr-x    4 root     root         4096  3월 28 16:36 ./
     drwxr-xr-x   21 root     root         4096  3월 28 16:18 ../
     drwxr-xr-x    2 root     root         4096  3월 28 16:21 aaa/
     -rw-r--r--    1 root     root           27  3월 28 16:31 file
     -rw-r--r--    1 root     root           27  3월 28 16:36 file1
     -rw-r--r--    1 root     root           12  3월 28 16:32 file2
     drwx------    2 tomato   root         4096  3월 28 16:20 melon/
     [root@ns /test]# ln file file3
     [root@ns /test]# ll
     합계 32
     drwxr-xr-x    4 root     root         4096  3월 28 16:48 ./
     drwxr-xr-x   21 root     root         4096  3월 28 16:18 ../
     drwxr-xr-x    2 root     root         4096  3월 28 16:21 aaa/
    -rw-r--r--    2 root     root           27  3월 28 16:31 file
    -rw-r--r--    1 root     root           27  3월 28 16:36 file1
    -rw-r--r--    1 root     root           12  3월 28 16:32 file2
    -rw-r--r--    2 root     root           27  3월 28 16:31 file3
    drwx------    2 tomato   root         4096  3월 28 16:20 melon/



25. logname 


 로그인해 있는 사용자의 이름을 출력한다.

26. lpq


 프린터의 상태를 알려주는 명령어이다.


27. lpr


 파일을 프린터 스풀로 보내는 명령어이다.


28. lprm 


 인쇄 대기열에서 특정 작업을 삭제하라는 명령어이다.



29. mouseconfig


 마우스 설정 프로그램이다.


30. printerconfig


 프린터 설정 프로그램이다.


31. ps


 프로세서를 확인하는 명령어입니다.
    -l : 자세한 형태의 정보를 출력한다.
    -u : 각 프로세스의 사용자 이름과 시작 시간을 보여준다.
    -j : 작업 중심 형태로 출력한다.
    -s : 시그널 중심 형태로 출력한다.
    -v : 가상 메모리 중심 형태로 출력한다.
    -m: 메모리 정보를 출력한다.
    -a : 다른 사용자들의 프로세스도 보여준다.
    -x : 로그인 상태에 있는 동안 완료되지 않은 프로세스들을 보여준다. 유닉스 시스템은 사용자가  로그아웃하고 난 후에도 임의의 프로세스가 계속 동작하게 할 수 있다. 그러면 그 프로세스는 자신을 실행시킨 쉘이 없이도 계속 자신의 일을 수행한다. 이러한 프로세스는 일반적인 ps 명령으로 확인할 수 없다. 이때 -x 옵션을 사용하면 자신의 터미널이 없는 프로세스들을 확인할 수 있다.
    -S: 챠일드(child) CPU 시간과 메모리 페이지 결함(fault) 정보를 추가한다.
    -c: 커널 task_structure 로부터 명령 이름을 보여준다.
    -e: 환경을 보여준다.
    -w: 긴(wide) 형태로 출력한다. 한 행 안에 출력이 잘리지 않는다.
    -h: 헤더를 출력하지 않는다.
    -r: 현재 실행중인 프로세스를 보여준다.
    -n: USER와 WCHAIN을 위해 수치 출력을 지원한다.
    ps -aux (메모리에 로드중인 프로세서들을 출력합니다.)
    ps -aux | grep 프로세서 (해당 프로세서만 출력합니다.)

 

 

32.rcp 


 컴퓨터 사이에서 파일을 복사할 때 사용된다. "remote cp"에서 이름이 유래한다.
 rcp [ -rpkx ] 파일명1 파일명2
 rcp [ -rpkx ] 파일명들 디렉토리
 -r : 하위 디렉토리까지 재귀적으로 모두 복사한다.
 -p : 파일의 시간과 모드를 보존한다.
 -k : kerberos ticktets을 요구한다.
              -x : 복사되는 모든 데이터에 암호화 과정을 거친다.



33. rlogin


 rlogin(remote login)은 telnet과 마찬가지로 원격 시스템에 로긴할 때 사용하는 명령어로telnet과 사용법이 거의 동일하지만, 다른점은 rlogin의 경우, 자기가 해당 시스템에 id를 가지고 있고, 시스템에 로긴할 때마다 패스워드를 치기가  싫을 경우 자신의 홈 디렉토리  아래에 rhosts라는 파일에 자신의 계정 id와 로긴할 호스트이름을 넣어두면 로긴시에 패스워드를 넣지 않고도 $rlogin -l blueksy target_host 형식으로 로긴이 가능하다. 만약 ~/.rhosts에 "+ +"의 내용이 들어있다면 누구라도 패스워드 없이 접속할 수가 있게되어 예전에 유행했던 해킹방법이 되기도 했으나 지금은 시스템들의 보안강화로 이게 통하는 시스템은 거의 없다..


 

34. rpm  


 레드햇패키지 메니저로 패키지를 관리하는 프로그램입니다.
         rpm -Uvh 해당패키지 (업그레이드)
         rpm -ivh 해당패키지 (설치)
         rpm -e  해당패키지 (삭제)
         rpm -Uvh --nodeps --force 해당패키지  (파일대치 패키지대치로 설치)


35. shutdown 


 시스템을 종료할 때 일반적으로 사용되는 명령어이다.
   shutdown -t n : 옵션 t 뒤에 n 초만큼 후에 경고 메시지 후에 kill 신호를 보낸다.
   shutdown -h(halt) : 완전히 닫는다.
   shutdown -r(reboot) : 종료 후 재부팅을 한다.
   shutdown -f(fast) : 빠른 리부팅을 한다 (파일 시스템 검사 생략)
   shutdown -c(cancel) : 예약되어 있는 종료 취소
   shutdown -k(kidding) : 모든 것이 정상이지만, 종료 시간이 되면 모든 프로그램이 멈춘다.



36. sort 


 파일을 소팅할때 사용합니다.
      -c : 파일이 정렬되었는지 검사한다. 그렇다면 아무런 출력도 하지 않는다.
      -m : 특정한 파일을 병합한다. 파일은 이미 정렬되었다고 가정한다.                      

      -u : 고유한 행만이 출력된다.
      -o 파일명: 출력 파일 이름을 지정한다. 이름은 입력 파일 이름과 같을 수 있다.
      -d : 사전(dictionary)과 같은 순서대로 정렬한다. 단어 정렬 순서에는 문자, 숫자,공백 문자만이 사용된다. 
      -f : 대문자와 소문자를 구별하지 않는다. 
      -i : 정렬에 사용되는 문자 중 프린트될 수 없는 문자는 사용하지 않는다. 
      -M : 단어를 정렬할 때 달을 의미하는 문자를 취급한다. FEB는 JAN보다 뒤에 정렬 된다.
      -n : 숫자를 같은 문자가 아닌 정말로 숫자로 취급해서 수의 크기대로 정렬한다.
      -r : 역순으로 정렬한다. 
      -t 문자 : 단어 등 필드를 구분하는 문자를 지정한다. 탭(tab)이나 공백 문자 이외의  문자를 구분 문자로 취급하도록 한다.
   -b : 단어의 뒤에 오는 공백 문자는 정렬 키(key) 값으로 무시하도록 한다.



37. sndconfig


 사운드카드를 설정해 주는 프로그램이다.
  


38. stat

파일이나 디렉토리엥 관한 다양한 통계 자료를 보여주는 프로그램이다.
   stat file
 ex)[root@ns /test]# ll
   drwxr-xr-x    4 root     root         4096  3월 28 17:55 ./
   drwxr-xr-x   21 root     root         4096  3월 28 17:50 ../
   drwxr-xr-x    2 root     root         4096  3월 28 16:21 aaa/
   -rw-r--r--    1 root     root           27  3월 28 16:36 file1
   [root@ns /test]# stat file1
   File: "file1"
   Size: 27           Filetype: Regular File
   Mode: (0644/-rw-r--r--)        Uid: (    0/    root)  Gid: (    0/    root)
   Device:  3,6   Inode: 16348     Links: 1
   Access: Wed Mar 28 16:36:11 2001(00000.01:24:55)
   Modify: Wed Mar 28 16:36:11 2001(00000.01:24:55)
   Change: Wed Mar 28 16:36:11 2001(00000.01:24:55)


39.sync


현재 시스템 디스크의 IO  버퍼에 있는 디스크 이미지를 하드 디스크로 기록한다.
 sync


40. test


 파일의 각종 상태를 검사하여 결과를 알려준다. 이것은 셸 스크립트 상에서 if 문이나 while 문 등과 함께 사용되는 것이 보통이다.
test 표현식
  -r  파일명 : 파일이 읽기 권한이 있으면 참
  -w 파일명 : 파일이 쓰기 권한이 있으면 참
  -x 파일명 : 파일이 실행하기 권한이 있으면 참
  -f 파일명 : 파일이 일반(regular) 파일이면 참
  -d 파일명 : 파일이 디렉토리이면 참
  -b 파일명 : 파일이 존재하고 블록 장치 파일이면 참
  -c 파일명 : 파일이 문자 전용 파일(character special file)이면 참
  -u 파일명 : 파일이 set-user-ID 플래그가 세트되어 있으면 참
  -g 파일명 : 파일이 set-group-ID 플래그가 세트되어 있으면 참
  -k 파일명 : 파일이 sticky 비트가 세트되어 있으면 참
  -s 파일명 : 파일의 크기가 0보다 크면 참
  -t 파일 디스크립터 : 파일 디스크립터에 해당하는 파일이 열려 있고, 터미널 장치로부터 사용되고 있으면 참, 기본 디스크립터 값은 1이다.
  -z 문자열 : 문자열의 길이가 0이면 참
  -n 문자열 : 문자열의 길이가 t 이상이면 참


41. top

 

 cpu와 메모리를 사용하는 작업들에 대한 시스템 정보를 출력한다. 원래 화면으로 되돌아가려면 q를 입력한다.



42. tty


 현재 사용하고 있는 단말기 장치의 경로명과 파일명을 보여줌


43. uname


 사용중인 운영체제에 대한 정보를 출력한다.
   -a : 현재 사용중인 운영체제와 커널의 컴파일 정보 등을 출력한다.-snrvm 과 같다.
   -s : 시스템 이름을 알려준다.
   -n : 시스템의 노드(node) 이름을 알려준다.
   -r : 오퍼레이팅 시스템의 증명번호를 알려준다.
   -v : 오퍼레이팅 시스템의 버전(version) 번호를 알려준다.
   -m : 하드웨어의 이름을 알려준다.
[root@ns /test]# uname -a
Linux ns.pubnet.ne.kr 2.2.16-3kr2 #1 Thu Aug 10 16:33:55 KST 2000 i686 unknown

 

Posted by 나비:D
:

사내 웹사이트 구축 번거롭고 힘드셨죠?
이제 Visio 2007의 웹사이트 관리 기능을 이용해 보세요.
시간낭비와 고민하실 필요 없이 효율적으로 웹사이트를 계획하고 관리하실 수 있습니다.
어떤 프로그램을 이용했을지 궁금해 하실 것 같아 알려드립니다~ ^^


사내 웹사이트 구축에 참여해 본 분들이시라면 다음의 이야기에 공감하실 겁니다.

웹사이트 구축을 의뢰한 사측 관리자는 보통은 복잡한 문서를 넘겨주고 웹사이트에 들어갈 자료이니 알아서 분류해서 메뉴를 만들어 달라고 요구를 합니다. 웹사이트 개발을 맡은 개발자는 혼자서 아이디어를 구상하고 열심히 웹사이트를 만들고 나면, 왠지 구조가 맘에 안 들거나 구성이 짜임새가 없어 보인다고 핀잔을 듣기 일쑤입니다. 서로의 의견이 조율될 때까지 개발자는 스트레스와 업무에 시달리게 되고, 관리자는 늦어지는 사이트 오픈에 조바심과 불안함을 가지고 지켜보게 됩니다. 결국, 적당한 합의를 보고 사이트를 오픈 하지만 100% 맘에 들 수는 없다는 말로 위안을 삼죠.. 여러분 언제까지 이런 일들을 반복하실 건가요?
또 이렇게 어렵게 구축한 웹사이트 제대로 운영되고 있는지 확인은 해보시나요? Visio 2007의 웹사이트 관리 기능을 이용하여 가장 효율적으로 웹사이트를 계획하고 관리하는 방법을 알려드리겠습니다.
이번 팁을 통해서 익히게 되는 기능을 정리하면 다음과 같습니다. 1. 웹사이트 개념도 작성
2. 웹사이트 맵 작성


웹사이트 구축과 관리를 위한 템플릿 Visio 2007는 웹사이트를 구축하고 관리하기 위한 템플릿을 제공하고 있습니다. 1. [파일]-[새로 만들기]-[시작] 메뉴를 이용하면 다양한 템플릿을 선택할 수 있습니다.
그 중 [네트워크] 또는 [소프트웨어 및 데이터 베이스] 범주에서 웹사이트 템플릿을 찾을 수 있습니다.



2. 아래 이미지는 Visioplus.com 사이트 기획 당시 [웹 사이트 개념도]를 이용하여 사이트를 기획한 결과물입니다. [웹 사이트 개념도]는 아래와 같이 웹 사이트의 콘텐츠, 메뉴 구분, 디렉터리 구분 등 관리자와 개발자 사이에 커뮤니케이션을 편리하게 하기 위해 사용합니다.


3. [웹 사이트 개념도]를 이용하는 방법은 순서도, 조직도 그리는 방법과 유사합니다.
웹사이트 개념도에서 제공하는 [웹 사이트 개념도 셰이프]를 이용하여 적절히 관계를 연결하면 됩니다. 이전 팁들을 통해 셰이프를 연결하고 활용하는 방법을 알아봤으므로, 이번 팁은 [웹사이트 맵]을 위주로 진행하겠습니다.


4. Visio 2007을 실행시키고 [템플릿 범주]에서 [소프트웨어 및 데이터베이스]를 선택하고 [웹 사이트 맵]을 클릭합니다.


5. 웹사이트 맵을 시작하면 다음과 같이 웹 주소를 넣을 수 있는 창이 나타납니다.
자주 들어오는 오피스튜터 사이트는 어떻게 관리되고 있는지 한번 확인해볼까요?
[주소] 입력란에 http://www.officetutor.co.kr 을 입력합니다.


6. 만일 사이트를 읽어올 때, 읽혀지는 사이트의 설정을 조정하고 싶다면, [설정] 메뉴를 클릭합니다.

1)[웹사이트 맵 설정]의 [레이아웃]탭에서 읽어오려는 링크의 최대 수와 링크 수준 (depth) 등을 조절할 수 있습니다.
[기본 셰이프 텍스트]는 사이트를 읽어서 그 사이트를 표시할 때 주소를 표시하도록 하거나 HTML 제목을 표시하면, 확인하기에 편리합니다.
지금은 기본 설정인 [상대 URL]을 선택합니다.



2)[확장명],[프로토콜],[특성] 탭에서는 인식할 수 있는 웹 사이트의 형식, 종류를 구분하여 선택할 수 있습니다. ① [프로토콜] 탭
Visio 2007의 경우 HTTP, HTTPS, File, FTP, GOPHER, MailTo, NEWS, NNTP, PROSPERO, TELNET, WAIS 등의 프로토콜을 지원합니다. ② [특성] 탭
웹 사이트 맵은 HTML내의 하이퍼링크 값을 읽어서 표현하게 된다. 상황에 따라서 아래와 같은 HTML 태그 내부에 정의된 속성의 링크 값들은 표시하지 않도록 조절할 수 있다.


3)[고급] 탭에는 사이트 맵을 그리기 위한 영역을 설정합니다.


① 검색조건
다음 3가지 다른 방법 중 한 가지 검색 방법을 선택합니다. I. 검색한 모든 파일 분석 : 조건 없이 모든 링크된 사이트를 검색합니다.
II. 지정한 도메인에 있는 파일 분석 : 입력 주소의 도메인 내부에 포함된 사이트를 검색합니다.
III. 지정한 디렉터리에 있는 파일 분석 : 입력 주소와 같은 폴더 내의 사이트를 검색합니다. ② HTTP 인증
만일, 웹 서버에 접근할 때에 암호 인증이 필요하다면, HTTP 인증란에 아이디와 패스워드를 입력합니다.


7. [설정] 메뉴의 모든 옵션을 기본 상태로 유지하기 위해 [웹 사이트 맵 설정] 창의 [취소] 버튼을 누르고 빠져나옵니다. 8. 마지막 단계로 웹 사이트 맵을 그리기 위해 [사이트 맵 생성] 창에서 [확인]을 클릭합니다.



9. 드디어 입력한 사이트의 웹사이트 맵이 그려졌습니다.


10. 각 아이콘이 무엇을 나타내는지는 [웹 사이트 맵 셰이프]의 셰이프를 확인하면 알 수 있습니다.


11. 대부분의 맵 셰이프 옆에는 아래와 같이 군인 마크와 같은 모양이 덧붙여져 있습니다.
이 표시는 이 사이트를 확장할 수 있다는 표시입니다.


12. 마우스 오른쪽 버튼을 클릭한 후 바로 가기 메뉴 중 [하이퍼링크 확장]을 선택하여 사이트의 링크 정보를 트리 구조로 확인할 수 있습니다.


13. [하이퍼링크 확장]메뉴를 클릭하면 모든 트리의 마지막에 선택한 셰이프의 복사본과 그와 링크된 사이트들이 추가로 표시됩니다.


14. 사이트 맵 중간에 아래와 같이 X 표시가 빨갛게 되어 있는 사이트도 있습니다.
이미지의 X 표시는 읽어온 콘텐츠에 연결된 하이퍼링크 주소가 정확하지 않을 경우 나타납니다. 웹 사이트에 잘못된 주소가 없는지 확인하는 것도 웹 사이트 맵을 그리는 가장 큰 이유 중 하나입니다.


15. 사이트 맵으로 그려진 구조가 너무 복잡하거나 콘텐츠가 너무 많을 경우, 그 종류에 따라 구분하여 볼 수 있도록 [필터 창]과 [목록 창]을 제공하고 있습니다.
각 창의 리스트 앞에 있는 체크박스의 선택을 해제하면 해당되는 페이지와 그와 연결된 하이퍼링크, 또는 해제된 종류의 콘텐츠는 사이트 맵에서 지워지게 됩니다.


16. 마지막으로 웹사이트 맵이 제공하는 또 하나의 멋진 기능인 [보고서]를 이용해 보도록 하겠습니다. [웹 사이트 맵]-[보고서]를 클릭합니다.
사이트 맵을 이용하여 깨진 링크, 등록된 콘텐츠, 사이트의 구조 등을 시각화하여 파악하기도 이 사이트 맵을 텍스트로 표시하여 엑셀 파일로 변환하여 모든 링크 정보를 표시하거나, 오류를 가진 링크 정보를 보고서로 출력할 수 있습니다.


17. [보고서] 리스트에서 웹 사이트 맵 링크(오류 포함)을 선택하여 보고서를 작성해 보겠습니다. [보고서] 창의 보고서 목록 중 [웹 사이트 맵 링크(오류 포함)]을 선택하고 [실행]을 클릭합니다.


18. [보고서 실행] 창의 [보고서 형식 선택] 목록 중에서 [Excel]을 선택하고 [확인]을 클릭합니다.


19. 오피스튜터 사이트는 1개의 링크가 깨져있고, 이 링크는 비트맵 파일과 연결된 링크입니다.


실전 응용
관리자님을 대신하여 제가 깨진 링크를 확장하여 어떤 비트맵 파일인지 확인해보겠습니다.
위에서 다룬 방법 중 사이트를 선택하여 마우스 오른쪽 메뉴를 보면 [하이퍼링크 확장]이 있었죠. 이 기능을 이용하여 깨진 사이트를 확장하였더니 아래와 같은 트리가 생성이 되었습니다.



자 이제 어떤 경로에 있는 그림인지 파악이 되시죠?
링크가 정상인 사이트는 하이퍼링크를 이용하여 그 콘텐츠를 확인할 수 있습니다.


출처 :
Posted by 나비:D
:
Posted by 나비:D
:

BLOG main image
by 나비:D

공지사항

카테고리

분류 전체보기 (278)
Programming? (0)
---------------------------.. (0)
나비의삽질 (5)
Application (177)
SQL (51)
Web (27)
etc. (14)
Omnia (0)
---------------------------.. (0)

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

달력

«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Total :
Today : Yesterday :