일단 이것땜에 숙제, 턴프로젝트, 할일등 모두 내 팽겨쳐 졌다.. orz

유니코드는 이 아래에서 긁어온 자료와 같이 여러 종류가 있다고 한다.

하지만 지금 중요한건 저 글자를 파일로 저장한뒤 온전하게 불러오는데 목적이 있다.

예제는 한줄경우 어떻게 처리가 되었지만, 몇백줄 넘어가는 자료를 저장하면 그 나름대로 테크닉이
필요하다.

데브 피아 등 여러곳을 돌아다니가 결국 잘못된곳을 찾아냈다..

다음은 J-Notebook 프로그램의 파일 저장 소스 일부분이다.

if(dlg.DoModal() == IDOK)
 {
  CFile file;
  CFileException e;
  if(!file.Open(dlg.GetFileName(), CFile::modeWrite | CFile::modeCreate, &e))
  {
   e.ReportError();
   return;
  }
  // 파일을 쓴다. 음... file.Write가 \n 이 자동으로 붙고, \r\n하면 한줄씩 내려준다.
  // 유니코드 시작
  WORD  a;
  a = 0xFEFF;
                                   <- 16진수 변환 프로그램을 보니, 제대로 읽히는 파일은 FFFE로 시작한다.
                                       하지만 FEFF로 넣었다.. 왜냐? 윈도우는 리틀 앤디안이기 떄문이라;;;
  file.Write((void*)&a, sizeof(a));
                                // 맨 처음부분에 넣어준다. 왜인지 모르겠지만 아무래도 유니코드 식별인자 인거 같다;;

  // 유니코드에서 한줄내림은 코드는 0x0a인듯 하다..
  a = 0x0A;
  JWord note;
  CString strWord;
 
  int i=0;
  for(; i < pDoc->m_szNoteWord.size()-1; i++)
  {
   note = pDoc->m_szNoteWord[i];
   strWord.Format(L"%s;%s;%s;%d\r",note.word, note.yomigana, note.mean, note.count);
   // 글자를 쓰고,
   file.Write(strWord, strWord.GetLength()* sizeof(wchar_t));
   // 이 글자의  유니코드식별자? 를 추가해준다.. 파일흐름상 개행라인인거 같다.
   file.Write((void*)&a, sizeof(a));

  }
  // 마지막은 개행할 필요가 없으므로 따로 써준다.
  note = pDoc->m_szNoteWord[i];
  strWord.Format(L"%s;%s;%s;%d",note.word, note.yomigana, note.mean, note.count);
  file.Write(strWord, strWord.GetLength()* sizeof(wchar_t));
 }

이짓을 해주면. CFile::typeText | CFile::modeRead 로 문제없이 읽어온다.

하지만... 유니코드... 이거 난해해서.. 괜한 지뢰밭 들어간건 아닌지 걱정된다.

  1. 오즈마스터™ 2008.01.25 15:03 신고

    0x0a 는 유니코드의 개행라인이라기보다 ANSI 였을때부터 개행라인으로 쓰던 코드입니다.

MFC
리스트뷰 컨트롤의 추가, 삭제, 수정, 검색 등

아주 기초적인 사용법에 대해 적어보고자 합니다.




이런식으로 전체적인 레이아웃을 잡고 시작한다고 봐야겠죠?

그리고 중요한 컨트롤의 컨트롤의 ID 의 값을 각각 아래와 같이 정하고 시작하겠습니다.




각각의 컨트롤에 대해서는 WM_COMMAND 메시지를 다루면 되겠죠.



추가



추가의 경우에는 지난번에 했던 방식 그대로

ListView_InsertItem 과 ListView_SetItemText 매크로를 이용하면 됩니다.


   li.mask=LVIF_TEXT;
   li.state=0;
   li.stateMask=0;
   
   idx=ListView_GetItemCount(hList);

   GetDlgItemText(hWnd,IDC_NAME,szName,255);
   GetDlgItemText(hWnd,IDC_SEX,szSex,255);
   GetDlgItemText(hWnd,IDC_ADDR,szAddr,255);


   li.iItem=idx;
   li.iSubItem=0;
   li.pszText=szName;


   ListView_InsertItem(hList,&li);
   ListView_SetItemText(hList,idx,1,szSex);
   ListView_SetItemText(hList,idx,2,szAddr);



그나마 지난번과 달라진건 컨트롤의 값을 읽어오는 GetDlgItemText 와

리스트 뷰의 아이템들의 수를 읽는 ListView_GetItemCount 가 추가된 것 밖에 없겠군요 ^^


int ListView_GetItemCount(HWND hWnd)


이게 원형입니다. sizeof 와 비슷하다고 보면 되겠군요.



삭제


삭제를 하기 위해서 사용되는 매크로는 아래와 같습니다.


int ListView_GetNextItem(HWND hWnd, int iStart, UINT flags);

BOOL ListView_DeleteItem(HWND hWnd, int iItem)


ListView_GetNextItem 의 첫번째 인수는 당연히 리스트의 핸들이고,

두번째는 어디서부터 찾을 것인가를 정하는 것입니다. -1 의 경우는

전체에서 찾는 것이고 주어지는 값에 따라 그 인덱스부터 차례로 찾아가는 것이죠.


리턴값이 int 형인데 이건 찾은 인덱스 값을 리턴합니다 ^^ 몇 번째 존재하는지를 리턴하죠.

세번째 인수는 Flags 값을 지정하는 것인데 LVNI_ALL | LVNI_SELECTED 를 보통 지정합니다.

왜 그런가 싶으면 LVNI_ALL 이나 LVNI_SELECTED 를 하나씩 삭제하여 컴파일해보면 알겠죠?


idx=ListView_GetNextItem(hList, -1, LVNI_ALL | LVNI_SELECTED);


이 경우는 만약 찾았을 경우에는 idx 의 값에는 해당 인덱스가 들어가겠지만,

찾기 실패하였을 경우에는 idx 에 -1 값이 들어갑니다.



   idx=ListView_GetNextItem(hList,-1,LVNI_ALL|LVNI_SELECTED);
   if(idx==-1)
        MessageBox(hWnd,"삭제할 아이템을 선택하세요","Error",MB_OK);
   else
   {
        while(idx!=-1)
        {
             ListView_DeleteItem(hList,idx);
             idx=ListView_GetNextItem(hList,idx-1,LVNI_ALL|LVNI_SELECTED);
        }
   }



여기서 중요한 것은 while 문의 ListView_GetNextItem 에 idx-1 이 들어간다는 것이죠.

선택된 아이템들을 하나씩 찾아서 지워주는 것이기 때문에 idx 보다 -1 된 것을 넣어야

차례로 지워나갑니다. idx  를 그대로 넣어준다면 무슨 일이 일어나는지는 직접 해보시면 압니다.


선택된 아이템들이 전부 삭제가 되지 않겠죠;



수정


수정은 추가와 비슷하여 상당히 쉽습니다. 다만 ListView_InsertItem 매크로 대신

ListView_SetItem 을 통하여 재설정을 해줘야 합니다. 아주 조금 추가와 다를 뿐,

기본 방식은 같습니다.



   idx=ListView_GetNextItem(hList,-1,LVNI_ALL|LVNI_SELECTED);

   if(idx==-1)
        MessageBox(hWnd,"수정할 아이템을 선택하세요","Error",MB_OK);
   else
   {
        GetDlgItemText(hWnd,IDC_NAME,szName,255);
        GetDlgItemText(hWnd,IDC_SEX,szSex,255);
        GetDlgItemText(hWnd,IDC_ADDR,szAddr,255);


        li.iItem=idx;
        li.iSubItem=0;
   
        ListView_SetItem(hList,&li);
        ListView_SetItemText(hList,idx,0,szName);
        ListView_SetItemText(hList,idx,1,szSex);
        ListView_SetItemText(hList,idx,2,szAddr);
   }



보시면 아시겠지만 일단 선택된 것을 찾아서 idx 에 그 인덱스 값을 넣어줍니다.

만약 선택되지 않았다면 Error 메시지박스가 뜨겠죠. 이제 LVITEM 구조체인

li 의 iItem 에 idx 값을 지정하고 iSubItem 멤버에도 첫번째 컬럼을 의미하는 0을 지정한 뒤


ListView_SetItem 으로 li 를 hList 에 설정합니다.

일단 내가 몇 번째 리스트 뷰 아이템을 설정한다고 알려주는 것이죠.


그런 뒤 ListView_SetItemText 매크로를 통하여 수정해주면 됩니다 ^^



검색



다행히 검색을 할 때도 편리하게(?) 매크로가 존재합니다.


int ListView_FindItem(HWND hWnd, int iStart, const LPLVFINDINFO plvfi);


여기서 중요한건 LVFINFO 구조체가 들어가는데요, 이건 검색의 조건으로


typedef struct tagLVFINDINFO {
    UINT flags;
    LPCTSTR psz;
    LPARAM lParam;
    POINT pt;
    UINT vkDirection;
} LVFINDINFO, *LPFINDINFO;


flags 멤버로 중요한건


LVFI_STRING    psz 멤버가 지정하는 문자열과 일치하는 텍스트를 가진 항목을 검색

LVFIN_WRAP    검색 대상이 발견되지 않을 경우 처음부터 다시 검색


이 두 개 정도로만 봐도 가장 기초적인 곳에서는 사용할 수 있습니다.

그리고 vkDirection 이라는 특이한 멤버가 존재하는데요,

이건 VK_LEFT , VK_DOWN, VK_HOME 등 가상 키를 넣어주는겁니다.


대게 VK_DOWN 을 설정하는 편이라는군요.



   LVFINDINFO fi;

   GetDlgItemText(hWnd,IDC_NAME,szName,255);


   fi.flags=LVFI_STRING;
   fi.psz=szName;
   fi.vkDirection=VK_DOWN;

   idx=ListView_FindItem(hList,-1,&fi);


   if(idx==-1)
        MessageBox(hWnd,"검색된 아이템이 없습니다","Error",MB_OK);
   else
   {
        ListView_SetItemState(hList,-1,0,LVIS_FOCUSED|LVIS_SELECTED);
        ListView_SetItemState(hList,idx,LVIS_FOCUSED|LVIS_SELECTED,0x000F);
        ListView_EnsureVisible(hList,idx,FALSE);
   }



이렇게 IDC_NAME 의 값을 읽어와 psz 에 설정한 후 ListView_FindItem 매크로에서 찾아주면 되네요.

ListView_FindItem 에서 -1 은 가장 처음에서 찾는, 전체에서 찾는다는 의미죠. 같은 문자열로 찾기를

계속 이어주려면 idx-1 값으로 루프를 돌려주면서 찾으면 되겠군요 ^^


찾았을 경우 ListView_SetItemState 로 상태를 설정해줘야하는데요.


ListView_SetItemState(hList,-1, 0,LVIS_FOCUSED|LVIS_SELECTED);

ListView_SetItemState(hList,idx,LVIS_FOCUSED|LVIS_SELECTED,0x000F);


이 두개가 왜 존재할까요? -1은 전체를 의미하고, 0은 상태를 없앤다고 보면 되죠.

일단 리스트 뷰에 어떤 항목들이 선택되어있거나 한다면 리플래시를 시켜 없앱니다.


그게 바로 ListView_SetItemState(hList,-1, 0,LVIS_FOCUSED|LVIS_SELECTED) 입니다.

그리고 나서 찾은 idx 번째의 리스트 뷰의 아이템을 선택해야하는데요, 그게 바로 두 번째인


ListView_SetItemState(hList,idx,LVIS_FOCUSED|LVIS_SELECTED,0x000F);


입니다. 마지막 인수가 16진수로 되어있지만 이것도 역시 아래와 같이 바꿀 수 있습니다.


ListView_SetItemState(hList,idx,LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED);


여기까지가 가장 기초적인(?) 방법이었네요.

사실상 개인적으로 시간이 많이 먹었던 부분이예요.


좀더 자세한건 소스 첨부 했으니 참고하시면 되구요 ^^;

다음엔 WM_NOTIFY 에 해당되는 리스트 뷰의 메시지 관리를 적어보겠습니다.

출처 : http://cafe.naver.com/seen/131

MFC
출처 : http://blog.naver.com/epicros/10018002323

MFC 클래스간 통신

SDI 형태
1.     MainFrame 얻기
-          CMainFrame *pFrame = (CmainFrame *) AfxGetMainWnd();

2.     App 포인터 얻기
-          CTestApp *pApp = (CtestApp *) AfxGetApp();

3.     Document 포인터 얻기
-          CMainFrame *pFrame = (CMainFrame *)AfxGetMainWnd();
    CTestDoc *pDoc = (CTestDoc *)pFrame->GetActiveDocument();
-          CTestDoc *pDoc = ((CMainFrame *)AfxGetMainWnd())->GetActiveDocument();

4.     View 포인터 얻기
-          CMainFrame *pFrame = (CMainFrame *)AfxGetMainWnd();
     CTestView *pView = (CTestView *)pFrame->GetActiveView();
-          CTestView *pView = ((CMainFrame *)AfxGetMainWnd())->GetActiveView();


MDI 형태
1.     ChildFrame 포인터 얻기
-          CMainFrame *pFrame = (CMainFrame *)AfxGetMainWnd();
    CChildFrame *pChild = (CChildFrame *)pFrame->GetActiveFrame();
-          CChildFrame *pChild = ((CMainFrame *)AfxGetMainWnd())->GetActiveFrame();

2.     Document 포인터 얻기
-          CMainFrame *pFrame = (CMainFrame)AfxGetMainWnd();
    CChildFrame *pChild = (CChildFrame *)pFrame->GetActiveFrame();
    CMdiTestDoc *pDoc = (CMdiTestDoc *)pChild->GetActiveDocument();
-          CMdiTestDoc *pDoc = (((CMainFrame *)AfxGetMainWnd())->GetActiveFrame())->GetActiveDocument();

3.     View 포인터 얻기
-          CCainFrame *pFrame = (CMainFrame)AfxGetMainWnd();
    CChildFrame *pChild = (CChildFrame *)pFrame->GetActiveFrame();
    CMdiTestView *pView = (CMdiTestDoc *)pChild->GetActiveView();
-          CMdiTestView *pView = (((CMainFrame *)AfxGetMainWnd())->GetActiveFrame())->GetActiveView();


출처 - 뿌리깊은 나무

출처: http://www.javalinux.co.kr/study/windows/

1. Non-MFC DLL

1.1 Basis

1.1.1 Features

n         내부적으로 C++ 클래스를 사용할 수 있고, C 함수 Wrapper만을 Export 할 수 있다. 따라서 내부적인 C++ Class에 대한 변경은 DLL의 호출에 영향을 주지 않는다.

n         MFC를 사용할 수 없으며, 별도의 MFC Library가 필요없다.

n         DLL을 사용하는 Client는 DLL 호출을 지원하는 어떠한 Language로 작성될 수 있다.

n         AppWizard를 이용하여 자동으로 Project를 생성할 수 있다.

1.1.2 Function Export

DLL 내에서 정의된 Function을 export하기 위해서는 __declspec(dllexport) 를 사용한다. __declspec MS만의 C, C++의 확장된 syntax로서, 확장된 storage-class 정보를 정의한다. dllexport storage-class의 한 속성으로, DLL의 Function, Data, Object를 export할 수 있도록 하여준다. 반대로 DLL내의 Function을 import하기 위해서는 dllimport 속성을 사용한다. Win32 환경에서는 Function Export/Import를 위하여 이것을 이용하며, Win32 이전의 Windows 환경에서 사용되던 module-definition file (.DEF)을 사용하지 않는다. 단, VB와 호환가능한 DLL을 제작하는 경우, module-definition file을 사용하도록 한다.

· export / import

함수 export/import를 위하여 아래와 같이 함수를 선언한다. Coding의 편의를 위하여 export선언을 #define으로 간략화시킨다.

#define DLLImport  __declspec(dllimport)

#define DLLExport  __declspec(dllexport)

DLLExport void somefunc();

· export/import Tips

위 방법으로 export/import 함수를 정의하면, DLL 내에서의 함수 정의와 DLL을 사용하는 Client에서의 함수정의를 다르게 해야 하는 불편이 생긴다. DLL과 Client에서 동일한 Header File을 사용할 수 있도록 하기 위하여 아래와 같이 export/import 함수를 정의한다.

#ifdef DLLTEST_EXPORTS

#define DLLFunction  __declspec(dllexport)

#elseif

#define DLLFunction  __declspec(dllimport)

#endif

DLLFunction void somefunc();

DLLTEST3_EXPORTS 은 DLL의 Project Settings에 Preprocessor definitions에 프로젝트명_EXPORTS의 형식으로 정의 되어 있다. 따라서 DLL Project에서는 export로, Client Project에서는 import로 동작한다.

· Adjusting Naming Convention

C++은 C와 다른 Naming Convention을 사용한다. 따라서 export되는 함수명은 Compile시에 기존의 정의한 이름과 다르게 해석된다. 따라서 Naming Convention에 대한 조정과정이 없으면, export된 함수는 C++ 이외의 Language로 작성되는 프로그램에서는 호출될 수 없다. extern C는 함수가 C naming convention을 사용하도록 만들어주며, 이를 통하여 C++로 작성되어 export되는 함수를 다른 Language에서도 사용가능하도록 하여 준다. VC는 기본적으로 프로젝트생성시에 C++을 사용하도록 구성되므로 모든 export함수는 Naming Convention의 조정이 필요하다.

#ifdef _USRDLL

#define DLLFunction  __declspec(dllexport)

#elseif

#define DLLFunction  __declspec(dllimport)

#endif

#ifdef __cplusplus

extern C {

#endif

DLLFunction void somefunc();

#ifdef __cplusplus

}

#endif

· Adjusting Calling Convention

Visual Basic은 C와 다른 Calling Convention을 사용하므로 Visual Basic에서 사용될 DLL을 작성하는 경우, 이를 조정해주어야 한다. VC는 기본적으로 __cdecl 방식을 사용하며, VB는 __stdcall 방식을 사용한다. 따라서 Project Settings에서 C/C++ Tab의 Code Generation Category를 선택하여 Calling Convention을 __stdcall로 설정한다. 또한 module-definition file(.Def)을 작성하여 프로젝트에 포함시킨다. VC로 작성한 DLL을 VB에서 사용하는 경우, Calling Convention이 틀린다는 에러가 발생하거나 Run 시에 다운되는 현상을 자주 볼 수 있는데, 이는 모두 Calling Convention을 조정과정을 거치지 않아서 발생하는 문제이다.

testdll.def

LIBRARY              "TESTDLL.DLL"

DESCRIPTION 'SIMPLEDLL Windows Dynamic Link Library'

EXPORTS

   somefunc   @1

1.2 Making DLL

1.2.1 Object

간단한 DLL을 만들기 위하여 아래와 같은 두가지의 기능만을 가지는 DLL을 만들기로 한다.

n         int 형의 두 숫자를 parameter로 받아 그 합을 return하는 함수

n         두개의 string을 받아 연결된 string을 넘겨주고, 그 총 길이를 return하는 함수

1.2.2 Implementation

n       아래와 같이 Win32 Dynamic-Link Library를 선택하여 Project를 생성한다.

n       App-Wizard에서 아래와 같이 A simple DLL Project를 선택한다. 이는 간단한 DLLMain 함수를 자동으로 생성하여 준다.



n       export할 함수의 정의를 위하여 Header File을 생성한다. 이는 후에 import 측에서도 공용으로 사용될 것이다. SimpleDll.h의 이름으로 Header를 생성하고, 두개의 함수를 위한 함수정의를 만든다.

SimpleDll.h

#ifndef __SIMPLEDLL_H__

#define __SIMPLEDLL_H__

 

#ifdef SIMPLEDLL_EXPORTS

   #define DLLFunction  __declspec(dllexport)

#else

   #define DLLFunction  __declspec(dllimport)

#endif

 

extern "C" {

 

DLLFunction int addint(int n1, int n2);

DLLFunction int addchar(char* s1, char* s2, char* added);

 

}

 

#endif //__SIMPLEDLL_H__

 

n       선언한 함수에 대하여 기능을 작성한다. 두 함수는 단지 int형과 char형의 더하기 만을 지원하므로 아래와 같이 함수를 작성한다.

SimpleDll.cpp

#include "stdafx.h"

#include "stdio.h"

#include "SimpleDll.h"

 

BOOL APIENTRY DllMain( HANDLE hModule,

                       DWORD  ul_reason_for_call,

                       LPVOID lpReserved

                                       )

{

    return TRUE;

}

 

DLLFunction int addint(int n1, int n2)

{

   return n1 + n2;

}

 

DLLFunction int addchar(char* s1, char* s2, char* added)

{

   sprintf(added, "%s%s", s1, s2);

   return strlen(added);

}

 

1.3 Using DLL

위에서 작성한 Code를 Compile하여 SimpleDll.dll 파일을 얻는다. 이것을 Test하기 위하여 VC++ 및 VB에서 DLL내의 함수를 호출하는 기능을 작성한다.

 

1.3.1 Using DLL with VC++ (Link Implicitly)

Dialog-Based Project를 생성하여 아래와 같은 순서로 DLL의 함수를 호출하는 기능을 작성한다.

 

n       SimpleDll.h를 복사하여 프로젝트에 추가한다.

n       Project-Settings 메뉴를 선택하여 Project Settings 화면을 열어, Link Tab의 library modules에 SimpleDll.lib를 추가한다. SimpleDll.lib 파일은 VC++의 환경설정의 Directories에 존재하는 폴더 또는 Project 폴더에 복사하도록 한다.

 

n       Dialog를 다음과 같이 Design하고 각 컨트롤에 멤버변수를 추가한다.

 

 

 

 

 

 

n       DLL 함수를 호출할 Button에 대한 Handler를 작성한다.

SimpleDllTestDlg.cpp

#include "SimpleDll.h"

 

void CSimpleDllTestDlg::OnAddint()

{

   UpdateData(TRUE);

   m_nSumInt = addint(m_nInt1, m_nInt2);

   UpdateData(FALSE);

}

 

void CSimpleDllTestDlg::OnAddchar()

{

   char s1[9];

   char s2[9];

   char sSum[17];

 

   UpdateData(TRUE);

 

   lstrcpy(s1, (LPCTSTR)m_sChar1);

   lstrcpy(s2, (LPCTSTR)m_sChar2);

 

   addchar(s1, s2, sSum);

 

   m_sSumChar = sSum;

   UpdateData(FALSE);

}

 

위의 방법으로 DLL 함수를 호출하는 프로그램을 작성하여 실행하면 각 함수들이 정확하게 호출되고 있음을 확인할 수 있다.

 

 

1.3.2 Using DLL with VC++ (Link Explicitly)

Explicit Link를 사용하여 DLL 함수를 호출하는 경우, Header 파일과 Library 파일은 필요하지 않다. 단지 그 함수의 원형만을 알고 있으면 된다. Explicit Link를 사용하기 위하여 아래와 같은 순서로 DLL 함수를 호출하는 기능을 작성한다.

 

n       1.3.1에서와 같이 Dialog-Based Project를 생성한 후, 같은 모양으로 Dialog를 Design하고 멤버변수를 연결한다.

 

n       DLL 함수호출을 위한 Button의 Handler를 만들고 아래와 같이 코드를 작성한다.

SimpleDllTest2Dlg.cpp

void CSimpleDllTest2Dlg::OnAddint()

{

   int (*lpfnAddInt)(int, int);

   HINSTANCE hLib = LoadLibrary("SimpleDll.dll");

   if(hLib == NULL)

            return;

 

   lpfnAddInt = (int(*)(int, int))GetProcAddress(hLib, "addint");

   if(lpfnAddInt == NULL)

   {

            FreeLibrary(hLib);

            return;

   }

 

   UpdateData(TRUE);

   m_nSumInt = lpfnAddInt(m_nInt1, m_nInt2);

   UpdateData(FALSE);

 

   FreeLibrary(hLib);

}

 

위와 같이 LoadLibrary를 이용하여 Explicit Link로 DLL 함수를 호출하도록 하면, 별도의 Library와 Header가 필요하지 않으며, 실행 시간에 DLL의 Load와 Unload의 시점을 결정할 수 있는 장점이 있다.

 

 

1.3.3 Using DLL with VB

VB에서는 DLL의 함수 호출이 매우 간단하다. 단지 어떤 Library의 어떤 함수를 사용할 것인지에 대한 선언만 정확이 명시하면 된다. 아래와 같이 addintaddchar 함수를 선언한다.

test.mod

Public Declare Function addint

Lib "SimpleDll.dll" (ByVal n1 As Long, ByVal n2 As Long) As Long

Public Declare Function addchar

Lib "SimpleDll.dll" (ByVal s1 As String, ByVal s2 As String, ByVal sum As String) As Long

 

함수선언 후, 실행을 위한 Handler에서 아래와 같이 호출한다.

Private Sub cmdAddStr_Click()

    Dim sum As String * 32

    addchar txtInt1, txtInt2, sum

    txtSum = sum

End Sub

 

Private Sub cmdCall_Click()

    Dim n1, n2, sum As Long

    n1 = CLng(txtInt1)

    n2 = CLng(txtInt2)

   

    sum = addint(n1, n2)

    txtSum = CStr(sum)

End Sub

VB로 작업시 char* Type에 대한 Parameter를 넘길 때, 반드시 그 크기를 지정하여야 한다. VB는 그 값이 지정될 때, 메모리가 할당되므로 함수 호출 이전에 값을 지정하거나 위 코드의 sum 변수에서처럼 그 크기를 미리 지정하여야 한다.

www.codein.co.kr  프로그래머의 놀이터 Code人

+ Recent posts