.Net FrameWork 버전 확인 방법

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


cmd.exe




dir %windir%\Microsoft.NET\Framework | findstr DIR





C# Class Library use in script

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

C# Class Library use in script




C# Class Library



namespace ClassLibrary2

{

    // Interface declaration.

    public interface ICalculator

    {

        int Add(int Number1, int Number2);

    };

    [ProgId("Test.SimpleCalc")]

    public class SimpleCalc : ICalculator

    {

        public int Add(int Number1, int Number2)

        {

            return Number1 + Number2;

        }

    }

}





이런 형태 일때

JavaScript 에서 부르는 방법



JavaScript 에서는 주로 


요런 형태로 DLL 을 로드한다.


<object name="Class1" id="Class1" classid="CLSID:*-*-*-*" width="0" height="0"></object>


일단 임의의 CLSID 를 만들어낸다


Visual Studio [도구] [GUID 만들기] 로 GUID 를 하나 만들어 낸다.



{3963CDD9-1079-463A-BCDA-0182D296C9B6}


namespace ClassLibrary2

{

    // Interface declaration.

    public interface ICalculator

    {

        int Add(int Number1, int Number2);

    };

    [ProgId("Test.SimpleCalc")]

    [Guid("3963CDD9-1079-463A-BCDA-0182D296C9B6")]

    public class SimpleCalc : ICalculator

    {

        public int Add(int Number1, int Number2)

        {

            return Number1 + Number2;

        }

    }

}



객체에 GUID 를 설정한다.




그다음 regasm 으로 등록한다.

등록할때 /codebase 옵션을 붙여야한다.

codebase 옵션을 붙이려면 어셈블리 서명이 필요하다.


어셈블리 서명은

Properties

[서명]

[어셈블리 서명] 에서 

새로만들기로 편한대로 만들면된다

키 파일 이름, 암호 없음







그다음 html 에서

<object name="Class1" id="Class1" classid="CLSID:3963CDD9-1079-463A-BCDA-0182D296C9B6" width="0" height="0"></object>

    <script>
        function TestAdd() {
            var ctrl = document.getElementById("Class1");
            ctrl.Add(13,4);
        }
    </script>





실행하면 잘 된다.





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

C# Class Library use in java (클래스 라이브러리)



Java 에서 C# 클래스 라이브러리를 불러오기




C# 클래스 라이브러리가


namespace ClassLibrary2

{

    // Interface declaration.

    public interface ICalculator

    {

        int Add(int Number1, int Number2);

    };

    public class SimpleCalc : ICalculator

    {

        public int Add(int Number1, int Number2)

        {

            return Number1 + Number2;

        }

    }

}



그리고

잊지 말아야할 설정들



[assembly: ComVisible(true)]


COM Interop 등록





JACOB 라이브러리를 활용하여 C# DLL 을 불러와 보겠다.



http://danadler.com/jacob/


에 들어가서 기본 라이브러리를 추가한다.




jacob.jar 를 Java Build Path 에 추가한다.


ActiveXComponent xl = new ActiveXComponent("Test.SimpleCalc");


try {

   System.out.println(Dispatch.call(xl, "Add", new Variant(1), new Variant(2)));

} catch (Exception e) {

e.printStackTrace();

}


JACOB 라이브러리는 기본적으로는 ProgID 를 통해 DLL 파일을 불러온다.




위의 C# 클래스 라이브러리는 ProgID 가 없다.


namespace ClassLibrary2

{

    // Interface declaration.

    public interface ICalculator

    {

        int Add(int Number1, int Number2);

    };

    [ProgId("Test.SimpleCalc")]

    public class SimpleCalc : ICalculator

    {

        public int Add(int Number1, int Number2)

        {

            return Number1 + Number2;

        }

    }

}



ProgID 를 추가하여 준다.




그 다음 해당 파일을 regasm 으로 등록한다.



그런 다음 Java 를 실행해 보면


Add 가 정상적으로 작동한다.


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

C# Class Library


VS2013


새 프로젝트 -> Visual C# -> 클래스 라이브러리 -> 프로젝트 이름(Library 이름이 된다, 예제에서는 ClassLibrary2 이다.) -> 


자동으로 Class1.cs 파일이 만들어진다.


이 Class1.cs 가 DLL 에서 불러쓸 객체의 이름이 된다.



참고 : https://support.microsoft.com/en-us/kb/828736




Class1.cs 를 우클릭하여 이름바꾸기 원하는 객체 이름으로 바꾼다.




예제에서는 SimpleCalc 로 진행한다.



----------------------------------------------------------------


SimpleCalc.cs


----------------------------------------------------------------


namespace ClassLibrary2

{

    public class SimpleCalc

    {

    }

}


----------------------------------------------------------------



interface 를 추가 구현한다.

// Interface declaration.
public interface ICalculator
{
    int Add(int Number1, int Number2);
};



----------------------------------------------------------------


SimpleCalc.cs


----------------------------------------------------------------


namespace ClassLibrary2

{

    // Interface declaration.

    public interface ICalculator

    {

        int Add(int Number1, int Number2);

    };

    public class SimpleCalc

    {

    }

}



----------------------------------------------------------------


interface를 상속 받고

interface 로 부터 상속받은 메서드를 구현한다.


// Interface implementation.
public class ManagedClass:ICalculator
{
    public int Add(int Number1,int Number2)
        {
            return Number1+Number2;
        }
}




----------------------------------------------------------------


SimpleCalc.cs


----------------------------------------------------------------


namespace ClassLibrary2

{

    // Interface declaration.

    public interface ICalculator

    {

        int Add(int Number1, int Number2);

    };

    public class SimpleCalc : ICalculator

    {

        public int Add(int Number1, int Number2)

        {

            return Number1 + Number2;

        }

    }

}




----------------------------------------------------------------


이제


Properties 를 열어서


AssemblyInfo.cs 를 열어보면


[assembly: ComVisible(false)] 를 찾아서



[assembly: ComVisible(true)]


로 변경한다.



[assembly: ComVisible(true)] 로 바꾸어야 ActiveX 로 사용이 가능하다.





이제 빌드하면


bin/Debug 폴더에


ClassLibrary2.dll 파일이 만들어진다.



궁극적으로 배포를 목적으로 하므로


Release 모드로 바꾸어준다.




빌드를 하게 되면


ClassLibrary2.dll 파일이 만들어진다.



하지만 클래스 내부의 구조가 보이게 하려면


tlb 파일이 필요하다


이 파일은


ClassLibrary2 프로젝트이름을 더블클릭하면 뜨는 속성 창에서


[빌드]


COM Interop 등록 을 체크해준다.


그러면 이제부터 빌드를 하면 tlb 파일도 같이 만들어진다.





tlb 파일과 dll 파일을 C# DLL 을 사용할 프로젝트의 폴더로 복사한다.




예제에서는 MFC 에서 해당 DLL 파일을 불러서 사용해보겠다.



사용할 cpp 파일에서



#import "ClassLibrary2.tlb" raw_interfaces_only

using namespace ClassLibrary2;


를 선언한다.





그 후 사용을 원하는 함수에서




HRESULT hr = CoInitialize(NULL);


// Create the interface pointer.

ICalculatorPtr pICalc(__uuidof(SimpleCalc));


long lResult = 0;


// Call the Add method.

pICalc->Add(5, 10, &lResult);


SetDlgItemInt(IDC_STERM, (int)lResult);


// Uninitialize COM.

CoUninitialize();





이렇게 사용을 하면 된다.



ICalculatorPtr 은 Interface 로 만든  ICalculator 의 스마트포인터이다


ICalculator* 와 같다.





pICalc-> 을 통해 내부에 있는 속성과 메서드에 접근이 가능하다.








c, cpp, com, atl, stl, vc7 String

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


. C 자료형

    char (1) , short (2) , int (4) , long (4), float (4) , double (8) , bool 

    문자 : char

    char szName[20] = "kim";


 

2. WIN API 자료형

 

    BYTE (1,unsigned char) , WORD (2,unsigned short) , UNIT (4, unsigned int) , 

    DWORD (4,unsigned long) , LONG (4,long) , BOOL

    문자 : UCHAR (unsigned char)

    핸들 : 대상을 구분하는 4바이트 정수(HWND, HDC 등)

 

    MBCS문자(열)                 유니코드문자(열)           자동매크로문자(열)

    char                                     wchar_t                              TCHAR

    LPSTR(char*)                    LPWSTR(wchar_t*)        LPTSTR

    LPCSTR(const char*)      LPCWSTR                         LPCTSTR

 

    (참조1) 문자열에 대해 그냥 습관적으로 LPTSTR 또는 LPCTSTR 를 써라

    (참조2) 헝가리안명명법 

                   w(WORD) , dw(DWORD) , i(int) , b(BOOL) , ch(문자) , sz(문자열) , h(핸들)

                   cb(바이트수) , a(배열)

 (참조3) OLECHAR(wchar_t), LPOLESTR(LPWSTR), LPCOLESTR(LPCWSTR), OLESTR(x) = _T(x)


 

3. COM 스트링


    BSTR : 문자열길이를 시작전에 저장하고, 이어서 유니코드문자열을 저장하는 방식
                  1> LPCWSTR ->  BSTR : 생성안됨. 생성함수를 이용해야함
                               BSTR bstr = sysAllocString(L"Hi Bob"); // 메모리할당

                              sysFreeString(bstr); // 메모리제거

                  2> BSTR  ->  LPCWSTR : 형변환 가능

 

    VARIANT : 문자열이 들어올때  BSTR과 동일

 

4. CRT(c runtime library) 지원 스트링클래스

 

    _bstr_t : BSTR랩퍼클래스, 메모리할당/제거를 자동으로 수행

                  1> LPCSTR, LPCWSTR  -> _bstr_t 
                               _bstr_t bs1 = "char string";  // 생성

                  2> _bstr_t  ->  LPCSTR, LPCWSTR 
                               LPCSTR psz1 = (LPCSTR)bs1; // 형변환

                  3> _bstr_t  ->  BSTR : 형변환안됨함수이용
                               BSTR bstr = bs1.copy();

                               sysFreeString(bstr);  // BSTR은 사용후 메모리해제를 해야하는 불편이있음..

 

    _variant_t : VARIANT랩퍼클래스, 메모리할당/제거를 자동으로 수행

                  1> LPCSTR, LPCWSTR  -> _variant_t 
                               _variant_t v1 = "char string"; // 생성

                  2> _variant_t  -> _bstr_t  ->  LPCSTR, LPCWSTR 
                               LPCSTR psz1 = (LPCSTR)(_bstr_t)v1;  //형변환

 

5. ATL 지원 스트링클래스

 

    CComBSTR : BSTR랩퍼클래스, 메모리할당/제거를 자동으로 수행

                  1> LPCSTR, LPCWSTR  ->  CComBSTR 

                               CComBSTR bs1 = "char string"; // 생성

                  2> CComBSTR  ->  BSTR   -> LPCWSTR

                               BSTR bstr = (BSTR)bs1;  // 형변환

 

                  (참조) BSTR -> CComBSTR 

                               CComBSTR bs2; bs2.Attach(W2BSTR(L"Bob"))

                              

    CComVariant : VARIANT랩퍼클래스, 메모리할당/제거를 자동으로 수행

                  1> LPCSTR, LPCWSTR  ->  CComVariant 

                               CComVariant bs1 = "char string"; // 생성

                  2> CComVariant  ->  CComBSTR   ->  BSTR   -> LPCWSTR

                               CComBSTR bs2 = bs1.bstrVal;

 

6. STL 스트링

 

    string 

                  1> LPCSTR -> string

                                string  str = "char string"; //생성

                  2> string -> LPCSTR : 형변환 안됨. 함수이용 

                                LPCSTR psz = str.c_str();

    wstring

                   1> LPCWSTR -> wstring

                                wstring  str = "wide char string"; //생성

                  2> wstring -> LPCWSTR : 형변환 안됨. 함수이용 

                                LPCWSTR psz = str.c_str();

 

7. MFC 스트링

 

    CString

                  1> LPCSTR, LPCWSTR  ->  CString 

                                CString  str = "char string"; //생성

                  2> CString  -> LPCTSTR :

                                LPCTSTR  lpsz = (LPCTSTR)str; //형변환

 

                  (참고)  CString  -> LPTSTR :  함수이용

                               LPTSTR lptsz  = str.GetBuffer(0); str.ReleaseBuffer(); //  올바른 사용

                               LPTSTR lptsz  = (LPTSTR)(LPCTSTR)str  //  잘못된 사용

                               CString  -> BSTR  

                               BSTR bstr = str.AllocSysString(); sysFreeString(bstr)

 

8. VC7 스트링

 

    String : .NET에서 새로 정의한 스트링 클래스

                               String* s1 = S"this is nice"; // 생성

                               CString s2(s1); // 형변환


출처 : http://hacheo.egloos.com/3891296


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

PostMessage , SendMessage 쓰레드간 메시지 주고받을때, 동기화


PostMessage (in "pure windows programming", aka win32 API) is asynchronous, i.e., to quote the docs:

Places (posts) a message in the message queue associated with the thread that created the specified window and returns without waiting for the thread to process the message.

To post a message in the message queue associated with a thread, use the PostThreadMessage function.

SendMessage is synchronous, that is, again quoting:

Sends the specified message to a window or windows. The SendMessage function calls the window procedure for the specified window and does not return until the window procedure has processed the message.

To send a message and return immediately, use the SendMessageCallback or SendNotifyMessage function. To post a message to a thread's message queue and return immediately, use the PostMessage or PostThreadMessage function.

A good tutorial on these two functions and their use is here.

The connection to WPF is discussed in this SO question.



PostMessage 는 메세지 큐에만 넣어주고 메세지 처리 까지는 기다리지 않기 때문에 비동기 처리, 보낸 순서와 메세지 처리 끝나는 시점이 순서가 맞지 않을 수 있다.



SnedMessage 는 메세지 큐에만 넣어주고 메세지 처리 까지 기다리기 때문에 동기 처리, 하나의 메세지가 다 처리되고나서 다음 메세지가 처리된다.




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


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