본문 바로가기
컴퓨터/MFC_API

MSFlexGrid 사용하기

by adnoctum 2009. 12. 27.
1. 이벤트 입력 받는 방법
2. 체크 박스 흉내 내는 방법
3. 클릭된 쎌 찾는 방법



1. 이벤트 입력 받는 방법

2가지를 해 주어야 한다. active x control에서 이벤트를 받을 수 있게 event sink map을 만들어 주어야 하고, 그 이벤트들에 대한 message map을 만들어 주어야 한다.

우선 헤더 파일에,

[code cpp]
//h 파일
afx_msg void OnClickGrid();
DECLARE_EVENTSINK_MAP()
[/code]


선언을 해준 후, cpp 파일에,


[code cpp]
//CPP파일
BEGIN_EVENTSINK_MAP(CEPisDsgnMngrView, CView)
//{{AFX_EVENTSINK_MAP(CEPisDsgnMngrView)
ON_EVENT(CEPisDsgnMngrView, IDC_FLEXGRID1, -600 /* Click */, OnClickGrid, VTS_NONE)
ON_EVENT(CEPisDsgnMngrView, IDC_FLEXGRID1, -605 /* MouseDown */, OnMouseGridDown, VTS_I2 VTS_I2 VTS_I4 VTS_I4)
//}}AFX_EVENTSINK_MAP
END_EVENTSINK_MAP()
[/code]


을 적어 준다. ON_EVENT macro의 첫번째 인자는, 뷰의 이름이고, 두번째 인자는 active x의 ID이고, 세번째 인자는 이벤트에 할당된 번호이고, 네번째 인자는, 이벤트에 할당된 함수이름이고, 다섯번째 인자는 그 함수가 받을 파라미터 정보이다.

이렇게 작성한 후, cpp 파일에 함수를 만들면 된다. MSFlexGrid에 할당된 이벤트 번호는 다음과 같다.

-600 void Click();
-602 void KeyDown(short* KeyCode, short Shift);
-601 void DblClick();
-603 void KeyPress(short* KeyAscii);
-604 void KeyUp(short* KeyCode, short Shift);
-605 void MouseDown(short Button, short Shift,  OLE_XPOS_PIXELS x, OLE_YPOS_PIXELS y);
-606 void MouseMove(short Button, short Shift, OLE_XPOS_PIXELS x, OLE_YPOS_PIXELS y);
-607 void MouseUp(short Button, short Shift, OLE_XPOS_PIXELS x, OLE_YPOS_PIXELS y);
69 void SelChange();
70 void RowColChange();
71 void EnterCell();
72 void LeaveCell();
73 void Scroll();
74 void Compare(long Row1, long Row2, short* Cmp);


short 형의 파라미터 정보는 VTS_I2이다. 이것에 대한 정보는, OLE Viewer를 이용한다. 즉, Object Class --> Grouped by Component Category --> Controls --> Microsoft FlexGrid Control, version 6.0 을 오른쪽 클릭한 후, View Type Information을 선택하면 볼 수 있다.



2. 체크 박스 흉내 내는 방법


쎌에 그림을 넣어 주면 된다. 체크 박스를 집어 넣을 것이라면, 2개의 그림이 필요하다. 각각을 리소스에 비트맵으로 만들어 놓은 후 다음과 같은 함수를 이용하여 쎌에 그림을 집어 넣어 준다.

[code cpp]
CPictureHolder pic ;
pic.CreateFromBitmap(IDB_BITMAP1);
_grid.SetRefCellPicture(pic.GetPictureDispatch());
[/code]




이 때, afxctl.h 파일을 include해야 한다. 그림을 없애고 싶을 때는, pic.CreateEmpty();로 생성한 그림을 설정해 주면 된다. 쎌에 있는 그림이 어떤 그림인지를 알 수 있는 방법은 없기 때문에(그 그림을 얻을 수는 있다), 체크 박스를 흉내내기 위한 토글 기능은, 각 쎌의 정보를 따로 저장하고 있는 데이터를 이용해야 한다. STL의 vector를 이용하면 될 것이다. 즉, vector<char> 정도가 좋을 것이다. 이것은 row나 col 하나의 정보만을 저장할 때이고, 만약 행/열을 모두 고려하여 체크 박스를 넣고 싶다면, 그 정보는 map에 저장하면 될 것이다. 즉, map<pair<int, int>, char> 정도가 될 것이다.

이 방법은 이 이외에도 여러 가지로 응용이 가능하다.


3. 클릭된 쎌 찾는 방법

mouse에 의해 발생한 이벤트 처리기로 넘어 오는 좌표는 pixel 단위이다. 반면, 그리드의 GetCellWidth 함수 등으로 얻는 단위는 twip이다. 따라서 pixel 단위로 된 마우스의 좌표를 트윕으로 바꾸어 주어야 한다. 다음과 같이 한다.


[code cpp]
void CPubMedView::OnMouseUpOnGrid(short Button, short shift, long x, long y)
{ //현재 x, y는 pixel 단위
CClientDC dc(this);
long TwipsPerPixelX = 1440 / dc.GetDeviceCaps(LOGPIXELSX);
long TwipsPerPixelY = 1440 / dc.GetDeviceCaps(LOGPIXELSY);
y *= TwipsPerPixelY; // 이제 twip 단위
x *= TwipsPerPixelX; // 이제 twip 단위
[/code]



모든 쎌을 다 확인할 필요는 없고, 화면에 보이는 쎌만 확인하면 된다. 따라서,


[code cpp]
long top_row = _grid.GetTopRow(); // 화면에 보이는 쎌만 선택
[/code]


로 화면에 보이는 row만 선택한 후, 각 쎌의 왼쪽 위 좌표와 오른쪽 아래 좌표를 찾아 내서, 그 안에 마우스 포인터의 위치가 포함되는지 확인한다. 즉,


[code cpp]
// 화면에 보이는 row 부터 시작하여, 어느 위치에서 마우스가 눌렸는지 알아 낸다.
BOOL bFindClickedCell = false;
// 1000은 전체 row의 갯수. 적당히 구해서 넣어 준다.
for(int i = top_row; i<1000; i++){
    // 우선 어느 row에 속하는지부터 구한다. 어차피 row + col 단위의 시간 소요.
    _grid.SetRow(i);
    long top = _grid.GetCellTop(); // row 의 위쪽 좌표.
    // row의 아래쪽 좌표를 구하기 위해 row의 높이를 구한다.
    long height = _grid.GetRowHeight(i);
    // 현재 마우스의 y 좌표가 i 번째 row에 속하는가?
    if(top <= y && y <= top + height){
        for(int k = 0; k<10; k++){ // 만약 그렇다면, 이제 col 을 구한다.
            _grid.SetCol(k);
            // 역시 컬럼의 왼쪽 좌표를 구한다.
            long left = _grid.GetCellLeft();
            // 오른쪽 좌표를 구하기 위해, 컬럼의 폭을 구한다.
            long width = _grid.GetCellWidth();
            // 현재 마우스 x 좌표가 k 번째 컬럼에 속하는가?
            if(left <= x && x <= left + width){
                    // 찾았다! 이제 할 일을 한다.
            }
        }
    }
}
[/code]



중요한 것은, 헤더가 눌린 것은 따로 처리해 주어야 한다는 것이다.