따라해보는 후킹

작성자 : 이은규

작성일 : 2003.11.02

홈페이지 : http://unkyulee.net

 

목차

1. 들어가는 글

2. 후킹이란?

3. 후킹 프로시져를 만들어 보자.

4. 후킹 프로시져를 시작, 종료하는 함수

5. 프로시져 내에서 다른 윈도우로 데이터 전송하기

6. 간단한 샘플 프로그램

 


1. 들어가는 글

 

 "그냥 실행되는 걸 보고 싶었다."

 

 예전에 했던 프로젝트의 내용 중에 사용자가 키보드로 입력하는 내용을 얻어와서 처리해야 되는 부분이 있었다. 이러한 기능을 구현하기 위해서는 후킹 이라는 기술을 사용해야 한다. 그래서 관련된 내용을 인터넷에서 찾아봤는데, 왜 이렇게 알아야 되는 내용이 많은지… 또 내용들은 어찌나 어렵던지… 후킹 구현한답시고 한달 내내 문서 읽고 인터넷 뒤지고 엄청 고생 했었다. 결국 간단한 샘플 코드를 구해서 원하는 기능을 구현 했던 기억이 있다.

 

 프로젝트 내에서 그리 중요한 부분도 아니였고, 그냥 호기심에 후킹이라는 걸 실제로 구현해보고 싶었던 것 뿐이였는데, 정말 어렵게 공부했던 것 같다.

 

 이 강좌는 순전히 호기심으로 혹은 그냥(?) 한번 후킹을 실제로 구현해 보고자 하는 사람들을 대상으로 한다. 후킹에 대한 자세한 이론은 대부분 생략할 예정이다. 대신에 이 강좌를 다 읽고 나면 후킹을 사용한, 일단 돌아가는 코드를 작성 할 수 있을 것이다.

 

 일단 돌아가는 코드를 작성하고 나면, 그 외의 내용을 익히는 것은 시간 문제일 뿐이지 않을까 생각한다. ^0^)

 


2. 후킹이란?

 

 "후킹은 도청하는 걸 예로 들면 쉽게 이해할 수 있다."

 

 후킹이란 다른 프로세스에 걸려서(Hooked) 해당 프로세스의 정보를 얻어 오거나, 변경하는 것이 가능한 기술이다. 여기서 프로세스란 좁게 봐서 "윈도우 프로시져" 혹은 "윈도우 메시지" 라고 생각하면 되겠다.

 

 예를 들어 보자. 한 아파트 건물이 있다고 하자. 그리고 이 건물을 도청하고 싶다. 그럼 전화선들이 지나가는 곳(Window Process) 에 도청 장치(후킹 프로시져)를 설치한다. 그럼 도청장치 사이로 전화 내용들이(Window Message) 지나간다. 도청 장치는 그 중 필요한 메시지를 저장하고 있거나, 필요한 곳으로 전송한다.

 

 위의 과정들에 의해서 빌딩은 도청을 당한다. 그럼 실제 후킹의 경우를 살펴보자. 일단 윈도우 메시지(전화 내용)를 후킹 한다고 하면 윈도우 메시지를 발생시키는 곳(전화선들이 지나가는 곳)에 후킹 프로시져(도청 장치)를 설치한다. 그럼 해당 윈도우에서 발생하는 메시지가 후킹 프로시져를 거쳐가게 된다. 그럼 후킹 프로시져는 메시지들을 보고 필요한 내용을 저장하던지 필요한 곳에 전달을 하면 되는 것이다.

 

 그림 한번 보자. 위 그림은 Ivo Ivanov 라는 사람이 쓴 API Hooking Reveal 라는 문서에서 퍼 가지고 왔다. 그림을 보면 Hook Driver 라는 것들이 3개가 보인다. 그림에서 현재 윈도우가 3 개가 떠있는데 각각의 윈도우에 하나씩 Hook Driver 가 붙어 있는 모양이다. 따라서 이 드라이버(후킹 프로시져) 들이 각각의 윈도우에서 오는 메시지들을 받을 수가 있는 것이다.

 

 뭔가 굉장히 많아 보인다. 하지만 결국 개발자가 만들어 주는 것은 후킹 프로시져 하나이다.

 

 여기서 키포인트는 특정 위도우가 받는 메시지를 후킹 프로시져도 받을 수 있다는 것이다. 이런 기술을 바로 후킹이라고 한다.

 

 


3. 후킹 프로시져를 만들어 보자.

 

 "이론은 끝났다. 이제 만들어 보자."

 

 후킹 프로시져… 아까부터 프로시져라는 단어가 계속 나오는데 결국 프로시져는 함수와 그 의미가 비슷하다. 따라서 후킹 프로시져라고 함은 후킹을 하는 함수라고 생각하자. 따라서 후킹 프로시져를 만든다는 것은 함수를 하나 만든다고 생각하면 된다.

 

 후킹 함수를 만들기 위해서는 지켜야 하는 규칙들이 있다.

1. Call Back 함수이여야 한다.

2. 함수의 마지막 부분에서는 CallNextHookEx() 함수를 호출한다.

3. 함수가 받는 인자는 정해져 있다.

4. 후킹 프로시져는 DLL 안에 있어야 한다.

 

Ex)

//--------------------------------------------------------------

// Hook Procedure - Keyboard

//--------------------------------------------------------------

LRESULT CALLBACK KeyboardProcedure(int nCode, WPARAM wParam, LPARAM lParam)

{

             if( nCode >= 0 )

             {

            

             }

             // We must pass the all messages on to CallNextHookEx.

           return ::CallNextHookEx( g_Hook , nCode , wParam , lParam );

}

 

 위의 규칙들을 지켜서 만든 후킹 프로시져 함수이다.

 

 4번째 규칙에 의하면 후킹 함수는 DLL 내부에 있어야 한다. Visual C++ 6.0 에서 DLL 프로젝트를 하나 만들어 보자.

 

Step 1. Win32 Dynamic-Link Library 프로젝트 생성

Step 2. Simple 프로젝트 선택 후 Finish

Step 3. cpp 파일에 위의 후킹 함수를 만들어 준다.

 

위의 프로젝트를 컴파일 하면 HookDll.dll 파일이 생성된다.

 

전체 프로젝트 파일 내용

// HookDll.cpp : Defines the entry point for the DLL application.

//

 

#include "stdafx.h"

 

BOOL APIENTRY DllMain( HANDLE hModule,

                       DWORD  ul_reason_for_call,

                       LPVOID lpReserved

                                                                   )

{

    return TRUE;

}

 

//--------------------------------------------------------------

// Hook Procedure - Keyboard

//--------------------------------------------------------------

LRESULT CALLBACK KeyboardProcedure(int nCode, WPARAM wParam, LPARAM lParam)

{

             if( nCode >= 0 )

             {

                          

             }

             // We must pass the all messages on to CallNextHookEx.

             return ::CallNextHookEx( g_Hook , nCode , wParam , lParam );

}

 

 

 


4. 후킹 프로시져를 시작, 종료하는 함수

 

 이번 단계에서는 앞서 만든 후킹 프로시져를 설치하고, 제거하는 함수를 만들어 보겠다. 후킹 프로시져는 특정 윈도우에 설치가 되어야 제 역할을 할 수 있게 된다. 이때 후킹 프로시져를 설치해주는 함수가 바로 SetWindowsHookEx() 이다. 그 다음에 설치된 후킹 프로시져를 제거하기 위해서는 UnhookWindowsHookEx() 가 쓰이게 된다. 각각의 사용법을 알아보고 앞에서 만든 프로젝트에 이어서 적용시켜 보자.

 

SetWindowsHookEx()의 사용법

HHOOK SetWindowsHookEx(

    int idHook,

    HOOKPROC lpfn,

    HINSTANCE hMod,

    DWORD dwThreadId

);

 

 첫번째 패러메터는 후킹 필터를 설정한다. 후킹 프로시져가 받은 메시지의 종류를 설정하는 항목이다. 예를 들어 WH_GETMESSAGE로 설정하면 모든 메시지를 받게 되고, WH_KEYBOARD로 설정하게 되면 키보드 관련 메시지만 전달 받게 된다. 더 자세한 내용은 MSDN 을 참고하기 바란다.

 

 두번재 패러메터는 후킹 프로시져의 포인터를 지정해야 한다. 간단하게 후킹 프로시져 함수 이름 써주면 된다.

 

 세번째 패러메터는 DLL 의 핸들을 넘겨줘야 된다. 이 값은 앞에서 만든 프로젝트에서 DLlMain() 함수를 보면 HANDLE hModule 값이 넘어오는데 이걸 저장 해놨다가 넘겨주면 된다.

 

 네번째 패러메터는 후킹 프로시져를 설치할 윈도우 값을 넘겨준다. 이번 예에서는 0 을 넘겨준다. 0 을 넘겨주면 후킹 프로시져가 모든 윈도우에 설치가 된다.

 

 이 함수가 리턴하는 값을 잘 저장 해 놓자. 나중에 후킹을 해제할 때 필요하게 된다.

 

Ex) g_HookKeyboard = SetWindowsHookEx( WH_KEYBOARD , KeyboardProcedure , (HINSTANCE)g_Module , 0 ) ;

 

UnhookWindowsHookEx() 의 사용법

 

BOOL UnhookWindowsHookEx(         

             HHOOK hhk

);

 

 이 함수는 후킹 핸들을 받아서 해당 후킹 프로시져를 해제한다. 이때 받는 핸들은 SetWindowsHookEx() 함수가 리턴한 값을 넣어주면 된다.

 

 

프로젝트를 계속 진행 해보자.

 

1. 필요한 전역 변수를 만들어 준다.

//---------------------------------------------------

// Global Variables

// 공용 메모리

//---------------------------------------------------

#pragma data_seg(".HKT")

HINSTANCE g_Module = NULL ;     // DLL Handle

HHOOK g_Hook = NULL ;  // Hook Handle

HWND g_HwndServer = NULL ;      // Hook Server Window Handle

#pragma data_seg()

 

 

2. SetHook, Remove 이라는 함수를 만든다.

//------------------------------------------------------------------// Set Hook

//------------------------------------------------------------------BOOL     SetHook( HWND hWnd )

{

             g_HwndServer = hWnd ;                // Set Hook Server

             g_Hook = SetWindowsHookEx( WH_KEYBOARD , KeyboardProcedure , (HINSTANCE)g_Module , 0 ) ;

             return false ;

}

 

//------------------------------------------------------------------// Remove Hook

//------------------------------------------------------------------BOOL     RemoveHook()

{

             UnhookWindowsHookEx( g_Hook ) ;

             return false;

}

 

 

// HookDll.def 파일 부분

LIBRARY   HookDll

 

SECTIONS

             .HKT   Read Write Shared

 

EXPORTS

             SetImeWindow                 @1

             SetHook                                        @2

             RemoveHook                                 @3

 

 

 

3.. 위의 함수와 전역 변수의 세팅을 위한 [프로젝트명].def 파일을 만들어 준다.

LIBRARY   [프로젝트명]

 

SECTIONS

             .HKT   Read Write Shared

 

EXPORTS

             SetHook                                        @2

             RemoveHook                                 @3

 

 

4. DllMail 함수에서 핸들을 저장한다.

//------------------------------------------------------------------// DllMain : Entry point

//------------------------------------------------------------------BOOL APIENTRY DllMain( HANDLE hModule,

                       DWORD  ul_reason_for_call,

                       LPVOID lpReserved

                                                                   )

{

             switch (ul_reason_for_call)

             {

             case DLL_PROCESS_ATTACH:

                           g_Module = (HINSTANCE)hModule; // Save Dll Handle

                           break;

 

             case DLL_PROCESS_DETACH:

                           RemoveHook();

                           break;

    }

 

    return TRUE;

}

 

 

전체 프로젝트 파일

 

1. HookDll.cpp

// HookDll.cpp : Defines the entry point for the DLL application.

//

 

#include "stdafx.h"

 

//---------------------------------------------------

// Global Variables

// 공용 메모리

//---------------------------------------------------

#pragma data_seg(".HKT")

HINSTANCE g_Module = NULL ;     // DLL Handle

HHOOK g_Hook = NULL ;  // Hook Handle

HWND g_HwndServer = NULL ;      // Hook Server Window Handle

#pragma data_seg()

 

BOOL    RemoveHook() ;

BOOL    SetHook( HWND hWnd ) ;

 

//------------------------------------------------------------------

// DllMain : Entry point

//------------------------------------------------------------------

BOOL APIENTRY DllMain(

                                                                                HANDLE hModule,

                                                                                DWORD  ul_reason_for_call,

                                                                                LPVOID lpReserved

                                                                  )

{

             switch (ul_reason_for_call)

             {

             case DLL_PROCESS_ATTACH:

                           g_Module = (HINSTANCE)hModule; // Save Dll Handle

                           break;

                          

             case DLL_PROCESS_DETACH:

                           RemoveHook();

                           break;

    }

            

    return TRUE;

}

 

//--------------------------------------------------------------

// Hook Procedure - Keyboard

//--------------------------------------------------------------

LRESULT CALLBACK KeyboardProcedure(int nCode, WPARAM wParam, LPARAM lParam)

{

             if( nCode >= 0 )

             {

                          

             }

             // We must pass the all messages on to CallNextHookEx.

             return ::CallNextHookEx( g_Hook , nCode , wParam , lParam );

}

 

//------------------------------------------------------------------

// Set Hook

//------------------------------------------------------------------

BOOL    SetHook( HWND hWnd )

{

             g_HwndServer = hWnd ;                // Set Hook Server

             g_Hook = SetWindowsHookEx( WH_KEYBOARD , KeyboardProcedure , (HINSTANCE)g_Module , 0 ) ;

            

             return false ;

}

 

//------------------------------------------------------------------

// Remove Hook

//------------------------------------------------------------------

BOOL    RemoveHook()

{

             UnhookWindowsHookEx( g_Hook ) ;

             return true ;

}

 

 

2. HookDll.def 파일

LIBRARY   HookDll

 

SECTIONS

.HKT   Read Write Shared

 

EXPORTS

SetHook                                        @2

RemoveHook                                 @3

 

 

프로젝트를 컴파일 하면 HookDll.lib 와 HookDll.dll 파일이 생성이 된다.


5. 프로시져 내에서 다른 윈도우로 데이터 전송하기

 

 이번에는 앞서 만든 후킹 프로시져를 좀더 강화해보기로 하자. 후킹 프로시져 내에서 메시지를 받고 받은 메시지를 복사하여 특정 윈도우에게 보낼 것이다.

 

 이때 WM_COPYDATA 메시지를 생성 할 것이다.

 

1. WM_COPYDATA 로 보낼 데이터의 구조를 정의한다.

// 메시지를 저장하는 구조체

typedef struct

{

             int                       Type ;

             WPARAM            Data ;

             LPARAM              lParam ;

} HEVENT;

 윈도우 메시지의 내용을 저장할 구조체

 

 

2. 현재의 메시지를 복사한다.

COPYDATASTRUCT  CDS;

HEVENT          Event;

 

// Set CDS

CDS.dwData = 0 ;

CDS.cbData = sizeof(Event);

CDS.lpData = &Event;

 

// 메시지의 내용을 저장한다.

Event.Type = 1 ;               // It's WM_KEY..

Event.Data = wParam ;     // Send CharCode

Event.lParam = lParam ;

 

 

3. g_HwndServer 에게로 메시지를 전달한다.

// g_HwndServer  에게로 메시지를 날린다.

// g_HwndServer 는 SetHook 함수 호출시 저장한 윈도우 핸들이다.

::SendMessage( g_HwndServer , WM_COPYDATA , 0 , (LPARAM)(VOID*)&CDS ) ;

 

 

 

프로젝트를 계속 진행 해보자.

 

1. 앞선 프로젝트의 내용 중 KeyboardProcedure() 함수의 내용을 수정한다.

 

//------------------------------------------------------------------

// Hook Procedure - Keyboard

//------------------------------------------------------------------

LRESULT CALLBACK KeyboardProcedure(int nCode, WPARAM wParam, LPARAM lParam)

{

             if( nCode >= 0 )

             {

                           // Send To HookServer

                           COPYDATASTRUCT  CDS;

                           HEVENT          Event;

                           // Set CDS

                           CDS.dwData = 0 ;

                           CDS.cbData = sizeof(Event);

                           CDS.lpData = &Event;

                           // Set Variables

                           Event.Type = 1 ;               // It's WM_KEY..

                           Event.Data = wParam ;     // Send CharCode

                           Event.lParam = lParam ;

                          

                            ::SendMessage( g_HwndServer , WM_COPYDATA , 0 , (LPARAM)(VOID*)&CDS ) ;    

             }

 

             // We must pass the all messages on to CallNextHookEx.

             return ::CallNextHookEx( g_Hook , nCode , wParam , lParam );

}

 

 

2. Event 구조체를 정의 해준다.

typedef struct

{

             int                       Type ;

             WPARAM            Data ;

             LPARAM              lParam ;

} HEVENT;


6. 간단한 샘플 프로그램

 

 지금까지 만들어 본 후킹 프로시져를 가지고 실제로 샘플 프로그램을 작성해보자.

 

 

1. 프로젝트를 생성한다.

             - MFC 다이얼로그

 

2. 위의 프로젝트를 컴파일 하면 HookDll.lib 와 HookDll.dll 파일이 생성이 된다. 이 파일을 새롭게 생성할 프로젝트 폴더에 복사한다.

 

3. 프로젝트를 세팅한다.

             - 메뉴에서 Project -> Setting -> Link 탭에서 Object/Modules Library 칸에 HookDll.lib 를 지정한다.

 

 

 

4 . 다이얼로그를 위의 모양같이 만들어 주고

에디트 컨트롤을 생성하고 다음과 같이 변수를 연결해준다..

 

ID : IDC_EDIT_CNT

Value : m_Cnt

Type : int


5. 클래스 위저드로 WM_COPYDATA 메시지 핸들러를 생성한다.

BOOL CHookTestDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)

{

             // TODO: Add your message handler code here and/or call default

            

             // WM_COPYDATA 메시지가 올때마다 카운트를 증가한다.

             m_Cnt++ ;

             UpdateData( false ) ;

 

             return CDialog::OnCopyData(pWnd, pCopyDataStruct);

}

 

위와 같이 수정해준다.

 

6. DLL 에 있는 함수를 사용하기 위해 헤더 파일에 다음을 추가한다.

BOOL    RemoveHook() ;

BOOL    SetHook( HWND hWnd ) ;

 

 

7. InitDialog() 함수에서 SetHook() 함수를 호출한다.

BOOL CHookTestDlg::OnInitDialog()

{

             CDialog::OnInitDialog();

 

             // Add "About..." menu item to system menu.

 

             // IDM_ABOUTBOX must be in the system command range.

             ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);

             ASSERT(IDM_ABOUTBOX < 0xF000);

 

             CMenu* pSysMenu = GetSystemMenu(FALSE);

             if (pSysMenu != NULL)

             {

                           CString strAboutMenu;

                           strAboutMenu.LoadString(IDS_ABOUTBOX);

                           if (!strAboutMenu.IsEmpty())

                           {

                                        pSysMenu->AppendMenu(MF_SEPARATOR);

                                        pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);

                           }

             }

 

             // Set the icon for this dialog.  The framework does this automatically

             //  when the application's main window is not a dialog

             SetIcon(m_hIcon, TRUE);                           // Set big icon

             SetIcon(m_hIcon, FALSE);                          // Set small icon

            

             // TODO: Add extra initialization here

             SetHook( this->GetSafeHwnd() ) ; // 후킹 프로시져 설치

            

             return TRUE;  // return TRUE  unless you set the focus to a control

}

 

자 이제 실행하면 키보드를 칠 때마다 카운트가 증가하는 프로그램이 완성이 되었다

'C/C++언어 > 후킹' 카테고리의 다른 글

Hooking 을 사용하는 프로그램 내의 구현  (0) 2007.11.11
Global Hooking in Win32  (0) 2007.11.11
[본문스크랩] 메세지 후킹  (0) 2007.09.06
[본문스크랩] Knowledge Base API  (0) 2007.09.06
API Hooking Revealed  (0) 2007.09.06
동적 API 후킹의 구조  (0) 2007.09.06
 

파일 입.출력


파일 입.출력은 앞으로도 매우 중요하게 쓰이는 부분이다.

어떤 파일로부터 데이터를 읽어들이고 또 데이터를 어떤 파일에 저장하는 것을 말한다.


데이터 저장과 불러오기 기능을 구현한것

읽기 / 쓰기 전용 , 읽기 / 쓰기 혼합 모드 기능

파일을 열고 닫는 작업이 쌍으로 존재한다.


[파일 오픈]


* FILE *fopen(const char *filename, const char *mode) ;    // 성공시 해당파일의 포인터. 실패시 NULL 포인터 리턴


- filename : 문자형 포인터로 사용할 파일 이름을 지정

- mode     : 파일에 대한 접근 방식

- 리턴값     : open 한 파일을 가리키는 파일 포인터


mode 에는 기본적으로 r, w, a 가 있고 세부적으로 바이너리 코드(이진모드)와 텍스트 모드로 분리



[파일 오픈 모드]


r   텍스트 모드이며 읽기 모드로 파일을 오픈

w  텍스트 모드이며 쓰기 모드로 파일을 오픈. 단 파일을 없으면 자동으로 생성. 있으면 내용을 전부 삭제하고 새로운 파일을 생성

a   텍스트 모드이며 쓰기 모드로 파일을 오픈. 단 파일이 없으면 자동으로 생성. 있으면 파일의 가장 끝부분에 이어 쓰기를 실행

b   바이너리 모드를 의미

+   읽기 / 쓰기의 혼합 모드가 가능함을 의미



[데이터 입.출력 모드]


t   텍스트 모드(text mode)

b   2진 모드(binary mode)


데이터의 읽기 / 쓰기를 텍스트 모드로 할건지 2진 모드로 할건지 정해주는 거이다.

문자열과 같은 텍스트 기반의 데이터는 텍스트 모드로 입. 출력 하는 것이 좋고 데이터 변환이 발생하면 안되는 경우 2진 모드로 데이터 입. 출력 하는 것이 좋다.


파일 접근 모드 + 데이터.입출력모드 = 파일 개방 모드     rt  ( r + t )  : 텍스트 모드의 읽기 전용



[일반적인 파일 열기 방법과 파일 오픈시 주의 사항]


FILE *fp ;                                                 // 파일을 오픈하기전에 반드시 파일포인터 선언

.......

fp = fopen( "test.txt" , "r" ) ;                        // 파일이름과 모드는 "와" 사이에 입력   test.txt 파일을 읽기 모드로 읽는 것이다.  

.......                                                        // 반드시 test.txt 파일이 폴더내에 있어야 한다.

if( fp == NULL )                                          // 파일이 제대로 열렸는지 반드시 체크

{

     ........

     return -1 ;

}



[파일 종결]


* int fclose(FILE *stream) ;


- stream : fopen() 함수를 통해 생성된 파일 포인터

- 현재 열린 파일을 닫을때 사용

- 출력 버퍼에 남아있는 데이터를 파일에 기록한 후 파일을 닫음


FILE *fp ;

.......

fp = fopen( "test.txt", "r" ) ;             // 파일 오픈

.......

fclose( fp ) ;                                  // 파일 닫음


동적할당에서 malloc 과 free 가 짝이 듯이 항상 파일을 오픈하면 종료를 해주어야 한다. fopen -> fclose



* 파일을 읽기 와 쓰기 에서 사용되는 함수들은 기존의 함수와 비슷하다. f 만 들어가면 된다.















<fputc() 함수>


하나의 문자를 파일에 저장

int fputc(int c, FILE *fp) ;

- c : 파일에 저장할 데이터

- fp : open 한 파일을 가리키는 포인터

- 리턴값 : fputc() 함수가 파일에 기록한 데이터


#include <stdio.h>

void main()

{

     FILE *fp ;

     fp = fopen( "text.txt", "w" ) ;                  // w 생성한다. test.txt   기존에 파일이 있으면 데이터 삭제 새로 사용.

     for( int i = 0 ; i < 128 ; i++ ){

          fputc( '\n', fp ) ;                           

          fputc( i, fp ) ;

     }

     fclose( fp ) ;

}


실행하면 아무것도 안나올 것이다.. 폴더에 가보면 test.txt 란 파일이 생기고  아스키 코드값 0번부터 128번의 문자들이 들어있다.


<fgetc() 함수>


* int fgetc( FILE *fp ) ;

- fp : fopen() 함수를 통해 생성된 파일 포인터

- 리턴값 : 문자

- fp 는 항상 NULL 이 될수 없음


폴더에 text.txt 안에 a b c 를 작성하고 종료.(저장. 공백 주의)


#include <stdio.h>

#include <stdlib.h>


void main()

{

     FILE* fp ;

     fp = fopen( "test.txt" , "r" ) ;

     if( fp == NULL){

          printf("Error\n") ;

          exit( 1 ) ;

     }

    

     while( !feof(fp) )                                  // 끝이 아니라면 실행

          printf( "%c", fgetc(fp) ) ;                   // 문자를 읽어들여 출력  a b c 출력

     

     fclose( fp ) ;

}


<feof() 함수>


* int feof( FILE *filepointer )

- fileopinter : fopen() 함수를 통해 생성된 파일 포인터

- 현재 가리키는 위치가 파일의 끝인가를 검사한다.

- 리턴값 : 현재 가리키는 위치가 파일의 끝인 경우 0 을. 아닌 경우에는 0 이 아닌 값을 리턴


<fputs() 함수>


문자열을 대상파일( 지정한 파일 포인터의 파일) 에 기록


* int *fputs( const char *buffer, FILE *fp ) ;

- buffer : 출력할 문자열의 포인터

- fp : 출력할 파일을 가리키는 포인터


#include <stdio.h>

#include <stdlib.h>


void main()

{

     FILE *fp ;

     fp = fopen( "test.txt", "w" ) ;


     fputs( "Hello" , fp ) ;                              // test.txt 에 Hello 가 저장된다.

     fclose( fp ) ;

}


<fgets() 함수>


파일 포인터로부터 원하는 양 만큼의 문자열 데이터를 읽어옴


* char *fgets( char *buffer, int n, FILE *fp ) ;

- buffer : 문자열을 저장하게 되는 영역

- n : 읽어드릴 양

- fp : open 한 파일을 가리키는 포인터


현재 test.txt 파일에는 Hello 가 저장되어 있다.


#include <stdio.h>

#include <stdlib.h>


void main()

{

     FILE *fp ;

     char str[20] ;

     fp = fopen( "test.txt", "r" ) ;

   

     fgets( str, sizeof(str), fp ) ;

     printf( "str : %s\n", str ) ;                     // Hello 출력

     fclose( fp ) ;

}


<fread() 함수>


파일로 부터 바이트 단위로 데이터를 읽어들인다.


* size_t fread( void *buffer, size_t size, FILE *fp ) ;

- buffer : 읽어올 데이터를 저장할 메몰리 영역의 포인터

- size : 읽어올 사이즈

- fp : 파일 포인터

- 파일 포인터 fp 에서 size 만큼의 데이터 n 개를 buffer 에 저장


<fwrite() 함수>


파일에 바이트 단위로 데이터 기록


* size_t fwrite( void *buffer, size_t size, size_t n, FILE *fp ) ;

- buffer : 파일에 기록할 데이터가 저장되어 있는 메모리 영역의 포인터

- size : 개별적인 데이터 항목의 크기

- n : 기록할 수

- fp : 파일 포인터

- buffer 에 있는 size 만큼의 데이터 n 개를 파일 포인터 fp 에 기록


#include <stdio.h>

#include <stdlib.h>


struct ADDS{

     char name[30] ;

     char number[30] ;

} ;


void main()

{

     FILE *fp ;

     int input, cnt ;

     ADDS *Juso ;


     while(1)

     {

          printf( "* [1] 입력  [2] 출력  [3] 종료 *\n" ) ;

          printf( "입력  : " ) ;

          scanf( "%d", &input ) ;


          if( input == 3 ){

               printf( "-Good Bye-\n" ) ;

               exit( 1 ) ;

          }

          if( input == 1 ){

               printf( "총 몇명 의 주소록을 입력할까요 ?" ) ;

               scanf( "%d", &cnt ) ;


               Juso = (ADDS*)malloc(sizeof(ADDS)*cnt) ;         

               fp = fopen( "test.txt", "w" ) ;


               for( int i = 0 ; i < cnt ; i++ ){

                    printf( "이름 : " ) ;

                    scanf( "%s", Juso[i].name ) ;

                    printf( "전화번호 : " ) ;

                    scanf( "%s", Juso[i].number ) ;

               }

               fwrite( &cnt, sizeof(int), 1, fp ) ;                       // fwrite cnt 변수값

               fwrite( Juso, sizeof(ADDS), cnt, fp ) ;                // fwrite Juso 구조체

               printf( "저장 완료\n" ) ;

               fclose( fp ) ;

               free( Juso ) ;

          }

          if( input == 2 ){

               fp = fopen( "test.txt", "r" ) ;            

               fread( &cnt, sizeof(int), 1, fp ) ;

          

               Juso = (ADDS*)malloc(sizeof(ADDS)*cnt)  ;          

               fread( Juso, sizeof(ADDS), cnt, fp ) ;

               printf( "\n" ) ;

     

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

                    printf( "이름 : %s  전화 : %s\n", Juso[i].name, Juso[i].number ) ;


               printf( "\n" ) ;

               free( Juso ) ;

               fclose( fp ) ;

          }

     }

}


간단한 주소록 프로그램이다.  소스가 그다지 어렵지 않기 때문에 쉽게 이해 할수 있을 것이다.


<fprintf 와 fscanf>


fprintf 와 fscanf 함수는 printf 와 scanf 함수와 똑같다. 단지 파일이냐 모니터냐의 차이이다.  그리고 앞에 FILE 포인터 변수가 들어간다.


#include <stdio.h>

#include <stdlib.h>


void main()

{

     FILE *fp ;

     int Index ;    

     int Data ;


     fp = fopen( "test.txt", "w" ) ;

     for( Index = 0 ; Index < 9 ; Index++ )                            // 0 부터 9 까지 test.txt 에 저장

          fprintf( fp, "%d\n", Index ) ;


     fclose( fp ) ;


     fp = fopen( "test.txt", "r" ) ;

     for( Index = 0 ; Index < 9 ; Index++ ){                           // test.txt 에 있는 값을 9개 불러옴.. 0 부터 9 까지 출력

          fscanf( fp, "%d", &Data ) ;                            

          printf( "%d\n", Data ) ;

     }


     fclose( fp ) ;

}

'C/C++언어' 카테고리의 다른 글

여러 C++ 컴파일러  (0) 2007.09.06
함수포인터란 ?  (0) 2007.09.06
[본문스크랩] 파일 입.출력  (0) 2007.09.06
[본문스크랩] VC++ Article  (0) 2007.09.06
[강좌] MASM 6.0 사용법  (0) 2007.09.06
어셈블리 초급 기초 #1(정태식님)  (0) 2007.09.06

출처 : http://www.gosu.net/GosuWeb/ArticleBList.aspx?CateCode=0502000

 
• General (52) • Database (0)
• Command and Function (0) • Internet & Network (8)
• API/DLLs (1) • COM/DCOM/COM+ (5)
• Threads, Processes & IPC (2) • Shell Programming (1)
• Windows forms (0) • Doc/View/Printing (1)
• Files and Folders (2) • Dialog and Windows (6)
• TextBoxs/String (0) • Button Controls (0)
• Menus (0) • Tab/Toolbars/Status Bar (0)
• Edit Controls (0) • List/Combo Controls (1)
• ListView/TreeView (1) • Static Controls (0)
• Samples (0)
 
General (52)
 
 
How to i386 32bit OS Kernel Compile in VC6 (0) / 작성자: bro / 작성일: 2004-10-14 / 평점: 4.56
본 문서는 VC6에서 어떻게 커널을 컴파일 할 수 있는가에 대한 간단한 소개를 하는 문서입니다. VC에서 OS를 만들기 위해서 생기는 특이한 사항과 간단한 컴파일 후 콘솔 커널을 띄우는 것의 데모까지 해보도록 합니다.
MFC DLL 간단 설명 (0) / 작성자: bro / 작성일: 2004-11-28 / 평점: 4.75
MFC DLL 과 관련된 여러 재미있는 내용들을 알아보았습니다. MSDN에서 본 영문 자료를 기반으로 이해를 위해 추가를 하거나 한 설명입니다.
프로그램내에서 한/영 전환하기 (0) / 작성자: 디버깅전문가 / 작성일: 2004-12-25 / 평점: 4.75
프로그램적으로 한영키를 제어 하는 방법으로 Imm*() 함수를 사용하시면 됩니다. 아래의 예제 코드는 한글키와 영문키로 바꾸는 두가지 함수를 설명하고 있습니다
프로그램 한번만 실행하기 (0) / 작성자: 디버깅전문가 / 작성일: 2004-11-28 / 평점: 4.75
프로그램의 중복 실행을 막는 방법에는 여러가지가 있겠지만, 공유 Data segment 를 사용하는 방법을 살펴보겠습니다.
MetaFile 사용 및 클립보드에 복사하기 (1) / 작성자: 하얀그림자 / 작성일: 2004-12-02 / 평점: 4.75
메타파일을 클립보드를 이용하여 다른 프로그램에 붙여넣을 수 있는 기능을 구현하자. 여기서는 윈도우메타파일이 아닌 확장 메타파일을 다루고 있다. 뭐, 그게 그것이지만,,,
트레이 아이콘(TrayIcon) 사라지는 버그 막기 (0) / 작성자: 디버깅전문가 / 작성일: 2004-11-09 / 평점: 4.00
요즘 나오는 프로그램에서는 대부분 TrayIcon을 제공합니다. 단순히 프로그램 리스트(태스크 바)에 나오는 것보다는, TrayIcon이 사용자에게 보다 더 편리한 UI를 제공하기 때문입니다. 그런데, 익스플로어(인터넷 익스플로어가 아닙니다.)의 버그 때문에 <그림 1>과 같이 종종 TrayIcon이 Tray에서 사라지는 경우가 있습니다. 하지만, 몇몇의 프로그램은 사라지지 않고 계속 남아있는 경우도 볼 수 있습니다.
DLL, LIB 인텔리센스, Debug Step Trace되게 하기 (0) / 작성자: bro / 작성일: 2004-10-20 / 평점: 4.25
Static Lib나 DLL을 배포할때 DLL, LIB만 배포하면 쓰는 사람쪽(클라이언트)에서 인텔리센스와 스텝트레이스 디버깅을 제대로 할 수 없는 문제가 있습니다. 이 문서는 이를 위한 경험에 따른 팁입니다.
소스 세이프 ( Source Safe )의 간략한 소개와 설명 (1) / 작성자: 규서스 / 작성일: 2004-11-09 / 평점: 4.25
Visual Studio 에서 제공하는 공동 프로젝트 소스관리 툴인 소스세이프 (Source Safe)에 관하여 간략하게 설명합니다. 보다 세밀하고 어려운 기능은 많은 방법으로 테스트를 한 이후에 실제 프로젝트에 적용을 하면 보다 안전(Safe)한 프로젝트 소스와 리소스 관리가 되지 않을까 생각됩니다.
MFC DLL Debug/Release 구분해서 하기 (0) / 작성자: bro / 작성일: 2004-11-18 / 평점: 3.80
Release용 MFC42.dll 디버그용 MFC42d.dll 처럼 dll 만들때 디버그용 릴리즈용으로 세팅하는 방법에 대해서 알아봅니다.
CStringArray 정렬하기 (0) / 작성자: 디버깅전문가 / 작성일: 2004-11-28 / 평점: 4.67
CStringArray 객체를 정렬하기 위해서 아래에서 보여주는 소스코드를 사용하실 수 있습니다. main() 함수에서는 CStringArray 객체를 만들고, 내용들을 추가시킵니다. 그리고 나서 화면에 출력하고 sort() 함수를 호출하죠. 이제 sort()함수가 끝나고 난후 다시 화면에 출력해서 sort() 함수가 제대로 역할을 수행했는지 결과를 보여줍니다. sort() 함수는 Bubble Sort 알고리즘을 사용했으면 CompareAndSwap()라는 함수를 구현하여 CString 객체끼리 서로 위치를 바꿀 수 있도록 하고 있습니다.
일반적인 윈도우 소멸 순서 (0) / 작성자: 디버깅전문가 / 작성일: 2004-11-28 / 평점: 4.00
MFC framework에서, 사용자가 frame 윈도를 닫게되면, 윈도는 기본적으로 OnClose 핸들을 call 합니다. 그리고 OnClose 내부에서는 DestroyWindow를 호출하죠. 가장 마지막으로 호출되는 함수는 OnNcDestroy이다.
_ASSERTE 가 GetLastError()를 망친다 (0) / 작성자: 디버깅전문가 / 작성일: 2004-11-15 / 평점: 4.00
MFC 에서 제공하는 에러 방지용 매크로인 _ASSERTE 가 호출되면 MFC 는 Last Error 를 0 을 셋팅하게 되어 GetLastError() 가 무용지물이 되어 버립니다.
윈도우용 CVS 의 활용-클라이언트_WinCVS (1) / 작성자: nak / 작성일: 2004-11-12 / 평점: 4.00
WinCVS는 CVS명령을 쉽게 사용하게 하는 클라이언트 프로그램이다. 비슷한 프로그램으로 여러가지가 나와 있지만 Tortoise CVS 프로그램과 가장 많이 사용하는 CVS 클라이언트 이다. 역시 군더더기는 빼고 사용법만 설명하도록 하겠다.
tstring: string for TCHAR (0) / 작성자: bro / 작성일: 2004-10-20 / 평점: 3.75
MBCS 환경이나 UNICODE 환경에서도 stl::string과 stl::wstring을 자동으로 선택해서 사용할 수 있는 tstring에 대해서 알아보도록합니다.
파일 버전 구해서 비교하기... (1) / 작성자: 데미소다오렌지 / 작성일: 2004-11-16 / 평점: 4.33
요즘은 대부분의 파일을 인터넷을 통해서 배포하는 것이 일반적입니다. 이럴 경우 파일이 업데이트 되었는지 검사하기 위해서 버전 정보를 구하는 함수가 필요합니다. 이 문서에서는 Win32 PE 파일에 포함된 버전 정보를 구하는 함수와 함께 구해진 버전을 비교하는 함수의 구현 과정을 포함하고 있습니다.
자동 버전 증가 매크로 (0) / 작성자: 데미소다오렌지 / 작성일: 2004-11-28 / 평점: 4.33
이 문서는 VC++의 자동 버전 증가 매크로에 대한 설명과 좀 더 개선된 매크로의 소스를 포함하고 있습니다.
HBITMAP을 BMP 파일로 만들어 주는 함수 (0) / 작성자: 디버깅전문가 / 작성일: 2004-12-07 / 평점: 4.33
어떤 내용이 들어있는 HBITMAP 값과 파일이름을 넘겨주면 주어진 파일 이름으로 Bitmap 이미지 파일을 만드는 함수입니다.
디스크 복사 및 포맷 (0) / 작성자: 디버깅전문가 / 작성일: 2004-11-28 / 평점: 4.33
디스크 포맷 기능을 하는 API함수가 존재하는데 이건 Undocument된 내용으로 MSDN에 나오지않고 헤더에도 선언되어있지 않습니다. 함수 Prototype을 선언하면 사용할 수 있습니다.
친절한 메세지 ( benign message ) (0) / 작성자: 디버깅전문가 / 작성일: 2004-12-23 / 평점: 3.25
특정 Thread 나 Window 에 아무런 영향을 끼치지 않으면서 단순히 그 Thread 나 Window 가 살아있는지를 확인하고 싶을때 '친절한 메세지' 를 사용하시면 됩니다.
Source Safe과 Project를 분리시키기 (0) / 작성자: 디버깅전문가 / 작성일: 2004-11-28 / 평점: 3.67
Source Safe와 연결되어있는 Project는 자체적으로 이와 관련된 정보를 가지고 있습니다. 이 정보를 제거하는 방법을 알아보겠습니다.
재밌는(?) 시스템 강제로 다운시키기 (0) / 작성자: 디버깅전문가 / 작성일: 2004-11-28 / 평점: 3.67
필요한 경우가 거의 없겠지만(바이러스가 아니고서야. ^^;;), 시스템을 강제로 다운시키고자 하는 경우가 있을 수 있습니다. 이런 경우 아래의 예제에서 처럼 어셈블리 코드를 사용하는 방법과 Thread 를 와장창 만들어서 thread 러쉬(?)를 통해서 다운시키는 방법이 있습니다. 아래의 예제를 참고 하세요.
SearchPath()의 리턴값 알아보기 (0) / 작성자: 디버깅전문가 / 작성일: 2004-11-28 / 평점: 4.50
"Win32 Programmer's Reference"에서 "SearchPath()"는 다음과 같은 reture value를 갖고 있습니다. The length (in characters) of the string copied to the buffer. -or- 0 if the function fails [see "GetLastError()" in the "Win32 Programmer's Reference" for more information]. 하지만, 만약 찾고자 하는 파일을 찾을 수 없을때에도 0을 return 해주는데, 이때 GetLastError()로 error값을 살펴보아도 error값은 변경되어 있지 않다는 것을 알수 있습니다.
MFC UNICODE 컴파일 하기 (0) / 작성자: bro / 작성일: 2004-11-10 / 평점: 4.50
MFC에서 다국어 버전( 한프로그램에서 여러 국가의 문자를 표현하는 )을 만들때 유니코드를 사용하므로 유니코드 컴파일을 해야 합니다.
윈도우용 CVS 의 활용-서버편 (0) / 작성자: nak / 작성일: 2004-11-11 / 평점: 4.50
많은 사람들이 알지만 귀차니즘 혹은 정보의 부족으로 인해 하지 않았던 CVS를 아주 쉽게 따라하며 직접 설치하고 사용 할 수 있도록하는데 이 문서의 목적이 있다.
Hatch 가 밀려나오는 브러시 수정하기 (0) / 작성자: 디버깅전문가 / 작성일: 2004-11-15 / 평점: 4.50
Hatch 스타일이 적용된 브러시가 정상적으로 표시되지 않는 이유는 브러시 원점과 관련되어 있습니다.
IPicture를 이용한 JPG, GIF, BMP, WMF, EMF, ICO 보기 (0) / 작성자: 디버깅전문가 / 작성일: 2004-11-15 / 평점: 4.50
JPG나 GIF 등의 이미지 파일포멧을 읽어올려면 직접구현하던가 아니면 해당 라이브러리(예, LeadTool,...)을 이용해야 됩니다. 그러나 윈도즈에서 제공하는 IPicture인터페이스로 간단하게 그림파일(JPG, GIF, BMP, WMF, EMF, ICO)을 불러오는 방법을 알아보겠습니다.
web session : MD5, RC4, base64 (0) / 작성자: bro / 작성일: 2004-12-24 / 평점: 4.50
웹 세션에 대해서알아본 후 md5, rc4, base64등을 사용하는 방법과 쉽게 사용 할 수 있는 md5, rc4, base64 소스를 얻어봅니당.
First-chance exception 에서 Stop 하도록 만들기 (0) / 작성자: 디버깅전문가 / 작성일: 2004-12-19 / 평점: 4.50
가끔씩 Visaul C++의 Debug 창에 위의 문구가 출력되는 걸 볼 수 있습니다. 이 문구의 의미는 무엇이며, 어떻게 디버깅할 수 있는지 알아보겠습니다.
ISAPI필터dll Attach to Process로 디버깅하기 (0) / 작성자: bro / 작성일: 2004-11-17 / 평점: 3.00
VC의 Attach to Process를 하는 방법에 대해서 알아보고 예로 ISAPI 필터 dll을 디버깅하는 방법을 알아보았습니다.
스플리터 윈도우 위치 고정하기 (0) / 작성자: 디버깅전문가 / 작성일: 2004-11-28 / 평점: 4.00
스플리터 윈도우의 크기를 위치를 공정하는 방법을 설명한다. 스플릿바의 행동양식을 살펴보면 스플리터 윈도우의 크기를 고정하는 방법을 찾을 수 있다.
CDROM Insertion / Removal 감지하기 (0) / 작성자: 디버깅전문가 / 작성일: 2004-11-15 / 평점: 4.00
CDROM (or DVD) Insertion / Removal 감지하는 방법을 알아보겠습니다.
할당된 블록의 크기 구하기 (0) / 작성자: 디버깅전문가 / 작성일: 2004-11-28 / 평점: 4.00
new, malloc을 사용해서 메모리 블럭을 할당한 경우에, 포인터를 통해 메모리 블럭의 크기를 구하는 함수입니다. 물론 디버그 버전에서만 사용할 수 있습니다.
base pointer를 지정하자. (0) / 작성자: 디버깅전문가 / 작성일: 2004-12-16 / 평점: 4.00
microsoft c++에서는 __base 키워드를 사용해서 base pointer를 지정할 수 있습니다.
CPList - CPtrList for non-MFC (0) / 작성자: bro / 작성일: 2005-01-02 / 평점: 4.00
MFC의 CPtrList를 대치할 수 있는 non-MFC 환경하의 PList 클래스를 소개합니다
Top 윈도우들의 핸들을 알수 없을까? (0) / 작성자: 디버깅전문가 / 작성일: 2004-12-25 / 평점: 3.50
프로그램을 하다 보면, 현재 Windows System 에서 돌아가는 상위 윈도우들을 알아야 되는 경우가 있습니다. 어떻게 하면 쉬울까요?
소스로 바로가는 TRACE (0) / 작성자: 디버깅전문가 / 작성일: 2004-12-19 / 평점: 3.50
ANSI CRT에는 TRACE와 같은 기능이 없지만 Visual C++에는 _RPTn 들과 _RPTFn 들이 있습니다. 여기서 _RPTFn 을 주목할 필요가 있는데 _RPTFn 은 다음과 같은 형태의 매크로들을 말합니다.
파일로 트레이스 하도록 바꾸기 (0) / 작성자: 디버깅전문가 / 작성일: 2004-12-19 / 평점: 3.50
MFC에서 말입니다. 모든 트레이스를 파일로 하도록 바꿔봅시다. 예전에 어떻게 좀 해볼라고 하다가 실패했는데, 간단하고도 효과적인 방법이 무수히 많이 있습니다. 그중에 하나!
폴더내의 dll 한 번에 등록하기 (0) / 작성자: 디버깅전문가 / 작성일: 2004-12-19 / 평점: 3.50
쉘에서 for 명령을 지원하네요.
포인터 변수를 검증하기위한 매크로 (0) / 작성자: 디버깅전문가 / 작성일: 2004-12-16 / 평점: 3.50
포인터가 올바른 메모리 블럭을 가리키고 있는지 조사할 수 있는 API 들이 몇 가지 있습니다. ( IsBadWritePtr() 을 MSDN 에서 찾으시면 비슷한 친구들까지 모두 찾을실 수 있을겁니다 ) MFC 에는 이 API를 사용해서 간단한 매크로를 만들어 두었습니다.
COM 디버그 설정 (0) / 작성자: bro / 작성일: 2004-11-29 / 평점: 3.50
웹페이지에 붙은 COM 디버깅 VB 프로그램에 붙은 COM 디버깅 MTS COM+ 디버깅 참고 ISAPI DLL 디버깅
특정 파일의 Property 창 띄우기 (0) / 작성자: 디버깅전문가 / 작성일: 2004-11-28 / 평점: 3.50
프로그래머가 직접 정보를 수정하지 않고 사용자가 정보를 수정하게 하고 싶은 경우에 파일의 Property 창을 띄울 수 있습니다. 그럴때 간단히 ShellExcute() 를 사용해 보시면 됩니다.
CTString - CString on non-MFC (0) / 작성자: bro / 작성일: 2005-01-02 / 평점: 5.00
CString만 사용하는 경우 MFC 라이브러리를 포함하기에는 무겁습니다. 이럴때 간단히 대치할 수 있는 클래스로 CTString을 소개합니다.
Watch 창에서 함수 실행하기 (0) / 작성자: 디버깅전문가 / 작성일: 2004-12-19 / 평점: 3.00
아시는 분은 다 아시겠지만, watch 창에서는 함수를 실행시킬 수 있습니다.
Floating-Point Error가 Exception을 발생하도록 만들기 (0) / 작성자: 디버깅전문가 / 작성일: 2004-12-19 / 평점: 4.00
int대신 float를 사용했다면 Exception은 발생하지 않습니다. 어떻게하면 Exception이 발생하도록 만들 수 있을까요?
특정 컨트롤에서 한글을 입력받고 싶지 않을때 (0) / 작성자: 디버깅전문가 / 작성일: 2004-12-21 / 평점: 4.00
특정 컨트롤에서 영문만 입력 받고자 할때에는 IME의 사용을 중지하면 됩니다.
WaitCursor가 만들어지지 않는 경우 (0) / 작성자: 디버깅전문가 / 작성일: 2004-12-23 / 평점: 4.00
모래시계 커서를 만드는데 실패하셨던( 저처럼) 분들은 부디 유용하게 사용하시기 바랍니다.
트레이 메뉴가 사라지지 않을때 (0) / 작성자: 디버깅전문가 / 작성일: 2004-12-19 / 평점: 4.00
트레이 아이콘에서 메뉴를 띄울 때 메뉴의 특정 항목을 선택하지 않고 다른 윈도우를 선택하게 되면 메뉴가 사라지지 않습니다. 이 문제는 임의의 윈도우를 생성하여 메세지가 사라지도록 하는 것입니다.
MFC 라이브러리에 동적으로 링크된 정규 DLL (0) / 작성자: 디버깅전문가 / 작성일: 2004-12-19 / 평점: 4.00
MFC 라이브러리에 DLL을 동적으로 링크하는 방법을 알아보도록 합니다.
연결 프로그램 찾기 다이얼로그 띄우기 (0) / 작성자: 디버깅전문가 / 작성일: 2004-11-28 / 평점: 4.00
Explorer 에서 파일 아이콘을 더블클릭할 경우 파일의 확장명에 따라 연결되어 있는 프로그램이 동작하게 되어 있다. 하지만 연결되어 있는 프로그램이 없을 경우 "연결 프로그램 찾기" 다이얼로그가 화면에 나타나게 할 수 있습니다.
xmlite : simple xml parser (0) / 작성자: bro / 작성일: 2004-12-17 / 평점: 4.00
XMLite 는 DOM 기반의 사용하기 쉬운 c++ XML 파서입니다. 처음에는 간단히 엘리먼트만 파싱하도록 하였다가, 필요에 의해서 여러가지 기능이 추가되었습니다.
Capture가 되지 않는 경우 (0) / 작성자: 디버깅전문가 / 작성일: 2004-12-23 / 평점: 3.00
Capture가 되기 위해서는 마우스 버튼이 눌려져 있어야 한다는 사실을 아십니까?
간단한 LoadString (0) / 작성자: bro / 작성일: 2004-11-26 / 평점: 2.00
애플리케이션의 문자열 리소스를 가져다 쓰려면 LoadString을 호출해야 합니다. MFC에서는 그나마 편리하게 사용하라고 CString의 맴버 함수로 LoadString 맴버 함수를 제공 하고 있지만, 매번 CString 객체를 생성해서 사용해야 하므로 불편하기도 합니다. 게다가, 문자열 리소스에서 인자를 받게 하고 싶으면 더욱 불편합니다. 그래서 아래와 같은 방식으로 저는 간단한 LoadString 매크로를 만들어 사용하고 있습니다.
 

 
Internet & Network (8)
 
 
PHP나 ASP 코드 직접 호출하기 (2) / 작성자: 디버깅전문가 / 작성일: 2004-11-09 / 평점: 4.00
IE(Internet Explorer)같은 웹 브라우저를 이용하지 않고, 서버측에 있는 코드를 직접호출하는 방법에 대해서 알아보도록 합니다.
네트워크 정보 얻어오는 방법 (3) / 작성자: bro / 작성일: 2004-11-10 / 평점: 4.00
1. MAC Address 그냥 보는 방법 2. GetNetworkParams / GetAdaptersInfo 3. NIC 카드 랜카드 이름 얻기
HTML코드를 임시파일로 저장한 파일 URL얻기 (0) / 작성자: bro / 작성일: 2004-11-29 / 평점: 4.00
가끔가다보면 동적으로 HTML코드를 만들어서 이를 네비게이트해야하는 경우가 있습니다. about 을 사용하면 간단한 경우 해결되지만, 제약으로 인해 몇 K 이상되는 코드는 넣을수 없습니다.
인터넷에 연결되어 있는지 알아보기 (0) / 작성자: 디버깅전문가 / 작성일: 2004-12-21 / 평점: 4.33
현재 컴퓨터가 인터넷에 연결되어 있는지를 확인하는 함수를 알아보도록 합니다.
mshtml 메모리 릭 최소화하기 (0) / 작성자: bro / 작성일: 2004-11-29 / 평점: 4.50
mshtml은 웹브라우저 컨트롤이나 CHtmlView를 사용할때 내부 HTML 다큐먼트 안의 엘리먼트 값을 보거나 수정하기 위해서 쓰는 HTML DOM Parser COM 라이브러리이다. 문제는 잘못사용하면 메모리릭이 많이 생긴다는 것이다.
HTML 스크립트 함수 ActiveX에서 호출하기 (0) / 작성자: bro / 작성일: 2004-11-30 / 평점: 4.50
IDocument 를 얻은 후 get_script로 스크립트 객체를 얻은 후 GetIDsOfNames( 함수명 ) 으로 해당 함수를 얻은 후 Invoke 할 수 있습니다.
HTML 리소스에 넣어 Navigate 하기 (0) / 작성자: bro / 작성일: 2004-11-29 / 평점: 4.00
HTML 페이지를 리소스로 EXE에 포함하여 이를 Navigate 하는 방법에 대해서 알아봅니다.
웹페이지가 이동될때 진입하는 함수 (0) / 작성자: 디버깅전문가 / 작성일: 2004-12-07 / 평점: 4.00
웹상에서 구동되는 ActiveX 컨트롤의 경우 웹페이지가 이동될때 진입하는 함수를 알아본다.
 

 
API/DLLs (1)
 
 
local folder에 있는 dll 사용하게 만들기 (2) / 작성자: 디버깅전문가 / 작성일: 2004-12-21 / 평점: 3.00
dll hell 을 방지하기 위한 방법 중 한가지로, local 폴더에 dll을 두고 혼자만 쓰는 방법을 들 수 있습니다. 그와 관련하여 재밌는 기능이 한 가지 있네요..
 

 
COM/DCOM/COM+ (5)
 
 
MS Script Control in MFC (0) / 작성자: bro / 작성일: 2004-11-20 / 평점: 5.00
MS VB Script Control을 MFC 에서 사용하는 방법에 대해서 간략하게 알아보았습니다.
Lite control에서 이벤트가 가능하게 하기 (0) / 작성자: 디버깅전문가 / 작성일: 2004-12-19 / 평점: 4.00
Lite control에서 이벤트가 가능하게 하기위해서는 IProvideClassInfo2Impl를 상속받게 하면 된다.
ATL Object가 한글 폴더에 있으면 등록이 안되는 버그 (0) / 작성자: 디버깅전문가 / 작성일: 2004-12-19 / 평점: 4.00
이 버그는 MS에서 인정하는 버그이고 해결책까지 나와있습니다. 아래 참조에서 MSDN 항목을 확인하실 수 있습니다. 시키는대로 했는데 잘 안되서, 독자적인 해결책을 제시합니다.
OLE를 이용한 Drag and Drop (0) / 작성자: 디버깅전문가 / 작성일: 2004-12-25 / 평점: 4.00
Ole를 이용하여 간단하게 Window 사이에서 Drag and Drop하여 데이터를 교환하는 방법을 설명합니다.
다른 스레드에서 인터페이스 받아다 쓰기 마샬링하기 (0) / 작성자: bro / 작성일: 2004-11-30 / 평점: 2.00
같은 에러는 다른 스레드에서 인터페이스 포인터 받아와서 직접 메소드를 호출하려고 할때 나는 에러다. 이런 경우 해당 인터페이스를 스레드로 넘겨줄때는 마샬링을 해야 한다.
 

 
Threads, Processes & IPC (2)
 
 
멀티 프로세서 시스템에서 한개의 CPU만 사용하도록 하기. (3) / 작성자: nak / 작성일: 2004-11-10 / 평점: 4.80
멀티 프로세서 시스템에서 프로그램을 개발시 가장 좋은 방법은 생성한 스레드가 잘 분산되어 처리 되도록 하는것이다. 그러나 멀티 프로세서 시스템을 염두하지 않고 만들어진 프로그램에서 비정상적인 종료, dead lock 등으로 인한 pendig 현상등의 문제가 발생하면 당혹스러울 수 밖에 없다. 아주 간단한 팁이지만 실무에서 유용하게 사용할 수있는 팁을 소개한다.
Safe TerminateProcess() (0) / 작성자: snaiper / 작성일: 2004-10-20 / 평점: 4.50
Win32 API 에 보면 TerminateProcess 라는 함수가 있습니다. 함수명 그대로 Process 를 강제로 Kill 시키는 함수입니다. 하지만 권고하지 않는 함수이고, 여러가지 Side Effect 들이 존재합니다. 이를 피하고 안전하게 처리할 수 있는 방법을 소개합니다.
 

 
Shell Programming (1)
 
 
바탕화면, 즐겨찾기, 내 문서 등의 패스얻기 (0) / 작성자: 디버깅전문가 / 작성일: 2004-11-09 / 평점: 4.67
Windows에서는 여러가지 특별한 폴더들이 있습니다. 내 문서도 그렇고 휴지통 등이 이에 속합니다. 이들 경로는 절대적인 경로가 아니기 때문에(대표적인 예가 Windows root 경로나 System 경로등이죠) 절대적인 경로를 사용하는 경우에는 낭패를 보기 쉽상입니다. 이 글에서는 SHGetSpecialFolderPath()를 이용하여 윈도우에서 사용하는 특별한 폴더들의 패스를 얻어오는 방법을 설명합니다.
 

 
Doc/View/Printing (1)
 
 
Doc/View 구조 없는 SDI에서 스플릿 윈도우 만들기 (0) / 작성자: bro / 작성일: 2004-11-28 / 평점: 4.00
Visual C++ 6 에서 새롭게 지원된 MFC App Wizard 옵션은 바로 다큐먼트 뷰 구조를 사용하지 않고 SDI나 MDI를 할 수 있다는 것입니다. 다큐먼트 뷰 구조가 아닐때 스플릿 윈도우를 만드는 방법을 간단히 알아보도록 합니다.
 

 
Files and Folders (2)
 
 
실행 파일(바이너리)에서 파일 이름 가져오기 (0) / 작성자: 디버깅전문가 / 작성일: 2004-12-21 / 평점: 4.50
실행 파일의 헤더안에 저장되어 있는 정보를 읽는 것은 심볼릭 정보나 실행 파일에 대한 더 자세한 것을 얻을 수 있는 방법입니다.
파일 사이즈 별로 단위를 나누어서 출력하기 (0) / 작성자: 디버깅전문가 / 작성일: 2004-12-21 / 평점: 4.00
파일의 사이즈를 바이트 연산을 하여, 화면에 적당한 값으로 출력하는 함수를 알아보도록 합니다.
 

 
Dialog and Windows (6)
 
 
Dialog Box의 Control에 Tooltip넣기 (0) / 작성자: 디버깅전문가 / 작성일: 2004-11-28 / 평점: 4.67
Tooltip은 CToolTipCtrl 클래스를 이용하면 쉽게 구현할 수 있습니다. 먼저 Create()를 호출해서 Tooltip 객체를 생성합니다. 그리고 나서 AddTool()을 호출해 각각의 컨트롤과 Tooltip 문자열을 연결해 줍니다. 여기서 Tooltip 문자열을 표시해 주는 함수는 ReplyEvent()이며, Tooltip 컨트롤 객체를 생성해 주고 컨트롤과 연결할 수 있는 가장 적당한 곳은 WM_INITDIALOG 메시지의 핸들러(OnInitDialog())입니다.
Dialog Base 프로그램을 Tray에 등록할 때 문제점 (0) / 작성자: 디버깅전문가 / 작성일: 2004-11-28 / 평점: 4.33
Dialog Base 프로그램을 Tray에 등록할 때 대부분 Window를 Hide시켜서 실행하게 된다. 그런데 Dialog Base로 프로그램 작성하면 프로그램이 처음 실행되면서 화면에 잠깐 나타났다가 사라지는 모습을 볼 수 있다. 이런 현상을 피할 수 있는 방법을 소개한다.
윈앰프처럼 TaskBar와 SystemTray 마음대로 주무루기 (0) / 작성자: 디버깅전문가 / 작성일: 2004-11-15 / 평점: 4.50
윈앰프에서 보면 TaskBar와 SystemTray에 동시에 보여주는 모드 혹은 각각 보여주는 모드 그리고 모두 보여주지 않는 모드가 있습니다. 4가지의 기능을 모두 구현해 보도록 하겠습니다.
다이얼로그 리소스의 실제 크기 얻기 (0) / 작성자: 디버깅전문가 / 작성일: 2004-11-15 / 평점: 5.00
VC++ 의 Resouce Editor 에서 작성한 다이얼로그의 크기는 실제 화면의 pixel 단위와 맞지 않기 때문에 종종 컨트롤 배치시에 어려움을 겪게 됩니다. 아래의 함수는 리소스에서 작성한 다이얼로그의 실제 크기를 구하는 함수입니다.
모달 다이알로그 시작시 숨기기 (0) / 작성자: 데미소다오렌지 / 작성일: 2004-11-30 / 평점: 4.00
이 문서는 MFC의 모달 다이알로그의 생성시 초기 상태를 숨김 상태로 하는 방법을 설명하고 있습니다.
Brush 의 패턴을 사용하여 스킨 구현하기 (0) / 작성자: 디버깅전문가 / 작성일: 2004-12-19 / 평점: 4.00
브러시의 패턴을 설정할 수 있다는 점과 브러시의 원점을 설정할 수 있다는 점에서 착안하여 만들어본 스킨 예제입니다.
 

 
List/Combo Controls (1)
 
 
List Control 에 다른 Control 넣기 (0) / 작성자: 디버깅전문가 / 작성일: 2004-11-28 / 평점: 5.00
특정 Column에서 다른 Control 을 띄우는 방법 설명. 여기서 사용한 방법은 현재 Cursor가 있는 위치를 파악한후 그 위치에 적당한 크기의 Edit Control를 생성 시킨다.
 

 
ListView/TreeView (1)
 
 
리스트 컨트롤 몇가지 팁 (0) / 작성자: bro / 작성일: 2004-10-20 / 평점: 4.86
1. 특정 ROW 포커스 주기 2. 특정 ROW로 가기 3. 헤더 컬럼수 얻어오기 4. 컬럼의 너비를 이쁘게 주기 5. 한줄 쭉 선택되게 하기, 그리드 라인 주기 6. 선택한 아이템(ROW)를 지우기 7. 두 아이템을 스왑 하기 8. 기존에 선택되어있는 것을 해체하기
 

'C/C++언어' 카테고리의 다른 글

함수포인터란 ?  (0) 2007.09.06
[본문스크랩] 파일 입.출력  (0) 2007.09.06
[본문스크랩] VC++ Article  (0) 2007.09.06
[강좌] MASM 6.0 사용법  (0) 2007.09.06
어셈블리 초급 기초 #1(정태식님)  (0) 2007.09.06
어셈블리 초급 기초 #2(정태식님)  (0) 2007.09.06


일단 첨부된 파일을 VC8.0 (.net 2005) 으로 돌려보면..
MS에서 제공하는 기본 Direct Draw 구동 소스가 나옵니다.

여기있는 구동소스를 이리저리 고치고 응용하면,
그럭저럭 괜찮은 DirectDraw를 구사할수 있답니다.

일부 초보를 상대로 만들어놓은 책은..

너무 자기네가 직접 짠 소스를 (그것도 256색 컬러 그림만 불러올수 있는 ㅡㅡ..) 설명하지만
(하지만 256컬러가 나쁘단건 아닙니다. 오히려 더 좋죠..)

이 소스는 어떤 그림이든 BMP 이면 불러올수 있는 소스입니다.
대충 이 소스를 분석하는것이 좋겠지만.

아무리 봐도 모르겠다 싶으신 분들은 이 밑의 설명을 봐주십시요.
그러나.. 분명히 말하는거지만... 설명만 읽고 아.. 글쿤 하고 넘기면
내일 까먹습니다 ㅡㅡ..

이해 가는 부분을 주석 처리하고는 식이든 해서 꼭 복습 하시길...

//////////////////////////////////////////////////////////////////
일단 Visual C++ 6.0 의 file view를 보면
=========================
Source Files
- ddex3.cpp       - 윈도 생성및 DirectDraw 초기화 및 구동소스
- ddex3.rc          - 별로 필요가.. 없는.. 그냥 밑의 리소스 ico 파일뗌에...
- ddutil.cpp        - Direct Draw 에 쓰이는 주요 명령어 함수들을 정의하는 소스 (중요)
=========================
Header Files
- ddutil.h            - ddex3.cpp 에서 ddutil.cpp 함수를 불러올수 없으니
                           여기서 ddutil.cpp 함수명들을 선언한뒤 ddex3.cpp 등에서 쓴다..
                          (즉 ddutil.cpp 안의 함수를 쓰고 싶으면 cpp 파일에 ddutil.h 만 선언하면 끝)
- resource.h       - 밑의 BMP 를 쓰기위해 필요한듯.. ㅡㅡ..
=========================
Resource Files
- directx.ico        // 필요 없음..  나중에 ddex3.cpp 의 winmain 함수를 고쳐주면 끝..ㅡㅡ..
- FRNTBACK.BMP // 필요없음..
=========================
가 있습니다....

여기서 중요한건 ddex3.cpp, ddutil.cpp 와 ddutil.h 임...
나머진 빼먹어도 상관없다

ddutil.cpp 와 ddutil.h 는 파일 이름에서 말해주듯..
Direct Draw Util 이다.. 즉 Direct Draw에서 쓰이는 화면 초기화
그림 불러오기, 표면생성, 투명키 설정등의 명령 함수가 있다.

이 ddutil.cpp를 잘 조합해서 쓰는곳이 ddex3.cpp 의 UpdateFrame 함수다..
일종의 UpdateFrame 함수를 이 소스의 엔진이라 생각해도 좋다.

이 UpdateFrame 함수는...WindowProc함수의 WM_TIMER 쪽에서 정해진 시간마다 실행하지만..
프로그래밍으로 보면 WinMain 함수의 while 문을 개조 하는편이 좋다

대략
==============================================================================
 while ( !GetAsyncKeyState(VK_ESCAPE))  // 여기서 부터는.. 게임 실제 돌아가는 부분..
 {
  Sleep(1); // M$꽁수인듯.. 이러면 Direct Draw cpu 점유율이 상당히 낮아지는..
  if ( PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) )
  {
   if ( !GetMessage(&msg, NULL, 0, 0) ) return msg.wParam;

   TranslateMessage( &msg );
   DispatchMessage( &msg );
  }
  else
  {
    //  게임 구동 함수
   }
 }
==============================================================================
식으로 바꾸는게 좋다.

하지만 이래도 사실 CPU 점유율이 높은데.. 그이유는
While 문으로 계속 키입력을 체크하기 때문이다.
즉 while 을.. while(1) 로 바꾸고 따로 탈출 루트를 만들면 CPU 점유율은 거의 없다고 봐도 좋을정도로 떨어진다.

'대학생 졸업하기 전 레벨 > DirectX' 카테고리의 다른 글

D3DX 조명  (0) 2007.12.03
Direct 3D 프로그래밍 과제  (0) 2007.11.12
픽킹. Projection 변환  (0) 2007.11.11
DirectX 3D 초기 소스  (0) 2007.10.08
DirectDraw의 기본 소스  (0) 2007.09.06
역전재판 소스.... 자작  (0) 2007.09.06

+ Recent posts