1315 lines
34 KiB
C++
1315 lines
34 KiB
C++
|
/*
|
||
|
* mouse - Dialog box property sheet for "mouse ui tweaks"
|
||
|
*/
|
||
|
|
||
|
#include "tweakui.h"
|
||
|
|
||
|
#pragma BEGIN_CONST_DATA
|
||
|
|
||
|
KL const c_klDelay = { &c_hkCU, c_tszRegPathDesktop, c_tszDelay };
|
||
|
|
||
|
const char CODESEG c_szUser[] = "USER"; /* Must be ANSI */
|
||
|
|
||
|
const static DWORD CODESEG rgdwHelp[] = {
|
||
|
IDC_SPEEDTEXT, IDH_SPEEDHELP,
|
||
|
IDC_SPEEDFAST, IDH_SPEEDHELP,
|
||
|
IDC_SPEEDSLOW, IDH_SPEEDHELP,
|
||
|
IDC_SPEEDTRACK, IDH_SPEEDHELP,
|
||
|
IDC_SPEEDHELP, IDH_SPEEDHELP,
|
||
|
|
||
|
IDC_SENSGROUP, IDH_GROUP,
|
||
|
|
||
|
IDC_DBLCLKTEXT, IDH_DBLCLK,
|
||
|
IDC_DBLCLK, IDH_DBLCLK,
|
||
|
IDC_DBLCLKUD, IDH_DBLCLK,
|
||
|
|
||
|
IDC_DRAGTEXT, IDH_DRAG,
|
||
|
IDC_DRAG, IDH_DRAG,
|
||
|
IDC_DRAGUD, IDH_DRAG,
|
||
|
|
||
|
IDC_SENSHELP, IDH_GROUP,
|
||
|
|
||
|
IDC_EFFECTGROUP, IDH_GROUP,
|
||
|
IDC_BEEP, IDH_BEEP,
|
||
|
|
||
|
/* SOMEDAY - SPI_GETMOUSEHOVERHEIGHT/WIDTH */
|
||
|
|
||
|
IDC_WHEELGROUP, IDH_GROUP,
|
||
|
IDC_WHEELENABLE, IDH_WHEEL,
|
||
|
IDC_WHEELPAGE, IDH_WHEEL,
|
||
|
IDC_WHEELLINE, IDH_WHEEL,
|
||
|
IDC_WHEELLINENO, IDH_WHEEL,
|
||
|
|
||
|
IDC_TESTGROUP, IDH_TEST,
|
||
|
IDC_TEST, IDH_TEST,
|
||
|
|
||
|
IDC_XMOUSE, IDH_XMOUSE,
|
||
|
IDC_XMOUSERAISE, IDH_XMOUSERAISE,
|
||
|
IDC_XMOUSEDELAYTXT, IDH_XMOUSEDELAY,
|
||
|
IDC_XMOUSEDELAY, IDH_XMOUSEDELAY,
|
||
|
|
||
|
IDC_TIPS, IDH_TIPSTIP,
|
||
|
IDC_RESET, IDH_RESET,
|
||
|
|
||
|
0, 0,
|
||
|
};
|
||
|
|
||
|
#pragma END_CONST_DATA
|
||
|
|
||
|
typedef WORD DT, FAR *LPDT; /* typeof(dtMNDropDown) */
|
||
|
|
||
|
#ifdef WIN32
|
||
|
#define fLpdt (lpdt != &dtScratch)
|
||
|
#else
|
||
|
#define fLpdt (SELECTOROF(lpdt) != SELECTOROF((LPDT)&dtScratch))
|
||
|
#endif
|
||
|
|
||
|
/*
|
||
|
* Globals
|
||
|
*/
|
||
|
DT dtScratch; /* Point lpdt here if we are stuck */
|
||
|
DT dtNT; /* Point lpdt here if we are on NT */
|
||
|
|
||
|
LPDT lpdt; /* Where to tweak to adjust the actual dt */
|
||
|
|
||
|
/*
|
||
|
* Instanced. We're a cpl so have only one instance, but I declare
|
||
|
* all the instance stuff in one place so it's easy to convert this
|
||
|
* code to multiple-instance if ever we need to.
|
||
|
*/
|
||
|
typedef struct MDII { /* Mouse_dialog instance info */
|
||
|
BOOL fDrag; /* Potential drag in progress? */
|
||
|
DT dtOrig; /* Original dt when we started */
|
||
|
RECT rcTest; /* Test area */
|
||
|
RECT rcDrag; /* Drag test rectangle */
|
||
|
RECT rcDblClk; /* Double click rectangle */
|
||
|
LONG tmClick; /* Time of previous lbutton down */
|
||
|
HCURSOR hcurDrag; /* What is being dragged? */
|
||
|
BOOL fFactory; /* Factory defaults? */
|
||
|
POINT ptDblClk; /* Double click values pending */
|
||
|
POINT ptDrag; /* Drag values pending */
|
||
|
POINT ptDragStart; /* Where the start click went down */
|
||
|
int cxAspect; /* Screen aspect ratio */
|
||
|
int cyAspect; /* Screen aspect ratio */
|
||
|
int idi; /* Which icon to use? */
|
||
|
} MDII, *PMDII;
|
||
|
|
||
|
MDII mdii;
|
||
|
#define pmdii (&mdii)
|
||
|
|
||
|
#define DestroyCursor(hcur) SafeDestroyIcon((HICON)(hcur))
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* Grovelling to find the dropmenu variable.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* dtDefault
|
||
|
*
|
||
|
* Return the default dropmenu time, which is DoubleClickTime * 4 / 5.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
DT PASCAL
|
||
|
dtDefault(void)
|
||
|
{
|
||
|
return GetDoubleClickTime() * 4 / 5;
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* dtCur
|
||
|
*
|
||
|
* Determine what the dropmenu time is, by external means.
|
||
|
*
|
||
|
* It ought to be DoubleClickTime * 4 / 5, or the value in the registry.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
INLINE DT
|
||
|
dtCur(void)
|
||
|
{
|
||
|
return (DT)GetIntPkl(dtDefault(), &c_klDelay);
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* GetProcOrd
|
||
|
*
|
||
|
* Win95 does not allow GetProcAddress to work on Kernel32, so we must
|
||
|
* implement it by hand.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
/*
|
||
|
* winnt.h uses these strange structure names.
|
||
|
* Does anybody speak Hungarian over there?
|
||
|
*/
|
||
|
typedef IMAGE_DOS_HEADER IDH, *PIDH;
|
||
|
typedef IMAGE_NT_HEADERS NTH, *PINTH; /* I like how this is "HEADERS" plural */
|
||
|
typedef IMAGE_EXPORT_DIRECTORY EDT, *PEDT;
|
||
|
typedef DWORD EAT, *PEAT;
|
||
|
typedef IMAGE_DATA_DIRECTORY OTE, *POTE;
|
||
|
|
||
|
#define pvAdd(pv, cb) ((LPVOID)((LPSTR)(pv) + (DWORD)(cb)))
|
||
|
#define pvSub(pv1, pv2) (DWORD)((LPSTR)(pv1) - (LPSTR)(pv2))
|
||
|
|
||
|
#define poteExp(pinth) (&(pinth)->OptionalHeader. \
|
||
|
DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT])
|
||
|
|
||
|
FARPROC PASCAL
|
||
|
GetProcOrd(LPVOID lpv, UINT ord)
|
||
|
{
|
||
|
PIDH pidh = (PIDH)lpv;
|
||
|
if (!IsBadReadPtr(pidh, sizeof(*pidh)) &&
|
||
|
pidh->e_magic == IMAGE_DOS_SIGNATURE) {
|
||
|
PINTH pinth = (PINTH)pvAdd(pidh, pidh->e_lfanew);
|
||
|
if (!IsBadReadPtr(pinth, sizeof(*pinth)) &&
|
||
|
pinth->Signature == IMAGE_NT_SIGNATURE) {
|
||
|
PEDT pedt = (PEDT)pvAdd(pidh, poteExp(pinth)->VirtualAddress);
|
||
|
if (!IsBadReadPtr(pedt, sizeof(*pedt)) &&
|
||
|
(ord - pedt->Base) < pedt->NumberOfFunctions) {
|
||
|
PEAT peat = (PEAT)pvAdd(pidh, pedt->AddressOfFunctions);
|
||
|
FARPROC fp = (FARPROC)pvAdd(pidh, peat[ord - pedt->Base]);
|
||
|
if (pvSub(fp, peat) >= poteExp(pinth)->Size) {
|
||
|
return fp;
|
||
|
} else { /* Forwarded!? */
|
||
|
return 0;
|
||
|
}
|
||
|
} else {
|
||
|
return 0;
|
||
|
}
|
||
|
} else {
|
||
|
return 0;
|
||
|
}
|
||
|
} else {
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* fGrovel
|
||
|
*
|
||
|
* Grovel into USER's DS to find the dropmenu time.
|
||
|
* The problem is that there is no documented way of getting and setting
|
||
|
* the dropmenu time without rebooting. So we find it by (trust me)
|
||
|
* disassembling the SetDoubleClickTime function and knowing that the
|
||
|
* last instructions are
|
||
|
*
|
||
|
* mov [xxxx], ax ; set drop menu time
|
||
|
* pop ds
|
||
|
* leave
|
||
|
* retf 2
|
||
|
*
|
||
|
* Good news! On Windows NT, there is a new SPI to do this.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
typedef HINSTANCE (*LL16)(LPCSTR);
|
||
|
typedef FARPROC (*GPA16)(HINSTANCE, LPCSTR);
|
||
|
typedef BOOL (*FL16)(HINSTANCE);
|
||
|
typedef LPVOID (*MSL)(DWORD);
|
||
|
|
||
|
BOOL PASCAL
|
||
|
fGrovel(void)
|
||
|
{
|
||
|
OSVERSIONINFO ovi;
|
||
|
|
||
|
if (SystemParametersInfo(SPI_GETMENUSHOWDELAY, 0, &dtNT, 0)) {
|
||
|
lpdt = &dtNT;
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
#ifdef _X86_
|
||
|
|
||
|
/* Else win95 - must grovel */
|
||
|
ovi.dwOSVersionInfoSize = sizeof(ovi);
|
||
|
if (GetVersionEx(&ovi) &&
|
||
|
ovi.dwMajorVersion == 4 &&
|
||
|
ovi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
|
||
|
HINSTANCE hinstK32 = GetModuleHandle(c_tszKernel32);
|
||
|
if (hinstK32) {
|
||
|
LL16 LoadLibrary16 = (LL16)GetProcOrd(hinstK32, 35);
|
||
|
FL16 FreeLibrary16 = (FL16)GetProcOrd(hinstK32, 36);
|
||
|
GPA16 GetProcAddress16 = (GPA16)GetProcOrd(hinstK32, 37);
|
||
|
MSL MapSL = (MSL)GetProcAddress(hinstK32, c_tszMapSL);
|
||
|
if ((DWORD)LoadLibrary16 & (DWORD)FreeLibrary16 &
|
||
|
(DWORD)GetProcAddress16 & (DWORD)MapSL) {
|
||
|
HINSTANCE hinst16 = LoadLibrary16(c_szUser);
|
||
|
if ((UINT)hinst16 > 32) {
|
||
|
FARPROC fp = GetProcAddress16(hinst16,
|
||
|
MAKEINTRESOURCE(20));
|
||
|
if (fp) {
|
||
|
LPBYTE lpSDCT;
|
||
|
GetDoubleClickTime(); /* Force segment present */
|
||
|
lpSDCT = (LPBYTE)MapSL((DWORD)fp);
|
||
|
if (!IsBadReadPtr(lpSDCT, 84)) {
|
||
|
int i;
|
||
|
for (i = 0; i < 80; i++, lpSDCT++) {
|
||
|
if (*(LPDWORD)lpSDCT == 0x02CAC91F) {
|
||
|
lpdt = (LPDT)MapSL(MAKELONG(
|
||
|
*(LPWORD)(lpSDCT - 2),
|
||
|
hinst16));
|
||
|
return *lpdt == dtCur();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
FreeLibrary16(hinst16);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* msDt
|
||
|
*
|
||
|
* Get the actual drop time if possible. Don't all this unless
|
||
|
* you know it'll work.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
DT PASCAL
|
||
|
msDt(void)
|
||
|
{
|
||
|
if (lpdt == &dtNT) {
|
||
|
SystemParametersInfo(SPI_GETMENUSHOWDELAY, 0, &dtNT, 0);
|
||
|
}
|
||
|
return (DT)*lpdt;
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* SetDt
|
||
|
*
|
||
|
* Set the drop time, returning TRUE if we need a reboot.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
BOOL PASCAL
|
||
|
SetDt(UINT ms, DWORD spif)
|
||
|
{
|
||
|
#ifdef _X86_
|
||
|
if (lpdt == &dtNT) {
|
||
|
#endif
|
||
|
SystemParametersInfo(SPI_SETMENUSHOWDELAY, ms, 0, spif);
|
||
|
return 0;
|
||
|
#ifdef _X86_
|
||
|
} else {
|
||
|
if (spif & SPIF_UPDATEINIFILE) {
|
||
|
SetIntPkl(pmdii->dtOrig, &c_klDelay);
|
||
|
}
|
||
|
if (fLpdt) {
|
||
|
*lpdt = (WORD)ms;
|
||
|
return 0;
|
||
|
} else {
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* fXMouse
|
||
|
*
|
||
|
* Determine whether XMouse is enabled.
|
||
|
*
|
||
|
* Returns 0 if disabled, 1 if enabled, or -1 if not supported.
|
||
|
*
|
||
|
* Note that there are *two* ways of getting this information,
|
||
|
* depending on which flavor of NT/Win9x we are running. So
|
||
|
* try all of them until one of them works.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
BOOL PASCAL
|
||
|
fXMouse(void)
|
||
|
{
|
||
|
BOOL fX;
|
||
|
if (SystemParametersInfo(SPI_GETUSERPREFERENCE,
|
||
|
SPI_UP_ACTIVEWINDOWTRACKING, &fX, 0)) {
|
||
|
return fX != 0;
|
||
|
} else if (SystemParametersInfo(SPI_GETACTIVEWINDOWTRACKING,
|
||
|
0, &fX, 0)) {
|
||
|
return fX != 0;
|
||
|
} else {
|
||
|
return -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* SetXMouse
|
||
|
*
|
||
|
* Set the XMouse feature.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
INLINE void
|
||
|
SetXMouse(BOOL f)
|
||
|
{
|
||
|
if (SystemParametersInfo(SPI_SETUSERPREFERENCE,
|
||
|
SPI_UP_ACTIVEWINDOWTRACKING, IntToPtr(f),
|
||
|
SPIF_UPDATEINIFILE | SPIF_SENDCHANGE)) {
|
||
|
} else {
|
||
|
SystemParametersInfo(SPI_SETACTIVEWINDOWTRACKING,
|
||
|
0, IntToPtr(f), SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* msXMouseDelay
|
||
|
*
|
||
|
* Returns the XMouse hover delay, or -1 if not supported.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
int
|
||
|
msXMouseDelay(void)
|
||
|
{
|
||
|
DWORD dw;
|
||
|
if (SystemParametersInfo(SPI_GETACTIVEWNDTRKTIMEOUT, 0, &dw, 0)) {
|
||
|
return (int)dw;
|
||
|
}
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* SetXMouseDelay
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
INLINE void
|
||
|
SetXMouseDelay(int msDelay)
|
||
|
{
|
||
|
SystemParametersInfo(SPI_SETACTIVEWNDTRKTIMEOUT, 0, IntToPtr(msDelay),
|
||
|
SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* fXMouseRaise
|
||
|
*
|
||
|
* Returns 0 if autoraise disabled, 1 if enabled, or -1 if not supported.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
BOOL PASCAL
|
||
|
fXMouseRaise(void)
|
||
|
{
|
||
|
BOOL f;
|
||
|
if (SystemParametersInfo(SPI_GETACTIVEWNDTRKZORDER, 0, &f, 0)) {
|
||
|
return f != 0;
|
||
|
} else {
|
||
|
return -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* SetXMouseRaise
|
||
|
*
|
||
|
* Set the XMouse autoraise feature.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
INLINE void
|
||
|
SetXMouseRaise(BOOL f)
|
||
|
{
|
||
|
SystemParametersInfo(SPI_SETACTIVEWNDTRKZORDER, 0, IntToPtr(f),
|
||
|
SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* cxDragCur
|
||
|
*
|
||
|
* Return the current horizontal drag sensitivity.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
INLINE int
|
||
|
cxDragCur(void)
|
||
|
{
|
||
|
return GetSystemMetrics(SM_CXDRAG);
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* SetCxCyDrag
|
||
|
*
|
||
|
* Set the new horizontal and vertical drag tolerances.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
INLINE void
|
||
|
SetCxCyDrag(int cxDrag, int cyDrag)
|
||
|
{
|
||
|
SystemParametersInfo(SPI_SETDRAGWIDTH, (UINT)cxDrag, 0L,
|
||
|
SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
|
||
|
SystemParametersInfo(SPI_SETDRAGHEIGHT, (UINT)cyDrag, 0L,
|
||
|
SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* cxDblClkCur
|
||
|
*
|
||
|
* Return the current horizontal double click sensitivity.
|
||
|
* Note that GetSystemMetrics records the total width, so we
|
||
|
* need to divide by two to get the half-wit half-width.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
INLINE int
|
||
|
cxDblClkCur(void)
|
||
|
{
|
||
|
return GetSystemMetrics(SM_CXDOUBLECLK) / 2;
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* SetCxCyDblClk
|
||
|
*
|
||
|
* Set the current horizontal double click sensitivity.
|
||
|
* Note that GetSystemMetrics records the total width, so we
|
||
|
* need to multiply the half-width and half-height by two.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
INLINE void
|
||
|
SetCxCyDblClk(int cxDblClk, int cyDblClk)
|
||
|
{
|
||
|
SystemParametersInfo(SPI_SETDOUBLECLKWIDTH, (UINT)cxDblClk * 2, 0L,
|
||
|
SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
|
||
|
SystemParametersInfo(SPI_SETDOUBLECLKHEIGHT, (UINT)cyDblClk * 2, 0L,
|
||
|
SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* Mouse_ReloadDlgInt
|
||
|
*
|
||
|
* Reload values from an edit control.
|
||
|
*
|
||
|
* hdlg is the dialog box itself.
|
||
|
*
|
||
|
* idc is the edit control identifier.
|
||
|
*
|
||
|
* ppt -> a POINT structure which will contain the current value
|
||
|
* in the x, and an aspect-ratio-corrected value in the y.
|
||
|
*
|
||
|
* We allow the value to exceed the range, in case you
|
||
|
* really want it.
|
||
|
*
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
void PASCAL
|
||
|
Mouse_ReloadDlgInt(HWND hdlg, UINT idc, PPOINT ppt)
|
||
|
{
|
||
|
BOOL f;
|
||
|
LRESULT lr;
|
||
|
HWND hwnd;
|
||
|
int x;
|
||
|
|
||
|
hwnd = GetDlgItem(hdlg, idc+didcUd);
|
||
|
if (hwnd) {
|
||
|
lr = SendMessage(hwnd, UDM_GETRANGE, 0, 0L);
|
||
|
x = (int)GetDlgItemInt(hdlg, idc+didcEdit, &f, 0);
|
||
|
x = max((UINT)x, HIWORD(lr)); /* Force to lower limit of range */
|
||
|
ppt->x = x;
|
||
|
ppt->y = MulDiv(x, pmdii->cyAspect, pmdii->cxAspect);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* Mouse_InitDlgInt
|
||
|
*
|
||
|
* Initialize a paired edit control / updown control.
|
||
|
*
|
||
|
* hdlg is the dialog box itself.
|
||
|
*
|
||
|
* idc is the edit control identifier. It is assumed that idc+didcUd is
|
||
|
* the identifier for the updown control.
|
||
|
*
|
||
|
* xMin and xMax are the limits of the control.
|
||
|
*
|
||
|
* x = initial value
|
||
|
*
|
||
|
* ppt -> a POINT structure which will contain the current value
|
||
|
* in the x, and an aspect-ratio-corrected value in the y.
|
||
|
*
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
void PASCAL
|
||
|
Mouse_InitDlgInt(HWND hdlg, UINT idc, int xMin, int xMax, int xVal, PPOINT ppt)
|
||
|
{
|
||
|
SendDlgItemMessage(hdlg, idc+didcEdit, EM_LIMITTEXT, 2, 0L);
|
||
|
SetDlgItemInt(hdlg, idc+didcEdit, xVal, 0);
|
||
|
|
||
|
SendDlgItemMessage(hdlg, idc+didcUd,
|
||
|
UDM_SETRANGE, 0, MAKELPARAM(xMax, xMin));
|
||
|
|
||
|
Mouse_ReloadDlgInt(hdlg, idc, ppt);
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* The trackbar
|
||
|
*
|
||
|
* The trackbar slider is piecewise linear. It really should be
|
||
|
* exponential, but it's hard to write exp() and log() for integers.
|
||
|
*
|
||
|
* Given two parallel arrays which describe the domain and range,
|
||
|
* with
|
||
|
*
|
||
|
* x[N] <= x <= x[N+1] mapping to y[N] <= y <= y[N+1],
|
||
|
*
|
||
|
* then
|
||
|
*
|
||
|
* x[N] <= x <= x[N+1] maps to
|
||
|
*
|
||
|
* y = y[N] + (x - x[N]) * (y[N+1] - y[N]) / (x[N+1] - x[N]).
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
/* tbt = trackbar tick */
|
||
|
#define tbtMax 120
|
||
|
#define tbtFreq 15
|
||
|
#define dtMax 65534 /* Don't use 65535; that's uiErr */
|
||
|
|
||
|
const static UINT CODESEG rgtbt[] =
|
||
|
{ 0, tbtMax/2, tbtMax*3/4, tbtMax*7/8, tbtMax };
|
||
|
const static UINT CODESEG rgdt[] =
|
||
|
{ 0, 500, 2000, 5000, dtMax };
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* Mouse_Interpolate
|
||
|
*
|
||
|
* Perform piecewise linear interpolation. See the formulas above.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
UINT PASCAL
|
||
|
Mouse_Interpolate(UINT x, const UINT CODESEG *px, const UINT CODESEG *py)
|
||
|
{
|
||
|
while (x > px[1]) px++, py++;
|
||
|
return py[0] + MulDiv(x - px[0], py[1] - py[0], px[1] - px[0]);
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* Mouse_GetDt
|
||
|
*
|
||
|
* Get the setting that the user has selected.
|
||
|
*
|
||
|
* hdlg = dialog handle
|
||
|
*
|
||
|
* dtMax maps to dtInfinite.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
DT PASCAL
|
||
|
Mouse_GetDt(HWND hdlg)
|
||
|
{
|
||
|
return (DT)Mouse_Interpolate(
|
||
|
(UINT)SendDlgItemMessage(hdlg, IDC_SPEEDTRACK,
|
||
|
TBM_GETPOS, 0, 0L), rgtbt, rgdt);
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* Mouse_SetDt
|
||
|
*
|
||
|
* Set the setting into the trackbar.
|
||
|
*
|
||
|
* hdlg = dialog handle
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
void PASCAL
|
||
|
Mouse_SetDt(HWND hdlg, DT dt)
|
||
|
{
|
||
|
SendDlgItemMessage(hdlg, IDC_SPEEDTRACK, TBM_SETPOS, 1,
|
||
|
Mouse_Interpolate(dt, rgdt, rgtbt));
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* Mouse_SetDirty
|
||
|
*
|
||
|
* Make a control dirty.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
void NEAR PASCAL
|
||
|
Mouse_SetDirty(HWND hdlg)
|
||
|
{
|
||
|
pmdii->fFactory = 0;
|
||
|
PropSheet_Changed(GetParent(hdlg), hdlg);
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* Mouse_UpdateWheel
|
||
|
*
|
||
|
* Update all the wheel control controls.
|
||
|
*
|
||
|
* If "Use wheel" is unchecked, then disable all the insides.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
void PASCAL
|
||
|
Mouse_UpdateWheel(HWND hdlg)
|
||
|
{
|
||
|
HWND hwnd = GetDlgItem(hdlg, IDC_WHEELENABLE);
|
||
|
if (hwnd) {
|
||
|
BOOL f = IsWindowEnabled(hwnd) &&
|
||
|
IsDlgButtonChecked(hdlg, IDC_WHEELENABLE);
|
||
|
AdjustDlgItems(hdlg, IDC_WHEELPAGE, IDC_WHEELLAST, f ? ADI_ENABLE : ADI_DISABLE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* Mouse_Reset
|
||
|
*
|
||
|
* Reset all controls to initial values. This also marks
|
||
|
* the control as clean.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
BOOL PASCAL
|
||
|
Mouse_Reset(HWND hdlg)
|
||
|
{
|
||
|
HWND hwnd = GetDlgItem(hdlg, IDC_SPEEDTRACK);
|
||
|
BOOL f;
|
||
|
SendMessage(hwnd, TBM_SETRANGE, 0, MAKELPARAM(0, tbtMax));
|
||
|
SendMessage(hwnd, TBM_SETTICFREQ, tbtFreq, 0L);
|
||
|
|
||
|
if (fLpdt) {
|
||
|
pmdii->dtOrig = msDt(); /* Save for revert */
|
||
|
if (pmdii->dtOrig > dtMax) { /* Max out here */
|
||
|
pmdii->dtOrig = dtMax;
|
||
|
}
|
||
|
} else {
|
||
|
/* just use what seems to be the current setting */
|
||
|
pmdii->dtOrig = dtCur();
|
||
|
}
|
||
|
Mouse_SetDt(hdlg, pmdii->dtOrig);
|
||
|
|
||
|
f = fXMouse();
|
||
|
if (f >= 0) {
|
||
|
CheckDlgButton(hdlg, IDC_XMOUSE, f);
|
||
|
f = fXMouseRaise();
|
||
|
if (f >= 0) {
|
||
|
CheckDlgButton(hdlg, IDC_XMOUSERAISE, f);
|
||
|
}
|
||
|
|
||
|
int ms = msXMouseDelay();
|
||
|
if (ms >= 0) {
|
||
|
SetDlgItemInt(hdlg, IDC_XMOUSEDELAY, ms, FALSE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Mouse_UpdateWheel(hdlg);
|
||
|
|
||
|
Mouse_InitDlgInt(hdlg, IDC_DBLCLK, 1, 32, cxDblClkCur(), &pmdii->ptDblClk);
|
||
|
Mouse_InitDlgInt(hdlg, IDC_DRAG, 1, 32, cxDragCur(), &pmdii->ptDrag);
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* Mouse_Apply
|
||
|
*
|
||
|
* Write the changes to the registry and into USER's DS.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
BOOL NEAR PASCAL
|
||
|
Mouse_Apply(HWND hdlg)
|
||
|
{
|
||
|
BOOL f;
|
||
|
BOOL fNow;
|
||
|
DWORD dwNow;
|
||
|
DT dt;
|
||
|
|
||
|
dt = Mouse_GetDt(hdlg);
|
||
|
if (dt != pmdii->dtOrig) {
|
||
|
pmdii->dtOrig = dt;
|
||
|
if (pmdii->fFactory) {
|
||
|
/* DelPkl(&c_klDelay); */
|
||
|
dt = dtDefault();
|
||
|
}
|
||
|
if (SetDt(pmdii->dtOrig, SPIF_UPDATEINIFILE)) {
|
||
|
Common_NeedLogoff(hdlg);
|
||
|
}
|
||
|
SendNotifyMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0,
|
||
|
(LPARAM)(LPCTSTR)c_tszWindows);
|
||
|
}
|
||
|
|
||
|
if (cxDragCur() != pmdii->ptDrag.x) {
|
||
|
/* This will send WM_WININICHANGE as necessary */
|
||
|
SetCxCyDrag(pmdii->ptDrag.x, pmdii->ptDrag.y);
|
||
|
}
|
||
|
|
||
|
if (cxDblClkCur() != pmdii->ptDblClk.x) {
|
||
|
/* This will send WM_WININICHANGE as necessary */
|
||
|
SetCxCyDblClk(pmdii->ptDblClk.x, pmdii->ptDblClk.y);
|
||
|
}
|
||
|
|
||
|
fNow = fXMouse();
|
||
|
if (fNow >= 0) {
|
||
|
f = IsDlgButtonChecked(hdlg, IDC_XMOUSE);
|
||
|
if (fNow != f) {
|
||
|
/* This will send WM_WININICHANGE as necessary */
|
||
|
SetXMouse(f);
|
||
|
}
|
||
|
|
||
|
fNow = fXMouseRaise();
|
||
|
f = IsDlgButtonChecked(hdlg, IDC_XMOUSERAISE);
|
||
|
if (fNow != f) {
|
||
|
SetXMouseRaise(f);
|
||
|
}
|
||
|
|
||
|
int msDelay = (int)GetDlgItemInt(hdlg, IDC_XMOUSEDELAY, &f, FALSE);
|
||
|
int msDelayNow = msXMouseDelay();
|
||
|
if (msDelay != msDelayNow) {
|
||
|
SetXMouseDelay(msDelay);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &dwNow, 0)) {
|
||
|
if (IsWindowEnabled(GetDlgItem(hdlg, IDC_WHEELENABLE))) {
|
||
|
DWORD dw;
|
||
|
|
||
|
if (!IsDlgButtonChecked(hdlg, IDC_WHEELENABLE)) {
|
||
|
dw = 0;
|
||
|
} else if (IsDlgButtonChecked(hdlg, IDC_WHEELPAGE)) {
|
||
|
dw = WHEEL_PAGESCROLL;
|
||
|
} else {
|
||
|
dw = GetDlgItemInt(hdlg, IDC_WHEELLINENO, &f, 0);
|
||
|
}
|
||
|
|
||
|
if (dw != dwNow) {
|
||
|
SystemParametersInfo(SPI_SETWHEELSCROLLLINES, dw, 0,
|
||
|
SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return Mouse_Reset(hdlg);
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* Mouse_ReloadUpdowns
|
||
|
*
|
||
|
* Reload the values from the updown controls and update our
|
||
|
* internals accordingly.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
BOOL PASCAL
|
||
|
Mouse_ReloadUpdowns(HWND hdlg)
|
||
|
{
|
||
|
Mouse_ReloadDlgInt(hdlg, IDC_DBLCLK, &pmdii->ptDblClk);
|
||
|
Mouse_ReloadDlgInt(hdlg, IDC_DRAG, &pmdii->ptDrag);
|
||
|
Mouse_SetDirty(hdlg);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* Mouse_FactoryReset
|
||
|
*
|
||
|
* Restore to original factory settings.
|
||
|
*
|
||
|
* Droptime = DoubleClickTime * 4 / 5.
|
||
|
* Animation = !((GetSystemMetrics(SM_SLOWMACHINE) & 0x0004) &&
|
||
|
* (GetSystemMetrics(SM_SLOWMACHINE) & 0x0001))
|
||
|
* cxDrag = 2
|
||
|
* cxDblClk = 2
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
BOOL PASCAL
|
||
|
Mouse_FactoryReset(HWND hdlg)
|
||
|
{
|
||
|
Mouse_SetDirty(hdlg);
|
||
|
|
||
|
Mouse_SetDt(hdlg, dtDefault());
|
||
|
|
||
|
if (fXMouse() >= 0) {
|
||
|
CheckDlgButton(hdlg, IDC_XMOUSE, 0);
|
||
|
}
|
||
|
|
||
|
SetDlgItemInt(hdlg, IDC_DRAG, 2, 0);
|
||
|
SetDlgItemInt(hdlg, IDC_DBLCLK, 2, 0);
|
||
|
|
||
|
Mouse_ReloadUpdowns(hdlg);
|
||
|
|
||
|
if (GetDlgItem(hdlg, IDC_WHEELENABLE)) {
|
||
|
CheckDlgButton(hdlg, IDC_WHEELENABLE, TRUE);
|
||
|
CheckRadioButton(hdlg, IDC_WHEELPAGE, IDC_WHEELLINE, IDC_WHEELLINE);
|
||
|
SetDlgItemInt(hdlg, IDC_WHEELLINENO, 3, 0);
|
||
|
}
|
||
|
|
||
|
pmdii->fFactory = 1;
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* Mouse_OnTips
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
void PASCAL
|
||
|
Mouse_OnTips(HWND hdlg)
|
||
|
{
|
||
|
WinHelp(hdlg, c_tszMyHelp, HELP_FINDER, 0);
|
||
|
}
|
||
|
|
||
|
#ifdef IDC_BUGREPORT
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* Mouse_OnBugReport
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
void PASCAL
|
||
|
Mouse_OnBugReport(HWND hdlg)
|
||
|
{
|
||
|
ShellExecute(hdlg, "open", "http://abject/tweakui/", "", "",
|
||
|
SW_NORMAL);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* Mouse_OnCommand
|
||
|
*
|
||
|
* Ooh, we got a command.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
BOOL PASCAL
|
||
|
Mouse_OnCommand(HWND hdlg, int id, UINT codeNotify)
|
||
|
{
|
||
|
switch (id) {
|
||
|
case IDC_RESET: /* Reset to factory default */
|
||
|
if (codeNotify == BN_CLICKED) return Mouse_FactoryReset(hdlg);
|
||
|
break;
|
||
|
|
||
|
case IDC_TIPS: /* Call up help */
|
||
|
if (codeNotify == BN_CLICKED) Mouse_OnTips(hdlg);
|
||
|
break;
|
||
|
|
||
|
#ifdef IDC_BUGREPORT
|
||
|
case IDC_BUGREPORT:
|
||
|
if (codeNotify == BN_CLICKED) Mouse_OnBugReport(hdlg);
|
||
|
break;
|
||
|
#endif
|
||
|
|
||
|
case IDC_XMOUSE:
|
||
|
case IDC_XMOUSERAISE:
|
||
|
case IDC_WHEELPAGE:
|
||
|
case IDC_WHEELLINE:
|
||
|
if (codeNotify == BN_CLICKED) Mouse_SetDirty(hdlg);
|
||
|
break;
|
||
|
|
||
|
case IDC_DRAG:
|
||
|
case IDC_DBLCLK:
|
||
|
case IDC_WHEELLINENO:
|
||
|
case IDC_XMOUSEDELAY:
|
||
|
if (codeNotify == EN_CHANGE) {
|
||
|
Mouse_ReloadUpdowns(hdlg);
|
||
|
Mouse_SetDirty(hdlg);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case IDC_WHEELENABLE:
|
||
|
if (codeNotify == BN_CLICKED) {
|
||
|
Mouse_UpdateWheel(hdlg);
|
||
|
Mouse_SetDirty(hdlg);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* Mouse_SetTestIcon
|
||
|
*
|
||
|
* Set a new test icon, returning the previous one.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
HCURSOR PASCAL
|
||
|
Mouse_SetTestIcon(HWND hdlg, UINT idi)
|
||
|
{
|
||
|
return (HCURSOR)
|
||
|
SendDlgItemMessage(hdlg, IDC_TEST, STM_SETICON,
|
||
|
(WPARAM)LoadIconId(idi), 0L);
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* Mouse_StopDrag
|
||
|
*
|
||
|
* Stop any drag operation in progress.
|
||
|
*
|
||
|
* We must release the capture unconditionally, or a double-click
|
||
|
* will result in the mouse capture being stuck!
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
void PASCAL
|
||
|
Mouse_StopDrag(HWND hdlg)
|
||
|
{
|
||
|
ReleaseCapture(); /* Always do this! */
|
||
|
if (pmdii->hcurDrag) {
|
||
|
SetCursor(0); /* We're about to destroy the current cursor */
|
||
|
DestroyCursor(pmdii->hcurDrag);
|
||
|
pmdii->hcurDrag = 0;
|
||
|
DestroyCursor(Mouse_SetTestIcon(hdlg, pmdii->idi));
|
||
|
}
|
||
|
pmdii->fDrag = 0; /* not dragging */
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* Mouse_OnNotify
|
||
|
*
|
||
|
* Ooh, we got a notification.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
BOOL PASCAL
|
||
|
Mouse_OnNotify(HWND hdlg, NMHDR FAR *pnm)
|
||
|
{
|
||
|
switch (pnm->code) {
|
||
|
case PSN_APPLY:
|
||
|
Mouse_Apply(hdlg);
|
||
|
break;
|
||
|
|
||
|
/*
|
||
|
* If we are dragging, then ESC cancels the drag, not the prsht.
|
||
|
* Note that we must set the message result *last*, because
|
||
|
* ReleaseCapture will recursively call the dialog procedure,
|
||
|
* smashing whatever used to be in the message result.
|
||
|
*/
|
||
|
case PSN_QUERYCANCEL:
|
||
|
if (pmdii->fDrag) {
|
||
|
Mouse_StopDrag(hdlg);
|
||
|
SetDlgMsgResult(hdlg, WM_NOTIFY, 1);
|
||
|
}
|
||
|
return 1;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* Mouse_OnInitDialog
|
||
|
*
|
||
|
* Initialize the controls.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
BOOL NEAR PASCAL
|
||
|
Mouse_OnInitDialog(HWND hdlg)
|
||
|
{
|
||
|
UINT idc;
|
||
|
DWORD dw;
|
||
|
|
||
|
pmdii->idi = IDI_GEAR1; /* Start with the first gear */
|
||
|
|
||
|
pmdii->fDrag = 0; /* not dragging */
|
||
|
|
||
|
/* Make sure first click isn't counted as a double */
|
||
|
pmdii->tmClick = 0;
|
||
|
|
||
|
pmdii->fFactory = 0;
|
||
|
pmdii->hcurDrag = 0;
|
||
|
|
||
|
GetDlgItemRect(hdlg, IDC_TEST, &pmdii->rcTest);
|
||
|
|
||
|
{
|
||
|
HDC hdc = GetDC(0);
|
||
|
if (hdc) {
|
||
|
pmdii->cxAspect = GetDeviceCaps(hdc, ASPECTX);
|
||
|
pmdii->cyAspect = GetDeviceCaps(hdc, ASPECTY);
|
||
|
ReleaseDC(0, hdc);
|
||
|
if (pmdii->cxAspect == 0) { /* Buggy display driver */
|
||
|
goto Fallback;
|
||
|
}
|
||
|
} else { /* Assume 1:1 aspect ratio */
|
||
|
Fallback:
|
||
|
pmdii->cxAspect = pmdii->cyAspect = 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
SendDlgItemMessage(hdlg, IDC_WHEELLINENO, EM_LIMITTEXT, 3, 0L);
|
||
|
SetDlgItemInt(hdlg, IDC_WHEELLINENO, 3, 0);
|
||
|
SendDlgItemMessage(hdlg, IDC_WHEELLINEUD,
|
||
|
UDM_SETRANGE, 0, MAKELPARAM(999, 1));
|
||
|
if (SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &dw, 0)) {
|
||
|
if (GetSystemMetrics(SM_MOUSEWHEELPRESENT)) {
|
||
|
CheckDlgButton(hdlg, IDC_WHEELENABLE, dw != 0);
|
||
|
if (dw == WHEEL_PAGESCROLL) {
|
||
|
CheckDlgButton(hdlg, IDC_WHEELPAGE, TRUE);
|
||
|
} else {
|
||
|
CheckDlgButton(hdlg, IDC_WHEELLINE, TRUE);
|
||
|
if (dw) {
|
||
|
SetDlgItemInt(hdlg, IDC_WHEELLINENO, dw, 0);
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
EnableDlgItem(hdlg, IDC_WHEELENABLE, 0);
|
||
|
}
|
||
|
} else {
|
||
|
DestroyDlgItems(hdlg, IDC_WHEELFIRST, IDC_WHEELLAST);
|
||
|
}
|
||
|
|
||
|
if (fXMouse() < 0) {
|
||
|
DestroyDlgItems(hdlg, IDC_XMOUSEFIRST, IDC_XMOUSELAST);
|
||
|
} else {
|
||
|
|
||
|
if (fXMouseRaise() < 0) {
|
||
|
EnableDlgItem(hdlg, IDC_XMOUSERAISE, FALSE);
|
||
|
}
|
||
|
|
||
|
if (msXMouseDelay() < 0) {
|
||
|
EnableDlgItem(hdlg, IDC_XMOUSEDELAY, FALSE);
|
||
|
EnableDlgItem(hdlg, IDC_XMOUSEDELAYTXT, FALSE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (fGrovel()) {
|
||
|
Mouse_Reset(hdlg);
|
||
|
return 1; /* Allow focus to travel normally */
|
||
|
} else {
|
||
|
lpdt = &dtScratch;
|
||
|
*lpdt = dtCur(); /* Gotta give it something */
|
||
|
Mouse_Reset(hdlg);
|
||
|
ShowWindow(GetDlgItem(hdlg, IDC_SPEEDHELP), SW_HIDE);
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* Mouse_OnLButtonDown
|
||
|
*
|
||
|
* If the left button went down in the test area, begin capturing.
|
||
|
* Also record the time the button went down, so we can do double-click
|
||
|
* fuzz testing.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
BOOL PASCAL
|
||
|
Mouse_OnLButtonDown(HWND hdlg, int x, int y)
|
||
|
{
|
||
|
POINT pt = { x, y };
|
||
|
LONG tm = GetMessageTime();
|
||
|
|
||
|
if (PtInRect(&pmdii->rcTest, pt)) {
|
||
|
/*
|
||
|
* Is this a double-click?
|
||
|
*/
|
||
|
if (pmdii->tmClick &&
|
||
|
(DWORD)(tm - pmdii->tmClick) < GetDoubleClickTime() &&
|
||
|
PtInRect(&pmdii->rcDblClk, pt)) {
|
||
|
pmdii->idi ^= IDI_GEAR1 ^ IDI_GEAR2;
|
||
|
DestroyCursor(Mouse_SetTestIcon(hdlg, pmdii->idi));
|
||
|
tm = 0;
|
||
|
}
|
||
|
|
||
|
SetRectPoint(&pmdii->rcDrag, pt);
|
||
|
SetRectPoint(&pmdii->rcDblClk, pt);
|
||
|
InflateRect(&pmdii->rcDrag, pmdii->ptDrag.x, pmdii->ptDrag.y);
|
||
|
InflateRect(&pmdii->rcDblClk, pmdii->ptDblClk.x, pmdii->ptDblClk.y);
|
||
|
|
||
|
pmdii->fDrag = 1; /* Drag in progress */
|
||
|
SetCapture(hdlg);
|
||
|
}
|
||
|
pmdii->tmClick = tm;
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* Mouse_OnMouseMove
|
||
|
*
|
||
|
* If we are captured, see if we've moved far enough to act as
|
||
|
* if a drag is in progress.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
BOOL PASCAL
|
||
|
Mouse_OnMouseMove(HWND hdlg, int x, int y)
|
||
|
{
|
||
|
if (pmdii->fDrag && !pmdii->hcurDrag) {
|
||
|
POINT pt = { x, y };
|
||
|
if (!PtInRect(&pmdii->rcDrag, pt)) {
|
||
|
pmdii->hcurDrag = Mouse_SetTestIcon(hdlg, IDI_BLANK);
|
||
|
|
||
|
/*
|
||
|
* Tweak the cursor position so it looks like the icon
|
||
|
* dragged from the original click point.
|
||
|
*/
|
||
|
ICONINFO ii;
|
||
|
if (GetIconInfo(pmdii->hcurDrag, &ii)) {
|
||
|
DeleteObject(ii.hbmMask);
|
||
|
DeleteObject(ii.hbmColor);
|
||
|
|
||
|
/*
|
||
|
* These formulas are heinous.
|
||
|
*
|
||
|
* xClick = client coordinates of original click
|
||
|
* = pmdii->rcDrag.left + pmdii->ptDrag.x
|
||
|
*
|
||
|
* xTest = client coordinates of start of clickable icon
|
||
|
* = pmdii->rcTest.left
|
||
|
*
|
||
|
* xOffset = location of click relative to icon corner
|
||
|
* = xClick - xTest
|
||
|
*
|
||
|
* xAdjust = amount the user's click location differs
|
||
|
* from the actual hotspot
|
||
|
* = ii.xHotspot - xOffset
|
||
|
* = ii.xHotspot - xClick + xTest
|
||
|
*/
|
||
|
pt.x += + ii.xHotspot
|
||
|
- (pmdii->rcDrag.left + pmdii->ptDrag.x)
|
||
|
+ pmdii->rcTest.left;
|
||
|
pt.y += + ii.yHotspot
|
||
|
- (pmdii->rcDrag.top + pmdii->ptDrag.y)
|
||
|
+ pmdii->rcTest.top;
|
||
|
ClientToScreen(hdlg, &pt);
|
||
|
SetCursorPos(pt.x, pt.y);
|
||
|
}
|
||
|
|
||
|
SetCursor(pmdii->hcurDrag);
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* Mouse_OnRButtonUp
|
||
|
*
|
||
|
* If the button went up in the menu test area, track a menu.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
BOOL PASCAL
|
||
|
Mouse_OnRButtonUp(HWND hdlg, int x, int y)
|
||
|
{
|
||
|
POINT pt = { x, y };
|
||
|
if (PtInRect(&pmdii->rcTest, pt) && fLpdt) {
|
||
|
DT dt;
|
||
|
int id;
|
||
|
|
||
|
dt = msDt(); /* Save for revert */
|
||
|
SetDt(Mouse_GetDt(hdlg), 0);
|
||
|
|
||
|
ClientToScreen(hdlg, &pt); /* Make it screen coordinates */
|
||
|
id = TrackPopupMenuEx(GetSubMenu(pcdii->hmenu, 0),
|
||
|
TPM_RETURNCMD | TPM_RIGHTBUTTON | TPM_VERTICAL |
|
||
|
TPM_LEFTALIGN | TPM_TOPALIGN, pt.x, pt.y,
|
||
|
hdlg, 0);
|
||
|
|
||
|
SetDt(dt, 0);
|
||
|
return 1;
|
||
|
} else {
|
||
|
return 0; /* Do the default thing */
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* Our window procedure.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
/*
|
||
|
* The HANDLE_WM_* macros weren't designed to be used from a dialog
|
||
|
* proc, so we need to handle the messages manually. (But carefully.)
|
||
|
*/
|
||
|
|
||
|
INT_PTR EXPORT
|
||
|
Mouse_DlgProc(HWND hdlg, UINT wm, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
switch (wm) {
|
||
|
case WM_INITDIALOG: return Mouse_OnInitDialog(hdlg);
|
||
|
|
||
|
/* We have only one trackbar, so we don't need to check */
|
||
|
case WM_HSCROLL: Mouse_SetDirty(hdlg); return 1;
|
||
|
|
||
|
/* We have two updowns, but reloading is cheap, so we just reload both */
|
||
|
case WM_VSCROLL:
|
||
|
if (GET_WM_VSCROLL_CODE(wParam, lParam) == SB_THUMBPOSITION) {
|
||
|
return Mouse_ReloadUpdowns(hdlg);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_COMMAND:
|
||
|
return Mouse_OnCommand(hdlg,
|
||
|
(int)GET_WM_COMMAND_ID(wParam, lParam),
|
||
|
(UINT)GET_WM_COMMAND_CMD(wParam, lParam));
|
||
|
case WM_NOTIFY:
|
||
|
return Mouse_OnNotify(hdlg, (NMHDR FAR *)lParam);
|
||
|
|
||
|
case WM_LBUTTONDOWN:
|
||
|
case WM_LBUTTONDBLCLK:
|
||
|
return Mouse_OnLButtonDown(hdlg, LOWORD(lParam), HIWORD(lParam));
|
||
|
|
||
|
case WM_ACTIVATE:
|
||
|
if (GET_WM_ACTIVATE_STATE(wParam, lParam) == WA_INACTIVE) {
|
||
|
Mouse_StopDrag(hdlg);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_LBUTTONUP:
|
||
|
Mouse_StopDrag(hdlg);
|
||
|
break;
|
||
|
|
||
|
case WM_RBUTTONUP:
|
||
|
return Mouse_OnRButtonUp(hdlg, LOWORD(lParam), HIWORD(lParam));
|
||
|
|
||
|
case WM_HELP: Common_OnHelp(lParam, &rgdwHelp[0]); break;
|
||
|
|
||
|
case WM_CONTEXTMENU: Common_OnContextMenu(wParam, &rgdwHelp[0]); break;
|
||
|
|
||
|
case WM_MOUSEMOVE:
|
||
|
return Mouse_OnMouseMove(hdlg, LOWORD(lParam), HIWORD(lParam));
|
||
|
|
||
|
default: return 0; /* Unhandled */
|
||
|
}
|
||
|
return 1; /* Handled */
|
||
|
}
|