📄 listviewwindow.cpp
字号:
/* * * listviewwindow.cpp * Copyright (C) 2006 Michael H. Overlin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Contact at poster_printer@yahoo.com */#include "listviewwindow.h"#include "listviewwindow_rc.h"#include "mathutils.h"#include "sprite.h"#include <commctrl.h>#include <strsafe.h>#define ID_SCROLLTIMER 100#define SCROLLTIMER_MS 50#define LABEL_FONTNAME TEXT("Times New Roman")#define MOUSEOUTOBACCEL_GRID 20#define RULER_SIZE 30//7/6 TRY MAKING SMALLER// FIX -- MAKES MORE SINCE TO SPECIFIY 'FRAME DEPTH' AND SINGLE FRAME SIZE//#define FRAME_SIZE 4#define FRAME_SIZE 3#define DEFAULT_BKGND_COLOR ::GetSysColor( COLOR_BTNFACE )#define SELECTION_BOX_COLOR RGB(0,0,0)#define SELECTION_BOX_CORNER_SIZE 12#define SELECTION_BOX_LINE_WIDTH 6#define DEFAULT_ARROW_SEL_MODE ListViewWindow::eSelectItemsstatic const TCHAR gatstrLabelFontName[] = LABEL_FONTNAME;// THIS CLASS IS USED TO DRAW THE ARROW SELECTION RECTANGLEclass ArrowSelectionOutlineDirectPainter : public UpdateDirectLayer {public: ArrowSelectionOutlineDirectPainter(IN const RECTD& rdOld, IN const RECTD& rdNew, IN BOOL bEraseOld, IN BOOL bDrawNew, IN const RECT& rView, IN const CoordTrans &trans) : m_trans(trans) { m_rdOld = rdOld; m_rdNew = rdNew; m_bEraseOld = bEraseOld; m_bDrawNew = bDrawNew; m_rView = rView; } virtual ~ArrowSelectionOutlineDirectPainter() {} virtual void PaintDirect(HDC hdc) { ::IntersectClipRect(hdc, m_rView.left, m_rView.top, m_rView.right, m_rView.bottom); if (m_bEraseOld) { RECT rMouseSelOld; m_trans.DoTrans(m_rdOld, rMouseSelOld); ::DrawFocusRect(hdc, &rMouseSelOld); } if (m_bDrawNew) { RECT rMouseSel; m_trans.DoTrans(m_rdNew, rMouseSel); ::DrawFocusRect(hdc, &rMouseSel); } }private: RECTD m_rdOld, m_rdNew; BOOL m_bEraseOld, m_bDrawNew; RECT m_rView; const CoordTrans& m_trans;};// ****************************************************************************************************// ** class ListViewWindow **************************************************************************// ****************************************************************************************************// ***// *** PUBLIC: class ListViewWindow// ***ListViewWindow::ListViewWindow(HINSTANCE hinst, HWND hwnd) : Window(hinst, hwnd, Window::ePaintBuffered){ m_pList = NULL; m_mouseTrackMode = ListViewWindow::eNotTracking; //m_bHasMouseCapture = FALSE; m_ct = eHand; // 7/2 REMOVE //m_hcursArrow = LoadCursor(NULL, IDC_ARROW); //m_hcursHand = LoadCursor(NULL, IDC_HAND); m_hcursArrow = m_hcursHand = NULL; m_ptMouseDown.x = m_ptMouseDown.y = 0; m_ptMouseLast = m_ptMouseDown; m_prdp = NULL; //7/2 m_bDraftMode = FALSE; m_hcursTwoArrowTLBR = ::LoadCursor(hinst, MAKEINTRESOURCE(IDC_CURSOR_TWOARROWS_TLBR)); m_hcursTwoArrowTRBL = ::LoadCursor(hinst, MAKEINTRESOURCE(IDC_CURSOR_TWOARROWS_TRBL)); m_hcursFourArrow = ::LoadCursor(hinst, MAKEINTRESOURCE(IDC_CURSOR_FOURARROWS)); ::StringCbCopy(m_lfkHoriz.m_lfNew.lfFaceName, sizeof(m_lfkHoriz.m_lfNew.lfFaceName), gatstrLabelFontName); ::StringCbCopy(m_lfkVert.m_lfNew.lfFaceName, sizeof(m_lfkVert.m_lfNew.lfFaceName), gatstrLabelFontName); CalculateLayout(); // HARD CODED BACKGROUND COLOR this->SetBackgroundColor( DEFAULT_BKGND_COLOR ); SelectionBoxSprite::Spec spec; spec.nLineWidth = SELECTION_BOX_LINE_WIDTH; spec.nBoxSize = SELECTION_BOX_CORNER_SIZE; spec.clr = SELECTION_BOX_COLOR; m_arrowSelMode = DEFAULT_ARROW_SEL_MODE; m_ps = new SelectionBoxSprite(m_rView, spec); // FIX - COULD SET/UNSET AS LISTS ARE SET this->SetSprite(m_ps); HRGN hrgnClip = ::CreateRectRgnIndirect( &m_rView ); m_ps->SetClipRgn(hrgnClip); // DEBUG#if 0 SIZE sz = { 40, 40 }; POINT pt = { 10, 10 }; POINT ptV = { 1, 1 }; RECT rBounce = this->rClient(); COLORREF clr = RGB(0,0,0); NextStateRegionSprite *ps = new ::DebugBounceSprite(sz, pt, clr, rBounce, ptV); ptV.x = 4; pt.x = 200; NextStateRegionSprite *ps2 = new ::DebugBounceSprite(sz, pt, clr, rBounce, ptV); ptV.x = 2; ptV.y = 1; pt.y = 200; NextStateRegionSprite *ps3 = new ::DebugBounceSprite(sz, pt, clr, rBounce, ptV); ptV.x = 3; pt.x = 200; pt.y = 200; NextStateRegionSprite *ps4 = new ::DebugBounceSprite(sz, pt, clr, rBounce, ptV); std::vector<PNextStateRegionSprite> vSprite; vSprite.push_back(ps); vSprite.push_back(ps2); vSprite.push_back(ps3); vSprite.push_back(ps4); Sprite *pcs = new ::CompositeNextStateRegionSprite(vSprite); this->SetSprite(pcs); this->SetTimer(200, 100);#elif 0 ::SelectionBoxSprite::Spec spec; spec.nLineWidth = 6; spec.nBoxSize = 12; spec.clr = RGB(0,0,0); ::SelectionBoxSprite *ps = new ::SelectionBoxSprite(m_rView, spec); this->SetSprite(ps); RECT rBox = { 100, 100, 300, 300 }; ps->SetNextBox(rBox); this->SetTimer(200, 100);#endif}ListViewWindow::~ListViewWindow() { // NOTHING TO DELETE}//void ListViewWindow::Init(ListViewWindow::ArrowSelectionMode arrowSelMode, const SIZED& szdMinSelectionBox) {// SelectionBoxSprite::Spec spec;// spec.nLineWidth = SELECTION_BOX_LINE_WIDTH;// spec.nBoxSize = SELECTION_BOX_CORNER_SIZE;// spec.clr = SELECTION_BOX_COLOR;// m_arrowSelMode = arrowSelMode; // m_ps = new SelectionBoxSprite(m_rView, spec);//// this->SetSprite(m_ps);//// switch(m_arrowSelMode) {// case ListViewWindow::eSelectBox:// m_szdMinSelectionBox = szdMinSelectionBox;// break;// case ListViewWindow::eSelectItems:// break;// default:// ASSERTFAIL();// break;// }//}//::ViewableList* ListViewWindow::SetList(IN ViewableList *pList, IN const RulerDrawerProvider *prdp,// ListViewWindow::ArrowSelectionMode arrowSelMode, const SIZED& szdMinSelectionBox) {// ::ViewableList *pvlRetValue = m_pList;// BOOL bResetList = FALSE;// BOOL bResetSelection = TRUE;// BOOL bResetRDP = FALSE;// // 7/2// BOOL bArrowSelModeChange = FALSE;//// if (m_arrowSelMode != arrowSelMode) {// m_arrowSelMode = arrowSelMode; // bResetSelection = TRUE;// // 7/2// bArrowSelModeChange = TRUE;// }// if (m_szdMinSelectionBox.cx != szdMinSelectionBox.cx || m_szdMinSelectionBox.cy != szdMinSelectionBox.cy) {// m_szdMinSelectionBox = szdMinSelectionBox;// bResetSelection = TRUE;// }// if (m_pList != pList) {// bResetList = TRUE;// }// if (m_prdp != prdp) {// bResetRDP = TRUE;// }//// // 5/30 REORDERED TO SET NEW VARIABLE VALUES BEFORE CALL// // CONCEIVABLY THE CALCULATIONS COULD REQUIRE UP-TO-DATE STATE VARIABLE VALUES// // HAVEN'T CAREFULLY WORKED OUT HOW STATE TRANSITION SHOULD WORK, USING // // A HEURISTIC APPROACH UNFORTUNATELY// if (bResetList) {// bResetSelection = TRUE;// }// // FIRST STATE VARIABLES// if (bResetList) {// m_pList = pList;// }// if (bResetRDP) {// m_prdp = prdp;// }// // NOW NEW CALCULATIONS// if (bResetList) {// this->ResetView();// }// // 7/2// if (bArrowSelModeChange) {// this->SendNotification(ListViewWindow::eArrowSelectionModeChange);// }// if (bResetSelection) {// // 6/2// //this->ResetSelection();// switch(m_arrowSelMode) {// case ListViewWindow::eSelectBox:// this->MoveArrowSelectionBox(FALSE, NULL, FALSE, TRUE);// // FALL THRU// case ListViewWindow::eSelectItems: {// //std::vector<uint>& vsel = m_vsel;// //vsel.clear();// //int nList = m_pList->GetCount();// //vsel.insert(vsel.begin(), nList, ViewableList::eNormal);// if (m_pList == NULL || m_pList->GetCount() != m_vsel.size()) {// BOOL bNotify = this->SelModeVectorHasMode(ViewableList::eArrowSel);// int nList = ( (m_pList != NULL) ? m_pList->GetCount() : 0 );// m_vsel.clear();// m_vsel.insert(m_vsel.begin(), nList, ViewableList::eNormal);// if (bNotify) {// this->SendNotification(ListViewWindow::eArrowSelectionItemsChange);// }// }// } break;// default:// ASSERTFAIL();// break;// }//// // 5/30// // IN THIS ROUTINE WE ARE RESETTING TO DEFAULT STATE, WITHOUT // // ENSURING INVALIDATION OF DIRTY PAINT REGIONS// // THE ABOVE CALL TO "MoveArorwSelectionBox" SHOULDN'T BE USED,// // BUT SHOULD BE OK (IT DOESN'T MAKE USE OF m_pList)// ListViewWindow::HandSelState handsel;// //this->SetHandSelection(handsel);// this->m_handsel = handsel;//// this->ResetRulers();// }// if (bResetRDP) {// this->ResetRulers();// }// return pvlRetValue;//}::ViewableList* ListViewWindow::SetList(IN ViewableList *pList, IN const RulerDrawerProvider *prdp, ListViewWindow::ArrowSelectionMode arrowSelMode, const SIZED& szdMinSelectionBox) { ::ViewableList *pvlRetValue = m_pList; BOOL bResetList = FALSE; BOOL bResetSelection = TRUE; BOOL bResetRDP = FALSE; // 7/2 BOOL bArrowSelModeChange = FALSE; if (m_arrowSelMode != arrowSelMode) { m_arrowSelMode = arrowSelMode; bResetSelection = TRUE; // 7/2 bArrowSelModeChange = TRUE; } if (m_szdMinSelectionBox.cx != szdMinSelectionBox.cx || m_szdMinSelectionBox.cy != szdMinSelectionBox.cy) { m_szdMinSelectionBox = szdMinSelectionBox; bResetSelection = TRUE; } if (m_pList != pList) { bResetList = TRUE; } if (m_prdp != prdp) { bResetRDP = TRUE; } // 5/30 REORDERED TO SET NEW VARIABLE VALUES BEFORE CALL // CONCEIVABLY THE CALCULATIONS COULD REQUIRE UP-TO-DATE STATE VARIABLE VALUES // HAVEN'T CAREFULLY WORKED OUT HOW STATE TRANSITION SHOULD WORK, USING // A HEURISTIC APPROACH UNFORTUNATELY if (bResetList) { bResetSelection = TRUE; } // FIRST STATE VARIABLES if (bResetList) { m_pList = pList; } if (bResetRDP) { m_prdp = prdp; } // NOW NEW CALCULATIONS if (bResetList) { this->ResetView(); } // 7/2 if (bArrowSelModeChange) { this->SendNotification(ListViewWindow::eArrowSelectionModeChange); } if (bResetSelection) { // 6/2 //this->ResetSelection(); switch(m_arrowSelMode) { case ListViewWindow::eSelectBox: this->MoveArrowSelectionBox(FALSE, NULL, FALSE, TRUE); // FALL THRU case ListViewWindow::eSelectItems: { //std::vector<uint>& vsel = m_vsel; //vsel.clear(); //int nList = m_pList->GetCount(); //vsel.insert(vsel.begin(), nList, ViewableList::eNormal); if (m_pList == NULL || m_pList->GetCount() != m_vsel.size()) { BOOL bNotify = this->SelModeVectorHasMode(ViewableList::eArrowSel); int nList = ( (m_pList != NULL) ? m_pList->GetCount() : 0 ); m_vsel.clear(); m_vsel.insert(m_vsel.begin(), nList, ViewableList::eNormal); if (bNotify) { this->SendNotification(ListViewWindow::eArrowSelectionItemsChange); } ListViewWindow::HandSelState handsel; this->SetHandSelection(handsel); //this->m_handsel = handsel; } } break; default: ASSERTFAIL(); break; } this->ResetRulers(); } if (bResetRDP) { this->ResetRulers(); } return pvlRetValue;}void ListViewWindow::SetZoomLevel(IN double dZoom) { if (m_trans.GetZoom() != dZoom) { m_trans.SetZoom(dZoom); if (this->m_pList != NULL) { this->InvalidateRect(m_rView, TRUE); switch(m_arrowSelMode) { case ListViewWindow::eSelectBox: if (m_bHasArrowSelectionBox) { this->MoveArrowSelectionBox(TRUE, &m_rdSelectionBox, TRUE, FALSE); } break; case ListViewWindow::eSelectItems: break; default: ASSERTFAIL(); break; } } this->ResetRulers(); }}double ListViewWindow::GetZoomLevel(void) const { return m_trans.GetZoom();}BOOL ListViewWindow::HasRulerUnitLabel(RulerPlacementSpec::Direction dir) const { BOOL bRetValue = FALSE; switch(dir) { case RulerPlacementSpec::eHorizontal: bRetValue = m_rHoriz.HasUnitLabel(); break; case RulerPlacementSpec::eVertical: bRetValue = m_rVert.HasUnitLabel(); break; default: ASSERTFAIL(); break; } return bRetValue;}const tstring& ListViewWindow::GetRulerUnitLabel(RulerPlacementSpec::Direction dir) const { switch(dir) { case RulerPlacementSpec::eHorizontal: return m_rHoriz.GetUnitLabel(); case RulerPlacementSpec::eVertical: return m_rVert.GetUnitLabel(); default: ASSERTFAIL(); break; } // AVOID COMPILER ERROR return m_rHoriz.GetUnitLabel();}BOOL ListViewWindow::HasArrowSelectionBox(void) const { // I THINK m_bHasArrowSelectionBox VALUE IS ONLY VALID IF m_arrowSelMode IS eSelectBox // TEST m_pList TO BE SAFE, BUT SHOULDN'T BE NECESSARY BOOL b = m_pList != NULL && m_arrowSelMode == ListViewWindow::eSelectBox && m_bHasArrowSelectionBox; return b;}const RECTD& ListViewWindow::GetArrowSelectionBox(void) const { ASSERT(m_pList != NULL && m_arrowSelMode == ListViewWindow::eSelectBox); return this->m_rdSelectionBox;}//void ListViewWindow::SetNoSelectionBox(void) {// if (HasArrowSelectionBox()) {// this->MoveArrowSelectionBox(FALSE, NULL, FALSE, TRUE);// }//}// DEBUG - FIX -- IT'S NOT VERIFYING THAT THIS IS A VALID PLACE TO PUT THE SELECTION BOX// THAT IS WITHIN THE SELECTABLE AREA OF SOME ITEM// REALLY SELECTION SHOULD BE SOMETHING THE ITEMS KNOW ABOUT AND NOTIFY ALL WHO ARE INTERESTED -- OH WELLvoid ListViewWindow::SetArrowSelectionBox(IN BOOL bSelectionBox, const RECTD *prdSelectionBox, BOOL bSendNotification) { ASSERT(m_pList != NULL && m_arrowSelMode == ListViewWindow::eSelectBox); //this->MoveArrowSelectionBox(bSelectionBox, prdSelectionBox, FALSE, TRUE); // 7/1 FIX/DEBUG DONT SEND A NOTIFICATION FOR NOW this->MoveArrowSelectionBox(bSelectionBox, prdSelectionBox, FALSE, bSendNotification);}BOOL ListViewWindow::HasSelectionItems(void) const { BOOL b = m_pList != NULL && m_arrowSelMode == ListViewWindow::eSelectItems; if (b) { b = this->SelModeVectorHasMode(ViewableList::eArrowSel); return b; } return FALSE;}const std::vector<uint>& ListViewWindow::GetSelectionItems(void) const { return m_vsel;}void ListViewWindow::SetCursorType(IN CursorType ct) { this->EndMouseTracking(TRUE, FALSE); m_ct = ct;}// 7/2void ListViewWindow::SetDraftMode(IN BOOL bDraftMode) { //if (bDraftMode ^ m_bDraftMode) { if (lxor(bDraftMode, m_bDraftMode)) { m_bDraftMode = bDraftMode; //this->ResetView(); this->InvalidateRect(this->rClient(), TRUE); }}void ListViewWindow::SetCursorResources(IN HCURSOR hcursHand, IN HCURSOR hcursArrow) { m_hcursHand = hcursHand; m_hcursArrow = hcursArrow;}// ****// **** protected:// ****void ListViewWindow::Paint(HDC hdc) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -