- BORLAND/: Borland C++ 4.52 (chosen over 4.5 by byte-match: CODE/RP/CW32.LIB
is identical to 4.52's install lib). BCC32/TLINK32/TLIB/MAKE run natively on
Win11; CODE/BT/OPT.MAK is the shipped BTL4OPT.EXE's exact flag recipe
(extender = Borland PowerPack DPMI32, not Phar Lap TNT).
- restoration/source410/: the literal 1995-form reconstruction of the missing
BT game source (never mixed into CODE/). Round 1-3 state:
* 6 of 10 surviving original TUs COMPILE CLEAN under the period toolchain
(BTMSSN, BTCNSL, BTSCNRL, BTTEAM, BTL4MODE, BTL4ARND) - first builds
since 1996.
* BT_L4/BTL4APP.CPP pilot reconstruction: 12/12 functions, Fail() lands on
its binary-recorded line 400 exactly.
* BT/BTCNSL.HPP: console wire IDs recovered from the binary's ctors
(Killed=9, Damaged=10, ScoreUpdate=13, DeathWithoutHonor=15 [T1];
TeamScore=12 flagged [T4]).
* MUNGA/: 8 engine-header backfills back-dated from the BT412 WinTesla tree
(VDATA numbering decomp-verified; AUDREND's OpenAL-era virtual removed -
the period compiler is the drift detector).
* Tooling: backdate.py (WinTesla->1995 header transform), compile410.sh
(per-TU verification sweep under authentic OPT.MAK flags).
* README: corrected roadmap - MECH.HPP is the capstone grown with the mech
TU reconstructions; BTREG.CPP green = the header-family milestone.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
656 lines
16 KiB
C++
656 lines
16 KiB
C++
//----------------------------------------------------------------------------
|
|
// ObjectWindows
|
|
// (C) Copyright 1992, 1994 by Borland International, All Rights Reserved
|
|
//
|
|
// Implementation of class TButtonGadget.
|
|
//----------------------------------------------------------------------------
|
|
#include <owl/owlpch.h>
|
|
#include <owl/buttonga.h>
|
|
#include <owl/gadgetwi.h>
|
|
#include <owl/celarray.h>
|
|
|
|
//
|
|
// make the monochrome bitmap large enough to hold any possible bitmap
|
|
//
|
|
#define GLYPH_MASK_WIDTH 128
|
|
#define GLYPH_MASK_HEIGHT 128
|
|
const long RopPSDPxax = 0x00B8074AL; //
|
|
const long RopDSPDxax = 0x00E20746L; //
|
|
|
|
//
|
|
// local 'class' vars
|
|
//
|
|
static THatch8x8Brush ditherBrush(THatch8x8Brush::Hatch11F1,
|
|
::GetSysColor(COLOR_BTNHIGHLIGHT),
|
|
::GetSysColor(COLOR_BTNHIGHLIGHT));
|
|
|
|
static TBitmap glyphMask(GLYPH_MASK_WIDTH, GLYPH_MASK_HEIGHT, 1, 1, 0);
|
|
|
|
//
|
|
// command enabler for button gadgets
|
|
//
|
|
class _OWLCLASS TButtonGadgetEnabler : public TCommandEnabler {
|
|
public:
|
|
TButtonGadgetEnabler(HWND hWndReceiver, TButtonGadget* g)
|
|
: TCommandEnabler(g->GetId(), hWndReceiver) {
|
|
Gadget = g;
|
|
}
|
|
|
|
//
|
|
// override member functions of TCommandEnabler
|
|
//
|
|
void Enable(bool);
|
|
void SetText(const char far*);
|
|
void SetCheck(int);
|
|
|
|
protected:
|
|
TButtonGadget* Gadget;
|
|
};
|
|
|
|
void
|
|
TButtonGadgetEnabler::Enable(bool enable)
|
|
{
|
|
TCommandEnabler::Enable(enable);
|
|
Gadget->SetEnabled(enable);
|
|
}
|
|
|
|
void
|
|
TButtonGadgetEnabler::SetText(const char far*)
|
|
{
|
|
# pragma warn -ccc
|
|
CHECK(false);
|
|
# pragma warn .ccc
|
|
}
|
|
|
|
void
|
|
TButtonGadgetEnabler::SetCheck(int state)
|
|
{
|
|
Gadget->SetButtonState(TButtonGadget::TState(state));
|
|
}
|
|
|
|
TButtonGadget::TButtonGadget(TResId bmpResId,
|
|
int id,
|
|
TType type,
|
|
bool enabled,
|
|
TState state,
|
|
bool repeat)
|
|
:
|
|
TGadget(id, Plain)
|
|
{
|
|
ResId = bmpResId.IsString() ? strnewdup(bmpResId) : (char far*)bmpResId;
|
|
CelArray = 0;
|
|
BitmapOrigin.x = BitmapOrigin.y = 0;
|
|
Type = type;
|
|
Repeat = repeat;
|
|
TrackMouse = true;
|
|
State = state;
|
|
NotchCorners = true;
|
|
Pressed = false;
|
|
SetEnabled(enabled);
|
|
SetShadowStyle(DoubleShadow);
|
|
SetAntialiasEdges(true);
|
|
}
|
|
|
|
TButtonGadget::~TButtonGadget()
|
|
{
|
|
delete CelArray;
|
|
if (ResId.IsString())
|
|
delete (char far*)ResId;
|
|
}
|
|
|
|
void
|
|
TButtonGadget::SetShadowStyle(TShadowStyle shadowStyle)
|
|
{
|
|
TBorders borders;
|
|
|
|
ShadowStyle = shadowStyle;
|
|
borders.Left = borders.Top = 2;
|
|
borders.Right = borders.Bottom = ShadowStyle + 1;
|
|
SetBorders(borders);
|
|
}
|
|
|
|
void
|
|
TButtonGadget::CommandEnable()
|
|
{
|
|
// Must send, not post here, since a ptr to a temp is passed
|
|
//
|
|
Window->Parent->HandleMessage(
|
|
WM_COMMAND_ENABLE,
|
|
0,
|
|
(LPARAM)&TButtonGadgetEnabler(*Window->Parent, this)
|
|
);
|
|
}
|
|
|
|
void
|
|
TButtonGadget::SysColorChange()
|
|
{
|
|
ditherBrush.Reconstruct(THatch8x8Brush::Hatch11F1,
|
|
::GetSysColor(COLOR_BTNHIGHLIGHT),
|
|
::GetSysColor(COLOR_BTNHIGHLIGHT));
|
|
BuildCelArray();
|
|
}
|
|
|
|
void
|
|
TButtonGadget::CheckExclusively()
|
|
{
|
|
if (State != Down) {
|
|
if (Window) {
|
|
TGadget* g = Window->FirstGadget();
|
|
TButtonGadget* first = 0;
|
|
TButtonGadget* last = this;
|
|
|
|
//
|
|
// look for the start of the group in which the receiver is located
|
|
//
|
|
while (g != this) {
|
|
TButtonGadget* bg = TYPESAFE_DOWNCAST(g, TButtonGadget);
|
|
if (!bg || bg->Type != Exclusive)
|
|
first = 0;
|
|
|
|
else if (!first)
|
|
first = bg;
|
|
|
|
g = g->NextGadget();
|
|
}
|
|
if (!first)
|
|
first = this;
|
|
|
|
// Look for the end of the group in which the receiver is located
|
|
//
|
|
while (last->NextGadget()) {
|
|
TButtonGadget* bg = TYPESAFE_DOWNCAST(last->NextGadget(), TButtonGadget);
|
|
if (!bg || bg->Type != Exclusive)
|
|
break;
|
|
|
|
else
|
|
last = bg;
|
|
}
|
|
|
|
while (true) {
|
|
CHECK(first); // Already know they are buttons, but just in case...
|
|
if (first->State == Down) {
|
|
first->State = Up;
|
|
first->Invalidate();
|
|
first->Update();
|
|
}
|
|
|
|
if (first == last)
|
|
break;
|
|
|
|
first = TYPESAFE_DOWNCAST(first->NextGadget(), TButtonGadget);
|
|
}
|
|
}
|
|
|
|
State = Down;
|
|
}
|
|
}
|
|
|
|
void
|
|
TButtonGadget::SetButtonState(TState state)
|
|
{
|
|
if (state != State) {
|
|
if (Type == Exclusive && state == Down)
|
|
CheckExclusively();
|
|
|
|
State = state;
|
|
Invalidate();
|
|
Update();
|
|
}
|
|
}
|
|
|
|
void
|
|
TButtonGadget::SetBounds(TRect& bounds)
|
|
{
|
|
TRect innerRect;
|
|
TSize bitmapSize = CelArray->CelSize();
|
|
|
|
TGadget::SetBounds(bounds);
|
|
|
|
// Center the glyph within the inner bounds
|
|
//
|
|
GetInnerRect(innerRect);
|
|
|
|
BitmapOrigin.x = innerRect.left + (innerRect.Width() - bitmapSize.cx) / 2;
|
|
BitmapOrigin.y = innerRect.top + (innerRect.Height() - bitmapSize.cy) / 2;
|
|
}
|
|
|
|
void
|
|
TButtonGadget::GetDesiredSize(TSize& size)
|
|
{
|
|
TGadget::GetDesiredSize(size);
|
|
|
|
if (!CelArray)
|
|
BuildCelArray();
|
|
|
|
size += CelArray->CelSize();
|
|
}
|
|
|
|
//
|
|
// determines the parts of "r1" that do not lie within "r2"
|
|
//
|
|
// returns the resulting number of rectangles which will be in the
|
|
// range "0 .. 4" inclusive
|
|
//
|
|
uint
|
|
Subtract(TRect& r1, TRect& r2, TRect result[4])
|
|
{
|
|
if (!r1.Touches(r2)) {
|
|
result[0] = r1;
|
|
return 1;
|
|
}
|
|
else {
|
|
uint i = 0;
|
|
|
|
if (r2.top > r1.top) {
|
|
result[i].left = r1.left;
|
|
result[i].top = r1.top;
|
|
result[i].right = r1.right;
|
|
result[i].bottom = r2.top;
|
|
i++;
|
|
}
|
|
|
|
if (r2.bottom < r1.bottom) {
|
|
result[i].left = r1.left;
|
|
result[i].top = r2.bottom;
|
|
result[i].right = r1.right;
|
|
result[i].bottom = r1.bottom;
|
|
i++;
|
|
}
|
|
|
|
if (r2.left > r1.left) {
|
|
result[i].left = r1.left;
|
|
result[i].top = max(r1.top, r2.top);
|
|
result[i].right = r2.left;
|
|
result[i].bottom = min(r1.bottom, r2.bottom);
|
|
i++;
|
|
}
|
|
|
|
if (r2.right < r1.right) {
|
|
result[i].left = r2.right;
|
|
result[i].top = max(r1.top, r2.top);
|
|
result[i].right = r1.right;
|
|
result[i].bottom = min(r1.bottom, r2.bottom);
|
|
i++;
|
|
}
|
|
return i;
|
|
}
|
|
}
|
|
|
|
//
|
|
// build a monochrome mask bitmap for the glyph that has 1's where
|
|
// COLOR_BTNFACE is and 0's everywhere else. assumes glyphDC is already setup
|
|
//
|
|
static void
|
|
BuildMask(TDC& maskDC, TRect& maskRect, TDC& glyphDC, TRect& glyphRect)
|
|
{
|
|
maskDC.PatBlt(0, 0, maskRect.Width(), maskRect.Height(), WHITENESS);
|
|
glyphDC.SetBkColor(GetSysColor(COLOR_BTNFACE)); // btnface to white
|
|
maskDC.BitBlt(maskRect.left, maskRect.top, glyphRect.Width(), glyphRect.Height(),
|
|
glyphDC, glyphRect.left, glyphRect.top, SRCCOPY);
|
|
}
|
|
|
|
//
|
|
// tiles the rectangle with a even dithered (checkerboard) pattern
|
|
//
|
|
// maskDC determines the stencil area of dither
|
|
//
|
|
static void
|
|
DitherBackground(TDC& dc, TDC& maskDC, TRect& rect)
|
|
{
|
|
dc.SelectObject(HBRUSH(ditherBrush));
|
|
|
|
dc.SetTextColor(RGB(0, 0, 0)); // 0 to black
|
|
dc.SetBkColor(RGB(255, 255, 255)); // 1 to white
|
|
|
|
dc.BitBlt(rect, maskDC, TPoint(0, 0), RopDSPDxax);
|
|
}
|
|
|
|
//
|
|
// virtual function responsible for supplying glyphdib. Can be overriden to
|
|
// get dib from elsewhere, cache it, map colors differently, etc.
|
|
//
|
|
TDib*
|
|
TButtonGadget::GetGlyphDib()
|
|
{
|
|
TDib* glyph = new TDib(*Window->GetModule(), ResId);
|
|
glyph->MapUIColors(
|
|
TDib::MapFace | TDib::MapText | TDib::MapShadow | TDib::MapHighlight
|
|
);
|
|
return glyph;
|
|
}
|
|
|
|
//
|
|
// virtual function responsible for releasing glyph dib as needed based on how
|
|
// GetGlyphDib() got it (if different from new/delete).
|
|
//
|
|
void
|
|
TButtonGadget::ReleaseGlyphDib(TDib* glyph)
|
|
{
|
|
delete glyph;
|
|
}
|
|
|
|
//
|
|
// Build the CelArray member using the resource bitmap as the base glyph
|
|
// CelArray may contain an existing cel array that should be deleted if
|
|
// replaced
|
|
//
|
|
void
|
|
TButtonGadget::BuildCelArray()
|
|
{
|
|
//
|
|
// Get the base glyph as a dib, & map the colors to current SysColors.
|
|
//
|
|
TDib* glyph = GetGlyphDib();
|
|
TSize celSize = glyph->Size();
|
|
|
|
//
|
|
// Create a TCelArray if we don't already have one, else use existing one.
|
|
//
|
|
if (!CelArray) {
|
|
TBitmap* bitmap = new TBitmap(TScreenDC(), celSize.cx*CelsTotal,
|
|
celSize.cy);
|
|
CelArray = new TCelArray(bitmap, CelsTotal);
|
|
}
|
|
|
|
TMemoryDC maskDC;
|
|
maskDC.SelectObject(glyphMask);
|
|
TRect maskRect(0,0, celSize.cx, celSize.cy);
|
|
|
|
TMemoryDC celDC;
|
|
celDC.SelectObject(*CelArray);
|
|
|
|
//
|
|
// CelArray[CelNormal]: normal appearance, blit directly from the glyph dib
|
|
//
|
|
TRect nrmlCelRect = CelArray->CelRect(CelNormal);
|
|
celDC.StretchDIBits(nrmlCelRect, maskRect, *glyph);
|
|
|
|
ReleaseGlyphDib(glyph);
|
|
|
|
//
|
|
// CelArray[CelDisabled]: disabled variant of glyph
|
|
//
|
|
TRect celRect = CelArray->CelRect(CelDisabled);
|
|
|
|
//
|
|
// make sure area under highlight color ends up face color
|
|
//
|
|
BuildMask(maskDC, maskRect, celDC, nrmlCelRect);
|
|
celDC.TextRect(celRect, GetSysColor(COLOR_BTNFACE));
|
|
|
|
//
|
|
// inactivate mask--convert the highlight color to 1's on existing mask
|
|
//
|
|
celDC.SetBkColor(GetSysColor(COLOR_BTNHIGHLIGHT));
|
|
maskDC.BitBlt(maskRect, celDC, nrmlCelRect.TopLeft(), SRCPAINT);
|
|
|
|
//
|
|
// make the image look embossed--highlight color offset down & right
|
|
//
|
|
celDC.SetTextColor(RGB(0, 0, 0)); // 0 to black
|
|
celDC.SetBkColor(RGB(255, 255, 255)); // 1 to white
|
|
|
|
TBrush hiliteBrush(GetSysColor(COLOR_BTNHIGHLIGHT));
|
|
celDC.SelectObject(hiliteBrush); // 0 -> highlight color
|
|
celDC.BitBlt(celRect.left + 1, celRect.top + 1,
|
|
celRect.Width() - 1, celRect.Height() - 1,
|
|
maskDC, 0, 0, RopPSDPxax);
|
|
|
|
//
|
|
// fade the image by replacing the button text color with the button
|
|
// shadow color
|
|
//
|
|
TBrush shadowBrush(GetSysColor(COLOR_BTNSHADOW));
|
|
celDC.SelectObject(shadowBrush); // 0 -> shadow
|
|
celDC.BitBlt(celRect, maskDC, TPoint(0, 0), RopPSDPxax);
|
|
|
|
//
|
|
// CelArray[CelIndeterm]: Indeterminate variant of glyph
|
|
//
|
|
celRect = CelArray->CelRect(CelIndeterm);
|
|
|
|
//
|
|
// fade the image by replacing the button text color with the button
|
|
// shadow color
|
|
//
|
|
celDC.SelectObject(shadowBrush); // 0 -> shadow
|
|
celDC.BitBlt(celRect, maskDC, TPoint(0, 0), RopPSDPxax);
|
|
|
|
//
|
|
// dither the background everywhere except where the glyph is
|
|
//
|
|
DitherBackground(celDC, maskDC, celRect);
|
|
|
|
//
|
|
// CelArray[CelDown]: Down (but not Pressed) variant of glyph
|
|
//
|
|
celRect = CelArray->CelRect(CelDown);
|
|
celDC.BitBlt(celRect, celDC, CelArray->CelRect(CelNormal).TopLeft(), SRCCOPY);
|
|
|
|
//
|
|
// dither the background everywhere except where the glyph is
|
|
//
|
|
BuildMask(maskDC, maskRect, celDC, celRect);
|
|
DitherBackground(celDC, maskDC, celRect);
|
|
|
|
maskDC.RestoreBitmap();
|
|
celDC.RestoreBitmap();
|
|
celDC.RestoreBitmap();
|
|
celDC.RestoreBrush();
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
void
|
|
TButtonGadget::Paint(TDC& dc)
|
|
{
|
|
int cxBorder = GetSystemMetrics(SM_CXBORDER);
|
|
int cyBorder = GetSystemMetrics(SM_CYBORDER);
|
|
TPoint bitmapOrigin = BitmapOrigin;
|
|
TRect innerRect(cxBorder, cyBorder,
|
|
Bounds.Width()-cxBorder, Bounds.Height()-cyBorder);
|
|
|
|
PaintBorder(dc); // Assumes Plain border--other styles will be overpainted
|
|
|
|
TBrush faceBrush(GetSysColor(COLOR_BTNFACE));
|
|
TBrush hiliteBrush(GetSysColor(COLOR_BTNHIGHLIGHT));
|
|
TBrush shadowBrush(GetSysColor(COLOR_BTNSHADOW));
|
|
|
|
//
|
|
// draw top and left
|
|
//
|
|
int shadow = Pressed && Type != Command ? 2 : 1;
|
|
dc.SelectObject(Pressed || State == Down ? shadowBrush : hiliteBrush);
|
|
dc.PatBlt(innerRect.left, innerRect.top,
|
|
innerRect.Width(), shadow * cyBorder, PATCOPY);
|
|
dc.PatBlt(innerRect.left, innerRect.top,
|
|
shadow * cxBorder, innerRect.Height(), PATCOPY);
|
|
|
|
if (Pressed || State == Down) {
|
|
innerRect.left += shadow * cxBorder;
|
|
innerRect.top += shadow * cyBorder;
|
|
}
|
|
else {
|
|
int i = 0;
|
|
|
|
//
|
|
// draw right and bottom
|
|
//
|
|
dc.SelectObject(shadowBrush);
|
|
innerRect.bottom -= cyBorder;
|
|
innerRect.right -= cxBorder;
|
|
|
|
while (true) {
|
|
dc.PatBlt(innerRect.left, innerRect.bottom,
|
|
innerRect.Width() + cxBorder, cyBorder, PATCOPY);
|
|
dc.PatBlt(innerRect.right, innerRect.top,
|
|
cxBorder, innerRect.Height(), PATCOPY);
|
|
|
|
if (++i == ShadowStyle)
|
|
break;
|
|
|
|
innerRect.Inflate(-cxBorder, -cyBorder);
|
|
}
|
|
}
|
|
|
|
if (NotchCorners || AntialiasEdges && State == Up && !Pressed) {
|
|
dc.SelectObject(faceBrush);
|
|
|
|
if (NotchCorners) {
|
|
dc.PatBlt(0, 0, cxBorder, cyBorder);
|
|
dc.PatBlt(Bounds.Width() - cxBorder, 0, cxBorder, cyBorder);
|
|
dc.PatBlt(0, Bounds.Height() - cyBorder, cxBorder, cyBorder);
|
|
dc.PatBlt(Bounds.Width() - cxBorder, Bounds.Height() - cyBorder,
|
|
cxBorder, cyBorder);
|
|
}
|
|
if (AntialiasEdges && State == Up && !Pressed) {
|
|
TRect edge(0, 0, Bounds.Width(), Bounds.Height());
|
|
for (int i = 0; i <= shadow; i++) {
|
|
edge.Inflate(-cxBorder,-cyBorder);
|
|
dc.PatBlt(edge.right-cxBorder, edge.top, cxBorder, cyBorder);
|
|
dc.PatBlt(edge.left, edge.bottom-cyBorder, cxBorder, cyBorder);
|
|
}
|
|
}
|
|
dc.RestoreBrush();
|
|
}
|
|
|
|
//
|
|
// adjust the bitmap origin based on the state
|
|
//
|
|
if (Pressed || State == Down)
|
|
bitmapOrigin.Offset(shadow * cxBorder, shadow * cyBorder);
|
|
TRect bitmapRect(bitmapOrigin, CelArray->CelSize());
|
|
|
|
TMemoryDC celDC;
|
|
celDC.SelectObject(*CelArray);
|
|
|
|
//
|
|
// blit the appropriate cel at the calculated origin
|
|
//
|
|
if (!GetEnabled() || State == Indeterminate) {
|
|
if (!GetEnabled())
|
|
dc.BitBlt(bitmapRect, celDC, CelArray->CelRect(CelDisabled).TopLeft());
|
|
|
|
else //(State == Indeterminate)
|
|
dc.BitBlt(bitmapRect, celDC, CelArray->CelRect(CelIndeterm).TopLeft());
|
|
}
|
|
else {
|
|
TRect dirtyRects[4];
|
|
int numRects = Subtract(innerRect, bitmapRect, dirtyRects);
|
|
if (numRects) {
|
|
dc.SetBkColor(GetSysColor(COLOR_BTNFACE));
|
|
while (numRects--)
|
|
dc.TextRect(dirtyRects[numRects]);
|
|
}
|
|
if (State == Down && !Pressed)
|
|
dc.BitBlt(bitmapRect, celDC, CelArray->CelRect(CelDown).TopLeft());
|
|
else //(State == Up || Pressed)
|
|
dc.BitBlt(bitmapRect, celDC, CelArray->CelRect(CelNormal).TopLeft());
|
|
}
|
|
|
|
celDC.RestoreBitmap();
|
|
dc.RestoreBrush();
|
|
}
|
|
|
|
void
|
|
TButtonGadget::Invalidate()
|
|
{
|
|
TRect r(0, 0, Bounds.Width(), Bounds.Height());
|
|
|
|
r.Inflate(-GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
|
|
InvalidateRect(r, false);
|
|
}
|
|
|
|
//
|
|
// Begin button pressed state, repaint & enter menuselect state
|
|
//
|
|
void
|
|
TButtonGadget::BeginPressed(TPoint&)
|
|
{
|
|
Pressed = true;
|
|
Invalidate();
|
|
Update();
|
|
if (Window->GetHintMode() == TGadgetWindow::PressHints)
|
|
Window->SetHintCommand(GetId());
|
|
}
|
|
|
|
//
|
|
// Cancel pressed state, repaint & end menuselect state
|
|
//
|
|
void
|
|
TButtonGadget::CancelPressed(TPoint&)
|
|
{
|
|
Pressed = false;
|
|
Invalidate();
|
|
Update();
|
|
if (Window->GetHintMode() == TGadgetWindow::PressHints)
|
|
Window->SetHintCommand(-1);
|
|
}
|
|
|
|
void
|
|
TButtonGadget::Activate(TPoint& pt)
|
|
{
|
|
switch (Type) {
|
|
case Exclusive:
|
|
if (State != Down)
|
|
CheckExclusively();
|
|
break;
|
|
|
|
case NonExclusive:
|
|
State = State == Up ? Down : Up;
|
|
break;
|
|
}
|
|
|
|
CancelPressed(pt);
|
|
|
|
if (!(Type == Exclusive && State != Down) && GetEnabled())
|
|
Window->Parent->PostMessage(WM_COMMAND, GetId());
|
|
}
|
|
|
|
void
|
|
TButtonGadget::LButtonDown(uint modKeys, TPoint& pt)
|
|
{
|
|
TGadget::LButtonDown(modKeys, pt);
|
|
BeginPressed(pt);
|
|
}
|
|
|
|
void
|
|
TButtonGadget::MouseMove(uint modKeys, TPoint& pt)
|
|
{
|
|
TGadget::MouseMove(modKeys, pt);
|
|
|
|
bool hit = PtIn(pt);
|
|
if (Pressed) {
|
|
if (!hit)
|
|
CancelPressed(pt);
|
|
}
|
|
else if (hit) {
|
|
BeginPressed(pt);
|
|
}
|
|
}
|
|
|
|
void
|
|
TButtonGadget::MouseEnter(uint modKeys, TPoint& pt)
|
|
{
|
|
TGadget::MouseEnter(modKeys, pt);
|
|
if (Window->GetHintMode() == TGadgetWindow::EnterHints)
|
|
Window->SetHintCommand(GetId());
|
|
}
|
|
|
|
void
|
|
TButtonGadget::MouseLeave(uint modKeys, TPoint& pt)
|
|
{
|
|
TGadget::MouseLeave(modKeys, pt);
|
|
if (Window->GetHintMode() == TGadgetWindow::EnterHints)
|
|
Window->SetHintCommand(-1);
|
|
}
|
|
|
|
void
|
|
TButtonGadget::LButtonUp(uint modKeys, TPoint& pt)
|
|
{
|
|
TGadget::LButtonUp(modKeys, pt);
|
|
if (Pressed)
|
|
Activate(pt);
|
|
}
|