2478 lines
68 KiB
C
2478 lines
68 KiB
C
/*++
|
|
|
|
Copyright (c) 1994-1998, Microsoft Corporation All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
mouseptr.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the routines for the Mouse Pointer Property Sheet
|
|
page.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
|
|
//
|
|
// Include Files.
|
|
//
|
|
|
|
#include "main.h"
|
|
#include "rc.h"
|
|
#include "mousehlp.h"
|
|
#include <regstr.h>
|
|
|
|
//
|
|
// From shell\inc\shsemip.h
|
|
//
|
|
#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
|
|
|
|
|
|
|
|
//
|
|
// Constant Declarations.
|
|
//
|
|
|
|
#define gcxAvgChar 8
|
|
|
|
#define MAX_SCHEME_NAME_LEN 64
|
|
#define MAX_SCHEME_SUFFIX 32 // length of " (system scheme)" - update if more space is needed
|
|
#define OVERWRITE_TITLE 32 // length of title for the confirm overwrite dialog
|
|
#define OVERWRITE_MSG 200 // length of the message for the overwrite dialog
|
|
|
|
#define PM_NEWCURSOR (WM_USER + 1)
|
|
#define PM_PAUSEANIMATION (WM_USER + 2)
|
|
#define PM_UNPAUSEANIMATION (WM_USER + 3)
|
|
|
|
#define ID_PREVIEWTIMER 1
|
|
|
|
#define CCH_ANISTRING 80
|
|
|
|
#define CIF_FILE 0x0001
|
|
#define CIF_MODIFIED 0x0002
|
|
#define CIF_SHARED 0x0004
|
|
|
|
#define IDT_BROWSE 1
|
|
|
|
|
|
|
|
|
|
//
|
|
// Typedef Declarations.
|
|
//
|
|
|
|
typedef struct _CURSOR_INFO
|
|
{
|
|
DWORD fl;
|
|
HCURSOR hcur;
|
|
int ccur;
|
|
int icur;
|
|
TCHAR szFile[MAX_PATH];
|
|
} CURSOR_INFO, *PCURSOR_INFO;
|
|
|
|
#pragma pack(2)
|
|
typedef struct tagNEWHEADER
|
|
{
|
|
WORD reserved;
|
|
WORD rt;
|
|
WORD cResources;
|
|
} NEWHEADER, *LPNEWHEADER;
|
|
#pragma pack()
|
|
|
|
typedef struct
|
|
{
|
|
UINT idVisName;
|
|
int idResource;
|
|
int idDefResource;
|
|
LPTSTR pszIniName;
|
|
TCHAR szVisName[MAX_PATH];
|
|
} CURSORDESC, *PCURSORDESC;
|
|
|
|
//
|
|
// Structure that contains data used within a preview window. This
|
|
// data is unique for each preview window, and is used to optimize
|
|
// the painting.
|
|
//
|
|
typedef struct
|
|
{
|
|
HDC hdcMem;
|
|
HBITMAP hbmMem;
|
|
HBITMAP hbmOld;
|
|
PCURSOR_INFO pcuri;
|
|
} PREVIEWDATA, *PPREVIEWDATA;
|
|
|
|
|
|
typedef struct _MOUSEPTRBR
|
|
{
|
|
HWND hDlg;
|
|
CURSOR_INFO curi;
|
|
} MOUSEPTRBR, *PMOUSEPTRBR;
|
|
|
|
|
|
|
|
|
|
//
|
|
// Global Variables.
|
|
//
|
|
|
|
extern HINSTANCE g_hInst; // from main.c
|
|
int gcxCursor, gcyCursor;
|
|
HWND ghwndDlg, ghwndFile, ghwndFileH, ghwndTitle, ghwndTitleH;
|
|
HWND ghwndCreator, ghwndCreatorH, ghwndCursors, ghwndPreview, ghwndSchemeCB;
|
|
HBRUSH ghbrHighlight, ghbrHighlightText, ghbrWindow, ghbrButton;
|
|
|
|
UINT guTextHeight = 0;
|
|
UINT guTextGap = 0;
|
|
|
|
COLORREF gcrHighlightText;
|
|
|
|
TCHAR gszFileName2[MAX_PATH];
|
|
|
|
UINT wBrowseHelpMessage;
|
|
|
|
LPTSTR gszFileNotFound = NULL;
|
|
LPTSTR gszBrowse = NULL;
|
|
LPTSTR gszFilter = NULL;
|
|
|
|
TCHAR gszNoMem[256] = TEXT("No Memory");
|
|
|
|
HHOOK ghhkMsgFilter; // hook handle for message filter function
|
|
|
|
static const TCHAR szRegStr_Setup[] = REGSTR_PATH_SETUP TEXT("\\Setup");
|
|
static const TCHAR szSharedDir[] = TEXT("SharedDir");
|
|
|
|
BOOL gfCursorShadow = FALSE;
|
|
|
|
//
|
|
// Make sure you add new cursors to the end of this array.
|
|
// Otherwise the cursor schemes will not work
|
|
//
|
|
CURSORDESC gacd[] =
|
|
{
|
|
{ IDS_ARROW, OCR_NORMAL, OCR_ARROW_DEFAULT, TEXT("Arrow"), TEXT("") },
|
|
{ IDS_HELPCUR, OCR_HELP, OCR_HELP_DEFAULT, TEXT("Help"), TEXT("") },
|
|
{ IDS_APPSTARTING, OCR_APPSTARTING, OCR_APPSTARTING_DEFAULT, TEXT("AppStarting"), TEXT("") },
|
|
{ IDS_WAIT, OCR_WAIT, OCR_WAIT_DEFAULT, TEXT("Wait"), TEXT("") },
|
|
{ IDS_CROSS, OCR_CROSS, OCR_CROSS_DEFAULT, TEXT("Crosshair"), TEXT("") },
|
|
{ IDS_IBEAM, OCR_IBEAM, OCR_IBEAM_DEFAULT, TEXT("IBeam"), TEXT("") },
|
|
{ IDS_NWPEN, OCR_NWPEN, OCR_NWPEN_DEFAULT, TEXT("NWPen"), TEXT("") },
|
|
{ IDS_NO, OCR_NO, OCR_NO_DEFAULT, TEXT("No"), TEXT("") },
|
|
{ IDS_SIZENS, OCR_SIZENS, OCR_SIZENS_DEFAULT, TEXT("SizeNS"), TEXT("") },
|
|
{ IDS_SIZEWE, OCR_SIZEWE, OCR_SIZEWE_DEFAULT, TEXT("SizeWE"), TEXT("") },
|
|
{ IDS_SIZENWSE, OCR_SIZENWSE, OCR_SIZENWSE_DEFAULT, TEXT("SizeNWSE"), TEXT("") },
|
|
{ IDS_SIZENESW, OCR_SIZENESW, OCR_SIZENESW_DEFAULT, TEXT("SizeNESW"), TEXT("") },
|
|
{ IDS_SIZEALL, OCR_SIZEALL, OCR_SIZEALL_DEFAULT, TEXT("SizeAll"), TEXT("") },
|
|
{ IDS_UPARROW, OCR_UP, OCR_UPARROW_DEFAULT, TEXT("UpArrow"), TEXT("") },
|
|
{ IDS_HANDCUR, OCR_HAND, OCR_HAND_DEFAULT, TEXT("Hand"), TEXT("") },
|
|
};
|
|
|
|
#define CCURSORS (sizeof(gacd) / sizeof(gacd[0]))
|
|
|
|
CURSOR_INFO acuri[CCURSORS];
|
|
|
|
//
|
|
// Registry Keys.
|
|
//
|
|
const TCHAR szCursorSubdir[] = TEXT("Cursors");
|
|
const TCHAR szCursorRegPath[] = REGSTR_PATH_CURSORS;
|
|
|
|
static const TCHAR c_szRegPathCursors[] = REGSTR_PATH_CURSORS;
|
|
static const TCHAR c_szSchemes[] = TEXT("Schemes");
|
|
|
|
static const TCHAR c_szRegPathCursorSchemes[] = REGSTR_PATH_CURSORS TEXT( "\\Schemes" );
|
|
|
|
//
|
|
// Strings used to read from the combo box must be larger than max length.
|
|
//
|
|
TCHAR gszSchemeName[MAX_SCHEME_SUFFIX + MAX_SCHEME_NAME_LEN + 1]; // used to store selected scheme name for saving
|
|
int iSchemeLocation; // used to store scheme location (HKCU vs HKLM)
|
|
|
|
static const TCHAR c_szRegPathSystemSchemes[] = REGSTR_PATH_SETUP TEXT("\\Control Panel\\Cursors\\Schemes");
|
|
TCHAR szSystemScheme[MAX_SCHEME_SUFFIX];
|
|
TCHAR szNone[MAX_SCHEME_NAME_LEN + 1];
|
|
const TCHAR szSchemeSource[] = TEXT("Scheme Source");
|
|
|
|
TCHAR gszPreviousScheme[MAX_SCHEME_SUFFIX + MAX_SCHEME_NAME_LEN + 1]; // used to tell if a different scheme is selected
|
|
|
|
#define ID_NONE_SCHEME 0
|
|
#define ID_USER_SCHEME 1
|
|
#define ID_OS_SCHEME 2
|
|
|
|
|
|
|
|
|
|
//
|
|
// Context Help Ids.
|
|
//
|
|
|
|
const static DWORD aMousePtrHelpIDs[] =
|
|
{
|
|
IDC_GROUPBOX_1, IDH_COMM_GROUPBOX,
|
|
ID_SCHEMECOMBO, IDH_MOUSE_POINT_SCHEME,
|
|
ID_SAVESCHEME, IDH_MOUSE_POINT_SAVEAS,
|
|
ID_REMOVESCHEME, IDH_MOUSE_POINT_DEL,
|
|
ID_PREVIEW, IDH_MOUSE_POINT_PREVIEW,
|
|
ID_CURSORLIST, IDH_MOUSE_POINT_LIST,
|
|
ID_DEFAULT, IDH_MOUSE_POINT_DEFAULT,
|
|
ID_BROWSE, IDH_MOUSE_POINT_BROWSE,
|
|
ID_CURSORSHADOW, IDH_MOUSE_CURSORSHADOW,
|
|
|
|
0, 0
|
|
};
|
|
|
|
const static DWORD aMousePtrBrowseHelpIDs[] =
|
|
{
|
|
IDC_GROUPBOX_1, IDH_MOUSE_POINT_PREVIEW,
|
|
ID_CURSORPREVIEW, IDH_MOUSE_POINT_PREVIEW,
|
|
|
|
0, 0
|
|
};
|
|
|
|
const static DWORD aHelpIDs[] =
|
|
{
|
|
ID_SCHEMEFILENAME, IDH_MOUSE_NEW_SCHEME_NAME,
|
|
|
|
0, 0
|
|
};
|
|
|
|
|
|
|
|
|
|
//
|
|
// Forward Declarations.
|
|
//
|
|
|
|
void LoadCursorSet(HWND hwnd);
|
|
|
|
void CreateBrushes(void);
|
|
|
|
LPTSTR GetResourceString(HINSTANCE hmod,int id);
|
|
|
|
void DrawCursorListItem(DRAWITEMSTRUCT *pdis);
|
|
|
|
BOOL GetCursorFromFile(CURSOR_INFO *pcuri);
|
|
|
|
BOOL Browse(HWND hwndOwner);
|
|
|
|
void CleanUpEverything(void);
|
|
|
|
VOID UpdateCursorList(void);
|
|
|
|
VOID NextFrame(HWND hwnd);
|
|
|
|
void HourGlass(BOOL fOn);
|
|
|
|
BOOL TryToLoadCursor(
|
|
HWND hwnd,
|
|
int i,
|
|
CURSOR_INFO *pcuri);
|
|
|
|
BOOL LoadScheme(void);
|
|
|
|
BOOL SaveScheme(void);
|
|
|
|
BOOL SaveSchemeAs(void);
|
|
|
|
void SaveCurSchemeName(void);
|
|
|
|
BOOL RemoveScheme(void);
|
|
|
|
BOOL InitSchemeComboBox(void);
|
|
|
|
BOOL SchemeUpdate(int i);
|
|
|
|
LPTSTR MakeFilename(LPTSTR sz);
|
|
|
|
INT_PTR CALLBACK SaveSchemeDlgProc(
|
|
HWND hWnd,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam);
|
|
|
|
void CurStripBlanks(LPTSTR pszString, int cchString);
|
|
|
|
int SystemOrUser(TCHAR *pszSchemeName);
|
|
|
|
BOOL UnExpandPath(LPTSTR pszPath, int cchPath);
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// RegisterPointerStuff
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL RegisterPointerStuff(
|
|
HINSTANCE hi)
|
|
{
|
|
gcxCursor = GetSystemMetrics(SM_CXCURSOR);
|
|
gcyCursor = GetSystemMetrics(SM_CYCURSOR);
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// InitCursorsShadow
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void InitCursorShadow(HWND hwnd)
|
|
{
|
|
BOOL fPalette;
|
|
HDC hdc;
|
|
int nCommand;
|
|
|
|
hdc = GetDC(NULL);
|
|
fPalette = (GetDeviceCaps(hdc, NUMCOLORS) != -1);
|
|
ReleaseDC(NULL, hdc);
|
|
|
|
if (!fPalette) {
|
|
nCommand = SW_SHOW;
|
|
} else {
|
|
nCommand = SW_HIDE;
|
|
}
|
|
ShowWindow(GetDlgItem(hwnd, ID_CURSORSHADOW), nCommand);
|
|
|
|
if (nCommand == SW_SHOW) {
|
|
SystemParametersInfo(SPI_GETCURSORSHADOW, 0, (PVOID)&gfCursorShadow, 0);
|
|
CheckDlgButton(hwnd, ID_CURSORSHADOW, gfCursorShadow);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// InitCursorsDlg
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL InitCursorsDlg(HWND hwnd)
|
|
{
|
|
int i;
|
|
ghwndDlg = hwnd;
|
|
gszPreviousScheme[0] = TEXT('\0');
|
|
|
|
//
|
|
// Register the help message from the File Open (Browse) dialog.
|
|
//
|
|
wBrowseHelpMessage = RegisterWindowMessage(HELPMSGSTRING);
|
|
|
|
//
|
|
// Load Strings.
|
|
//
|
|
if (gszFileNotFound == NULL)
|
|
{
|
|
gszFileNotFound = GetResourceString(g_hInst, IDS_CUR_BADFILE);
|
|
|
|
if (gszFileNotFound == NULL)
|
|
{
|
|
return (FALSE);
|
|
}
|
|
}
|
|
|
|
if (gszBrowse == NULL)
|
|
{
|
|
gszBrowse = GetResourceString(g_hInst, IDS_CUR_BROWSE);
|
|
|
|
if (gszBrowse == NULL)
|
|
{
|
|
return (FALSE);
|
|
}
|
|
}
|
|
|
|
#ifdef WINNT
|
|
if (gszFilter == NULL)
|
|
{
|
|
gszFilter = GetResourceString(g_hInst, IDS_ANICUR_FILTER);
|
|
|
|
if (!gszFilter)
|
|
{
|
|
return (FALSE);
|
|
}
|
|
}
|
|
#else
|
|
if (gszFilter == NULL)
|
|
{
|
|
HDC dc = GetDC(NULL);
|
|
BOOL fAni = (GetDeviceCaps(dc, CAPS1) & C1_COLORCURSOR) != 0;
|
|
|
|
ReleaseDC(NULL, dc);
|
|
|
|
gszFilter = GetResourceString( g_hInst,
|
|
fAni
|
|
? IDS_ANICUR_FILTER
|
|
: IDS_CUR_FILTER );
|
|
|
|
if (!gszFilter)
|
|
{
|
|
return (FALSE);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Load description strings from the resource file.
|
|
//
|
|
for (i = 0; i < CCURSORS; i++)
|
|
{
|
|
if ((!gacd[i].idVisName) ||
|
|
(LoadString( g_hInst,
|
|
gacd[i].idVisName,
|
|
gacd[i].szVisName,
|
|
ARRAYSIZE(gacd[i].szVisName) ) <= 0))
|
|
{
|
|
//
|
|
// Show something.
|
|
//
|
|
StringCchCopy(gacd[i].szVisName, ARRAYSIZE(gacd[i].szVisName), gacd[i].pszIniName);
|
|
}
|
|
}
|
|
|
|
//
|
|
// As an optimization, remember the window handles of the cursor
|
|
// information fields.
|
|
//
|
|
ghwndPreview = GetDlgItem(hwnd, ID_PREVIEW);
|
|
ghwndFile = GetDlgItem(hwnd, ID_FILE);
|
|
ghwndFileH = GetDlgItem(hwnd, ID_FILEH);
|
|
ghwndTitle = GetDlgItem(hwnd, ID_TITLE);
|
|
ghwndTitleH = GetDlgItem(hwnd, ID_TITLEH);
|
|
ghwndCreator = GetDlgItem(hwnd, ID_CREATOR);
|
|
ghwndCreatorH = GetDlgItem(hwnd, ID_CREATORH);
|
|
ghwndCursors = GetDlgItem(hwnd, ID_CURSORLIST);
|
|
ghwndSchemeCB = GetDlgItem(hwnd, ID_SCHEMECOMBO);
|
|
|
|
//
|
|
// Create some brushes we'll be using.
|
|
//
|
|
CreateBrushes();
|
|
|
|
//
|
|
// Initialize the scheme combo box.
|
|
//
|
|
InitSchemeComboBox();
|
|
|
|
//
|
|
// Pre-clear the cursor info array.
|
|
//
|
|
ZeroMemory(&acuri, sizeof(acuri));
|
|
|
|
//
|
|
// Load the cursors.
|
|
//
|
|
LoadCursorSet(hwnd);
|
|
|
|
//
|
|
// Force an update of the preview window and the cursor details.
|
|
//
|
|
UpdateCursorList();
|
|
|
|
InitCursorShadow(hwnd);
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// LoadCursorSet
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void LoadCursorSet(
|
|
HWND hwnd)
|
|
{
|
|
CURSOR_INFO *pcuri;
|
|
HKEY hkCursors;
|
|
int i;
|
|
|
|
if (RegOpenKeyEx(HKEY_CURRENT_USER, szCursorRegPath, 0, KEY_READ, &hkCursors) != ERROR_SUCCESS)
|
|
{
|
|
hkCursors = NULL;
|
|
}
|
|
|
|
for (pcuri = &acuri[0], i = 0; i < CCURSORS; i++, pcuri++)
|
|
{
|
|
if ( hkCursors )
|
|
{
|
|
DWORD dwType;
|
|
DWORD dwCount = sizeof(pcuri->szFile);
|
|
|
|
DWORD dwErr = RegQueryValueEx( hkCursors,
|
|
gacd[i].pszIniName,
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE)pcuri->szFile,
|
|
&dwCount );
|
|
|
|
if (dwErr == ERROR_SUCCESS)
|
|
{
|
|
if (TryToLoadCursor(hwnd, i, pcuri))
|
|
{
|
|
goto EverythingWorked;
|
|
}
|
|
}
|
|
}
|
|
|
|
// This is actually the failure case. We load the default cursor.
|
|
pcuri->hcur =
|
|
(HCURSOR)LoadImage( NULL,
|
|
MAKEINTRESOURCE(gacd[i].idResource),
|
|
IMAGE_CURSOR,
|
|
0,
|
|
0,
|
|
LR_SHARED | LR_DEFAULTSIZE | LR_ENVSUBST );
|
|
|
|
pcuri->fl |= CIF_SHARED;
|
|
|
|
EverythingWorked:
|
|
|
|
SendMessage(ghwndCursors, LB_ADDSTRING, 0, (LPARAM)gacd[i].szVisName);
|
|
SendMessage(ghwndCursors, LB_SETITEMDATA, i, i);
|
|
}
|
|
|
|
if (hkCursors)
|
|
{
|
|
RegCloseKey(hkCursors);
|
|
}
|
|
|
|
SendMessage(ghwndCursors, LB_SETCURSEL, 0, 0);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CreateBrushes
|
|
//
|
|
// Creates the brushes that are used to paint within the Cursors applet.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
VOID CreateBrushes()
|
|
{
|
|
ghbrHighlight = GetSysColorBrush(COLOR_HIGHLIGHT);
|
|
gcrHighlightText = GetSysColor(COLOR_HIGHLIGHTTEXT);
|
|
ghbrHighlightText = GetSysColorBrush(COLOR_HIGHLIGHTTEXT);
|
|
ghbrWindow = GetSysColorBrush(COLOR_WINDOW);
|
|
ghbrButton = GetSysColorBrush(COLOR_BTNFACE);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// GetResourceString
|
|
//
|
|
// Gets a string out of the resource file.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
LPTSTR GetResourceString(
|
|
HINSTANCE hmod,
|
|
int id)
|
|
{
|
|
TCHAR szBuffer[256];
|
|
LPTSTR psz;
|
|
int cch;
|
|
|
|
if ((cch = LoadString(hmod, id, szBuffer, ARRAYSIZE(szBuffer))) == 0)
|
|
{
|
|
return (NULL);
|
|
}
|
|
|
|
psz = LocalAlloc(LPTR, (cch + 1) * sizeof(TCHAR));
|
|
|
|
if (psz != NULL)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i <= cch; i++)
|
|
{
|
|
psz[i] = (szBuffer[i] == TEXT('\1')) ? TEXT('\0') : szBuffer[i];
|
|
}
|
|
}
|
|
|
|
return (psz);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// FreeItemCursor
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void FreeItemCursor(
|
|
CURSOR_INFO *pcuri)
|
|
{
|
|
if (pcuri->hcur)
|
|
{
|
|
if (!(pcuri->fl & CIF_SHARED))
|
|
{
|
|
DestroyCursor(pcuri->hcur);
|
|
}
|
|
pcuri->hcur = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MousePtrDlg
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
INT_PTR CALLBACK MousePtrDlg(
|
|
HWND hwnd,
|
|
UINT msg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
CURSOR_INFO *pcuri;
|
|
HKEY hkCursors;
|
|
int i;
|
|
|
|
switch (msg)
|
|
{
|
|
case ( WM_INITDIALOG ) :
|
|
{
|
|
return InitCursorsDlg(hwnd);
|
|
}
|
|
case ( WM_DISPLAYCHANGE ) :
|
|
{
|
|
InitCursorShadow(hwnd);
|
|
SHPropagateMessage(hwnd, msg, wParam, lParam, TRUE);
|
|
break;
|
|
}
|
|
case ( WM_MEASUREITEM ) :
|
|
{
|
|
((MEASUREITEMSTRUCT *)lParam)->itemHeight = gcyCursor + 2;
|
|
break;
|
|
}
|
|
case ( WM_DRAWITEM ) :
|
|
{
|
|
DrawCursorListItem((DRAWITEMSTRUCT *)lParam);
|
|
break;
|
|
}
|
|
case ( WM_COMMAND ) :
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case ( ID_SCHEMECOMBO ) :
|
|
{
|
|
switch (HIWORD(wParam))
|
|
{
|
|
case ( CBN_SELCHANGE ) :
|
|
{
|
|
LoadScheme();
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case ( ID_DEFAULT ) :
|
|
{
|
|
//
|
|
// Throw away any fancy new cursor and replace it with
|
|
// the system's original.
|
|
//
|
|
i = (int)SendMessage(ghwndCursors, LB_GETCURSEL, 0, 0);
|
|
|
|
pcuri = &acuri[i];
|
|
|
|
if (!(pcuri->fl & CIF_FILE))
|
|
{
|
|
break;
|
|
}
|
|
pcuri->fl = CIF_MODIFIED;
|
|
|
|
SendMessage(GetParent(hwnd), PSM_CHANGED, (WPARAM)hwnd, 0L);
|
|
|
|
FreeItemCursor(pcuri);
|
|
|
|
pcuri->hcur =
|
|
(HCURSOR)LoadImage( NULL,
|
|
MAKEINTRESOURCE(gacd[i].idDefResource),
|
|
IMAGE_CURSOR,
|
|
0,
|
|
0,
|
|
LR_DEFAULTSIZE | LR_ENVSUBST );
|
|
|
|
*pcuri->szFile = TEXT('\0');
|
|
|
|
EnableWindow(GetDlgItem(hwnd, ID_SAVESCHEME), TRUE);
|
|
|
|
UpdateCursorList();
|
|
|
|
break;
|
|
}
|
|
case ( ID_CURSORLIST ) :
|
|
{
|
|
switch (HIWORD(wParam))
|
|
{
|
|
case ( LBN_SELCHANGE ) :
|
|
{
|
|
i = (int)SendMessage((HWND)lParam, LB_GETCURSEL, 0, 0);
|
|
pcuri = &acuri[i];
|
|
|
|
//
|
|
// Show a preview (including animation) in the
|
|
// preview window.
|
|
//
|
|
SendMessage( ghwndPreview,
|
|
STM_SETICON,
|
|
(WPARAM)pcuri->hcur,
|
|
0L );
|
|
|
|
//
|
|
// Enable the "Set Default" button if the cursor
|
|
// is from a file.
|
|
//
|
|
EnableWindow( GetDlgItem(hwnd, ID_DEFAULT),
|
|
(pcuri->fl & CIF_FILE ) ? TRUE : FALSE );
|
|
break;
|
|
}
|
|
case ( LBN_DBLCLK ) :
|
|
{
|
|
Browse(hwnd);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case ( ID_BROWSE ) :
|
|
{
|
|
Browse(hwnd);
|
|
break;
|
|
}
|
|
case ( ID_SAVESCHEME ) :
|
|
{
|
|
SaveSchemeAs();
|
|
break;
|
|
}
|
|
case ( ID_REMOVESCHEME ) :
|
|
{
|
|
RemoveScheme();
|
|
break;
|
|
}
|
|
case ( ID_CURSORSHADOW ) :
|
|
{
|
|
gfCursorShadow = IsDlgButtonChecked(hwnd, ID_CURSORSHADOW);
|
|
SendMessage(GetParent(hwnd), PSM_CHANGED, (WPARAM)hwnd, 0L);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case ( WM_NOTIFY ) :
|
|
{
|
|
switch(((NMHDR *)lParam)->code)
|
|
{
|
|
case ( PSN_APPLY ) :
|
|
{
|
|
//
|
|
// Change cursor to hour glass.
|
|
//
|
|
HourGlass(TRUE);
|
|
|
|
// Set cursor shadow
|
|
SystemParametersInfo( SPI_SETCURSORSHADOW,
|
|
0,
|
|
IntToPtr(gfCursorShadow),
|
|
SPIF_UPDATEINIFILE);
|
|
|
|
//
|
|
// Save the modified scheme, order of calls important.
|
|
//
|
|
SaveCurSchemeName();
|
|
|
|
//
|
|
// Set the system cursors.
|
|
//
|
|
if (RegCreateKeyEx(HKEY_CURRENT_USER, szCursorRegPath, 0, NULL, 0, KEY_SET_VALUE, NULL, &hkCursors, NULL) == ERROR_SUCCESS)
|
|
{
|
|
for (pcuri = &acuri[0], i = 0; i < CCURSORS; i++, pcuri++)
|
|
{
|
|
if (pcuri->fl & CIF_MODIFIED)
|
|
{
|
|
LPCTSTR data;
|
|
UINT count;
|
|
|
|
// Always unexpand before we save a filename
|
|
UnExpandPath(pcuri->szFile, ARRAYSIZE(pcuri->szFile));
|
|
|
|
data = (pcuri->fl & CIF_FILE) ? pcuri->szFile : TEXT("");
|
|
count = (pcuri->fl & CIF_FILE) ? (lstrlen(pcuri->szFile) + 1) * sizeof(TCHAR) : sizeof(TCHAR);
|
|
|
|
RegSetValueEx(hkCursors, gacd[i].pszIniName, 0L, REG_EXPAND_SZ, (CONST LPBYTE)data, count);
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hkCursors);
|
|
|
|
SystemParametersInfo( SPI_SETCURSORS,
|
|
0,
|
|
0,
|
|
SPIF_SENDCHANGE );
|
|
}
|
|
|
|
HourGlass(FALSE);
|
|
break;
|
|
}
|
|
default :
|
|
{
|
|
return (FALSE);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case ( WM_SYSCOLORCHANGE ) :
|
|
{
|
|
gcrHighlightText = GetSysColor(COLOR_HIGHLIGHTTEXT);
|
|
SHPropagateMessage(hwnd, msg, wParam, lParam, TRUE);
|
|
break;
|
|
}
|
|
|
|
case ( WM_WININICHANGE ) :
|
|
{
|
|
SHPropagateMessage(hwnd, msg, wParam, lParam, TRUE);
|
|
break;
|
|
}
|
|
|
|
case ( WM_DESTROY ) :
|
|
{
|
|
//
|
|
// Clean up global allocs.
|
|
//
|
|
CleanUpEverything();
|
|
|
|
if (gszFileNotFound != NULL)
|
|
{
|
|
LocalFree(gszFileNotFound);
|
|
gszFileNotFound = NULL;
|
|
}
|
|
|
|
if (gszBrowse != NULL)
|
|
{
|
|
LocalFree(gszBrowse);
|
|
gszBrowse = NULL;
|
|
}
|
|
|
|
if (gszFilter != NULL)
|
|
{
|
|
LocalFree(gszFilter);
|
|
gszFilter = NULL;
|
|
}
|
|
break;
|
|
}
|
|
case ( WM_HELP ) :
|
|
{
|
|
WinHelp( ((LPHELPINFO)lParam)->hItemHandle,
|
|
HELP_FILE,
|
|
HELP_WM_HELP,
|
|
(DWORD_PTR)(LPTSTR)aMousePtrHelpIDs );
|
|
break;
|
|
}
|
|
case ( WM_CONTEXTMENU ) :
|
|
{
|
|
WinHelp( (HWND)wParam,
|
|
HELP_FILE,
|
|
HELP_CONTEXTMENU,
|
|
(DWORD_PTR)(LPVOID)aMousePtrHelpIDs );
|
|
break;
|
|
}
|
|
default :
|
|
{
|
|
return (FALSE);
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// DrawCursorListItem
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void DrawCursorListItem(
|
|
DRAWITEMSTRUCT *pdis)
|
|
{
|
|
CURSOR_INFO *pcuri;
|
|
COLORREF clrOldText, clrOldBk;
|
|
RECT rc;
|
|
DWORD dwLayout;
|
|
|
|
if (!guTextHeight || !guTextGap)
|
|
{
|
|
TEXTMETRIC tm;
|
|
|
|
tm.tmHeight = 0;
|
|
GetTextMetrics(pdis->hDC, &tm);
|
|
|
|
if (tm.tmHeight < 0)
|
|
{
|
|
tm.tmHeight *= -1;
|
|
}
|
|
guTextHeight = (UINT)tm.tmHeight;
|
|
guTextGap = (UINT)tm.tmAveCharWidth;
|
|
}
|
|
|
|
pcuri = &acuri[pdis->itemData];
|
|
|
|
if (pdis->itemState & ODS_SELECTED)
|
|
{
|
|
clrOldText = SetTextColor(pdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
|
|
clrOldBk = SetBkColor(pdis->hDC, GetSysColor(COLOR_HIGHLIGHT));
|
|
}
|
|
else
|
|
{
|
|
clrOldText = SetTextColor(pdis->hDC, GetSysColor(COLOR_WINDOWTEXT));
|
|
clrOldBk = SetBkColor(pdis->hDC, GetSysColor(COLOR_WINDOW));
|
|
}
|
|
|
|
ExtTextOut( pdis->hDC,
|
|
pdis->rcItem.left + guTextGap, // fudge factor
|
|
(pdis->rcItem.top + pdis->rcItem.bottom - guTextHeight) / 2,
|
|
ETO_OPAQUE,
|
|
&pdis->rcItem,
|
|
gacd[pdis->itemData].szVisName,
|
|
lstrlen(gacd[pdis->itemData].szVisName),
|
|
NULL );
|
|
|
|
if (pcuri->hcur != NULL)
|
|
{
|
|
dwLayout = GetLayout(pdis->hDC);
|
|
SetLayout(pdis->hDC, dwLayout | LAYOUT_BITMAPORIENTATIONPRESERVED);
|
|
DrawIcon( pdis->hDC,
|
|
pdis->rcItem.right - (gcxCursor + guTextGap),
|
|
pdis->rcItem.top + 1, pcuri->hcur );
|
|
SetLayout(pdis->hDC, dwLayout);
|
|
}
|
|
|
|
if (pdis->itemState & ODS_FOCUS)
|
|
{
|
|
CopyRect(&rc, &pdis->rcItem);
|
|
InflateRect(&rc, -1, -1);
|
|
DrawFocusRect(pdis->hDC, &rc);
|
|
}
|
|
|
|
SetTextColor(pdis->hDC, clrOldText);
|
|
SetBkColor(pdis->hDC, clrOldBk);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// TryToLoadCursor
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL TryToLoadCursor(
|
|
HWND hwnd,
|
|
int i,
|
|
CURSOR_INFO *pcuri)
|
|
{
|
|
BOOL fRet = TRUE;
|
|
BOOL bCustom = (*pcuri->szFile != 0);
|
|
|
|
|
|
if (bCustom && !GetCursorFromFile(pcuri))
|
|
{
|
|
HWND hwndControl = GetParent(hwnd);
|
|
LPTSTR pszText;
|
|
LPTSTR pszFilename;
|
|
int cchText;
|
|
|
|
//
|
|
// MakeFilename returns the address of a global, so we don't
|
|
// need to free pszFilename.
|
|
//
|
|
pszFilename = MakeFilename(pcuri->szFile);
|
|
|
|
cchText = lstrlen(gszFileNotFound) + lstrlen(gacd[i].szVisName) + lstrlen(pszFilename) + 1;
|
|
|
|
pszText = LocalAlloc(LPTR, cchText * sizeof(TCHAR));
|
|
|
|
if (pszText == NULL)
|
|
{
|
|
return (FALSE);
|
|
}
|
|
|
|
StringCchPrintf(pszText, cchText, gszFileNotFound, pszFilename, gacd[i].szVisName);
|
|
|
|
MessageBeep(MB_ICONEXCLAMATION);
|
|
|
|
MessageBox(hwndControl, pszText, NULL, MB_ICONEXCLAMATION | MB_OK);
|
|
|
|
pcuri->fl = CIF_MODIFIED;
|
|
|
|
SendMessage(GetParent(hwnd), PSM_CHANGED, (WPARAM)hwnd, 0L);
|
|
|
|
bCustom = FALSE;
|
|
|
|
LocalFree(pszText);
|
|
}
|
|
|
|
if (!bCustom)
|
|
{
|
|
FreeItemCursor(pcuri);
|
|
|
|
pcuri->hcur =
|
|
(HCURSOR)LoadImage( NULL,
|
|
MAKEINTRESOURCE(gacd[i].idDefResource),
|
|
IMAGE_CURSOR,
|
|
0,
|
|
0,
|
|
LR_DEFAULTSIZE | LR_ENVSUBST );
|
|
|
|
*pcuri->szFile = TEXT('\0');
|
|
|
|
EnableWindow(GetDlgItem(hwnd, ID_SAVESCHEME), TRUE);
|
|
UpdateCursorList();
|
|
}
|
|
|
|
return (pcuri->hcur != NULL);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// GetCursorFromFile
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL GetCursorFromFile(
|
|
CURSOR_INFO *pcuri)
|
|
{
|
|
pcuri->fl = 0;
|
|
pcuri->hcur =
|
|
(HCURSOR)LoadImage( NULL,
|
|
MakeFilename(pcuri->szFile),
|
|
IMAGE_CURSOR,
|
|
0,
|
|
0,
|
|
LR_LOADFROMFILE | LR_DEFAULTSIZE | LR_ENVSUBST );
|
|
|
|
if (pcuri->hcur)
|
|
{
|
|
pcuri->fl |= CIF_FILE;
|
|
}
|
|
|
|
return (pcuri->hcur != NULL);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MousePtrBrowsePreview
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void MousePtrBrowsePreview(
|
|
HWND hDlg)
|
|
{
|
|
PMOUSEPTRBR pPtrBr;
|
|
HCURSOR hcurOld;
|
|
|
|
pPtrBr = (PMOUSEPTRBR)GetWindowLongPtr(hDlg, DWLP_USER);
|
|
|
|
hcurOld = pPtrBr->curi.hcur;
|
|
|
|
CommDlg_OpenSave_GetFilePath( GetParent(hDlg),
|
|
pPtrBr->curi.szFile,
|
|
ARRAYSIZE(pPtrBr->curi.szFile) );
|
|
|
|
if (!GetCursorFromFile(&pPtrBr->curi))
|
|
{
|
|
pPtrBr->curi.hcur = NULL;
|
|
}
|
|
|
|
SendDlgItemMessage( hDlg,
|
|
ID_CURSORPREVIEW,
|
|
STM_SETICON,
|
|
(WPARAM)pPtrBr->curi.hcur, 0L );
|
|
|
|
if (hcurOld)
|
|
{
|
|
DestroyCursor(hcurOld);
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MousePtrBrowseNotify
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL MousePtrBrowseNotify(
|
|
HWND hDlg,
|
|
LPOFNOTIFY pofn)
|
|
{
|
|
switch (pofn->hdr.code)
|
|
{
|
|
case ( CDN_SELCHANGE ) :
|
|
{
|
|
//
|
|
// Don't show the cursor until the user stops moving around.
|
|
//
|
|
if (SetTimer(hDlg, IDT_BROWSE, 250, NULL))
|
|
{
|
|
//
|
|
// Don't destroy the old cursor.
|
|
//
|
|
SendDlgItemMessage( hDlg,
|
|
ID_CURSORPREVIEW,
|
|
STM_SETICON,
|
|
0,
|
|
0L );
|
|
}
|
|
else
|
|
{
|
|
MousePtrBrowsePreview(hDlg);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MousePtrBrowseDlgProc
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
INT_PTR CALLBACK MousePtrBrowseDlgProc(
|
|
HWND hDlg,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case ( WM_INITDIALOG ) :
|
|
{
|
|
PMOUSEPTRBR pPtrBr = (PMOUSEPTRBR)((LPOPENFILENAME)lParam)->lCustData;
|
|
|
|
if (pPtrBr)
|
|
{
|
|
pPtrBr->hDlg = hDlg;
|
|
}
|
|
|
|
SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR) pPtrBr);
|
|
break;
|
|
}
|
|
case ( WM_DESTROY ) :
|
|
{
|
|
KillTimer(hDlg, IDT_BROWSE);
|
|
|
|
//
|
|
// Don't destroy the old cursor.
|
|
//
|
|
SendDlgItemMessage(hDlg, ID_CURSORPREVIEW, STM_SETICON, 0, 0L);
|
|
break;
|
|
}
|
|
case ( WM_TIMER ) :
|
|
{
|
|
KillTimer(hDlg, IDT_BROWSE);
|
|
|
|
MousePtrBrowsePreview(hDlg);
|
|
break;
|
|
}
|
|
case ( WM_NOTIFY ) :
|
|
{
|
|
return (MousePtrBrowseNotify(hDlg, (LPOFNOTIFY) lParam));
|
|
}
|
|
case ( WM_HELP ) :
|
|
{
|
|
WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle,
|
|
HELP_FILE,
|
|
HELP_WM_HELP,
|
|
(DWORD_PTR)(LPTSTR)aMousePtrBrowseHelpIDs );
|
|
break;
|
|
}
|
|
case ( WM_CONTEXTMENU ) :
|
|
{
|
|
WinHelp( (HWND)wParam,
|
|
HELP_FILE,
|
|
HELP_CONTEXTMENU,
|
|
(DWORD_PTR)(LPVOID)aMousePtrBrowseHelpIDs );
|
|
break;
|
|
}
|
|
default :
|
|
{
|
|
return (FALSE);
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Browse
|
|
//
|
|
// Browse the file system for a new cursor for the selected item.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL Browse(HWND hwndOwner)
|
|
{
|
|
static TCHAR szCustomFilter[80] = TEXT("");
|
|
static TCHAR szStartDir[MAX_PATH] = TEXT("");
|
|
|
|
OPENFILENAME ofn;
|
|
CURSOR_INFO curi;
|
|
int i;
|
|
BOOL fRet = FALSE;
|
|
MOUSEPTRBR sPtrBr;
|
|
|
|
if (!*szStartDir)
|
|
{
|
|
HKEY key = NULL;
|
|
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szRegStr_Setup, 0, KEY_READ, &key) == ERROR_SUCCESS)
|
|
{
|
|
LONG len = ARRAYSIZE(szStartDir);
|
|
|
|
if (RegQueryValueEx( key,
|
|
szSharedDir,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)szStartDir,
|
|
&len ) != ERROR_SUCCESS)
|
|
{
|
|
*szStartDir = TEXT('\0');
|
|
}
|
|
|
|
RegCloseKey(key);
|
|
}
|
|
|
|
if (!*szStartDir)
|
|
{
|
|
if (0 == GetWindowsDirectory(szStartDir, ARRAYSIZE(szStartDir)))
|
|
{
|
|
goto Error;
|
|
}
|
|
}
|
|
|
|
PathAppend(szStartDir, szCursorSubdir);
|
|
}
|
|
|
|
curi.szFile[0] = TEXT('\0');
|
|
|
|
sPtrBr.curi.szFile[0] = TEXT('\0');
|
|
sPtrBr.curi.hcur = NULL;
|
|
|
|
ofn.lStructSize = sizeof(ofn);
|
|
ofn.hwndOwner = hwndOwner;
|
|
ofn.hInstance = g_hInst;
|
|
ofn.lpstrFilter = gszFilter;
|
|
ofn.lpstrCustomFilter = szCustomFilter;
|
|
ofn.nMaxCustFilter = ARRAYSIZE(szCustomFilter);
|
|
ofn.nFilterIndex = 1;
|
|
ofn.lpstrFile = curi.szFile;
|
|
ofn.nMaxFile = ARRAYSIZE(curi.szFile);
|
|
ofn.lpstrFileTitle = NULL;
|
|
ofn.nMaxFileTitle = 0;
|
|
ofn.lpstrInitialDir = szStartDir;
|
|
ofn.lpstrTitle = gszBrowse;
|
|
ofn.Flags = OFN_EXPLORER | OFN_ENABLETEMPLATE | OFN_ENABLEHOOK |
|
|
OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
|
|
ofn.lpstrDefExt = NULL;
|
|
ofn.lpfnHook = MousePtrBrowseDlgProc;
|
|
ofn.lpTemplateName = MAKEINTRESOURCE(DLG_MOUSE_POINTER_BROWSE);
|
|
ofn.lCustData = (LPARAM)(PMOUSEPTRBR)&sPtrBr;
|
|
|
|
fRet = GetOpenFileName(&ofn);
|
|
|
|
if (!fRet)
|
|
{
|
|
goto brErrExit;
|
|
}
|
|
// we got a valid value, save the current location
|
|
GetCurrentDirectory(ARRAYSIZE(szStartDir), szStartDir);
|
|
|
|
fRet = FALSE;
|
|
|
|
//
|
|
// We have probably already gotten this cursor.
|
|
//
|
|
if (lstrcmpi(curi.szFile, sPtrBr.curi.szFile) == 0)
|
|
{
|
|
if (!sPtrBr.curi.hcur)
|
|
{
|
|
goto brErrExit;
|
|
}
|
|
|
|
curi = sPtrBr.curi;
|
|
|
|
//
|
|
// Clear this so it will not get destroyed in the cleanup code.
|
|
//
|
|
sPtrBr.curi.hcur = NULL;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The user must have typed in a name.
|
|
//
|
|
if (!GetCursorFromFile(&curi))
|
|
{
|
|
goto brErrExit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Convert mapped drive letters to UNC.
|
|
//
|
|
if (curi.szFile[1] == TEXT(':'))
|
|
{
|
|
TCHAR szDrive[3];
|
|
TCHAR szNet[MAX_PATH];
|
|
int lenNet = ARRAYSIZE(szNet);
|
|
|
|
StringCchCopy(szDrive, ARRAYSIZE(szDrive), curi.szFile);
|
|
|
|
if ((WNetGetConnection(szDrive, szNet, &lenNet) == NO_ERROR) &&
|
|
(szNet[0] == TEXT('\\')) &&
|
|
(szNet[1] == TEXT('\\')))
|
|
{
|
|
StringCchCat(szNet, ARRAYSIZE(szNet), curi.szFile + 2);
|
|
StringCchCopy(curi.szFile, ARRAYSIZE(curi.szFile), szNet);
|
|
}
|
|
}
|
|
|
|
i = (int)SendMessage(ghwndCursors, LB_GETCURSEL, 0, 0);
|
|
|
|
curi.fl |= CIF_MODIFIED;
|
|
|
|
SendMessage(GetParent(ghwndDlg), PSM_CHANGED, (WPARAM)ghwndDlg, 0L);
|
|
|
|
EnableWindow(GetDlgItem(ghwndDlg, ID_SAVESCHEME), TRUE);
|
|
|
|
//
|
|
// Destroy the old cursor before we retain the new one.
|
|
//
|
|
FreeItemCursor(acuri + i);
|
|
|
|
acuri[i] = curi;
|
|
|
|
UpdateCursorList();
|
|
|
|
fRet = TRUE;
|
|
|
|
brErrExit:
|
|
if (sPtrBr.curi.hcur)
|
|
{
|
|
DestroyCursor(sPtrBr.curi.hcur);
|
|
}
|
|
|
|
Error:
|
|
return (fRet);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CleanUpEverything
|
|
//
|
|
// Destroy all the outstanding cursors.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CleanUpEverything()
|
|
{
|
|
CURSOR_INFO *pcuri;
|
|
int i;
|
|
|
|
for (pcuri = &acuri[0], i = 0; i < CCURSORS; i++, pcuri++)
|
|
{
|
|
FreeItemCursor(pcuri);
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// UpdateCursorList
|
|
//
|
|
// Force the Cursor ListBox to repaint and the cursor information below the
|
|
// listbox to be refreshed as well.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
VOID UpdateCursorList()
|
|
{
|
|
int i = (int)SendMessage(ghwndCursors, LB_GETCURSEL, 0, 0);
|
|
PCURSOR_INFO pcuri = ((i >= 0) ? &acuri[i] : NULL);
|
|
HCURSOR hcur = pcuri ? pcuri->hcur : NULL;
|
|
HWND hDefaultButton = GetDlgItem(ghwndDlg, ID_DEFAULT);
|
|
BOOL fEnableDefaultButton = (pcuri && (pcuri->fl & CIF_FILE));
|
|
|
|
InvalidateRect(ghwndCursors, NULL, FALSE);
|
|
|
|
SendMessage(ghwndPreview, STM_SETICON, (WPARAM)hcur, 0L);
|
|
|
|
if (!fEnableDefaultButton && (GetFocus() == hDefaultButton))
|
|
{
|
|
SendMessage(ghwndDlg, WM_NEXTDLGCTL, (WPARAM)ghwndCursors, TRUE);
|
|
}
|
|
|
|
EnableWindow(hDefaultButton, fEnableDefaultButton);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// SaveSchemeAs
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL SaveSchemeAs()
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
|
|
//
|
|
// Dialog proc returns TRUE & sets gszSchemeName to filename entered
|
|
// on OK.
|
|
//
|
|
if (DialogBox( g_hInst,
|
|
MAKEINTRESOURCE(DLG_MOUSE_POINTER_SCHEMESAVE),
|
|
ghwndDlg,
|
|
SaveSchemeDlgProc ))
|
|
{
|
|
fSuccess = SaveScheme();
|
|
|
|
if (fSuccess)
|
|
{
|
|
int index = (int)SendMessage( ghwndSchemeCB,
|
|
CB_FINDSTRINGEXACT,
|
|
(WPARAM)-1,
|
|
(LPARAM)gszSchemeName );
|
|
//
|
|
// If not found, add it.
|
|
//
|
|
if (index < 0)
|
|
{
|
|
index = (int)SendMessage( ghwndSchemeCB,
|
|
CB_ADDSTRING,
|
|
0,
|
|
(LPARAM)gszSchemeName );
|
|
}
|
|
|
|
//
|
|
// Select the name.
|
|
//
|
|
SendMessage(ghwndSchemeCB, CB_SETCURSEL, (WPARAM) index, 0);
|
|
|
|
//
|
|
// Since this is now a user saved scheme, activate the delete
|
|
// button.
|
|
//
|
|
EnableWindow(GetDlgItem(ghwndDlg, ID_REMOVESCHEME), TRUE);
|
|
}
|
|
}
|
|
|
|
return (fSuccess);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// SubstituteString
|
|
//
|
|
// Replaces the string pszRemove with the string pszReplace in the
|
|
// string pszInput and places the output in pszResult. Only looks
|
|
// at the begining of the input string.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL SubstituteString(LPCTSTR pszInput, LPCTSTR pszRemove, LPCTSTR pszReplace, LPTSTR pszResult, UINT cchResult)
|
|
{
|
|
UINT cchInput = lstrlen(pszInput);
|
|
UINT cchRemove = lstrlen(pszRemove);
|
|
|
|
if (cchRemove <= cchInput)
|
|
{
|
|
if (CompareString(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE,
|
|
pszRemove, cchRemove, pszInput, cchRemove) == CSTR_EQUAL)
|
|
{
|
|
int cchReplace = lstrlen(pszReplace);
|
|
if ((cchInput - cchRemove) + cchReplace < cchResult)
|
|
{
|
|
StringCchCopy(pszResult, cchResult, pszReplace);
|
|
StringCchCat(pszResult, cchResult, pszInput + cchRemove);
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL UnExpandPath(LPTSTR pszPath, int cchPath)
|
|
{
|
|
static TCHAR szUserProfile[MAX_PATH];
|
|
static TCHAR szSystemRoot[MAX_PATH];
|
|
static TCHAR szProgramFiles[MAX_PATH];
|
|
static BOOL bInit = FALSE;
|
|
TCHAR szUnexpandedFilename[MAX_PATH];
|
|
|
|
if ( !bInit )
|
|
{
|
|
ExpandEnvironmentStrings( TEXT("%USERPROFILE%"), szUserProfile, ARRAYSIZE(szUserProfile) );
|
|
ExpandEnvironmentStrings( TEXT("%SYSTEMROOT%"), szSystemRoot, ARRAYSIZE(szSystemRoot) );
|
|
ExpandEnvironmentStrings( TEXT("%ProgramFiles%"), szProgramFiles, ARRAYSIZE(szProgramFiles) );
|
|
bInit = TRUE;
|
|
}
|
|
|
|
if (!SubstituteString(pszPath, szUserProfile, TEXT("%USERPROFILE%"), szUnexpandedFilename, ARRAYSIZE(szUnexpandedFilename)))
|
|
{
|
|
if (!SubstituteString(pszPath, szSystemRoot, TEXT("%SYSTEMROOT%"), szUnexpandedFilename, ARRAYSIZE(szUnexpandedFilename)))
|
|
{
|
|
if (!SubstituteString(pszPath, szProgramFiles, TEXT("%ProgramFiles%"), szUnexpandedFilename, ARRAYSIZE(szUnexpandedFilename)))
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
StringCchCopy(pszPath, cchPath, szUnexpandedFilename);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// SaveScheme
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL SaveScheme()
|
|
{
|
|
BOOL fSuccess = FALSE;
|
|
|
|
if (*gszSchemeName)
|
|
{
|
|
const BUFFER_SIZE = CCURSORS * (MAX_PATH + 1) + 1;
|
|
LPTSTR pszBuffer = (LPTSTR)LocalAlloc( LMEM_FIXED,
|
|
BUFFER_SIZE * sizeof(TCHAR) );
|
|
|
|
HKEY hk;
|
|
int i;
|
|
if (!pszBuffer)
|
|
{
|
|
return (FALSE);
|
|
}
|
|
|
|
pszBuffer[0] = TEXT('\0');
|
|
|
|
|
|
for (i = 0; i < CCURSORS; i++)
|
|
{
|
|
if (i)
|
|
{
|
|
StringCchCat(pszBuffer, BUFFER_SIZE, TEXT(","));
|
|
}
|
|
|
|
// Replace path with evnironment variables.
|
|
UnExpandPath(acuri[i].szFile, ARRAYSIZE(acuri[i].szFile));
|
|
|
|
StringCchCat(pszBuffer, BUFFER_SIZE, acuri[i].szFile);
|
|
}
|
|
|
|
if (RegCreateKeyEx( HKEY_CURRENT_USER, c_szRegPathCursors, 0, NULL, 0, KEY_CREATE_SUB_KEY, NULL, &hk, NULL) == ERROR_SUCCESS)
|
|
{
|
|
HKEY hks;
|
|
if (RegCreateKeyEx(hk, c_szSchemes, 0, NULL, 0, KEY_SET_VALUE | KEY_QUERY_VALUE, NULL, &hks, NULL) == ERROR_SUCCESS)
|
|
{
|
|
LPTSTR pszOldValue = (LPTSTR)LocalAlloc(LMEM_FIXED,
|
|
BUFFER_SIZE * sizeof(TCHAR));
|
|
if (NULL != pszOldValue)
|
|
{
|
|
DWORD dwType;
|
|
DWORD dwSize = BUFFER_SIZE*sizeof(TCHAR);
|
|
BOOL bSave = FALSE;
|
|
|
|
int ret = RegQueryValueEx(hks, gszSchemeName, NULL, &dwType, (LPBYTE)pszOldValue, &dwSize);
|
|
|
|
//
|
|
// If the key already exists, ask to confirm the overwrite.
|
|
//
|
|
if (ret == ERROR_SUCCESS && (dwType==REG_SZ || dwType==REG_EXPAND_SZ))
|
|
{
|
|
// only need to save if value is different from old value
|
|
if (lstrcmp(pszOldValue,pszBuffer)!=0)
|
|
{
|
|
TCHAR szTitle[OVERWRITE_TITLE];
|
|
TCHAR szMsg[OVERWRITE_MSG];
|
|
LoadString(g_hInst, IDS_OVERWRITE_TITLE, szTitle, OVERWRITE_TITLE);
|
|
LoadString(g_hInst, IDS_OVERWRITE_MSG, szMsg, OVERWRITE_MSG);
|
|
|
|
if (MessageBox( ghwndDlg,
|
|
szMsg,
|
|
szTitle,
|
|
MB_ICONQUESTION | MB_YESNO ) == IDYES)
|
|
{
|
|
//
|
|
// Overwrite confirmed. Safe to save.
|
|
//
|
|
bSave = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// no need to save since the new value is the same as the old value.
|
|
fSuccess = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The key doesn't exist, so it's safe to create it.
|
|
//
|
|
bSave = TRUE;
|
|
}
|
|
|
|
if (bSave)
|
|
{
|
|
if (RegSetValueEx(hks, gszSchemeName, 0, REG_EXPAND_SZ, (LPBYTE)pszBuffer, (lstrlen(pszBuffer) + 1) * sizeof(TCHAR)) == ERROR_SUCCESS)
|
|
{
|
|
fSuccess = TRUE;
|
|
}
|
|
}
|
|
LocalFree( pszOldValue );
|
|
}
|
|
|
|
RegCloseKey(hks);
|
|
}
|
|
RegCloseKey(hk);
|
|
}
|
|
LocalFree(pszBuffer);
|
|
}
|
|
return (fSuccess);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// SaveCurSchemeName
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void SaveCurSchemeName()
|
|
{
|
|
HKEY hk;
|
|
|
|
if (RegCreateKeyEx(HKEY_CURRENT_USER, c_szRegPathCursors, 0, NULL, 0, KEY_SET_VALUE, NULL, &hk, NULL) == ERROR_SUCCESS)
|
|
{
|
|
int index = (int)SendMessage(ghwndSchemeCB, CB_GETCURSEL, 0, 0L);
|
|
|
|
SendMessage(ghwndSchemeCB, CB_GETLBTEXT, (WPARAM)index, (LPARAM)gszSchemeName);
|
|
//
|
|
// Exclude the "none" pattern.
|
|
//
|
|
if (lstrcmpi(gszSchemeName, szNone) == 0)
|
|
{
|
|
*gszSchemeName = 0;
|
|
iSchemeLocation = ID_NONE_SCHEME;
|
|
}
|
|
else
|
|
{
|
|
iSchemeLocation = SystemOrUser(gszSchemeName);
|
|
}
|
|
|
|
RegSetValue(hk, NULL, REG_SZ, gszSchemeName, (lstrlen(gszSchemeName) + 1) * sizeof(TCHAR) );
|
|
|
|
RegSetValueEx(hk, szSchemeSource, 0, REG_DWORD, (unsigned char *)&iSchemeLocation, sizeof(iSchemeLocation));
|
|
|
|
RegCloseKey(hk);
|
|
|
|
if (iSchemeLocation == ID_USER_SCHEME)
|
|
{
|
|
SaveScheme();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// LoadScheme
|
|
//
|
|
// This is called whenever a selection is made from the schemes combo box.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL LoadScheme()
|
|
{
|
|
const BUFFER_SIZE = CCURSORS * (MAX_PATH + 1) + 1;
|
|
TCHAR pszSchemeName[MAX_SCHEME_SUFFIX + MAX_SCHEME_NAME_LEN + 1];
|
|
LPTSTR pszBuffer;
|
|
BOOL fSuccess = FALSE;
|
|
int index, ret;
|
|
HKEY hk;
|
|
|
|
//
|
|
// Allocate buffer for cursor paths.
|
|
//
|
|
pszBuffer = (LPTSTR)LocalAlloc(LMEM_FIXED, BUFFER_SIZE * sizeof(TCHAR));
|
|
if (pszBuffer == NULL)
|
|
{
|
|
return (FALSE);
|
|
}
|
|
|
|
HourGlass(TRUE);
|
|
|
|
*pszBuffer = *pszSchemeName = 0;
|
|
|
|
index = (int)SendMessage(ghwndSchemeCB, CB_GETCURSEL, 0, 0L);
|
|
|
|
//
|
|
// Get current scheme name.
|
|
//
|
|
SendMessage( ghwndSchemeCB,
|
|
CB_GETLBTEXT,
|
|
(WPARAM)index,
|
|
(LPARAM)pszSchemeName );
|
|
|
|
// Get the text for the item at index, compare to the previous value to see
|
|
// if it changed. We can't simply compare the previous index because new items
|
|
// get inserted into the list so the index can change and still be the same or
|
|
// can be different when nothing has changed.
|
|
if ( 0 == lstrcmp(gszPreviousScheme, pszSchemeName) )
|
|
{
|
|
LocalFree(pszBuffer);
|
|
// nothing to do, we're loading the already selected scheme
|
|
return FALSE;
|
|
}
|
|
|
|
// We're loading a different scheme, enable the apply button.
|
|
SendMessage(GetParent(ghwndDlg), PSM_CHANGED, (WPARAM)ghwndDlg, 0L);
|
|
StringCchCopy(gszPreviousScheme, ARRAYSIZE(gszPreviousScheme), pszSchemeName);
|
|
|
|
//
|
|
// Exclude the "none" pattern.
|
|
//
|
|
if (lstrcmpi(pszSchemeName, szNone) != 0)
|
|
{
|
|
//
|
|
// If we have an os scheme, then search for the scheme in HKLM,
|
|
// otherwise look in HKCU.
|
|
//
|
|
if ((((ret = SystemOrUser(pszSchemeName)) == ID_OS_SCHEME)
|
|
? (RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegPathSystemSchemes, 0, KEY_READ, &hk))
|
|
: (RegOpenKeyEx(HKEY_CURRENT_USER, c_szRegPathCursorSchemes, 0, KEY_READ, &hk)))
|
|
== ERROR_SUCCESS)
|
|
{
|
|
DWORD len = BUFFER_SIZE * sizeof(TCHAR);
|
|
|
|
if (RegQueryValueEx( hk,
|
|
pszSchemeName, 0, NULL,
|
|
(LPBYTE)pszBuffer,
|
|
&len ) == ERROR_SUCCESS)
|
|
{
|
|
fSuccess = TRUE; // can be reset to FALSE below
|
|
}
|
|
|
|
RegCloseKey(hk);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// "none" pattern is a valid choice.
|
|
//
|
|
ret = ID_NONE_SCHEME;
|
|
fSuccess = TRUE;
|
|
}
|
|
|
|
if (fSuccess)
|
|
{
|
|
LPTSTR pszNextFile, pszFile = pszBuffer;
|
|
BOOL fEOL = FALSE;
|
|
int i = 0;
|
|
|
|
//
|
|
// Remove an enclosing pair of double quotes from the list
|
|
// of cusor file names associated with the scheme.
|
|
//
|
|
// Why? On 3/29/00 someone changed the setup file accessor.inx
|
|
// placing double quotes around some of the cursor scheme reg values
|
|
// in HKLM. We'll fix the setup file but we should handle this
|
|
// case for all those who have already installed using that
|
|
// setup file.
|
|
//
|
|
if (TEXT('"') == *pszFile)
|
|
{
|
|
const LPTSTR pszLastChar = pszFile + lstrlen(pszFile) - 1;
|
|
if (TEXT('"') == *pszLastChar && pszLastChar > pszFile)
|
|
{
|
|
//
|
|
// Increment passed first dbl quote and truncate
|
|
// string before the last.
|
|
//
|
|
pszFile++;
|
|
*pszLastChar = TEXT('\0');
|
|
}
|
|
}
|
|
|
|
//
|
|
// Parse string of format TEXT("filename1, filename2, filename3...")
|
|
// into cursor info array.
|
|
//
|
|
do
|
|
{
|
|
while (*pszFile &&
|
|
(*pszFile == TEXT(' ') ||
|
|
*pszFile == TEXT('\t') ||
|
|
*pszFile == TEXT('\n')))
|
|
{
|
|
pszFile++;
|
|
}
|
|
|
|
pszNextFile = pszFile;
|
|
|
|
while (*pszNextFile != TEXT('\0'))
|
|
{
|
|
if (*pszNextFile == TEXT(','))
|
|
{
|
|
break;
|
|
}
|
|
|
|
pszNextFile = CharNext(pszNextFile);
|
|
}
|
|
|
|
if (*pszNextFile == TEXT('\0'))
|
|
{
|
|
fEOL = TRUE;
|
|
}
|
|
else
|
|
{
|
|
*pszNextFile = TEXT('\0');
|
|
}
|
|
|
|
if (lstrcmp(pszFile, acuri[i].szFile))
|
|
{
|
|
//
|
|
// It's different than current, update.
|
|
//
|
|
StringCchCopy(acuri[i].szFile, ARRAYSIZE(acuri[i].szFile), pszFile);
|
|
|
|
fSuccess &= SchemeUpdate(i);
|
|
}
|
|
|
|
pszFile = pszNextFile;
|
|
|
|
if (!fEOL)
|
|
{
|
|
pszFile++; // skip TEXT('\0') and move to next path
|
|
}
|
|
|
|
i++;
|
|
|
|
} while (i < CCURSORS);
|
|
}
|
|
|
|
LocalFree(pszBuffer);
|
|
|
|
UpdateCursorList();
|
|
|
|
EnableWindow(GetDlgItem(ghwndDlg, ID_REMOVESCHEME), (ret == ID_USER_SCHEME));
|
|
|
|
HourGlass(FALSE);
|
|
|
|
return (fSuccess);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// SchemeUpdate
|
|
//
|
|
// Updates the cursor at index i in acuri.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL SchemeUpdate(int i)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
|
|
if (acuri[i].hcur)
|
|
{
|
|
FreeItemCursor(acuri + i);
|
|
}
|
|
|
|
//
|
|
// If TEXT("Set Default").
|
|
//
|
|
if (*(acuri[i].szFile) == TEXT('\0'))
|
|
{
|
|
acuri[i].hcur =
|
|
(HCURSOR)LoadImage( NULL,
|
|
MAKEINTRESOURCE(gacd[i].idDefResource),
|
|
IMAGE_CURSOR,
|
|
0,
|
|
0,
|
|
LR_DEFAULTSIZE | LR_ENVSUBST );
|
|
acuri[i].fl = 0;
|
|
}
|
|
else
|
|
{
|
|
fSuccess = TryToLoadCursor(ghwndDlg, i, &acuri[i]);
|
|
}
|
|
|
|
acuri[i].fl |= CIF_MODIFIED;
|
|
|
|
return (fSuccess);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// RemoveScheme
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL RemoveScheme()
|
|
{
|
|
//
|
|
// Only user schemes can be removed, so this only needs to
|
|
// be MAX_SCHEME_NAME_LEN + 1 long.
|
|
//
|
|
TCHAR szSchemeName[MAX_SCHEME_NAME_LEN + 1];
|
|
int index;
|
|
HKEY hk;
|
|
|
|
index = (int)SendMessage(ghwndSchemeCB, CB_GETCURSEL, 0, 0L);
|
|
|
|
//
|
|
// Get current scheme name.
|
|
//
|
|
SendMessage( ghwndSchemeCB,
|
|
CB_GETLBTEXT,
|
|
(WPARAM)index,
|
|
(LPARAM)szSchemeName );
|
|
|
|
//
|
|
// Exclude the "none" pattern from removal.
|
|
//
|
|
if (lstrcmpi(szSchemeName, szNone) == 0)
|
|
{
|
|
return (FALSE);
|
|
}
|
|
|
|
//
|
|
// HACK: assume deleting noname needs no confirmation -
|
|
// this is because the scheme won't save properly anyway.
|
|
//
|
|
if (*szSchemeName)
|
|
{
|
|
TCHAR RemoveMsg[MAX_PATH];
|
|
TCHAR DialogMsg[MAX_PATH];
|
|
|
|
LoadString(g_hInst, IDS_REMOVESCHEME, RemoveMsg, MAX_PATH);
|
|
|
|
StringCchPrintf(DialogMsg, ARRAYSIZE(DialogMsg), RemoveMsg, (LPTSTR)szSchemeName);
|
|
|
|
LoadString(g_hInst, IDS_NAME, RemoveMsg, MAX_PATH);
|
|
|
|
if (MessageBox( ghwndDlg,
|
|
DialogMsg,
|
|
RemoveMsg,
|
|
MB_ICONQUESTION | MB_YESNO ) != IDYES)
|
|
{
|
|
return (TRUE);
|
|
}
|
|
}
|
|
|
|
if (RegOpenKeyEx(HKEY_CURRENT_USER, c_szRegPathCursors, 0, KEY_WRITE, &hk) == ERROR_SUCCESS)
|
|
{
|
|
HKEY hks;
|
|
|
|
if (RegOpenKeyEx(hk, c_szSchemes, 0, KEY_WRITE, &hks) == ERROR_SUCCESS)
|
|
{
|
|
RegDeleteValue(hks, szSchemeName);
|
|
RegCloseKey(hks);
|
|
}
|
|
|
|
RegCloseKey(hk);
|
|
}
|
|
|
|
//
|
|
// Delete from list box.
|
|
//
|
|
index = (int)SendMessage( ghwndSchemeCB,
|
|
CB_FINDSTRINGEXACT,
|
|
(WPARAM)-1,
|
|
(LPARAM)szSchemeName );
|
|
|
|
SendMessage(ghwndSchemeCB, CB_DELETESTRING, (WPARAM)index, 0);
|
|
|
|
SendMessage(ghwndSchemeCB, CB_SETCURSEL, 0, 0);
|
|
SendMessage(ghwndDlg, WM_NEXTDLGCTL, 1, 0L);
|
|
|
|
EnableWindow(GetDlgItem(ghwndDlg, ID_REMOVESCHEME), FALSE);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// InitSchemeComboBox
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL InitSchemeComboBox()
|
|
{
|
|
TCHAR szSchemeName[MAX_SCHEME_NAME_LEN + 1];
|
|
TCHAR szDefaultSchemeName[MAX_SCHEME_NAME_LEN + 1];
|
|
TCHAR szLongName[MAX_SCHEME_SUFFIX + MAX_SCHEME_NAME_LEN + 1];
|
|
int index;
|
|
HKEY hk;
|
|
DWORD len;
|
|
|
|
LoadString(g_hInst, IDS_NONE, szNone, ARRAYSIZE(szNone));
|
|
LoadString(g_hInst, IDS_SUFFIX, szSystemScheme, ARRAYSIZE(szSystemScheme));
|
|
|
|
if (RegOpenKeyEx(HKEY_CURRENT_USER, c_szRegPathCursors, 0, KEY_READ, &hk) == ERROR_SUCCESS)
|
|
{
|
|
HKEY hks;
|
|
|
|
//
|
|
// Enumerate the schemes.
|
|
//
|
|
if (RegOpenKeyEx(hk, c_szSchemes, 0, KEY_READ, &hks) == ERROR_SUCCESS)
|
|
{
|
|
DWORD i;
|
|
|
|
for (i = 0; ;i++)
|
|
{
|
|
LONG ret;
|
|
|
|
//
|
|
// Reset each pass.
|
|
//
|
|
len = ARRAYSIZE(szSchemeName);
|
|
|
|
ret = RegEnumValue( hks,
|
|
i,
|
|
szSchemeName,
|
|
&len,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL );
|
|
|
|
if (ret == ERROR_MORE_DATA)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (ret != ERROR_SUCCESS)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// HACK to keep "NONE" pure.
|
|
//
|
|
if (lstrcmpi(szSchemeName, szNone) != 0)
|
|
{
|
|
SendMessage( ghwndSchemeCB,
|
|
CB_ADDSTRING,
|
|
0,
|
|
(LPARAM)szSchemeName );
|
|
}
|
|
}
|
|
|
|
//
|
|
// At this point, all of the user defined scheme names have been
|
|
// added to the combo box.
|
|
//
|
|
RegCloseKey(hks);
|
|
}
|
|
|
|
//
|
|
// Get name of current one.
|
|
//
|
|
// Reset again.
|
|
//
|
|
len = sizeof(szDefaultSchemeName);
|
|
|
|
RegQueryValue(hk, NULL, szDefaultSchemeName, &len);
|
|
|
|
//
|
|
// Try to read the value of Scheme Source. If this value doesn't
|
|
// exist, then we have a pre NT 5.0 implementation, so all schemes
|
|
// will be user schemes.
|
|
//
|
|
len = sizeof(iSchemeLocation);
|
|
if (RegQueryValueEx( hk,
|
|
szSchemeSource,
|
|
NULL,
|
|
NULL,
|
|
(unsigned char *)&iSchemeLocation,
|
|
&len ) != ERROR_SUCCESS)
|
|
{
|
|
iSchemeLocation = ID_USER_SCHEME;
|
|
}
|
|
|
|
RegCloseKey(hk);
|
|
}
|
|
|
|
//
|
|
// Now add the system defined pointer schemes.
|
|
//
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegPathSystemSchemes, 0, KEY_READ, &hk) == ERROR_SUCCESS)
|
|
{
|
|
DWORD i;
|
|
|
|
for (i = 0; ;i++)
|
|
{
|
|
LONG ret;
|
|
|
|
//
|
|
// Reset each pass.
|
|
//
|
|
len = ARRAYSIZE(szSchemeName);
|
|
|
|
ret = RegEnumValue( hk,
|
|
i,
|
|
szSchemeName,
|
|
&len,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL );
|
|
|
|
//
|
|
// If the Scheme name is longer than the allowed length, skip it.
|
|
//
|
|
if (ret == ERROR_MORE_DATA)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// If there's an error, then we're done.
|
|
//
|
|
if (ret != ERROR_SUCCESS)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// When we add the system identifier to the string, it could be
|
|
// longer than MAX_SCHEME_NAME, however we only want to read
|
|
// max length from the registry.
|
|
//
|
|
StringCchCopy(szLongName, ARRAYSIZE(szLongName), szSchemeName);
|
|
StringCchCat(szLongName, ARRAYSIZE(szLongName), szSystemScheme);
|
|
SendMessage(ghwndSchemeCB, CB_ADDSTRING, 0, (LPARAM)szLongName);
|
|
}
|
|
|
|
RegCloseKey(hk);
|
|
}
|
|
|
|
//
|
|
// Add the "none" scheme.
|
|
//
|
|
SendMessage(ghwndSchemeCB, CB_INSERTSTRING, 0, (LPARAM)szNone);
|
|
|
|
//
|
|
// Try to find current one in the combobox.
|
|
//
|
|
StringCchCopy(szLongName, ARRAYSIZE(szLongName), szDefaultSchemeName);
|
|
if (iSchemeLocation == ID_OS_SCHEME)
|
|
{
|
|
StringCchCat(szLongName, ARRAYSIZE(szLongName), szSystemScheme);
|
|
}
|
|
index = (int)SendMessage( ghwndSchemeCB,
|
|
CB_FINDSTRINGEXACT,
|
|
0xFFFF,
|
|
(LPARAM)szLongName );
|
|
|
|
//
|
|
// If found, select it.
|
|
//
|
|
if (index < 0) // if we are on the None scheme
|
|
{
|
|
iSchemeLocation = ID_NONE_SCHEME;
|
|
index = 0;
|
|
}
|
|
|
|
// We keep around a selection indicator so we know when selection has changed.
|
|
// Initialize that value here.
|
|
StringCchCopy(gszPreviousScheme, ARRAYSIZE(gszPreviousScheme), szLongName);
|
|
|
|
SendMessage(ghwndSchemeCB, CB_SETCURSEL, (WPARAM)index, 0);
|
|
|
|
EnableWindow( GetDlgItem(ghwndDlg, ID_REMOVESCHEME),
|
|
(iSchemeLocation == ID_USER_SCHEME) );
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// SaveSchemeDlgProc
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
INT_PTR CALLBACK SaveSchemeDlgProc(
|
|
HWND hWnd,
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
TCHAR szSchemeName[MAX_SCHEME_SUFFIX + MAX_SCHEME_NAME_LEN + 1];
|
|
|
|
switch (message)
|
|
{
|
|
case ( WM_INITDIALOG ) :
|
|
{
|
|
HourGlass(TRUE);
|
|
|
|
GetWindowText(ghwndSchemeCB, szSchemeName, ARRAYSIZE(szSchemeName));
|
|
|
|
//
|
|
// CANNOT SAVE "NONE" SCHEME.
|
|
//
|
|
if (lstrcmpi(szSchemeName, szNone) == 0)
|
|
{
|
|
*szSchemeName = 0;
|
|
}
|
|
|
|
iSchemeLocation = SystemOrUser(szSchemeName);
|
|
|
|
SetDlgItemText(hWnd, ID_SCHEMEFILENAME, szSchemeName);
|
|
|
|
SendDlgItemMessage(hWnd, ID_SCHEMEFILENAME, EM_SETSEL, 0, 32767);
|
|
|
|
SendDlgItemMessage( hWnd,
|
|
ID_SCHEMEFILENAME,
|
|
EM_LIMITTEXT,
|
|
MAX_SCHEME_NAME_LEN,
|
|
0L );
|
|
|
|
EnableWindow(GetDlgItem(hWnd, IDOK), szSchemeName[0] != TEXT('\0'));
|
|
|
|
HourGlass(FALSE);
|
|
return (TRUE);
|
|
}
|
|
case ( WM_HELP ) :
|
|
{
|
|
WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle,
|
|
HELP_FILE,
|
|
HELP_WM_HELP,
|
|
(DWORD_PTR)(LPTSTR)aHelpIDs );
|
|
return (TRUE);
|
|
}
|
|
case ( WM_CONTEXTMENU ) :
|
|
{
|
|
WinHelp( (HWND)wParam,
|
|
HELP_FILE,
|
|
HELP_CONTEXTMENU,
|
|
(DWORD_PTR)(LPVOID)aHelpIDs );
|
|
return (TRUE);
|
|
}
|
|
case ( WM_COMMAND ) :
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case ( ID_SCHEMEFILENAME ) :
|
|
{
|
|
if (HIWORD(wParam) == EN_CHANGE)
|
|
{
|
|
//
|
|
// CANNOT SAVE "NONE" SCHEME
|
|
// cannot save a scheme ending with szSystemScheme
|
|
//
|
|
EnableWindow(
|
|
GetDlgItem(hWnd, IDOK),
|
|
((GetDlgItemText( hWnd,
|
|
ID_SCHEMEFILENAME,
|
|
szSchemeName,
|
|
ARRAYSIZE(szSchemeName) ) > 0) &&
|
|
(lstrcmpi(szSchemeName, szNone) != 0) &&
|
|
(SystemOrUser(szSchemeName) != ID_OS_SCHEME)) );
|
|
}
|
|
break;
|
|
}
|
|
case ( IDOK ) :
|
|
{
|
|
GetDlgItemText( hWnd,
|
|
ID_SCHEMEFILENAME,
|
|
szSchemeName,
|
|
MAX_SCHEME_NAME_LEN + 1 );
|
|
|
|
CurStripBlanks(szSchemeName, ARRAYSIZE(szSchemeName));
|
|
|
|
if (*szSchemeName == TEXT('\0'))
|
|
{
|
|
MessageBeep(0);
|
|
break;
|
|
}
|
|
|
|
StringCchCopy(gszSchemeName, ARRAYSIZE(gszSchemeName), szSchemeName);
|
|
|
|
// fall through...
|
|
}
|
|
case ( IDCANCEL ) :
|
|
{
|
|
EndDialog(hWnd, LOWORD(wParam) == IDOK);
|
|
return (TRUE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Didn't process a message.
|
|
//
|
|
return (FALSE);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MakeFilename
|
|
//
|
|
// Returns Filename with a default path in system directory if no path
|
|
// is already specified.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
LPTSTR MakeFilename(
|
|
LPTSTR sz)
|
|
{
|
|
TCHAR szTemp[MAX_PATH];
|
|
|
|
ExpandEnvironmentStrings(sz, szTemp, MAX_PATH);
|
|
|
|
if (szTemp[0] == TEXT('\\') || szTemp[1] == TEXT(':'))
|
|
{
|
|
StringCchCopy(gszFileName2, ARRAYSIZE(gszFileName2), szTemp);
|
|
|
|
return (gszFileName2);
|
|
}
|
|
else
|
|
{
|
|
GetSystemDirectory(gszFileName2, ARRAYSIZE(gszFileName2));
|
|
|
|
StringCchCat(gszFileName2, ARRAYSIZE(gszFileName2), TEXT("\\"));
|
|
StringCchCat(gszFileName2, ARRAYSIZE(gszFileName2), szTemp);
|
|
|
|
return (gszFileName2);
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CurStripBlanks
|
|
//
|
|
// Strips leading and trailing blanks from a string.
|
|
// Alters the memory where the string sits.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CurStripBlanks(LPTSTR pszString, int cchString)
|
|
{
|
|
LPTSTR pszPosn;
|
|
|
|
//
|
|
// Strip leading blanks.
|
|
//
|
|
pszPosn = pszString;
|
|
|
|
while (*pszPosn == TEXT(' '))
|
|
{
|
|
pszPosn++;
|
|
}
|
|
|
|
if (pszPosn != pszString)
|
|
{
|
|
WCHAR szEdit[MAX_PATH];
|
|
StringCchCopy(szEdit, ARRAYSIZE(szEdit), pszPosn);
|
|
StringCchCopy(pszString, cchString, szEdit);
|
|
}
|
|
|
|
//
|
|
// Strip trailing blanks.
|
|
//
|
|
if ((pszPosn = pszString + lstrlen(pszString)) != pszString)
|
|
{
|
|
pszPosn = CharPrev(pszString, pszPosn);
|
|
|
|
while (*pszPosn == TEXT(' '))
|
|
{
|
|
pszPosn = CharPrev(pszString, pszPosn);
|
|
}
|
|
|
|
pszPosn = CharNext(pszPosn);
|
|
|
|
*pszPosn = TEXT('\0');
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// SystemOrUser
|
|
//
|
|
// Attempts to determine if the scheme name selected from the combo
|
|
// box ends with the string szSystemScheme and retuns ID_OS_SCHEME
|
|
// if it does, ID_USER_SCHEME if it doesn't.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
int SystemOrUser(TCHAR *pszSchemeName)
|
|
{
|
|
TCHAR *pszSN;
|
|
int lenSS, lenSN;
|
|
int i;
|
|
|
|
lenSS = lstrlen(szSystemScheme);
|
|
lenSN = lstrlen(pszSchemeName);
|
|
|
|
if (lenSN <= lenSS)
|
|
{
|
|
return (ID_USER_SCHEME);
|
|
}
|
|
|
|
pszSN = pszSchemeName + (lenSN - lenSS);
|
|
|
|
//
|
|
// If these strings are different, it's a user scheme.
|
|
//
|
|
if (lstrcmpi(pszSN, szSystemScheme))
|
|
{
|
|
return (ID_USER_SCHEME);
|
|
}
|
|
|
|
//
|
|
// For system schemes, this function also removes the
|
|
// szSystemScheme string from the end.
|
|
//
|
|
*pszSN = TEXT('\0');
|
|
|
|
return (ID_OS_SCHEME);
|
|
}
|