공룡호가 사는 세상 이야기

1. [New File] 메뉴를 이용하여 나오는 창에서 C++ 항목을 선택하세요
    - Cocoa Thouch 에서는 C++ 생성 항목이 없습니다, 아래쪽 Cocoa 항목에서 선택할 수 있습니다.

2. 파일이름을 입력하세요( CppObject.mm)
   - 헤더파일과 함께 프로젝트에 생성됩니다.

3. 클래스를 구현하세요.

 CppObject.h

    class CppObject
    {
           int  m_nMeber;
public:        
       CppObject();
       ~CppObject();
    }

 

 CppObject.mm

   CppObject::CppObject()
   {
       m_nMember = 10;
   }   
   CppObject::~CppObject()
   {
   }

4. 컴파일을 우선 해봅니다.
5. 컴파일 성공해서 빌드까지 무사히 성공되는 것을 볼 수 있습니다.

--------------------------------------
 이제 Object-C에서 직접 사용해 보시다.
--------------------------------------

1. AppDelegate 클래스의 초기화 함수에서 호출해 봅니다. 

 AppDelegate.m

 #include "CppObject.h"
 - (void) somefunction
{
   CppObject* pObj = new CppObject();
  delete pObj;
}

2. 컴파일 합니다.
3. 에러가 발생합니다.
   - Object-C는 파일확장자를 이용하여 언어를 구분하는 것 같았습니다.
   - m 확장자인 경우에는 C++ 코드를 사용할 수 없었습니다.
4. 그래서 AppDelegate.m의 확장자를 mm으로 변경합니다

 AppDelegate.mm

 #include "CppObject.h"
- (void) somefunction
{
   CppObject* pObj = new CppObject();
  delete pObj;
}

5. 다시 빌드합니다
6. 빌드 성공해서 디버깅해봅니다.
   m_pObj->m_nMember 값이 생성자에서 설정한 '10'을 가지고 있음을 알 수 있습니다.
이제부터는 C++를 자유롭게 이용할 수 있다니, 한결 개발이 자유로울 것 같네요. 

----------------------------------------------
Cocoa 객체 사용하기
----------------------------------------------

다음으로, C++ 클래스에서 Cocoa 객체를 사용할 수 있는지 테스트 해보았습니다. 
1. 아래와 같이 Cocoa 객체를 선언하고, 생성합니다. 

 CppObject.h

    class CppObject
   {
       int  m_nMeber;
       NSString*   strTitle;
public:        
       CppObject();
       ~CppObject();
    }

 

 CppObject.mm

   CppObject::CppObject()
   {
       m_nMember = 10;
       strTitle = [NSString stringWithString:@"Hello World"];
   }   

   CppObject::~CppObject()
   {
       [strTitle release];
   } 

2. 빌드 합니다.
3. 위의 테스트 코드에서 breakpoint를 설정하고 값을 확인 또는 생성자에서 값을 확인합니다.
   - strTitle이 "Hello World"를 가지고 있는 것을 볼 수 있습니다. 
이상입니다. 

결론은  C++를 사용하고 싶으면 확장자를 mm으로 사용하는 것 이었습니다. 참 쉽죠~

기존에 가지고 있던 C++ 코드가 있다면, 많은 부분을 재사용할 수 있을것 같네요.
C++를 사용함으로써 iPhone에서 다른 문제가 있는지는 저두 입문한지 얼마안되서 잘 모르겠습니다.
이부분은 저두 사용해 보면서, 추가적인 정보가 있으면 올리도록 하겠습니다.

[출처]맥부기 개발자 모임: 아이펠스님 게시물

Resource Leaking

프로그래밍2007. 8. 13. 18:33

MFC 에서, 컨트롤의 색상을 변경하고자 할 때, OnCtlColor()을 사용한다. (버튼 컨트롤 제외)

HBRUSH CPppDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
 HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);

 if( pWnd->GetDlgCtrlID() == IDC_DIC)
 {
  hbr = CreateSolidBrush( RGB(0,0,255) );
  pDC->SetBkMode( TRANSPARENT );
  pDC->SetBkColor( RGB(0,0,255) );
  pDC->SetTextColor( RGB(255,255,0) );
    
  return hbr;       
 }
 return hbr;
}


여기서 문제가 있다. 이 메소드는 해당 컨트롤을 다시 그려야 할 이유가 생길 때 마다 자동적으로 호출된다.
따라서, 프로세스의 메모리 점유가 늘어날 수 밖에 없다.
계속해서 CreateSolidBrush()를 통해 계속해서 브러시를 생성하기 때문.

프로그램 시작시, 단 한번만 브러시를 생성하고 프로그램 종료 시, 생성된 브러시를 파괴해 주는 것으로 이 부분은 해결된다. 코드는 다음과 같다.

생성자에 다음과 같은 코드를 삽입한다.
물론 hBkBrush 는 HBRUSH type 이며, 클래스 정의부분에 명시해 둔다.
hBkBrush = CreateSolidBrush(RGB(0,0,255));

그리고 위의 코드 중, 붉은색으로 된 부분을 다음과 같이 변경한다.
hbr = hBkBrush;

마지막으로, 프로그램 종료시 호출되는 파괴자나, 기타 메소드 중에 적당한 곳을 골라 브러시 객체를 파괴한다.
DeleteObject(hBkBrush);

'프로그래밍' 카테고리의 다른 글

C# TIP 몇가지  (0) 2007.10.04
구글 가젯 만들기, Part1  (1) 2007.08.21
WebPage Redirect (MFC / API)  (0) 2007.05.16
SetTimer()  (0) 2007.05.14
ROBOCODE Master의 비밀!!!  (0) 2007.04.23

Memod Version 0.1 Beta



프로그램의 이름은 Memorize 와 Word 를 합성하여 붙였습니다.
워낙에 컴퓨터 앞에 앉아 있는 시간이 많다 보니,
좀 더 효과적으로 영어 단어를 외우는 방법은 없을까 해서 간단하게 만들어 보았습니다.
Data 파일의 형식만 지킨다면, 영어 단어 암기 외의 용도로도 사용할 수 있을 것 같습니다.
사용하시는 분들의 많은 버그레포팅 부탁합니다.
사실 너무 간단한 프로그램이라 내놓기에도 민망하지만 -_ -;

[사용법]
실행파일과 함께 들어 있는 dic.txt 파일을 메모장으로 EDIT 합니다.
구분자 '|'를 기준으로 좌측은 영단어, 우측은 뜻이나 의미 등을 기술합니다.
저장 후, 메모드를 실행시키고, Play 버튼을 클릭하면 기록한 데이터가 일정 간격으로 회전합니다.
회전 시간 변경은 Play 버튼 우측의 ComboBox를 통해 할 수 있습니다.

[주의사항]
dic.txt 파일 내에 공백(space)이 존재할 경우, 정상적인 출력이 불가능합니다.
하나의 단어에 여러개의 의미를 부여할 경우, '|'를 사용하여 구분할 수 있습니다.
example)
dog|개|멍멍이|강아지
cat|고양이|야옹이

[사용 예]
저는 화면 우상단에 최대 최소화, 종료버튼이 가리지 않을 만큼에 위치에 두고 씁니다;


invalid-file

Memod 다운로드


다음 버전에서 수정할 사항
1. 공백이 들어간 문자열 표시 기능 (단어 외 숙어 표시 가능)
2. Stop 버튼
3. Stop 된 상태에서 단어의 자세한 의미를 알고자 할 경우, 네이버 OpenAPI를 이용, 서비스
[추가중]

SetTimer()

프로그래밍2007. 5. 14. 16:15

일정 시간마다 특정한 일을 수행할 때 대개 SetTimer() 함수를 사용한다. (일정 시간이 경과할 때까지 Sleep하는 건 유치할 것같다.. ㅋㅋ) 책을 좀 찾아보니 SetTimer()는 SDK에서 제공되는 API 함수가 원조격이다. 일단, MSDN을 열어봤다.

이미지를 클릭하시면 원본크기로 보실수 있습니다.

보다시피 VC++에서 제공되는 SetTimer() 함수는 총 3개가 존재한다. 그런데, 맨 위의 CWindows::SetTimer는 ATL에서 사용되기 때문에 통상으로 사용되는 SetTimer() 함수는 SDK의 API 함수와 CWnd::SetTimer 멤버함수가 되겠다. (따라서, SetTimer()는 SDK버전과 MFC버전 두개만 정리하면 된다.)

먼저, SDK의 SetTimer() 함수의 원형을 살펴본다.

UINT SetTimer(
  HWND hWnd,    // handle of window for timer messages
  UINT nIDEvent,          // timer identifier
  UINT uElapse,           // time-out value
  TIMERPROC lpTimerFunc   // address of timer procedure
);

첫번째 인자는 SetTimer()를 호출하는 윈도우의 핸들이고, 두번째는 타이머의 ID이다. 애플리케이션은 여러 개의 독립된 타이머를 이용할 수 있다. 따라서, 각각의 타이머를 구별하기 위해 ID를 부여한다. 세번째 인자는 타이머의 주기(단위는 밀리초)이며, 마지막 인자는 타이머가 동작할 때 시스템이 호출하는 콜백함수(이를 타이머 프로시져라 한다)의 함수포인터(여기서, 타이머 프로시져의 함수이름은 자기 마음대로 결정해도 된다)이다. 즉, 일정 시간이 발생하면 해당 콜백함수를 실행하게 되는데, 거기에 우리가 필요로 하는 루틴을 넣어주면 된다.

그러면, SetTimer()에 등록하는 콜백함수(타이머 프로시져)는 어떻게 정의해야 할까? (타이머 프로시져는 콜백함수이기 때문에 함수이름은 SetTimer에 등록한 함수이름과 동일해야 하며, 시스템이 정한 호출 형식대로 정의를 해두어야 한다.)

VOID CALLBACK TimerProc(
  HWND hwnd,     // handle of window for timer messages
  UINT uMsg,     // WM_TIMER message
  UINT idEvent,  // timer identifier
  DWORD dwTime   // current system time
);

호출되는 타이머 프로시져 함수는 위와 같은 형식이다. 첫번째 인자인 hWnd는 타이머를 호출한 윈도우의 핸들이며(SetTimer()함수의 첫번째 인자를 생각할 것), 두번째는 시스템이 던져주는 타이머 메시지(항상 WM_TIMER이다), 세번째는 호출한 SetTimer함수의 Id값, 네번째는 시스템 시간이다. 위의 인자들은 TimerProc가 콜백함수이기 때문에 시스템이 알아서 던져준다. 따라서, 우리는 타이머 Id를 조사(if 내지는 switch)하여 해당 타이머에 대한 기능을 구현하면 될 것이다.

그런데, MSDN을 자세히 읽어보면 SetTimer()의 인자 중에서 콜백함수 대신 NULL을 대입하는 경우가 있다. 이 경우, 시스템은 일정 시간에 이르면 콜백함수를 호출하는 것이 아니라 애플리케이션에 WM_TIMER 메시지를 전달한다. 따라서, Win32 프로그램의 경우라면 WndProc에서 WM_TIMER 발생에 따른 처리루틴을 구현하면 된다.

정리하면, SDK의 SetTimer함수는 콜백함수에 의한 처리방식과 WM_TIMER 메시지에 대한 처리방식으로 그 사용방법이 나뉘어진다. 이는 MFC에서도 마찬가지이다. 이제 MFC의 SetTimer() 함수를 살펴보자.

UINT

CWnd::SetTimer(

            UINT nIDEvent,

            UINT nElapse,

void (CALLBACK EXPORT* lpfnTimer)(HWND, UINT,

                                        UINT, DWORD) );

MFC의 SetTimer() 함수는 CWnd클래스의 멤버함수로 구현되어 있기 때문에 SDI, MDI, 다이얼로그 애플리케이션에서 모두 사용이 가능하다. SDK와의 차이점은 SDK의 첫번째 인자인 hWnd를 가지고 있지 않다는 점. 당연히 CWnd의 멤버함수이므로 hWnd를 알고 있기 때문일 거다. 그 점을 제외하면 SDK버전과 별반 다를게 없다.

다만, MFC에서는 타이머 프로시져를 사용하지 않을 경우 WM_TIMER의 처리를 위해서 OnTimer() 이벤트 핸들러를 추가해서 사용하면 될 것이고, 타이머 프로시져를 사용할 경우 타이머 프로시져는 전역함수이기 때문에 주윈도우(또는 주다이얼로그)의 멤버에 접근하기 위해서 다음과 같은 방법을 사용할 수 있다.

가령, 다이얼로그 기반으로 TestProg라는 애플리케이션을 작성하였을 경우

void CALLBACK TimerProc(HWND hWnd, UINT nIDEvent, UINT nElapse, DWORD dwTime)

{

    ...

    CWnd *pWnd = AfxGetMainWnd();

    CTestProgDlg *dlg = (CTestProgDlg *)pWnd;

    dlg->멤버함수();

}


이런 식으로 하면 된다.

'프로그래밍' 카테고리의 다른 글

Resource Leaking  (6) 2007.08.13
WebPage Redirect (MFC / API)  (0) 2007.05.16
ROBOCODE Master의 비밀!!!  (0) 2007.04.23
우연히 보게 된 코드  (2) 2007.04.19
공사  (0) 2007.04.17