third-party libs

This commit is contained in:
Benjamin Palko 2026-10-14 15:54:34 -04:00
parent f836927d3a
commit b154ee9266
3667 changed files with 854591 additions and 0 deletions

View file

@ -0,0 +1,474 @@
/*
* This is a part of the BugTrap package.
* Copyright (c) 2005-2009 IntelleSoft.
* All rights reserved.
*
* Description: Splitter control class.
* Author: Maksim Pyatkovskiy.
*
* This source code is only intended as a supplement to the
* BugTrap package reference and related electronic documentation
* provided with the product. See these sources for detailed
* information regarding the BugTrap package.
*/
#include "StdAfx.h"
#include "Splitter.h"
#include "BugTrapUtils.h"
#include "Globals.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
/**
* @param eDirection - splitter direction.
* @param bProportionalMode - proportional mode.
*/
CSplitter::CSplitter(SPLITTER_DIRECTION eDirection, bool bProportionalMode)
{
ClearPanels();
m_pfnOldSplitterWndProc = NULL;
m_bProportionalMode = bProportionalMode;
SetDirection(eDirection);
m_nSplitterSize = 0;
}
/**
* @param eDirection - new splitter direction.
*/
void CSplitter::SetDirection(SPLITTER_DIRECTION eDirection)
{
m_eDirection = eDirection;
if (m_hwnd)
ResetSplitterPos();
else
ClearSplitterPos();
}
void CSplitter::ResetSplitterPos(void)
{
_ASSERTE(m_hwnd != NULL);
m_nSplitterSize = CalcSplitterSize();
m_nSplitterPos = m_nIdealPos = m_nSplitterSize / 2;
UpdateLayout();
}
/**
* @param rect - splitter bar coordinates.
*/
void CSplitter::GetSplitterBarRect(RECT& rect) const
{
_ASSERTE(m_hwnd != NULL);
GetClientRect(m_hwnd, &rect);
int nBarSize = GetSystemMetrics(m_eDirection == SD_VERTICAL ? SM_CYFRAME : SM_CXFRAME);
int nSplitterBarEnd = m_nSplitterPos + nBarSize;
if (m_eDirection == SD_VERTICAL)
{
rect.top = m_nSplitterPos;
if (rect.bottom > nSplitterBarEnd)
rect.bottom = nSplitterBarEnd;
}
else
{
rect.left = m_nSplitterPos;
if (rect.right > nSplitterBarEnd)
rect.right = nSplitterBarEnd;
}
}
/**
* @param point - point coordinates.
* @return true if point appears in boundaries of Splitter text.
*/
BOOL CSplitter::HitTest(const POINT& point) const
{
_ASSERTE(m_hwnd != NULL);
RECT rect;
GetSplitterBarRect(rect);
return PtInRect(&rect, point);
}
/**
* @param x - point x-coordinate.
* @param y - point y-coordinate.
* @return true if point appears in boundaries of Splitter text.
*/
BOOL CSplitter::HitTest(int x, int y) const
{
POINT point;
point.x = x;
point.y = y;
return HitTest(point);
}
/**
* @param hdc - drawing context.
* @param iPanel - panel number.
* @return true if panel index is valid.
*/
BOOL CSplitter::DrawPanel(HDC hdc, int iPanel) const
{
_ASSERTE(m_hwnd != NULL);
_ASSERTE(g_pResManager != NULL);
if (iPanel >= 0 && iPanel < NUM_PANELS)
{
RECT rect;
CalcPanelRect(iPanel, rect, false);
HWND hwndPanel = m_arrPanels[iPanel];
if (hwndPanel == NULL || (GetWindowLong(hwndPanel, GWL_EXSTYLE) & WS_EX_CLIENTEDGE) == 0)
{
int nCXEdge = GetSystemMetrics(SM_CXEDGE) * 2;
int nCYEdge = GetSystemMetrics(SM_CYEDGE) * 2;
if (rect.right - rect.left >= nCXEdge && rect.bottom - rect.top >= nCYEdge)
DrawEdge(hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
}
if (hwndPanel == NULL)
FillRect(hdc, &rect, g_pResManager->m_hbrAppWorkspace);
return TRUE;
}
return FALSE;
}
/**
* @param hdc - drawing context.
*/
void CSplitter::DrawSplitter(HDC hdc) const
{
_ASSERTE(m_hwnd != NULL);
DrawSplitterBar(hdc);
DrawPanel(hdc, 0);
DrawPanel(hdc, 1);
}
/**
* @param hdc - drawing context.
*/
void CSplitter::DrawSplitterBar(HDC hdc) const
{
_ASSERTE(m_hwnd != NULL);
RECT rect;
GetSplitterBarRect(rect);
_ASSERTE(g_pResManager != NULL);
FillRect(hdc, &rect, g_pResManager->m_hbrButtonFaceBrush);
}
/**
* @param iPanel - panel number.
* @param hwndPanel - panel window handle.
* @return true if panel index is valid.
*/
BOOL CSplitter::SetPanel(int iPanel, HWND hwndPanel)
{
_ASSERTE(m_hwnd != NULL);
if (iPanel >= 0 && iPanel < NUM_PANELS)
{
m_arrPanels[iPanel] = hwndPanel;
if (hwndPanel)
{
RECT rect;
CalcPanelRect(iPanel, rect, true);
HWND hwndPanelParent = GetParent(hwndPanel);
MapWindowRect(m_hwnd, hwndPanelParent, &rect);
SetWindowPos(hwndPanel, NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);
}
return TRUE;
}
return FALSE;
}
/**
* @param iPanel - panel number.
* @param rect - panel rectangle.
* @param bShrinkRect - true if rectangle must be shrinked.
* @return true if panel index is valid.
*/
BOOL CSplitter::CalcPanelRect(int iPanel, RECT& rect, bool bShrinkRect) const
{
_ASSERTE(m_hwnd != NULL);
if (iPanel >= 0 && iPanel < NUM_PANELS)
{
GetClientRect(m_hwnd, &rect);
if (m_eDirection == SD_VERTICAL)
{
if (iPanel == 0)
rect.bottom = m_nSplitterPos;
else
{
int nBarSize = GetSystemMetrics(SM_CYFRAME);
int nSplitterBarEnd = m_nSplitterPos + nBarSize;
rect.top = rect.bottom > nSplitterBarEnd ? nSplitterBarEnd : rect.bottom;
}
}
else
{
if (iPanel == 0)
rect.right = m_nSplitterPos;
else
{
int nBarSize = GetSystemMetrics(SM_CXFRAME);
int nSplitterBarEnd = m_nSplitterPos + nBarSize;
rect.left = rect.right > nSplitterBarEnd ? nSplitterBarEnd : rect.right;
}
}
if (bShrinkRect)
{
HWND hwndPanel = m_arrPanels[iPanel];
if (hwndPanel == NULL || (GetWindowLong(hwndPanel, GWL_EXSTYLE) & WS_EX_CLIENTEDGE) == 0)
{
int nCXEdge = GetSystemMetrics(SM_CXEDGE);
int nCYEdge = GetSystemMetrics(SM_CYEDGE);
if (rect.right - rect.left >= nCXEdge * 2)
{
rect.left += nCXEdge;
rect.right -= nCXEdge;
}
if (rect.bottom - rect.top >= nCYEdge * 2)
{
rect.top += nCYEdge;
rect.bottom -= nCYEdge;
}
}
}
return TRUE;
}
return FALSE;
}
void CSplitter::UpdateLayout(void)
{
_ASSERTE(m_hwnd != NULL);
InvalidateRect(m_hwnd, NULL, FALSE);
HDWP hdwp = BeginDeferWindowPos(NUM_PANELS);
if (hdwp)
{
for (int iPanel = 0; iPanel < NUM_PANELS; ++iPanel)
{
HWND hwndPanel = m_arrPanels[iPanel];
if (hwndPanel)
{
RECT rect;
CalcPanelRect(iPanel, rect, true);
HWND hwndPanelParent = GetParent(hwndPanel);
MapWindowRect(m_hwnd, hwndPanelParent, &rect);
DeferWindowPos(hdwp, hwndPanel, NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);
}
}
EndDeferWindowPos(hdwp);
}
}
/**
* @param nSplitterSize - new splitter size.
*/
void CSplitter::ResizeSplitter(int nSplitterSize)
{
int nEdgeType, nFrameType;
if (m_eDirection == SD_VERTICAL)
{
nEdgeType = SM_CYEDGE;
nFrameType = SM_CYFRAME;
}
else
{
nEdgeType = SM_CXEDGE;
nFrameType = SM_CXFRAME;
}
int nBarSize = GetSystemMetrics(nFrameType);
int nEdgeSize = GetSystemMetrics(nEdgeType) * 2;
nSplitterSize -= nBarSize;
nSplitterSize -= nEdgeSize;
if (nSplitterSize < 0)
nSplitterSize = 0;
if (m_bProportionalMode)
m_nSplitterPos = m_nSplitterSize > 0 ? MulDiv(m_nIdealPos, nSplitterSize, m_nSplitterSize) : nSplitterSize / 2;
if (m_nSplitterPos < nEdgeSize)
m_nSplitterPos = nEdgeSize;
if (m_nSplitterPos > nSplitterSize)
m_nSplitterPos = nSplitterSize;
UpdateLayout();
}
/**
* @param nSplitterPos - new splitter position.
*/
void CSplitter::SetSplitterPos(int nSplitterPos)
{
_ASSERTE(m_hwnd != NULL);
int nEdgeSize = GetSystemMetrics(m_eDirection == SD_VERTICAL ? SM_CYEDGE : SM_CXEDGE) * 2;
int nSplitterSize = CalcSplitterSize();
if (nSplitterPos < nEdgeSize)
nSplitterPos = nEdgeSize;
if (nSplitterPos > nSplitterSize)
nSplitterPos = nSplitterSize;
if (m_nSplitterPos != nSplitterPos)
{
m_nSplitterSize = nSplitterSize;
m_nIdealPos = m_nSplitterPos = nSplitterPos;
UpdateLayout();
}
}
/**
* @param hwnd - window handle.
* @param uMsg - message identifier.
* @param wParam - first message parameter.
* @param lParam - second message parameter.
*/
LRESULT CALLBACK CSplitter::SplitterWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
int x, y, nSplitterPos, nSplitterSize;
POINT point;
HCURSOR hCursor;
PAINTSTRUCT ps;
HDC hdc;
DWORD dwResult;
CSplitter* _this = (CSplitter*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
_ASSERTE(_this != NULL);
switch(uMsg)
{
case WM_NCHITTEST:
if (GetCapture() == hwnd)
return HTCLIENT;
point.x = GET_X_LPARAM(lParam);
point.y = GET_Y_LPARAM(lParam);
ScreenToClient(hwnd, &point);
return (_this->HitTest(point) ? HTCLIENT : HTTRANSPARENT);
case WM_SETCURSOR:
_ASSERTE(g_pResManager != NULL);
dwResult = GetMessagePos();
point.x = GET_X_LPARAM(dwResult);
point.y = GET_Y_LPARAM(dwResult);
ScreenToClient(hwnd, &point);
if (_this->HitTest(point))
hCursor = _this->m_eDirection == SD_VERTICAL ? g_pResManager->m_hUpDownCursor : g_pResManager->m_hLeftRightCursor;
else
hCursor = g_pResManager->m_hArrowCursor;
if (hCursor)
{
SetCursor(hCursor);
return TRUE;
}
return FALSE;
case WM_LBUTTONDOWN:
if (GetCapture() != hwnd)
{
x = GET_X_LPARAM(lParam);
y = GET_Y_LPARAM(lParam);
if (_this->HitTest(x, y))
SetCapture(hwnd);
}
return 0;
case WM_MOUSEMOVE:
if (GetCapture() == hwnd)
{
nSplitterPos = _this->m_eDirection == SD_VERTICAL ? GET_Y_LPARAM(lParam) : GET_X_LPARAM(lParam);
_this->SetSplitterPos(nSplitterPos);
}
return 0;
case WM_LBUTTONUP:
if (GetCapture() == hwnd)
ReleaseCapture();
return 0;
case WM_CAPTURECHANGED:
return 0;
case WM_ERASEBKGND:
return TRUE;
case WM_SIZE:
nSplitterSize = _this->m_eDirection == SD_VERTICAL ? GET_Y_LPARAM(lParam) : GET_X_LPARAM(lParam);
_this->ResizeSplitter(nSplitterSize);
return 0;
case WM_PAINT:
hdc = (HDC)wParam;
if (! hdc)
{
hdc = BeginPaint(hwnd, &ps);
if (hdc)
{
_this->DrawSplitter(hdc);
EndPaint(hwnd, &ps);
}
}
else
_this->DrawSplitter(hdc);
return 0;
case WM_PRINTCLIENT:
hdc = (HDC)wParam;
_this->DrawSplitter(hdc);
return 0;
case WM_GETDLGCODE:
return DLGC_STATIC;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
/**
* @param hwnd - splitter window handle.
*/
void CSplitter::Attach(HWND hwnd)
{
_ASSERTE(hwnd != NULL);
_ASSERTE(m_hwnd == NULL);
m_hwnd = hwnd;
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)this);
m_pfnOldSplitterWndProc = SubclassWindow(hwnd, SplitterWndProc);
ResetSplitterPos();
InvalidateRect(hwnd, NULL, TRUE);
}
void CSplitter::Detach(void)
{
if (m_pfnOldSplitterWndProc)
{
SubclassWindow(m_hwnd, m_pfnOldSplitterWndProc);
SetWindowLongPtr(m_hwnd, GWLP_USERDATA, NULL);
ClearSplitterPos();
ClearPanels();
InvalidateRect(m_hwnd, NULL, TRUE);
m_pfnOldSplitterWndProc = NULL;
m_hwnd = NULL;
}
}
void CSplitter::ClearSplitterPos(void)
{
m_nIdealPos = m_nSplitterPos = m_nSplitterSize = 0;
}
void CSplitter::ClearPanels(void)
{
m_arrPanels[0] = NULL;
m_arrPanels[1] = NULL;
}
/**
* @return splitter size value.
*/
int CSplitter::CalcSplitterSize(void) const
{
_ASSERTE(m_hwnd != NULL);
RECT rect;
GetClientRect(m_hwnd, &rect);
int nSplitterSize, nEdgeType, nFrameType;
if (m_eDirection == SD_VERTICAL)
{
nSplitterSize = rect.bottom;
nEdgeType = SM_CYEDGE;
nFrameType = SM_CYFRAME;
}
else
{
nSplitterSize = rect.right;
nEdgeType = SM_CXEDGE;
nFrameType = SM_CXFRAME;
}
int nEdgeSize = GetSystemMetrics(nEdgeType) * 2;
int nBarSize = GetSystemMetrics(nFrameType);
nSplitterSize -= nBarSize;
nSplitterSize -= nEdgeSize;
if (nSplitterSize < 0)
nSplitterSize = 0;
return nSplitterSize;
}