HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, 
BOOL bInitialState, LPCTSTR lpName); 

HANDLE OpenEvent(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName); 

bManualReset은 이벤트가 수동리셋 이벤트(manual)인지 자동리셋 이벤트(automatic)인지 지정하는데 TRUE이면 수동리셋 이벤트가 된다. 
bInitialState가 TRUE이면 이벤트를 생성함과 동시에 신호상태로 만들어 이벤트를 기다리는 쓰레드가 곧바로 실행을 하도록 해준다. 
이벤트도 이름(lpName)을 가지므로 프로세스간의 동기화에 사용될 수 있다. 

또한 이벤트가 임계영역이나 뮤텍스와 다른점은 
대기함수를 사용하지 않고도, 쓰레드에서 임의적으로 신호상태와 비신호상태를 설정할 수 있다는 점이다. 다음 함수를 사용한다. 

BOOL SetEvent(HANDLE hEvent); 
BOOL ResetEvent(HANDLE hEvent);



1. 함수의 원형


    HANDLE WINAPI CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, 
                                          BOOL bManualReset, BOOL bInitialState, LPCTSTR lpName);


2. 함수의 기능
 
    이름이 정해진 또는 이름이 없는 이벤트 객체를 열거나 생성하는 함수이다. 이 객체에
    접근할수 있는 경우를 명시하고 싶다면 CreateEventEx 함수를 사용해야 한다.
   
3. 함수의 매개변수에 대한 설명
 
    3.1 lpEventAttributes
        
        SECURITY_ATTRIBUTES 구조체로 선언된 변수의 주소를 명시한다. 이 매개변수에 NULL을 명시하면 
        생성된 이벤트 핸들은 자식 프로세스에 상속되지 않는다. SECURITY_ATTRIBUTES 구조체의 항목인
        lpSecurityDescript-xor에는 새로운 이벤트의 보안 기술자(security descript-xor)에 대하여 명시하도록 되어있다.
        만약, 이 매개변수에 NULL을 사용하여 보안 기술자에 대한 명시를 하지 않은 경우에는, 새로 생성될
        이벤트 객체에 일반적인 보안 기술자가 명시된걸로 간주한다. 일반적인 보안 기술자의
        ACL(Access Control List)은 현재 로그인되어 있는 사용자의 로그인정보에 있는 ACL을 이용하거나 
        이벤트 객체를 생성한 프로세스의 ACL을 가져와 사용한다.

        ACL에 대한 좀더 자세한 내용은 아래의 항목을 참고하시기 바랍니다.
        http://www.tipssoft.com/bulletin/tb.php/FAQ/15

    3.2 bManualReset
 
        이 매개변수에 TRUE를 명시하면 발생된 이벤트 정보가 계속 유지되는 이벤트 객체를 생성한다. 
        즉, 이벤트 객체에 SetEvent 함수를 이용하여 이벤트를 설정하면 ResetEvent 함수를 호출하여
        해제하기 전까지 계속 이벤트가 발생한 상태로 유지된다.
        반대로 이 매개변수에 FALSE를 명시하면 자동으로 이벤트가 해제되는 이벤트 객체를 생성한다.
        즉, 이벤트를 기다리는 스레드가 이벤트가 발생한 상황을 체크하게 되면 자동으로 이벤트
        정보가 해제된다. 따라서 별도의 ResetEvent 함수를 호출할 필요가 없다.
 
    3.3 bInitialState
 
        이 매개변수가 TRUE라면 이벤트 객체는 이벤트가 발생한 상태로 생성되며 FALSE이면 이벤트가
        발생하지 않은 상태로 생성된다.
 
    3.4 lpName
 
        이 매개변수에는 이벤트 객체에 사용할 이름을 명시한다. 여기에 사용되는 이름의 길이는
        MAX_PATH까지로 제한되며 대소문자를 구별(Tips, tips, tipS는 서로 다른걸로 간주)한다.
        만약, 명시한 이름이 이미 생성된 다른 이벤트 객체에 사용되고 있다면 이미 생성된 객체와
        이벤트 발생정보를 공유하게 된다. 따라서 먼저 만들어진 이벤트 객체의 정보가 우선시
        되기 때문에 현재 사용한 bManualReset(3.2), bInitialState(3.3)에 명시한 정보는 무시된다.
        그리고 lpEventAttributes(3.1)에 NULL이 아닌 보안정보가 명시된 경우, 먼저 생성된 
        이벤트 객체의 보안 기술자에 의해서 사용되어질것인지 결정되며 사용가능하다고
        판단되더라도 해당 구조체의 세부항목인 보안기술자 항목에 명시된 정보는 무시된다.
        따라서 고유한 이벤트 객체를 생성하려면 이벤트 이름을 명시할때 주의해야 한다.

        만약, 이 매개변수에 명시한 이름이 이미 생성된 Semaphore, Mutex, Waitable timer, Job 
        또는 File-mapping 객체에 사용되고 있다면 이 함수는 실패할것이고 정확한 오류체크를
        위해 GetLastError 함수를 호출하면 ERROR_INVALID_HANDLE 값이 반환될 것이다. 
        즉, 하나의 객체는 다른 형식의 객체와 이름을 공유할수 없고 동일한 형식의 객체에서만
        공유여부가 결정되어진다.

        이 매개변수에 NULL을 명시하면 이름없는 이벤트 객체를 생성한다.
        
        추가적으로 객체의 이름을 명시할때, 시스템 전역적으로 객체의 이름을 공유하고 싶다면 
        사용하고자 하는 이름앞에 "Global\"이라는 접두어를 사용하고 현재 세션공간에서만
        사용하고 싶을때에는 "Local\"이라는 접두어를 사용할수 있다.

        "Global" 또는  "Local" 이라는 접두어를 사용할수 있는 커널 객체에 대해서 좀더 자세한 
        내용을 원하신다면 아래 내용을 참고하시기 바랍니다.
        ( Kernal Objcet Namespace ) -http://www.tipssoft.com/bulletin/tb.php/FAQ/17

        그리고 사적인 이름공간에도 이벤트 객체를 생성할수 있는데 이방법에 대해서 좀더
         자세한 내용을 원하신다면 아래 내용을 참고하시기 바랍니다.
         [ Object Namespaces ] - http://www.tipssoft.com/bulletin/tb.php/FAQ/18


4. 함수의 반환값
    
    이 함수가 성공적으로 수행을 완료했다면 생성된 이벤트 객체의 핸들이 반환될 것이다. 만약,
    lpName에 사용한 이름과 동일한 이름으로 생성된 이벤트 객체가 이미 생성되어 있다면
    해당 객체의 핸들이 반환될것이다. 이때, GetLastError 함수를 호출해보면 
    ERROR_ALREADY_EXISTS가 반환될 것이다. 따라서 다른 프로세스와 이벤트 객체가
    공유되는것을 원치 않는다면 CreateEvent 함수가 정상적인 이벤트 핸들값을 반환하더라도
    GetLastError 함수를 호출하여 ERROR_ALREADY_EXISTS 값이 반환되는지를 체크하는것도
    좋은 방법일 것이다.

    만약 함수가 실패한다면 NULL값이 반환될 것이고, GetLastError 함수를 호출해서 좀더 자세한 
    오류 상황을 확인할 수 있다.

'NativeCode > api' 카테고리의 다른 글

CkLibrary  (1) 2010.03.19
Sendarp 사용법  (0) 2010.03.19
Deadlock 4가지 조건  (0) 2010.03.19
Synchronization Function  (0) 2010.03.19
Win Version & Macro  (0) 2010.03.18

개 이상의 프로세스가 각각의 공유 자원을 사용하고 있으면서 다른 자원을 요구하여 무한정 대기하는 상태를 교착상태라 하는데 이는 4가지 반드시 필요한 조건이 있다. 다음의 정리 내용을 확인하자.

교착상태가 일어나기 위한 네 가지 조건(하나라도 만족하지 않으면 일어나지 않음)

상호배제(Mutual Exclusion)

▪공유 자원을 하나의 프로세스만 공유해야 한다.

점유와 대기(Hold and Wait)

▪최소한 하나의 자원을 점유하고 있고, 다른 프로세스가 점유한 자원을 이용하기 위해 대기하는 프로세스가 있어야 한다.

비선점(Non-Preemption)

▪다른 프로세스에 할당된 자원을 강제로 중지할 수 없어야 한다.

환형대기(Circular Wait)

▪공유 자원과 공유 자원을 사용하려는 프로세스가 원형으로 구성되어 자신에게 할당된 자원을 점유하면서 인접한 양쪽 프로세스의 자원을 요구해야 한다.


'NativeCode > api' 카테고리의 다른 글

Sendarp 사용법  (0) 2010.03.19
Event  (0) 2010.03.19
Synchronization Function  (0) 2010.03.19
Win Version & Macro  (0) 2010.03.18
사용법  (0) 2010.03.18

Critical Section

크리티컬 섹션을 사용하는 이유.

속도가 뮤텍스나 세마포어보다 빠르다.

동기화시 가장 주의할 점은 DeadLock이다

한 프로세스 안에서만 사용이 가능하다.


CRITICAL_SECTION m_CriticalSection;

InitializeCriticalSection( &m_CriticalSection );

DeleteCriticalSection( &m_CriticalSection );


EnterCriticalSection( &m_CriticalSection );

LeaveCriticalSection( &m_CriticalSection );



Mutex

뮤텍스는 크리티컬 섹션과 비슷해서 크리티컬 섹션이 쓰이는 곳에 대신 사용할 수 있다.

그리고 이름을 갖고 있으므로 다른 프로세스에서도 사용이 가능하다.

하지만 속도는 더 느리다.


HANDLE hMutex;

hMutex = CreateMutex( NULL, FALSE, NULL );

ReleaseMutext( hMutex );

WaitForSingleObject( hMutex, INFINITE );



Semaphore

세마포어는 뮤텍스와 유사한 동기화 객체이다. 물론 차이점이 있다. 뮤텍스는 하나의 공유 자원을 보호하기 위해 사용하지만 세모포어는 제한된 일정 개수를 가지는 자원을 보호하고 관리한다. 여기서 자원이라 함은 상당히 추상적이지만 그것이 하드웨어일 수도 윈도우 프로세스, 스레드와 같은 소페트웨어적인 것을 수도 있다.

HANDLE hSemaphore = ( HANDLE )CreateSemaphore( NULL, 3, 3, NULL );

WaitForSingleObject( hSemaphore, INFINITE );

ReleaseSemaphore( hSemaphore, 1, NULL );


HANDLE CreateSemaphore( LPSECURTY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCSTR lpName );

lMaximumCount 는 최대 사용 개수 lInitialCount = 초기값


HANDLE OpenSemaphore( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName );

OpenSemaphore 함수로 세마포어의 핸들을 구할 수 있다.

OpenSemaphore(SYNCHRONIZE, FALSE, "MySemaphore");


BOOL ReleaseSemaphore( HANDLE hSemaphore, LONG lReleaseCount, LPLONG lpPreviousCount );

자원의 사용이 끝난 스레드는 이 함수를 호출하여 사용 종료를 세마포어에 알려야 한다. lReleaseCount 로 자신이 사용한 자원의 개수를 알리는데 하나만 사용했으면 이 값은 1이고 만약 여러개를 사용했으면 사용한 만큼 자원을 풀어줘야 한다. 세번째 함수는 이전 카운트를 리턴받기 위한 참조 인수이다.


파괴 void CloseHandle( HANDLE );


// 세마포어의 카운트를 조사하는 함수

int RetSemaCount( HANDLE hSema )

{   

int result;

int count;

result = WaitForSingleObject( hSema, 0 );

if( result == WAIT_TIMEOUT )

return 0;

ReleaseSemaphore( hSema, 1, &count );

return count +1;

}

'NativeCode > api' 카테고리의 다른 글

Event  (0) 2010.03.19
Deadlock 4가지 조건  (0) 2010.03.19
Win Version & Macro  (0) 2010.03.18
사용법  (0) 2010.03.18
LoadLibrary  (0) 2010.03.18

_WIN32_WINNT, WINVER 값

Windows "Longhorn"         0x0600 <= 이게 비스타인듯~ 
Windows Server 2003         0x0502 
Windows XP                     0x0501 
Windows 2000                   0x0500 
Windows 98                      0x0410 
Windows 95                      0x0400

_WIN32_IE 값

IE 7.0                       0x0700 
IE 6.0 SP2                0x0603 
IE 6.0 SP1                0x0601 
IE 6.0                       0x0600 
IE 5.5                       0x0550 
IE 5.01                     0x0501 
IE 5.0  5.0a  5.0b       0x0500 
IE 4.01                     0x0401 
IE 4.0                       0x0400 
IE 3.0  3.01  3.02        0x0300

-----------------< 추가 내용 >-----------------

알아두면 좋을거 같은 매크로들 몇 개 (MSDN)

ANSI 호환 매크로들

__DATE__ 매크로가 사용된 파일이 컴파일 된 시간 
__FILE__ 매크로가 사용된 파일의 이름 
__LINE__ 매크로가 사용된 파일에서 매크로가 있는 곳의 라인 넘버 
__STDC__ ANSI C 표준에 준하는지 확인. /Za옵션이 없거나 C++코드 컴파일 하면 정의 안됨 
__TIME__ 매크로가 사용된 파일의 가장 최근에 컴파일 된 시간 
__TIMESTAMP__ 매크로가 사용된 파일의 최종 수정된 시간

Microsoft 에서만 사용되는 매크로들

_ATL_VER ATL 버전 
_CHAR_UNSIGNED char타입을 unsigned로 함. /J 옵션 주면 정의 됨 
__CLR_VER Common Language Runtime 버전 
__cplusplus_cli /clr, /clr:pure, /clr:safe 옵션 주면 정의. 
__COUNTER__ 빌드 할때마다 1씩 증가하는 매크로. PCH에 저장됨. 
__cplusplus C++사용할 때 정의 됨 
_CPPLIB_VER C++ 표준 라이브러리 버전 
_CPPRTTI RTTI 사용하면 정의 됨 
_CPPUNWIND 예외 처리 사용하면 정의 됨 
_DEBUG 디버그 모드 (/LDd, /MDd, /MTd 옵션 주면 됨) 
_DLL 다중 쓰레드 버전의 DLL(/MD, /MDd 옵션)사용할 때 정의 
__FUNCDNAME__ 매크로가 사용된 함수의 decorated name (/EP나 /P옵션이 없어야 함) 
__FUNCSIG__ 매크로가 사용된 함수의 signature (/EP나 /P옵션이 없어야 함) 
__FUNCTION__ 매크로가 사용된 함수의 이름 (/EP나 /P옵션이 없어야 함)

아~ 귀찮어, 졸려, 담배 땡겨, 배불러, 안해. 나머진 MSDN의 Predefined Macros 항목에서 찾아보슈.

_INTEGRAL_MAX_BITS 
_M_ALPHA 
_M_CEE 
_M_CEE_PURE 
_M_CEE_SAFE 
_M_IX86 
_M_IA64 
_M_IX86_FP 
_M_MPPC 
_M_MRX00 
_M_PPC 
_M_X64 
_MANAGED 
_MFC_VER 
_MSC_EXTENSIONS 
_MSC_VER 
__MSVC_RUNTIME_CHECKS 
_MT 
_NATIVE_WCHAR_T_DEFINED 
_OPENMP 
_VC_NODEFAULTLIB 
_WCHAR_T_DEFINED 
_WIN32 
_WIN64 
_Wp64

'NativeCode > api' 카테고리의 다른 글

Deadlock 4가지 조건  (0) 2010.03.19
Synchronization Function  (0) 2010.03.19
사용법  (0) 2010.03.18
LoadLibrary  (0) 2010.03.18
Hooking  (0) 2010.03.18

파일 다운로드!:: SQL_Lite.zip 


 CppSQLite3DB dbConnection;

 try
 {
      dbConnection.open("UserList.db3");

      int nRows = dbConnection.execDML("insert into userinfo values ('한효주', '한국');");
      cout << nRows << " rows inserted" << endl;


     CppSQLite3Query q = dbConnection.execQuery("select * from userinfo;");

     for (int fld = 0; fld < q.numFields(); fld++)
    {
        cout << q.fieldName(fld) << "(" << q.fieldDataType(fld) << ")|";
    }
    cout << endl;

    while (!q.eof())
    {
       cout << q.fieldValue(0) << "|";
       cout << q.fieldValue(1) << "|" << endl;
       q.nextRow();
    }

   nRows = dbConnection.execDML("delete from userinfo where user_name = '한효주';");
   cout << nRows << " rows deleted" << endl;

 }
 catch (CppSQLite3Exception& e)
 {
      cerr << e.errorCode() << ":" << e.errorMessage() << endl;
 }

'NativeCode > SQLite Cpp' 카테고리의 다른 글

SQL Query  (0) 2010.03.18
SqlConnection  (0) 2010.03.18
SqlCommand  (0) 2010.03.18

CppSQLite3DB m_DB;

char query[ 255 ];

try

{

m_DB.open( "c:\aaa.db" ); // 데이터 베이스 열기


m_DB.execDML( "create table Tcp(num int, SrcAddr char(16), DstAddr char(16), SrcPort int, DstPort int, TcpLen int, Time char(20)) " ); 

// 테이블 생성

sprintf( query, "insert tcp values( %d, 'aaa', 'bbb', 10, 20, 30, '%d시간' );", i, 30 ); // 입력 쿼리문 생성
m_DB.execDML( query ); // 쿼리 실행

}


데이터 읽기

CppSQLite3Query q = m_DB.execQuery( "select * from Tcp;" );


while( !q.eof() )

{

data[ 0 ] = const_cast< char* >( q.fieldValue( 0 ) );

data[ 1 ] = const_cast< char* >( q.fieldValue( 1 ) );

data[ 2 ] = const_cast< char* >( q.fieldValue( 2 ) );

data[ 3 ] = const_cast< char* >( q.fieldValue( 3 ) );

data[ 4 ] = const_cast< char* >( q.fieldValue( 4 ) );

data[ 5 ] = const_cast< char* >( q.fieldValue( 5 ) );

  data[ 6 ] = const_cast< char* >( q.fieldValue( 6 ) );
  q.nextRow();

}


'NativeCode > api' 카테고리의 다른 글

Synchronization Function  (0) 2010.03.19
Win Version & Macro  (0) 2010.03.18
LoadLibrary  (0) 2010.03.18
Hooking  (0) 2010.03.18
윈도우 핸들 얻기  (0) 2010.03.18

Algorithm

#include <algorithm>

sort( b, e ) // 범위 [b, e]에 의해 정의되는 요소들을 재 정렬시킨다.

max( b, e ) // b와 e중 더 큰 값을 리턴시킨다.

min( b, e ) // b와 e중 더 작은은 값을 리턴시킨다.

'NativeCode > C++ STL' 카테고리의 다른 글

STL find()와 sort() 사용하기  (0) 2010.07.27
list  (0) 2010.03.18
Sequential Container  (0) 2010.03.18
stl C++ Exception Class  (0) 2010.03.18
String  (0) 2010.03.18

list


#include <list>


list<Student_info> extract_failslist<Student_info>& students )

{

list<Student_info> fail;

list<Student_info>::iterator iter = students.begin();


         while( iter != students.end() )

{

if( fgrade( *iter) )

{

fail.push_back( *iter );

iter = students.erase( iter );

}

      else

++iter;

}


return fail;

}


list sort 함수

list<Student_info> students;

students.sort( compare );


list<int> l;

l.sort(), l.sort( cmp ) // list 의 타입에 대한 < 연산자를 사용하거나, cmp 함수를 사용하여 l의 요소들을 정렬합니다.



// 반복자 미 사용

forlist<Student_info>::size_type i = 0; i != students.size(); ++i )

cout << students[ i ].name << endl;


// 반복자 iterator 사용

forlist<Student_info>::const_iterator iter = students.begin(); iter != students.end(); ++iter )

cout << iter->name << endl;


'NativeCode > C++ STL' 카테고리의 다른 글

STL find()와 sort() 사용하기  (0) 2010.07.27
Algorithm  (0) 2010.03.18
Sequential Container  (0) 2010.03.18
stl C++ Exception Class  (0) 2010.03.18
String  (0) 2010.03.18

모든 순차 컨테이너들과 string 타입은 다음과 같은 연산들을 제공한다.


container<T>::iterator

container<T>::const_iterator // 이 컨테이너에 대한 반복자의 타입명

container<T>::size_type // 이 컨테이너의 인스턴스가 가질 수 있는 최대 사이즈 갑을 저장할 수 있는 타입의 이름

c.begin()

c.end() // 컨테이너의 첫 번째 및 마지막 요소를 가리키는 반복자

c.rbegin()

c.rend() // 컨테이너의 요소를 역순으로 접근할 수 있도록 컨테이너의 마지막 및 (하나 이전의) 첫 번째 요소를 가리키는 반복자

container<T> c();

container<T> c( c2 ); // 빈 컨테이너로서의 c를 정의하거나, 만약 주어진다면, c2의 복사본으로서의 c를 정의합니다.

container<T> c( n ); // T의 타입에 따라 값지정-초기화된 n개의 요소들을 갖는 컨테이너로서의 c를 정의합니다. 만약 T가 클래스 타입이라면, 이 클래스 타입에 따라 요소들이 어떻게 초기화될 것인지가 결정됩니다. 만약 T가 내장된 연산 타입이라면, 요소들은 0으로 초기화 됩니다.


container<T> c( n, t ); // t의 복사본인 n 개의 요소들을 갖는 컨테이너로서의 c를 정의합니다.

container<T> c( b, e ); // b, e 범위의 반복자로 얻어진 요소들의 복사본을 담는 컨테이너를 생성합니다.

c = c2 // 컨테이너 c의 내용을 컨테이너 c2의 복사본으로 변경합니다.

c.size() c의 요소들의 개수를 size_type 으로 리턴합니다.

c.empty() c에 요소가 하나도 없는지 알려주는 함수

c.insert( d, b, e ) // b, e 범위의 반복자가 가리키는 요소들을 복사해서 d 바로 앞에 삽입시킨다.

c.erase( iterator )

c.erase( b, e ) // 컨테이너 c로부터 iterator가 기리키는 요소, 또는 (b, e ) 가 나타내는 범위의 요소들을 삭제한다. 이 연산은 list에 대해서는 빠르지만, vector 및 string에 대해서는 느릴 수 있습니다. 왜냐하면, 이러한 타입에 대해서는 삭제된 요소 다음에 있는 모든 요소들을 복사하는 작업이 필요하기 때문입니다. list에 대해서는 삭제된 요소에 대한 반복자들만 무효화되지만, vector와 string에 대해서는 삭제된 요소의 다음에 위치한 요소들을 가리키는 모든 반복자들이 무효화 됩니다.

c.push_back(t) // c의 끝을 가리키는 요소에 값 t를 추가합니다.


임의 접근을 지원하는 컨테이너들과 string 타입은 다음의 기능을 제공합니다. 

c[n] // 컨테이너 c로부터 n의 위치에 있는 문자를 얻습니다.



반복자 연산

*it // 반복자 iterator를 역참조하여 iterator가 가리키는 위치에 저장된 값을 얻습니다. 이 연산은 보통 it->x 로 사용이됩니다.

++it, it++ 반복자를 증가시켜 컨테이너의 다음 요소를 가리키게 합니다.

b == e, b != e // 두 반복자가 동일한지, 동일하지 않은지 비교합니다.


'NativeCode > C++ STL' 카테고리의 다른 글

Algorithm  (0) 2010.03.18
list  (0) 2010.03.18
stl C++ Exception Class  (0) 2010.03.18
String  (0) 2010.03.18
Vector  (0) 2010.03.18

logic_error

domain_error

invalid_argument

length_error

out_of_range

runtime_error

range_error

overflow_error

underflow_error


e.what() 오류를 발생시킨 것이 무엇인지를 설명하는 값을 리턴합니다. 

'NativeCode > C++ STL' 카테고리의 다른 글

Algorithm  (0) 2010.03.18
list  (0) 2010.03.18
Sequential Container  (0) 2010.03.18
String  (0) 2010.03.18
Vector  (0) 2010.03.18

String

#include <string>

s1 < s2 string 인 s1과 s2를 사전 검색 순서로 비교합니다.

s.width( n ) 다음 번 출력에서( n이 생력되면 변화 없음), 스트림 s의 넓이를 n으로 설정합니다. 출력의 오른쪽에 주어진 넓이만큼의 공백이 덧붙여집니다. 이전 넓이를 리턴합니다. 표준 출력 연산자는 기존의 넓이 값을 사용하며, width(0)를 사용하면 넓이를 리셋시킵니다.


s.substr( i, j ) // ( i ~ i + j ) 범위의 인덱스에 해당하는 s의 문자들을 복사하여 새로운 string을 생성합니다.

getline( is, s ) // is로부터 한 라인의 입력을 받아들여 s에 저장합니다.

s += s2 // s를 s + s2의 값으로 변경합니다.


'NativeCode > C++ STL' 카테고리의 다른 글

Algorithm  (0) 2010.03.18
list  (0) 2010.03.18
Sequential Container  (0) 2010.03.18
stl C++ Exception Class  (0) 2010.03.18
Vector  (0) 2010.03.18

Vector

#include <vector>

// 벡터는 임의 접근에 대해 최적화되어 있다. 최적화의 대가로, 벡터의 끝이 아닌 다른 위치에 요소를 삽입하고 삭제하는 작업은 매우 느리다.

vector<int> vec_int; // int 형의 빈 vector 생성

vec_int.begin() // vec_int의 첫 번째 요소를 나타내는 값을 리턴
vec_int.end() // vec_int의 마지막 요소를 나타내는 값을 리턴

vec_int.push_back( e ) // vector에 e로 초기화된 요소 하나를 추가

vec_int[ i ] // i 위치에 저장된 값을 리턴

vec_int.size() // vec_int 에 들어있는 요소들의 개수를 리턴

vec_int.erase( vec_int.begin() + i ) // 시작위치부터 i번째 떨어져 있는 값을 지움


반복자

  • 컨테이너와 컨테이너 안에 있는 요소를 구별시킵니다.
  • 그 요소의 값을 확인할 수 있습니다.
  • 컨테이너 안에 있는 요소들 간에 이동을 할 수 있는 연산을 제공합니다.
  • 컨테이너가 효과적으로 처리할 수 있는 방식으로 가용한 연산들을 한정시킵니다.


// 반복자 미 사용

forvector<Student_info>::size_type i = 0; i != students.size(); ++i )

cout << students[ i ].name << endl;


// 반복자 iterator 사용

forvector<Student_info>::const_iterator iter = students.begin(); iter != students.end(); ++iter )

cout << ( iter->name << endl;


v.reserve( n ) // n 개의 요소를 담을 수 있는 공간을 확보합니다. 하지만, 초기화하지 않습니다. 이 연산은 컨테이너의 크기를 변화시키지는 않습니다. 단지 반복적인 insert나 push_back으로 인한 빈번한 메모리 할당을 막기 위해서 사용합니다.

v.resize( n ) // v의 사이즈를 n이 되도록 만듭니다. 만약 n이 현재 v의 사이즈보다 작다면, n 이하의 요소들은 vector에서 제거됩니다. 만약 n이 현재 사이즈보다 크다면, 새로운 요소들이 v에 추가되고 v의 타입에 의해 적당한 값으로 초기화 됩니다.

'NativeCode > C++ STL' 카테고리의 다른 글

Algorithm  (0) 2010.03.18
list  (0) 2010.03.18
Sequential Container  (0) 2010.03.18
stl C++ Exception Class  (0) 2010.03.18
String  (0) 2010.03.18

Snap9.bmp Snap8.bmp

'NativeCode > mfc' 카테고리의 다른 글

D-H,appy :: MFC list control 사용  (2) 2010.07.28
MySQL C++, MFC에서 사용하기  (0) 2010.06.17
Font 바꾸기  (0) 2010.03.18
CFile  (0) 2010.03.18
Modal Vs Modless  (0) 2010.03.18

 CFont font;    //CFont object 확보

 font.CreateFont(          // object의 생성
      20,                  // 문자 폭
      20,                  // 문자 높이 
      0,                   // 기울기 각도
      0,                   // 문자 방향
      FW_HEAVY,            // 문자 굵기
      FALSE,               // 문자 기울림 모양
      FALSE,               // 밑 줄
      FALSE,               // 취소선
      DEFAULT_CHARSET,     // 문자 셋
      OUT_DEFAULT_PRECIS,  // 출력 정확도
      CLIP_DEFAULT_PRECIS, // 킬립핑 정확도
      DEFAULT_QUALITY,     // 출력의 질
      DEFAULT_PITCH,       // 자간 거리
      "궁서"               // 문자 모양
   );

 
 pDC->SelectObject(&font);     //pDC에 font 등록

 pDC->SetTextColor(RGB(0,0,255));


 pDC->TextOut(100,200,"청산은 나를 보고 말없이 살라하고");
 pDC->TextOut(100,250,"창공은 나를 보고 티없이 살라하네");
 pDC->TextOut(100,300,"사랑도 벗어놓고 미움도 벗어놓고");
 pDC->TextOut(100,350,"물처럼 바람처럼 살다 가라하네");

 
font.DeleteObject();    //font 삭제

'NativeCode > mfc' 카테고리의 다른 글

MySQL C++, MFC에서 사용하기  (0) 2010.06.17
CDC 글 쓰기  (0) 2010.03.18
CFile  (0) 2010.03.18
Modal Vs Modless  (0) 2010.03.18
Process 강제 종료 막기  (0) 2010.03.18

file.Open( "Data.txt", CFile::modeWrite | CFile::modeCreate | CFile::typeBinary );

file.Write( "BackupData\n", 13 );


for( int i = 0; i < m_FolderBackupList.GetCount(); i ++ )

{

csBuffer = m_FolderBackupList.GetAt( i );

file.Write( csBuffer, csBuffer.GetLength() );

}


file.Write( "ProtectData\n", 14 );

for( int i = 0; i < m_FolderProtectList.GetCount(); i ++ )

{

csBuffer = m_FolderProtectList.GetAt( i );

file.Write( csBuffer, csBuffer.GetLength() );

}


file.Close();

'NativeCode > mfc' 카테고리의 다른 글

CDC 글 쓰기  (0) 2010.03.18
Font 바꾸기  (0) 2010.03.18
Modal Vs Modless  (0) 2010.03.18
Process 강제 종료 막기  (0) 2010.03.18
Dialog 메인 윈도우 색 바꾸기  (0) 2010.03.18


모달

모달리스

생성방법

DoModal

Create

종료방법

EndDialog

DestroyWindow

인스턴스선언

지역변수로선언

동적으로할당

윈도우 SHOW

.ShowWindow( SW_SHOW )

->ShowWindow( SW_SHOW )


'NativeCode > mfc' 카테고리의 다른 글

Font 바꾸기  (0) 2010.03.18
CFile  (0) 2010.03.18
Process 강제 종료 막기  (0) 2010.03.18
Dialog 메인 윈도우 색 바꾸기  (0) 2010.03.18
Dialog 아무데나 누르고 창 이동  (0) 2010.03.18

PreTranslateMessage 함수를 재정의 한다. 그래서 특정 값이 들어 오면 다음 함수를 호출 하지 않고 거기서 종료!! 쉽지?


if(pMsg->message == WM_SYSKEYDOWN )

{

//Alt+F4키면무시(Alt키는 VK_KEYDOWN아니라 VK_SYSKEYDOWN으로알아내야함


if(pMsg->wParam == VK_F4)

{

return TRUE;

}

}


if(pMsg->message == WM_KEYDOWN)

{

if(pMsg->wParam == VK_ESCAPE) return TRUE;

if(pMsg->wParam == VK_RETURN) return TRUE;

}

'NativeCode > mfc' 카테고리의 다른 글

CFile  (0) 2010.03.18
Modal Vs Modless  (0) 2010.03.18
Dialog 메인 윈도우 색 바꾸기  (0) 2010.03.18
Dialog 아무데나 누르고 창 이동  (0) 2010.03.18
Dialog 항상 위  (0) 2010.03.18

CtlColor 이벤트 추가

m_Back.CreateSolidBrush( RGB( 255, 255, 255 ) );

HBRUSH CH7Dlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)

{

HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);


// TODO:  여기서 DC의 특성을 변경합니다.

hbr = ( HBRUSH )m_Back;


// TODO:  기본값이 적당하지 않으면 다른 브러시를 반환합니다.

return hbr;

}


'NativeCode > mfc' 카테고리의 다른 글

Modal Vs Modless  (0) 2010.03.18
Process 강제 종료 막기  (0) 2010.03.18
Dialog 아무데나 누르고 창 이동  (0) 2010.03.18
Dialog 항상 위  (0) 2010.03.18
CRichEditCtrl  (0) 2010.03.18

void CH7Dlg::OnLButtonDown(UINT nFlags, CPoint point)

{

// TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.

CDialog::OnLButtonDown(nFlags, point);

PostMessage( WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM( point.x, point.y ) );

}


void CH7Dlg::OnLButtonUp(UINT nFlags, CPoint point)

{

// TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.

CDialog::OnLButtonUp(nFlags, point);

PostMessage( WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM( point.x, point.y ) );

}

두 이벤트를 추가하고 PostMessage를 해주면 끝끝

'NativeCode > mfc' 카테고리의 다른 글

Process 강제 종료 막기  (0) 2010.03.18
Dialog 메인 윈도우 색 바꾸기  (0) 2010.03.18
Dialog 항상 위  (0) 2010.03.18
CRichEditCtrl  (0) 2010.03.18
리스트 컨트롤 Column 추가 아이템 추가  (1) 2010.03.18

SetWindowPos( &CWnd::wndTopMost, 0, 0, 0, 0, SWP_NOACTIVATE );

문자열 이어서 넣기


void ChttpDlg::AppendString( const CString str )

{

int nOldLines = 0, nNewLines = 0, nScroll = 0;

long nInsertionPoint = 0;


CHARFORMAT cf;

// Save number of lines before insertion of new text

nOldLines = m_CRichEdit.GetLineCount();

// Initialize character format structure

cf.cbSize = sizeof(CHARFORMAT);

cf.dwMask = CFM_COLOR;

cf.dwEffects = 0; // To disable CFE_AUTOCOLOR

cf.crTextColor = RGB( 0, 0, 0 );


// Set insertion point to end of text

nInsertionPoint = m_CRichEdit.GetWindowTextLength();

m_CRichEdit.SetSel(nInsertionPoint, -1);


// Set the character format

m_CRichEdit.SetSelectionCharFormat(cf);

// Replace selection. Because we have nothing 

// selected, this will simply insert

// the string at the current caret position.

m_CRichEdit.ReplaceSel(str);


// Get new line count

nNewLines = m_CRichEdit.GetLineCount();


// Scroll by the number of lines just inserted

nScroll = nNewLines - nOldLines;

m_CRichEdit.LineScroll(nScroll);

}

CListCtrl 아이템 다 지우기

DeleteAllItems();


Column추가

ListCtrl.InsertColumn( 0, "aaaa", 0, 100 );

ListCtrl.InsertColumn( 1, "bbbb", 0, 100 );

ListCtrl.InsertColumn( 2, "cccc", 0, 100 );


아이템 추가

LVITEM item;

Zeromemory( &item, sizeof( LVITEM ) );

item.iItem = 0;

item.pszText = "aaa";

for( int i = 1; i < 3; i ++ )

{

    ListCtrl.SetItemText( i, j, "다음문자열" );

}                                            


asd.bmp

'NativeCode > mfc' 카테고리의 다른 글

Dialog 항상 위  (0) 2010.03.18
CRichEditCtrl  (0) 2010.03.18
리스트 컨트롤 GridLine 추가하기  (1) 2010.03.18
리스트 컨트롤 값 얻기 & 검색하기  (1) 2010.03.18
리스트 컨트롤 시스템 아이콘 삽입  (0) 2010.03.18

z_AttrList.SetExtendedStyle(LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT); 

값 얻기 : m_list.GetText( 1, strFind );

m_list.FindStringExact( -1, "문자열" );

m_List.FindString( -1, "문자열" );


if( m_List.FindString( -1, "문자열" ) != LB_ERR ) // 문자열 찾았을 때


GetNextItem( -1, LVNI_SELECTED ) // 선택한 아이템 번호 얻기



CFileFind cFinder;

SHFILEINFO sfi;

BOOL bWorking;

int index = 0;

HIMAGELIST hImageList;

hImageList = ( HIMAGELIST )SHGetFileInfo( *pFolder, 0, &sfi, sizeof(SHFILEINFO), SHGFI_SYSICONINDEX | SHGFI_SMALLICON );

if( hImageList )

{

  m_imgShareSmall.Attach( hImageList );

}

else

{

::AfxMessageBox( "파일을 갖고 올 수 없습니다." );

return -1;

}


m_CListCtrlFileList.DeleteAllItems();

m_CListCtrlFileList.SetImageList( &m_imgShareSmall, LVSIL_SMALL );

*pFolder += "\\*.*";

bWorking = cFinder.FindFile( *pFolder );


while( bWorking )

{

bWorking = cFinder.FindNextFile();

SHGetFileInfo( cFinder.GetFilePath(), 0, &sfi, sizeof( SHFILEINFO ), 

SHGFI_DISPLAYNAME | SHGFI_TYPENAME | SHGFI_SYSICONINDEX | SHGFI_SMALLICON ); 

m_CListCtrlFileList.InsertItem( index, sfi.szDisplayName, sfi.iIcon );


if( !cFinder.IsDirectory() )

{

m_CListCtrlFileList.SetItemText( index++, 1, "파일" );

}


else

{

m_CListCtrlFileList.SetItemText( index++, 1, "폴더" );

}

}


m_imgShareSmall.Detach();


while (bWorking)

    {

        bWorking = finder.FindNextFile();

        SHGetFileInfo(finder.GetFilePath(), 

            0, 

            &sfi, 

            sizeof(SHFILEINFO), 

            SHGFI_DISPLAYNAME | SHGFI_TYPENAME| SHGFI_SYSICONINDEX | SHGFI_SMALLICON); 

        ndx = AddItem1(finder, sfi, ndx);

    }


 ndx = m_list.InsertItem(ndx, sfi.szDisplayName, sfi.iIcon);

'NativeCode > mfc' 카테고리의 다른 글

리스트 컨트롤 값 얻기 & 검색하기  (1) 2010.03.18
리스트 컨트롤 시스템 아이콘 삽입  (0) 2010.03.18
리스트 컨트롤 색상 다루기  (1) 2010.03.18
CTRL 값 얻기  (0) 2010.03.18
배경 그림 넣기  (0) 2010.03.18

[MFC 컨트롤] 리스트 컨트롤 색상 다루기

간단하지만 복잡하기도한 리스트 컨트롤 색상 다루기입니다.


칼럼과 행 별로 색상을 컨트롤할 수 있는데요,


일단 코드를 보시면서 말씀드릴게요,


밑의 코드는 제가 프로젝트하던 코드의 일부분입니다 :)


헤더 파일에


 afx_msg void OnCustomdrawList(NMHDR* pNMHDR, LRESULT* pResult);



이렇게 추가해 주시구요,


메시지맵을 등록해야 겠죠,


BEGIN_MESSAGE_MAP 밑에 이렇게 입력해줍니다.


ON_NOTIFY(NM_CUSTOMDRAW, IDC_RESULT/*컨트롤 리소스 ID*/, OnCustomdrawList)


그리고 사용자 함수를 추가해서 코딩해 줍니다.


void CNetManagerView::OnCustomdrawTcpList(NMHDR* pNMHDR, LRESULT* pResult)
{
 CString strProtocol,strRSTFIN;
 BOOL bEmerFlag = FALSE;
 
 NMLVCUSTOMDRAW* pLVCD = (NMLVCUSTOMDRAW*)pNMHDR;
 
 strProtocol = m_ctrlTCPlist.GetItemText(pLVCD->nmcd.dwItemSpec, 1);
 strRSTFIN = m_ctrlTCPlist.GetItemText(pLVCD->nmcd.dwItemSpec, 9);
 
 if( (strRSTFIN.Find("RST") != -1) || (strRSTFIN.Find("FIN") != -1) )
 {
  bEmerFlag=TRUE;
 }
 
    *pResult = 0;
 
    if ( CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage )
        *pResult = CDRF_NOTIFYITEMDRAW;
 
    else if ( CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage )
    {
       if( bEmerFlag )        // TCP && 긴급 플래그 일떄
       {
        pLVCD->clrText = RGB(255,102,102);
       }
       pLVCD->clrTextBk = RGB(237,255,255);
  
       if( !bEmerFlag )        // 긴급 플래그가 아닐때
       {
        pLVCD->clrText   = RGB(0, 0, 0);
       }
       *pResult = CDRF_DODEFAULT;
    }
}



프로그램 화면캡쳐의 일부분입니다. 저런식으로 색상을 변경할 수 있습니다.


경우에 따라서 색상을 입히시면 됩니다,


RGB값은 임의로 주시면 되구요, (RGB 색상 표를 참고하세요 )


기본 리스트 컨트롤 배경 색상 및 글자 색상 글자 배경 색상은


API를 제공하고 있습니다.


SetBkColor(), SetTextBkColor() 등을 MSDN을 참고하셔서


사용하시면 됩니다.




[리스트컨트롤-기초05 뽀나스] 리소스 이미지 배경 깔기 & 투명 라벨


OnInitDialog에 추가한 코드는 아래와 같다.

말하자면 전나 쉽다!


    //

    if (!AfxOleInit())

    {

        AfxMessageBox("Unable to initialize OLE.\nTerminating application!");

        return FALSE;

    }


    TCHAR szBuffer[_MAX_PATH];

    VERIFY(::GetModuleFileName(AfxGetInstanceHandle(), szBuffer, _MAX_PATH));

    CString sPath;

    sPath.Format(_T("res://%s/%s/#%d"), szBuffer, _T("JPG"), IDR_JPG1);

    m_list.SetBkImage((LPTSTR)(LPCTSTR)sPath);


    //

    m_list.SetTextBkColor((COLORREF)-1);

    m_list.SetTextColor(GetSysColor(COLOR_3DDKSHADOW));


설명이 필요없다. 걍 보면 안다.




즐감~~!!



listCtrl01.zip




리스트 컨트롤 헤더에 인디케이터 집어넣기

리스트 컨트롤을 사용하다가 보면 컬럼을 클릭했을때 보통 정렬 기능을 구현하게 됩니다.

 정렬기능을 구현해놓고 보면 내림차순인지 오름차순 정렬인지는 사용자가 리스트안에 있는 데이터를 직접 봐야하는데 이것을 시각적으로 표현하기 위해서 보통

 인디케이터를 삽입합니다.  이 기능을 구현하기 위해서 미리 할일은 하나도 없습니다. ^^

 리스트 컨트롤의 어떤 속성도 건드릴 필요없이 바로 몇 줄의 코딩으로 가능합니다.


샘플 코드

다음과 같은 함수를 하나 추가하시고요

void ?????::SetIndicatorOnColumn(int Col)

{

    CHeaderCtrl* pHeader = ????? (리스트컨트롤 이름).GetHeaderCtrl();


    for(int i=0; i<pHeader->GetItemCount(); i++) {

        HDITEM hItem;


        pHeader->GetItem(i, &hItem);


        if(i == Col) {

            hItem.mask = HDI_FORMAT | HDI_BITMAP;

            hItem.fmt |= HDF_BITMAP | HDF_STRING | HDF_BITMAP_ON_RIGHT;

            hItem.hbm = (HBITMAP)LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_DOWN), IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);

            pHeader->SetItem(i, &hItem);


        }

        else {

            hItem.mask = HDI_FORMAT ;

            hItem.fmt = HDF_STRING;

            hItem.hbm = NULL;

            pHeader->SetItem(i, &hItem);

        }

    }

}


OnColumnClick 함수내에 다음과 같은 코드를 추가합니다.


void ????::OnColumnclickList(NMHDR* pNMHDR, LRESULT* pResult)

{

    NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;

    

    int Col = pNMListView->iSubItem;

    this->SetIndicatorOnColumn(Col);


    (보통 이곳에는 소트에 관련된 함수를 콜하는 코드가 들어가죠)

   ....

   ....


   *pResult = 0;

}


다음과 같은 것으로 작업은 완성 (단 비트맵 리소스로 IDB_UP 혹은 IDB_DOWN의 이름으로 화살표를 그려주어야 합니다. 크기는 5*10 정도가 적당한거 같군요.)


참고로 comctl32.dll 6.0버젼부터는 HDF_SORTDOWN, HDF_SORTUP 이라는 플래그가 추가 되었습니다.




리스트 뷰 간격 조절


p, td, ul, ol, li { font-size:12px; line-height:140%; margin-top:0; margin-bottom:0; } body { font-size:12px; }

CListCtrl 경우는 멤버중 SetIconSpacing() 함수 사용 하면 될것이고.

리스트뷰 일경우에는 ListView_SetIconSpacing 매크로 사용 하시면 됩니다.


단 리스트의 스타일(간단히, 자세히, 아이콘....)에 따라서 지원이 안될수 도 있습니다..






리스트 컨트롤의 컬럼별로 소트하기


//생성자에서 정/역방향 소팅을 위해
//m_bSort=NULL;
//로 셋팅해주시고
//소트하기위한 정보를 가진 클래스를 하나 만듭니다. 뭐 스트럭쳐로 해도 상관없겠져
//스트럭처로 하시면 public:이부분 없어도 되니..
//생성자와 SORT를 위한 참조 변수도 만들구여
class CSortData{
public:

    CSortData(CString str,DWORD dw);
    ~CSortData(){};

    CString m_strText;
    DWORD m_dw;
    
};

CSortData::CSortData(CString str,DWORD dw)
{
    m_strText=str;
    m_dw=dw;
}

//콜백함수를 정의합니다.
//콜백함수에서 데이터를 비교하고 비교한 값을 리턴합니다.
//lParamSort 인자에는 ASCENDING할것인지 DESCENDING할 것인가하는 정보를 받습니다.

static int CALLBACK MyCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
    CSortData *pLc1=(CSortData*)lParam1;
    CSortData *pLc2=(CSortData*)lParam2;
    int nReturn=pLc1->m_strText.Compare(pLc2->m_strText);
    if(lParamSort)
        return nReturn;
    else
        return -nReturn;
}

//리스트 컨트롤 아이템 길이를 구해와서 각각의 아이템에 SetItemData를 이용하여 스트럭처정보를
//넣어줍니다.(나중에 소트하기위해)
//그리고 SortItems함수를 호출하는데 이때 위에서 정의한 콜백함수의 포인터를 인자로 넣어주고
//ASCENDING 혹은 DESCENDING할것인지에 대한 boolean값을 같이 보내어 줍니다.
//그럼 OS가 알아서 콜백함수를 계속 호출해서 비교정보를 받아가겠지여..
//소트가 완료된다음에는 
//동적할당한 CSortData 클래스를 메모리에서 삭제해줍니다.
BOOL CTestDlg::SortData(int nCol,BOOL bSort)
{
    LkListCtrl *pLc=(LkListCtrl*)GetDlgItem(IDC_LIST_DATA);
    int totItems = pLc->GetItemCount();
// Callback Item Setting
    for(int i=0; i<totItems; i++) 
    {
        DWORD dw = pLc->GetItemData(i);
        CString txt = pLc->GetItemText(i, nCol);
        pLc->SetItemData( i, (DWORD) new CSortData(txt,dw) );
    }
    if(m_bSort)
        pLc->SortItems(MyCompare, bSort);
    else
    {
        pLc->SortItems(MyCompare, bSort);
    }
    //    m_bSort=!m_bSort;

    for(i=0; i<totItems; i++)
    {
        CSortData* pItem = (CSortData*)pLc->GetItemData(i);
        ASSERT( pItem );
        pLc->SetItemData(i, pItem->m_dw);
        delete pItem;
    }

    return TRUE;
}

//컬럼해드를 클릭했을때 우리가 정의한 SortData라는 함수를 호출하도록 클래스 위저드를 
//이용하여 통지메세지인 LVN_COLUMNCLICK 를 오버라이딩 합니다. 아니면 직접 코딩하셔도 무방하지여.
//BEGIN_MESSAGE_MAP(CTestDlg,CDialog)
//    ON_NOTIFY(LVN_COLUMNCLICK,IDC_LIST_DATA, OnColumnclickListData)
//END_MESSAGE_MAP()
//일케 직접하셔도 되겠져..

//호출시에 몇번째 컬럼인지에 대한 정보와 정방향소트인지, 역방향 소트인지를 결정지어 보내줍니다.
//여기서는 클릭할때마다 바뀌게 해놨습니다.
void CTestDlg:OnColumnclickListData(NMHDR* pNMHDR, LRESULT* pResult) 
{
    NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;

    if(!SortData(pNMListView->iSubItem,m_bSort))
        return ;
    m_bSort=!m_bSort;
    *pResult = 0;
}

//자 이렇게 하고 (리스트컨트롤에 자료가 들어있음을 가정하고)
//컴파일해서 컬럼해드를 클릭하여 보면 정/역방향 소팅이 되는것을 눈으로 확인하실수 있으실겁니다.

//약간이라도 도움이 되시길.
//그리고 혹 잘못된 점이 있으면 꼭 알려주세여~
//명절 잘보내시길~~
likehood@hanmail.net
송영배




몇가지 팁

 1. 특정 ROW 포커스 주기
 2. 특정 ROW로 가기
 3. 헤더 컬럼수 얻어오기
 4. 컬럼의 너비를 이쁘게 주기
 5. 한줄 쭉 선택되게 하기, 그리드 라인 주기
 6. 선택한 아이템(ROW)를 지우기
 7. 두 아이템을 스왑 하기
 8.기존에 선택되어있는 것을 해체하기



 1. 특정 ROW 포커스 주기
---------------------------------------------------
 리스트 컨트롤에서 어떤 특정 Row를 선택하게 하고 싶을때
 ( 이때 선택뿐아니라 포커스도 가야 한다.
 포커스가 간다는 의미는 다음에 키다운을 하면 바로 부드럽게
 다음 아이템을 가리키도록 하는 것이다 )

   ListView_SetItemState (pListCtrl->GetSafeHwnd(),         // handle to listview
                          10,         // index to listview item
                          LVIS_FOCUSED | LVIS_SELECTED, // item state
                          0x000F);   //mask

 위와 같이 코딩하면 된다.


 2. 특정 ROW로 가기
---------------------------------------------------
 만일 원하는 Row를 스크롤을 하던 어떻게 하든 화면에 보이게
 하고 싶을때
 
 pListCtrl->EnsureVisible(15, TRUE);

 이렇게 하면 된다.


 3. 헤더 컬럼수 얻어오기
---------------------------------------------------
 헤더 컬럼의 갯수를 알고 싶을때
    CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
    int nColumnCount = pHeader->GetItemCount();

 또는 pList->GetHeaderCtrl()을 통해서 얻어올수 도 있다.


 4. 컬럼의 너비를 이쁘게 주기
---------------------------------------------------
    공백없이 잘 채워 준다.

부모 다이얼로그의 OnSize에서
void CAttrListDlg::OnSize(UINT nType, int cx, int cy) 
{
    CDialog::OnSize(nType, cx, cy);
    
    // TODO: Add your message handler code here
    if( IsWindow( z_AttrList.m_hWnd ))
    {
        z_AttrList.MoveWindow( 0, 0, cx, cy );
        z_AttrList.SetColumnWidth(1 , LVSCW_AUTOSIZE_USEHEADER);
    }
}


 5. 한줄 쭉 선택되게 하기, 그리드 라인 주기
---------------------------------------------------
 z_AttrList.SetExtendedStyle(LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT); 


 6. 선택한 아이템(ROW)를 지우기
---------------------------------------------------

CDWordArray m_anDragIndexes;    // 선택한 아이템을 기억하는
 배열

int    CAttrList::fnRemoveItem()
{

    m_anDragIndexes.RemoveAll();
    POSITION pos = GetFirstSelectedItemPosition();
    while (pos)
    {
        m_anDragIndexes.Add(GetNextSelectedItem(pos));
    }

    int nSize = m_anDragIndexes.GetSize();    
    int nRet = -1;
    if( nSize )
        nRet = m_anDragIndexes[0];    

    while( nSize-- )
        DeleteItem( m_anDragIndexes[nSize] );

    m_anDragIndexes.RemoveAll();
    return nRet;
}


 7. 두 아이템을 스왑 하기
---------------------------------------------------
void CAttrList::fnSwapItem( int nItem1, int nItem2 )
{
    int hi = nItem2;
    int lo = nItem1;
    CStringArray rowText;

    LV_ITEM lvitemlo, lvitemhi;
    CHeaderCtrl* pHeaderCtrl = GetHeaderCtrl();
    int nColCount =pHeaderCtrl->GetItemCount();
            
    rowText.SetSize( nColCount );
    int i;
    for( i=0; i<nColCount; i++)
        rowText[i] = GetItemText(lo, i);
    lvitemlo.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
    lvitemlo.iItem = lo;
    lvitemlo.iSubItem = 0;
    lvitemlo.stateMask = LVIS_CUT | LVIS_DROPHILITED |
        LVIS_FOCUSED | LVIS_SELECTED |
        LVIS_OVERLAYMASK | LVIS_STATEIMAGEMASK;
    
    lvitemhi = lvitemlo;
    lvitemhi.iItem = hi;
    
    GetItem( &lvitemlo );
    GetItem( &lvitemhi );
    
    for( i=0; i<nColCount; i++)
        SetItemText(lo, i, GetItemText(hi, i));
    
    lvitemhi.iItem = lo;
    SetItem( &lvitemhi );
    
    for( i=0; i<nColCount; i++)
        SetItemText(hi, i, rowText[i]);
    
    lvitemlo.iItem = hi;
    SetItem( &lvitemlo );
}

 8.기존에 선택되어있는 것을 해체하기
 -----------------------------------
        int nOldItem = GetSelectionMark();
        if( nOldItem > 0 )
            SetItemState( nOldItem , 0, LVIS_SELECTED);




리스트 컨트롤에 콤보박스 올려놓기


Codeguru 에 있는 내용을 약간 번역 겸 수정했습니다. 

오류 부분도 잡아내서 수정했고요 
그럼 도움이 되셨으면 합니다.  시험용 소소도 같이 올려놓습니다.
즐거운 하루 되세요.....



Step1 : CListCtrl 로부터 파생클래스를 생성한다.
    class  CMyListCtrl  : public CListCtrl   

Step 2: Define HitTestEx()
CMyListCtrl class 에 확장 HitTest 함수를 정의합니다. 이 함수는 마우스 포인터가 위치한 줄과 컬럼의 번
호를 리턴합니다. 

// Returns    - 줄의 인덱스값. 데이타가 없는 줄이면 -1 을 리턴함  .
// point    - point to be tested.
// col        - to hold the column index

int CMyListCtrl::HitTestEx(CPoint &point, int *col) const
{
    int colnum = 0;
    int row = HitTest( point, NULL );   // 기존의 HitTest 함수를 이용하여 줄의 인덱스값을 얻어
옴.

    if( col ) *col = 0;

    // LVS_REPORT 모드 인지 확인함.

    if( (GetWindowLong(m_hWnd, GWL_STYLE) & LVS_TYPEMASK) != LVS_REPORT )
        return row;

    // 보여지는 가장 윗줄과 아랫줄의 인덱스를 얻어옴 

    row = GetTopIndex();
    int bottom = row + GetCountPerPage();

    if( bottom > GetItemCount() )
        bottom = GetItemCount();

    // 컬럼의 갯수를 가져온다. 

    CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
    int nColumnCount = pHeader->GetItemCount();


    for( ;row <= bottom;row++)
    {

        // 각 줄의 아이템 영역을 잡아서 Pointer가 그 안에 위치하는지 검사한다.

        CRect rect;
        GetItemRect( row, &rect, LVIR_BOUNDS );

        if( rect.PtInRect(point) )
        {
            // 여기서는 컬럼을 뒤짐
            for( colnum = 0; colnum < nColumnCount; colnum++ )
            {
                int colwidth = GetColumnWidth(colnum);
                if( point.x >= rect.left 
                    && point.x <= (rect.left + colwidth ) )
                {
                    if( col ) *col = colnum;
                    return row;
                }
                rect.left += colwidth;
            }
        }
    }
    return -1;
}

Step 3: Drop Down List 를 생성시키는 함수 추가하기 

// ShowInPlaceList        - Drop Down List 를 생성키키는 함수명 
// Returns            - ComboBox Ctrl에 대한 포인터
// nItem            - 위치한 Cell 의 줄 인덱스
// nCol                - 위치한 Cell 의 컬럼 인덱스 
// lstItems            - A list of strings to populate the control with
// nSel                - drop down list 에서 초기에 설정될 인덱스 

CComboBox* CMyListCtrl::ShowInPlaceList( int nItem, int nCol, 
                    CStringList &lstItems, int nSel )
{
    // The returned pointer should not be saved

    // 선택된 아이템(Cell) 이 Visible 인가를 확인 
    if( !EnsureVisible( nItem, TRUE ) ) return NULL;

    // 컬럼이 유효한가를 확인  
    CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
    int nColumnCount = pHeader->GetItemCount();
    if( nCol >= nColumnCount || GetColumnWidth(nCol) < 10 ) 
        return NULL;

    // 모든 컬럼의 길이를 얻어냄 
    int offset = 0;
    for( int i = 0; i < nCol; i++ )
        offset += GetColumnWidth( i );

    CRect rect;
    GetItemRect( nItem, &rect, LVIR_BOUNDS );

    CRect rcClient;
    GetClientRect( &rcClient );
    if( offset + rect.left < 0 || offset + rect.left > rcClient.right )
    {
        CSize size;
        size.cx = offset + rect.left;
        size.cy = 0;
        Scroll( size );
        rect.left -= size.cx;
    }

    rect.left += offset+4;
    rect.right = rect.left + GetColumnWidth( nCol ) - 3 ;
    int height = rect.bottom-rect.top;
    rect.bottom += 5*height;
    if( rect.right > rcClient.right) rect.right = rcClient.right;

    DWORD dwStyle = WS_BORDER|WS_CHILD|WS_VISIBLE|WS_VSCROLL|WS_HSCROLL
                    |CBS_DROPDOWNLIST|CBS_DISABLENOSCROLL;
    CComboBox *pList = new CInPlaceList(nItem, nCol, &lstItems, nSel);
    pList->Create( dwStyle, rect, this, IDC_IPEDIT );
    pList->SetItemHeight( -1, height);
    pList->SetHorizontalExtent( GetColumnWidth( nCol ));


    return pList;
}

Step 4: Handle the scroll messages
CInPlaceList class 는 drop down list 가 포커스를 잃을때 객체를 지우고(delete) , 파괴(destroy) 하기위
해 설계되었음. 리스트 컨트롤의 스크롤바를 클릭킹 하는 것은 drop down list로 부터 포커스를 가져오지 
못함.그러므로 리스트 컨트롤의 스크롤바를 클릭함으로써 포커스를 가져오는 메시지 핸들러를 작성해야 함.

void CMyListCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
    if( GetFocus() != this ) SetFocus();
    CListCtrl::OnHScroll(nSBCode, nPos, pScrollBar);
}

void CMyListCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
    if( GetFocus() != this ) SetFocus();
    CListCtrl::OnVScroll(nSBCode, nPos, pScrollBar);
}

Step 5: 
유저가 drop down list 에서 아이템을 선택하면 LVN_ENDLABELEDIT notification 을 보냄. 따라서 다음의 메
시지 핸들러 추가 

void CMyListCtrl::OnEndLabelEdit(NMHDR* pNMHDR, LRESULT* pResult)
{
    LV_DISPINFO  *plvDispInfo = (LV_DISPINFO *)pNMHDR;
     LV_ITEM         *plvItem = &plvDispInfo->item;

    if (plvItem->pszText != NULL)
    {
        SetItemText(plvItem->iItem, plvItem->iSubItem, plvItem->pszText);
    }
    *pResult = FALSE;
}

Step 6: 
아래의 코드는 WM_LBUTTONDOWN message에 대한 핸들러임. 이 함수는 이미 다른 곳에 drop down list 가 존
재할때 현재 click 한 곳에 dorp down list를 새로 생성함. 아래 코드는 drop down list 를 생성하기전
에   LVS_EDITLABELS style 을 체크함. 이 부분을 각자에 맞게 수정되어야 함.

void CMyListCtrl::OnLButtonDown(UINT nFlags, CPoint point) 
{
    int index;
    CListCtrl::OnLButtonDown(nFlags, point);

    int colnum;
    if( ( index = HitTestEx( point, &colnum )) != -1 )
    {
        UINT flag = LVIS_FOCUSED;
        if( (GetItemState( index, flag ) & flag) == flag )
        {
            
            if( !(GetWindowLong(m_hWnd, GWL_STYLE) & LVS_EDITLABELS) )
            {
                CStringList lstItems;
                lstItems.AddTail( "First Item");
                lstItems.AddTail( "Second Item");
                lstItems.AddTail( "Third 
Item");                             // 이부분을 각자에 맞게 수정하면 됨.
                lstItems.AddTail( "Fourth Item");
                lstItems.AddTail( "Fifth Item");
                lstItems.AddTail( "Sixth Item");
                ShowInPlaceList( index, colnum, lstItems, 2 );
            }
        }
        else
            SetItemState( index, LVIS_SELECTED | LVIS_FOCUSED , 
                    LVIS_SELECTED | LVIS_FOCUSED);
    }
}

Step 7: ComboBox Class 서브 클래싱 하기  
이 클래스에 가장 필요한 부분은 유저가 아이템 선택을 끝냈을 경우  LVN_ENDLABELEDIT message 를 보내는 
기능임. 
에디트가 끝나면 자신을 삭제하기도 해야함. 
에디트 작업은 ,Esc , Enter 키가 눌렸을때 , 유저가 아이템을 선택했을 경우, 입력 포커스를 잃었을때 끝
나야 함.

 // InPlaceList.h : header file
//

/////////////////////////////////////////////////////////////////////////////
// CInPlaceList window

class CInPlaceList : public CComboBox
{
// Construction
public:
    CInPlaceList(int iItem, int iSubItem, CStringList *plstItems, int nSel);

// Attributes
public:

// Operations
public:

// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CInPlaceList)
    public:
    virtual BOOL PreTranslateMessage(MSG* pMsg);
    //}}AFX_VIRTUAL

// Implementation
public:
    virtual ~CInPlaceList();

    // Generated message map functions
protected:
    //{{AFX_MSG(CInPlaceList)
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
    afx_msg void OnKillFocus(CWnd* pNewWnd);
    afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
    afx_msg void OnNcDestroy();
    afx_msg void OnCloseup();
    //}}AFX_MSG

    DECLARE_MESSAGE_MAP()
private:
    int     m_iItem;
    int     m_iSubItem;
    CStringList m_lstItems;
    int     m_nSel;
    BOOL    m_bESC;                // To indicate whether ESC key was pressed
};

/////////////////////////////////////////////////////////////////////////////
// InPlaceList.cpp : implementation file
//

#include "stdafx.h"
#include "InPlaceList.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CInPlaceList

CInPlaceList::CInPlaceList(int iItem, int iSubItem, CStringList *plstItems, int nSel)
{
    m_iItem = iItem;
    m_iSubItem = iSubItem;

    m_lstItems.AddTail( plstItems );
    m_nSel = nSel;
    m_bESC = FALSE;
}

CInPlaceList::~CInPlaceList()
{
}


BEGIN_MESSAGE_MAP(CInPlaceList, CComboBox)
    //{{AFX_MSG_MAP(CInPlaceList)
    ON_WM_CREATE()
    ON_WM_KILLFOCUS()
    ON_WM_CHAR()
    ON_WM_NCDESTROY()
    ON_CONTROL_REFLECT(CBN_CLOSEUP, OnCloseup)
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CInPlaceList message handlers

int CInPlaceList::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
    if (CComboBox::OnCreate(lpCreateStruct) == -1)
        return -1;
    
    // Set the proper font
    CFont* font = GetParent()->GetFont();
    SetFont(font);

    for( POSITION pos = m_lstItems.GetHeadPosition(); pos != NULL; )
    {
        AddString( (LPCTSTR) (m_lstItems.GetNext( pos )) );
    }
    SetCurSel( m_nSel );
    SetFocus();
    return 0;
}

BOOL CInPlaceList::PreTranslateMessage(MSG* pMsg) 
{
    if( pMsg->message == WM_KEYDOWN )
    {
        if(pMsg->wParam == VK_RETURN 
                || pMsg->wParam == VK_ESCAPE
                )
        {
            ::TranslateMessage(pMsg);
            ::DispatchMessage(pMsg);
            return TRUE;                // DO NOT process further
        }
    }
    
    return CComboBox::PreTranslateMessage(pMsg);
}

void CInPlaceList::OnKillFocus(CWnd* pNewWnd) 
{
    CComboBox::OnKillFocus(pNewWnd);
    
    CString str;
    GetWindowText(str);

    // Send Notification to parent of ListView ctrl
    LV_DISPINFO dispinfo;
    dispinfo.hdr.hwndFrom = GetParent()->m_hWnd;
    dispinfo.hdr.idFrom = GetDlgCtrlID();
    dispinfo.hdr.code = LVN_ENDLABELEDIT;

    dispinfo.item.mask = LVIF_TEXT;
    dispinfo.item.iItem = m_iItem;
    dispinfo.item.iSubItem = m_iSubItem;
    dispinfo.item.pszText = m_bESC ? NULL : LPTSTR((LPCTSTR)str);
    dispinfo.item.cchTextMax = str.GetLength();

    GetParent()->GetParent()->SendMessage( WM_NOTIFY, GetParent()->GetDlgCtrlID(), (LPARAM)
&dispinfo );

    PostMessage( WM_CLOSE );
}

void CInPlaceList::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
    if( nChar == VK_ESCAPE || nChar == VK_RETURN)
    {
        if( nChar == VK_ESCAPE )
            m_bESC = TRUE;
        GetParent()->SetFocus();
        return;
    }
    
    CComboBox::OnChar(nChar, nRepCnt, nFlags);
}

void CInPlaceList::OnNcDestroy() 
{
    CComboBox::OnNcDestroy();
    
    delete this;
}

void CInPlaceList::OnCloseup() 
{
    GetParent()->SetFocus();
}




리포트 스타일의 리스트 콘트롤에 행간 높이 조절

 리스트 콘트롤의 행간 높이를 조절하고자 할때,
 원래 윈도우가 날려주는 메세지가 있지만, CListCtrlView 를 이용하는경우 도움이 전혀 안됩니다.
 이경우 마지막 방법은 이미지 리스트를 이용하는 것입니다.

         CImageList m_image;

    ....
         CListCtrl &m_list=GetListCtrl();
    m_image.Create(1,20,ILC_COLORDDB,1,0); 
    list.SetImageList(&m_image,LVSIL_SMALL);
  .......

 을 써서 Y 크기를 조절해서 크기를 바꿀 수 있습니다.
 메세지를 생성하는게 제일 좋은데 어쩔 수 없네요



 그리고

ListView_SetExtendedListViewStyle(list, LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_SUBITEMIMAGES);

 을 이용하시면  ROW 전체를 선택하거나, GRID 를 표시해주고,  서브아이템에 이미지 표시하기 등이 가능해
집니다.


BOOL ListCtrl_ModifyExtendedStyle(CListCtrl&   p_rListCtrl,
                                   const DWORD  p_dwStyleEx,
                                   const bool   p_bAdd)
{
    HWND t_hWnd = p_rListCtrl.GetSafeHwnd();
    DWORD t_dwStyleEx = ListView_GetExtendedListViewStyle(t_hWnd);
 
    if(p_bAdd)
    {
        if(0 == (p_dwStyleEx & t_dwStyleEx))
        {
            // add style
            t_dwStyleEx |= p_dwStyleEx;
        }
    }
    else
    {
        if(0 != (p_dwStyleEx & t_dwStyleEx))
        {
            // remove style
            t_dwStyleEx &= ~p_dwStyleEx;
        }
    }
 
    ListView_SetExtendedListViewStyle(t_hWnd, t_dwStyleEx);
 
    return true;
}  


리스트콘트롤에서 원하는 값을 맨위로 오게 스크롤 하기

void CMyListView::SelectListItem(CString text) 

CListCtrl &list = GetListCtrl(); 
LVFINDINFO info; 
int index; 
POINT p; 

info.flags = LVFI_PARTIAL|LVFI_STRING; 
info.psz = text; 

index = list.FindItem(&info) - 1; 
list.SetItemState(index, LVIS_SELECTED | LVIS_FOCUSED, LVIF_STATE); 

list.GetItemPosition(index, &p); 
list.Scroll((CSize)p); 



콘트롤에 멤버 변수를 설정해 놓았으면 맨 첫줄은 필요없구요

아래 list 변수대신 멤버변수를 사용하시면 됨다.

'NativeCode > mfc' 카테고리의 다른 글

리스트 컨트롤 시스템 아이콘 삽입  (0) 2010.03.18
리스트 컨트롤 파일 아이콘 추가하기  (1) 2010.03.18
CTRL 값 얻기  (0) 2010.03.18
배경 그림 넣기  (0) 2010.03.18
부모윈도우 호출  (0) 2010.03.18

CString csData;

m_Edit.GetWindowText( csData );

const char *pData = ( LPSTR )( LPCTSTR )csData;


'NativeCode > mfc' 카테고리의 다른 글

리스트 컨트롤 파일 아이콘 추가하기  (1) 2010.03.18
리스트 컨트롤 색상 다루기  (1) 2010.03.18
배경 그림 넣기  (0) 2010.03.18
부모윈도우 호출  (0) 2010.03.18
좌표, 영역 관련 함수  (0) 2010.03.18
private: 
          // 리소스에 등록된 비트맵 이미지를 읽어들일 비트맵 객체 
          CBitmap m_logo_bitmap; 
       
          // 대화상자의 배경에 사용할 블러쉬 객체 
          CBrush m_bk_brush;  

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

BOOL CTestPatternBrushDlg::OnInitDialog() 

    CDialog::OnInitDialog(); 
  
    SetIcon(m_hIcon, TRUE);    
    SetIcon(m_hIcon, FALSE);  
      
    // 리소스 파일에서 비트맵을 읽어 들인다. 
    m_logo_bitmap.LoadBitmap(IDB_ZZANG_LOGO); 
    // 읽어 들인 비트맵을 이용하여 패턴 블러쉬를 생성한다. 
    m_bk_brush.CreatePatternBrush(&m_logo_bitmap);     
     
    return TRUE; 
}

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

void CTestPatternBrushDlg::OnDestroy() 

    CDialog::OnDestroy(); 
      
    // 사용하던 블러쉬 객체와 비트맵 객체를 제거한다. 
    m_bk_brush.DeleteObject(); 
    m_logo_bitmap.DeleteObject(); 
}

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

BOOL CTestPatternBrushDlg::OnEraseBkgnd(CDC* pDC) 

    // 사용자가 정의한 배경 그리기 루틴이 CDialog::OnEraseBkgnd 함수보다 먼저 
    // 위치하면 기본 대화상자 그리기 루틴에 의해서 아무것도 나오지 않는다. 따라서 
    // 항상 자기가 표시하고 싶은 정보는 CDialog::OnEraseBkgnd 함수보다 아래쪽에 
    // 정의 해야한다. 
    BOOL ret = CDialog::OnEraseBkgnd(pDC); 
      
    CRect r; 
     
    // 대화상자의 크기를 얻는다. 
    GetClientRect(r); 
        
    // 현재 DC에 자신이 생성한 블러쉬를 사용하도록 설정한다. 
    CBrush *p_old_brush = pDC->SelectObject(&m_bk_brush); 
      
    // 대화상자의 크기보다 패턴블러쉬에 사용된 이미지가 작다면 Tile 형식으로 
    // 이미지가 채워진다. 
    pDC->Rectangle(r); 
      
    // 이전에 사용한던 블러쉬로 복구한다. 
    pDC->SelectObject(p_old_brush); 
   
    return ret; 
}

'NativeCode > mfc' 카테고리의 다른 글

리스트 컨트롤 색상 다루기  (1) 2010.03.18
CTRL 값 얻기  (0) 2010.03.18
부모윈도우 호출  (0) 2010.03.18
좌표, 영역 관련 함수  (0) 2010.03.18
컨트롤러 투명화 & 색 변화 시키기  (0) 2010.03.18

CUpdateServerDlg *pServerDlg = static_cast< CUpdateServerDlg * >( AfxGetMainWnd() );

'NativeCode > mfc' 카테고리의 다른 글

CTRL 값 얻기  (0) 2010.03.18
배경 그림 넣기  (0) 2010.03.18
좌표, 영역 관련 함수  (0) 2010.03.18
컨트롤러 투명화 & 색 변화 시키기  (0) 2010.03.18
CStringArray  (0) 2010.03.18

+ Recent posts