814 lines
19 KiB
C
814 lines
19 KiB
C
/******************************Module*Header*******************************\
|
|
* Module Name: buttons.c
|
|
*
|
|
* Bitmap button support. On Daytona bitmap buttons are provided by
|
|
* mmcntrls. On Chicago there is no mmcntrls, so we use the functions
|
|
* in this file.
|
|
*
|
|
*
|
|
* Created: 19-04-94
|
|
* Author: Stephen Estrop [StephenE]
|
|
*
|
|
* Copyright (c) 1993 Microsoft Corporation
|
|
\**************************************************************************/
|
|
#pragma warning( once : 4201 4214 )
|
|
|
|
#define NOOLE
|
|
#include <windows.h>
|
|
#include <windowsx.h>
|
|
#include <commctrl.h>
|
|
|
|
#include "buttons.h"
|
|
#include "literals.h"
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
** Color globals
|
|
** -------------------------------------------------------------------------
|
|
*/
|
|
int nSysColorChanges = 0;
|
|
DWORD rgbFace;
|
|
DWORD rgbShadow;
|
|
DWORD rgbHilight;
|
|
DWORD rgbFrame;
|
|
|
|
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* PatB
|
|
*
|
|
* Fast way to fill an rectangle with a solid colour.
|
|
*
|
|
* History:
|
|
* 18-11-93 - StephenE - Created
|
|
*
|
|
\**************************************************************************/
|
|
void
|
|
PatB(
|
|
HDC hdc,
|
|
int x,
|
|
int y,
|
|
int dx,
|
|
int dy,
|
|
DWORD rgb
|
|
)
|
|
{
|
|
RECT rc;
|
|
|
|
SetBkColor(hdc,rgb);
|
|
rc.left = x;
|
|
rc.top = y;
|
|
rc.right = x + dx;
|
|
rc.bottom = y + dy;
|
|
|
|
ExtTextOut(hdc,0,0,ETO_OPAQUE,&rc,NULL,0,NULL);
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* CheckSysColors
|
|
*
|
|
* Checks the system colors and updates the cached global variables if
|
|
* they have changed.
|
|
*
|
|
* History:
|
|
* 18-11-93 - StephenE - Created
|
|
*
|
|
\**************************************************************************/
|
|
void
|
|
CheckSysColors(
|
|
void
|
|
)
|
|
{
|
|
static COLORREF rgbSaveFace = 0xffffffffL,
|
|
rgbSaveShadow = 0xffffffffL,
|
|
rgbSaveHilight = 0xffffffffL,
|
|
rgbSaveFrame = 0xffffffffL;
|
|
|
|
rgbFace = GetSysColor(COLOR_BTNFACE);
|
|
rgbShadow = GetSysColor(COLOR_BTNSHADOW);
|
|
rgbHilight = GetSysColor(COLOR_BTNHIGHLIGHT);
|
|
rgbFrame = GetSysColor(COLOR_WINDOWFRAME);
|
|
|
|
if (rgbSaveFace!=rgbFace || rgbSaveShadow!=rgbShadow
|
|
|| rgbSaveHilight!=rgbHilight || rgbSaveFrame!=rgbFrame)
|
|
{
|
|
++nSysColorChanges;
|
|
|
|
rgbSaveFace = rgbFace;
|
|
rgbSaveShadow = rgbShadow;
|
|
rgbSaveHilight = rgbHilight;
|
|
rgbSaveFrame = rgbFrame;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
** Button globals -- some of these should be constants
|
|
** -------------------------------------------------------------------------
|
|
*/
|
|
const TCHAR szBbmProp[] = TEXT("ButtonBitmapProp");
|
|
const TCHAR szButtonProp[] = TEXT("ButtonProp");
|
|
|
|
typedef struct tagBTNSTATE { /* instance data for toolbar window */
|
|
WNDPROC lpfnDefProc;
|
|
HWND hwndToolTips;
|
|
HINSTANCE hInst;
|
|
UINT wID;
|
|
UINT uStyle;
|
|
HBITMAP hbm;
|
|
HDC hdcGlyphs;
|
|
HDC hdcMono;
|
|
HBITMAP hbmMono;
|
|
HBITMAP hbmDefault;
|
|
int dxBitmap;
|
|
int dyBitmap;
|
|
int nButtons;
|
|
int nSysColorChanges;
|
|
BITMAPBTN Buttons[1];
|
|
} BTNSTATE, NEAR *PBTNSTATE, FAR *LPBTNSTATE;
|
|
|
|
typedef struct {
|
|
WNDPROC lpfnDefProc;
|
|
HWND hwndParent;
|
|
HWND hwndToolTips;
|
|
} BTN_INFO, *LPBTN_INFO;
|
|
|
|
|
|
LRESULT CALLBACK
|
|
ButtonSubclassProc(
|
|
HWND hwnd,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
);
|
|
|
|
LRESULT CALLBACK
|
|
ParentSubclassProc(
|
|
HWND hwnd,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
);
|
|
|
|
void FAR PASCAL
|
|
RelayToToolTips(
|
|
HWND hwndToolTips,
|
|
HWND hWnd,
|
|
UINT wMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
);
|
|
|
|
BOOL
|
|
InitObjects(
|
|
LPBTNSTATE pTBState
|
|
);
|
|
|
|
BOOL
|
|
FreeObjects(
|
|
LPBTNSTATE pTBState
|
|
);
|
|
|
|
void
|
|
CreateButtonMask(
|
|
LPBTNSTATE pTBState,
|
|
PBITMAPBTN pTBButton
|
|
);
|
|
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* InitObjects
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* 18-11-93 - StephenE - Created
|
|
*
|
|
\**************************************************************************/
|
|
BOOL
|
|
InitObjects(
|
|
LPBTNSTATE pTBState
|
|
)
|
|
{
|
|
pTBState->hdcGlyphs = CreateCompatibleDC(NULL);
|
|
if (pTBState->hdcGlyphs == NULL ) {
|
|
return FALSE;
|
|
}
|
|
|
|
pTBState->hdcMono = CreateCompatibleDC(NULL);
|
|
if (pTBState->hdcMono == NULL ) {
|
|
DeleteObject( pTBState->hdcGlyphs );
|
|
return FALSE;
|
|
}
|
|
|
|
pTBState->hbmMono = CreateBitmap( pTBState->dxBitmap,
|
|
pTBState->dyBitmap, 1, 1, NULL);
|
|
if ( pTBState->hbmMono == NULL ) {
|
|
DeleteObject( pTBState->hdcGlyphs );
|
|
DeleteObject( pTBState->hdcMono );
|
|
return FALSE;
|
|
}
|
|
|
|
pTBState->hbmDefault = SelectObject(pTBState->hdcMono, pTBState->hbmMono);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* FreeObjects
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* 18-11-93 - StephenE - Created
|
|
*
|
|
\**************************************************************************/
|
|
BOOL
|
|
FreeObjects(
|
|
LPBTNSTATE pTBState
|
|
)
|
|
{
|
|
if (pTBState->hdcMono) {
|
|
SelectObject(pTBState->hdcMono, pTBState->hbmDefault);
|
|
DeleteDC(pTBState->hdcMono); /* toast the DCs */
|
|
}
|
|
|
|
if (pTBState->hdcGlyphs) {
|
|
DeleteDC(pTBState->hdcGlyphs);
|
|
}
|
|
|
|
if (pTBState->hbmMono) {
|
|
DeleteObject(pTBState->hbmMono);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* CreateButtonMask
|
|
*
|
|
* create a mono bitmap mask:
|
|
* 1's where color == COLOR_BTNFACE || COLOR_HILIGHT
|
|
* 0's everywhere else
|
|
*
|
|
*
|
|
* History:
|
|
* 18-11-93 - StephenE - Created
|
|
*
|
|
\**************************************************************************/
|
|
void
|
|
CreateButtonMask(
|
|
LPBTNSTATE pTBState,
|
|
PBITMAPBTN pTBButton
|
|
)
|
|
{
|
|
/* initalize whole area with 0's */
|
|
PatBlt( pTBState->hdcMono, 0, 0, pTBState->dxBitmap,
|
|
pTBState->dyBitmap, WHITENESS);
|
|
|
|
/* create mask based on color bitmap
|
|
** convert this to 1's
|
|
*/
|
|
SetBkColor(pTBState->hdcGlyphs, rgbFace);
|
|
BitBlt( pTBState->hdcMono, 0, 0, pTBState->dxBitmap, pTBState->dyBitmap,
|
|
pTBState->hdcGlyphs, pTBButton->iBitmap * pTBState->dxBitmap, 0,
|
|
SRCCOPY );
|
|
|
|
/* convert this to 1's */
|
|
SetBkColor(pTBState->hdcGlyphs, rgbHilight);
|
|
|
|
/* OR in the new 1's */
|
|
BitBlt( pTBState->hdcMono, 0, 0, pTBState->dxBitmap, pTBState->dyBitmap,
|
|
pTBState->hdcGlyphs, pTBButton->iBitmap * pTBState->dxBitmap, 0,
|
|
SRCPAINT );
|
|
}
|
|
|
|
|
|
|
|
#define PSDPxax 0x00B8074A
|
|
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* BtnDrawButton
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* 18-11-93 - StephenE - Created
|
|
*
|
|
\**************************************************************************/
|
|
void WINAPI
|
|
BtnDrawButton(
|
|
HWND hwnd,
|
|
HDC hdc,
|
|
int dx,
|
|
int dy,
|
|
LPBITMAPBTN ptButton
|
|
)
|
|
{
|
|
int glyph_offset;
|
|
HBRUSH hbrOld, hbr;
|
|
BOOL bMaskCreated = FALSE;
|
|
RECT rcFocus;
|
|
PBTNSTATE pTBState;
|
|
int x = 0, y = 0;
|
|
|
|
|
|
pTBState = (PBTNSTATE)GetProp(hwnd, szBbmProp);
|
|
|
|
CheckSysColors();
|
|
if (pTBState->nSysColorChanges != nSysColorChanges) {
|
|
|
|
DeleteObject( pTBState->hbm );
|
|
pTBState->hbm = CreateMappedBitmap( pTBState->hInst,
|
|
pTBState->wID, TRUE, NULL, 0);
|
|
pTBState->nSysColorChanges = nSysColorChanges;
|
|
}
|
|
|
|
/*
|
|
** erase with face color
|
|
*/
|
|
|
|
PatB(hdc, x, y, dx, dy, rgbFace);
|
|
SetRect( &rcFocus, x, y, x + dx, y + dy );
|
|
|
|
if (ptButton->fsState & BTNSTATE_PRESSED) {
|
|
DrawEdge( hdc, &rcFocus, EDGE_SUNKEN, BF_RECT );
|
|
glyph_offset = 1;
|
|
}
|
|
else {
|
|
DrawEdge( hdc, &rcFocus, EDGE_RAISED, BF_RECT );
|
|
glyph_offset = 0;
|
|
}
|
|
|
|
|
|
/*
|
|
** make the coordinates the interior of the button
|
|
*/
|
|
x += 2;
|
|
y += 2;
|
|
dx -= 4;
|
|
dy -= 4;
|
|
|
|
SelectObject( pTBState->hdcGlyphs, pTBState->hbm );
|
|
|
|
/* now put on the face */
|
|
|
|
/*
|
|
** We need to centre the Bitmap here within the button
|
|
*/
|
|
x += (dx - pTBState->dxBitmap ) / 2;
|
|
y += (dy - pTBState->dyBitmap ) / 2;
|
|
|
|
if (!(ptButton->fsState & BTNSTATE_DISABLED)) {
|
|
|
|
/* regular version */
|
|
BitBlt( hdc, x + glyph_offset, y + glyph_offset,
|
|
pTBState->dxBitmap, pTBState->dyBitmap,
|
|
pTBState->hdcGlyphs,
|
|
ptButton->iBitmap * pTBState->dxBitmap, 0, SRCCOPY);
|
|
}
|
|
else {
|
|
|
|
/* disabled version */
|
|
bMaskCreated = TRUE;
|
|
CreateButtonMask(pTBState, ptButton );
|
|
|
|
SetTextColor(hdc, 0L); /* 0's in mono -> 0 (for ROP) */
|
|
SetBkColor(hdc, 0x00FFFFFF); /* 1's in mono -> 1 */
|
|
|
|
hbr = CreateSolidBrush(rgbHilight);
|
|
if (hbr) {
|
|
hbrOld = SelectObject(hdc, hbr);
|
|
if (hbrOld) {
|
|
/* draw hilight color where we have 0's in the mask */
|
|
BitBlt( hdc, x + 1, y + 1,
|
|
pTBState->dxBitmap, pTBState->dyBitmap,
|
|
pTBState->hdcMono, 0, 0, PSDPxax);
|
|
SelectObject(hdc, hbrOld);
|
|
}
|
|
DeleteObject(hbr);
|
|
}
|
|
|
|
hbr = CreateSolidBrush(rgbShadow);
|
|
if (hbr) {
|
|
hbrOld = SelectObject(hdc, hbr);
|
|
if (hbrOld) {
|
|
/* draw the shadow color where we have 0's in the mask */
|
|
BitBlt(hdc, x, y, pTBState->dxBitmap, pTBState->dyBitmap,
|
|
pTBState->hdcMono, 0, 0, PSDPxax);
|
|
SelectObject(hdc, hbrOld);
|
|
}
|
|
DeleteObject(hbr);
|
|
}
|
|
}
|
|
|
|
if (ptButton->fsState & ODS_FOCUS) {
|
|
|
|
BtnDrawFocusRect(hdc, &rcFocus, ptButton->fsState);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*****************************Private*Routine******************************\
|
|
* BtnCreateBitmapButtons
|
|
*
|
|
* Returns TRUE if successful, otherwise FALSE;
|
|
*
|
|
* History:
|
|
* 18-11-93 - StephenE - Created
|
|
*
|
|
\**************************************************************************/
|
|
BOOL WINAPI
|
|
BtnCreateBitmapButtons(
|
|
HWND hWnd,
|
|
HINSTANCE hInst,
|
|
UINT wID,
|
|
UINT uStyle,
|
|
LPBITMAPBTN lpButtons,
|
|
int nButtons,
|
|
int dxBitmap,
|
|
int dyBitmap
|
|
)
|
|
{
|
|
PBTNSTATE pTBState;
|
|
|
|
|
|
/*
|
|
** If we have already created Bitmap Buttons for this
|
|
** window just return.
|
|
*/
|
|
if (GetProp(hWnd, szBbmProp)) {
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
CheckSysColors();
|
|
|
|
/*
|
|
** Allocate the required storage and save the pointer in the window
|
|
** property list.
|
|
*/
|
|
pTBState = (PBTNSTATE)LocalAlloc( LMEM_FIXED,
|
|
(sizeof(BTNSTATE) - sizeof(BITMAPBTN)) +
|
|
(nButtons * sizeof(BITMAPBTN)) );
|
|
if (pTBState == NULL ) {
|
|
return FALSE;
|
|
}
|
|
SetProp(hWnd, szBbmProp, (HANDLE)pTBState);
|
|
|
|
|
|
pTBState->hInst = hInst;
|
|
pTBState->wID = wID;
|
|
pTBState->uStyle = uStyle;
|
|
pTBState->nButtons = nButtons;
|
|
pTBState->hbm = CreateMappedBitmap( hInst, wID, TRUE, NULL, 0);
|
|
pTBState->dxBitmap = dxBitmap;
|
|
pTBState->dyBitmap = dyBitmap;
|
|
|
|
InitObjects( pTBState );
|
|
|
|
CopyMemory( pTBState->Buttons, lpButtons, nButtons * sizeof(BITMAPBTN) );
|
|
|
|
/*
|
|
** Does the caller want tool tips ?
|
|
*/
|
|
if (pTBState->uStyle & BBS_TOOLTIPS) {
|
|
|
|
pTBState->hwndToolTips = CreateWindow(TOOLTIPS_CLASS, g_szEmpty,
|
|
WS_POPUP,
|
|
CW_USEDEFAULT, CW_USEDEFAULT,
|
|
CW_USEDEFAULT, CW_USEDEFAULT,
|
|
hWnd, NULL, hInst, NULL);
|
|
|
|
if (pTBState->hwndToolTips != (HWND)NULL ) {
|
|
|
|
int i;
|
|
TOOLINFO ti;
|
|
|
|
pTBState->lpfnDefProc = SubclassWindow( hWnd, ParentSubclassProc );
|
|
|
|
ti.uFlags = 0;
|
|
ti.cbSize = sizeof(ti);
|
|
ti.lpszText = LPSTR_TEXTCALLBACK;
|
|
|
|
for ( i = 0; i < nButtons; i++ ) {
|
|
|
|
LPBTN_INFO lpBtnInfo;
|
|
HWND hwndBtn;
|
|
|
|
hwndBtn = GetDlgItem(hWnd, pTBState->Buttons[i].uId);
|
|
if ( hwndBtn == (HWND)NULL ) {
|
|
break;
|
|
}
|
|
|
|
lpBtnInfo = (LPBTN_INFO)LocalAlloc(LPTR, sizeof(BTN_INFO));
|
|
if (lpBtnInfo == NULL ) {
|
|
break;
|
|
}
|
|
|
|
SetProp(hwndBtn, szButtonProp, (HANDLE)lpBtnInfo);
|
|
lpBtnInfo->hwndToolTips = pTBState->hwndToolTips;
|
|
lpBtnInfo->hwndParent = hWnd;
|
|
lpBtnInfo->lpfnDefProc = SubclassWindow( hwndBtn,
|
|
ButtonSubclassProc );
|
|
|
|
ti.hwnd = hwndBtn;
|
|
ti.uId = pTBState->Buttons[i].uId;
|
|
|
|
GetClientRect( hwndBtn, &ti.rect );
|
|
SendMessage( lpBtnInfo->hwndToolTips, TTM_ADDTOOL,
|
|
(WPARAM)0, (LPARAM)&ti );
|
|
|
|
|
|
/*
|
|
** Add the same rectangle in parent co-ordinates so that
|
|
** the tooltip still gets displayed even though the button
|
|
** is disabled.
|
|
*/
|
|
MapWindowRect( hwndBtn, hWnd, &ti.rect );
|
|
ti.hwnd = hWnd;
|
|
SendMessage( lpBtnInfo->hwndToolTips, TTM_ADDTOOL,
|
|
(WPARAM)0, (LPARAM)&ti );
|
|
}
|
|
|
|
}
|
|
else {
|
|
|
|
/*
|
|
** No tips available, just remove the BBS_TOOLTIPS style
|
|
*/
|
|
pTBState->uStyle &= ~BBS_TOOLTIPS;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BtnDestroyBitmapButtons
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* dd-mm-94 - StephenE - Created
|
|
*
|
|
\**************************************************************************/
|
|
void WINAPI
|
|
BtnDestroyBitmapButtons(
|
|
HWND hwnd
|
|
)
|
|
{
|
|
PBTNSTATE pTBState;
|
|
|
|
pTBState = (PBTNSTATE)GetProp(hwnd, szBbmProp);
|
|
if ( pTBState != NULL ) {
|
|
|
|
DeleteObject( pTBState->hbm );
|
|
FreeObjects( pTBState );
|
|
}
|
|
RemoveProp(hwnd, szBbmProp);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BtnDrawFocusRect
|
|
*
|
|
* Use this function to draw focus rectangle around a bitmap button.
|
|
*
|
|
* History:
|
|
* 18-11-93 - StephenE - Created
|
|
*
|
|
\**************************************************************************/
|
|
void WINAPI
|
|
BtnDrawFocusRect(
|
|
HDC hdc,
|
|
const RECT *lpRect,
|
|
UINT fsState
|
|
)
|
|
{
|
|
int iFaceOffset;
|
|
RECT rc;
|
|
|
|
CopyRect( &rc, lpRect );
|
|
|
|
rc.top = rc.left = 3;
|
|
|
|
if (fsState & ODS_SELECTED) {
|
|
iFaceOffset = 2;
|
|
}
|
|
else {
|
|
iFaceOffset = 4;
|
|
}
|
|
|
|
rc.right -= iFaceOffset;
|
|
rc.bottom -= iFaceOffset;
|
|
|
|
SetBkColor( hdc, rgbFace );
|
|
DrawFocusRect( hdc, &rc );
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BtnUpdateColors
|
|
*
|
|
* After a WM_SYSCOLORCHANGE message is received this function should be
|
|
* called to update the colors of the button bitmaps.
|
|
*
|
|
* History:
|
|
* 18-11-93 - StephenE - Created
|
|
*
|
|
\**************************************************************************/
|
|
void WINAPI
|
|
BtnUpdateColors(
|
|
HWND hwnd
|
|
)
|
|
{
|
|
PBTNSTATE pTBState;
|
|
|
|
pTBState = (PBTNSTATE)GetProp(hwnd, szBbmProp);
|
|
if (pTBState->nSysColorChanges != nSysColorChanges)
|
|
{
|
|
DeleteObject( pTBState->hbm );
|
|
pTBState->hbm = CreateMappedBitmap( pTBState->hInst,
|
|
pTBState->wID, TRUE, NULL, 0);
|
|
|
|
pTBState->nSysColorChanges = nSysColorChanges;
|
|
}
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* ButtonSubclassProc
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* dd-mm-94 - StephenE - Created
|
|
*
|
|
\**************************************************************************/
|
|
LRESULT CALLBACK
|
|
ButtonSubclassProc(
|
|
HWND hwnd,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
LPBTN_INFO lpBtnInfo;
|
|
WNDPROC lpfnDefProc;
|
|
|
|
|
|
lpBtnInfo = (LPBTN_INFO)GetProp( hwnd, szButtonProp );
|
|
|
|
/*
|
|
** Save this in case anything happens to lpBtnInfo before we return.
|
|
*/
|
|
lpfnDefProc = lpBtnInfo->lpfnDefProc;
|
|
|
|
switch ( uMsg ) {
|
|
|
|
case WM_DESTROY:
|
|
SubclassWindow( hwnd, lpfnDefProc );
|
|
if (lpBtnInfo) {
|
|
LocalFree((HLOCAL)lpBtnInfo);
|
|
RemoveProp(hwnd, szButtonProp);
|
|
}
|
|
break;
|
|
|
|
case WM_LBUTTONDOWN:
|
|
case WM_LBUTTONUP:
|
|
case WM_RBUTTONDOWN:
|
|
case WM_RBUTTONUP:
|
|
case WM_MBUTTONDOWN:
|
|
case WM_MBUTTONUP:
|
|
case WM_MOUSEMOVE:
|
|
RelayToToolTips( lpBtnInfo->hwndToolTips, hwnd, uMsg, wParam, lParam );
|
|
break;
|
|
|
|
case WM_MOVE:
|
|
{
|
|
TOOLINFO ti;
|
|
|
|
ti.cbSize = sizeof(ti);
|
|
ti.uFlags = 0;
|
|
ti.hwnd = hwnd;
|
|
ti.lpszText = LPSTR_TEXTCALLBACK;
|
|
ti.uId = GetDlgCtrlID( hwnd );
|
|
|
|
GetClientRect( hwnd, &ti.rect );
|
|
|
|
SendMessage( lpBtnInfo->hwndToolTips, TTM_NEWTOOLRECT, 0,
|
|
(LPARAM)&ti );
|
|
|
|
/*
|
|
** Add the same rectangle in parent co-ordinates so that
|
|
** the tooltip still gets displayed even though the button
|
|
** is disabled.
|
|
*/
|
|
MapWindowRect( hwnd, lpBtnInfo->hwndParent, &ti.rect );
|
|
ti.hwnd = lpBtnInfo->hwndParent;
|
|
SendMessage( lpBtnInfo->hwndToolTips, TTM_NEWTOOLRECT,
|
|
(WPARAM)0, (LPARAM)&ti );
|
|
}
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
SendMessage(lpBtnInfo->hwndParent, WM_NOTIFY, wParam, lParam);
|
|
break;
|
|
|
|
}
|
|
|
|
return CallWindowProc(lpfnDefProc, hwnd, uMsg, wParam, lParam);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* ParentSubclassProc
|
|
*
|
|
* Why do I need to subclass the buttons parent window ? Well,
|
|
* if a button is disable it will not receive mouse messages, the
|
|
* messages go to the window underneath the button (ie. the parent).
|
|
* Therefore we detect this and relay the mouse message to the tool tips
|
|
* window as above.
|
|
*
|
|
* History:
|
|
* dd-mm-94 - StephenE - Created
|
|
*
|
|
\**************************************************************************/
|
|
LRESULT CALLBACK
|
|
ParentSubclassProc(
|
|
HWND hwnd,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
WNDPROC lpfnDefProc;
|
|
PBTNSTATE pTBState;
|
|
|
|
|
|
pTBState = (PBTNSTATE)GetProp(hwnd, szBbmProp);
|
|
|
|
/*
|
|
** Save this in case anything happens to lpBtnInfo before we return.
|
|
*/
|
|
lpfnDefProc = pTBState->lpfnDefProc;
|
|
|
|
switch ( uMsg ) {
|
|
|
|
case TB_GETTOOLTIPS:
|
|
return (LRESULT)(UINT)pTBState->hwndToolTips;
|
|
|
|
case WM_LBUTTONDOWN:
|
|
case WM_LBUTTONUP:
|
|
case WM_RBUTTONDOWN:
|
|
case WM_RBUTTONUP:
|
|
case WM_MBUTTONDOWN:
|
|
case WM_MBUTTONUP:
|
|
case WM_MOUSEMOVE:
|
|
case WM_NCMOUSEMOVE:
|
|
RelayToToolTips( pTBState->hwndToolTips, hwnd, uMsg, wParam, lParam );
|
|
break;
|
|
}
|
|
|
|
return CallWindowProc(lpfnDefProc, hwnd, uMsg, wParam, lParam);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* RelayToToolTips
|
|
*
|
|
*
|
|
*
|
|
* History:
|
|
* dd-mm-94 - StephenE - Created
|
|
*
|
|
\**************************************************************************/
|
|
void FAR PASCAL
|
|
RelayToToolTips(
|
|
HWND hwndToolTips,
|
|
HWND hWnd,
|
|
UINT wMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
if(hwndToolTips) {
|
|
MSG msg;
|
|
msg.lParam = lParam;
|
|
msg.wParam = wParam;
|
|
msg.message = wMsg;
|
|
msg.hwnd = hWnd;
|
|
SendMessage(hwndToolTips, TTM_RELAYEVENT, 0, (LPARAM)(LPMSG)&msg);
|
|
}
|
|
}
|
|
|