📄 doublelistpicker.cpp
字号:
}
else
{
m_labelTitle.ShowWindow(SW_HIDE);
nTitleLabelGap = EDGE_GAP_Y;
}
if (! m_bHorizontal)
{
// something like this:
// title
// label1 label2
// | btn1 |
// list1 btn2 list2
// | btn3 |
// | btn4 |
if (! m_sLabelLeft.IsEmpty() || ! m_sLabelRight.IsEmpty())
{
// put labels at the top, offset a bit, and alter rc to chop off the label heights
int nLabelWidth = (rc.Width() - ((EDGE_GAP_X * 2) + (LIST_BTN_GAP * 2) + CX_BTN)) / 2;
m_labelLeft.MoveWindow(rc.left + EDGE_GAP_X, rc.top + nTitleLabelGap, nLabelWidth, CY_LABEL);
m_labelRight.MoveWindow((rc.left + rc.Width()) - (EDGE_GAP_X + nLabelWidth), rc.top + nTitleLabelGap, nLabelWidth, CY_LABEL);
rc.top += (nTitleLabelGap + CY_LABEL);
m_labelLeft.SetWindowText(m_sLabelLeft);
m_labelRight.SetWindowText(m_sLabelRight);
}
int nCentreX = rc.left + (rc.Width() / 2);
int nCentreY = ((rc.Height() - (nTitleLabelGap + LABEL_LIST_GAP)) / 2);
// put the buttons in the middle left-to-right
m_btnMoveRight.MoveWindow(nCentreX - (CX_BTN / 2), rc.top + (nCentreY - ((CY_BTN * 2) + BTN_BTN_GAP_SML + (BTN_BTN_GAP / 2))), CX_BTN, CY_BTN);
m_btnMoveAllRight.MoveWindow(nCentreX - (CX_BTN / 2), rc.top + (nCentreY - (CY_BTN + (BTN_BTN_GAP / 2))), CX_BTN, CY_BTN);
m_btnMoveLeft.MoveWindow(nCentreX - (CX_BTN / 2), rc.top + (nCentreY + (BTN_BTN_GAP / 2)), CX_BTN, CY_BTN);
m_btnMoveAllLeft.MoveWindow(nCentreX - (CX_BTN / 2), rc.top + (nCentreY + (CY_BTN + BTN_BTN_GAP_SML + (BTN_BTN_GAP / 2))), CX_BTN, CY_BTN);
// put lists one either side beside buttons
int nListHeight = rc.Height() - (EDGE_GAP_Y + LABEL_LIST_GAP);
int nListWidth = (rc.Width() - ((EDGE_GAP_X * 2) + (LIST_BTN_GAP * 2) + CX_BTN)) / 2;
m_listLeft.MoveWindow(rc.left + EDGE_GAP_X, rc.top + LABEL_LIST_GAP, nListWidth, nListHeight);
m_listRight.MoveWindow(rc.right - (nListWidth + EDGE_GAP_X), rc.top + LABEL_LIST_GAP, nListWidth, nListHeight);
}
else
{
// something like this:
// title
// labelleft
// listleft
// btn1 btn2 btn3 btn4
// labelright
// listright
CPoint ptCentre = rc.CenterPoint();
int nCentreX = ptCentre.x;
int nCentreY = nTitleLabelGap + ((rc.Height() - (nTitleLabelGap + LABEL_LIST_GAP)) / 2);
int nLabelHeightLeft = m_sLabelLeft.IsEmpty() ? 0 : CY_LABEL;
int nLabelHeightRight = m_sLabelRight.IsEmpty() ? 0 : CY_LABEL;
// put the buttons in the middle top-to-bottom
m_btnMoveRight.MoveWindow(nCentreX - ((CX_BTN * 2) + BTN_BTN_GAP_SML + (BTN_BTN_GAP / 2)),
rc.top + (nCentreY - (CY_BTN / 2)),
CX_BTN, CY_BTN);
m_btnMoveAllRight.MoveWindow(nCentreX - (CX_BTN + (BTN_BTN_GAP / 2)),
rc.top + (nCentreY - (CY_BTN / 2)),
CX_BTN, CY_BTN);
m_btnMoveLeft.MoveWindow(nCentreX + (BTN_BTN_GAP / 2),
rc.top + (nCentreY - (CY_BTN / 2)),
CX_BTN, CY_BTN);
m_btnMoveAllLeft.MoveWindow(nCentreX + (CX_BTN + BTN_BTN_GAP_SML + (BTN_BTN_GAP / 2)),
rc.top + (nCentreY - (CY_BTN / 2)),
CX_BTN, CY_BTN);
if (nLabelHeightLeft != 0)
nLabelHeightLeft += LABEL_LIST_GAP;
if (nLabelHeightRight != 0)
nLabelHeightRight += LABEL_LIST_GAP;
// put lists one at top, other at bottom, above and below buttons
int nListHeight = (rc.Height() - ((EDGE_GAP_Y * 2) + (LIST_BTN_GAP * 2) + CY_BTN)) / 2;
int nListWidth = rc.Width();
m_listLeft.MoveWindow(rc.left + EDGE_GAP_X, rc.top + nTitleLabelGap + nLabelHeightLeft, nListWidth, nListHeight - nLabelHeightLeft);
m_listRight.MoveWindow(rc.left + EDGE_GAP_X, (rc.bottom - (nListHeight + LABEL_LIST_GAP)) + nLabelHeightRight, nListWidth, nListHeight - nLabelHeightRight);
if (! m_sLabelLeft.IsEmpty() || ! m_sLabelRight.IsEmpty())
{
// put labels above lists top, full width
m_labelLeft.MoveWindow(rc.left + EDGE_GAP_X, rc.top + nTitleLabelGap, nListWidth, CY_LABEL);
m_labelRight.MoveWindow(rc.left + EDGE_GAP_X, rc.bottom - nListHeight, nListWidth, CY_LABEL);
m_labelLeft.SetWindowText(m_sLabelLeft);
m_labelRight.SetWindowText(m_sLabelRight);
}
}
// redraw self and the controls
RedrawWindow();
for (int n = 0; n < NUM_CTRLS; n++)
m_apCtrls[n]->RedrawWindow();
}
void CDoubleListPicker::PreSubclassWindow()
{
CStatic::PreSubclassWindow();
// grab the static text for the title, and clear the static text
GetWindowText(m_sTitle);
SetWindowText("");
// remove edges used to locate control in resource editor
// remove or modify this line if you really want the control
// to have client or static edges
ModifyStyleEx(WS_EX_CLIENTEDGE | WS_EX_STATICEDGE, 0);
CreateChildControls();
DoSizing();
}
void CDoubleListPicker::MoveListItems(BOOL bRightToLeft/*=FALSE*/, BOOL bAll/*=FALSE*/)
{
CListBox& listFrom = GetListCtrl(! bRightToLeft);
CListBox& listTo = GetListCtrl(bRightToLeft);
// get the selected item in listLeft, and move to list 2
int nSelCount = bAll ? listFrom.GetCount() : listFrom.GetSelCount();
if (nSelCount <= 0)
return;
int* pnSels = new int[nSelCount];
if (bAll)
for (int n = 0; n < nSelCount; n++) pnSels[n] = n;
else
listFrom.GetSelItems(nSelCount, pnSels);
for (int n = 0; n < nSelCount; n++)
{
CString sText;
listFrom.GetText(pnSels[n], sText);
int nIndex = listTo.AddString(sText);
listTo.SetItemData(nIndex, listFrom.GetItemData(pnSels[n]));
}
// delete items copied - need to do in reverse order
for (n = nSelCount - 1; n >= 0; n--)
listFrom.DeleteString(pnSels[n]);
delete [] pnSels;
}
void CDoubleListPicker::OnControlNotification(UINT nID, UINT nCode)
{
switch (nCode)
{
case BN_CLICKED:
switch (nID)
{
case ID_BTN_MOVE_RIGHT: MoveListItems(); break;
case ID_BTN_MOVE_ALL_RIGHT: MoveListItems(FALSE, TRUE); break;
case ID_BTN_MOVE_LEFT: MoveListItems(TRUE); break;
case ID_BTN_MOVE_ALL_LEFT: MoveListItems(TRUE, TRUE); break;
}
break;
case LBN_DBLCLK:
switch (nID)
{
case ID_LIST_LEFT: MoveListItems(); break;
case ID_LIST_RIGHT: MoveListItems(TRUE); break;
}
break;
}
}
CListBox& CDoubleListPicker::GetListCtrl(BOOL bLeft/*=TRUE*/) const
{
if (bLeft)
return (CListBox&)m_listLeft;
return (CListBox&)m_listRight;
}
CStatic& CDoubleListPicker::GetLabelCtrl(BOOL bLeft/*=TRUE*/) const
{
if (bLeft)
return (CStatic&)m_labelLeft;
return (CStatic&)m_labelRight;
}
CStatic& CDoubleListPicker::GetTitleCtrl() const
{
return (CStatic&)m_labelTitle;
}
void CDoubleListPicker::SetLabels(LPCSTR lpszLabelLeft, LPCSTR lpszLabelRight)
{
m_sLabelLeft = lpszLabelLeft;
m_sLabelRight = lpszLabelRight;
if (m_listLeft.GetSafeHwnd() != NULL)
m_labelLeft.SetWindowText(m_sLabelLeft);
if (m_listRight.GetSafeHwnd() != NULL)
m_labelRight.SetWindowText(m_sLabelRight);
// new text may mean that the control is no longer needed
// or simply that its size has changed, so do resizing
if (GetSafeHwnd() == NULL)
return;
DoSizing();
}
void CDoubleListPicker::SetTitle(LPCSTR lpszTitle/*=NULL*/)
{
m_sTitle = lpszTitle;
if (m_labelTitle.GetSafeHwnd() == NULL)
return;
m_labelTitle.SetWindowText(m_sTitle);
// new text may mean that the control is no longer needed
// or simply that its size has changed, so do resizing
DoSizing();
}
void CDoubleListPicker::RecreateList(BOOL bLeft)
{
CListBox& list = GetListCtrl(bLeft);
BOOL bSort = m_bSortListLeft;
BOOL bMultiSel = m_bMultiSelLeft;
if (! bLeft)
{
bSort = m_bSortListRight;
bMultiSel = m_bMultiSelRight;
}
if (list.GetSafeHwnd() != NULL)
{
list.ModifyStyle(bSort ? 0 : LBS_SORT, bSort ? LBS_SORT : 0);
list.ModifyStyle(bMultiSel ? 0 : LBS_EXTENDEDSEL, bMultiSel ? LBS_EXTENDEDSEL : 0);
list.ModifyStyle(0, WS_VSCROLL);
RecreateListBox(&list);
}
}
void CDoubleListPicker::SetListSort(BOOL bLeft, BOOL bSort)
{
if (bLeft)
m_bSortListLeft = bSort;
else
m_bSortListRight = bSort;
RecreateList(bLeft);
}
void CDoubleListPicker::SetListMultiSel(BOOL bLeft, BOOL bMultiSel/*=TRUE*/)
{
if (bLeft)
m_bMultiSelLeft = bMultiSel;
else
m_bMultiSelRight = bMultiSel;
RecreateList(bLeft);
}
int CDoubleListPicker::AddListItem(BOOL bLeft, LPCSTR lpszItem, DWORD dwData)
{
CListBox& list = GetListCtrl(bLeft);
int nIndex = list.AddString(lpszItem);
if (nIndex != -1)
list.SetItemData(nIndex, dwData);
return nIndex;
}
// add item to list, and return index of new item
int CDoubleListPicker::AddListItem(BOOL bLeft, LPCSTR lpszItem, LPVOID lpData)
{
return AddListItem(bLeft, lpszItem, (DWORD)lpData);
}
// add items in slistItems to list, and return number added
int CDoubleListPicker::AddListItems(BOOL bLeft, const CStringList& slistItems)
{
CListBox& list = GetListCtrl(bLeft);
POSITION pos = slistItems.GetHeadPosition();
while (pos != NULL)
list.AddString(slistItems.GetNext(pos));
return slistItems.GetCount();
}
// add items in saItems to list, and return number added
int CDoubleListPicker::AddListItems(BOOL bLeft, const CStringArray& saItems)
{
CListBox& list = GetListCtrl(bLeft);
int nNumItems = saItems.GetSize();
for (int n = 0; n < nNumItems; n++)
list.AddString(saItems.GetAt(n));
return nNumItems;
}
// get items in list and add them to slistItems, and return number added
int CDoubleListPicker::GetListItems(BOOL bLeft, CStringList &slistItems) const
{
CListBox& list = GetListCtrl(bLeft);
int nNumItems = list.GetCount();
for (int n = 0; n < nNumItems; n++)
{
CString sText;
list.GetText(n, sText);
slistItems.AddTail(sText);
}
return nNumItems;
}
// get items in list and add them to slistItems, and return number added
int CDoubleListPicker::GetListItems(BOOL bLeft, CStringArray &saItems) const
{
CListBox& list = GetListCtrl(bLeft);
int nNumItems = list.GetCount();
for (int n = 0; n < nNumItems; n++)
{
CString sText;
list.GetText(n, sText);
saItems.Add(sText);
}
return nNumItems;
}
// if we have the focus set to us, then we really need to
// set the focus to our first focus-able control, ie the left list
void CDoubleListPicker::OnSetFocus(CWnd* pOldWnd)
{
CStatic::OnSetFocus(pOldWnd);
// set the focus to the first list
m_listLeft.SetFocus();
}
void CDoubleListPicker::OnEnable(BOOL bEnable)
{
CStatic::OnEnable(bEnable);
// enable/disable all 'child' controls
for (int n = 0; n < NUM_CTRLS; n++)
m_apCtrls[n]->EnableWindow(bEnable);
}
void CDoubleListPicker::OnShowWindow(BOOL bShow, UINT nStatus)
{
CStatic::OnShowWindow(bShow, nStatus);
// show/hide all 'child' controls
for (int n = 0; n < NUM_CTRLS; n++)
m_apCtrls[n]->ShowWindow(bShow ? SW_SHOW : SW_HIDE);
if (m_sTitle.IsEmpty())
m_labelTitle.ShowWindow(SW_HIDE);
}
void CDoubleListPicker::OnWindowPosChanged(WINDOWPOS FAR* lpwndpos)
{
CStatic::OnWindowPosChanged(lpwndpos);
DoSizing();
if (lpwndpos->flags & SWP_NOZORDER)
return;
// we may have changed z-order, so re-adjust the 'child' controls
for (int n = 0; n < NUM_CTRLS; n++)
SetZOrder(m_apCtrls[n], n == 0 ? this : m_apCtrls[n - 1]);
}
LRESULT CDoubleListPicker::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_GETTEXTLENGTH:
case WM_GETTEXT:
{
if (m_labelTitle.GetSafeHwnd() != NULL)
m_labelTitle.SendMessage(message, wParam, lParam);
}
break;
case WM_SETTEXT:
{
SetTitle((LPCTSTR)lParam);
}
break;
};
return CStatic::WindowProc(message, wParam, lParam);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -