Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

658 lines
17 KiB

///////////////////////////////////////////////////////////////////////////////
//
// mousebut.c
// Mouse Buttons Property sheet page.
//
//
// History:
// 29 Jan 94 FelixA
// Taken from mouse.c - functions only pertaining to General
// Property sheet.
// Double Click Speed
// Left/Right handed use
//
// 11 May 95 SteveCat
// Ported to Windows NT and Unicode, cleaned up
//
//
// NOTE/BUGS
//
// Copyright (C) 1994-1995 Microsoft Corporation
//
///////////////////////////////////////////////////////////////////////////////
//==========================================================================
// Include files
//==========================================================================
//
// Mouse Buttons Property sheet page.
//
#include "main.h"
#include "util.h"
#include "rc.h"
#include "mousectl.h"
#include <regstr.h>
#include <WinError.H> // Needed for ERROR_SUCCESS value.
const TCHAR szYes[] = TEXT("yes");
const TCHAR szNo[] = TEXT("no");
const TCHAR szDblClkSpeed[] = TEXT("DoubleClickSpeed");
const TCHAR szRegStr_Mouse[]= REGSTR_PATH_MOUSE;
// SwapMouseButtons takes
// TRUE to make it a right mouse
// FALSE to make it a left mouse
#define CLICKMIN 100 /* milliseconds */
#define CLICKMAX 900
#define CLICKSUM (CLICKMIN+CLICKMAX)
#define CLICKRANGE (CLICKMAX-CLICKMIN)
#define RIGHT TRUE
#define LEFT FALSE
typedef struct tag_MouseGenStr
{
BOOL bSwap;
BOOL bOrigSwap;
short ClickSpeed;
short OrigDblClkSpeed;
HWND hWndDblClkScroll;
HWND hDlg; // HWND hMouseButDlg;
RECT OrigRect;
RECT DblClkRect;
POINT ObjectPoint;
POINT SelectPoint;
int jackstate, jackhits; // for jack-in-the-box control
int jackignore; // for jack-in-the-box control
} MOUSEBUTSTR, *PMOUSEBUTSTR, FAR * LPMOUSEBUTSTR;
// #include "..\..\..\inc\mousehlp.h"
#include "mousehlp.h"
const DWORD aMouseButHelpIds[] = {
IDC_GROUPBOX_1, IDH_COMM_GROUPBOX,
IDC_GROUPBOX_2, IDH_DLGMOUSE_HANDED_PIC,
IDC_GROUPBOX_3, IDH_DLGMOUSE_HANDED_PIC,
IDC_GROUPBOX_4, IDH_COMM_GROUPBOX,
IDC_SELECTDRAG, IDH_DLGMOUSE_HANDED_PIC,
IDC_OBJECTMENU, IDH_DLGMOUSE_HANDED_PIC,
MOUSE_LEFTHAND, IDH_DLGMOUSE_LEFT,
MOUSE_RIGHTHAND, IDH_DLGMOUSE_RIGHT,
MOUSE_SELECTBMP, IDH_DLGMOUSE_HANDED_PIC,
MOUSE_MOUSEBMP, IDH_DLGMOUSE_HANDED_PIC,
MOUSE_MENUBMP, IDH_DLGMOUSE_HANDED_PIC,
MOUSE_CLICKSCROLL, IDH_DLGMOUSE_DOUBCLICK,
IDC_GROUPBOX_5, IDH_DLGMOUSE_DCLICK_PIC,
MOUSE_DBLCLKBMP, IDH_DLGMOUSE_DCLICK_PIC,
0, 0
};
#ifdef DEBUG
#define REG_INTEGER 1000
int fTraceRegAccess = 0;
void NEAR PASCAL RegDetails( int iWrite,
HKEY hk,
LPCTSTR lpszSubKey,
LPCTSTR lpszValueName,
DWORD dwType,
LPTSTR lpszString,
int iValue )
{
TCHAR Buff[256];
TCHAR far *lpszReadWrite[] = { TEXT("DESK.CPL:Read"), TEXT("DESK.CPL:Write") };
if( !fTraceRegAccess )
return;
switch( dwType )
{
case REG_SZ:
wsprintf( Buff, TEXT("%s String:hk=%#08lx, %s:%s=%s\n\r"),
lpszReadWrite[iWrite],
hk, lpszSubKey, lpszValueName, lpszString );
break;
case REG_INTEGER:
wsprintf( Buff, TEXT("%s int:hk=%#08lx, %s:%s=%d\n\r"),
lpszReadWrite[iWrite],
hk, lpszSubKey, lpszValueName, iValue );
break;
case REG_BINARY:
wsprintf( Buff, TEXT("%s Binary:hk=%#08lx, %s:%s=%#0lx;DataSize:%d\r\n"),
lpszReadWrite[iWrite],
hk, lpszSubKey, lpszValueName, lpszString, iValue );
break;
}
OutputDebugString( Buff );
}
#endif // DEBUG
///////////////////////////////////////////////////////////////////////////////
//
// GetIntFromSubKey
// hKey is the handle to the subkey
// (already pointing to the proper location).
//
///////////////////////////////////////////////////////////////////////////////
int NEAR PASCAL GetIntFromSubkey( HKEY hKey, LPCTSTR lpszValueName, int iDefault )
{
TCHAR szValue[20];
DWORD dwSizeofValueBuff = sizeof( szValue );
DWORD dwType;
int iRetValue = iDefault;
if( (RegQueryValueEx( hKey, (LPTSTR)lpszValueName, NULL, &dwType,
(LPBYTE) szValue, &dwSizeofValueBuff )
== ERROR_SUCCESS )
&& dwSizeofValueBuff )
{
//
// BOGUS: This handles only the string type entries now!
//
if( dwType == REG_SZ )
iRetValue = (int) StrToLong( szValue );
#ifdef DEBUG
else
OutputDebugString( TEXT("String type expected from Registry\n\r"));
#endif
}
#ifdef DEBUG
RegDetails( 0, hKey, TEXT(""), lpszValueName, REG_INTEGER, NULL, iRetValue );
#endif
return( iRetValue );
}
///////////////////////////////////////////////////////////////////////////////
//
// GetIntFromReg()
// Opens the given subkey and gets the int value.
//
///////////////////////////////////////////////////////////////////////////////
int NEAR PASCAL GetIntFromReg( HKEY hKey,
LPCTSTR lpszSubkey,
LPCTSTR lpszNameValue,
int iDefault )
{
HKEY hk;
int iRetValue = iDefault;
//
// See if the key is present.
//
if( RegOpenKey( hKey, lpszSubkey, &hk ) == ERROR_SUCCESS )
{
iRetValue = GetIntFromSubkey( hk, lpszNameValue, iDefault );
RegCloseKey( hk );
}
return( iRetValue );
}
BOOL NEAR PASCAL GetStringFromReg( HKEY hKey,
LPCTSTR lpszSubkey,
LPCTSTR lpszValueName,
LPCTSTR lpszDefault,
LPTSTR lpszValue,
DWORD dwSizeofValueBuff )
{
HKEY hk;
DWORD dwType;
BOOL fSuccess = FALSE;
//
// See if the key is present.
//
if( RegOpenKey( hKey, lpszSubkey, &hk ) == ERROR_SUCCESS )
{
if( (RegQueryValueEx( hk, (LPTSTR) lpszValueName, NULL, &dwType,
(LPBYTE) lpszValue, &dwSizeofValueBuff )
== ERROR_SUCCESS )
&& dwSizeofValueBuff )
{
//
// BOGUS: This handles only the string type entries now!
//
#ifdef DEBUG
if( dwType != REG_SZ )
{
OutputDebugString( TEXT("String type expected from Registry\n\r"));
}
else
#endif
fSuccess = TRUE;
}
RegCloseKey( hk );
}
//
// If failure, use the default string.
//
if( !fSuccess )
lstrcpy( lpszValue, lpszDefault );
#ifdef DEBUG
RegDetails( 0, hKey, lpszSubkey, lpszValueName, REG_SZ, lpszValue, 0 );
#endif
return( fSuccess );
}
///////////////////////////////////////////////////////////////////////////////
//
// UpdateRegistry:
// This updates a given value of any data type at a given
// location in the registry.
//
// The value name is passed in as an Id to a string in USER's String table.
//
///////////////////////////////////////////////////////////////////////////////
BOOL FAR PASCAL UpdateRegistry( HKEY hKey,
LPCTSTR lpszSubkey,
LPCTSTR lpszValueName,
DWORD dwDataType,
LPVOID lpvData,
DWORD dwDataSize )
{
HKEY hk;
if( RegCreateKey( hKey, lpszSubkey, &hk ) == ERROR_SUCCESS )
{
RegSetValueEx( hk, (LPTSTR)lpszValueName, 0, dwDataType,
(LPBYTE)lpvData, dwDataSize );
#ifdef DEBUG
RegDetails( 1, hKey, lpszSubkey, lpszValueName, dwDataType, lpvData, (int)dwDataSize );
#endif
RegCloseKey( hk );
return( TRUE );
}
return( FALSE );
}
//
// Swaps the menu and selection bitmaps.
//
void NEAR PASCAL ShowButtonState( PMOUSEBUTSTR pMstr )
{
HWND hDlg;
Assert( pMstr );
hDlg = pMstr->hDlg;
MouseControlSetSwap( GetDlgItem( hDlg, MOUSE_MOUSEBMP ), pMstr->bSwap );
SetWindowPos( GetDlgItem( hDlg, pMstr->bSwap? IDC_SELECTDRAG : IDC_OBJECTMENU ),
NULL,
pMstr->ObjectPoint.x,
pMstr->ObjectPoint.y,
0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER );
SetWindowPos( GetDlgItem( hDlg, !pMstr->bSwap ? IDC_SELECTDRAG : IDC_OBJECTMENU ), NULL,
pMstr->SelectPoint.x,
pMstr->SelectPoint.y,
0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER );
CheckDlgButton( hDlg, MOUSE_RIGHTHAND, !pMstr->bSwap );
CheckDlgButton( hDlg, MOUSE_LEFTHAND, pMstr->bSwap );
}
void NEAR PASCAL DestroyMouseButDlg( PMOUSEBUTSTR pMstr )
{
if( pMstr )
{
SetWindowLong( pMstr->hDlg, DWL_USER, (LONG)NULL );
LocalFree( (HGLOBAL)pMstr );
}
}
///////////////////////////////////////////////////////////////////////////////
//
// Jack stuff -- code to manage the jack-in-the-box double-click testbox
//
///////////////////////////////////////////////////////////////////////////////
typedef struct
{
int first; // first frame of state
int last; // last frame of state
int repeat; // state's repeat count
} JACKSTATE;
#define JACK_OPPOSITE_STATE (-2)
#define JACK_NEXT_STATE (-1)
#define JACK_CRANKING ( 0)
#define JACK_OPENING ( 1)
#define JACK_BOUNCING ( 2)
#define JACK_CLOSING ( 3)
//
// NOTE every state starts with a key frame in the AVI file
//
JACKSTATE JackFSA[] =
{
{ 0, 7, -1 }, // cranking
{ 8, 12, 1 }, // opening
{ 16, 23, -1 }, // bouncing
{ 24, 27, 1 }, // closing
};
#define JACK_NUM_STATES ( sizeof( JackFSA ) / sizeof( JACKSTATE ) )
void JackSetState( HWND dlg, PMOUSEBUTSTR mstr, int index )
{
JACKSTATE *state;
switch( index )
{
case JACK_OPPOSITE_STATE:
mstr->jackstate++;
//
// fall thru
//
case JACK_NEXT_STATE:
index = mstr->jackstate + 1;
}
index %= JACK_NUM_STATES;
state = JackFSA + index;
mstr->jackstate = index;
mstr->jackignore++;
Animate_Play( GetDlgItem( dlg, MOUSE_DBLCLKBMP ),
state->first, state->last, state->repeat );
}
void JackClicked( HWND dlg, PMOUSEBUTSTR mstr )
{
JACKSTATE *state = JackFSA + mstr->jackstate;
if( state->repeat < 0 )
JackSetState( dlg, mstr, JACK_NEXT_STATE );
else
mstr->jackhits++;
}
void JackStopped( HWND dlg, PMOUSEBUTSTR mstr )
{
if( --mstr->jackignore < 0 )
{
JACKSTATE *state = JackFSA + mstr->jackstate;
if( state->repeat > 0 )
{
int index;
if( mstr->jackhits )
{
mstr->jackhits--;
index = JACK_OPPOSITE_STATE;
}
else
index = JACK_NEXT_STATE;
JackSetState( dlg, mstr, index );
}
}
}
void JackStart( HWND dlg, PMOUSEBUTSTR mstr )
{
mstr->jackhits = 0;
mstr->jackstate = 0;
mstr->jackignore = -1;
Animate_Open( GetDlgItem( dlg, MOUSE_DBLCLKBMP ),
MAKEINTRESOURCE( IDA_JACKNBOX ) );
JackSetState( dlg, mstr, JACK_CRANKING );
}
BOOL NEAR PASCAL InitMouseButDlg( HWND hDlg )
{
POINT Origin;
PMOUSEBUTSTR pMstr;
RECT TmpRect;
//
// BUGBUG must do the alloc when you are adding these pages
// you cannot just return false and hope things work.
//
pMstr = (PMOUSEBUTSTR) LocalAlloc( LPTR , sizeof( MOUSEBUTSTR ) );
if( pMstr == NULL )
return TRUE;
SetWindowLong( hDlg, DWL_USER, (LONG)pMstr );
pMstr->hDlg = hDlg;
Origin.x = Origin.y = 0;
ClientToScreen( hDlg, (LPPOINT) &Origin );
GetWindowRect( hDlg, &pMstr->OrigRect );
pMstr->OrigRect.left -= Origin.x;
pMstr->OrigRect.right -= Origin.x;
GetWindowRect( GetDlgItem( hDlg, MOUSE_DBLCLKBMP ), &pMstr->DblClkRect );
pMstr->DblClkRect.top -= Origin.y;
pMstr->DblClkRect.bottom -= Origin.y;
pMstr->DblClkRect.left -= Origin.x;
pMstr->DblClkRect.right -= Origin.x;
//
// Find position of Select and Object windows
//
GetWindowRect( GetDlgItem( hDlg, IDC_SELECTDRAG ), &TmpRect );
ScreenToClient( hDlg, (POINT FAR*)&TmpRect );
pMstr->SelectPoint.x = TmpRect.left;
pMstr->SelectPoint.y = TmpRect.top;
GetWindowRect( GetDlgItem( hDlg, IDC_OBJECTMENU ), &TmpRect );
ScreenToClient( hDlg, (POINT FAR*)&TmpRect );
pMstr->ObjectPoint.x = TmpRect.left;
pMstr->ObjectPoint.y = TmpRect.top;
//
// Set(and get), then restore the state of the mouse buttons.
//
(pMstr->bOrigSwap) = (pMstr->bSwap) = SwapMouseButton( TRUE );
SwapMouseButton( pMstr->bOrigSwap );
ShowButtonState( pMstr );
pMstr->OrigDblClkSpeed = pMstr->ClickSpeed =
GetIntFromReg( HKEY_CURRENT_USER,
szRegStr_Mouse,
szDblClkSpeed,
CLICKMIN + (CLICKRANGE/2) );
pMstr->hWndDblClkScroll = GetDlgItem( hDlg, MOUSE_CLICKSCROLL );
SendMessage( pMstr->hWndDblClkScroll, TBM_SETRANGE, 0, MAKELONG( CLICKMIN, CLICKMAX ));
SendMessage( pMstr->hWndDblClkScroll, TBM_SETPOS, TRUE, (LONG)(CLICKMIN + CLICKMAX - pMstr->ClickSpeed ));
SetDoubleClickTime( pMstr->ClickSpeed );
JackStart( hDlg, pMstr );
return TRUE;
}
BOOL CALLBACK MouseButDlg( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
{
PMOUSEBUTSTR pMstr = (PMOUSEBUTSTR) GetWindowLong( hDlg, DWL_USER );
switch( message )
{
case WM_INITDIALOG:
return InitMouseButDlg( hDlg );
case WM_DESTROY:
DestroyMouseButDlg( pMstr );
break;
case WM_HSCROLL:
if( (HWND)lParam == pMstr->hWndDblClkScroll )
{
short temp = CLICKMIN + CLICKMAX - (short) SendMessage( (HWND)lParam,
TBM_GETPOS,
0, 0L );
if( temp != pMstr->ClickSpeed )
{
pMstr->ClickSpeed = temp;
SetDoubleClickTime( pMstr->ClickSpeed );
SendMessage( GetParent( hDlg ), PSM_CHANGED, (WPARAM)hDlg, 0L );
}
}
break;
case WM_RBUTTONDBLCLK:
case WM_LBUTTONDBLCLK:
{
POINT point = { (int)MAKEPOINTS( lParam ).x, (int)MAKEPOINTS( lParam ).y };
if( PtInRect( &pMstr->DblClkRect, point ) )
JackClicked( hDlg, pMstr );
break;
}
case WM_COMMAND:
switch( LOWORD( wParam ) )
{
case MOUSE_LEFTHAND:
if( pMstr->bSwap != RIGHT )
{
SendMessage( GetParent( hDlg ), PSM_CHANGED, (WPARAM)hDlg, 0L );
pMstr->bSwap = RIGHT;
ShowButtonState( pMstr );
}
break;
case MOUSE_RIGHTHAND:
if( pMstr->bSwap != LEFT )
{
SendMessage( GetParent( hDlg ), PSM_CHANGED, (WPARAM)hDlg, 0L );
pMstr->bSwap = LEFT;
ShowButtonState( pMstr );
}
break;
case MOUSE_DBLCLKBMP:
if( HIWORD( wParam ) == ACN_STOP )
JackStopped( hDlg, pMstr );
break;
}
break;
case WM_NOTIFY:
switch( ((NMHDR FAR *)lParam)->code )
{
case PSN_APPLY:
HourGlass( TRUE );
if( pMstr->bSwap != pMstr->bOrigSwap )
{
SystemParametersInfo( SPI_SETMOUSEBUTTONSWAP,
pMstr->bSwap, NULL,
SPIF_UPDATEINIFILE |
SPIF_SENDWININICHANGE );
pMstr->bOrigSwap = pMstr->bSwap;
}
if( pMstr->ClickSpeed != pMstr->OrigDblClkSpeed )
{
SystemParametersInfo( SPI_SETDOUBLECLICKTIME,
pMstr->ClickSpeed, NULL,
SPIF_UPDATEINIFILE |
SPIF_SENDWININICHANGE );
pMstr->OrigDblClkSpeed = pMstr->ClickSpeed;
}
HourGlass( FALSE );
break;
case PSN_RESET:
SetDoubleClickTime( pMstr->OrigDblClkSpeed );
break;
default:
return FALSE;
}
break;
case WM_HELP: // F1
WinHelp( ((LPHELPINFO) lParam)->hItemHandle, HELP_FILE, HELP_WM_HELP,
(DWORD) (LPTSTR) aMouseButHelpIds );
break;
case WM_CONTEXTMENU: // right mouse click
WinHelp( (HWND) wParam, HELP_FILE, HELP_CONTEXTMENU,
(DWORD) (LPTSTR) aMouseButHelpIds );
break;
default:
return FALSE;
}
return TRUE;
}