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

원래 c와 c++은 string이라는 똑똑한 자료구조형을 compiler차원에서 지원하고 있지 않습니다.

그대신 가장 많이 사용하는 string을 어떻게 저장해야 할지에 대해 고심한 결과...
결국 배열의 끝에 '\0'또는 0 또는 NULL값을 넣어 string을 표현하도록 했습니다.
결국 가장 적은 용량의 string처리와 가장 골치아픈 string처리가 탄생하는 순간이였죠.

어쨌거나 요점은...
Windows에서는 이런 string처리를 위해서 char* 형을 그대로 쓰기 보다는 LPCSTR등의 표현으로 
대치해 사용함으로써, 개발의 편의성을 돕고 있습니다.

* LPSTR, LPCSTR
LP는 long pointer를 나타내는 약어로서 16bit시절의 윈도우의 유산입니다.
과거 windows3.1까지의 시절에는 포인터는 모두 16bit였고, 24bit 메모리를 long pointer라는 것을 통해서 
extended memory라는 이름으로 관리했었거든요..
현재 LP(long pointer)는 .Net에서는 64bit pointer를, VC++6.0과 그 이전 버전에서는 32bit pointer를 나타냅니다.

C는 constant, 즉 함수의 내부에서 인자값을 변경하지 말라는 뜻입니다.

STR은 내부적으로는 char형 배열에 null값 종료를 의미하고 있죠.

LPSTR = long pointer string = char *
LPCSTR = long pointer constant string = const char *
결과적으로는 맨 마지막과 같은 형이라는 거죠.



* LPWSTR, LPCWSTR
W 이넘은 wide char를 나타냅니다. 쉽게 말하면 unicode죠..
한글 조합형 코드도 아니고...unicode를 나타냅니다.

LPWSTR = long pointer wide string = w_char *
LPCWSTR = long pointer constant wide string = const w_char *

//이하 미정리
* LPCTSTR
LPCTSTR = long pointer constant t_string = const tchar *
- t_char('티캐릭터'라고 읽습니다.)

마이크로소프트가 세계 각국에 제품을 판매하면서..각국의 언어에 맞추어 개발하는 것에 환멸을 느끼다가..
드디어 windows를 unicode기반으로 개발하는 작업에 착수했습니다.



그런데... 문제는 char는 1Byte이고 wide char는 2Byte이므로..포인터 연산을 많이하는 c, c++코드는 호환성에 치명적인 문제가 있었죠. 그래서 컴파일러가 precompile option을 보고. 환경에 맞게 동작하는 코드를 작성할 수 있는 새로운 변수 모양의 Macro를 선언하게 되었습니다.


그것이 바로 TCHAR, t_char라는 변수죠.
이놈들은 자신의 운영체제가 
multi-byte환경이면, char형으로, unicode환경이면, w_char, wide char형으로 type casting됩니다.

그래서... 보통 windows 9x, 2000계열의 환경이라면,
LPTSTR = LPSTR = char *
LPCTSTR = LPCSTR = const char *가 됩니다.

그런데..
아마 저 코드에서..
(LPSTR)(LPCTSTR) 형변환을 할때 자세히 보면..
const 라는 키워드만 떼내는거지요...
그러니까 사실은 (char *)(const char *)와 같은 말입니다.
웃기는 형변환이죠..
그럼 없어도 될까요?^^

없으면 당연히 오류가 나게됩니다.
왜냐면...(LPSTR)CString을 하면.... CString형 자료의 맨 처음 주소부터 char * 형으로 형변환하기 때문이죠.
CString형은 앞의 16Byte를 자료형을 표현하기 위해서 사용하기 때문에, 여기서부터 형 변환을 해주면 엉뚱한 값이 표현되게 됩니다.

따라서 MFC에서 지원하는 CString class는 LPCTSTR라는 함수를 통해서 일단 안전하게 const char * 형으로 바뀐 자료형을 얻어오게 하는거죠.

CString myString;
(LPCTSTR)myString;이라고 해주면..
myString내부의 string 값을 꺼내오게 도와주는 연산자 또는 함수를 사용하게 된겁니다.
즉 (LPCTSTR)이란 놈이 반환값이 const char* 인 함수입니다.
정확하게 표현하면 operator overloading이라는 거지요.

결과적으로 (LPSTR)(LPCTSTR)myString은
myString의 내부 string 자료를 함수를 통해 자료를 꺼내온뒤에, char* type으로 안전하게 바꾸어주는 역할을 하게 되는 거지요.

참고로, 함수의 인자가 char * 인곳에 const char* 형을 넣으면 컴파일 오류가 발생하기 때문에 (LPSTR)을 한번더 앞에 써주어서 강제 type casting을 한 것입니다.



-- 출처 : http://egloos.zum.com/qufl1999/v/2338193


CPP 기본 예외처리

Programming/C,CPP,CS 2016. 3. 28. 09:21 Posted by TanSanC
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

try

{

// Exception 발생 구문

}

catch (std::exception&  e)

{

e.what(); // 활용하여 예외처리


}




https://msdn.microsoft.com/ko-kr/library/c4ts6d5a.aspx


ATL/COM 강좌

Programming/COM,ATL 2016. 3. 25. 16:21 Posted by TanSanC
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

ATL/COM 강좌


  COM(Component Object Model)은 컴포넌터 기반의 분산 컴퓨팅 기술이고, ATL(Active Template Library)은 그 COM 프로그래밍을 쉽게 하기 위해 Visual C++에서 제공하는 라이브러리이다. 소개에서는 COM의 개념 및 구조를 개괄적으로 설명하고, Client 프로그램 제작 및 Server 프로그램 제작에서 ATL을 사용하지 않고 COM 프로그램을 작성하는 방법을 설명하는데 이 부분은 개념 위주로 보면 되고, 실제 프로그래밍에서는 나머지 부분(쉬운 Server 프로그램 제작, 쉬운 COM Client 프로그램 제작)을 이용하여 프로그램을 작성한다.


좋은 강좌가 있어서 링크를 올립니다.


http://jys92.com.ne.kr/AtlCom.htm


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

ATL 프로젝트에서 hWnd사용하기




문제 상황 : 


ATL 프로젝트에서


소켓 통신을 위한 쓰레드를 만들어 사용하다


소켓 통신 도중 특정 메시지 수신시


ATL 이벤트를 발생 시키고 싶었다.


------요약-----------


Worker Thread 에서 ATL event(Fire_xxxx) 실행



직접 Fire 함수를 실행시 Invoke 부분에서


E_UNEXPECTED Catastrophic failure. 를 리턴한다.



Worker Thread 에서 ATl main Thread 의 함수를 실행하여 그런것 같다.



SendMessage 나 PostMessage 로 Main Thread 가 실행하도록 메시지를 주는 방법을 찾던 도중


SendMessage가 hWnd 를 이용하여 타 쓰레드간 메시지를 주고 받을수 있다는 점을 활용하였다.



하지만 기본 ATL 객체는 hWnd 를 갖고 있지 않다.



생성자 호출 시


상속 받은 m_bWindowOnly 변수를 TRUE 로 초기화하면 


m_bWindowOnly = TRUE;



상속 받은 m_hWndCD 를 사용 할 수 있다.


m_hWndCD를 활용하여 WorkerThread 에서


메인 쓰레드로 메세지를 준다.



::SendMessage(pHelloCtrl->m_hWndCD, WM_xxx, (WPARAM)NULL, (LPARAM)NULL);




추가-------

혹시나 메인 쓰레드에서 메세지를 받는 방법을 모르는 사람이 있을까 싶어서 추가합니다.

일반 MFC 는 이런 메세지 맵을 갖고 있는데

BEGIN_MESSAGE_MAP(CMFCApplication2Dlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON1, &CMFCApplication2Dlg::OnBnClickedButton1)
END_MESSAGE_MAP()


ATL 프로젝트는


BEGIN_MSG_MAP(xxxxxx)
MESSAGE_HANDLER(WM_CODE_START, OnSTART)
MESSAGE_HANDLER(WM_CODE_STOP, OnSTOP)
CHAIN_MSG_MAP(CComControl<xxxxxxxx>)
DEFAULT_REFLECTION_HANDLER()
END_MSG_MAP()

이런 메세지 맵을 갖고 있습니다.



여기에 SendMessage 로 받을 메세지를 선언하고 그 때 실행할 함수를 위치시키면 됩니다.




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

ATL 프로젝트로 만든 DLL 을 MFC 프로젝트에서 사용하기



ATL 프로젝트로 만든 DLL 이름을 ComServer.DLL 이라고 가정하겠습니다.


ComServer 대신에 자신이 만든 DLL 을 쓰면 됩니다.



사용하고자하는 ComServer.dll 파일을 프로젝트 디렉토리에 복사한다.


stdafx.h 파일에 


#import "ComServer.dll" no_namespace named_guids


넣고


빌드를 하게 되면


빌드 폴더에 ComServer.tlh , ComServer.tli 가 생성된것을 확인 할 수 있습니다.



ComServer.tlh 파일을 열어 둡니다.




그다음 Dlg 의 OnInitDialog() 같은 곳에 아래의 코드를 삽입한다.


ComTest 는 객체 이름입니다.


try{


UpdateData();


HRESULT rc;


IComTestPtr pComTest; //IComTest *pComTest 도 가능 !!! (IComTest 의 스마트포인터)


rc = CoCreateInstance(CLSID_ComTest, NULL, CLSCTX_INPROC_SERVER, DIID_IComTest, (void**)&pComTest);


if (FAILED(rc)){


MessageBox("Failure in call to CoCreateInstance");


return;


}


pComTest->(사용하고 싶은 속성이나 메서드);


}


catch (_com_error &e){


CString strBuffer;


strBuffer.Format("Code = %08lXnCode meaning = %snSource = %snDescription = %sn",

e.Error(), e.ErrorMessage(), e.Source(), e.Description());

AfxMessageBox(strBuffer);

}






'Programming > COM,ATL' 카테고리의 다른 글

MFC 프로젝트에서 ATL 연동하기  (2) 2016.03.29
ATL/COM 강좌  (0) 2016.03.25
ATL 프로젝트에서 hWnd사용하기 #2  (0) 2016.03.25
ATL 프로젝트에서 hWnd사용하기  (0) 2016.03.25
ocx, dll 라이브러리 등록  (0) 2016.03.15

ATL 프로젝트에서 hWnd사용하기

Programming/COM,ATL 2016. 3. 25. 11:19 Posted by TanSanC
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

ATL 프로젝트에서 hWnd사용하기




문제 상황 : 


ATL 프로젝트에서


소켓 통신을 위한 쓰레드를 만들어 사용하다


소켓 통신 도중 특정 메시지 수신시


ATL 이벤트를 발생 시키고 싶었다.


------요약-----------


Worker Thread 에서 ATL event(Fire_xxxx) 실행



직접 Fire 함수를 실행시 Invoke 부분에서


E_UNEXPECTED Catastrophic failure. 를 리턴한다.



Worker Thread 에서 ATl main Thread 의 함수를 실행하여 그런것 같다.



SendMessage 나 PostMessage 로 Main Thread 가 실행하도록 메시지를 주는 방법을 찾던 도중


SendMessage가 hWnd 를 이용하여 타 쓰레드간 메시지를 주고 받을수 있다는 점을 활용하였다.



하지만 기본 ATL 객체는 hWnd 를 갖고 있지 않다.



생성자 호출 시


상속 받은 m_bWindowOnly 변수를 TRUE 로 초기화하면 


m_bWindowOnly = TRUE;



상속 받은 m_hWndCD 를 사용 할 수 있다.


m_hWndCD를 활용하여 WorkerThread 에서


메인 쓰레드로 메세지를 준다.



::SendMessage(pHelloCtrl->m_hWndCD, WM_xxx, (WPARAM)NULL, (LPARAM)NULL);






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

MSDN 번역


■ PostMessage()


1. 원형

BOOL PostMessage(

    HWND hWnd,     // 이 메시지를 받을 윈도우 핸들

    UINT Msg,      // 전달할 메시지

    WPARAM wParam, // 여분 데이터

    LPARAM lParam  // 여분 데이터

);  


2. 동작

   - Msg 인수로 지정된 메시지를 hWnd 윈도우의 메시지 큐에 집어 넣는다.

   - 메시지를 받은 윈도우는 윈도우 프로시저에서 이 메시지를 처리한다.

   - 메시지를 메시지 큐에 넣기만 하고 바로 리턴 한다.

   - 큐에 붙인 메시지는 GetMessage() 에 의해 읽혀지고, DispatchMessage() 에 의해 윈도우 프로시저로 보내짐


3. 리턴값에 대하여

    - TRUE : 메시지를 메시지 큐에 붙이기 성공

    - FALSE : 메시지를 메시지 큐에 붙이기 실패

    ※ 가급적이면 리턴값을 점검해 보는 것이 좋다.

        메시지 큐는 크기가 한정되어 있기 때문에 고속으로 전송되는 모든 메시지를 다 수용하지 못할 수도 있기때문


4. 장점

   - 메시지를 메시지 큐에 넣기만 하고 곧바로 리턴 하므로 보내는 쪽에서 "블록(Block)" 시키지 않는다.

      따라서 바로 다른 작업을 할 수 있다.


5. 단점

   - 메시지를 메시지 큐에 넣고 리턴한다. 이때 메시지 큐에 대기하고 있는 다른 메시지가 있으면 해당 메시지가

     바로 처리되지 않을 수도 있다.

   - 메시지가 언제 처리 될지도 예측할 수 없으므로 메시지의 wParam, lParam 에는 지역 포인터를 사용하지 

     않아야 한다.

     (메시지를 붙일 시점에는 포인터가 존재했더라고 메시지가 처리될 시점에는 포인터가 무효해 질수도 있다.)

     

6. 활용

   - 급하게 처리할 필요가 없는 처리의 메시지

   - 지금 하고 있는 작업을(메시지를 보내는 입장에서) 완전히 끝내야만 처리할 수 있는 메시지


7. 첫 번째 인수 hWnd 가 NULL 인 경우

   - 특정 윈도우에게 신호를 보내기 위한 것이 아니라 응용 프로그램 전반에 걸친 작업 지시를 보낼 때 사용

   - 대상 윈도우가 없기 때문에 이 메시지는 윈도우 프로시저가 처리할 수 없으며 윈도우 프로시저로 가기전인

     메시지 루프에서 직접 처리해 주어야 한다.

while (GetMessage(&Message, 0, 0, 0)) {

    if (Message.message == WM_SOME) {

        // 직접 처리

    } else {

        TranslateMessage(&Message);

        DispatchMessage(&Message);

    }

   - GetMessage로 메시지를 꺼낸 후 곧바로 메시지 ID를 비교해 보고 스레드를 위한 메시지 인지 검사해 본다

   - 만약 스레드를 위한 메시지라면 메시지 루프에서 직접 처리해야 하며 DispatchMessage 함수로 보내지말것

   - 대상 윈도우가 지정되지 않은 메시지이기 때문에 이 메시지를 받아줄 윈도우 프로시저가 없기 때문.

   - PostMessage 함수가 메시지를 붙여넣는 큐가 윈도우를 위한 큐가 아니라 스레드를 위한 큐이기 때문에 가능





■ PostThreadMessage()


1. 원형

BOOL PostThreadMessage(

     DWORD idThread,    // 스레드 ID

     UINT Msg,          // 전달할 메시지

     WPARAM wParam,

     LPARAM lParam

);  

2. 사용 목적

   - 다른 스레드의 메시지 큐에 메시지를 붙일 때 사용

   - 스레드 외부에서 특정 스레드로 메시지를 전달할 때


3. 한계

   - 작업자 스레드에선 사용할 수 없고, 사용자 인터페이스 스레드 에서만 사용 가능





■ SendMessage()


1. 원형

BOOL SendMessage(

    HWND hWnd,     // 이 메시지를 받을 윈도우 핸들

    UINT Msg,      // 전달할 메시지

    WPARAM wParam, // 여분 데이터

    LPARAM lParam  // 여분 데이터

); 


            ※ SendMessage() 와 PostMessage() 함수의 원형은 동일


2. 동작

   - 메시지를 메시지 큐에 넣는 것이 아니라 곧바로 윈도우 프로시저로 보내 즉각 처리하도록 한다.

   - 메시지가 완전히 처리되기 전에 리턴하지 않는다. (블록 시킴)


3. 장점

   - 보낸 메시지의 정확한 처리 보장


4. 단점

   - 보낸 메시지가 완전히 처리 될때까지 기다리므로, 메시지를 보낸쪽은 블록 상태에 머물게 된다.

     영영 블록되어 프로그램이 죽을 수도 있다.

   ※ 메인 스레드에서 다른 스레드로 메시지를 보낼때 SendMessage() 의 사용은 위험하다


5. 활용

   - 부모 윈도우와 차일드 컨트롤 간의 통신

   - 윈도우간 정확한 데이터 전송 및 처리를 위한 통신

   - 윈도우의 특정 메시지는 SendMessage() 만을 사용해야 하는 경우도 있다. (WM_COPYDATA)

■ PostMessage()


1. 원형

BOOL PostMessage(

    HWND hWnd,     // 이 메시지를 받을 윈도우 핸들

    UINT Msg,      // 전달할 메시지

    WPARAM wParam, // 여분 데이터

    LPARAM lParam  // 여분 데이터

);  


2. 동작

   - Msg 인수로 지정된 메시지를 hWnd 윈도우의 메시지 큐에 집어 넣는다.

   - 메시지를 받은 윈도우는 윈도우 프로시저에서 이 메시지를 처리한다.

   - 메시지를 메시지 큐에 넣기만 하고 바로 리턴 한다.

   - 큐에 붙인 메시지는 GetMessage() 에 의해 읽혀지고, DispatchMessage() 에 의해 윈도우 프로시저로 보내짐


3. 리턴값에 대하여

    - TRUE : 메시지를 메시지 큐에 붙이기 성공

    - FALSE : 메시지를 메시지 큐에 붙이기 실패

    ※ 가급적이면 리턴값을 점검해 보는 것이 좋다.

        메시지 큐는 크기가 한정되어 있기 때문에 고속으로 전송되는 모든 메시지를 다 수용하지 못할 수도 있기때문


4. 장점

   - 메시지를 메시지 큐에 넣기만 하고 곧바로 리턴 하므로 보내는 쪽에서 "블록(Block)" 시키지 않는다.

      따라서 바로 다른 작업을 할 수 있다.


5. 단점

   - 메시지를 메시지 큐에 넣고 리턴한다. 이때 메시지 큐에 대기하고 있는 다른 메시지가 있으면 해당 메시지가

     바로 처리되지 않을 수도 있다.

   - 메시지가 언제 처리 될지도 예측할 수 없으므로 메시지의 wParam, lParam 에는 지역 포인터를 사용하지 

     않아야 한다.

     (메시지를 붙일 시점에는 포인터가 존재했더라고 메시지가 처리될 시점에는 포인터가 무효해 질수도 있다.)

     

6. 활용

   - 급하게 처리할 필요가 없는 처리의 메시지

   - 지금 하고 있는 작업을(메시지를 보내는 입장에서) 완전히 끝내야만 처리할 수 있는 메시지


7. 첫 번째 인수 hWnd 가 NULL 인 경우

   - 특정 윈도우에게 신호를 보내기 위한 것이 아니라 응용 프로그램 전반에 걸친 작업 지시를 보낼 때 사용

   - 대상 윈도우가 없기 때문에 이 메시지는 윈도우 프로시저가 처리할 수 없으며 윈도우 프로시저로 가기전인

     메시지 루프에서 직접 처리해 주어야 한다.

while (GetMessage(&Message, 0, 0, 0)) {

    if (Message.message == WM_SOME) {

        // 직접 처리

    } else {

        TranslateMessage(&Message);

        DispatchMessage(&Message);

    }

   - GetMessage로 메시지를 꺼낸 후 곧바로 메시지 ID를 비교해 보고 스레드를 위한 메시지 인지 검사해 본다

   - 만약 스레드를 위한 메시지라면 메시지 루프에서 직접 처리해야 하며 DispatchMessage 함수로 보내지말것

   - 대상 윈도우가 지정되지 않은 메시지이기 때문에 이 메시지를 받아줄 윈도우 프로시저가 없기 때문.

   - PostMessage 함수가 메시지를 붙여넣는 큐가 윈도우를 위한 큐가 아니라 스레드를 위한 큐이기 때문에 가능





■ PostThreadMessage()


1. 원형

BOOL PostThreadMessage(

     DWORD idThread,    // 스레드 ID

     UINT Msg,          // 전달할 메시지

     WPARAM wParam,

     LPARAM lParam

);  

2. 사용 목적

   - 다른 스레드의 메시지 큐에 메시지를 붙일 때 사용

   - 스레드 외부에서 특정 스레드로 메시지를 전달할 때


3. 한계

   - 작업자 스레드에선 사용할 수 없고, 사용자 인터페이스 스레드 에서만 사용 가능





■ SendMessage()


1. 원형

BOOL SendMessage(

    HWND hWnd,     // 이 메시지를 받을 윈도우 핸들

    UINT Msg,      // 전달할 메시지

    WPARAM wParam, // 여분 데이터

    LPARAM lParam  // 여분 데이터

); 


            ※ SendMessage() 와 PostMessage() 함수의 원형은 동일


2. 동작

   - 메시지를 메시지 큐에 넣는 것이 아니라 곧바로 윈도우 프로시저로 보내 즉각 처리하도록 한다.

   - 메시지가 완전히 처리되기 전에 리턴하지 않는다. (블록 시킴)


3. 장점

   - 보낸 메시지의 정확한 처리 보장


4. 단점

   - 보낸 메시지가 완전히 처리 될때까지 기다리므로, 메시지를 보낸쪽은 블록 상태에 머물게 된다.

     영영 블록되어 프로그램이 죽을 수도 있다.

   ※ 메인 스레드에서 다른 스레드로 메시지를 보낼때 SendMessage() 의 사용은 위험하다


5. 활용

   - 부모 윈도우와 차일드 컨트롤 간의 통신

   - 윈도우간 정확한 데이터 전송 및 처리를 위한 통신

   - 윈도우의 특정 메시지는 SendMessage() 만을 사용해야 하는 경우도 있다. (WM_COPYDATA)

CFile 클래스

Programming/C,CPP,CS 2016. 3. 18. 09:57 Posted by TanSanC
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

CFile 클래스



AlternativeMFC.zip


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


위의 문제는 컴파일 시에 일어나는 단순한 링크 타이밍의 문제입니다. 
인클루드의 순서를 바꾸어 주는 것으로 해결 가능하지요.


기존 링크 순서는 아래와 같았습니다. 
#include <xxxx.h>
#include <xxxx.h>
#include "stdafx.h"

이것을 아래와 같이 바꾸어 주어서 해결했습니다.
#include "stdafx.h"
#include <xxxx.h>
#include <xxxx.h>



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

CStdString 표준 C++ 을 사용한 CString C/C++

http://j2doll.tistory.com/488



StdString_src.zip