'개발'에 해당되는 글 73건

  1. 2007.10.17 비트벡터(BitVector) 이용하기
  2. 2007.09.28 인터넷 연결확인 방법
  3. 2007.09.13 뒤에 있는 윈도우를 앞으로 보내기
  4. 2007.09.13 윈도우를 투명하게 만들기 Win2000이상 1
  5. 2007.09.11 WM_MOUSELEAVE 메시지 받기 2
  6. 2007.08.30 [강좌] WTL로 프로그래밍하기#6 – 컨트롤 사용하기 1
  7. 2007.08.30 [CxxTest] 사용하려면... 이렇게.. 1
  8. 2007.08.30 [CxxTest] 소개 - 단위(유닛)테스트를 위한 C++용 라이브러리
  9. 2007.08.29 UTF간의 변환하는 소스
  10. 2007.08.17 작업관리자가 응답없음을 판별하는 방법

비트벡터(BitVector) 이용하기

개발 2007. 10. 17. 17:33

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

제목 : 비트벡터 이용하기

날짜 : 2007-10-02

저자 : hanburn



데이터를 표현할 때 비트단위를 이용하면 효율적인 경우가 있다. 요즘처럼 메모리도 많아지고 CPU도 빨라진 상황에서 굳이 비트단위의 연산을 사용할 필요가 있나 라고 생각할 수도 있지만 상황에 따라서 사용하면 상당히 효과적인 경우가 있다. 예를 들어서 2, 5, 8, 10, 14 19 이렇게 6개의 숫자를 저장해야 한다고 할 때 다음과 같이 표현될 수 있다.

 

비트 : 0010 0100 1010 0010 0001 0000

 

앞에서부터 각각의 비트는 0,1,2,3,... 을 나타내는 표현방식으로 3번째 비트가 참이므로 2를 의미하게 된다.  20이하의 숫자이므로 3Byte(3*8=24 : 24까지 표현가능) 표현을 할 수가 있는 것이다.  6개의 int를 저장하려면 4*6=24Bytye 가 필요한것에 피하면 21Byte가 절약이 된것이다.  1백만 이하의 숫자를 저장하는데는 1백만 비트가 필요하므로 125000 바이트가( 125KB) 필요하게 된다. 그냥 4Byte 의 숫자 1백만개를 저장하려면 4백만 바이트 ( 4MB)의 공간이 필요하다. 메모리 사용측면에서 엄청난 효율이다. 더욱이 사용하는 메모리가 줄어들면 속도도 빨라지는 이점이 있으므로 상당히 괜찮은 방법이다.

 

하지만 몇가지 제약사항이 있는데, 다음과 같다.

  
   첫째, 중복되는 숫자가 있으면 안 된다.

   둘째, 상대적으로 작은 숫자의 범위

   셋째, 숫자와 연관되는 데이터가 없어야 한다.

 

그러면 이러한 비트형태의 데이터를 표현하기 위해서는 어떻게 하면 좋을까?

 

보통의 경우라면 C++ 의 표준라이브러리에서(STL) 제공하는 vector<bool> 을 이용하는 것이 좋은 방법이고, 환경적인 요인으로 C++ STL을 사용할 수 없다면 다음과 같이 간단하게 구현하여 사용 할 수 있을 것이다. 간단한 클래스라서 C 함수로 변경도 쉬울 것이다.

 

// BitVector.h 파일

#define BITPERWORD 32

#define SHIFT_FIVE 5

#define MASK_BYTE 0x1F                // 0001 1111

#define BITCOUNT 1000000

 

class CBitVector

{

public:

        CBitVector(){}

        ~CBitVector(){}

 

        void SetBit(int i)

        {

               bitVector[i>>SHIFT_FIVE] |=  ( 1<<(i&MASK_BYTE) );

        }

 

        void ClearBit(int i)

        {

               bitVector[i>>SHIFT_FIVE] &=  ~( 1<<(i&MASK_BYTE) );

        }

 

        int GetBit(int i)

        {

               return bitVector[i>>SHIFT_FIVE] &  ( 1<<(i&MASK_BYTE) );

        }

 

protected:

        int bitVector[BITCOUNT/BITPERWORD+1];

 

private:

 

};

 

 

위의 클래스를 사용하는 예는 다음과 같다.

 

BOOL bit;

        CBitVector bitVector;

        bitVector.SetBit(5);

        bit = bitVector.GetBit(5);

        bitVector.ClearBit(5);

        bit = bitVector.GetBit(5);

 

5번째 비트를 설정하고 그값을 확인하고 다시 5번째 비트를 해제하고 값을 확인하는 간단한 코드이다.

 

정리하면, 비트벡터는 적절한 경우에 사용하면 메모리와 수행성능에서 좋은 결과를 보여준다. 다만 사용할 때 몇 가지 제약사항이 있고, 나중에 프로그램이 변경되어서(요구사항 변경으로) 비트벡터로 저장된 값이 다른데이터와 연관이 생기는 경우에는 대폭적인 수정이 필요 할 수도 있다.

 

비트벡터라는 개념과 사용시의 주의점을 알아두고 나중에 필요할 때 한번씩 사용을 해보자.

 



:

인터넷 연결확인 방법

개발 2007. 9. 28. 21:08

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

작성인 : 2007-09-28

작성자 : hanburn

 

인터넷 연결확인 방법

 

인터넷 관련 프로그램을 많이 하는데, 이때 필요한 것 중에 하나가 현재 인터넷에 연결이 되었는지 확인하는 것입니다. 보통 인터넷 파일오픈등의 방법으로 확인을 하는데, 이것보다는 인터넷에 연결된 상태를 확인하는 API가 있으니 이것을 이용하면 됩니다. InternetGetConnectedState, InternetGetConnectedStateEx  함수가 그것입다. 사용하는 법은 아래와 같습니다.
필요한 헤더파일은 WinInet.h 파일이고, 라이브러리는 WinInet.lib 입니다.

 


#include <WinInet.h>
#pragma comment (lib, "WinInet.lib")

        DWORD
dwFlag;

        TCHAR szName[256];

        ::InternetGetConnectedStateEx(&dwFlag, szName, 256, 0);

 

함수 리턴값이 TRUE이면 인터넷에 연결된 것이고, FALSE이면 연결이 안된 것입다. 그리고 dwFlag에 상태정보가 넘어오게 되는데 그 정보는 아래와 같습니다.

 

Value

Meaning

INTERNET_CONNECTION_CONFIGURED
0x40

Local system has a valid connection to the Internet, but it might or might not be currently connected.

INTERNET_CONNECTION_LAN
0x02

Local system uses a local area network to connect to the Internet.

INTERNET_CONNECTION_MODEM
0x01

Local system uses a modem to connect to the Internet.

INTERNET_CONNECTION_MODEM_BUSY
0x08

No longer used.

INTERNET_CONNECTION_OFFLINE
0x20

Local system is in offline mode.

INTERNET_CONNECTION_PROXY
0x04

Local system uses a proxy server to connect to the Internet.

INTERNET_RAS_INSTALLED
0x10

Local system has RAS installed.

 


dwFlag 값은 비트연산으로 확인 할 수 있는데, ( dwFlag & INTERNET_CONNECTION_LAN ) 이 참이면 랜으로 연결된 것입니다.

그리고 세번째 인자에는 현재 연결된 이름이 나오게 된다. 랜으로 연결된 경우에는 “LAN연결이라는 문자열이 넘어온다. 마지막 인자는 0으로 고정이다. 그리고 간단한 버전으로


         

InternetGetConnectedState(&dwFlag, 0);

 

이렇게 사용해도 된다.

 



:

뒤에 있는 윈도우를 앞으로 보내기

개발 2007. 9. 13. 14:05

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

목적 : 윈도우를 Foreground로 보내고 싶을때

보통 윈도우가 어떤 윈도우에 가려져 있는 경우나 또는 다른윈도우의 뒤에 있어서 않보이게 된경우 프로그램적으로 윈도우를 앞으로 나오게 할때 BringWindowToTop(), SetForegroundWindow 를 사용하여 처리를 하면 윈도우가 앞으로 나오게 된다. 그러나 가끔 않나올때가 있는데, 이럴때는 아래처럼 강제로 나오게 하는 방법이다.

void ForceForegroundWindow(HWND hWnd)
{
 if(hWnd == NULL) return;

 // DWORD SPI_GETFOREGROUNDLOCKTIMEOUT = 0x2000;
 // const DWORD SPI_SETFOREGROUNDLOCKTIMEOUT = 0x2001;

 DWORD ForegroundThreadID;
 DWORD ThisThreadID;
 DWORD Timeout;
 BOOL Result;

 if(GetForegroundWindow() == hWnd) {
  return;
 }
 else {
  // Windows 98/2000 doesn't want to foreground a window when some other
  // window has keyboard focus

  OSVERSIONINFO os;
  os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  GetVersionEx(&os);
  if((os.dwPlatformId == VER_PLATFORM_WIN32_NT && os.dwMajorVersion > 4) ||
   (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS &&
   (os.dwMajorVersion > 4 || (os.dwMajorVersion == 4 && os.dwMinorVersion > 0)))){

    Result = FALSE;
    ForegroundThreadID = GetWindowThreadProcessId(GetForegroundWindow(), NULL);
    ThisThreadID = GetWindowThreadProcessId(hWnd, NULL);
    if(AttachThreadInput(ThisThreadID, ForegroundThreadID, TRUE)) {
     BringWindowToTop(hWnd);
     SetForegroundWindow(hWnd);
     AttachThreadInput(ThisThreadID, ForegroundThreadID, FALSE);
     Result = GetForegroundWindow() == hWnd;
    }

    if(!Result) {
     SystemParametersInfo(0x2000, 0, &Timeout, 0);
     SystemParametersInfo(0x2001, 0, NULL, SPIF_SENDCHANGE);
     BringWindowToTop(hWnd);
     SetForegroundWindow(hWnd);
     SystemParametersInfo(0x2001, 0, &Timeout, SPIF_SENDCHANGE);
    }
   }
  else
  {
   BringWindowToTop(hWnd);
   SetForegroundWindow(hWnd);
  }
 }
}




:

윈도우를 투명하게 만들기 Win2000이상

개발 2007. 9. 13. 13:53

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

가끔 윈도우를 투명하게 하고 싶을때가 있는데, 이렇게 윈도우 전체를 투명하게 하는 방법이 있다. 이 방법은 윈도우가 WS_CHILD 속성을 가지고 있을 경우에는 효과가 나타나지 않는다. 즉 어떤 윈도우의 자식인 이부분의 윈도우를 투명하게는 못한다. 윈도우위 하위 윈도우를 투명하게 할때는 직접 그려주는 방법밖에는 없는듯 한다. WIN32 로는 AlphaBlend 함수를 이용하면 되고, GDI+ 를 이용하면 더 간단하게 투명하게 그릴수가 있다.

아래는 간단하게 윈도우 전체를 투명하게 하는 방법이다. SetLayeredWindowAttributes 함수를 이용해서 동작하는 간단한 효과이다.

BOOL SetWindowTransparent(HWND hWnd, BYTE nAlpha)
{
 if( FALSE == ::IsWindow(hWnd))
  return FALSE;

#define LWA_ALPHA 0x00000002


 // 투명윈도우를 위한 LayeredWindow 설정
 long oldWinStyle = GetWindowLong(hWnd, GWL_STYLE);
 ::SetWindowLong(hWnd, GWL_STYLE,  oldWinStyle & WS_POPUPWINDOW & ~WS_BORDER );

 LONG style = ::GetWindowLong(hWnd, GWL_EXSTYLE);
 if(!(style & 0x00080000))
 {
  ::SetWindowLong(hWnd, GWL_EXSTYLE, style | 0x00080000);
 }

 typedef BOOL (WINAPI *SLWA)(HWND hWnd, COLORREF crKey, BYTE bAlpha, DWORD dwFlags);
 SLWA pSetLayeredWindowAttributes = NULL;
 HINSTANCE hUSER32 = LoadLibrary("USER32.DLL");
 pSetLayeredWindowAttributes=(SLWA)GetProcAddress(hUSER32,"SetLayeredWindowAttributes");
 BYTE chAlpha = nAlpha;
 pSetLayeredWindowAttributes(hWnd, NULL, chAlpha, LWA_ALPHA);
 FreeLibrary(hUSER32);

 return TRUE;
}



:

WM_MOUSELEAVE 메시지 받기

개발 2007. 9. 11. 18:11

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

저자 : hanburn
환경 : Windows

WM_MOUSELEAVE 메시지는 마우스가 해당 윈도우를 떠날 때 발생하는 메시지이다.

기본적으로 이 메시지는 발생을 안 하는데 이 메시지를 받을려면 다음과 같이 처리를 해야 된다.

OnMouseMove 등에 다음과 같은 코드를 추가해주어야 한다.



 

TRACKMOUSEEVENT        mouseEvent;

mouseEvent.cbSize = sizeof(mouseEvent);

mouseEvent.dwFlags = TME_LEAVE;

mouseEvent.hwndTrack = m_hWnd;

TrackMouseEvent(&mouseEvent);

 

 

그러면 마우스가 윈도우를 떠날 때 WM_MOUSELEAVE 메시지가 날라오게 된다.



:

[강좌] WTL로 프로그래밍하기#6 – 컨트롤 사용하기

개발 2007. 8. 30. 15:19

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

저자 : hanburn

날짜 : 2007.08.29

환경 : WTL7.5, VS-2003

 

 

지난시간까지 정리를 하면(오랜만에 강좌를 쓰니까 기억이 않나서~ ) 위저드를 통해서 생성되는 코드의 뼈대를 살펴보고, 메시지맵에 대해서 알아 보았습니다. 그럼 다음단계로는 윈도우의 각종 컨트롤들을 사용하는 방법입니다. 컨트롤의 사용법이라고 해서 윈도우의 공용컨트롤들의 각각의 사용법을 알아보는 것이 아니라 MFC와 비교해서 컨트롤들의 일반적인 사용법을 애기하는 것입니다. 그럼 또 편한 말로 계속하겠습니다.

 

 

WTL에서 제공하는 컨트롤의 종류는 아래와 같습니다.

 

User controls: CStatic, CButton, CListBox, CComboBox, CEdit, CScrollBar, CDragListBox

Common controls: CImageList, CListViewCtrl (CListCtrl in MFC), CTreeViewCtrl (CTreeCtrl in MFC), CHeaderCtrl, CToolBarCtrl, CStatusBarCtrl, CTabCtrl, CToolTipCtrl, CTrackBarCtrl (CSliderCtrl in MFC), CUpDownCtrl (CSpinButtonCtrl in MFC), CProgressBarCtrl, CHotKeyCtrl, CAnimateCtrl, CRichEditCtrl, CReBarCtrl, CComboBoxEx, CDateTimePickerCtrl, CMonthCalendarCtrl, CIPAddressCtrl

Common control wrappers not in MFC: CPagerCtrl, CFlatScrollBar, CLinkCtrl (clickable hyperlink, available in XP and later)

 

이중에서 User / Common 그룹의 컨트롤들은 MFC에서 일상적으로 사용하던 것들이고 추가로 CPagerCtrl, CFlatScrollBar, CLinkCtrl등의 유용한 클래스들도 제공이 되고 있다. 윈도우 공용컨트롤들이야 윈도우에서 제공되는 것들을 MFC에서 랩핑한 방식 비슷하게 WTL도 랩핑하여 제공하고 있고 함수이름도 똑같이 제공한다. 다만, 파라미터의 순서가 조금 다른것도 있다.

 

윈도우 공용 컨트롤들을 사용하는 것은 리소스편집기에서 Dialog에 추가하거나 직접 코드에서 생성하여 사용하는 방법이 있는데, 이 방법에 대해서 자세하게 알아보자.

 

먼저 리소스에서 추가한 컨트롤을 제어 하려면 아래처럼 하면된다.

 

HWND hWndListBox = GetDlgItem(IDC_LIST1);

CListBox list1(hWndListBox);

CListBox list2;

list2.Attach(hWndListBox);

 

CListBox list3 = GetDlgItem(IDC_LIST1);

 

 

GetDlgItem으로 HWND를 얻어와서 생성자에 넣어 주거나 Attach 함수를 이용해서 hwnd를 붙여주면 된다. 또는 간편하게 GetDlgItem의 반환값을 직접 대입하는 식으로 써주면 된다. 그런뒤에는 CListBox의 멤버함수를 통해서 원하는 작업을 하면 된다. 여기서 한가지 알고 넘어갈 것은 list1,list2,list3 같은 래퍼클래스의(여기서는 CListBox) 인스턴스가 소멸된다고 해서 실제적인 CListBox가 파괴되는 것은 아니라는 점이다. 따라서 attach한 핸들을 detach할 필요가 없다.

 

코드에서 직접생성하는 경우는 더 쉽다. 아래는 CButton을 직접 생성하는 경우인데 m_btnTitle을 가지고 해당 버튼을 제어하면 된다.

 

m_btnTitle.Create(m_hWnd, NULL, NULL, WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 0, IDC_NES_WIDGET_BTN_TITLE);

 

컨트롤을 생성해서 제어를 하였으면 이제는 컨트롤에서 발생하는 이벤트를 처리해야 되는데, 이벤트 처리는 지난시간에 살펴본 메시지 핸들러를 통해서 제어하게 된다. 차일드 컨트롤에서 발생되는 이벤트는 부모위도로 WM_COMMAND, WM_NOTIFY 등의 메시지로 전달이 되므로 이 메시지를 잡아서 처리하면 된다. 간단하게 CListCtrl에서 발생하는 몇가지 이벤트처리 예를 보자

 

BEGIN_MSG_MAP_EX(CMainDlg)

        NOTIFY_HANDLER_EX(IDC_LIST, NM_DBLCLK, OnListDblClicked)

NOTIFY_HANDLER_EX(IDC_LIST, LVN_ITEMCHANGED, OnListItemchanged)

END_MSG_MAP()

 

LRESULT        OnListItemchanged(NMHDR* phdr);

LRESULT        OnListDblClicked(LPNMHDR pnmh);

 

 

위에서는 NM 계열의 일반적인 통지메시지와 ListCtrl의 통지메시지인 LVN_ITEMCHANGED를 처리하는 핸들러 함수의 모습이다. (.. 너무 쉽군 ^^)

 

다음으로는 컨트롤 관련해서 DDX라는 방법을 MFC에서 제공하기때문에 WTL에서도 DDX를 유사하게 제공하고 있다. 필자는 DDX/DDV 방법을 별로 사용하지 않지만 그래도 간단하게 알아보고 넘어가도록 하자.

 

DDX를 사용하기 위해서는 WTL의 설계 철학대로 CWinDataExchange 템플릿 클래스에서 상속을 받아야 한다. 그리고 메시지맵 비슷한 DDX맵을 추가해주어야 한다. DDX맵은 CWinDataExchange DoDataExchange 라는 함수를 재정의(override)하는 역할을 한다. 쉽게말하면 상속을 받았으면 꼭 추가를 해주어야 하는 매크로이다.(매크로대신 직접 코드를 써도 되긴 하지만.. ) 메시지맵에 익숙한 우리에게 DDX맵도 익숙할 수밖에 없다. DDX맵을 직접 보고 이야기 하도록 하자.

 

BEGIN_DDX_MAP(CMainDlg)

        DDX_CONTROL(IDC_EDIT, m_wndEdit)

        DDX_TEXT(IDC_EDIT, m_sEditContents)

DDX_FLOAT(IDC_EDIT, m_fEditFloat)

        DDX_FLOAT(IDC_EDIT, m_dEditDouble)

        DDX_CHECK(IDC_SHOW_MSG, m_bShowMsg)

        DDX_CONTROL(IDC_TREE, m_wndTree)

END_DDX_MAP()

 

시작과 끝은 DDX_MAP을 나타내고 중간에 있는 여러가지 DDX_로 시작하는 매크로들에 대해서 알아보자. 첫번째인 DDX_CONTROL은 컨트롤아이디에 해당하는 컨트롤과 변수를 연결시켜주는 역할을 한다. 두번째인 DDX_TEXT는 컨트롤과 변수를 연결시켜주는데, 여기서 변수는 CString, BSTR, CComBSTR 등이나 정적으로 할당된 char 배열도 가능하다. DDX_INT는 컨트롤과 정수 변수를 연결시켜주고, DDX_FLOAT는 컨트롤과 실수를 연결시켜준다. DDX_CHECK는 체크박스컨트롤과 intbool형 변수와 연결이 된고, DDX_RADIO는 라이오버튼과 int형 변수와 연결을 시켜준다.

 

이렇게 DDX_ 관련 매크로를 사용하여 컨트롤과 변수를 연결시킨 다음에는, 필요한 시점에 DoDataExchange() 함수를 호출해주면 MFC에서 UpdateData를 호출하는 것처럼 호출시 파라미터를 TRUE로 하면 컨트롤의 데이터가 변수로, 파라미터를 FALSE로 하면 변수의 값이 컨트롤로 전달이 된다.  그리고 여러가지 DDX_ 매크로 중에서 특정 컨트롤의 변수만 update하고 싶을때는 DoDataExchange의 두번째 인자로 컨트롤 아이디를 넣어주면 된다.

 

DoDataExchange(false, IDC_EDIT);

 

한가지 주의할 점은 DDX_ 매크로중에 잘못되 부분이 있다면 잘못된 부분의 아래에 있는 매크로는 작동이 안 되는 점이다.

 

여기까지 왔으면 다이얼로그 기반의 윈도우를 만들고 거기에 각종 컨트롤을 생성하고, 컨트롤을 제어하고, 컨트롤에서 발생하는 이벤트를 처리할수 있게 되었다. 이정도만 하면 왠만한 프로그램은 그냥 만들 수가 있을 것이다. ^^

 

 

프로그램을 하다보면 스킨등 입히거나 컨트롤의 기능을 확장하기위해서 subclassing을 해야 뭔가 그럴듯해 보이는 프로그램이 나오게 됩니다. 그래서 다음시간에는 Subclassing에 대해서 알아보도록 하겠습니다.  

 



:

[CxxTest] 사용하려면... 이렇게..

개발 2007. 8. 30. 15:09

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

작성일 : 2007.05.09
작성자 : 한상철 (hanburn)
환경 : VS-2003, CxxTest 


예전에 작석한 들인데 참 못섰다. 글제주가 이렇게 없다니~ ^^
CxxTest
2006년에 처음 접해보았다. TDD를 접하면서 테스트코드를 만드는 도구라는 이야기에 사용하게 되었다
TDD에 대해서는 여기에서 이미 알고 있다는 가정하에 시작하겠다. ( 본인은 아직 TDD에 대해서 잘 모른다. ^^)

CxxTest C++을 위한 테스트 프레임 워크이다. 아마 이것을 만든 사람이 워드 커닝햄인가?

간단한 용어정리부터 해보자. (여기서만 사용할 용어이다. ^^)
 

원본코드 : 여기서는 원래의 의미와 조금 다른뜻으로 사용하였다. (적당한 표현이 없어서.. ㅎㅎ) 우리가 원하는 동작을 하는 코드이다. 일반적으로 어플, dll 모듈에 해당한다.  

테스트코드 : 우리가 만든 코드를 테스트 해주는 코드이다. CxxTest 가 반자동으로 생성해 준다. 반자동이라는 얘기는 기초코드를 규치게 맞게 작성해야 한다는 말이다.
 


기본적으로  객체(class) 단위의 테스트코드를 작성하게 된다. 보통 프로젝트를 만들면 테스트코드를 위해서 테스트 하려는 부분을 클래스화 시켜야 한다. 그리고 원본코드를 테스트하기 위한 테스트 프로젝트를 만들어야 한다. 보통은 프로젝트이름+Test 정도로 이름을 붙여준다.  

그리고 우리가 테스트할 class 를 위한 테스트코드 헤더파일을 작성해야 한다. 예를들어 CMyCalc 라는 목적클래스가 있으면 CMyCalcTest.h 라는 파일을 생성한다. (여기서 파일이름의 끝이 xxxtest.h로 끝나야만 된다. 이것은 파이선스크립트에서 파일이름을 가지고 테스트코드(C++)를 생성하기 때문다. ) 그리고 CxxTest::TestSuite를 상속받는 클래스를 만들어 준다. 그리고 test로 시작하는 테스트함수를 작성해준다. 글로 길게쓰니까 무슨 말인지 잘 모를 것 같아서 간단한 샘플코드를 보자.

 

// RawPlayerTest.h
#include <CxxTest/TestSuite.h>   // for TestSuite
#include "..\\RawPlayer\\RawPicture.h" // for
테스트할 class 헤더

class RawPlayerTestSuit : public CxxTest::TestSuite
{
public:

 CRawPicture rawPicture;

 // 규칙 : 시작하기 전에 초기설정하는 함수(이름이 정확해야한다.)
 void setUp()
 {
  // rawPicture.Init();
 }

 // 규칙 : 객체에 대한 종료작업하는 부분
 void tearDown()
 {
  // rawPicture.Uninit();
 }
 
 //
규칙 : 테스트 함수는 test로 시작해야 한다.
 //
규칙 : 테스트 함수가 새로 추가되면 runner.cpp를 새로 생성해야 한다.
 void test_ReadRaw()  
 {  
  rawPicture.SetSize(2, 2);
  rawPicture.SetRGBMode(TRUE);
  TS_ASSERT_EQUALS(rawPicture.ReadFile("..\\Data\\small_2x2.raw"), TRUE);  
  std::vector<COLORREF> Pixcells;
  Pixcells.push_back(RGB(0,0,0));
  Pixcells.push_back(RGB(255,255,255));
  Pixcells.push_back(RGB(255,255,255));
  Pixcells.push_back(RGB(255,255,255));

  TS_ASSERT_EQUALS( Pixcells == rawPicture.GetPixcells(), TRUE );  
 }

 void test_111()
 {
  //
기타로 필요한 코드를 추가한다.  
 }
 
};

 위의 샘플을 보면 대충 알수 있다 .


---------중요한것 몇개 정리해보면..---------------

* 테스트함수는 test로 시작해야 한다. (파이선스크립트때문에)
* 파일이름은 test로 끝나야 된다. (RawPlayerTest.h)
* 초기화 함수이름은 void setUP(), 종료작업 함수이름은 void tearDown() 이다. (대소문자 구분)
* 테스트함수가 추가되면 Runner를 재생성 시켜야 된다.
* 테스트 프로젝트는 보통 폴더구조상 같은 레벨에 위치한다.
* 테스트프로젝트에서 테스트할 클래스를 포함시켜야 된다. (작업시에도 테스트 프로젝트로 클래스를 개발하는 것이편하다.)


어찌 보면 사용하는데 불편할 수도 있어 보인다. 그러나 CppUnit 보다는 간결하다.
(간단하다는 증거가 있나요? 라고 물으면, ..  개인적인 생각입니다~ ) 

VS2005 에서는 테스트프로젝트가 생겼다던데..  그것도 한번 봐야 겠다.
NUnit은 사용하기가 어떨까??

ps : 실제 적용된 환경에 맞추어서 작성된 간단한 샘플을 첨부파일로 올려두었다.



:

[CxxTest] 소개 - 단위(유닛)테스트를 위한 C++용 라이브러리

개발 2007. 8. 30. 14:50

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

저자 : hanburn

날짜 : 2007.08.30

환경 : VS-2003, CxxTest, Python

 

단위테스트를 클래스를 작성하고 클래스단위로 테스트 모듈을 만들어 두면, 추후에 수정을 가해가 할 때 조금 편리하게 작업을 할 수 있게 된다. 자바쪽에서는 JUnit이라는 라이브러리를 이용하고 C++ 쪽에서는 이것을 포팅한 CppUnit 이라는 것이 있다. 그런데 CppUnit 이라는 것이 사용하기가 좀 불편한 감이 있다. 그래서 조금 가볍고 사용이 쉬운 CxxTest라는 것을 소개한다.

 

소스받는곳 : http://cxxtest.sourceforge.net

기본사용법 : http://cxxtest.sourceforge.net/guide.html

 

 

CxxTest를 사용하기 위해서는 Python을 설치하는게 좋다. 왜냐하면, python 스크립트 중에서 cxxtestgen.py라는 스크립트가 포함되어 있는데, 이 스크립트가 testcode를 만들어 주기 때문이다. , CxxTest와 궁합이 잘 맞는다고 할 수 있다.

 

컴퓨터에 Python이 설치가 않되었다면 먼저 설치부터 하도록 하자.

 

파이선받기 : http://www.python.org

 

파이선은 받아서 설치만 하면 되니까 별다른 설정없이 그냥 설치하면 된다. 필자는 C:\밑에 그냥 설치를 하였다. 설치된 폴더에 보면 cxxtestgen.py라는 파이선 스크립트 파일이 보일 것이다. 내용이 꽤 긴 스크립트 파일이다. 이것이 용도는 파일을 열어보면 알겠지만, 테스트용 소스파일을 생성해주는 역할을 하는데, 옵션이 꽤 된다. 그래서 좀금더 편리하게 하기 위해서 다음과 같은 파이서 스크립트를 더 생성한다. (출처는 인터넷에서 구했다. )

 

 

import os

 

def toStr(aList):

           return ' '.join(aList)

 

def main():

           testFiles = []

           for eachFile in os.listdir("."):

                     if os.path.isfile(eachFile):

                                lastestPeriod = eachFile.rfind(".")

                                fileName = eachFile[:lastestPeriod]

                                extension = eachFile[lastestPeriod+1:]

                                if fileName.endswith("Test"):

                                          print fileName, extension

                                          testFiles.append(eachFile)

                    

           files = toStr(testFiles)

           if files == '':

                     print "No Test Files... Make XxxText.xxx..."

           else :

                     #cmd= "python cxxtestgen.py --runner=ParenPrinter --gui=Win32Gui -o runner.cpp "+toStr(testFiles)

                     cmd= "C:\Python25\python.exe C:\Python25\cxxtestgen.py --runner=ParenPrinter --gui=Win32Gui -o runner.cpp "+toStr(testFiles)

                     print cmd

                     os.system(cmd)

 

if __name__=="__main__":

           main()

 

 

대충보면 폴더에서 파일을 찾아서 확장자 전에 Test 라는 이름이 들어가는 파일을 찾아서 cxxtestget.py 스크립트 파일에 몇가지 옵션과 함께 넘겨서 테스트 소스를 생성해주는 역할이다.

 

위의 내용을 MakeCxxTest.py 라는 이름으로 파이선이 설치된 폴더(C:\Python25)에 생성을 해 놓는다.

 

다음으로는 우리가 사용할 VS2003에서 방금 만든 MakeCxxTest.py를 호출(실행)할수 있도록 간단하게 환경설정을 해보도록 하자.

메뉴에서 도구 -> 외부도구를 누르면 뜨는 창에 아래처럼 추가를 한다.

 

사용자 삽입 이미지


제목을 써주고, 명령과 인수를 각자 환경에 맞추어서 설정해주면 된다. 그리고 오류내용을 보기 쉽게 출력창사용에 체크를 해주면 된다. 요렇게 간단하게 설정하면 CxxTest를 사용할 준비가 된된 것이. ^^

 

위에보면 Run Cxx Test Runner 라는 명령도 추가를 해주었는데, 별로 필요는 없다. 왜냐하면, 나중에 테스트 프로젝트를 실행 프로젝트로 하고 실행을 하는 것과 같기 때문이다. 개발시에 그냥 실행프로젝트를 설정해놓고 개발하는 것이 더 편리한 것 같더라. VS-2003의 개발환경에 익숙하고 단축키에도 익숙하므로..   단축키 얘기가 나왔으니, 위의 명령을 단축키로 할당해 놓는 것도 편리하다.




:

UTF간의 변환하는 소스

개발 2007. 8. 29. 14:05

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

Unicode Consortium이 제공하는
유니코드간 변환소스(C언어)

http://www.unicode.org/Public/PROGRAMS/CVTUTF/

를 참고하여 CUTFTrans 라는 클래스를 만들어 보자.. ㅋㅋ



:

작업관리자가 응답없음을 판별하는 방법

개발 2007. 8. 17. 14:53

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

예전에 어디에서가 비슷한 내용을 본적이 있다. 그때 본 내용은 WM_GETICON 이라는 메시지를 보내서 바로 응답이 오면 프로그램이 작동중이고, 응답이 않오면 프로그램이 멈춘상태(응답없음)라는 것이다. 당연히 메시지를 보냈는데, 응답이 않오면 작업관리에서 보이는 것처럼 응답없음 상태로 보는 것이다.

  그런에 이와 유사한 기능을 하는 api가 있었다. 바로 IsHungAppWindow 라는 함수이다. 그래서 테트스겸 사용을 해볼려고 하니까 아래처럼 링크에러가 발생한다.

WindowsAPIDlg.obj : error LNK2019: __imp__IsHungAppWindow 외부 기호("protected: virtual int __thiscall CWindowsAPIDlg::OnInitDialog(void)" (?OnInitDialog@CWindowsAPIDlg@@MAEHXZ) 함수에서 참조)를 확인하지 못했습니다.
Debug/WindowsAPI.exe : fatal error LNK1120: 1개의 확인할 수 없는 외부 참조입니다.

이럴수가!!  분명히 msdn에서 말하기 아래처럼 정보가 있었는데..

Minimum DLL Version user32.dll
Header Declared in Winuser.h, include Windows.h
Import library User32.lib
Minimum operating systems Windows 2000

허허 참 이상하다..  그래서 검색을 조금 해보니까.. user32.dll을 직접 로딩해서 사용해라는 것이다. 허허.. msdn 이거 않되겠구만~ 엉터리 정보를 가지고 있다니..
그래서 할 수 없이 아래처럼 직접 로딩해서 사용하면 된다.

typedef BOOL (WINAPI *PROC_IsHangAppWindow)(HWND);
PROC_IsHangAppWindow IsHangAppWindow;
HMODULE hUser32 = GetModuleHandle("user32");
IsHangAppWindow = (PROC_IsHangAppWindow) GetProcAddress(hUser32, "IsHungAppWindow");

BOOL b = IsHangAppWindow(hWnd);

확인결과 잘 작동한다. 리턴값은 응답없음이면 TRUE 를 리턴한다. 
단점은 윈도우2000 이상에서만 된다는..



: