hyeonk lab

블로그 이미지

hyeonk

hello world! hyeonk lab.

'mfc & winAPI'에 해당되는 글 17건

제목 날짜
  • 마우스 이벤트 중복 클릭 방지 함수 2017.05.29
  • [강좌/메시지] WM_NOTIFY 메시지에 대해서...(ON_NOTIFY) - 2편 2015.08.19
  • [강좌/메시지] WM_NOTIFY 메시지에 대해서...(ON_NOTIFY) - 1편 2015.08.19
  • #import msado15.dll이 소스에서 OS등에 따라 컴파일이 되지 않을 때 2014.04.11
  • BOOL PreTranslateMessage(MSG* pMsg) 2014.03.21
  • 분할 윈도우 중 하나에 접근하는 방법 2014.02.10
  • [MFC] SendMessage 2014.01.07
  • 어플리케이션(MFC)에서 스레드 사용 및 주의사항 (필독!!) 2014.01.07
  • [MFC] MFC 팁 모음 2013.06.28
  • Win32Api에서 x64(64비트) Application을 개발할때의 주의점들 2013.04.15

마우스 이벤트 중복 클릭 방지 함수

mfc & winAPI 2017. 5. 29. 11:16

실행중인 기능을 마칠때 

함수 인자의 메시지 범위 마우스 클릭 관련 메시지들을 삭제해버린다.

메시지 범위는 수정이 가능.


MSG _msg;

while( PeekMessage( &_msg, NULL, WM_LBUTTONDOWN, WM_MBUTTONDBLCLK, PM_REMOVE ) );


* 주의: 예약된 중복 클릭을 이것으로 방지 하더라도, 다른 ui부분에서 또 발생이 되면 처리가 곤란해질 수 있다.

돌발적인 지연은 어떤 ui 요소에서건 발생할 수 있기 때문에, 꼭 이 방법이 정답이 될 수는 없다.

그럴 경우엔, 메시지를 삭제하지말고, flag를 통한 구분으로 무시할 메시지는 흘려보내는게 더 좋을 수 있다.

저작자표시 동일조건 (새창열림)

'mfc & winAPI' 카테고리의 다른 글

[강좌/메시지] WM_NOTIFY 메시지에 대해서...(ON_NOTIFY) - 2편  (0) 2015.08.19
[강좌/메시지] WM_NOTIFY 메시지에 대해서...(ON_NOTIFY) - 1편  (0) 2015.08.19
#import msado15.dll이 소스에서 OS등에 따라 컴파일이 되지 않을 때  (0) 2014.04.11
BOOL PreTranslateMessage(MSG* pMsg)  (0) 2014.03.21
분할 윈도우 중 하나에 접근하는 방법  (0) 2014.02.10
Posted by hyeonk

[강좌/메시지] WM_NOTIFY 메시지에 대해서...(ON_NOTIFY) - 2편

mfc & winAPI 2015. 8. 19. 13:57

출처 : http://www.tipssoft.com/bulletin/tb.php/FAQ/65


4. MFC 프로그램에서 WM_NOTIFY 메시지 사용하기
 
    일반적인 방식으로 생각한다면 WM_NOTIFY 메시지에 대한 핸들러는 OnNotify 일것입니다. 
    CWnd 클래스를 살펴보시면 아시겠지만 OnNotify라는 멤버함수가 있습니다. 하지만, 우리는
    이 함수를 등록해서 사용하지는 않습니다. 왜냐하면 이 함수로는 모든 통보 메시지가
    전달되기 때문에 OnNotify 함수에서 코드를 작성하면 C++적인 의미가 다소 줄어들수 있으므로
    이 함수를 등록해서 사용하지 않고 개별적인 처리루틴을 사용하도록 권장하고 있습니다.
    ( OnNotify 함수를 등록하고 if문 또는 switch문을 사용해서 각 메시지를 분류하여 사용하기도
      하는데, 이런 형식은 C 방식에서 많이 사용하는 방법입니다. )
 
    MFC에서는 기본적으로 메시지별로 핸들러 함수를 사용하도록 되어있습니다. 따라서 각 
    통보 메시지별로 핸들러를 등록할수 있는데, 메시지 맵에 아래와 같이 등록하시면 됩니다.
 
    ON_NOTIFY( notify_code, control_id, HandlerFunction )
 
    위와 같이 정의하면 control_id를 가진 컨트롤에서 발생된 통보 메시지 중에 세부 코드가
    notify_code (NMHDR 구조체의 code 항목에 저장된 값) 인 경우, HandlerFunction 함수를
    수행하겠다는 뜻이 됩니다.
 
    예를 들어, 리스트 뷰 컨트롤이 있고 키를 눌렀을때 OnMyListViewKeyDown 이라는 함수를
    호출하고 싶다면 아래와 같이 사용하시면 됩니다.
    ( 해당 리스트 뷰 컨트롤의 아이디 :  IDC_MY_LIST_VIEW 로 가정 )
 
    ON_NOTIFY( LVN_KEYDOWN, IDC_MY_LIST_VIEW, OnMyListViewKeyDown )
 
    사실, 리스트 뷰, 트리 뷰 등과 같이 잘 알려진 컨트롤의 통보 메시지는 클래스위저드를
    이용해서 등록가능하기 때문에 위 사항을 직접 입력하실 필요는 없습니다. ^^;; 하지만,
    자신이 새롭게 만든 컨트롤인 경우에는 클래스위저드의 지원을 받을 수 없기 때문에
    직접 메시지맵에 입력하셔야 합니다.
 
    ON_NOTIFY 매크로의 3번째에 입력한 핸들러는 어떻게 구성되는지에 대해서 알아보겠습니다.
    먼저 함수의 원형은 아래와 같습니다.
 
    afx_msg void HandlerFunction( NMHDR * pNotifyStruct, LRESULT * result );
 
    일반적으로 클래스위저드를 사용해서 등록하게 되면 위 코드가 해당 클래스의 헤더파일 내에
    자동으로 추가됩니다. 그리고 아래와 같이 해당 클래스의 소스 파일에는 핸들러 코드가 추가됩니다.
 
    void 해당클래스::HandlerFunction( NMHDR * pNotifyStruct, LRESULT * result )
    {
        // TODO: Add your control notification handler
        //       code here
   
        *pResult = 0;
    }
 
    위에서 예를 든것처럼 리스트 뷰 컨트롤이 있고 키를 눌렀을때 OnMyListViewKeyDown 이라는 함수를
    호출하고 싶다고 선택했다면 아래와 같이 핸들러 루틴이 추가될 것입니다.
    ( 클래스위저드가 자동으로 추가해 줍니다.  )
 
    void 해당클래스::OnMyListViewKeyDown( NMHDR * pNotifyStruct, LRESULT * result )
    {
        LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNotifyStruct;
        // TODO: Add your control notification handler
        //       code here
   
        *pResult = 0;
    }
 
    위 코드에서 보시면 알수 있듯이 리스트 뷰 컨트롤의 LVN_KEYDOWN 통보 메시지는 NMHDR 구조체를
    확장해서 LV_KEYDOWN 이라는 구조체를 사용하고 있기 때문에 클래스위저드가 자동으로 형변환까지
    코드를 생성시켜 줍니다. 만약, 이 강좌의 1편에서처럼 자신이 만든 클래스에 통보 메시지를 보내는
    코드를 보냈고 해당 통보 메시지가 MyNotifyData 라는 구조체를 사용했다면 형변환을 아래처럼 직접
    하시면 됩니다.
 
    MyNotifyData *p_my_data = (MyNotifyData *)pNotifyStruct;
 
    당연한 이야기겠지만 통보 메시지 데이터 자체가 NMHDR을 이용한다면 형변환 없이 pNotifyStruct 변수를
    바로 사용하시면 됩니다.
 

5. 동일한 통보 메시지를 일괄 처리하기
 
    자신이 하나의 대화상자에 리스트 뷰 컨트롤을 3개를 만들고 각 아이디를 IDC_MY_LIST_VIEW1, 
    IDC_MY_LIST_VIEW2, IDC_MY_LIST_VIEW3로 부여했다고 합시다. ( 각 컨트롤의 번호는 
    resource.h 파일에서 확인했을 때, 순차적으로 배열되어있다고 가정하겠습니다. ) 대화상자에서
    각 컨트롤의 LVN_KEYDOWN 통보 메시지를 일괄적으로 처리해야 하는 경우, 핸들러를 3개
    등록하지 않고 1개만 등록해서 처리하는 방법에 대해서 알아보도록 하겠습니다.
 
    먼저 메시지 맵에 아래와 같은 메크로를 등록합니다.
 
    ON_NOTIFY_RANGE( notify_code, start_control_id, end_control_id, HandlerFunction )
 
    위 사항을 적용해서 등록한다면 아래와 같습니다.
 
    ON_NOTIFY_RANGE( LVN_KEYDOWN, IDC_MY_LIST_VIEW1, 
                                                           MY_LIST_VIEW3,  OnMyListViewKeyDown)
 
    Range 관련 메크로는 클래스위저등의 지원을 받지 못하기 때문에 직접 입력하셔야 합니다.
    해당 클래스의 헤더파일에 추가되는 OnMyListViewKeyDown 함수의 형식은 ON_NOTIFY 때와
    약간의 차이가 생기는 아래와 같습니다.
 
    afx_msg void HandlerFunction( UINT control_id, NMHDR * pNotifyStruct, LRESULT * result );
 

    위와 같이 control_id라는 인자가 하나 추가되는데, 그 이유는 3개의 컨트롤에서 발생된 
    통보 메시지가 일괄적으로  이 함수를 사용하기 때문에 어떤 컨트롤에서 이 메시지가
    전달되었는지 확인할수 있도록 통보 메시지를 발생시킨 컨트롤의 아이디가 추가된 것입니다.


저작자표시 (새창열림)

'mfc & winAPI' 카테고리의 다른 글

마우스 이벤트 중복 클릭 방지 함수  (0) 2017.05.29
[강좌/메시지] WM_NOTIFY 메시지에 대해서...(ON_NOTIFY) - 1편  (0) 2015.08.19
#import msado15.dll이 소스에서 OS등에 따라 컴파일이 되지 않을 때  (0) 2014.04.11
BOOL PreTranslateMessage(MSG* pMsg)  (0) 2014.03.21
분할 윈도우 중 하나에 접근하는 방법  (0) 2014.02.10
Posted by hyeonk

[강좌/메시지] WM_NOTIFY 메시지에 대해서...(ON_NOTIFY) - 1편

mfc & winAPI 2015. 8. 19. 13:56

출처: http://www.tipssoft.com/bulletin/tb.php/FAQ/63


WM_NOTIFY 메시지는 우리가 프로그램하면서 많이 사용하는 메시지 중에 하나입니다.:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

하지만 그 용법이나 의도를 제대로 이해하지 못하고 사용하는 사람들이 많아서

MSDN의 Technical note 61번의 내용을 근거로 간단한 소개글을 만들었습니다.

 

 

1. 통보(Notify) 메시지의 필요성

 

    WM_NOTIFY 메시지는 일반적으로 자식윈도우(예, 컨트롤-버튼,에디트박스, ...)가 자신에게

    일어난 여러가지 상황을 부모윈도우(예, 대화상자)에게 전달할때 사용합니다.

 

   예를 들어, 대화상자에 버튼을 하나 만들었다고 하면 해당 버튼을 눌렀을때 WM_COMMAND 라는

   메시지가 발생합니다. 이 메시지는 단순한 통보(notify)를 목적으로 구성되었기 때문에

   WPARAM에 BN_CLICKED(HI WORD)와 해당 컨트롤의 ID(LOW WORD)가 저장되고

   LPARAM에 해당 버튼 컨트롤의 핸들이 저장된 상태로 전달됩니다.

 

   위 구성에서 본것처럼 이미 WPARAM, LPARAM을 모두 사용해버렸기 때문에 버튼 컨트롤 입장에서는

   추가적인 정보(마우스 클릭 좌표와 같은 정보)를 전달하고 싶어도 전달할 방법이 없습니다.

 

   컨트롤의 종류가 다양해지고 요구사항이 복잡해짐에 따라서 윈도우즈 시스템은 추가적인 정보를

   포함할수 있는 메시지가 필요하게 되었고 아래와 같은 메시지가 추가되었습니다.

 

   WM_CTLCOLOR, WM_VSCROLL, WM_HSCROLL, WM_DRAWITEM, WM_MEASUREITEM,

   WM_COMPAREITEM, WM_DELETEITEM, WM_CHARTOITEM, WM_VKEYTOITEM, ...

 

 

2. Win32 시스템에서의 통보 메시지에 대하여...

 

    Win32 시스템은 하위 시스템의 호환성을 유지하기 위해 기존 Windows 3.x에서 사용하던 메시지들을

    대부분 수용하고 있습니다. 즉, 위에서 언급한 메시지들은 모두 사용할수 있습니다.

    그리고 프로그램이 복잡해지고 컨트롤이 다양해짐에 따라, 이미 많은 메시지가 있음에도 불구하고,

    메시지 추가에 대한 요구 사항이 늘어나게 되었고 윈도우즈 시스템은 필요할때마다 WM_ 메시지를

    추가해서 문제를 해결하는데 한계가 있다는것 알고 통보 메시지에 대한 새로운 표준을 정했고

    그것이 WM_NOTIFY 메시지로 구체화 되었습니다.  WM_NOTIFY 메시지의 형식은 아래와 같습니다.

 

 

    WM_NOTIFY 메시지의 LPARAM에 사용된 구조체의 형식은 아래와 같습니다.

 

    typedef struct tagNMHDR {

        HWND hwndFrom;

        UINT idFrom;

        UINT code;

    } NMHDR;

 

    NMHDR 구조체를 보시면 아시겠지만 항목이 너무 간단해서 다양한 정보를 수용할만한 구조가

    아닙니다.

    그렇다면 어떻게 컨트롤의 다양한 정보를 이 구조체를 이용해서 전달할수 있을까요?

    그건 LPARAM에 전달되는 정보의 형식을 살펴보면 의문이 풀립니다.

    LPARAM에 저장된 정보는 NMHDR 구조체의 주소입니다. 즉, 구조체의 크기가 한정되지 않다는

    뜻입니다. WM_NOTIFY 메시지는 전달되는 정보의 시작형식을 NMHDR 구조체 형식으로 정한것이지

    꼭 저 구조체를 사용하라는 뜻이 아닙니다.

 

    예를 들어, 자신이 컨트롤을 하나 만들었고 해당 컨트롤이 x, y 좌표정보를 부모에게 통보해야 한다면

    아래와 같이 구조체를 정의하고 사용하시면 됩니다.

 

    typedef struct tagMyNotifyData {

        HWND hwndFrom;    // 변경불가

        UINT idFrom;           // 변경불가

        UINT code;              // 변경불가

        // 자신이 추가하고 싶은 정보를 추가하면 됩니다.

        int x_pos;

        int y_pos;

    } MyNotifyData;

 

   위 구조체를 아래와 같이 선언해도 마찬가지 입니다.

 

    typedef struct tagMyNotifyData {

        NMHDR hdr;   // 변경불가

        // 자신이 추가하고 싶은 정보를 추가하면 됩니다.

        int x_pos;

        int y_pos;

    } MyNotifyData;

 

    WM_NOTIFY 관련 처리기는 LPARAM으로 전달되는 메시지의 시작형식만 NMHDR 구조를 만족하면

    아무런 문제 없이 동작하도록 구성되어있기 때문에, 자신이 정의하는 구조체의 시작 부분만 정확하게

    NMHDR 구조체 형식으로 구성해주시면 됩니다.

 

    대부분의 통보 메시지를 사용하는 컨트롤들은 자신의 정보를 전달하기 위해서 NMHDR 구조체보다

    더 복잡한 형태의 구조체를 사용할 것입니다.  ( 툴팁 컨트롤이 통보하는 메시지 중에 TTN_SHOW,

    TTN_POP 같은 메시지는 특별한 추가 정보가 없어서 NMHDR 구조를 그대로 사용하고 있습니다. )

 

    WM_NOTIFY 메시지는 통보 메시지의 대표 메시지이고, 자신이 전달하고 싶은 통보 메시지 코드는

    NMHDR 구조체의 code 항목에 저장해서 전달하면 된다. 따라서 받는 쪽에서는 해당 통보 메시지가

    어떤 구조체인지는 모르지만 구조체의 앞부분이 NMHDR 구조체와 형식이 같기 때문에 일단 해당

    주소를 NMHDR 구조체로 형변환(casting)을 한 후에 code 항목을 체크하여 어떤 통보 메시지인지를

    구분하고 다시 정확한 구조체로 형변환(casting)을 해서 사용하게 됩니다.

 

    예를들어, 자신이 위에서 이야기한 MyNotifyData 구조체를 사용했다고 가정하고 code에 MN_DATA

    라는 메시지 코드를 넣어서 부모 윈도우로 WM_NOTIFY 형식으로 전달했다면 받는 쪽에서는 아래와

    같이 처리할 것입니다.

 

    // 통보 메시지는 일괄적으로 NM_NOTIFY 로 전달되기 때문에 어떤 통보메시지 인지를 확인해야

    // 한다.

    // 따라서 LPARAM 에 전달된 주소를 NMHDR로 형변환해서 code값을 확인해야 한다.

    NMHDR *p_hdr = (NMHDR *)lParam;

    if( p_hdr->code == MN_DATA ){

        // 전달된 통보 메시지가 MN_DATA인 경우       

        MyNotifyData *p_my_data =  (MyNotifyData *)lParam;

        // p_my_data 를 사용...

    } else {

        // 다른 통보 메시지인지를 체크

    }

 

 

3. WM_NOTIFY를 사용하는 컨트롤에서 공통적으로 사용되는 메시지들에 대하여..

통보 메시지 코드

통보 내용

  NM_CLICK  사용자가  해당 컨트롤에 마우스 왼쪽 버튼을 클릭한 경우 발생
  NM_DBLCLK  사용자가  해당 컨트롤에 마우스 왼쪽 버튼을 더블 클릭한 경우 발생
  NM_RCLICK  사용자가  해당 컨트롤에 마우스 오른쪽 버튼을 클릭한 경우 발생
  NM_RDBLCLK  사용자가  해당 컨트롤에 마우스 오른쪽 버튼을 더블 클릭한 경우 발생
  NM_RETURN
  해당 컨트롤이 포커스를 가지고 있는 상태에서 ENTER 키를 누른
  경우 발생
  NM_SETFOCUS  해당 컨트롤이 입력 포커스를 획득한 경우 발생
  NM_KILLFOCUS  해당 컨트롤이 입력 포커스를 잃어버린 경우 발생
  NM_OUTOFMEMORY    해당 컨트롤이 메모리 부족으로 명령 수행에 실패한 경우 발생

 

 

[ 2 편에서 계속하겠습니다. ]

저작자표시 (새창열림)

'mfc & winAPI' 카테고리의 다른 글

마우스 이벤트 중복 클릭 방지 함수  (0) 2017.05.29
[강좌/메시지] WM_NOTIFY 메시지에 대해서...(ON_NOTIFY) - 2편  (0) 2015.08.19
#import msado15.dll이 소스에서 OS등에 따라 컴파일이 되지 않을 때  (0) 2014.04.11
BOOL PreTranslateMessage(MSG* pMsg)  (0) 2014.03.21
분할 윈도우 중 하나에 접근하는 방법  (0) 2014.02.10
Posted by hyeonk

#import msado15.dll이 소스에서 OS등에 따라 컴파일이 되지 않을 때

mfc & winAPI 2014. 4. 11. 14:14

[문제]


컴퓨터에서 실행 중인 Windows 7 SP1 이나 Windows Server 2008 R2 SP1 나 설치 하는 kb983246가 다시 컴파일하십시오 다음 ADO 응용 프로그램 하위 수준 운영 체제에서 실행 되지 않습니다.


http://support.microsoft.com/kb/2517589



[해결책]


#1. Windows 7 의 SP1 을 올리지 않는다. (권장 안함)

-> 현재 시스템 상 자동 업데이트 되고 있고, 개발을 위해서 업그레이드를 미루는 것은 문제가 있을 듯 합니다.


#2. 개인 PC의 ADO 버전을 강제로 내린다 (권장 안함 )

  -> 문제가 있고 추후 상위 버전의 개발을 위해서도 바람직 하지 않습니다. 


#3. ADO 버전을 고정 시킨다 (권장)

-> 현재 사용되는 msado15.dll 버전을 사용하지 않고 아래의 버전중에 하나를 사용한다. 

  - Vista 이상의 환경에서의 컴파일 : #import msado60.tlb (권장)

  - XP 이상의 환경에서의 컴파일 : #import msado28.tlb (옵션)



AS-IS

#import "C:\Program Files\Common Files\System\ado\msado15.dll" rename("EOF", "adoEOF")


TO-BE

#import "C:\Program Files\Common Files\System\ado\msado60.tlb" rename("EOF", "adoEOF")



[기타]

#. 해결책 

http://support.microsoft.com/kb/2640696


#. ADO 버전 

http://msdn.microsoft.com/ko-kr/library/windows/desktop/ms676506(v=vs.85).aspx


출처: http://cdecl.tistory.com/285

저작자표시 (새창열림)

'mfc & winAPI' 카테고리의 다른 글

[강좌/메시지] WM_NOTIFY 메시지에 대해서...(ON_NOTIFY) - 2편  (0) 2015.08.19
[강좌/메시지] WM_NOTIFY 메시지에 대해서...(ON_NOTIFY) - 1편  (0) 2015.08.19
BOOL PreTranslateMessage(MSG* pMsg)  (0) 2014.03.21
분할 윈도우 중 하나에 접근하는 방법  (0) 2014.02.10
[MFC] SendMessage  (0) 2014.01.07
Posted by hyeonk

BOOL PreTranslateMessage(MSG* pMsg)

mfc & winAPI 2014. 3. 21. 10:08

- 키 입력 처리를 할 수 있는 함수.

- 보통 엔터키나 ESC키를 눌렀을때 자동으로 OnOK()나 OnCancel()로 처리 되지만,

  그전에 키 입력메세지를 사용자 정의로 처리하고 싶으면 이 함수를 쓰면 된다.


[-] Collapse

BOOL PreTranslateMessage(MSG* pMsg)
{
    if( pMsg->message == WM_KEYDOWN)    //키 다운 메세지
    {
        if( pMsg->wParam == VK_ESCAPE || pMsg->wParam == VK_RETURN)    //ESC or Enter 키
                         return FALSE;                    //처리 부분
    }
    return CDialog::PreTranslateMessage(pMsg);
}


키 다운을 처리하려면 보통 위와 같은 방법으로 처리한다.

해당되는 키 값을 조건문에 넣고, 해야할 처리를 코딩 해주면 된다.


* 부모 다이얼로그에서 탭컨트롤을 이용한 자식 다이얼로그의 키입력 처리를 할때도 사용하면 된다.

부모 다이얼로그에서 탭컨트롤에 있는 자식 다이얼로그가 3개가 있다면,

해당 자식 다이얼로그에 포커스를 두고 엔터키나 ESC를 누르면, OnOk()나 OnCancel()로 메세지가 가버려서, 

다이얼로그가 사라질 수가 있다. 그러면 탭 이동을 한뒤 다시 탭을 클릭해야 해당 다이얼로그가 나타나게 된다.


자, 그러면 아래와 같이 자식 다이얼로그 클래스에서 PreTranslateMessage()를 재정의 한 후

[-] Collapse

BOOL PreTranslateMessage(MSG* pMsg)
{
      return FALSE; //처리 부분
// return CDialog::PreTranslateMessage(pMsg);
}

return FALSE; 로 처리를 해주면 된다.


키 입력 메세지가 자식 다이얼로그에서 최종적으로 처리되기 이전에, PreTranslateMessage() 함수에서 처리를 할 수 있기 때문에

PreTranslateMessage()는 return TRUE; 가 되면, 더이상 메세지 처리가 되지 않고, 거기서 메세지 처리가 종결된다.

반면에 return FALSE; 가 되면, 자식 다이얼로그에서는 더이상 메세지 처리가 되지않고

부모 다이얼로그로 메세지가 넘어간다.

그러면, 부모 다이얼로그의 PreTranslateMessage() 함수나, OnOk(), OnCancel() 함수로 흐름이 이어지게 되어

부모 다이얼로그의 키 입력 처리대로 흘러간다.


부모 다이얼로그에서 탭컨트롤에 자식 다이얼로그를 붙일 경우,

이렇게 처리를 해주면, 자식 다이얼로그에서 ESC나 엔터키를 눌러도 자식 다이얼로그가 사라지거나 하는것을 방지하고, 부모 다이얼로그의 루틴대로 처리할 수 있다.

저작자표시 (새창열림)

'mfc & winAPI' 카테고리의 다른 글

[강좌/메시지] WM_NOTIFY 메시지에 대해서...(ON_NOTIFY) - 1편  (0) 2015.08.19
#import msado15.dll이 소스에서 OS등에 따라 컴파일이 되지 않을 때  (0) 2014.04.11
분할 윈도우 중 하나에 접근하는 방법  (0) 2014.02.10
[MFC] SendMessage  (0) 2014.01.07
어플리케이션(MFC)에서 스레드 사용 및 주의사항 (필독!!)  (0) 2014.01.07
Posted by hyeonk

분할 윈도우 중 하나에 접근하는 방법

mfc & winAPI 2014. 2. 10. 09:38

- 스플리터로 분할 윈도우를 구현했다면, 스플리터 객체를 이용해 해당 뷰의 포인터를 얻을 수 있다.

CRightListView *pView = (CRightListView*)((CMainFrame*)AfxGetMainWnd())->m_wndSplitHor.GetPane(0, 1);


- 그리고 해당 뷰 포인터를 이용해 컨트롤 객체를 핸들링 하면 된다.

CString strItem = CLeftTreeCtrl::GetItemText(pNMTreeView->itemNew.hItem);

pView->m_RightListCtrl.SetItemText(1, 0, strItem);

저작자표시 (새창열림)

'mfc & winAPI' 카테고리의 다른 글

#import msado15.dll이 소스에서 OS등에 따라 컴파일이 되지 않을 때  (0) 2014.04.11
BOOL PreTranslateMessage(MSG* pMsg)  (0) 2014.03.21
[MFC] SendMessage  (0) 2014.01.07
어플리케이션(MFC)에서 스레드 사용 및 주의사항 (필독!!)  (0) 2014.01.07
[MFC] MFC 팁 모음  (0) 2013.06.28
Posted by hyeonk

[MFC] SendMessage

mfc & winAPI 2014. 1. 7. 16:28

클래스간 데이터 전달을 하는 방법이 무엇이 있을까.


1. 전역변수
2. 헤더 include 후 변수 접근
3. SendMessage

SendMessage를 이용하면 클래스간 데이터 전달이 용이함을 알고, 사용해보았다(몇번의 삽질과 함께...)

?
1
2
3
4
5
6
7
8
9
10
11
12
LRESULT SendMessage(
    UINT message,
    WPARAM wParam = 0,
    LPARAM lParam = 0
) throw();
 
static LRESULT SendMessage(
    HWND hWnd, 
    UINT message,       // 메시지 이름
    WPARAM wParam,  // 정수형 포인터 전달인자
    LPARAM lParam       // 실수형 포인터 전달인자
) throw();

주로 static을 쓰게 될텐데...

선언해주어야 하는 파트는 3파트.

1. 메시지 등록
- '이런 메시지를 쓰겠습니다.' 하는 부분 
        - 메시지 등록은 이 메시지를 받을 곳 메시지 맵에 등록을 한다. 던져줬는데 받는놈이 뭔지 모르면 그건 스팸일테니... 매시지 맵의 역할에 대해서는 따로 공부..
 
        ex) BEGIN_MESSAGE_MAP(CsendMessageDlg, CDialog)
ON_MESSAGE(메시지 구별자, 처리함수)
      END_MESSAGE_MAP()
 
2. 처리함수 정의
- 위의 처리함수를 정의하는 부분.
 
3. 메시지 전달
- 메시지를 전달하는 부분
ex) ::SendMessage(전달 받을 곳의 핸들(받는사람) , 메시지 구별자, 전달인자1, 전달인자2);
 


흐름

SendMessage - 받는 핸들 찾음 - 처리 함수 호출



#sendMessageDlg.cpp // 부모 Dialog
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
BEGIN_MESSAGE_MAP(CsendMessageDlg, CDialog)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    //}}AFX_MSG_MAP
    ON_BN_CLICKED(IDOK, &CsendMessageDlg::OnBnClickedOk)
    ON_BN_CLICKED(IDC_BUTTON1, &CsendMessageDlg::OnBnClickedButton1)
    ON_MESSAGE(UM_TEST_SENDMESSAGE, &CsendMessageDlg::sets) // 1. 메시지 등록
END_MESSAGE_MAP()
 
LRESULT CsendMessageDlg::sets(WPARAM wParam, LPARAM lParam) // 2. 처리함수 정의
{
    CString *data = (CString*)lParam;
        // 이렇게 받아옴. 왜냐하면 lParam 은 포인터니까!! CString을 넘긴 주소를 가리키고 있다.
    ::MessageBox(NULL, _T("asdf"), (LPCWSTR)data, MB_OK); // 이건 그냥 확인용
}


#Modaless.h
?
1
#define UM_TEST_SENDMESSAGE WM_USER +1  // 메시지 구별자 등록


#Modaless.cpp
// 자식 Dialog
?
1
2
3
4
5
6
7
8
9
10
11
BOOL CModaless::OnInitDialog()
{
    CDialog::OnInitDialog();
    CString *str = new CString("asdf");
    ::SendMessage(((CSendMessageDlg*)GetParent())->GetSafeHwnd(), UM_TEST_SENDMESSAGE, 0, (LPARAM)str);
        // ((CSendMessageDlg*)GetParent())->GetSafeHwnd() : 상위 Dialog의 핸들을 가져옴
        // 만약 하위 Dialog에게 보내려면 하위 Dialog의 객체에 sendMessage를 던져주면된다.
        // 그땐 주소(hWnd가 필요없다. :D)
    // 3. 메시지 전달
    return TRUE;
}


여기에서 보면 가장 중요한 부분이 SendMessage 부분인것 같다.

첫번째 전달인자는 받을 클래스의 핸들러가 들어간다. 즉, 받는사람 주소인 셈.
나는 부모 다이얼로그에 전달하기위해서 getparent를 이용해서 핸들러를 받아왔다.

전달인자는 WPARAM 과 LPARAM.
둘다 dword 형으로
WPARAM은 UINT, LPARAM은 LONG 형으로 각각 정수형, 실수형 포인터이다.

끗.

PS. 위 내용은 단순히 라이브러리를 어떻게 쓰는지에 대한 방법을 적은 것이다.
후에 꼭, SendMessage와 PostMessage에 대한 이해를 하는것이 중요하다.

라이브러리를 쓰는 개발자보다는 라이브러리를 만들 수 있는 개발자가 되자.

출처: http://hatti.tistory.com/entry/MFC-SendMessage

저작자표시 (새창열림)

'mfc & winAPI' 카테고리의 다른 글

BOOL PreTranslateMessage(MSG* pMsg)  (0) 2014.03.21
분할 윈도우 중 하나에 접근하는 방법  (0) 2014.02.10
어플리케이션(MFC)에서 스레드 사용 및 주의사항 (필독!!)  (0) 2014.01.07
[MFC] MFC 팁 모음  (0) 2013.06.28
Win32Api에서 x64(64비트) Application을 개발할때의 주의점들  (0) 2013.04.15
Posted by hyeonk

어플리케이션(MFC)에서 스레드 사용 및 주의사항 (필독!!)

mfc & winAPI 2014. 1. 7. 16:26

1. 크기(size) 및 효율성(performance)의 이유로 MFC 객체(Object)는 스레드에 안전한 구조가 아니다.

2. MFC 객체에 접근(Access)하기 위해서는 CWinThread 객체를 사용한 스레드여야 한다. (User-Interface Thread, Worker Thread)
  - User-Interface Thread와 Worker Thread의 차이 : User-Interface Thread는 스레드 자체의 메시지 큐를 가지며 일반적으로 UI를 포함한다.

3. 일반적인 규칙으로 MFC 객체는 그것을 생성한 스레드에서만 접근할 수 있다. MFC는 윈도우 핸들과 윈도우 객체를 연결하는 
    맵(Windows Handle Maps)을 가지는데 이것은 스레드의 로컬 영역에 저장되기 때문이다.
  - Worker Thread에서 CDocument의 UpdateAllViews 나 CView의 UpdateWindow 등을 호출해도 뷰는 업데이트 되지 않는다.
  - Worker Thread에서 AfxGetMainWnd 등을 호출하면 NULL이 반환된다.
  - Worker Thread에서 CDialog의 UpdateData 등을 호출하면 ASSERT 에러가 난다.
  - Worker Thread에서 UI를 직접 접근할 경우 Dead lock에 빠질 수 있다.

4. SendMessage와 PostMessage의 차이를알자.
  - SendMessage를 호출하면 윈도우의 메시지 프로시저를 바로 호출해서 결과를 리턴 받는다.
  - PostMessage를 호출하면 메시지가 시스템 메시지 큐에 보내지고 호출한 함수는 바로 리턴이 된다.
    시스템은 해당 윈도우 스레드의 메시지 큐에 메시지를 보내고 메시지가 처리된다.
 - 따라서 Worker Thread에서 SendMessage를 호출하면 Worker Thread에서 메시지 핸들러를 호출하게 되는것이고
    PostMessage를 호출하면 메인 Thread에서 메시지 핸들러를 호출하게 되는것이다.

[MFC 어플리케이션에서 Worker Thread를 사용할 경우 지켜야 할 규칙]
1. UI에 대한 접근은 UI를 생성한 클래스에서만 한다. (Worker Thread에서 UI 접근 함수를 직접 호출하지 않는다.)

2. 메인 스레드와 서브 스레드(Worker Thread)에서 동시에 접근하는 Data는 최대한 줄인다.

3. 서브 스레드(Worker Thread)에서 처리한 작업은 사용자 메시지를 만든 후 PostMessage로 보내서 메인 스레드에서
   처리할 수 있도록 한다.


출처: http://blog.naver.com/ultimidou/130096322389

[출처] 어플리케이션(MFC)에서 스레드 사용 및 주의사항 (필독!!)|작성자 울티미도우


[출처] 어플리케이션(MFC)에서 스레드 사용 및 주의사항 (필독!!)|작성자 울티미도우

저작자표시 (새창열림)

'mfc & winAPI' 카테고리의 다른 글

분할 윈도우 중 하나에 접근하는 방법  (0) 2014.02.10
[MFC] SendMessage  (0) 2014.01.07
[MFC] MFC 팁 모음  (0) 2013.06.28
Win32Api에서 x64(64비트) Application을 개발할때의 주의점들  (0) 2013.04.15
CString 형변환 Programming  (0) 2013.02.13
Posted by hyeonk

[MFC] MFC 팁 모음

mfc & winAPI 2013. 6. 28. 15:40

1. DC얻기

CClientDC dc(this);


2. Client 영역 구하기

GetClientRect(&rect);

WM_SIZE 메시지발생후 cx,cy 사용


3. 문자열 사각형안에 그리기

pDC->DrawText(문자열,사각형,Style);

Style: DT_BOTTOM - 문자열을 사각형 맨아래줄에배열 반드시 DT_SINGLELINE과 함께사용

DT_CENTER - 문자열을 가로중앙에 배치

DT_VCENTER - 문자열을 세로중앙에 배치

DT_LEFT,RIGHT - 문자열을 좌,우로 배치

DT_SINGLELINE - 문자열을 한줄로만 쓴다


4. Brush 사용법

CBrush brushname(RGB(red,green,blue)); //브러쉬 생성

CBrush *oldBrush=pDC->SelectObject(&brushname); //이전Brush 저장, 새로운 Brush 선택

pDC->SelectObject(oldBrush); //원래의 브러쉬로 반환


5. Pen사용법

CPen pen(Pen Style,RGB(red,green,blue)); //브러쉬생성

//Style: PS_SOLID,PS_DASH,PS_DOT,PS_DASHDOT,PS_GEOMETRIC,PS_COSMETRIC - 펜종류

PS_ENDCAP_ROUND,PS_ENDCAP_SQUARE - 펜끝을 둥글게,각지게 설정

CPen *oldPen=pDC->SelectObject(&pen); //이전Pen저장, 새로운 Pen설정

pDC->SelectObject(oldPen); //펜반환


6. 화면다시그리기

View Class에서 - Invalidate(TRUE) : 화면을 지우고다시그린다

Invalidate(FALSE) : 화면을 덮어씌운다

UpdateAllViews(NULL); // Doc Class에서 View 의 OnDraw 호출

RedrawWindow();


7. 메시지,함수 수동으로 넣기 (EX)버튼클릭함수넣기

헤더파일의 AFX_MSG_MAP 부분에 함수를 정의

EX) afx_msg void funcName();

.cpp파일의 AFX_MSG 부분에 메시지를 추가한다

EX) ON_BN_CLICKED(ID_NAME,funcName)...

ID 등록: View 메뉴의 Resource Symbol 에 들어가서 메뉴 ID 를 등록해준다..

.cpp파일의 맨아래에서 함수를 정의한다

EX) void CClass::funcName() { ... }


8. 마우스커서 바꾸기

리소스탭에서 커서를 그리고 저장한뒤 ID값은 준다음

SetCapture(); //커서의입력을 클라이언트영역을 벗어나더라도 받아낸다

SetCursor(AfxGetApp()->LoadCursor(nIDResource));

//APP클래스의 LoadCursor View의 SetCursor 사용

ReleaseCapture(); //SetCursor()상태를 해제한다


9. 색상표 사용하기

CColorDialog dlg;

if(dlg.DoModal()==IDOK) //Dialog 를 띄운후 OK버튼을누르면 실행할부분

MemberFunc: GetColor() //선택된 색상을 받아온다 return 형은 COLORREF 형


10. 팝업메뉴 만들기

CMenu menu; //메뉴 객체생성

CMenu *pmenu; //메뉴 포인터생성

menu.LoadMenu(IDR_MAINFRAME); //메뉴를 불러온다

pmenu=menu.GetSubMenu(3); //메뉴의 3번째 메뉴를 가져온다

menu.CheckMenuItem(ID_MENU,m_kind==ID_MENU ? MF_CHECKED : MF_UNCHECKED);

//메뉴 체크하기 (메뉴 ID, ID 체크조건)

pmenu->TrackPopupMenu(TPM_LEFTALIGN,point.x,point.y,this) //(TMP_Style,x좌표,y좌표,hWnd) 메뉴 띄우기


*주의사항*

[안내]태그제한으로등록되지않습니다-OnContextMenu(CWnd* pWnd, CPoint point) //여기서 point 는 스크린 기준이고,

OnRButtonDown(UINT nFlags, CPoint point) //여기서 point 는 클라이언트 기준이다!


11. 클라이언트 포인터를 스크린 포인터로 변경

ClientToScreen(&point);


12. 그림판기능

if(m_flag==FALSE) return; //m_falg=그리기 기능 참,거짓설정 그리기 아니면 빠져나간다

CClientDC dc(this);

CPen myPen(PS_SOLID,m_width,m_color);

CPen *pOldPen=dc.SelectObject(&myPen);

switch(m_shape)

{

case ID_FREELINE: //자유선그리기

dc.MoveTo!!!!(m_oldpt.x,m_oldpt.y); //지난포인터부터

dc.LineTo(point.x,point.y); //새포인터까지 그린다

break;

case ID_RECT: //사각형그리기

dc.SetROP2(R2_NOTXORPEN);

dc.Rectangle(m_spt.x,m_spt.y,m_oldpt.x,m_oldpt.y); //지워지는 효과

dc.Rectangle(m_spt.x,m_spt.y,point.x,point.y); //그려지는 효과

break;

case ID_ELLIPSE: //원그리기

dc.SetROP2(R2_NOTXORPEN);

dc.Ellipse(m_spt.x,m_spt.y,m_oldpt.x,m_oldpt.y); //지워지는 효과

dc.Ellipse(m_spt.x,m_spt.y,point.x,point.y); //그려지는 효과

break;

case ID_LINE: //선그리기

dc.SetROP2(R2_NOTXORPEN);

dc.MoveTo!!!!(m_spt.x,m_spt.y); //시작점부터

dc.LineTo(m_oldpt.x,m_oldpt.y); //지난점까지 그은선을 지운다

dc.MoveTo!!!!(m_spt.x,m_spt.y); //시작점부터

dc.LineTo(point.x,point.y); //새로운점까지 그린다

break;

}

m_oldpt=point; //바로이전값 보관

dc.SelectObject(pOldPen); //펜 반환


13. MessageBox

AfxMessageBox() -> 전역함수를 이용하영 메세지 박스를 출력한다. //어디서든지 사용할수 잇다

int CWnd::MessageBox("메세지","창제목","아이콘|버튼(상수값)"); //View클래스에서 사용한다

아이콘 상수값 MB_IC[안내]태그제한으로등록되지않습니다-xxONERROR, MB_ICONWARNING, MB_ICONQUESTION,MB_ICONINFOMATION

MB_SYSTEMMODAL //시스템모달 대화창 닫기전에 다른작업 못함

MB_APPLMODAL //응용모달

버튼 상수값 MB_OK, MB_OKCANCEL, MB_YESNO


14. OS 컨트롤

ExitWindowEx(EWX_SHUTDOWN,NULL); //Shut Down

ExitWindowsEx(EWX_FORCE,0); //강제종료

ExitWindowsEx(EWX_LOGOFF,0); //로그오프

ExitWindowsEx(EWX_POWEROFF,0); //Shut Down -> Turn Off

ExitWindowsEx(EWX_REBOOT); //Shut Down -> Reboot


15. DialogBox 메시지 교환

UpdateData(FALSE); // 컨트롤에 멤버변수의 내용을 표시해준다

UpdateData(TRUE); // 컨트롤 내용을 다이얼로그 클래스의 멤버변수로 저장


16. 자료변환

atoi,itoa - int <=> ASCII(char) 변환

str.Format(" %d %d",x,y); // int형을 문자열로 변환

atol,ltoa - ASCII <=> long 변환

atof - ACSII => float 변환

fcvt,gcvt - 실수를 text로 변환

LPtoDP, DPtoLP - 장치좌표 <=> 논리좌표 변환


17. CEdit Class 사용하기

CEdit e_str.SetSel(int StartChae, int EndChar); //처음문자부터 마지막까지 블록 지정

CEdit e_str.GetSel(int SChar,int EChar); //블럭 지정한 처음문자와 마지막문자 받기

CString str=m_str.Mid(SChar,EChar-SChar); //블럭지정한 부분을 가져온다


18. 컨트롤과 자료교환

SetDlgItemText(컨트롤 ID,문자열) //컨트롤에 문자열을 넣는다

GetDlgItemText(컨트롤 ID,문자열) //컨트롤의 내용을 문자열에 넣는다

GetDlgItem(컨트롤 ID); //컨트롤의 주소를 가져온다


19. 상태바조작

CMainFrame 생성자 위에

static UINT indicators[] = //이안에 새로운 ID를 넣고 그 ID의 갱신핸들러를 만든다음 코딩

pCmdUI->SetText("표시할내용“);


20. 수동으로 Bitmap 컨트롤 사용하기

CStatic bitmap; //bitmap 컨트롤변수

bitmap.SetBitmap(CBitmap m_bitmap); //컨트롤에 비트맵지정

GetDlgItem(IDC_BITMAP)->ShowWindow(SW_SHOW,HIDE); // 그림을 보이거나 숨긴다.

21. 응용프로그램 실행하기

WinExec("프로그램경로“,SW_SHOW,HIDE); //응용프로그램실행,경로는 \\로 구분한다


22. Bitmap 사용하기

CBitmap bitmap.LoadBitmap(IDC_BITMAP); //비트맵객체에 비트맵지정

CDC memDC; //그림그릴 메모리DC생성

MemDC.CreateCompatibleDC(pDC); //화면 DC와 메모리 DC 호환 생성

CBitmap *pOldBitmap=MemDC.SelectObject(&m_bitmap); //메모리에 그림을그린다.

pDC->BitBlt(int x, int y,int Width, int Height, CDC* pSrcDC, int xSrc, int ySrc, DWORD dwRop);

//BitBlt(그림x좌표,그림y좌표,그림넓이,그림높이,그림그려진메모리DC,그림시작x좌표,그림시작y좌표,스타일);

pDC->StretchBlt( int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop )

//StretchBlt(그림x좌표,그림y좌표,그림넓이,그림높이,그림그려진메모리DC,그림x좌표,그림y좌표,메모리그림넓이,메모리그림높이,스타일);

MemDC.SelectObject(pOldBitmap); // 메모리DC반환


23. Font 바꾸기

CFontDialog dlg; //폰트다이얼로그 생성

LOGFONT m_logFont; //폰트받을변수선언

if(dlg.DoModal()==IDOK) //폰트다이얼로그표시

{dlg.GetCurrentFont(&m_logFont)} //선택된 폰트받기

OnDraw()

CFont newFont,*pOldFont; //폰트 객체 만들기

newFont.CreateFontIndirect(&m_logFont); //폰트 생성

pOldFont=(CFont *)pDC->SelectObject(&newFont); //폰트 선택

OnCreate()

CClientDC dc(this); //DC 생성

CFont *pFont=dc.GetCurrentFont(); //클라이언트 영역의 폰트를

pFont->GetLogFont(&m_logFont); //로그폰트 멤버값으로 지정


24. Font 만들기

LOGFONT logfont; //폰트를 만든다

logfont.lfHeight=50; //문자열 높이

logfont.lfWidth=0; //너비

logfont.lfEscapement=0; //문자열기울기

logfont.lfOrientation=0; //문자개별각도

logfont.lfWeight=FW_NORMAL; //굵기

logfont.lfItalic=TRUE; //이탤릭

logfont.lfUnderline=TRUE; //밑줄

logfont.lfStrikeOut=FALSE; //취소선

logfont.lfCharSet=HANGUL_CHARSET; //필수

logfont.lfOutPrecision=OUT_DEFAULT_PRECIS;

logfont.lfClipPrecision=CLIP_DEFAULT_PRECIS; //가변폭폰트 고정폭폰트

logfont.lfPitchAndFamily=DEFAULT_PITCH|FF_SWISS; //글꼴이름

strcpy(logfont.lfFaceName,"궁서체");

CClientDC dc(this);

CFont newFont; //폰트객체생성

newFont.CreateFontIndirect(&logfont); //폰트지정

CFont *pOldFont=dc.SelectObject(&newFont); //폰트선택

dc.TextOut(100,100,m_text);

dc.SelectObject(pOldFont); //폰트반환


25. Font 만들기 2

CFont newFont;

newFont.CreateFont( int nHeight, int nWidth, int nEscapement, int nOrientation, int nWeight, BYTE bItalic, BYTE bUnderline, BYTE cStrikeOut, BYTE nCharSet, BYTE nOutPrecision, BYTE nClipPrecision, BYTE nQuality, BYTE nPitchAndFamily, LPCTSTR lpszFacename );

CFont *pOldFont=dc.SelectObject(&newFont);


26. ComboBox 사용하기

CComboBox combo; //콤보박스 선언

combo.Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID );

//Style - WS_CHILD|WS_VISIBLE

int n=combo.GetCurSel(); //선택된 아이템의 index를 가져온다

combo.AddString("문자열“); //문자열을 추가한다

combo.GetLBText(n,str); //n번째 아이템을 str에 저장


27. Spin 사용하기

Spin은 바로앞의 Tab Order에 따라 붙는다

m_spinr.SetRange(1900,3000); //스핀 범위 지정

m_spinr.SetPos(m_nYear); //스핀 위치 지정


28. CTime사용하기

CTime time; //시간객체생성

time=CTime::GetCurrentTime(); //현재시간을 저장

time.GetYear(),time.GetMonth();,time.GetDay(),time.GetHour(),time.GetMinute(),time.GetSecond()


29. CListBox 메소드

AddString("문자열"); //리스트에 문자열 추가

DeleteString(index); //리스트에서 항목 삭제

GetCount() //전체 항목 갯수를 얻는다.

GetSelcount() //선택된 항목 갯수 리턴

GetSel() //선택된 것인지 아닌지를 리턴한다 -> 양수 = TRUE , 음수 => FALSE

GetText(int index,문자열변수) //index 번째 문자열을 문자열 변수에 넣는다

FindStringExact(문자열) //지정 문자열의 index 값 리턴 -> 없으면 리턴값 LB_ERR 반환

FindString("a") //"a"로 시작하는 항목을 모두 찾는다.

ResetCountent() //모든 내용을 지운다.


30. 파일입출력

프로젝트생성시 Step4 => Advanced => 저장파일확장자지정

.h 파일에 DECLARE_SERIAL(CSawon) //이 클래스를 저장,로드가능한 클래스로 쓰겟다는 선언

.cpp 파일에 IMPLEMENT_SERIAL(CSawon,CObject,1) //이거를 해야 저장이 가능하다

void CFileioDoc::Serialize(CArchive& ar)

if (ar.IsStoring()) //저장하기

{ar<

else //열기

{ar>>m_shape; //불러올걸 쓴다. 읽을때도순서대로읽어야한다}


31. MicroSoft FlexGrid 사용하기!

CMSFlexGrid m_Grid; //FlexGrid 컨트롤 변수

CString strTitle[]={"고객코드","고객성명","고객포인트","신장","몸무게","고객등급","BMT지수","판정결과"};

// Grid 의 제목에 넣을문자배열

int Width[]={900,900,1100,800,800,900,1000,900};

// Grid 의 열넓이 지정할 배열

m_Grid.SetRows(m_cnt+2); //전체행수 지정

m_Grid.SetCols(8); //전체열수 지정

m_Grid.Clear(); //지우기

m_Grid.SetFixedCols(0); //고정열은 없다.

m_Grid.SetRow(0); // 행선택

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

{

m_Grid.SetColWidth(i,Width[i]); //열 넓이 설정

m_Grid.SetCol(i); //열 선택

m_Grid.SetText(strTitle[i]); // 선택된행, 선택된열에 Text 를 넣는다

}


32. 4대 Class간 참조

//각각 헤더파일 include

#include "MainFrm.h" //메인프레임 헤더파일

#include "ClassDoc.h" //Doc클래스 헤더파일

#include "ClassView.h" //View를 include 할때는 반드시 Doc 헤더파일이 위에잇어야한다

#include "Class.h" //APP Class 의 헤더파일


void CClassView::OnMenuView() //뷰클래스

CClassApp *pApp=(CClassApp *)AfxGetApp(); //View -> App
CMainFrame *pMain=(CMainFrame *)AfxGetMainWnd(); //View -> MainFrm

CClassDoc *pDoc=(CClassDoc *)pMain->GetActiveDocument(); //View -> MainFrm -> Doc

CClassDoc *pDoc=(CClassDoc *)GetDocument(); //View -> Doc


//MainFrame 클래스

CClassView *pView=(CClassView *)GetActiveView(); //MainFrm -> View

CClassDoc *pDoc=(CClassDoc *)GetActiveDocument(); //MainFrm -> Doc

CClassApp *pApp=(CClassApp *)AfxGetApp(); //MainFrm -> App


//Doc 클래스

CClassApp *pApp=(CClassApp *)AfxGetApp(); //Doc -> App

CMainFrame *pMain=(CMainFrame *)AfxGetMainWnd(); //Doc -> MainFrm

CClassView *pView=(CClassView *)pMain->GetActiveView(); // Doc -> MainFrm -> View

CClassView *pView=(CClassView *)m_viewList.GetHead(); // Doc -> View


//App 클래스

CMainFrame *pMain=(CMainFrame *)AfxGetMainWnd(); //App -> MainFrm

CClassView *pView=(CClassView *)pMain->GetActiveView(); //App -> MainFrm -> View

CClassDoc *pDoc=(CClassDoc *)pMain->GetActiveDocument(); //App -> MainFrm -> Doc


33. ToolBar 추가하기

CMainFrame 으로 가서 멤버변수 추가

CToolBar m_wndToolBar1;

OnCreate 로 가서 다음 내용을 추가해준다 (위의 toolbar 부분을 복사하고 이름만 바꾸면 된다.3군데..)

if (!m_wndToolBar1.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP

| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||

!m_wndToolBar1.LoadToolBar(IDR_TOOLBAR1))

{

TRACE0("Failed to create toolbar\n");

return -1; // fail to create

}


그 함수내에서 //TODO 아래에 내용추가..역시..복사해서 이름만 바꾸면 된다.

m_wndToolBar1.EnableDocking(CBRS_ALIGN_TOP|CBRS_ALIGN_BOTTOM);

//DockControlBar(&m_wndToolBar1); <= 이부분 대신..

이거를 넣는다..

CRect toolRect; //툴바 영역을 얻을 사각형

this->RecalcLayout(); //현상태의 Client 영역을 구해서 저장한다

m_wndToolBar.GetWindowRect(&toolRect); //툴바영역을 저장한다

toolRect.left+=1; //사각형의 왼쪽을 1Pixel 줄인다

DockControlBar(&m_wndToolBar1,AFX_IDW_DOCKBAR_TOP,&toolRect); //ToolRect에 툴바를 붙인다

return 0;


34. ToolBar에 ComboBox붙이기

CComboBox m_combo; //객체생성

ID 등록 => view 메뉴 => resource symbol => new => ID_COMBO

oncreate 에 내용 추가 (콤보를 만들고 표시하는 내용)

m_wndToolBar.SetButtonInfo(10,IDC_COMBO,TBBS_SEPARATOR,150);

//툴바의 10번째버튼을 편집한다

CRect itemRect; //콤보를넣을 사각형을 만든다

m_wndToolBar.GetItemRect(10,&itemRect); //툴바의 10번째 버튼을 사각형에 넣는다
itemRect.left+=5; //앞여백

itemRect.right+=5; //뒤여백

itemRect.bottom+=100; //콤보가열릴 공간확보

m_combo.Create(WS_CHILD|WS_VISIBLE|CBS_DROPDOWN,itemRect,&m_wndToolBar,IDC_COMBO);

//콤보박스를 툴바에 붙여준다

m_combo.AddString("이름"); //내용추가

m_combo.SetCurSel(0); //셀 선택


35. Toolbar에 수동으로넣은 ComboBox 사용하기

afx_msg void [안내]태그제한으로등록되지않습니다-xxOnSelectCombo(); //원형

ON_CBN_SELCHANGE(IDC_COMBO,[안내]태그제한으로등록되지않습니다-xxOnSelectCombo) //메세지맵에 추가

CMainFrame *pMain=(CMainFrame *)GetParent(); //메인프레임 주소참조

CComboBox *pCom=(CComboBox *)(pMain->m_wndToolBar.GetDlgItem(IDC_COMBO));

//콤보박스의 주소를 가져온다, 접근할 때 메인프레임 -> 툴바 -> 콤보박스 의 순서로 가야한다

int n=pCom->GetCurSel(); //현재선택된 셀의 인덱스를 가져온다

if(n==CB_ERR) return; //선택된셀이 없으면 중지한다

CString str;

pMain->m_combo.GetLBText(n,str); //선택된셀의 Text를 가져온다


36. UPDATE_COMMAND 사용하기

pCmdUI->Enable(TRUE); //버튼 활성화

pCmdUI->SetText((bAdd)?"취소":"신규"); //버튼의 text 설정

pCmdUI->SetCheck(TRUE); //버튼 체크


37. 프로그램정보저장

CWinApp::GetProfileString(섹션명,항목명,기본값); // 함수를 사용한다. (문자열)

CWinApp::GetProfileInt(섹션명,항목명,기본값); //불러올때사용 (숫자)

CWinApp::WriteProfileString(섹션명,항목명,값); //저장할때 사용 (문자열)

CWinApp::WriteProfileInt(섹션명,항목명,값); //저장할때 사용 (숫자)

//불러올때 사용할함수

void CMainFrame::ActivateFrame(int nCmdShow) //프로그램 실행후 프레임생성될때 실행

//저장할 때 WM_DESTROY 메시지 사용


38. 컨트롤바 표시하기

CMainFrame *pMain=(CMainFrame *)GetParent(); //MainFrame 주소가져오기

pMain->ShowControlBar(&pMain->m_wndToolBar,bTool1,FALSE); //툴바를 bTool2 에따라 보이고 감춘다


39. Window 창크기,위치정보 저장하기

MainFrame 의 WM_DESTROY 에

WINDOWPLACEMENT w;

this->GetWindowPlacement(&w); //윈도우의 정보를 저장한다.

CString strRect;

strRect.Format("%04d,%04d,%04d,%04d", //04d 는 4자리 확보하고 남은건 0으로 채워라

w.rcNormalPosition.left,w.rcNormalPosition.top,

w.rcNormalPosition.right,w.rcNormalPosition.bottom); //윈도우의 위치,크기 확보..

BOOL bMax,bMin; //윈도우의 상태를 저장하기위한 변수

//w.falg 는 이전상태의 정보를 가지고 잇다!!

if(w.showCmd==SW_SHOWMINIMIZED) //최소화 상태

{

bMin=TRUE;

if(w.flags==0) //falg 값이 0 이면 이전 상태가 보통상태이다!!

bMax=FALSE;

else //이전상태가 최대화 상태

bMax=TRUE;

}

else

{

if(w.showCmd==SW_SHOWMAXIMIZED) //최대화상태

{

bMax=TRUE;

bMin=FALSE;

}

else //보통 상태

{

bMax=FALSE;

bMin=FALSE;

}

}

AfxGetApp()->WriteProfileString("WinStatus","Rect",strRect);

AfxGetApp()->WriteProfileInt("WinStatus","Max",bMax);

AfxGetApp()->WriteProfileInt("WinStatus","Min",bMin);


//읽어올차례..

ActivateFrame 함수로 가서

WINDOWPLACEMENT w; //윈도우의 상태를 저장하는 구조체..

BOOL bMax,bMin; //최대,최소상태를 저장할 변수

CString strRect; //창크기를 받아올 변수

strRect=AfxGetApp()->GetProfileString("WinStatus","Rect","0000,0000,0500,0700");

bMin=AfxGetApp()->GetProfileInt("WinStatus","Min",FALSE);

bMax=AfxGetApp()->GetProfileInt("WinStatus","Max",FALSE);

int a=atoi(strRect.Left(4)); //문자열을 int 로 바꿔준다.

int b=atoi(strRect.Mid(5,4)); //atoi 아스키 값을 int형으로 바꿔준다..

int c=atoi(strRect.Mid(10,4));

int d=atoi(strRect.Mid(15,4));

w.rcNormalPosition=CRect(a,b,c,d);

if(bMin)

{

w.showCmd=SW_SHOWMINIMIZED;

if(bMax)

{

w.flags=WPF_RESTORETOMAXIMIZED ;

}

else

{

w.flags=0;

}

}

else

{

if(bMax)

{

w.showCmd=SW_SHOWMAXIMIZED;

}

else

{

w.showCmd=SW_SHOWNORMAL;

}

}

this->SetWindowPlacement(&w); //설정된 값으로 윈도우를 그리게 한다..

//CFrameWnd::ActivateFrame(nCmdShow); //이건 반드시 주석처리한다..


40. progress Bar 쓰기


m_progress.SetRange(m_first,m_last); //Progress 범위설정하기

m_progress.SetStep(m_step); //Progress Step설정하기

//m_progress.StepIt(); //스텝만큼 움직이기

//또는 다음을 사용한다

for(int a=m_first;a<=m_last;a+=m_step) //a가 처음부터 끝까지

{

m_progress.SetPos(a); // 위치를 a에 맞춘다

Sleep(50); //천천히 움직이게한다

}


41. 파일대화상자 FileDialog 사용하기

void CConDlg1::OnFileopen() //파일열기 버튼

{

CFileDialog *fdlg; //파일대화상자 객체 생성 // 포인터로 만든다..

static char BASED_CODE szFilter[] = "Animate Video Files (*.avi)|*.avi|All Files (*.*)|*.*||";

//필터를 만들어 준다..이건 할줄 모름..

fdlg =new CFileDialog(TRUE, ".avi", NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,szFilter);

//대화상자 만들기..이렇게 해야댄다..

if(fdlg->DoModal()==IDOK) //이제..대화상자를 띠우고..

{ //OK 누르면 실행될 부분..

m_filename=fdlg->GetPathName(); //대화상자에서 경로를 받아서 저장.

UpdateData(FALSE);

}

}

선생님이 해준거 //파일 다이얼로그 만들기

CFileDialog fdlg(TRUE,"avi",".avi",OFN_OEVRWRITEPROMPT,"Vidoe Files(*.avi)|*.avi|All Files(*.*)|*.*||");


42. Animate Control 사용하기

m_animate.Open(m_filename); //파일을 연다

m_animate.Play(0,-1,1); //(처음프레임,마지막프레임,반복횟수)

m_animate.Stop(); //정지시키기

m_ani.SetAutoStart(TRUE); //자동으로 시작한다

43. Control 의 Style 바꿔주기

Control.ModyfyStyle(제거할스타일,추가할스타일); //스타일은 MSDN내용 참조


44. 시스템 날자바꾸기 버튼

//SetSystemTime(),GetSystemTime() //GMT 표준시를 가져온다.

//GetLocalTime(),SetLocalTime() //현재 지역시간을 가져온다.


SYSTEMTIME st;

GetLocalTime(&st); //현재 시간, 날자를 넣는다.

st.wYear=m_date2.GetYear();

st.wMonth=m_date2.GetMonth();

st.wDay=m_date2.GetDay();

SetSystemTime(&st);


45. 시스템 시간 바꾸기 버튼

UpdateData(TRUE);

SYSTEMTIME st;

GetLocalTime(&st);

st.wHour=m_time.GetHour();

st.wMinute=m_time.GetMinute();

st.wSecond=m_time.GetSecond();

SetLocalTime(&st);


46.시스템의 드라이브 문자 얻기


char temp[50];

GetLogicalDriveStrings(sizeof(temp),temp);

CString str,str1;

int n=0;

while(*(temp+n)!=NULL)

{

str=temp+n;

str1+= " "+str.Left(2);

n+=4;

}


47. 현재 작업경로 얻기

char temp[MAX_PATH]; //MAX_PATH 는 경로길이의 최대를 define 해놓은것.

GetCurrentDirectory(sizeof(temp),temp); // 현작업하는 경로를 얻어온다.(경로 길이,문자형);


48. Tree Control 사용하기

HTREEITEM hmov,hmus; //핸들을받을 변수 이게 잇어야 하위 디렉토리 생성가능

hmov=m_tree.InsertItem("영화",TVI_ROOT,TVI_LAST); //,TVI_ROOT,TVI_LAST는 default

hm1=m_tree.InsertItem("외화",hmov); //hmov 아래 “외화”트리 생성

CImageList m_image; //그림을 사용하기 위한 클래스다!! 알아두자..

m_tree.SetImageList(&m_image,TVSIL_NORMAL); //Tree View Style Image List => TVSIL

hmov=m_tree.InsertItem("영화",0,1,TVI_ROOT,TVI_LAST); //,TVI_ROOT,TVI_LAST는 default

hmus=m_tree.InsertItem("가요",1,2); //("문자열",처음그림번호,선택시그림)

hm1=m_tree.InsertItem("외화",2,3,hmov); //그림 번호는 default 로 0이 들어간다..


49. List Control 사용하기

m_list.ModifyStyle(LVS_TYPEMASK, LVS_ICON); //리스트를 큰아이콘형태로 보인다

m_list.ModifyStyle(LVS_TYPEMASK, LVS_SMALLICON); //리스트를 작은아이콘형태로 보인다

m_list.ModifyStyle(LVS_TYPEMASK, LVS_LIST); //리스트를 리스트형태로 보인다

m_list.ModifyStyle(LVS_TYPEMASK, LVS_REPORT); //리스트를 자세히형태로 보인다


CImageList m_treeimage; //이미지리스트

CImageList m_small, m_large;

m_large.Create(IDB_LARGE,32,0,RGB(255,255,255)); //이거는 클래스에서 추가해준거다

m_small.Create(IDB_SMALL,16,0,RGB(255,255,255)); (bmp ID값,

m_list.SetImageList(&m_large,LVSIL_NORMAL);

m_list.SetImageList(&m_small,LVSIL_SMALL);

CString name[]={"홍길동","진달래","한국남","개나리"};

CString tel[]={"400-3759","304-7714","505-9058","700-9898"};

CString born[]={"1980-1-1","1981-12-20","1980-05-15","1981-08-31"};

CString sex[]={"남자","여자","남자","여자"};

m_list.InsertColumn(0,"이름",LVCFMT_LEFT,70);

m_list.InsertColumn(1,"전화번호",LVCFMT_LEFT,80);

m_list.InsertColumn(2,"생일",LVCFMT_LEFT,90);

m_list.InsertColumn(3,"성별",LVCFMT_LEFT,50);

LVITEM it; //리스트 구조체

char temp[100];

for(int a=0;a<4;a++)

{

int n=(sex[a]=="남자")?0:1;

m_list.InsertItem(a,name[a],n); //insert item 은 행을 만들고..

it.mask=LVIF_TEXT|LVIF_IMAGE; //마스크 설정

it.iItem=a;

it.iSubItem=1; //열 설정

strcpy(temp,tel[a]); //이거 모하는거냐..

it.pszText=temp;

m_list.SetItem(&it); // setitem 열에 정보를 넣는다.


it.iSubItem=2; //열 설정

strcpy(temp,born[a]); //이거 모하는거냐..

it.pszText=temp;

m_list.SetItem(&it); // setitem 열에 정보를 넣는다.


it.iSubItem=3; //열 설정

strcpy(temp,sex[a]); //이거 모하는거냐..

it.pszText=temp;

m_list.SetItem(&it); // setitem 열에 정보를 넣는다.

50. Bitmap Button 사용하기

CBitmapButton 을 사용한다! CButton 에서 상속 받는클래스임..

m_button1.Create(NULL,

WS_CHILD|WS_VISIBLE|BS_OWNERDRAW,CRect(310,20,370,50),

this,IDC_MYBUTTON); //버튼만들기

m_button1.LoadBitmaps(IDB_UP,IDB_DOWN,IDB_FOCUS,IDB_DISABLE); //버튼의 그림설정

m_button1.SizeToContent(); //버튼을 그림 크기로 맞춰 준다!!


그냥 버튼을 비트맵버튼으로 바꾸기 -> 버튼을 만든다 속성에서 OWNERDRA 속성에 체크!!

m_button2.LoadBitmaps(IDB_UP,IDB_DOWN,IDB_FOCUS,IDB_DISABLE); //버튼의 그림설정

m_button2.SizeToContent(); //버튼을 그림 크기로 맞춰 준다!!


51. 중복없는 난수발생하기

int su; //발생된 난수저장

int a,b;

BOOL bDasi; //숫자가중복될경우 다시하기위한 변수

for(a=0;a<9;a++) //난수 9개 발생

{

bDasi=TRUE;

while(bDasi)

{

bDasi=FALSE;

su=rand()%10; //난수발생

for(b=0;b

{

if(temp[b]==su) //중복이면

{

bDasi=TRUE; //중복이 잇으면 다시while 문을 실행한다

break;

}//if

}//for

}//while

temp[a]=su; //중복이 아니면 대입한다


52. 메뉴 범위로 사용하기

ON_COMMAND_RANGE(ID_LEVEL3,ID_LEVEL9,OnLevel); //범위메세지 발생

//메뉴 ID의 값이 연속된 숫자일 경우 범위로 지정해서 사용할수잇다


53. 한,영 전환함수

void CCustView::SetHangul(BOOL bCheck) //T:한글 F:영문 이건 외우자..

{

HIMC hm=ImmGetContext(this->GetSafeHwnd()); //뷰클래스의 윈도우 핸들포인터를 얻는다.

if(bCheck)

{

::ImmSetConversionStatus(hm,1,0); //1은 한글 0은 영문

}

else

{

::ImmSetConversionStatus(hm,0,0); //영문으로 바꿔준다

}

::ImmReleaseContext(this->GetSafeHwnd(),hm); //장치를 풀어준다

}

#include "imm.h" //헤더 반드시 추가하고

imm32.lib (라이브러리 파일)를 반드시 링크해주어야 한다!

**** 라이브러리 추가하기

프로젝트메뉴 -> 셋팅 -> 링크탭


54. DLL함수정의하기

임포트함수 :

extern "C" __declspec(dllimport!!!!) 리턴형 함수명(매개변수,...);

- 메인프로그램에서 DLL에 있는 함수를 호출할때 사용한다.


엑스포트함수 :
extern "C" __declspec(dllexport) 리턴형 함수명(매개변수,...)
{

내용;

}

 

출처: http://elky.tistory.com/357

저작자표시 (새창열림)

'mfc & winAPI' 카테고리의 다른 글

[MFC] SendMessage  (0) 2014.01.07
어플리케이션(MFC)에서 스레드 사용 및 주의사항 (필독!!)  (0) 2014.01.07
Win32Api에서 x64(64비트) Application을 개발할때의 주의점들  (0) 2013.04.15
CString 형변환 Programming  (0) 2013.02.13
LPSTR LPCTSTR 위험 CString -> char 으로 변환  (0) 2013.02.13
Posted by hyeonk

Win32Api에서 x64(64비트) Application을 개발할때의 주의점들

mfc & winAPI 2013. 4. 15. 18:05

- 포인터의 전환 (64비트의 기본 개념은 DWORD라고 생각하면 된다)

> UINT to UINT_PTR : OnTimer(UINT nIDEvent) => OnTimer(UINT_PTR nIDEvent)
> LONG to DWORD_PTR : SetWindowLongPtr(hWnd1, GWLP_WNDPROC, (LONG)WndProc1);
=> SetWindowLongPtr(hWnd1, GWLP_WNDPROC, (DWORD_PTR)WndProc1);
> CWnd::OnNcHitTest 의 반환값을 int 에서 LRESULT 로 전환

 

- Linker 옵션의 /MACHINE:I386 을 MachineX64 (/MACHINE:X64) 로 전환

 

- OpenCV 를 64비트로 컴파일 하기 위해 전처리기 정의 부분에 WIN64 선언

 

- 새로운 윈도우 클래스 함수 및 정의를 사용 (좌->우)

GetClassLong GetClassLongPtr
GetWindowLong GetWindowLongPtr
SetClassLong SetClassLongPtr
SetWindowLong SetWindowLongPtr
GWL_WNDPROC GWLP_WNDPROC
GWL_HINSTANCE GWLP_HINSTANCE
GWL_HWNDPARENT GWLP_HWNDPARENT
GWL_USERDATA GWLP_USERDATA
GWL_ID GWLP_ID

GCL_MENUNAME GCLP_MENUNAME
GCL_HBRBACKGROUND GCLP_HBRBACKGROUND
GCL_HCURSOR GCLP_HCURSOR
GCL_HICON GCLP_HICON
GCL_HMODULE GCLP_HMODULE
GCL_WNDPROC GCLP_WNDPROC
GCL_HICONSM GCLP_HICONSM


 

출처: http://hebhy.cublip.com/232

저작자표시 (새창열림)

'mfc & winAPI' 카테고리의 다른 글

어플리케이션(MFC)에서 스레드 사용 및 주의사항 (필독!!)  (0) 2014.01.07
[MFC] MFC 팁 모음  (0) 2013.06.28
CString 형변환 Programming  (0) 2013.02.13
LPSTR LPCTSTR 위험 CString -> char 으로 변환  (0) 2013.02.13
CString과 char*간의 변환  (0) 2012.12.07
Posted by hyeonk
이전페이지 다음페이지
블로그 이미지

hello world! hyeonk lab.

by hyeonk

공지사항

    최근...

  • 포스트
  • 댓글
  • 트랙백
  • 더 보기

태그

글 보관함

«   2025/08   »
일 월 화 수 목 금 토
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31

링크

카테고리

전체 (44)
ios (1)
mfc & winAPI (17)
c & c++ (4)
java (1)
eclipse (1)
visual_studio (2)
javascript (3)
asp (1)
oracle (3)
개발이야기 (5)
윈도우 일반 (2)
etc (2)
reference (2)
personal_reference (0)

카운터

Total
Today
Yesterday
방명록 : 관리자 : 글쓰기
hyeonk's Blog is powered by daumkakao
Skin info material T Mark3 by 뭐하라
favicon

hyeonk lab

hello world! hyeonk lab.

  • 태그
  • 링크 추가
  • 방명록

관리자 메뉴

  • 관리자 모드
  • 글쓰기
  • 전체 (44)
    • ios (1)
    • mfc & winAPI (17)
    • c & c++ (4)
    • java (1)
    • eclipse (1)
    • visual_studio (2)
    • javascript (3)
    • asp (1)
    • oracle (3)
    • 개발이야기 (5)
    • 윈도우 일반 (2)
    • etc (2)
    • reference (2)
    • personal_reference (0)

카테고리

PC화면 보기 티스토리 Daum

티스토리툴바