📄 scwinthumbs.cpp
字号:
/*
* This file is part of the EMFexplorer projet.
* Copyright (C) 2004 Smith Charles.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*
* Extension: for commercial use, apply the Equity Public License, which
* adds to the normal terms of the GLPL a condition of donation to the author.
* If you are interested in support for this source code,
* contact Smith Charles <smith.charles@free.fr> for more information.
*/
#include "stdafx.h"
#include "SCWinThumbs.h"
#include "SCGDIUtils.h"
#include <math.h>
// #ifdef _DEBUG
// #define new DEBUG_NEW
// #undef THIS_FILE
// static char THIS_FILE[] = __FILE__;
// #endif
#define SC_PIX_TXTLINE 32
#define MIN_MARGIN 16
#define SHADOW_WDT 2
#define COL_SPACE (MIN_MARGIN - (1+1+SHADOW_WDT))
#define ROW_SPACE COL_SPACE
#define SC_CTL_SYSBKGN LTGRAY_BRUSH
#define SC_THUMB_SYSBKGN COLOR_WINDOW
#define SC_THUMBNUM_COLOR RGB(255, 255, 255)
#define SC_THUMBNUM_WIDTH MIN_MARGIN
#define SC_THUMBNUM_HEIGHT MIN_MARGIN
#define SC_CURSEL_COLOR RGB(0, 0, 255)
#define SC_CURSEL_VSTROKES 3
#define SC_CURSEL_HSTROKES 3
// #define SC_UNSCALED_THUMBS
// #define SC_FULL_DCPROTRECTION
/////////////////////////////////////////////////////////////////////////////
// CSCWinThumbs
CSCWinThumbs::CSCWinThumbs():
m_pIThumbsHolder(NULL),
m_ThumbsMinSize(32,32),
m_ThumbsSize(32,32),
m_iCurSel(-1),
m_bAdjusting(FALSE),
m_uiNbThumbs(0),
m_bShowNum(TRUE),
m_uiNbRows(1),
m_uiNbCols(1),
m_iMarginX(0),
m_iMarginY(0),
m_iWorldCx(0),
m_iWorldCy(0),
m_pFont(NULL),
m_bProgessDraw(TRUE),
m_bLastSeen(FALSE)
{
}
CSCWinThumbs::~CSCWinThumbs()
{
if (m_pFont)
delete m_pFont;
}
void CSCWinThumbs::SCReset()
{
m_iCurSel = -1;
m_uiNbThumbs = 0;
m_uiNbRows = 1;
m_uiNbCols = 1;
m_iMarginX = 0;
m_iMarginY = 0;
m_iWorldCx = 0;
m_iWorldCy = 0;
}
BEGIN_MESSAGE_MAP(CSCWinThumbs, CWnd)
//{{AFX_MSG_MAP(CSCWinThumbs)
ON_WM_PAINT()
ON_WM_ERASEBKGND()
ON_WM_HSCROLL()
ON_WM_VSCROLL()
ON_WM_SIZE()
ON_WM_KEYDOWN()
ON_WM_LBUTTONDOWN()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CSCWinThumbs utilities
void CSCWinThumbs::SCInitCtl()
{
CRect rc;
GetClientRect(&rc);
m_WorkMemDC.SCPrepareSurface(rc.Width(), rc.Height(), NULL);
SCSizeScrollBars(rc.Width(), rc.Height());
SCComputeRowsCols();
}
void CSCWinThumbs::SCSetThumbsHolder(I_SCThumbsHolder* pHolder, int iNbThumbs)
{
SCReset();
m_pIThumbsHolder = pHolder;
m_uiNbThumbs = iNbThumbs;
SCComputeRowsCols();
}
void CSCWinThumbs::SCPaint(CPaintDC &dc)
{
CRect rcClient;
GetClientRect(rcClient);
int cx = rcClient.Width();
int cy = rcClient.Height();
ASSERT(m_WorkMemDC.m_hDC); // you must init it
if (!m_WorkMemDC.m_hDC)
{
dc.PatBlt(0, 0, cx, cy, BLACKNESS);
return;
}
{// paint non covered region
CBrush brush;
brush.CreateStockObject(SC_CTL_SYSBKGN);
m_WorkMemDC.FillRect(&rcClient, &brush);
}
if (!m_pIThumbsHolder || (0==m_uiNbThumbs))
{
dc.StretchBlt(0, 0, cx, cy, &m_WorkMemDC, 0, 0, cx, cy, SRCCOPY);
return;
}
COLORREF crBkColor = GetSysColor(SC_THUMB_SYSBKGN);
CBrush BkBrush;
BkBrush.CreateSolidBrush(crBkColor);
int xScroll = GetScrollPos(SB_HORZ);
int yScroll = GetScrollPos(SB_VERT);
m_WorkMemDC.SetWindowOrg(xScroll, yScroll);
int iWdt = m_ThumbsSize.cx;
int iHgt = m_ThumbsSize.cy;
int iImgCx = iWdt + COL_SPACE;
int iImgCy = iHgt + ROW_SPACE;
long uiThumbIdx;
int iRowStart = yScroll/iImgCy;
int iRowStop = 1+(yScroll+cy)/iImgCy;
if (iRowStop>m_uiNbRows)
iRowStop=m_uiNbRows;
int iColStart = xScroll/iImgCx;
int iColStop = 1+(xScroll+cx)/iImgCx;
if (iColStop>m_uiNbCols)
iColStop=m_uiNbCols;
int xDest = m_iMarginX + iColStart*iImgCx;
int yDest = m_iMarginY + iRowStart*iImgCy;
for (int iRow = iRowStart; (iRow<iRowStop); iRow++)
{
// draw visible rows
for (int iCol = iColStart; (iCol<iColStop); iCol++)
{
uiThumbIdx = iRow*m_uiNbCols + iCol;
if (uiThumbIdx>=m_uiNbThumbs)
break; // a row may be incomplete
// draw visible columns
CRect rcElem(xDest, yDest, xDest + iWdt, yDest + iHgt);
// thumb background
m_WorkMemDC.FillRect(&rcElem, &BkBrush);
// thumb image
PSCThumbImage pImage = m_pIThumbsHolder->SCGetThumbImage(uiThumbIdx);
if (pImage)
{
#ifdef SC_UNSCALED_THUMBS
GReal fScaleXY = (GReal)pImage->GetWidth()/(GReal)pImage->GetHeight();
GReal height = iHgt;
GReal width = height*fScaleXY;
if (width>iWdt)
{
width = (GReal)iWdt;
height = width/fScaleXY;
}
#else
GReal height = (GReal)pImage->GetHeight();
GReal width = (GReal)pImage->GetWidth();
#endif
GReal xPos = xDest + (iWdt - width)/2;
GReal yPos = yDest + (iHgt - height)/2;
#ifdef SC_FULL_DCPROTRECTION
// Normally, DrawImage shouldn't be able to write outside rcElem.
// But with a metafile, maybe it could.
int iState = m_WorkMemDC.SaveDC();
m_WorkMemDC.IntersectClipRect(&rcElem);
#endif
GGraphics graphics(m_WorkMemDC.GetSafeHdc());
graphics.DrawImage(pImage, xPos, yPos, width, height);
#ifdef SC_FULL_DCPROTRECTION
m_WorkMemDC.RestoreDC(iState);
#endif
}
// shadow
SCDrawFrameAndShadow(&m_WorkMemDC, xDest, yDest, iWdt, iHgt, SHADOW_WDT, crBkColor);
// thumb number
if (m_bShowNum)
SCDrawNumber(xDest, yDest, uiThumbIdx);
// if we are on the current thumb, show selection
if (uiThumbIdx==m_iCurSel)
{
CBrush Brush;
Brush.CreateSolidBrush(SC_CURSEL_COLOR);
CRgn Rgn;
Rgn.CreateRectRgnIndirect(&rcElem);
m_WorkMemDC.FrameRgn(&Rgn, &Brush, SC_CURSEL_VSTROKES, SC_CURSEL_HSTROKES);
Rgn.DeleteObject();
Brush.DeleteObject();
}
if (m_bProgessDraw && !m_bLastSeen)
{// show progressively
dc.StretchBlt(0, 0, cx, cy, &m_WorkMemDC, xScroll, yScroll, cx, cy, SRCCOPY);
}
xDest += iImgCx;
}
yDest += iImgCy;
xDest = m_iMarginX;
}
m_WorkMemDC.SetWindowOrg(0, 0);
dc.StretchBlt(0, 0, cx, cy, &m_WorkMemDC, 0, 0, cx, cy, SRCCOPY);
if (uiThumbIdx==m_uiNbThumbs)
m_bLastSeen = TRUE; // TODO: fix this or don't use it
// Do not call CWnd::OnPaint()
}
void CSCWinThumbs::SCDrawNumber(int xDest, int yDest, UINT uiThumbIdx)
{
CFont* pOldFont = (m_pFont) ? m_WorkMemDC.SelectObject(m_pFont) : NULL;
COLORREF crOldColor = m_WorkMemDC.SetTextColor(SC_THUMBNUM_COLOR);
int iOldBkMode = m_WorkMemDC.SetBkMode(TRANSPARENT);
CRect rcNum(xDest, yDest, xDest + SC_THUMBNUM_WIDTH, yDest + SC_THUMBNUM_HEIGHT);
CBrush brush;
brush.CreateStockObject(BLACK_BRUSH);
m_WorkMemDC.FillRect(&rcNum, &brush);
CString strNum;
strNum.Format(_T("%d"), uiThumbIdx);
CSize size = m_WorkMemDC.GetTextExtent(strNum);
m_WorkMemDC.TextOut(rcNum.left + (rcNum.Width()- size.cx)/2,
rcNum.top + (rcNum.Height()- size.cy)/2,
strNum, strNum.GetLength());
m_WorkMemDC.SetBkMode(iOldBkMode);
if (pOldFont)
m_WorkMemDC.SelectObject(pOldFont);
m_WorkMemDC.SetTextColor(crOldColor);
}
void CSCWinThumbs::SCInitializeScrollBars(int width, int height)
{
RECT rClient;
SCROLLINFO ScrollInfo;
// Get windows client size.
GetClientRect(&rClient);
// If client size is equel to dib size, then add one to client size
// so that we don't show scroll bars.
// However, if client size is less than dib size, subtract scroll bar
// size form client size so that page size will be correct when
// scroll bars are shown.
if (rClient.bottom == height)
++rClient.bottom;
else if (rClient.bottom < height)
rClient.bottom -= GetSystemMetrics (SM_CYHSCROLL);
if (rClient.right == width)
++rClient.right;
else if (rClient.right < width)
rClient.right -= GetSystemMetrics (SM_CXVSCROLL);
// Initialize vertical scroll bar.
ScrollInfo.cbSize = sizeof(SCROLLINFO);
ScrollInfo.fMask = SIF_ALL;
ScrollInfo.nMin = 0;
ScrollInfo.nMax = height;
ScrollInfo.nPage = rClient.bottom;
SetScrollInfo(SB_VERT, &ScrollInfo, TRUE);
// Initialize horizontal scroll bar.
ScrollInfo.nMax = width;
ScrollInfo.nPage = rClient.right;
SetScrollInfo(SB_HORZ, &ScrollInfo, TRUE);
}
BOOL CSCWinThumbs::ScrollChildWindow(int nScrollBar, UINT wScrollCode, int iCount /*=1*/)
{
int nPosition;
int nHorzScroll = 0;
int nVertScroll = 0;
SCROLLINFO ScrollInfo;
// Get current scroll information.
ZeroMemory(&ScrollInfo, sizeof(SCROLLINFO));
ScrollInfo.cbSize = sizeof(SCROLLINFO);
ScrollInfo.fMask = SIF_ALL;
if (!GetScrollInfo(nScrollBar, &ScrollInfo))
{
int error = GetLastError();
return FALSE;
}
nPosition = ScrollInfo.nPos;
// Modify scroll information based on requested
// scroll action.
switch (wScrollCode)
{
case SB_LINEDOWN:
ScrollInfo.nPos += SC_PIX_TXTLINE*iCount;
break;
case SB_LINEUP:
ScrollInfo.nPos -= SC_PIX_TXTLINE*iCount;
break;
case SB_PAGEDOWN:
ScrollInfo.nPos += ScrollInfo.nPage*iCount;
break;
case SB_PAGEUP:
ScrollInfo.nPos -= ScrollInfo.nPage*iCount;
break;
case SB_TOP:
ScrollInfo.nPos = ScrollInfo.nMin;
break;
case SB_BOTTOM:
ScrollInfo.nPos = ScrollInfo.nMax;
break;
// Don't do anything.
case SB_THUMBTRACK:
return TRUE;
case SB_THUMBPOSITION:
ScrollInfo.nPos = ScrollInfo.nTrackPos;
break;
case SB_ENDSCROLL:
default:
return FALSE;
}
// Make sure that scroll position is in range.
if (0 > ScrollInfo.nPos)
ScrollInfo.nPos = 0;
else if (ScrollInfo.nMax - (int) ScrollInfo.nPage + 1 < ScrollInfo.nPos)
ScrollInfo.nPos = ScrollInfo.nMax - ScrollInfo.nPage + 1;
// Set new scroll position.
ScrollInfo.fMask = SIF_POS;
SetScrollInfo(nScrollBar, &ScrollInfo, TRUE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -