CListCtrl의 Drag & Drop
- CListCtrl의 row를 Drag & Drop 하는 경우를 말한다.
- 드래그 시작 시에 LVN_BEGINDRAG가, 드래그 중에 WM_MOUSEMOVE가, 드래그가 끝날 때 WM_LBUTTONUP이 발생한다
- 각 상황에 대한 처리 방법은 아래의 예제 코드를 참조
- CListCtrl의 row를 Drag & Drop 하는 경우를 말한다.
- 드래그 시작 시에 LVN_BEGINDRAG가, 드래그 중에 WM_MOUSEMOVE가, 드래그가 끝날 때 WM_LBUTTONUP이 발생한다
- 각 상황에 대한 처리 방법은 아래의 예제 코드를 참조
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
|
void CMG_HW1Dlg::OnBegindragListEditing(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
OnBegindrag(&m_listEditing, pNMHDR);
*pResult = 0;
}
void CMG_HW1Dlg::OnBegindrag(CListCtrl *list, NMHDR *pNMHDR)
{
if( list->GetSelectedCount() <= 0 )
return;
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
m_bDrag = TRUE;
m_hDragWnd = list;
CPoint pt;
CPoint hotSpotPt(pNMListView->ptAction);
m_pImageList = CreateDragImageEx(list, &pt);
if( m_pImageList == NULL )
return;
hotSpotPt -= pt;
m_pImageList->BeginDrag(0, hotSpotPt);
m_pImageList->DragEnter(NULL, pNMListView->ptAction);
m_pImageList->DragShowNolock(true);
SetCapture();
}
void CMG_HW1Dlg::OnMouseMove(UINT nFlags, CPoint point)
{
if( m_bDrag && m_hDragWnd )
{
CPoint screenPt(point);
ClientToScreen(&screenPt);
m_pImageList->DragMove(screenPt);
CWnd * hDropWnd = WindowFromPoint(screenPt);
CRect winRect;
GetWindowRect(&winRect);
BOOL bOutOfWindow = !(winRect.PtInRect(screenPt));
if( m_hDragWnd == &m_listRegistered && hDropWnd == &m_listFtpFile )
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
else if( m_hDragWnd == &m_listFtpFile && hDropWnd == &m_listRegistered )
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
else if( m_hDragWnd == &m_listFtpFile && hDropWnd == &m_listEditing )
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
else if( m_hDragWnd == &m_listEditing && hDropWnd == &m_listFtpFile )
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
else if( m_hDragWnd == &m_listRegistered && bOutOfWindow == TRUE )
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
else
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_NO));
}
CDialog::OnMouseMove(nFlags, point);
}
void CMG_HW1Dlg::OnLButtonUp(UINT nFlags, CPoint point)
{
if( m_bDrag && m_hDragWnd )
{
ReleaseCapture();
m_pImageList->DragLeave(NULL);
m_pImageList->EndDrag();
CPoint screenPt(point);
ClientToScreen(&screenPt);
CWnd * hDropWnd = WindowFromPoint(screenPt);
CRect winRect;
GetWindowRect(&winRect);
BOOL bOutOfWindow = !(winRect.PtInRect(screenPt));
if( m_hDragWnd == &m_listRegistered && hDropWnd == &m_listFtpFile )
OnButtonUpload();
else if( m_hDragWnd == &m_listFtpFile && hDropWnd == &m_listRegistered )
OnButtonDownload();
else if( m_hDragWnd == &m_listFtpFile && hDropWnd == &m_listEditing )
OnButtonEdit();
else if( m_hDragWnd == &m_listEditing && hDropWnd == &m_listFtpFile )
OnButtonApplyedit();
else if( m_hDragWnd == &m_listRegistered && bOutOfWindow == TRUE )
OnButtonUnregister();
m_bDrag = FALSE;
m_hDragWnd = NULL;
delete m_pImageList;
m_pImageList = NULL;
}
CDialog::OnLButtonUp(nFlags, point);
}
//////////////////////////////////////////////////////////////////////////
// Copied by KpsFtp
CImageList * CMG_HW1Dlg::CreateDragImageEx(CListCtrl *pList, LPPOINT lpPoint)
{
if (pList->GetSelectedCount() <= 0)
return NULL;
CRect rectSingle;
CRect rectComplete(0,0,0,0);
// Determine List Control Client width size
pList->GetClientRect(rectSingle);
int nWidth = rectSingle.Width();
// Start and Stop index in view area
int nIndex = pList->GetTopIndex() - 1;
int nBottomIndex = pList->GetTopIndex() + pList->GetCountPerPage() - 1;
if (nBottomIndex > (pList->GetItemCount() - 1))
nBottomIndex = pList->GetItemCount() - 1;
// Determine the size of the drag image (limit for rows visibled and Client width)
while ((nIndex = pList->GetNextItem(nIndex, LVNI_SELECTED)) != -1)
{
if (nIndex > nBottomIndex)
break;
pList->GetItemRect(nIndex, rectSingle, LVIR_BOUNDS);
if (rectSingle.left < 0)
rectSingle.left = 0;
if (rectSingle.right > nWidth)
rectSingle.right = nWidth;
rectComplete.UnionRect(rectComplete, rectSingle);
}
CClientDC dcClient(this);
CDC dcMem;
CBitmap Bitmap;
if (!dcMem.CreateCompatibleDC(&dcClient))
return NULL;
if (!Bitmap.CreateCompatibleBitmap(&dcClient, rectComplete.Width(), rectComplete.Height()))
return NULL;
CBitmap *pOldMemDCBitmap = dcMem.SelectObject(&Bitmap);
// Use green as mask color
dcMem.FillSolidRect(0, 0, rectComplete.Width(), rectComplete.Height(), RGB(0,255,0));
// Paint each DragImage in the DC
nIndex = pList->GetTopIndex() - 1;
while ((nIndex = pList->GetNextItem(nIndex, LVNI_SELECTED)) != -1)
{
if (nIndex > nBottomIndex)
break;
CPoint pt;
CImageList* pSingleImageList = pList->CreateDragImage(nIndex, &pt);
if (pSingleImageList)
{
pList->GetItemRect(nIndex, rectSingle, LVIR_BOUNDS);
pSingleImageList->Draw( &dcMem, 0, CPoint(rectSingle.left - rectComplete.left, rectSingle.top - rectComplete.top), ILD_MASK);
pSingleImageList->DeleteImageList();
delete pSingleImageList;
}
}
dcMem.SelectObject(pOldMemDCBitmap);
CImageList* pCompleteImageList = new CImageList;
pCompleteImageList->Create(rectComplete.Width(), rectComplete.Height(), ILC_COLOR | ILC_MASK, 0, 1);
pCompleteImageList->Add(&Bitmap, RGB(0, 255, 0)); // Green is used as mask color
Bitmap.DeleteObject();
if (lpPoint)
{
lpPoint->x = rectComplete.left;
lpPoint->y = rectComplete.top;
}
return pCompleteImageList;
}
|
'Dev.Programming > Lang.C_CPP' 카테고리의 다른 글
| [C/C++]DLL 외부에서 DLL 내부의 가변 크기 데이터를 가져오는 방법 (0) | 2007/05/29 |
|---|---|
| [C/C++] char *(*(**foo [][8])())[]; 를 해석할 줄 아는가? (0) | 2006/12/22 |
| [퍼옴]ActiveX 컨트롤에서의 IObjectSafety 인터페이스 구현 (0) | 2006/12/19 |
| [MFC]CListCtrl에 CUSTOM DRAW를 적용하는 방법 (0) | 2005/11/25 |
| [MFC]CListCtrl에 Drag & Drop 기능을 추가하는 방법 (0) | 2005/11/25 |
| [MFC]CListCtrl에 CUSTOM DRAW를 적용하는 방법 (0) | 2005/11/25 |


