1. 버튼

 case WM_CREATE:

  CreateWindow(TEXT("button"), TEXT("click"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON ,20,20,100,25, hWnd

                        (HMENU)0, g_Inst, NULL);

  return 0;

 case WM_COMMAND:

  switch(LOWORD(wParam))

   case 0:

    MessageBox(hWnd, Text("clicked"), "TEXT(button)", MB_OK);

    break;

  return 0;

버튼 컨트롤 사용 방식이다.. 윈도우 생성시 버튼을 만든 것이고, 버튼이 클릭되었을때 메시지박스를 띄우는 것이다.

CreateWindow(만들윈도우클래스, 윈도우제목, 스타일, 좌표,좌표,좌표,좌표, 부모윈도우, 아이디값, 윈도우인스턴스핸들, MDI사용될 구조체);

 스타일을 살펴보면 차일드라는 속성이 사용되었다. 이것은 메인 윈도우가 만들어지면 그안에 포함되는 컨트롤인 된다는 것이다.

 비지블은 보여준다, 푸쉬버튼 누른다. 라는 의미이다.

 자식윈도우로 지정을 했으면 부모의 핸들을 부모윈도우 자리에 넣어주면 되고 아이디 값을 그 버튼을 눌렀을때 wParam으로 넘어가는 값을 말한다.. 커맨드에선 하이워드의 wParam을 조사하여 그에 해당하는 코드를 넣어주면 된다.



2. 체크 박스

 생성방식은  위와 동일 하다..

static HWND c1;    // 체크박스 핸들저장,,, (체크 확인여부위해서)

static bool draw = false;  // 그림을 그릴것인가에 대한 변수

RECT rt;

GetClientRect(hWnd, &rt);   //현제 윈도우 클라이언트 영역을 얻어온다


case WM_CRATE:

 c1 = CreateWindow("button", "checkbox", WS_CHILD | WS_VISIBLE | BS_CHECKBOX, 20, 20, 160, 25, hWnd, (HMENU)1, g_hInst, NULL) ;   //수동체크박스 생성, 자동으로 하려면    BS_AUTOCHECKBOX로 변경한면 된다

break;


case WM_COMMAND:

 switch(LOWORD(wParam))

  case 1 :

   if(SendMessage(c1, BM_GETCHECK, 0, 0) == BST_UNCHECKED)  //센드메시지는 전에 보았다.. 찾아봐라
   {                          //체크 확인 메시지            // 체크 되있지 않다면
    draw = TRUE;
    SendMessage(c1, BM_SETCHECK, BST_CHECKED, 0); // 체크박스로 다시 보내 체크 하도록 요구한다
   }                          // 변경               // 체크상태
   else
   {
    draw = false;
    SendMessage(c1, BM_SETCHECK, BST_UNCHECKED, 0);
   }                                                   //비체크상태
   InvalidateRect(hWnd, &rt, true);   //이것도 전에 보았다.
   break;

인자는 동일하다,,,, 굳이 설명할 필요가 없다 체크 메시지와 체크 상수만 알아보겠다.

 BM_GETCHECK  체크상태를 조사.. 리턴값으로 돌려진다
 BM_SETCHECK  체크상태 변경... wParam에 변경할 상태를 지정
 BST_UNCHECKED  체크안됨
 BST_CHECKED  체크됨
 BST_INDETERMINATE  아무것도 아닌상태


3. 라디오 버튼

체크박스 생성방법과 동일하다 다만, 생성할 때 3번째 인자..

즉, 속성을 BS_RADIOBUTTON 이나 BS_AUTORADIOBUTTON으로 변경해봐라...

일반과 오토의 차이점은 체크상태를 스스로 변경하는가, 그렇제 않는가의 차이이다..


4. 에디트

 문자열을 입력받을때 사용하는 컨트롤이다...

#define ID_EDIT 100


 CHAR str[128];

 HWND hEdit;     //에디트 컨트롤을 담을 핸들


case WM_CREATE:

 hEdit = CreateWindow("edit", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL, 10, 10, 200, 25, hWnd, (HMENU)ID_EDIT, g_hInst, NULL);

 return 0;


case WM_COMMAND:

 switch(LOWORD(wParam))

  case ID_EDIT:

   switch(HIWORD(wParam))   //하이워드에서 문자열 변경상태를 파악한다

    case EN_CHANGE    // 변경되었다면

     GetWindowText(hEdit, str, 128);  // 에디트 핸들에 써진것을 가져와서

     SetWindowText(hWnd,str);    // 윈도우 캡션바 이름을 바꾼다

별로 특별한 것은 없다.  스타일과 메시지에 대해서만 간단히 알아보겠다

 ES_AUTO(H),(V)SCROLL  H는 수평, V는 수직 스크롤바가 생긴다
 ES_MULTILINE  여러 줄을 편집
 ES_READONLY  읽기전용으로 만든다


 EN_CHANGE  문자열이 변경되었을때
 EN_(H), (V)SCROLL  H는 수평바 클릭시, V는 수직바 클릭시
 EN_(KILL), (SET)FOCUS  KILL은 포커스를 잃었을때, SET은 포커스를 얻었을때
 EN_UPDATE  문자열이 변경되기 직전....


5. 리스트 박스

 #define ID_LISTBOX 100

 CHAR str[128];

 HWND hListbox;     //에디트 컨트롤을 담을 핸들

 int i;


case WM_CREATE:

 hListbox = CreateWindow("listbox", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | LBS_NOTIFY, 10, 10, 200, 250, hWnd, (HMENU)ID_LISTBOX, GetModuleHandle(0), NULL);
   SendMessage(hListbox, LB_ADDSTRING, 0, (LPARAM)"aaa");   //문자열 추가, 엘파람 으로 문자가 넘어간다.
   SendMessage(hListbox, LB_ADDSTRING, 0, (LPARAM)"BBB");  //문자열 추가

 return 0;

case WM_COMMAND:

 switch(LOWORD(wParam))

  case ID_LISTBOX:

   switch(HIWORD(wParam))   //하이워드에서 리스트 선택  상태를 파악한다

    case LBN_SELCHANGE    // 변경되었다면

     i = SendMessage(hListbox, LB_GETCURSEL, 0, 0);   //현제 몇번째 셀인지 조사한다      

    //구현하고 싶은 내용

사용 방식이 거의 동일하다... 역시 속성과 메시지만 알아보겠다..

 LBS_MULTIPLESEL  여러개의 항목을 선택할 수 있다
 LBS_NOTIFY  목록중 하나를 선택했을때 부모 윈도우로 메시지를 날린다
 LBS_SORT  항목을 정렬한다
 LB_(ADD), (DELETE) STRING  add는 문자열 추가, delete는 문자열 삭제
 LB_GETCURSEL  현재 선택된 항목의 번호를 얻어온다
   



6. 콤보박스

 리스트박스와 거의 동일하다... 바뀌는 부분말 말하겠다..

 listbox 부분을 combobox로 바꾸어준다... 속성을 CBS_DROPDOWN 으로 바꾸어 준다. 센드 메시지 안을 LB(리스트박스)에서 CB(콤보박스)로 바꾸어 준다.. 이러면 생성이 된다..

 

 case WM_COMMAND:

 switch(LOWORD(wParam))

  case ID_LISTBOX:

   switch(HIWORD(wParam))   //하이워드에서 리스트 선택  상태를 파악한다

    case CBN_SELCHANGE:    // 변경되었다면

     i = SendMessage(hListbox, CB_GETCURSEL, 0, 0);   //현제 몇번째 셀인지 조사한다      

    //구현하고 싶은 내용

    case CBN_EDITCHANGE:

     //구현하고 싶은 내용


난 간단히 하기 위해서 메시지 박스로 확인을 해봤다..


7. 스크롤 바

지금까지 컨트롤과는 조금 다르다..일단 생성은 동일하다

listbox 부분을 scrollbar로 바꾸어준다... 속성을 SBS_HORZ 으로 바꾸어 준다.  ID값 변경은 센스다.

생성한 후 다음 코드를 입력 한다.

 case WM_CREATE:

  //생성코드


  SetScrollRange(hScroll, SB_CTL, 0, 255, TRUE);  // 스크롤바 범위 셋팅

                                                                     //첫번째 스크롤바핸들, 두번째 별도의 컨트롤 지정하겠다는 의미

                                                                  //세번째 최소값,  네번째 최대값, 다섯번째 화면 재 출력여부

  SetScrollPos(hScroll, SB_CTL, 0, TRUE);   //스크롤바 스크롤의 초기 위치 지정

                                                              //나머진 동일하도 3번째가 초기 위치가 된다.

  return 0;

case WM_HSCROLL:
 if ((HWND)lParam == hRed) TempPos = Red;
  switch (LOWORD(wParam)) {
   case SB_LINELEFT:
    TempPos=max(0,TempPos-1);
    break;
   case SB_LINERIGHT:
    TempPos=min(255,TempPos+1);
    break;
   case SB_PAGELEFT:
    TempPos=max(0,TempPos-10);
    break;
   case SB_PAGERIGHT:
    TempPos=min(255,TempPos+10);
     break;
   case SB_THUMBTRACK:
    TempPos=HIWORD(wParam);
     break;
}
if ((HWND)lParam == hRed) Red=TempPos;

SetScrollPos((HWND)lParam,SB_CTL,TempPos,TRUE);
InvalidateRect(hWnd,NULL,FALSE);
return 0;


8. 스태틱

 간단한 컨트롤이다.... 에디트랑 비슷하며.... 글을 쓰는것이 아니라 저장된 글을 그냥 출력만 시키는 컨트롤이다..

CteateWindow("static", "넣고싶은텍스트", WS_CHILD | WS_VISIBLE, 20, 20, 120, 25, hWnd, (HMENU)-1, g_hInst, NULL);


Posted by 나비:D
:

● 컨트롤을 윈도우에 그려질려면 CreateWindow() 함수를 호출 해야한다.


CreateWindow() 함수


CreateWindow( "만들 컨트롤", "컨트롤에 나타날 문자", 컨트롤 속성, 시작할 X좌표, 시작할 Y좌표,

           , 컨트롤 폭, 컨트롤 높이, 나타낼 윈도우 핸들, (HMENU) 컨트롤 ID

           , 컨트롤을 만드는 인스턴스의 핸들 , 사용자 정의 데이터);


ex)

※ 버튼 생성

HWND hButton;


hButton = CreateWindow("button","Click",WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON

             , 20, 20, 100, 25, hWnd, (HMENU)0, g_hInst, NULL);


※ 에디트박스 생성

HWND hEdit;


hEdit = CreateWindow("eidt", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER

          | ES_AUTOHSCROLL, 10, 10, 200, 25, hWnd, (HMENU)ID_EDIT, g_hInst, NULL);


※ 리스트 박스 생성

HWND hList;


hList = CreateWindow("listbox", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER

          | LBS_NOTIFY, 10, 10, 100, 200, hWnd, (HMENU)ID_LISTBOX, g_hInst, NULL);


※ 컴보 박스 생성

HWND hCombo;


hCombo = CreateWindow("combobox", NULL, WS_CHILD | WS_VISIBLE | CBS_DROPDOW

               , 10, 10, 100, 200, hWnd, (HMENU)ID_COMBOBOX, g_hInst, NULL);


※ 스크롤 바 생성

HWND hScroll;


hScroll = CreateWindow("scrollbar", NULL, WS_CHILD | WS_VISIBLE | SBS_HORZ

             , 10, 10, 200, 20, hWnd, (HMENU)ID_SCROLL, g_hInst, NULL);


※ 스태틱 생성

HWND hStatic;


hStatic  = CreateWindow("static", "Only Text", WS_CHILD | WS_VISIBLE

              , 10, 10, 100, 24, hWnd, (HMENU)-1, g_hInst, NULL);


Posted by 나비:D
:

[출처] 다양한 형변환|작성자 삼돌이



Environment: Compiled using VC6.0 Sp3 and tested using Win95/98 WinNT4.0 and Win 2000
Here are a few data Conversions with small examples :-



########################################################################

PART ONE :- DECIMAL CONVERSIONS
########################################################################

Decimal To Hexa :-
Use _itoa( ) function and set radix to 16.

char hexstring[10];
int number = 30;
itoa( number, hexstring, 16);



In hexstring is 1e.

Hexa To Decimal :-
a)You can use strtol function and you can specify base.

char * hexstring= "ABCDEF";
char * p;
int number = strtol(hexstring, &p,16);



b) Or you can use this too

bool HexToDecimal (char* HexNumber, int& Number)
{
char* pStopString;
Number = strtol (HexNumber, &pStopString, 16);
return (bool)(Number != LONG_MAX);
}



Decimal to Time :-

char *DecToTime(float fTime, char *szTime)
{
int nHrs, nMin, nSec;
fTime *= 3600;
nHrs = (int)fTime / 3600;
nMin = (int)(fTime - nHrs * 3600) / 60;
nSec = (int)(fTime - nHrs * 3600 - nMin * 60);
wsprintf(szTime, "%02d.%02d.%02d Hrs.Min.Sec.", nHrs, nMin, nSec);
return szTime;
}



########################################################################

PART TWO :- STRING CONVERSIONS

########################################################################
String to Hexa :-

sscanf(string, %04X, &your_word16);
// where string = your string and 04 = length of your string and X = hex


Hex to CString :-
CString Str;
unsigned char Write_Buff[1];
Write_Buff[0] = 0x01;
Str.Format("0x0%x",Write_Buff[0]);


COleVariant to CString :-
CString strTemp;
COleVariant Var;
Var = "FirstName";
strTemp = Var.bstrVal;
AfxMessageBox(strTemp);


CString to Char Pointer :-
a) CString MyString = "ABCDEF";
char * szMyString = (char *) (LPCTSTR) MyString;



b) char *pBuffer = new char[1024];
CString strBuf = "Test";
pBuffer = strBuf.GetBuffer(sizeof(pBuffer));



Char Pointer to CString :-
char * mystring = "12345";
CString string = mystring;


Double to CString including the fractional part :-
CString strValue,strInt, strDecimal;
int decimal,sign;
double dValue = 4.125;
strValue = _fcvt(dValue,6,&decimal,&sign);

// Now decimal contains 1 because there is only one digit before the .

strInt = strValue.Left(decimal); // strInt contains 4
strDecimal = strValue.Mid(decimal); // strDecimal contains 125

CString strFinalVal;
strFinalVal.Format("%s.%s",strInt,strDecimal); // strFinalVal contains 4.125



Double To CString :-
CString strValue;
int decimal,sign;

double dValue = 123456789101112;
strValue = _ecvt(dValue,15,&decimal,&sign);


CString To Double :-
strValue = "121110987654321";
dValue = atof(strValue);


CString to LPCSTR :-
CString str1 = _T("My String");
int nLen = str1.GetLength();
LPCSTR lpszBuf = str1.GetBuffer(nLen);
// here do something with lpszBuf...........
str1.ReleaseBuffer();


CString to LPSTR :-
CString str = _T("My String");
int nLen = str.GetLength();
LPTSTR lpszBuf = str.GetBuffer(nLen);
// here do something with lpszBuf...........
str.ReleaseBuffer();

CString to WCHAR* :-
CString str = "A string here" ;
LPWSTR lpszW = new WCHAR[255];

LPTSTR lpStr = str.GetBuffer( str.GetLength() );
int nLen = MultiByteToWideChar(CP_ACP, 0,lpStr, -1, NULL, NULL);
MultiByteToWideChar(CP_ACP, 0, lpStr, -1, lpszW, nLen);
AFunctionUsesWCHAR( lpszW );
delete[] lpszW;



LPTSTR to LPWSTR :-
int nLen = MultiByteToWideChar(CP_ACP, 0, lptStr, -1, NULL, NULL);
MultiByteToWideChar(CP_ACP, 0, lptStr, -1, lpwStr, nLen);



string to LPCTSTR :-

std::string strTemp;

LPCTSTR lpName = strTemp.c_str();


string to BSTR :-
string ss = "Girish";
BSTR _bstr_home = A2BSTR(ss.c_str());


CString to BSTR :-
CString str = "whatever" ;
BSTR resultsString = str.AllocSysString();


_bstr_t to CString :-

#include
#include
_bstr_t bsText("Hai Bayram");
CString strName;
W2A(bsText, strName.GetBuffer(256), 256);
strName.ReleaseBuffer();
AfxMessageBox(strName);

char szFileName[256];
GetModuleFileName(NULL,szFileName,256);
AfxMessageBox(szFileName);



########################################################################

PART THREE :- CHARACTER ARRAYS

########################################################################

Char array to integer
char MyArray[20];
int nValue;

nValue = atoi(MyArray);



Char array to float
char MyArray[20];
float fValue;

fValue = atof(MyArray);


Char Pointer to double :-
char *str = " -343.23 ";
double dVal;
dVal = atof( str );


Char Pointer to integer :-
char *str = " -343.23 ";
int iVal;
iVal = atoi( str );



Char Pointer to long :-
char *str = "99999";
long lVal;
lVal = atol( str );


Char* to BSTR :-
char * p = "whatever";
_bstr_t bstr = p;

Float to WORD and Vice Versa :-
float fVar;
WORD wVar;
fVar = 247.346;
wVar = (WORD)fVar; //Converting from float to WORD. The value in wVar would be 247
wVar = 247;
fVar = (float)fVar; //Converting from WORD to float. The value in fVar would be 247.0 

Posted by 나비:D
:

C++ MFC Tip

2008. 7. 28. 16:16

출처 : Tong - navy9370님의 MFC통


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)   리터형  함수명(매개변수,...)

                      {

                             내용;

                      }

 

Posted by 나비:D
:

자 ! 이렇게 외우자 !! 아니, 외우지 말고 이렇게 이해하자!!!

  • 연산자 우선순위는 일단 15층짜리 건물로 생각을 하자. 보통 예전에는 아파트 15층 건물이 많지 않았는가? 쉽게 연상이 될 것이다.
  • 연산 순위가 낮은 연산자가 높은 층을 차지한다. 아무래도 1층과 가까운 층이 출구로 나오기 편하지 않겠는가? 그러므로 순위가 가장 낮은 컴마 연산자는 15층, 가장 높은 괄호 연산 등은 1층이다.
  • 각 층에 각각 연산자가 산다고 생각하자. 당연히 우선 순위가 중요한 것이 낮은 층에 위치시키고, 조금 낮은 순위를 높은 층에 위치시키자.
  • 연산자를 ‘외운다’ 고 생각하지 말고, 이제 한 ‘아파트’에 있는 ‘이웃’이라고 생각하자. 연산자의 특성을 생각하면서 ‘이웃’의 순서를 상기하자.
  • 연산자들은 각 역할 별로 고유한 특징이 있다. 그 특징을 바탕으로 연산자에게 좀더 ‘이웃’다운 성격을 부여하고 그 특징을 상기해 보자. 훨씬 이해하기 쉬울 것이다.

 

C 연산자 도시에는 많은 연산자들이 살고 있었다. C 연산자는 각각 그 나름대로의 개성과 고유한 역할, 성품이 있었고 연산자 도시에서 가지고 있는 사회적 지위, 재산과 평판을 가지고 있었다. 각각 연산자들은 자신의 역할을 담당하고 있었고, 그 역할에 따라 숫자 문자 논리값들은 각각 적절히 계산이 되어 결과가 나왔다. 연산자는 ‘연산’이라는 직업을 가지고 있었고, 그렇게 연산을 통해 생계를 꾸려갈 수 있었다.

 

어느 날 모든 연산자들은 연산자 타워라는 한 건물에서 살도록 프로그래머에게서 명령을 받았다. 제아무리 뛰어난 연산자라도 프로그래머의 명령은 절대적이었기 때문에 복종할 수밖에 없었다. 제각각 살던 그들은 이제 한 건물에서 살아야만 했다.

 

연산자 타워는 15층짜리 건물이었는데, 높은 층일수록 넓고 살기 좋았지만 한 층 한 층 올라갈수록 호되게 가격이 올라갔고, 1층 입구를 통해 바깥으로 나가 자신의 직장으로 출근하기도 어려웠다 게다가 높은 층에 걸맞은 사회적 지위가 없다면 눈치가 보여서 입주하기도 어려운 ‘불문율’이란 것이 있었다. 결국 누가 어느 층에서 살지를 의논하기 시작하였다.

 

15층은 너무나 좋아서 모든 연산자들이 탐을 낼만한 층이었다. 하지만 가격이 너무 비싸 선뜻 구입할 연산자가 없었다. 문득 컴마(,) 씨가 일어나 자신이 15층에 살겠다고 말하였다. 모든 연산자는 찬성하였다. 이미 컴마 씨는 다양한 분야에서 경험을 수많은 경험을 쌓은 베테랑이었고, 넉넉한 성품으로 유명하여 사회적으로도 명망이 높은 연산자였다.

컴마 씨의 재산 또한 어마어마하고, 최근 일선 업무에서 물러나 후진 양성에 힘쓰기로 하여 잦은 출퇴근을 할 이유가 없었으므로 결국 15층은 컴마 씨의 소유가 되었다.

 

14층은 연산 도시의 대부인 ‘할당 연산자’ 이퀄(=) 씨가 소유하기로 했다. 다른 연산자들도 동의하였다. 이퀄 씨 또한 이미 오래전부터 다양한 분야에서 활약을 펼친 존재였기 때문에 컴마 씨에 버금가는 사회적 지위와 재산을 누리고 있었다. 게다가 이퀄 씨의 할당 연산이 없이는 제아무리 복잡한 연산도 무용지물에 불과했다. 이퀄 씨 또한 후학 양성에 매진하였는데 그들의 직계 제자들은 다름아닌 += -= *= /= %= <<= >>= &= |= ^= 들이다. 이들은 종래 볼 수 없던 참신한 연산으로 연산업계의 새로운 화두로 떠오르고 있다.

 

13층은 의외로 삼항 연산자 씨가 소유하겠다고 말해 이목을 집중시켰다. 독특한 개성의 소유자인 삼항 연산자 씨는 젊을 때부터 C 연산업에서 주목받는 존재였다. 지금은 프리랜서 선언을 하고 조용히 자신의 창작 활동에 전념하고 싶은 터였다. 그에게 있어 13층은 자신의 거처로 더할 나위 없이 적당한 장소였다.

 

12층과 11층은 각각 논리 연산 오어(||) 씨 부부, 논리 연산 앤드(&&) 씨 부부가 맡기로 하였다. 각각 10층과 8층 비트 연산 오어(|) 씨, 비트 연산 앤드(&)씨의 형이기도 한 논리 오어 씨, 논리 앤드 씨는 맞벌이 부부였다. 두 부부 다 논리 연산에서 중요한 업무를 관장하고 있어 사회적 지위도 높았고 재산도 상당하였다.

원래 오어 씨가 11층을 먼저 선택하였다. 하지만 앤드 씨가 조금이라도 출근의 편의를 위해 11층에서 살기를 간곡히 원했고, 평소 앤드 씨와 친분이 깊은 데다 앤드 씨 부부의 바쁘디 바쁜 스케줄을 이미 잘 알고 있는 오어 씨는 ‘허허’하고 웃으며 선선히 11층을 양보해 주었다.

 

이미 언급하였듯 10층과 8층에는 논리 연산 오어 씨와 앤드 씨의 동생인 비트 연산 오어 군(|)과 앤드(&) 군이 살기로 하였다. 둘 다 각자의 형 못지않은 실력과 재능을 갖고 있어 비트 연산계의 젊은 인재로 촉망받는 두 연산자였다. 다소 파격적인 일이었지만 그들의 촉망받는 장래성과 논리 연산 오어 씨와 앤드 씨의 얼굴을 보아 다들 그 두 동생의 소유를 인정하는 분위기였다.

 

하지만 논리 연산 오어(||)씨와 앤드(&&)씨 부부는 내심 탐탁지 않다. 이제는 그 두 동생들도 알맞은 짝을 찾아 결혼하여 자신들처럼 아이도 낳고, 좀 더 행복하게 살기를 원했지만 아직 두 동생은 아직 결혼할 마음이 없는데다, 두 사람 다 9층에 있는 비트 연산 배타적 오어(^) 양에게 마음을 빼앗겨 있는 상황이기 때문이다.

 

논리 연산 오어 씨와 논리 연산 앤드 씨는 배타적 오어 양을 볼 때마다 속이 부글부글 끓어 올랐다. 자신들이 끔찍이 아끼는 동생들이 결혼할 생각도 하지 않고 오어 양에게만 매달려 있는 꼴이 맘에 들지 않아 사실 오어 양이 9층은 물론 연산자 타워에 입주하는 것조차도 반대하고 싶었기 때문이다. 게다가 자신들의 동생 사이 층에서 살겠다고 한 것은 대체 무슨 속내인지 알 수가 없었다.

하지만 그런 배타적 오어 양에게 무조건 몰아붙일 수만은 없었다. 배타적 오어 양은 깐깐하고 도도하기는 했지만 독특한 개성과 장기를 살려 이미 수많은 비트 연산 업무를 수월하게 진행한 그녀의 능력은 사실 그들 동생들을 능가할 정도이기 때문이었다.

 

그렇게 10층에는 비트 연산 오어 (|)군, 9층에는 비트 연산 배타적 오어(^)양, 8층에는 비트 연산 앤드 군(&)이 살기로 결정되었다.

 

7층에는 이퀄 씨의 아들이자 쌍둥이 같다(==) 씨와 다르다(!=) 씨가 같이 살기로 하였다. 생김새는 엇비슷하지만 (살펴보면 제법 다른 구석이 있다) 성격은 전혀 다른 두 연산자는 이퀄씨의 성격을 닮아 정직하고 우직한 성격이다. 아버지의 예전 업무(수학에서 =, ≠)를 물려 받아 C 연산 업무를 성실하게 또 하루하루 바쁘게 살고 있다.

 

6층에는 같다 씨와 다르다 씨보다 더욱 분주한 스케쥴을 보내는 관계 연산의 사총사가 입주하기로했다. 지방에서 지내다가 일약 C 연산자 업계의 다크호스로 떠오른 네 연산자 크거나 같다(>=), 작거나 같다(<=), 크다(>), 작다(<) 네 연산자는 의리로 똘똘 뭉친 친구들이었다. 같다 씨와 다르다 씨와 하는 일은 같지만, 수많은 연산 업무에서 더욱 많은 호출을 받는 탓에 항상 시간이 모자란 그들은 좀 더 출근에 유리한 6층에서 살기로 하였다.

 

5층에서 살기로 한 연산자는 말썽꾸러기 비트 이동 연산자(<<, >>) 두 남매였다. 두 남매는 매우 비사교적이었다. 솔직히 바쁘기로 따지만 관계 연산자나 논리 연산자들이 더욱 바쁘고 비트 이동 연산자는 매일 집에 틀어박혀 얼굴도 비추지 않고 무엇을 하는지 도통 알 수가 없었다.

그리고 비트 이동 연산자는 곱하기(*) 씨와 나누기(/) 씨에게 걸핏하면 트집을 잡았다. 지위가 좀 더 높은 까닭에 관계 연산자나 논리 연산자가 높은 층수에서 살았기에 망정이지.... 아무튼 비트 이동 연산자는 말썽꾸러기였다. 더 낮은 층도, 더 높은 층도 그들에게는 어울리지 않았다.

 

4층에는 너무나 유명한 더하기 씨(+), 빼기 씨(-) 부부, 3층에는 곱하기 씨(*), 나누기 씨(/) 부부, 그리고 그들의 자식인 몫 구하기(%)가 살기로 하였다. 이들 부부는 14층의 이퀄(=)씨 만큼이나 유명한 삶을 살았지만, 재물에는 초연하였다. 그들은 좋은 집을 원하지 않았다. 그리고 여전히 연산업에서 핵심적인 업무를 수행하기 때문에 이동이 편한 3층과 4층을 각각 원했고, 전통적으로 곱하기 씨와 나누기 씨 가족이 좀 더 우선순위가 주어졌기 때문에 곱하기 나누기 부부가 3층을 맡고 더하기 빼기 부부가 4층을 맡기로 했다.

 

2층에는 혼자만의 삶을 살기로 결정한 각 연산 분야의 많은 단항 연산자들이 모여 살기로 결정했다. 그들은 따로 또 같이 자신들이 원하는 삶을 살기로 결정하고 서로 간섭하지 않는다는 조건 하에 2층에서 뭉치기로 결정하였다. 그들은 반전(!), 비트 보수(~), 전치 증가(++) 전치 감소(--), 플러스 기호(+), 마이너스 기호(-), 주소 연산(&), 역참조 연산(*), 캐스팅 연산, sizeof 연산이었다.

 

1층에는 프로그래머의 잦은 호출로 24시간 항시 대기하는 연산자와 여러 도구들을 놓아두기로 하고 연산자들의 층 배분 토론은 끝이 났다. 이들은 [ ], 포인터 참조(->), 점 연산자(.) ... 프로그램 언어만 찾을 수 있는 연산들이었다.

그리고 괄호 연산자가 특이하게 그 도구들과 같이 살아가기로 했다. 다른 연산자는 그러려니 하고 생각하였다. 대관절 괄호 연산자는 괴짜인지, 도인인지 그 정체를 알 수 없었다. 그의 말 한 마디에 연산 전체가 좌지우지됨에도 불구하고, 재물도 지위도 그 어떤 것도 원하지 않았기 때문이다. 한편 괄호 연산의 강한 카리스마에 홀려 2층에서 1층으로 살기로 결심한 두 연산자가 있었으니 바로 전치 증가, 전치 감소 연산의 쌍둥이 형제 후치 증가(++), 후치 감소(--)이다. 이들은 항상 알 수 없는 행동을 하며 가끔씩 프로그래머조차 혼란에 빠뜨리는 기행을 저지르곤 한다.

Posted by 나비:D
:

출처 : http://warkyman.tistory.com/146

Flex 에서 MXML로 정의한 버튼이 다음과 같이 있다고 가정합니다.

 <mx:Button id="btnAlert"  label="Alert!" />


이 버튼을 클릭할 때 어떠한 동작을 하고자 하면 해당 버튼에 다음과 같이 클릭 이벤트 핸들러를 등록시켜주면 됩니다.

Script ---

public function alert(evt:MouseEvent):void
{
  Alert.show("Hello, Flex!", "Alert");
}

MXML ---

 <mx:Button id="btnAlert" label="Alert!" click="alert(event)" />


만약, 실제 버튼을 클릭하지 않고서 버튼을 클릭한 것과 같은 이벤트를 수동으로 발생시키려면 어떻게 해야할까요?
이럴때 필요한 것이 dispatchEvent 입니다.

dispatchEvent 의 구조는 다음과 같습니다.
objectInstance. dispatchEvent(event:Event)

자세한 설명은 수동에 의한 이벤트의 송출(Dispatch)  에서 참고하도록 하고 본 포스트에서는 생략하겠습니다.


아래에 보여드릴 소스는 캔버스를 MXML로 정의하여 이 캔버스를 클릭하였을때 버튼을 클릭한 것 과 같이 수동으로 이벤트를 발생시킴으로써 버튼을 클릭하였을 때와 같이 팝업이 뜨도록 하고 있습니다.

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="400" height="300">

    <mx:Script>
        <![CDATA[
   
        import mx.controls.Alert;

        public function alert(evt:MouseEvent):void
        {
            Alert.show("Hello, Flex!", "Alert");
        }

        public function canvasClick(evt:MouseEvent):void
        {
            btnAlert.dispatchEvent(new MouseEvent(MouseEvent.CLICK));
        }

        ]]>
    </mx:Script>

    <mx:Canvas x="44" y="79" width="200" height="153" backgroundColor="#FF0000" borderStyle="solid"
            cornerRadius="20" click="canvasClick(event)">
        <mx:Label text="Click Here!" horizontalCenter="0" verticalCenter="0"/>
    </mx:Canvas>

    <mx:Button id="btnAlert" x="271" y="137" label="Alert!" click="alert(event)"/>

</mx:Application>

dispatchEvent 를 이용하여 마치 버튼을 클릭한 것 처럼 MouseEvent.CLICK 이벤트를 버튼에 dispatch 함으로써 버튼에서 클릭 이벤트 핸들러로 등록해놓은 alert() 메소드가 실행되게 됩니다.

[Flash] http://warkyman.tistory.com/attachment/fk170000000001.swf


물론 위의 예제에서는 단순히 클릭시에 Alert 을 띄우는 작업으로 그쳤기에 문제가 없었지만, 실제 클릭이벤트와 관련된 작업이 필요할 경우 새로 생성해준 마우스이벤트 (new MouseEvent(MouseEvent.CLICK)) 의 상세한 값들을 제어할 필요가 있습니다.

MouseEvent (type:String , bubbles:Boolean = true, cancelable:Boolean = false, localX:Number , localY:Number , relatedObject:InteractiveObject = null, ctrlKey:Boolean = false, altKey:Boolean = false, shiftKey:Boolean = false, buttonDown:Boolean = false, delta:int = 0)

와.. 많다.;;;


Posted by 나비:D
:

[Flash] http://blog.jidolstar.com/attachment/1285711347.swf




위의 소스는 FlexComponent 카페에서 시난님이 만든 "XML의 자식을 가지고 있는 마지막 노드 알아내기(http://cafe.naver.com/flexcomponent/3755)" 글을 보고 아이디어를 얻었다. 시난님이 이것을 만들게 된 계기는 카페 주인장이신 브라이언 님이 WithFlex.com에서 운영할 Flex로 만든 트리메뉴를 같이 만들자고 제안을 했기 때문이다. 그렇지 않아도 Tree메뉴가 필요할 것 같아서 만들려고 하던 참이였는데 동지를 만난것 같아 넘 좋다.

동작은 아직 미비한 편이지만 http://blog.jidolstar.com/18 에서 만든 것에 기능을 개선시켰다.
개선된 기능은 다음과 같다.


  1. 전체펼치기/접기 기능 추가
  2. 선택된 노드 펼치기/접기 기능추가
  3. 찾을 노드 id를 입력하여 해당 노드를 펼치고 선택하기 기능 추가

프로그램은 아직 실용성은 없으며 계속 보완해가고 있는 중이다. 최종 결과물은 각 노드의 위치를 바꾸고 서버에 비동기적으로 통신하여 수정할 수 있게 만들어갈 예정이다.

사용한 XML 파일은 다음과 같다.


<?xml version="1.0" encoding="utf-8" ?>
<root>
    <msg>ok</msg>
    <nodes>
        <node id="a" label="홈">
            <node id="b-1" label="제품">
                <node id="c-1" label="플렉스" />
                <node id="c-2" label="플래시" />
            </node>
            <node id="b-2" label="도움말">
                <node id="c-3" label="플렉스 라이브 문서" />
                <node id="c-4" label="플래시 라이브 문서" />
            </node>
            <node id="b-3" label="커뮤니티">
                <node id="c-5" label="플렉스 커뮤니티">
                    <node id="d-1" label="플렉스컴포넌트 카페" />
                    <node id="d-2" label="어도비유저그룹" />
                </node>
                <node id="c-6" label="플래시 커뮤니티" />
            </node>
        </node>
    </nodes>
</root>

           
프로그램 소스는 http://blog.jidolstar.com/18 에서 올린 것과 다르게 Tree를 상속받아서 사용했다. 나중에 나만의 컴퍼넌트를 만들어 아무때나 사용하기 위해서이다.

파일명 : TreeTest.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml " layout="absolute"
  initialize="System.useCodePage=true"
  xmlns:js="com.jidolstar.components.*" creationComplete="init()">
 <mx:Script>
  <![CDATA[
   private function init():void
   {
    myTreeXMLMenu.setCrossDomain("crossdomain.xml 파일 url");
    myTreeXMLMenu.request("XML파일 url");  
   }
  ]]>
 </mx:Script>
 <mx:Style>
  Application
  {
   fontSize:12pt;
  }
 </mx:Style>
 <mx:Panel width="500" height="300"
  layout="absolute" title="동적으로 바인드되는 XML Tree 메뉴+Node찾아펼치기-jidolstar.com">
  <mx:VBox width="100%" height="100%">
   <js:TreeXMLMenu id="myTreeXMLMenu" width="100%"/>
   <mx:HBox>
    <mx:Label text="찾을 노드 ID"/>
    <mx:TextInput width="100" id="findValue" text="d-2"/>
    <mx:Button label="찾기" click="myTreeXMLMenu.find(findValue.text)"/>
   </mx:HBox>
   <mx:HBox>
    <mx:Button label="전체펼치기" click="myTreeXMLMenu.expandAll(true)"/>
    <mx:Button label="전체접기" click="myTreeXMLMenu.expandAll(false)"/>
    <mx:Button label="선택된노트 접기/펼치기" click="myTreeXMLMenu.expand()"/>
   </mx:HBox>
  </mx:VBox>
 </mx:Panel>
</mx:Application>



파일명 : com.jidolstar.componet.TreeXMLMenu.mxml
 


<?xml version="1.0" encoding="utf-8"?>
<mx:Tree xmlns:mx="http://www.adobe.com/2006/mxml "    
    labelField="@label"
    dataProvider="{xlcData}"
    showRoot="false" creationComplete="init()">
 <mx:Script>
  <![CDATA[
   import mx.collections.*;
   import mx.controls.Alert;
   import mx.rpc.events.FaultEvent;
   import mx.rpc.events.ResultEvent;
   import mx.rpc.http.HTTPService;
   import flash.system.Security;

   public var httpServ:HTTPService;
   
   [Bindable]
   public var xlcData:XMLListCollection;
   
   ////////////////////////////////////////////
   // 초기화
   // HTTPSerivce를 생성
   ////////////////////////////////////////////
   public function init():void
   {
    httpServ = new HTTPService();
   }  
   
   ////////////////////////////////////////////
   // CrossDomain 설정
   ////////////////////////////////////////////  
   public function setCrossDomain(url:String):void 
   {
    Security.loadPolicyFile(url);
   }
   
   ////////////////////////////////////////////
   // XML 요청
   // 1. POST방식으로 요청하고  결과물을 E4X형태로 한다.
   // 2. 결과를 받기 위해 Listener Handler함수를 선언
   ////////////////////////////////////////////
   public function request(url:String , params:Object=null):void
   {
    this.httpServ.url = url;
    this.httpServ.method = "POST";
    this.httpServ.resultFormat="e4x";
    this.httpServ.addEventListener("result", resultHandler);
    this.httpServ.addEventListener("fault", faultHandler);
    this.httpServ.send(params);
   }

   ////////////////////////////////////////////
   // XML 결과를 받았을 경우
   // 1. XMLList에 결과를 임시로 저장
   // 2. 적합한 데이타인지 확인
   // 3. nodes요소만 XMLListCollection으로 생성
   // 이는 동적으로 Tree에 바인드[Bindable]됨
   ////////////////////////////////////////////  
   private function resultHandler(e:ResultEvent):void
   {
    var xlData:XMLList = new XMLList(e.result);
    if(xlData.elements("msg").toString()!="ok")
    {
     mx.controls.Alert.show(xlData.elements("msg").toString(),"Error");
    }
    else
    {
     xlcData = new XMLListCollection(xlData.elements("nodes"));
    }       
   }
   
   ////////////////////////////////////////////
   // XML 데이타 요청에 대한 실패가 있을 경우 호출됨
   ////////////////////////////////////////////  
   private function faultHandler(e:FaultEvent):void
   {
    mx.controls.Alert.show("XML정보 읽어오기 실패\n"+e.fault.faultString);
   }
   
   ////////////////////////////////////////////
   // Tree 전체를 접고 펼침
   ////////////////////////////////////////////
   public function expandAll(open:Boolean):void
   {
    var xlc:XMLListCollection = this.dataProvider as XMLListCollection;
    var nodeList:XMLList = xlc.descendants();
    trace(nodeList.length());
    for(var i:int=0; i<nodeList.length(); i++)
    {
     trace(nodeList[i]);
     this.expandItem(nodeList[i], open, false);
    }
   }
   
   ////////////////////////////////////////////
   // 선택한 Node 접고 펼침
   ////////////////////////////////////////////  
   public function expand():void
   {
    var selectedNode:Object=this.selectedItem;
    trace(selectedNode);
    if(this.isItemOpen(selectedNode)==true)
    {
     this.expandItem(selectedNode, false);    
     trace("close");
    }
    else
    {
     this.expandItem(selectedNode, true);    
     trace("open");
    }
   }
   
   ////////////////////////////////////////////
   // 인자로 넘어온 id값을 찾는다.
   ////////////////////////////////////////////  
   public function find(id:String):Boolean
   {
    var xlc:XMLListCollection = this.dataProvider as XMLListCollection;
    var nodeList:XMLList = xlc.descendants();
    trace(nodeList.length());
    for(var i:int=0; i<nodeList.length(); i++)
    {
     trace(nodeList[i].@id.toString());
     if(nodeList[i].@id.toString() == id)
     {
      trace(i);
      break;
     }
    }
    if(i == nodeList.length())
    {
     trace("id='"+id+"'는 없음");
     return false;
    }
    expandParents(nodeList[i]);
    this.selectedItem = nodeList[i];
    return true;
   }
   
   ////////////////////////////////////////////
   // 인자로 넘어온 node의 부모를 전부 펼친다.
   ////////////////////////////////////////////
   protected function expandParents(xmlNode:XML):void
   {
    if(xmlNode == null)
    {
     return;
    }
    while (xmlNode.parent() != null && xmlNode.localName().toString() == "node")
    {
     xmlNode = xmlNode.parent();
     this.expandItem(xmlNode, true, false);
    }
   }

  ]]>
 </mx:Script>
 
</mx:Tree>



글쓴이 : 지돌스타 (http://blog.jidolstar.com/18  )
Posted by 나비:D
:

ASP.NET MVC Framework는 URL을 controller 클래스에 매핑합니다. Controller는 들어오는 요청을 처리하고, 사용자 입력과 상호작용을 다루며, 적당한 응용프로그램 로직을 수행합니다. Controller는 요청에 대한 HTML을 생성하기 위해 view 컴포넌트를 호출합니다.


모든 controller 클래스는 Controller 클래스를 상속받으며 IController, IActionFilter, IDisposable 인터페이스를 구현합니다.


모든 controller는 Controller라고 하는 접미사를 사용해서 이름을 지어야 합니다. 다음 예제를 보면 HomeController라고 되어 있는데요, action 메소드를 포함하고 있으며 view 페이지를 렌더링하기 위한 메소드를 제공합니다.


public class HomeController : Controller
{
    public ActionResult Index()
    {
        ViewData["Title"] = "Home Page";
        ViewData["Message"] = "Welcome to ASP.NET MVC!";

        return View();
    }

    public ActionResult About()
    {
        ViewData["Title"] = "About Page";

        return View();
    }
}


Action 메소드


MVC Framework를 사용하지 않는 ASP.NET 응용프로그램에서는 사용자와의 상호작용이 페이지를 통해 이루어지지만, ASP.NET MVC 응용프로그램에서는 controller와 action을 통해 이루어집니다. controller 클래스는 action 메소드를 정의하며 원하는 만큼의 action 메소드를 포함할 수 있습니다.


Action 메소드는 보통 사용자와의 상호작용과 1대 1로 매핑이 됩니다. 예를 들면, 브라우저에 URL을 입력하거나 링크를 클릭하거나 폼을 전송하는 것들이 이에 해당됩니다. 이런 동작들은 서버에 대해 요청을 하게 되고 URL은 MVC Framework이 Action을 호출할 수 있는 정보를 포함하게 됩니다.


예를 들어, 사용자가 브라우저에 URL을 입력하면 MVC 응용프로그램은 Global.asax에 정의된 라우팅 규칙을 적용하여 URL을 해석하여 적용할 controller를 결정하고 controller는 수행할 action을 결정합니다.


기본적으로 URL은 controller 다음에 action 이 오는 하위 경로 구조를 하고 있습니다. 예를 들어 URL이 http://contoso.com/MyWebSite/Products/Categories 라면, 하위 경로는 /Products/Categories가 되고 "Products" 가 controller의 이름이며 "Categories" 가 action 의 이름이 됩니다.


만약 URL이 /Products/Detail/5 라고 하면 "Detail" 이 Action이 되고 5 는 Detail Action 메소드에 전달하는 매개변수 값이 될 것입니다.


ActionResult Return Type


모든 action 메소드는 ActionResult 에서 파생된 클래스의 인스턴스를 반환합니다.  모든 action 결과에 대한 base는 ActionResult이지만 action에 따라 여러가지 타입의 action result type이 존재할 수 있습니다.


다음은 내장 action result type입니다.

  • ViewResult : View 메소드에 의해 반환됩니다.
  • RedirectToRouteResult : RedirectToAction 과 RedirectToRoute 메소드에 의해 반환됩니다.
  • RedirectResult : Redirect 메소드에 의해 반환됩니다.
  • ContentResult : Content 메소드에 의해 반환됩니다.
  • JsonResult : Json 메소드에 의해 반환됩니다.
  • EmptyResult : action 메소드가 null을 반환해야 할 경우 반환합니다.

Action 메소드 매개변수


controller 클래스 내에서 URL 매개변수를 참조하는 방법은 여러가지가 있습니다. 기본적으로는 Request와 Response 객체를 사용하여 접근할 수 있습니다.


public void Detail()
{
    int id = Convert.ToInt32(Request["id"]);
}

기존에 사용하던 방법과 크게 다르지 않습니다.


하지만, 좀 더 편리하게 매개변수를 참조할 수 있는 방법이 있습니다.


Action 메소드 매개변수 자동 매핑


ASP.NET MVC Framework는 URL 매개변수 값을 매개변수에 자동으로 연결할 수 있는 방법을 제공하고 있습니다. 이 방법을 사용하게 되면 위에서 살펴보았던 매개변수 값을 받는 문장을 사용하지 않아도 됩니다.


public ResultAction Detail(int id)
{
    ViewData["DetailInfo"] = id;
    return View("Detail");
}

이렇게 하면 매개변수 id에 요청한 내용중 id라는 이름으로 된 값이 자동으로 연결이 됩니다. 별도의 Request 구문을 작성하지 않아도 되는 것이죠.


또한 Query String 대신 매개변수 값을 URL의 일부로 포함시키는 것이 가능해집니다. 예를 들어 /Products/Detail?id=3 와 같은 URL이 있다고 하면, 이 것은 /Products/Detail/3 처럼 바꿀 수 있습니다.

 

기본적인 라우팅 규칙은 /{controller}/{action}/{id} 와 같은 형태를 하고 있습니다. id 에 해당하는 값이 action 메소드의 매개변수로 자동으로 전달이 됩니다.

 

이번 내용은 거의 번역 수준이 되었네요... ^^

Posted by 나비:D
:

출처 : http://blog.naver.com/process3?Redirect=Log&logNo=20050651724

Visual Studio 2008 서비스 팩1과 .net framework 3.5 서비스 팩1 이 나왔습니다.


한글판 서비스팩은 아직 나오지 않았습니다. 영문 Visual Studio2008에만 서비스팩이 설치 됩니다.



[Visual C++ 2008 관련 업데이트 사항]

VS 2008 SP1 beta does include VC 2008 Feature Pack and TR1.

 

VC++ 2008 Express SP1 beta does not include VC 2008 feature pack

VC++ 2008 Express SP1 beta does include TR1.


[변경 사항]

.NET 3.5 SP1 과 VS 2008 SP1은 제품 발표후에 보고된 버그를 수정했고 성능을 향상 시켰고 기능을 추가해서 .net application을 좀더 잘 만들수 있도록 했다. 이번 여름에 정식버전이 출시 될 예정이다.


.NET 3.5 SP1 and VS 2008 SP1 provide a bunch of bug fixes, performance improvements, and additional feature enhancements that make building all types of .NET applications better.  It will be a fully compatible service pack release. 

We plan to ship the final release of both .NET 3.5 SP1 and VS 2008 SP1 this summer as free updates.


각각 기능별 수정 사항을 알고 싶은신 분들은 Scott Guthrie 의 블로그를 방문하시면 됩니다.

http://weblogs.asp.net/scottgu/archive/2008/05/12/visual-studio-2008-and-net-framework-3-5-service-pack-1-beta.aspx


필요하신 분들은 아래 사이트에서 다운받으세요


Downloads
VS 2008 SP1 : http://download.microsoft.com/download/7/3/8/7382EA08-4DD6-4134-9B92-8585A5B07973/VS90sp1-KB945140-ENU.exe
 
.NET 3.5 SP1 : http://download.microsoft.com/download/8/f/c/8fc1fe13-55de-4bf5-b43e-375daf01452e/dotNetFx35setup.exe
 
Express 2008 with SP1:
http://download.microsoft.com/download/F/E/7/FE754BA4-140B-413C-933F-8D35FB150F12/vbsetup.exe
 
http://download.microsoft.com/download/F/E/7/FE754BA4-140B-413C-933F-8D35FB150F12/vcsetup.exe
 
http://download.microsoft.com/download/F/E/7/FE754BA4-140B-413C-933F-8D35FB150F12/vcssetup.exe
 
http://download.microsoft.com/download/F/E/7/FE754BA4-140B-413C-933F-8D35FB150F12/vnssetup.exe
 
TFS 2008 SP1: http://download.microsoft.com/download/a/e/2/ae2eb0ff-e687-4221-9c3e-9165a942bc1c/TFS90sp1-KB949786.exe


출처 : 다년간의 프로그램밍 경험 및 http://weblogs.asp.net/scottgu/archive/2008/05/12/visual-studio-2008-and-net-framework-3-5-service-pack-1-beta.aspx

Posted by 나비:D
:

ASP.NET에서 MVC(Model-View-Controller) 구현

? Data Column: select for more on pattern organization Application Column: select for more on pattern organization Deployment Column: select for more on pattern organization Infrastructure Column: select for more on pattern organization
Architecture Row: select for more on pattern organization Data Architecture: select for more on pattern organization Application Architecture: select for more on pattern organization Deployment Architecture: select for more on pattern organization Infrastructure Architecture: select for more on pattern organization
Design Row: select for more on pattern organization Data Design: select for more on pattern organization Application Design: select for more on pattern organization Deployment Design: select for more on pattern organization Infrastructure Design: select for more on pattern organization
Implementation Row Data Implementation: select for more on pattern organization Application Implementation: select for more on pattern organization Deployment Implementation: select for more on pattern organization Infrastructure Implementation: select for more on pattern organization
? Complete List of patterns & practices Complete List of patterns & practices Complete List of patterns & practices Complete List of patterns & practices

버전 1.0.1

이 패턴에 대한 공동 작업을 위한 DotDotNet 커뮤니티

patterns & practives 전체 목록 (영문)

상황

Microsoft ASP.NET에서 웹 응용 프로그램을 구축 중인데 응용 프로그램이 복잡하기 때문에 코드 중복을 줄이고 변경 사항이 전파되는 것을 제한하려면 프로그램의 서로 다른 기능을 분리해야 합니다.

구현 전략

소프트웨어의 모델, 뷰 및 컨트롤러 역할을 분리하여 제공된 값 및 ASP.NET에서 MVC(Model-View-Controller)패턴을 구현하는 방법을 설명하기 위해, 다음 예에서는 이 세 역할을 분리하지 않은 단일 페이지 솔루션을 이러한 역할을 분리한 솔루션으로 리팩토링합니다. 이 예제 응용 프로그램은 드롭다운 목록이 있는 단일한 웹 페이지(그림 1)로서, 데이터베이스에 저장되어 있는 기록을 표시합니다.

그림 1: 예제 웹 페이지

사용자는 드롭다운 목록에서 특정 기록을 선택한 다음 전송(Submit) 단추를 클릭합니다. 그러면 응용 프로그램이 데이터베이스의 이 기록에서 모든 트랙의 목록을 검색하여 그 결과를 표로 표시합니다. 이 패턴에 설명된 세 솔루션 모두 정확하게 동일한 기능을 구현합니다.

단일 ASP.NET 페이지

ASP.NET에서 이 페이지를 구현하는 방법은 많습니다. 가장 간단하고 단순한 방법은 다음 코드 예에서 볼 수 있는 것처럼 모든 것을 "Solution.aspx"라고 하는 한 파일에 모두 넣는 방법입니다.

 

<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<html>
   <head>
      <title>start</title>
      <script language="c#" runat="server">
         void Page_Load(object sender, System.EventArgs e)
         {
            String selectCmd = "select * from Recording";

            SqlConnection myConnection = 
               new SqlConnection(
                  "server=(local);database=recordings;Trusted_Connection=yes");
            SqlDataAdapter myCommand = new SqlDataAdapter(selectCmd, 
               myConnection);

            DataSet ds = new DataSet();
            myCommand.Fill(ds, "Recording");
            
            recordingSelect.DataSource = ds;
            recordingSelect.DataTextField = "title";
            recordingSelect.DataValueField = "id";
            recordingSelect.DataBind();
         }
         
         void SubmitBtn_Click(Object sender, EventArgs e) 
         {   
            String selectCmd = 
               String.Format(
               "select * from Track where recordingId = {0} order by id",
               (string)recordingSelect.SelectedItem.Value);

            SqlConnection myConnection = 
               new SqlConnection(
                  "server=(local);database=recordings;Trusted_Connection=yes");

            SqlDataAdapter myCommand = new SqlDataAdapter(selectCmd,
               myConnection);

            DataSet ds = new DataSet();
            myCommand.Fill(ds, "Track");

            MyDataGrid.DataSource = ds;
            MyDataGrid.DataBind();
         }
      </script>
   </head>
   <body>
      <form id="start" method="post" runat="server">
         <h3>Recordings</h3>
         Select a Recording:<br />
         <asp:dropdownlist id="recordingSelect" runat="server" />
         <asp:button runat="server" text="Submit" OnClick="SubmitBtn_Click" />
         <p/>
         <asp:datagrid id="MyDataGrid" runat="server" width="700" 
               backcolor="#ccccff" bordercolor="black" showfooter="false" 
               cellpadding="3" cellspacing="0" font-name="Verdana" 
               font-size="8pt" headerstyle-backcolor="#aaaadd" 
               enableviewstate="false" />
      </form>
   </body>
</html>
 

이 파일은 이 패턴의 세 역할을 모두 구현하지만 이 역할을 서로 다른 파일이나 클래스로 구분하지는 않습니다. 뷰 역할은 HTML 고유의 렌더링 코드에 의해 표시됩니다. 이 페이지는 바운드 데이터 제어 구현을 사용하여 데이터베이스에서 반환된 DataSet 개체를 표시합니다. 한편 모델 역할은 Page_Load 및 SubmitBtn_Click 함수에서 구현됩니다. 컨트롤러 역할은 직접 표시되지 않으며 ASP.NET에 내재되어 있습니다. 이에 대해서는 페이지 컨트롤러를 참조하십시오. 페이지는 사용자가 요청하면 업데이트됩니다. MVC(Model-View-Controller)는 이것을 수동적인 컨트롤러로 설명합니다. ASP.NET가 컨트롤러 역할을 구현하지만 그 컨트롤러가 응답하는 이벤트에 작업을 연결하는 책임은 프로그래머에게 있기 때문입니다. 이 예에서는 컨트롤러가 Page_Load 함수를 호출하면 페이지가 로드됩니다. 그리고 사용자가 전송(Submit) 단추를 클릭하면 컨트롤러가 SubmitBtn_Click 기능을 호출합니다.

이 페이지는 아주 단순하며 독립적입니다. 이 구현은 유용하며, 응용 프로그램이 작고 자주 변경되지 않는 경우 사용하기 좋습니다. 하지만 개발 중 다음과 같은 상황이 발생하는 경우에는 이 방법을 변경하는 방안을 고려해 보아야 합니다.

  • 병렬 처리를 늘리고 오류 가능성을 줄이고자 할 경우. 뷰 코드와 모델 코드를 서로 다른 사람이 작업하여 병렬 처리 양을 늘리고 오류 발생 가능성을 제한하고자 할 수 있습니다. 예를 들어, 모든 코드가 한 페이지에 있는 경우 개발자는 DataGrid 서식을 변경하고 데이터베이스를 액세스하는 원본 코드 일부를 무심코 변경할 수 있습니다. 하지만 페이지는 다시 보기를 해야만 컴파일되므로 페이지를 다시 보기 전까지는 오류를 발견할 수 없습니다.

  • 여러 페이지에 데이터베이스 액세스 코드를 다시 사용하고자 할 경우. 이 구현에서는 코드를 중복하지 않고는 다른 페이지에 코드를 다시 사용할 수 있는 방법이 없습니다. 중복 코드를 사용하면 데이터베이스 코드가 변경될 경우 그 데이터베이스를 액세스하는 모든 페이지를 수정해야 하므로 유지 관리가 어렵습니다.

    이러한 문제를 처리하기 위해 ASP.NET 구현자들은 코드 비하인드 기능을 도입했습니다.

    코드 비하인드 리팩토링

    Microsoft Visual Studio .NET 개발 시스템의 코드 비하인드 기능을 사용하면 프레젠테이션(뷰) 코드를 모델 컨트롤러 코드에서 쉽게 분리할 수 있습니다. 개별 ASP.NET 페이지에는 그 페이지에서 호출된 메서드가 별도의 클래스에서 구현되도록 하는 메커니즘이 있습니다. 이 메커니즘은 Visual Studio .NET에 의해 활성화되며 Microsoft IntelliSense 기술과 같은 많은 이점이 있습니다. 코드 비하인드 기능을 사용하여 페이지를 구현할 때에는 IntelliSense를 사용하여 해당 페이지 뒤의 코드에서 사용하고 있는 개체의 사용 가능한 메서드 목록을 표시할 수 있습니다. IntelliSense는 .aspx 페이지에서는 작동되지 않습니다.

    다음은 동일한 예로, 이번에는 코드 비하인드 기능을 사용하여 ASP.NET을 구현합니다.

    이 프레젠테이션 코드는 이제 Solution.aspx라고 하는 별도의 파일에 들어 있습니다.

     
    
    <%@ Page language="c#" Codebehind="Solution.aspx.cs" 
       AutoEventWireup="false" Inherits="Solution" %>
    <html>
       <head>
          <title>Solution</title>
       </head>
       <body>
          <form id="Solution" method="post" runat="server">
             <h3>Recordings</h3>
             Select a Recording:<br/>
             <asp:dropdownlist id="recordingSelect" runat="server" />
             <asp:button id="submit" runat="server" text="Submit" 
                enableviewstate="False" />
             <p/>
             <asp:datagrid id="MyDataGrid" runat="server" width="700"
                   backcolor="#ccccff" bordercolor="black" showfooter="false"
                   cellpadding="3" cellspacing="0" font-name="Verdana" font-size="8pt"
                   headerstyle-backcolor="#aaaadd" enableviewstate="false" />
          </form>
       </body>
    </html>
     

    이 코드의 대부분은 첫 번째 구현에서 사용된 코드와 비슷하며 가장 큰 차이점은 첫 번째 줄입니다.

     
    
    <%@ Page language="c#" Codebehind="Solution.aspx.cs" 
       AutoEventWireup="false" Inherits="Solution" %>
     

    이 줄은 코드 비하인드 클래스가 이 페이지에서 참조되는 메서드를 구현하는 ASP.NET 환경을 나타냅니다. 이 페이지에는 데이터베이스를 액세스하는 코드가 없으므로, 데이터베이스가 코드 변경 사항을 액세스하더라도 이 페이지를 수정해야 할 필요가 없습니다. 사용자 인터페이스 디자인에 익숙한 사람은 데이터베이스 액세스 코드에 오류를 유발하지 않고도 이 코드를 수정할 수 있습니다.

    모델 컨트롤러

    이 솔루션의 두 번째 부분은 다음과 같은 코드 비하인드 페이지입니다.

     
    
    using System;
    using System.Data;
    using System.Data.SqlClient;
    
    public class Solution : System.Web.UI.Page
    {
       protected System.Web.UI.WebControls.Button submit;
       protected System.Web.UI.WebControls.DataGrid MyDataGrid;
       protected System.Web.UI.WebControls.DropDownList recordingSelect;
       
       private void Page_Load(object sender, System.EventArgs e)
       {
          if(!IsPostBack)
          {
             String selectCmd = "select * from Recording";
    
             SqlConnection myConnection = 
                new SqlConnection(
                   "server=(local);database=recordings;Trusted_Connection=yes");
             SqlDataAdapter myCommand = new SqlDataAdapter(selectCmd, myConnection);
    
             DataSet ds = new DataSet();
             myCommand.Fill(ds, "Recording");
    
             recordingSelect.DataSource = ds;
             recordingSelect.DataTextField = "title";
             recordingSelect.DataValueField = "id";
             recordingSelect.DataBind();
          }
       }
    
       void SubmitBtn_Click(Object sender, EventArgs e) 
       {   
          String selectCmd = 
             String.Format(
             "select * from Track where recordingId = {0} order by id",
             (string)recordingSelect.SelectedItem.Value);
    
          SqlConnection myConnection = 
             new SqlConnection(
                "server=(local);database=recordings;Trusted_Connection=yes");
          SqlDataAdapter myCommand = new SqlDataAdapter(selectCmd, myConnection);
    
          DataSet ds = new DataSet();
          myCommand.Fill(ds, "Track");
    
          MyDataGrid.DataSource = ds;
          MyDataGrid.DataBind();
       }
    
       #region Web Form Designer generated code
       override protected void OnInit(EventArgs e)
       {
          //
          // CODEGEN: This call is required by the ASP.NET Web Form Designer.
          //
          InitializeComponent();
          base.OnInit(e);
       }
          
       /// <summary>
       /// Required method for Designer support - do not modify
       /// the contents of this method with the code editor.
       /// </summary>
       private void InitializeComponent()
       {    
          this.submit.Click += new System.EventHandler(this.SubmitBtn_Click);
          this.Load += new System.EventHandler(this.Page_Load);
    
       }
       #endregion
    }
     

    이 코드는 단일 ASP.NET 페이지에서 자체 파일로 옮겨졌습니다. 이 두 엔터티를 하나로 연결하려면 몇몇 구문을 변경해야 합니다. 이 클래스에 정의된 구성원 변수는 Solution.aspx 파일에 참조된 이름과 동일한 이름을 공유합니다. 명시적으로 정의되어야 하는 또 다른 부분은, 이 컨트롤러가 반드시 실행되어야 하는 작업이 발생한 이벤트에 어떻게 연결하는가 입니다. 이 예에서는 InitializeComponent 메서드가 이 두 이벤트를 연결합니다. 첫 번째 이벤트는 Load로, Page_Load 함수로 연결됩니다. 그리고 두 번째 이벤트는 Click으로, 전송(Submit) 단추를 클릭하면 SubmitBtn_Click 함수가 실행되도록 만듭니다.

    코드 비하인드 기능은 뷰 역할을 모델 및 컨트롤러 역할에서 분리하는 훌륭한 메커니즘입니다. 코드 비하인드 기능은 코드 비하인드 클래스에 있는 코드를 다른 페이지에 재사용해야 하는 경우 불충분해질 수 있습니다. 코드 비하인드 페이지에서 코드를 재사용하는 것이 기술적으로는 가능하지만 코드 비하인드 클래스를 공유하는 모든 페이지의 결합이 증가하기 때문에 바람직하지 않습니다.

    MVC(Model-View-Controller) 리팩토링

    마지막 문제를 해결하기 위해서는 컨트롤러에서 모델 코드를 분리해야 합니다. 뷰 코드는 이전 구현에서 사용한 코드와 동일합니다.

    모델

    다음 코드 예는 모델을 표시한 것으로, 데이터베이스에만 의존합니다. 따라서 뷰 의존 코드(ASP.NET 종속성 코드)는 포함되어 있지 않습니다.

     
    
    using System;
    using System.Collections;
    using System.Data;
    using System.Data.SqlClient;
    
    public class DatabaseGateway
    {
       public static DataSet GetRecordings()
       {
          String selectCmd = "select * from Recording";
    
          SqlConnection myConnection = 
             new SqlConnection(
                "server=(local);database=recordings;Trusted_Connection=yes");
          SqlDataAdapter myCommand = new SqlDataAdapter(selectCmd, myConnection);
    
          DataSet ds = new DataSet();
          myCommand.Fill(ds, "Recording");
          return ds;
       }
    
       public static DataSet GetTracks(string recordingId)
       {
          String selectCmd = 
             String.Format(
             "select * from Track where recordingId = {0} order by id",
             recordingId);
    
          SqlConnection myConnection = 
             new SqlConnection(
                "server=(local);database=recordings;Trusted_Connection=yes");
          SqlDataAdapter myCommand = new SqlDataAdapter(selectCmd, myConnection);
    
          DataSet ds = new DataSet();
          myCommand.Fill(ds, "Track");
          return ds;
       }
     

    이제 이 파일이 데이터베이스에 의존하는 유일한 파일입니다. 이 클래스는 테이블 데이터 게이트웨이의 훌륭한 예입니다. 테이블 데이터 게이트웨이에는 단일 테이블 또는 뷰를 액세스하는 모든 SQL 코드(선택, 삽입, 업데이트, 삭제)가 있습니다. 다른 코드는 이 데이터베이스와의 모든 상호 작용을 위해 자체 메서드를 호출합니다. [Fowler03]

    컨트롤러

    이 리팩토링은 코드 비하인드 기능을 사용하여 그 페이지에 있는 데이터 제어에 모델 코드를 적용하고 컨트롤러가 전달하는 이벤트를 특정 작업 메서드로 매핑합니다. 이 모델은 여기에서 DataSet 개체를 반환하기 때문에 작업이 단순합니다. 이 코드는 뷰 코드와 마찬가지로 데이터베이스에서 데이터가 검색되는 방법에 의존하지 않습니다.

     
    
    using System;
    using System.Data;
    using System.Collections;
    using System.Web.UI.WebControls;
    
    public class Solution : System.Web.UI.Page
    {
       protected System.Web.UI.WebControls.Button submit;
       protected System.Web.UI.WebControls.DataGrid MyDataGrid;
       protected System.Web.UI.WebControls.DropDownList recordingSelect;
       
       private void Page_Load(object sender, System.EventArgs e)
       {
          if(!IsPostBack)
          {
             DataSet ds = DatabaseGateway.GetRecordings();
             recordingSelect.DataSource = ds;
             recordingSelect.DataTextField = "title";
             recordingSelect.DataValueField = "id";
             recordingSelect.DataBind();
          }
       }
    
       void SubmitBtn_Click(Object sender, EventArgs e) 
       {   
          DataSet ds = 
             DatabaseGateway.GetTracks(
             (string)recordingSelect.SelectedItem.Value);
    
          MyDataGrid.DataSource = ds;
          MyDataGrid.DataBind();
       }
    
       #region Web Form Designer generated code
       override protected void OnInit(EventArgs e)
       {
          //
          // CODEGEN: This call is required by the ASP.NET Web Form Designer.
          //
          InitializeComponent();
          base.OnInit(e);
       }
          
       /// <summary>
       /// Required method for Designer support - do not modify
       /// the contents of this method with the code editor.
       /// </summary>
       private void InitializeComponent()
       {    
          this.submit.Click += new System.EventHandler(this.SubmitBtn_Click);
          this.Load += new System.EventHandler(this.Page_Load);
    
       }
       #endregion
    }
     

    테스트

    ASP.NET 환경에서 모델을 분리하면 모델 코드를 테스트하기가 더 쉬워집니다. ASP.NET 환경 내에서 이 코드를 테스트하려면 이 프로세스의 출력을 테스트해야 합니다. 이는, HTML을 읽고 정확한지를 판단해야 하는 것을 의미하는데 그 작업은 아주 지루하고 오류가 발생하기 쉽습니다. 모델을 분리하여 ASP.NET 없이 실행할 수 있게 되면 이러한 지루한 작업을 피할 수 있으며 코드만 분리하여 테스트할 수 있습니다. 다음은 NUnit (http://nunit.org)의 모델 코드 샘플 단위 테스트입니다.

     
    
    using System;
    
    using NUnit.Framework;
    using System.Collections;
    using System.Data;
    using System.Data.SqlClient;
    
    [TestFixture]
    public class GatewayFixture
    {
       [Test]
       public void Tracks1234Query()
       {
    
          DataSet ds = DatabaseGateway.GetTracks("1234");
          Assertion.AssertEquals(10, ds.Tables["Track"].Rows.Count);
       }
    
       [Test]
       public void Tracks2345Query()
       {
          DataSet ds = DatabaseGateway.GetTracks("2345");
          Assertion.AssertEquals(3, ds.Tables["Track"].Rows.Count);
       }
    
       [Test]
       public void Recordings()
       {
          DataSet ds = DatabaseGateway.GetRecordings();
          Assertion.AssertEquals(4, ds.Tables["Recording"].Rows.Count);
    
          DataTable recording = ds.Tables["Recording"];
          Assertion.AssertEquals(4, recording.Rows.Count);
    
          DataRow firstRow = recording.Rows[0];
          string title = (string)firstRow["title"];
          Assertion.AssertEquals("Up", title.Trim());
       }
    }
      

    결과

    ASP.NET에서 MVC를 구현하면 다음과 같은 이점과 단점이 있습니다.

    장점

  • 종속성 감소.ASP.NET 페이지는 프로그래머가 페이지 내에서 메서드를 구현할 수 있도록 해줍니다. 단일 ASP.NET 페이지에서 볼 수 있는 것처럼 이 페이지는 프로토타입 및 작고 수명이 짧은 웹 응용 프로그램에 유용할 수 있습니다. 하지만 페이지가 복잡하고 페이지 간 코드 공유 필요성이 증가하면 코드의 일부를 분리하는 것이 더욱 유용합니다.

  • 코드 중복 감소. DatabaseGateway 클래스의 GetRecordingsGetTracks 메서드를 이제 다른 페이지에서도 사용할 수 있습니다. 따라서 메서드를 여러 뷰로 복사할 필요가 없습니다.

  • 작업 및 문제점 분리. ASP.NET 페이지를 수정하는 데 필요한 기술은 데이터베이스를 액세스하는 코드 작성에 필요한 기술과 다릅니다. 앞서 설명한 것처럼 뷰와 모델을 분리하면 각 분야의 전문가가 동시에 작업할 수 있습니다.

  • 기회의 최적화. 앞서 설명한 것처럼 책임을 특정 클래스로 분리하면 최적화를 위한 기회가 증가됩니다. 앞에서 설명한 예에서, 요청이 있을 때마다 데이터베이스에서 데이터가 로드됩니다. 특정 상황에서 데이터를 캐싱하는 것이 가능하므로 응용 프로그램의 전체적인 성능이 향상될 수 있습니다. 하지만 이는 코드를 분리하지 않으면 어렵거나 불가능합니다.

  • 테스트 가능. 뷰에서 모델을 격리하면 ASP.NET 환경 밖에서 모델을 테스트할 수 있습니다.

    단점

    추가 코드 및 복잡성. 앞에 제시된 예는 더 많은 파일과 코드를 추가하므로 세 역할 모두를 변경해야 할 경우 코드 유지 관리 비용이 높아집니다. 어떤 경우에는 한 파일을 변경하는 것이 변경 사항을 여러 파일로 분리하는 것보다 더 쉬울 수 있습니다. 이 추가 비용은 코드 분리 이유에 불리하게 작용합니다. 작은 응용 프로그램의 경우 이러한 비용을 들일 만한 가치가 없을 수도 있습니다.

    관련 패턴

    자세한 정보는 다음 관련 패턴을 참조하십시오.

  • 테이블 데이터 게이트웨이. 이 패턴은 데이터베이스 테이블에 대해 게이트웨이 역할을 하는 개체입니다. 한 인스턴스가 한 테이블의 모든 역할을 처리합니다. [Fowler03]

  • 바운드 데이터 제어. 이 패턴은 데이터 원본에 바인딩된 사용자 인터페이스 구성 요소로서 화면 또는 페이지에 렌더링할 수 있습니다.

    참고 자료

    [Fowler03] Fowler, Martin. Patterns of Enterprise Application Architecture. Addison-Wesley, 2003.

    Patterns Practices

  • Posted by 나비:D
    :

    BLOG main image
    by 나비:D

    공지사항

    카테고리

    분류 전체보기 (278)
    Programming? (0)
    ---------------------------.. (0)
    나비의삽질 (5)
    Application (177)
    SQL (51)
    Web (27)
    etc. (14)
    Omnia (0)
    ---------------------------.. (0)

    최근에 올라온 글

    최근에 달린 댓글

    최근에 받은 트랙백

    글 보관함

    달력

    «   2024/12   »
    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
    Total :
    Today : Yesterday :