📄 bartool.cpp
字号:
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1998 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.
#include "stdafx.h"
#ifdef AFX_CORE3_SEG
#pragma code_seg(AFX_CORE3_SEG)
#endif
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define new DEBUG_NEW
/////////////////////////////////////////////////////////////////////////////
// CToolBar creation etc
#ifdef AFX_CORE3_SEG
#pragma code_seg(AFX_CORE3_SEG)
#endif
/*
DIBs use RGBQUAD format:
0xbb 0xgg 0xrr 0x00
Reasonably efficient code to convert a COLORREF into an
RGBQUAD is byte-order-dependent, so we need different
code depending on the byte order we're targeting.
*/
#define RGB_TO_RGBQUAD(r,g,b) (RGB(b,g,r))
#define CLR_TO_RGBQUAD(clr) (RGB(GetBValue(clr), GetGValue(clr), GetRValue(clr)))
struct AFX_COLORMAP
{
// use DWORD instead of RGBQUAD so we can compare two RGBQUADs easily
DWORD rgbqFrom;
int iSysColorTo;
};
AFX_STATIC_DATA const AFX_COLORMAP _afxSysColorMap[] =
{
// mapping from color in DIB to system color
{ RGB_TO_RGBQUAD(0x00, 0x00, 0x00), COLOR_BTNTEXT }, // black
{ RGB_TO_RGBQUAD(0x80, 0x80, 0x80), COLOR_BTNSHADOW }, // dark gray
{ RGB_TO_RGBQUAD(0xC0, 0xC0, 0xC0), COLOR_BTNFACE }, // bright gray
{ RGB_TO_RGBQUAD(0xFF, 0xFF, 0xFF), COLOR_BTNHIGHLIGHT } // white
};
HBITMAP AFXAPI
AfxLoadSysColorBitmap(HINSTANCE hInst, HRSRC hRsrc, BOOL bMono)
{
HGLOBAL hglb;
if ((hglb = LoadResource(hInst, hRsrc)) == NULL)
return NULL;
LPBITMAPINFOHEADER lpBitmap = (LPBITMAPINFOHEADER)LockResource(hglb);
if (lpBitmap == NULL)
return NULL;
// make copy of BITMAPINFOHEADER so we can modify the color table
const int nColorTableSize = 16;
UINT nSize = lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD);
LPBITMAPINFOHEADER lpBitmapInfo = (LPBITMAPINFOHEADER)::malloc(nSize);
if (lpBitmapInfo == NULL)
return NULL;
memcpy(lpBitmapInfo, lpBitmap, nSize);
// color table is in RGBQUAD DIB format
DWORD* pColorTable =
(DWORD*)(((LPBYTE)lpBitmapInfo) + (UINT)lpBitmapInfo->biSize);
for (int iColor = 0; iColor < nColorTableSize; iColor++)
{
// look for matching RGBQUAD color in original
for (int i = 0; i < _countof(_afxSysColorMap); i++)
{
if (pColorTable[iColor] == _afxSysColorMap[i].rgbqFrom)
{
if (bMono)
{
// all colors except text become white
if (_afxSysColorMap[i].iSysColorTo != COLOR_BTNTEXT)
pColorTable[iColor] = RGB_TO_RGBQUAD(255, 255, 255);
}
else
pColorTable[iColor] =
CLR_TO_RGBQUAD(::GetSysColor(_afxSysColorMap[i].iSysColorTo));
break;
}
}
}
int nWidth = (int)lpBitmapInfo->biWidth;
int nHeight = (int)lpBitmapInfo->biHeight;
HDC hDCScreen = ::GetDC(NULL);
HBITMAP hbm = ::CreateCompatibleBitmap(hDCScreen, nWidth, nHeight);
if (hbm != NULL)
{
HDC hDCGlyphs = ::CreateCompatibleDC(hDCScreen);
HBITMAP hbmOld = (HBITMAP)::SelectObject(hDCGlyphs, hbm);
LPBYTE lpBits;
lpBits = (LPBYTE)(lpBitmap + 1);
lpBits += (1 << (lpBitmapInfo->biBitCount)) * sizeof(RGBQUAD);
StretchDIBits(hDCGlyphs, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS, SRCCOPY);
SelectObject(hDCGlyphs, hbmOld);
::DeleteDC(hDCGlyphs);
}
::ReleaseDC(NULL, hDCScreen);
// free copy of bitmap info struct and resource itself
::free(lpBitmapInfo);
::FreeResource(hglb);
return hbm;
}
#ifdef AFX_INIT_SEG
#pragma code_seg(AFX_INIT_SEG)
#endif
struct AFX_DLLVERSIONINFO
{
DWORD cbSize;
DWORD dwMajorVersion; // Major version
DWORD dwMinorVersion; // Minor version
DWORD dwBuildNumber; // Build number
DWORD dwPlatformID; // DLLVER_PLATFORM_*
};
typedef HRESULT (CALLBACK* AFX_DLLGETVERSIONPROC)(AFX_DLLVERSIONINFO *);
int _afxComCtlVersion = -1;
DWORD AFXAPI _AfxGetComCtlVersion()
{
// return cached version if already determined...
if (_afxComCtlVersion != -1)
return _afxComCtlVersion;
// otherwise determine comctl32.dll version via DllGetVersion
HINSTANCE hInst = ::GetModuleHandleA("COMCTL32.DLL");
ASSERT(hInst != NULL);
AFX_DLLGETVERSIONPROC pfn;
pfn = (AFX_DLLGETVERSIONPROC)GetProcAddress(hInst, "DllGetVersion");
DWORD dwVersion = VERSION_WIN4;
if (pfn != NULL)
{
AFX_DLLVERSIONINFO dvi;
memset(&dvi, 0, sizeof(dvi));
dvi.cbSize = sizeof(dvi);
HRESULT hr = (*pfn)(&dvi);
if (SUCCEEDED(hr))
{
ASSERT(dvi.dwMajorVersion <= 0xFFFF);
ASSERT(dvi.dwMinorVersion <= 0xFFFF);
dwVersion = MAKELONG(dvi.dwMinorVersion, dvi.dwMajorVersion);
}
}
_afxComCtlVersion = dwVersion;
return dwVersion;
}
int _afxDropDownWidth = -1;
int AFXAPI _AfxGetDropDownWidth()
{
// return cached version if already determined...
if (_afxDropDownWidth != -1)
return _afxDropDownWidth;
// otherwise calculate it...
HDC hDC = GetDC(NULL);
ASSERT(hDC != NULL);
HFONT hFont;
if ((hFont = CreateFont(GetSystemMetrics(SM_CYMENUCHECK), 0, 0, 0,
FW_NORMAL, 0, 0, 0, SYMBOL_CHARSET, 0, 0, 0, 0, _T("Marlett"))) != NULL)
hFont = (HFONT)SelectObject(hDC, hFont);
VERIFY(GetCharWidth(hDC, '6', '6', &_afxDropDownWidth));
if (hFont != NULL)
{
SelectObject(hDC, hFont);
DeleteObject(hFont);
}
ReleaseDC(NULL, hDC);
ASSERT(_afxDropDownWidth != -1);
return _afxDropDownWidth;
}
CToolBar::CToolBar()
{
// initialize state
m_pStringMap = NULL;
m_hRsrcImageWell = NULL;
m_hInstImageWell = NULL;
m_hbmImageWell = NULL;
m_bDelayedButtonLayout = TRUE;
// default image sizes
m_sizeImage.cx = 16;
m_sizeImage.cy = 15;
// default button sizes
m_sizeButton.cx = 23;
m_sizeButton.cy = 22;
// top and bottom borders are 1 larger than default for ease of grabbing
m_cyTopBorder = 3;
m_cyBottomBorder = 3;
}
CToolBar::~CToolBar()
{
AfxDeleteObject((HGDIOBJ*)&m_hbmImageWell);
delete m_pStringMap;
m_nCount = 0;
}
BOOL CToolBar::Create(CWnd* pParentWnd, DWORD dwStyle, UINT nID)
{
return CreateEx(pParentWnd, 0, dwStyle,
CRect(m_cxLeftBorder, m_cyTopBorder, m_cxRightBorder, m_cyBottomBorder), nID);
}
BOOL CToolBar::CreateEx(CWnd* pParentWnd, DWORD dwCtrlStyle, DWORD dwStyle, CRect rcBorders, UINT nID)
{
ASSERT_VALID(pParentWnd); // must have a parent
ASSERT (!((dwStyle & CBRS_SIZE_FIXED) && (dwStyle & CBRS_SIZE_DYNAMIC)));
SetBorders(rcBorders);
// save the style
m_dwStyle = (dwStyle & CBRS_ALL);
if (nID == AFX_IDW_TOOLBAR)
m_dwStyle |= CBRS_HIDE_INPLACE;
dwStyle &= ~CBRS_ALL;
dwStyle |= CCS_NOPARENTALIGN|CCS_NOMOVEY|CCS_NODIVIDER|CCS_NORESIZE;
dwStyle |= dwCtrlStyle;
// initialize common controls
VERIFY(AfxDeferRegisterClass(AFX_WNDCOMMCTL_BAR_REG));
_AfxGetComCtlVersion();
ASSERT(_afxComCtlVersion != -1);
_AfxGetDropDownWidth();
ASSERT(_afxDropDownWidth != -1);
// create the HWND
CRect rect; rect.SetRectEmpty();
if (!CWnd::Create(TOOLBARCLASSNAME, NULL, dwStyle, rect, pParentWnd, nID))
return FALSE;
// sync up the sizes
SetSizes(m_sizeButton, m_sizeImage);
// Note: Parent must resize itself for control bar to be resized
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CToolBar
BOOL CToolBar::OnNcCreate(LPCREATESTRUCT lpCreateStruct)
{
if (!CControlBar::OnNcCreate(lpCreateStruct))
return FALSE;
// if the owner was set before the toolbar was created, set it now
if (m_hWndOwner != NULL)
DefWindowProc(TB_SETPARENT, (WPARAM)m_hWndOwner, 0);
DefWindowProc(TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
return TRUE;
}
void CToolBar::SetOwner(CWnd* pOwnerWnd)
{
ASSERT_VALID(this);
if (m_hWnd != NULL)
{
ASSERT(::IsWindow(m_hWnd));
DefWindowProc(TB_SETPARENT, (WPARAM)pOwnerWnd->GetSafeHwnd(), 0);
}
CControlBar::SetOwner(pOwnerWnd);
}
void CToolBar::SetSizes(SIZE sizeButton, SIZE sizeImage)
{
ASSERT_VALID(this);
// sizes must be non-zero and positive
ASSERT(sizeButton.cx > 0 && sizeButton.cy > 0);
ASSERT(sizeImage.cx > 0 && sizeImage.cy > 0);
// button must be big enough to hold image
// + 7 pixels on x
// + 6 pixels on y
ASSERT(sizeButton.cx >= sizeImage.cx + 7);
ASSERT(sizeButton.cy >= sizeImage.cy + 6);
if (::IsWindow(m_hWnd))
{
// set the sizes via TB_SETBITMAPSIZE and TB_SETBUTTONSIZE
VERIFY(SendMessage(TB_SETBITMAPSIZE, 0, MAKELONG(sizeImage.cx, sizeImage.cy)));
VERIFY(SendMessage(TB_SETBUTTONSIZE, 0, MAKELONG(sizeButton.cx, sizeButton.cy)));
Invalidate(); // just to be nice if called when toolbar is visible
}
else
{
// just set our internal values for later
m_sizeButton = sizeButton;
m_sizeImage = sizeImage;
}
}
void CToolBar::SetHeight(int cyHeight)
{
ASSERT_VALID(this);
int nHeight = cyHeight;
if (m_dwStyle & CBRS_BORDER_TOP)
cyHeight -= afxData.cyBorder2;
if (m_dwStyle & CBRS_BORDER_BOTTOM)
cyHeight -= afxData.cyBorder2;
m_cyBottomBorder = (cyHeight - m_sizeButton.cy) / 2;
// if there is an extra pixel, m_cyTopBorder will get it
m_cyTopBorder = cyHeight - m_sizeButton.cy - m_cyBottomBorder;
if (m_cyTopBorder < 0)
{
TRACE1("Warning: CToolBar::SetHeight(%d) is smaller than button.\n",
nHeight);
m_cyBottomBorder += m_cyTopBorder;
m_cyTopBorder = 0; // will clip at bottom
}
// recalculate the non-client region
SetWindowPos(NULL, 0, 0, 0, 0,
SWP_DRAWFRAME|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOZORDER);
Invalidate(); // just to be nice if called when toolbar is visible
}
struct CToolBarData
{
WORD wVersion;
WORD wWidth;
WORD wHeight;
WORD wItemCount;
//WORD aItems[wItemCount]
WORD* items()
{ return (WORD*)(this+1); }
};
BOOL CToolBar::LoadToolBar(LPCTSTR lpszResourceName)
{
ASSERT_VALID(this);
ASSERT(lpszResourceName != NULL);
// determine location of the bitmap in resource fork
HINSTANCE hInst = AfxFindResourceHandle(lpszResourceName, RT_TOOLBAR);
HRSRC hRsrc = ::FindResource(hInst, lpszResourceName, RT_TOOLBAR);
if (hRsrc == NULL)
return FALSE;
HGLOBAL hGlobal = LoadResource(hInst, hRsrc);
if (hGlobal == NULL)
return FALSE;
CToolBarData* pData = (CToolBarData*)LockResource(hGlobal);
if (pData == NULL)
return FALSE;
ASSERT(pData->wVersion == 1);
UINT* pItems = new UINT[pData->wItemCount];
for (int i = 0; i < pData->wItemCount; i++)
pItems[i] = pData->items()[i];
BOOL bResult = SetButtons(pItems, pData->wItemCount);
delete[] pItems;
if (bResult)
{
// set new sizes of the buttons
CSize sizeImage(pData->wWidth, pData->wHeight);
CSize sizeButton(pData->wWidth + 7, pData->wHeight + 7);
SetSizes(sizeButton, sizeImage);
// load bitmap now that sizes are known by the toolbar control
bResult = LoadBitmap(lpszResourceName);
}
UnlockResource(hGlobal);
FreeResource(hGlobal);
return bResult;
}
BOOL CToolBar::LoadBitmap(LPCTSTR lpszResourceName)
{
ASSERT_VALID(this);
ASSERT(lpszResourceName != NULL);
// determine location of the bitmap in resource fork
HINSTANCE hInstImageWell = AfxFindResourceHandle(lpszResourceName, RT_BITMAP);
HRSRC hRsrcImageWell = ::FindResource(hInstImageWell, lpszResourceName, RT_BITMAP);
if (hRsrcImageWell == NULL)
return FALSE;
// load the bitmap
HBITMAP hbmImageWell;
hbmImageWell = AfxLoadSysColorBitmap(hInstImageWell, hRsrcImageWell);
// tell common control toolbar about the new bitmap
if (!AddReplaceBitmap(hbmImageWell))
return FALSE;
// remember the resource handles so the bitmap can be recolored if necessary
m_hInstImageWell = hInstImageWell;
m_hRsrcImageWell = hRsrcImageWell;
return TRUE;
}
BOOL CToolBar::SetBitmap(HBITMAP hbmImageWell)
{
ASSERT_VALID(this);
ASSERT(hbmImageWell != NULL);
// the caller must manage changing system colors
m_hInstImageWell = NULL;
m_hRsrcImageWell = NULL;
// tell common control toolbar about the new bitmap
return AddReplaceBitmap(hbmImageWell);
}
BOOL CToolBar::AddReplaceBitmap(HBITMAP hbmImageWell)
{
// need complete bitmap size to determine number of images
BITMAP bitmap;
VERIFY(::GetObject(hbmImageWell, sizeof(BITMAP), &bitmap));
// add the bitmap to the common control toolbar
BOOL bResult;
if (m_hbmImageWell == NULL)
{
TBADDBITMAP addBitmap;
addBitmap.hInst = NULL; // makes TBADDBITMAP::nID behave a HBITMAP
addBitmap.nID = (UINT)hbmImageWell;
bResult = DefWindowProc(TB_ADDBITMAP,
bitmap.bmWidth / m_sizeImage.cx, (LPARAM)&addBitmap) == 0;
}
else
{
TBREPLACEBITMAP replaceBitmap;
replaceBitmap.hInstOld = NULL;
replaceBitmap.nIDOld = (UINT)m_hbmImageWell;
replaceBitmap.hInstNew = NULL;
replaceBitmap.nIDNew = (UINT)hbmImageWell;
replaceBitmap.nButtons = bitmap.bmWidth / m_sizeImage.cx;
bResult = (BOOL)DefWindowProc(TB_REPLACEBITMAP, 0,
(LPARAM)&replaceBitmap);
}
// remove old bitmap, if present
if (bResult)
{
AfxDeleteObject((HGDIOBJ*)&m_hbmImageWell);
m_hbmImageWell = hbmImageWell;
}
return bResult;
}
BOOL CToolBar::SetButtons(const UINT* lpIDArray, int nIDCount)
{
ASSERT_VALID(this);
ASSERT(nIDCount >= 1); // must be at least one of them
ASSERT(lpIDArray == NULL ||
AfxIsValidAddress(lpIDArray, sizeof(UINT) * nIDCount, FALSE));
// delete all existing buttons
int nCount = (int)DefWindowProc(TB_BUTTONCOUNT, 0, 0);
while (nCount--)
VERIFY(DefWindowProc(TB_DELETEBUTTON, 0, 0));
TBBUTTON button; memset(&button, 0, sizeof(TBBUTTON));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -