일반적인 파일 저장은 fopen / fprintf / fclose를 이용한다.


m_result_file = fopen(".\\DATA\\data.csv", "a");

if(m_result_file != NULL)

{

fprintf(m_result_file, 변수1, 변수 2 ... 등등 + CString("\n")

);

fclose(m_result_file);

}


해당 코드로는 CString을 이용한 파일 쓰기가 안되고 구글 검색 시에 나오는 파일 쓰기는 오류 등이 있다,

그래서 구글링 결과 다음과 같이 처리할 경우에 문제가 없어서 남겨둔다.


추가 팁으로 파일 존재 유무 코드가 있다.


WIN32_FIND_DATA finddata;

ZeroMemory(&finddata, sizeof(finddata));

HANDLE hExist = FindFirstFile(filepath, &finddata);

if(hExist == INVALID_HANDLE_VALUE) {

//이 경우에 파일이 없다는 뜻.

}

TCHAR *szPath;

int nLen;


TCHAR szTemp[2];

WORD wd = 0xfeff;

memcpy(szTemp, &wd, 2); // CString 변환하여 파일에 쓸 경우에 반드시 open 후 첫번째 이 문자열을 넣어줘야 한다.

csvfile.Write(szTemp, 2);

titleStr.Format(_T("~~~~~~~~~~~~~~~~~~~~~~~~~~~~")); //CString을 적당히 편집한다.

szPath = new TCHAR[titleStr.GetLength() + 1];


_tcscpy(szPath, titleStr);


nLen = _tcslen(szPath);


csvfile.Write(szPath, nLen * sizeof(WCHAR));


csvfile.Close();

잘 써짐. 기존에서는 CSV의 컬럼 구분자가 ","였으나 이렇게 사용할 경우에 "\t"이 구분자가 되니 참고 한다.



by 무위자연 2015. 2. 13. 10:49

0. MFC에서는 각 UI Component는 멤버변수를 추가해서 처리하는 것이 훨씬 간편하다

방법은 리소스 편집기에서 멤버변수 추가를 원하는 컴포넌트를 클릭후에 우클릭을 하면 메뉴가 나온다

이 메뉴에서 "Add Variable / 변수 추가하기"를 선택하면 마법사가 나온다.

마법사에서 멤버 변수명을 추가하고 "Finish/종료"를 선택하면 된다.


1. LISTBOX Tips

a. ListBox에 CString을 추가하기

AddString으로 넣을 경우에 UI 갱신 타이밍에 따라서 순서가 엉킬수가 있다.,

그러므로 Insert(인덱스, CString 객체)가 순서에 훨씬 명시적이다.


2. CEDIT Tips

b. CEDIT 컴포넌트에서의 Text 를 Get/Set하기

길이 - m_edit_fwversion.GetWindowTextLengthW()

Get - m_edit_fwversion.GetWindowTextW(m_fw_ver); // 선언한 CString 객체로 해당 값이 들어온다,

Set - m_admin_password.SetWindowTextW(_T("what you want")); //입력된 문자열이 바로 표시된다.

글자수 제한 - m_edit_sn_date.SetLimitText(3);

숫자만 입력 - 리소스 편집기에서 "Number" 라는 속성(property)를 true를 하면 숫자만 입력받게 할수 있다.

비밀번호 창으로 쓸 때 - "Password"라는 속성을 "true"로 해주면 입력 값이 "*"로 보이게 할 수 있다.


3. COMBOBOX Tips

a. 콤보박스에서 정해진 값만 보여주고 선택한 콤보아이템을 편집하지 못하게 할때

콤보박스 속성에 "Type" 중에 "Dropdownlist"를 선택할 경우에 정해진 아이템만 선택하고 편집이 불가능하게 할 수 있다.


b. 콥보박스에서 선택된 셀의 Text를 읽어오기.

GetLBText를 사용하면 해당 콤보박스의 아이템 텍스트를 바로 가져올 수 있고 형식은 CString이다.

ex. m_cb_sn_group1.GetLBText(m_cb_sn_group1.GetCurSel(),set_p_group1);




by 무위자연 2015. 2. 12. 12:09

MFC UI에서 입력 받은 여러개의 CString 으로 받은 다음에 하나의 char arry로 바꾸는 작업을 위해서 



방법 !

CString을 선언하고

strncpy로 복사하면 된다.


CString g_postSerialnum;

char temp_sn[12];

g_postSerialnum= _T("A0111010asdas");

strncpy(temp_sn, g_postSerialnum, 12);

만일 길이를 지정하지 않고 strcpy를 쓴다면?

strcpy(temp_sn, g_postSerialnum);

환경에 따라서 다르겠지만 MFC C++ / 2008에서는 함수 콜이 끝나면 죽는다

디버그에서는 안 죽고 릴리스에서만!!!

주의해서 써야 한다.


후썰...


이짓을 하게된 배경


<전임자코드>--------------------------------------------------------------

CString set_product_code1, set_product_code2, set_made_factory, set_made_date, set_made_year, set_product_num;


CString str;


//이 부분은 UI에서 얻어오는 부분이기때문에 일단 보류

m_sn_model_list.GetLBText(m_sn_model_list.GetCurSel(), set_product_code1);

m_sn_model_list1.GetLBText(m_sn_model_list1.GetCurSel(), set_product_code2);

m_mcnt_list.GetLBText(m_mcnt_list.GetCurSel(), set_made_factory);

GetDlgItemText(20012, set_made_date);

m_version_list.GetLBText(m_version_list.GetCurSel(), set_made_year);

GetDlgItemText(20017, set_product_num);


////////////////////////////////////////////////////////////////////////////////////////

//SN char 배열에 삽입


char model_code[2], factory_code[2], date[2], year[2], count1[2], count2[2];

CString set_made_date1, set_made_date2, set_made_date3;

CString set_product_num1, set_product_num2, set_product_num3, set_product_num4, set_product_num5;


//CString을 한자씩 짤라서 CString 한 글자씩으로 만든다.

//한글자씩 잘라서

set_made_date1 = set_made_date.Mid(0,1);

set_made_date2 = set_made_date.Mid(1,1);

set_made_date3 = set_made_date.Mid(2,1);

set_product_num1 = set_product_num.Mid(0,1);

set_product_num2 = set_product_num.Mid(1,1);

set_product_num3 = set_product_num.Mid(2,1);

set_product_num4 = set_product_num.Mid(3,1);

set_product_num5 = set_product_num.Mid(4,1);


//각 한자의 CString을 sctcpy로 복사한다.

strcpy(&model_code[0], (LPSTR)(LPCTSTR)set_product_code1);

strcpy(&model_code[1], (LPSTR)(LPCTSTR)set_product_code2);

strcpy(&factory_code[0], (LPSTR)(LPCTSTR)set_made_factory);

strcpy(&factory_code[1], (LPSTR)(LPCTSTR)set_made_date1);

strcpy(&date[0], (LPSTR)(LPCTSTR)set_made_date2);

strcpy(&date[1], (LPSTR)(LPCTSTR)set_made_date3);

strcpy(&year[0], (LPSTR)(LPCTSTR)set_made_year);//year의 경우에는 심지어 한자인데도 2개로 선언하고 처리함.

strcpy(&year[1], (LPSTR)(LPCTSTR)set_product_num1);

strcpy(&count1[0], (LPSTR)(LPCTSTR)set_product_num2);

strcpy(&count1[1], (LPSTR)(LPCTSTR)set_product_num3);

strcpy(&count2[0], (LPSTR)(LPCTSTR)set_product_num4);

strcpy(&count2[1], (LPSTR)(LPCTSTR)set_product_num5);


//한자씩 넣은 것을 또 char arry에 하나씩 넣는다.

//이때 변수명도 제각각 이라 순환문을 못 쓰고 다 따로 넣어줘야 해서 리팩토링이 절실하다.

send_packet[11] = model_code[0];

send_packet[12] = model_code[1];

send_packet[13] = factory_code[0];

send_packet[14] = factory_code[1];

send_packet[15] = date[0];

send_packet[16] = date[1];

send_packet[17] = year[0];

send_packet[18] = year[1];

send_packet[19] = count1[0];

send_packet[20] = count1[1];

send_packet[21] = count2[0];

send_packet[22] = count2[1];


<나의 코드>

//CString의 값을 하나로 붙인다.

g_postSerialnum = set_p_group1+ set_p_group2 + set_p_model1+set_p_model2 + set_made_date + set_made_year + set_product_num;

//한방에 복사 끝. 어차피 하나로 붙인 char 모음들을 묶어서 선언하고 복사한다.

//이때 반드시 strncpy를 쓴다.

strncpy(temp_sn, g_postSerialnum, 12);

//당연히 하나의 char array 이므로 순환문으로 넣는 것이 가능하다

for(int i = 11; i < 23; i++)

{

send_packet[i] = temp_sn[i - 11];

}




by 무위자연 2015. 2. 3. 10:30

• Data is negligible even longer delay included in the event.


• Raise the event in a row without delay, even if you can handle in Flex.



• The time the Event is passed to the swc in the Dll is the time that one function ends.


• Data transfer test results.


      You can receive all the treatment in less than one second in Flex in 2893 when the char array length Raise an event that contains as much as 1000 times.


Test environment;

- OS: Windows 7 64 bits

- Flash Builder 4.6

- VisualStudio 2010 - C ++

(Korean)


by 무위자연 2015. 1. 22. 08:49

If you have to deal with the issue at the Event dispatch in Flex.




This is not a problem occurring in the dispatch occurs in the event handler.




When A event raises and  a B event handler to handle the case.


Example.


// Normal  case, Use right


main.addEventListener (CustomEventA.DataSend, csEventHandler, false, 0, true);


// Abnormal case, Use wrong


main.addEventListener (CustomEventB.DataSend, csEventHandler, false, 0, true);




private function csEventHandler (e: CustomEventA): void


{


// handle events


}




When the CustomEventA raises to normal operation.


If CustomEventB is the same as a event handler, errors occurs. It is difficult to find this error because error message show at the dispatch event CustomEvent B


"TypeError: Error # 1034: Type Coercion failed: can not convert CustomEventB @ 64e6ca1 to CustomEventB will aereo is to be opened in this way.


If you make a new event handler for CustomEvent B, it can be solved


(Korean)

by 무위자연 2015. 1. 22. 08:48

Flex에서 Event dispatch시에 해당 이슈가 발생할 경우에 대한 대처.


이는 dispatch에서 발생하는 문제가 아니라 해당 이벤트 핸들러에서 발생하게 된다.


A 이벤트를 Raise를 하고 B 이벤트 핸들러로 처리하는 경우이다.


예.

//정상 처리, Use right

main.addEventListener(CustomEventA.DataSend, csEventHandler, false, 0, true);

//비정상 이벤트 등록, Use wrong

main.addEventListener(CustomEventB.DataSend, csEventHandler, false, 0, true);


private function csEventHandler(e:CustomEventA):void

{

//handle events

}


CustomEventA가 Raise되었을때는 정상 동작한다.

CustomEventB가 Raise가 되면 dispatch쪽에 애러가 나지만 실제 csEventHandler가 호출되는 순간에 제목과 같은 애러가 뜬다. 애러나는 라인이 dispatch쪽이라 찾기가 어려우므로 글로 남긴다.

"TypeError: Error #1034: Type Coercion failed: cannot convert CustomEventB@64e6ca1 to CustomEventB 이런식으로 애러가 뜨게 될 것이다.

CustomEventB 처리를 위한 새로운 이벤트 핸들러를 등록해주면 해결이 가능하다.



by 무위자연 2015. 1. 9. 13:54
• 이벤트에 포함된 Data가 길어져도 delay가 생기지 않습니다.

• 이벤트를 delay  없이 연속으로  Raise하더라도 Flex에서 처리 가능합니다.

• Dll에서 swc로 Event가 전달되는 시점은 하나의 함수가 끝나는 시점입니다.

• 데이터 전달 테스트 결과.

     char 배열 2893 길이 만큼이 포함된 event를 1000번 Raise 할 경우에 Flex에서 1초 이내에 모두 받아서 처리가 가능합니다.

[테스트 환경]
- OS : Windows 7 64 bits
- Flash Builder 4.6
- VisualStudio 2010 - C++


by 무위자연 2015. 1. 6. 14:15

Flex / AIR 플랫폼에서 native 구현부를 ANE라고 한다.


ANE를 만들기 위해서는 다음과 같은 동작이 필요하다


하기 예는 Windows를 환경에서의 과정이다.


1. native 코드로 (여기서는 C++) 기능을 구현한다.

구현시엔 하기와 같은 파일을 첨부하며 Flex에서 호출할수 있도록 함수 리스트를 추가해준다.


#include "FlashRuntimeExtensions.h"  


기능 구현

FREObject functions(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[])   

{

//C++ 코드

}

함수 리스트 추가

void ContextInitializer(void* extData, const uint8_t* ctxType, FREContext ctx, uint32_t* numFunctions, const FRENamedFunction** functions) { 

 *numFunctions = 12; //사용할 함수 개수

 FRENamedFunction* func = FRENamedFunction*)malloc(sizeof(FRENamedFunction)*(*numFunctions)); 

  func[0].name = (const uint8_t*)함수이름"; //Flex에서 call할때 쓸 이름

 func[0].functionData = NULL; 

 func[0].function = 실제 구현한 함수의 포인터; 

*functions = func;  //설정한 함수리스트를 함수의 포이턴에 추가해준다.

2. native 구현한 함수를 call하는 Flex 프로젝트를 생성하여 빌드한다.

빌드해서 만들어진 swc의 확장자를 바꿔서 압축을 풀면 catalog.xml/library .swf 파일을 확인할수 있다.


3. 1번에서 만든 dll / 2번에서 빌드한 swc, xml, swf 파일을 하나의 폴더에 복사한다.


4. C:\Users\User\Documents\flex_sdk_4.6\flex_sdk_4.6\bin\adt -package -target ane 생성될 ane파일명.ane extension.xml -swc 2번에서 생성한.swc -platform Windows-x86 1번에서 생선한.dll library.swf

5. 생성된 ane 파일을 Flex/AIR에서 프로젝트 properties - flex build packaging - native extensions에서 추가하면 해당 ane를 사용할수 있다.





by 무위자연 2014. 12. 11. 11:36

Visual C++.NET Programming Bible / 23장 C++와 COM 프로그래밍 / 삼양미디어

 

컴포넌트는 .dll이나 exe로 끝나는 파일이고 간혹 ocx 확장자를 가진 것도 내부적으로 dll와 동일한 것이다.

 

C++프로그래머 입장에서 보면 컴포넌트는 구조체의 포인터이다. 프로그래머는 이 포인터를 통해서 구조게가 가지고 있는 멤버함수에 접근할수 있다.

컴포넌트를 사용한다는 것은 구조체의 포인터를 통해 멤버함수를 호출한다는 것이다.

 

C++ 코드 상에서 컴포넌트를 생성하면 구조체의 포인터를 얻고 그 포인터를 통해서 구조체의 멤버함수에 접근할수 있다

컴포넌트가 제공하는 이러한 구조체를 인터페이스라고 한다. 모든 컴포넌트는 최소한 2개이상의 인터페이스를 반드시 제공해야 하고

프로그래머는 오직 인터페이스를 통해서만 컴포넌트에 접근 가능하다.

 

인터페이스는 다음과 같은 제약사항이 있다

  • 인터페이스는 자신의 멤버로 함수만 갖는다(변수를 멤버로 가질수 없다)
  • 인터페이스 내의 멤버 함수는 순수 가상 함수 형태로 선언되야 한다
  • 인터페이스의 멤버함수는 HRESULT라는 데이터 타입을 리턴해야 한다
  • 위와 같은 방법으로 정의된  인터페이스를 외부에 공표하면 절대로 바꾸면 안된다.

 

C++로 인터페이스를 정의한다는 것은 헤더파일에 구조체를 정의하고 그 속에 순수 가상함수를 선언하는 작업을 의미한다.

그리고 정의된 인터페이스를 구현한다는 것은 인터페이스를 상속 받는 클래를 만들고, 그 클래스를 통해 인터페이스가 가진 순수 가상함수를 구현한다는 것이다.

인터페이스의 정의와 구현은 별개이고 이것을 separation of interface from implementation이라 한다.

 

하나의 파일 안에는 여러 개의 컴포넌트가 들어 갈수 있고 하나의 컴포넌트안에는 여러개의 인터페이스가 들어갈수 있다.

 

COM 서브 시스템

클라이언트/서버 개념으로 볼때 컴포넌트는 서버이고, 이를 사용하는 애플리케이션은 클라이언트이다. COM 규약은 컴포넌트로부터 인스턴스, 즉 객체를 생성하는 방법을 규정하고 있는데

그 방법이 클라이언트가 CoCreateInstance라는 COM API 함수를 호출하는 것이다.

CoCreateInstance 함수는 매개변수로 컴포넌트 식별자와 인터페이스 식별자를 받아 컴포넌트 식별자와 일치하는 컴포넌트를 찾아 객체를 생성하고 인터페이스 식별자와 일치하는

인터페이스를 찾아 그에 대한 포인터를 리턴한다.

 

COM API는 컴포넌트 인스턴스를 생성하는 기본적인 함수 외에도 아양한 서비스를 제공하는 함수를 포함한다. 이렇게 API를 통해서 서비스를 제공할수 있는 것은 COM이 운영체제에

포함되어 일종의 서브 시스템으로 존재하기 떄문에 가능하다. app이 운영체제에서 제공되는 COM 서비스를 사용하기 위해서는 COM API가 들어 있는  라이브러리(이를  COM 라이브러리

라 한다)를 프로세스의 주소공간에 로드시키고 이를 초기화해 주어야 한다.

 

이러한 작업은 CoInitialize라는 API를 통해 이러우지고 클라이언트는 COM 서비스를 사용하기 전에 이를 반드시 호출한다. COM 라이브러리 초기화는 스레드와 밀접한 관련이 있다

만약 여러개의 쓰레드가 COM 서비스를 이용하고자 한다면 각각의 쓰레드는 개별적으로 CoInitialize 함수를 호출해서 COM 라이브러리를 초기화시켜주어야 한다. COM 서비스의 사용이 끝나면 각각의 쓰레드는 CoUninitialize 함수를 호출해서 쓰레드 별로 COM 라이브러리가 차지한 리소스를 풀어주어야 한다.

 

윈도우 운영체제가 모든 app이 메세지 펌프를 가지고 있든 전제하에 메세지를 통해 각종 서브 시스템과 app간듸 의사소통을 가능하게 한다. COM 서브 시스템은 컴포넌트의 프로세스가

기본적으로 메세지 펌푸를 가지고 있다는 전제하에 메세지를 통해 클라이언트와 컴포넌트간의 의사소통을 중재하게 된다.

 

컴포넌트 식별자

컴포넌트와 인터페이스는 자신을 식별하기 위해서 128비트 길이의 구조체를 사용하여 여기에 고유한 값을 넣고 자신의 식별자를 사용한다. 이 식별자는 지구상에서 유일하다는 뜻으로 GUID(Global Unique Identification)이라 한다. 새로운 GUID를 만들기위해서는 COM API 중에 CoCreateGUID 호출하거나 Guidgen.exe를 사용한다.

 

컴포넌트의 인스턴스를 생성하기 위해서는 CoCreateInstance 함수를 호출해야 하고 파라미터로 CLSID(컴포넌트 식별자)와 IID(인터페이스 식별자)를 전달한다.

컴포넌트와 관련된 정보는 루트키 중 HKEY_CLASSES_ROOT 밑에 있다. 여기에서 등록된 COM의 CLSID / IID를 볼수 있다

 

IUnknown  인터페이스

IUnknown 인터페이스는 모든 컴포넌트가 반드시 제공해야 하며, 다른 모든 인터페이스의 부모가 되는 인터페이스이다. 즉, 모든 인터페이스는 IUnknown 인터페이스를 상속받아야 한다.

그리고 IUnknwon의 세가지 메소드를 구현해야 한다

  • QueryInterface 함수는 인터페이스 식별자인 IID를 in 파라미터(클라이언트가 컴포넌트에게 전달하는 파라미터)로 받아서 이와 일치하는 인터페이스를 컴포넌트가 제공하는지 살펴보고 만약 제공한다면 그 인터페이스에 대한 포인터를 두번째 파라미터인 ppv out 파라미터(컴포넌트가 클라이언트에게 전달하는 파라미터)로 넘겨준다. IID를 조회(query)해서 일치하는 인터페이스의 포인터를 넘겨준다.
  • AddRef - 컴포넌트의 생명을 관리한다. 참조 카운트를 증가시킨다.
  • Release - 참조 카운트를 감소킨다. 참조카운트가   0이면 아무도 인터페이스를 사용하지 않는 것으로 보고 컴포넌트 스스로 소멸시켜야 한다.

     

IClassFactory

IUnknown 인터페이스와 마찬가지로 컴포넌트가 반드시 제공해야 하는 인터페이스다. 컴포넌트를 만드는 일을 한다. CoCreateInstance API를 호출하면 실질적으로 컴포넌트를 직접 생성하는 것이 아니라 IClassFactory 인터페이스를 얻은 다음에 이것을 이용해서 컴포넌트를 생성한다.

이 글은 스프링노트에서 작성되었습니다.

by 무위자연 2008. 10. 13. 12:14
사용자 삽입 이미지
사용자 삽입 이미지
사용자 삽입 이미지
사용자 삽입 이미지

RIA 월드.
by 무위자연 2008. 3. 20. 09:28
| 1 2 3 |