mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2551 lines
84 KiB
2551 lines
84 KiB
/* ETCDLG.C
|
|
Resident Code Segment // Tweak: make non-resident?
|
|
|
|
Routines for Pointers/Sounds/Etc preview dialog
|
|
|
|
Frosting: Master Theme Selector for Windows '95
|
|
Copyright (c) 1994-1999 Microsoft Corporation. All rights reserved.
|
|
*/
|
|
|
|
// ---------------------------------------------
|
|
// Brief file history:
|
|
// Alpha:
|
|
// Beta:
|
|
// Bug fixes
|
|
// ---------
|
|
//
|
|
// ---------------------------------------------
|
|
|
|
#define OEMRESOURCE 1 // for OBM_*
|
|
#include "windows.h"
|
|
#include "frost.h"
|
|
#include "global.h"
|
|
#include "prsht.h"
|
|
#include "commdlg.h"
|
|
#include "stdlib.h"
|
|
|
|
#include "mmsystem.h"
|
|
#include "..\inc\addon.h"
|
|
#include "loadimag.h"
|
|
#include "adutil.h"
|
|
#include "schedule.h" // IsPlatformNT()
|
|
|
|
// Local Routines
|
|
BOOL EtcInit(void );
|
|
void EtcDestroy(void );
|
|
INT_PTR FAR PASCAL PtrsPageProc(HWND, UINT, WPARAM, LPARAM);
|
|
INT_PTR FAR PASCAL SndsPageProc(HWND, UINT, WPARAM, LPARAM);
|
|
INT_PTR FAR PASCAL PicsPageProc(HWND, UINT, WPARAM, LPARAM);
|
|
void CreateDataStr(LPTSTR, LPTSTR, LPTSTR);
|
|
void GetFileStr(LPTSTR, LPTSTR);
|
|
void GetDisplayStr(LPTSTR, LPTSTR);
|
|
HBITMAP PASCAL GetSoundBitmap(LPTSTR lpszFile);
|
|
HANDLE PASCAL GetRiffAll(HMMIO hmmio, LPTSTR szText, int iLen);
|
|
void PASCAL SetDlgItemFile(HWND, UINT, LPCTSTR);
|
|
|
|
// stuff from DIB.C
|
|
HPALETTE WINAPI bmfCreateDIBPalette(HANDLE);
|
|
HBITMAP WINAPI bmfBitmapFromDIB(HANDLE, HPALETTE);
|
|
HPALETTE CreateBIPalette (LPBITMAPINFOHEADER);
|
|
DWORD WINAPI bmfDIBSize(HANDLE);
|
|
WORD PaletteSize (VOID FAR *pv);
|
|
WORD NumDIBColors (VOID FAR * pv);
|
|
|
|
// globals
|
|
HBITMAP hbmpCheck, hbmpQ;
|
|
BITMAP bmCheck, bmQ;
|
|
int iItemHeight; // height of listbox items
|
|
int xTextOffset; // leave room for checkmark when drawing text
|
|
RECT rPreview; // area of preview image
|
|
HCURSOR hCurCursor = NULL;
|
|
HBITMAP hbmpCurSnd = NULL;
|
|
HANDLE hCurImage = NULL; // icon or bitmap
|
|
|
|
TCHAR szCurPreviewFile[MAX_PATHLEN+1];
|
|
|
|
#define bThemed (*szCurThemeFile)
|
|
|
|
typedef struct {
|
|
int idStr; // resource id of display string
|
|
int indexF; // index into approp FROST_* struct
|
|
} STR_TO_KEY;
|
|
|
|
|
|
// stuff from DIB.C
|
|
#define PALVERSION 0x300
|
|
#define MAXPALETTE 256 /* max. # supported palette entries */
|
|
#define WIDTHBYTES(i) (((i)+31)/32*4)
|
|
|
|
//
|
|
// These arrays match the resource string ids of the strings displayed in
|
|
// the listboxes to the index into the appropriate FROST_* array -- to find
|
|
// the theme-file key needed to retrieve the filename of the associated
|
|
// cursor/icon/bitmap.
|
|
//
|
|
|
|
|
|
//
|
|
// WARNING: keep indices current with any changes in fvCursors[] in keys.h!
|
|
//
|
|
// THIS ARRAY SHOWS THE ORDER THAT THE ITEMS APPEAR IN THE LISTBOX!
|
|
STR_TO_KEY stkCursors[] = {
|
|
{STR_CUR_ARROW, 0 },
|
|
{STR_CUR_HELP, 1 },
|
|
{STR_CUR_APPSTART, 2 },
|
|
{STR_CUR_WAIT, 3 },
|
|
{STR_CUR_CROSSHAIR, 8 },
|
|
{STR_CUR_IBEAM, 9 },
|
|
{STR_CUR_NWPEN, 4 },
|
|
{STR_CUR_NO, 5 },
|
|
{STR_CUR_SIZENS, 6 },
|
|
{STR_CUR_SIZEWE, 7 },
|
|
{STR_CUR_SIZENWSE, 10 },
|
|
{STR_CUR_SIZENESW, 11 },
|
|
{STR_CUR_SIZEALL, 12 },
|
|
{STR_CUR_UPARROW, 13 }
|
|
};
|
|
|
|
//
|
|
// WARNING: keep indices current with any changes in fsCurUser[] in keys.h!
|
|
//
|
|
// This listbox has its items sorted. Currently.
|
|
STR_TO_KEY stkSounds[] = {
|
|
{STR_SND_DEF, 2 },
|
|
{STR_SND_GPF, 3 },
|
|
{STR_SND_MAX, 4 },
|
|
{STR_SND_MENUCMD, 5 },
|
|
{STR_SND_MENUPOP, 6 },
|
|
{STR_SND_MIN, 7 },
|
|
{STR_SND_OPEN, 8 },
|
|
{STR_SND_CLOSE, 9 },
|
|
{STR_SND_MAILBEEP, 10 },
|
|
{STR_SND_RESTDOWN, 11 },
|
|
{STR_SND_RESTUP, 12 },
|
|
{STR_SND_RINGIN, 13 },
|
|
{STR_SND_RINGOUT, 14 },
|
|
{STR_SND_SYSASTER, 15 },
|
|
{STR_SND_SYSDEF, 16 },
|
|
{STR_SND_SYSEXCL, 17 },
|
|
{STR_SND_SYSEXIT, 18 },
|
|
{STR_SND_SYSHAND, 19 },
|
|
{STR_SND_SYSQUEST, 20 },
|
|
{STR_SND_SYSSTART, 21 },
|
|
{STR_SND_TOSSTRASH, 22 }
|
|
};
|
|
|
|
// WARNING: keep current with any changes in number of items in visuals dlg
|
|
#define SCRSAV_NDX 6 // zero-based
|
|
|
|
// max number of items is in the sound listbox
|
|
#define MAX_ETC_ITEMS (sizeof(stkSounds)/sizeof(STR_TO_KEY))
|
|
|
|
// this array is init'd with the listbox init to keep track of
|
|
// which files actually exist
|
|
BOOL bCursorExists[MAX_ETC_ITEMS+1];
|
|
BOOL bSoundExists[MAX_ETC_ITEMS+1];
|
|
BOOL bVisualExists[MAX_ETC_ITEMS+1];
|
|
|
|
|
|
//
|
|
// HELP CONTEXT ID to CONTROL ID pairings for context help
|
|
//
|
|
|
|
POPUP_HELP_ARRAY phaPtrsDlg[] = {
|
|
{ (DWORD)LB_PTRS , (DWORD)IDH_THEME_POINTERS_LIST},
|
|
{ (DWORD)RECT_PREVIEW , (DWORD)IDH_THEME_POINTERS_PREV},
|
|
{ (DWORD)TXT_FILENAME , (DWORD)IDH_THEME_POINTERS_FILE},
|
|
{ (DWORD)0, (DWORD)0 } // double-null terminator
|
|
};
|
|
POPUP_HELP_ARRAY phaSndsDlg[] = {
|
|
{ (DWORD)LB_SNDS , (DWORD)IDH_THEME_SOUNDS_LIST},
|
|
{ (DWORD)RECT_PREVIEW , (DWORD)IDH_THEME_SOUNDS_ICON_PREV},
|
|
{ (DWORD)PB_PLAY , (DWORD)IDH_THEME_SOUNDS_PLAYS},
|
|
{ (DWORD)TXT_FILENAME , (DWORD)IDH_THEME_SOUNDS_FILE},
|
|
{ (DWORD)0, (DWORD)0 } // double-null terminator
|
|
};
|
|
POPUP_HELP_ARRAY phaPicsDlg[] = {
|
|
{ (DWORD)LB_PICS , (DWORD)IDH_THEME_PICS_LIST},
|
|
{ (DWORD)RECT_PREVIEW , (DWORD)IDH_THEME_PICS_PREV},
|
|
{ (DWORD)TXT_FILENAME , (DWORD)IDH_THEME_PICS_FILE},
|
|
{ (DWORD)0, (DWORD)0 } // double-null terminator
|
|
};
|
|
|
|
|
|
//
|
|
// DoEtcDlgs
|
|
//
|
|
// Sets up the property sheet for Pointers, Sounds, Pictures.
|
|
//
|
|
// Returns: BOOL success of setup.
|
|
//
|
|
|
|
INT_PTR FAR DoEtcDlgs(HWND hParent)
|
|
{
|
|
PROPSHEETPAGE psp[3];
|
|
PROPSHEETHEADER psh;
|
|
INT_PTR iret;
|
|
|
|
//
|
|
// Set up each of the three pages
|
|
|
|
ZeroMemory(psp, sizeof(psp));
|
|
psp[0].dwSize = sizeof(PROPSHEETPAGE);
|
|
psp[0].dwFlags = PSP_USETITLE;
|
|
psp[0].hInstance = hInstApp;
|
|
psp[0].pszTemplate = MAKEINTRESOURCE(DLGPROP_PTRS);
|
|
psp[0].pszIcon = (LPCTSTR)NULL;
|
|
psp[0].pszTitle = MAKEINTRESOURCE(STR_TITLE_PTRS);
|
|
psp[0].pfnDlgProc = PtrsPageProc;
|
|
psp[0].lParam = (LPARAM)0;
|
|
psp[0].pfnCallback = (LPFNPSPCALLBACK)0;
|
|
psp[0].pcRefParent = (UINT FAR *)0;
|
|
|
|
|
|
psp[1].dwSize = sizeof(PROPSHEETPAGE);
|
|
psp[1].dwFlags = PSP_USETITLE;
|
|
psp[1].hInstance = hInstApp;
|
|
psp[1].pszTemplate = MAKEINTRESOURCE(DLGPROP_SNDS);
|
|
psp[1].pszIcon = (LPCTSTR)NULL;
|
|
psp[1].pszTitle = MAKEINTRESOURCE(STR_TITLE_SNDS);
|
|
psp[1].pfnDlgProc = SndsPageProc;
|
|
psp[1].lParam = (LPARAM)0;
|
|
psp[1].pfnCallback = (LPFNPSPCALLBACK)0;
|
|
psp[1].pcRefParent = (UINT FAR *)0;
|
|
|
|
psp[2].dwSize = sizeof(PROPSHEETPAGE);
|
|
psp[2].dwFlags = PSP_USETITLE;
|
|
psp[2].hInstance = hInstApp;
|
|
psp[2].pszTemplate = MAKEINTRESOURCE(DLGPROP_PICS);
|
|
psp[2].pszIcon = (LPCTSTR)NULL;
|
|
psp[2].pszTitle = MAKEINTRESOURCE(STR_TITLE_PICS);
|
|
psp[2].pfnDlgProc = PicsPageProc;
|
|
psp[2].lParam = (LPARAM)0;
|
|
psp[2].pfnCallback = (LPFNPSPCALLBACK)0;
|
|
psp[2].pcRefParent = (UINT FAR *)0;
|
|
|
|
|
|
//
|
|
// set up the property sheet info header
|
|
|
|
psh.dwSize = sizeof(PROPSHEETHEADER);
|
|
psh.dwFlags = PSH_PROPSHEETPAGE | PSH_NOAPPLYNOW;
|
|
psh.hwndParent = hParent;
|
|
psh.hInstance = hInstApp;
|
|
psh.pszIcon = NULL;
|
|
psh.pszCaption = MAKEINTRESOURCE(STR_TITLE_ETC);
|
|
psh.nPages = sizeof(psp)/sizeof(PROPSHEETPAGE);
|
|
psh.nStartPage = 0;
|
|
psh.ppsp = (LPCPROPSHEETPAGE) &psp;
|
|
|
|
//
|
|
// object, etc init
|
|
if (!EtcInit())
|
|
return (FALSE); // couldn't initalize things EXIT
|
|
|
|
//
|
|
// create the property sheet and cleanup
|
|
iret = PropertySheet( (LPCPROPSHEETHEADER) &psh);
|
|
|
|
//
|
|
// object, etc cleanup
|
|
EtcDestroy();
|
|
|
|
return (iret >= 0); // TRUE if successful
|
|
}
|
|
|
|
|
|
//
|
|
// EtcInit/Destroy
|
|
//
|
|
// Init/Destroy things used in common by all three dialogs.
|
|
//
|
|
// Destroy returns: success
|
|
//
|
|
BOOL EtcInit(void)
|
|
{
|
|
BOOL bret = TRUE;
|
|
|
|
// owner-draw listboxes' checkmark and question mark
|
|
hbmpCheck = LoadBitmap(NULL, MAKEINTRESOURCE(OBM_CHECK));
|
|
hbmpQ = LoadBitmap(hInstApp, MAKEINTRESOURCE(BMP_QUESTION));
|
|
|
|
if (hbmpCheck && hbmpQ) {
|
|
// keep specs on bitmap
|
|
GetObject(hbmpCheck, sizeof(BITMAP), (LPVOID)(LPBITMAP)&bmCheck);
|
|
GetObject(hbmpQ, sizeof(BITMAP), (LPVOID)(LPBITMAP)&bmQ);
|
|
}
|
|
else
|
|
bret = FALSE;
|
|
|
|
// cleanup
|
|
return (bret);
|
|
}
|
|
|
|
void EtcDestroy(void)
|
|
{
|
|
if (hbmpCheck) DeleteObject(hbmpCheck);
|
|
hbmpCheck = NULL;
|
|
|
|
if (hbmpQ) DeleteObject(hbmpQ);
|
|
hbmpQ = NULL;
|
|
|
|
if (hCurCursor) DestroyCursor(hCurCursor);
|
|
hCurCursor = NULL;
|
|
|
|
if (hbmpCurSnd) DeleteObject(hbmpCurSnd);
|
|
hbmpCurSnd = NULL;
|
|
|
|
if (hCurImage) DestroyCursor(hCurImage);
|
|
hCurImage = NULL;
|
|
}
|
|
|
|
|
|
//
|
|
// *PageProc
|
|
//
|
|
// Property sheet page procedures for the Etc preview sheet.
|
|
//
|
|
|
|
TCHAR szCursors[] = TEXT("Control Panel\\Cursors");
|
|
|
|
INT_PTR FAR PASCAL PtrsPageProc(hDlg, message, wParam, lParam)
|
|
HWND hDlg;
|
|
UINT message;
|
|
WPARAM wParam;
|
|
LPARAM lParam;
|
|
{
|
|
switch (message) {
|
|
|
|
// set up listbox, initial selection, etc.
|
|
case WM_INITDIALOG:
|
|
{ // var scope
|
|
int iter;
|
|
extern FROST_VALUE fvCursors[]; // for theme file keys
|
|
HWND hText, hLBox;
|
|
RECT rText;
|
|
TCHAR szDispStr[MAX_STRLEN+1];
|
|
|
|
// just in first of these dialogs, need to init page OK to disabled
|
|
EnableWindow(GetDlgItem(GetParent(hDlg), IDCANCEL), FALSE);
|
|
SendMessage(GetParent(hDlg), PSM_CANCELTOCLOSE, (WPARAM)0, (LPARAM)0);
|
|
|
|
// just in first of these dialogs, need to init dialog title
|
|
LoadString(hInstApp, STR_PREVIEWDLG, (LPTSTR)szMsg, MAX_MSGLEN);
|
|
lstrcat((LPTSTR)szMsg,
|
|
bThemed ? FileFromPath((LPTSTR)szCurThemeFile)
|
|
: szCurSettings
|
|
);
|
|
|
|
TruncateExt((LPTSTR)szMsg);
|
|
SetWindowText(GetParent(hDlg), (LPTSTR)szMsg);
|
|
|
|
//
|
|
// get metrics for drawitem size
|
|
hText = GetDlgItem(hDlg, TXT_FILENAME); // 12 dialog box units high
|
|
GetWindowRect(hText, (LPRECT)&rText);
|
|
iItemHeight = ((rText.bottom - rText.top) * 8) / 12; // dialog font height
|
|
xTextOffset = (iItemHeight * 3) / 2; // proportional spacing
|
|
Assert(iItemHeight > 0, TEXT("didn't get positive text height for preview listbox!\n"));
|
|
|
|
#if 0 // this is when we painted the cursor by ourself
|
|
// other metrics, etc.
|
|
xCursor = GetSystemMetrics(SM_CXCURSOR);
|
|
yCursor = GetSystemMetrics(SM_CYCURSOR);
|
|
//
|
|
// save away preview rect area
|
|
GetWindowRect(GetDlgItem(hDlg, RECT_PREVIEW), (LPRECT)&rPreview);
|
|
GetWindowRect(hDlg, (LPRECT)&rText);
|
|
OffsetRect((LPRECT)&rPreview, -rText.left, -rText.top);
|
|
DestroyWindow(GetDlgItem(hDlg, RECT_PREVIEW));
|
|
#endif
|
|
|
|
//
|
|
// init the listbox with combined strings
|
|
|
|
// init
|
|
hLBox = GetDlgItem(hDlg, LB_PTRS);
|
|
Assert (sizeof(stkCursors)/sizeof(STR_TO_KEY) == NUM_CURSORS,
|
|
TEXT("size mismatch stkCursors and NUM_CURSORS\n"));
|
|
|
|
// for each cursor
|
|
for (iter = 0; iter < NUM_CURSORS; iter++) {
|
|
// get display string
|
|
LoadString(hInstApp, stkCursors[iter].idStr,
|
|
(LPTSTR)szDispStr, MAX_STRLEN);
|
|
// CPLs don't check for success on LoadString in INITDIALOG, so OK!?
|
|
// get filename if any
|
|
if (bThemed) {
|
|
GetPrivateProfileString((LPTSTR)szCursors,
|
|
(LPTSTR)( fvCursors[stkCursors[iter].indexF].szValName ),
|
|
(LPTSTR)szNULL,
|
|
(LPTSTR)szMsg, MAX_MSGLEN,
|
|
(LPTSTR)szCurThemeFile);
|
|
// expand filename string as necessary
|
|
InstantiatePath((LPTSTR)szMsg, MAX_MSGLEN);
|
|
}
|
|
else {
|
|
// cur system settings
|
|
HandGet(HKEY_CURRENT_USER,
|
|
(LPTSTR)szCursors,
|
|
(LPTSTR)( fvCursors[stkCursors[iter].indexF].szValName ),
|
|
(LPTSTR)szMsg);
|
|
}
|
|
|
|
// store whether the file exists
|
|
bCursorExists[iter] = szMsg[0] &&
|
|
(CF_NOTFOUND != ConfirmFile(szMsg, FALSE)); // don't alter str
|
|
|
|
// combine strings into data string to load up in
|
|
// owner-draw hasstrings listbox!
|
|
CreateDataStr((LPTSTR)pValue, (LPTSTR)szDispStr, (LPTSTR)szMsg);
|
|
|
|
// now, finally, go ahead and assign string to listbox
|
|
SendMessage(hLBox, LB_ADDSTRING, 0, (LPARAM)(LPTSTR)pValue);
|
|
}
|
|
|
|
// setup initial focus conditions
|
|
SetFocus(hLBox);
|
|
SendMessage(hLBox, LB_SETCURSEL, 0, 0);
|
|
|
|
// need to ensure it gets initial update of cur file
|
|
PostMessage(hDlg, WM_COMMAND, MAKEWPARAM(LB_PTRS, LBN_SELCHANGE),
|
|
MAKELPARAM(0, 0) );
|
|
|
|
} // var scope
|
|
break;
|
|
|
|
case WM_MEASUREITEM:
|
|
{
|
|
LPMEASUREITEMSTRUCT lpmis;
|
|
|
|
/* Set the height of the list box items. */
|
|
lpmis = (LPMEASUREITEMSTRUCT) lParam;
|
|
// lpmis->itemHeight = iItemHeight;
|
|
lpmis->itemHeight = 0; // DavidBa says they want these big default item hts
|
|
// Assert(iItemHeight > 0, TEXT("set non-positive item height for preview listbox!\n"));
|
|
// Assert(iItemHeight <= 0, TEXT("OK, set a positive item height for preview listbox!\n"));
|
|
}
|
|
break;
|
|
|
|
case WM_DRAWITEM:
|
|
{ // var scope
|
|
|
|
TEXTMETRIC tm;
|
|
LPDRAWITEMSTRUCT lpdis;
|
|
int yTextOffset;
|
|
LPTSTR lpszFile;
|
|
HDC hdcMem;
|
|
HBITMAP hbmpOld;
|
|
|
|
lpdis = (LPDRAWITEMSTRUCT) lParam;
|
|
|
|
/* If there are no list box items, skip this message. */
|
|
if (lpdis->itemID == -1) {
|
|
break;
|
|
} // jdk: well, what about focus rect in empty lbox?
|
|
|
|
//
|
|
// Inits
|
|
|
|
// get the filename assoc with this item, if any
|
|
SendMessage(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID,
|
|
(LPARAM)(LPTSTR)szMsg);
|
|
GetDisplayStr((LPTSTR)szMsg, (LPTSTR)szMsg); // Ok src and dst same
|
|
// you now have "displaystr\0filename" in szMsg[]
|
|
lpszFile = (LPTSTR)(szMsg + lstrlen((LPTSTR)szMsg) + 1);
|
|
|
|
//
|
|
// draw right background color
|
|
if (lpdis->itemState & ODS_SELECTED) {
|
|
|
|
// if item is selected, draw highlight background here
|
|
FillRect(lpdis->hDC, (LPRECT)&(lpdis->rcItem),
|
|
GetSysColorBrush(COLOR_HIGHLIGHT));
|
|
|
|
// set text color to highlight text
|
|
SetBkColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT));
|
|
SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
|
|
}
|
|
else { // not selected
|
|
// need to do normal background fill to undo prev selection
|
|
FillRect(lpdis->hDC, (LPRECT)&(lpdis->rcItem),
|
|
GetSysColorBrush(COLOR_WINDOW));
|
|
|
|
// set text color to foreground
|
|
SetBkColor(lpdis->hDC, GetSysColor(COLOR_WINDOW));
|
|
SetTextColor(lpdis->hDC, GetSysColor(COLOR_WINDOWTEXT));
|
|
}
|
|
|
|
// if there is a file associated with this item
|
|
if (*lpszFile) {
|
|
HBITMAP hbmpLeading;
|
|
BITMAP bmLeading;
|
|
|
|
//
|
|
// find the right leading bitmap: checkmark or question mark
|
|
if (bCursorExists[lpdis->itemID]) {
|
|
hbmpLeading = hbmpCheck;
|
|
bmLeading = bmCheck;
|
|
}
|
|
else {
|
|
hbmpLeading = hbmpQ;
|
|
bmLeading = bmQ;
|
|
}
|
|
|
|
//
|
|
// paint in the leading bitmap!
|
|
|
|
hdcMem = CreateCompatibleDC(lpdis->hDC);
|
|
if (hdcMem)
|
|
{
|
|
hbmpOld = SelectObject(hdcMem, hbmpLeading);
|
|
|
|
// if item height is less than bitmap height
|
|
if (lpdis->rcItem.bottom - lpdis->rcItem.top < bmLeading.bmHeight)
|
|
{
|
|
// stretch down bitmap size to fit
|
|
StretchBlt(lpdis->hDC,
|
|
lpdis->rcItem.left, lpdis->rcItem.top,
|
|
lpdis->rcItem.bottom - lpdis->rcItem.top, // width = height
|
|
lpdis->rcItem.bottom - lpdis->rcItem.top,
|
|
hdcMem, 0, 0, bmLeading.bmWidth, bmLeading.bmHeight, SRCCOPY);
|
|
}
|
|
else // item height taller than checkmark bitmap
|
|
{
|
|
// just center vertically
|
|
BitBlt(lpdis->hDC,
|
|
lpdis->rcItem.left,
|
|
lpdis->rcItem.top +
|
|
(lpdis->rcItem.bottom - lpdis->rcItem.top - bmLeading.bmHeight)/2,
|
|
bmLeading.bmWidth, bmLeading.bmHeight,
|
|
hdcMem, 0, 0, SRCCOPY);
|
|
}
|
|
|
|
SelectObject(hdcMem, hbmpOld);
|
|
DeleteDC(hdcMem);
|
|
}
|
|
|
|
// who cares
|
|
// Assert(lpdis->rcItem.bottom - lpdis->rcItem.top == iItemHeight,
|
|
// TEXT("MEASUREITEM and DRAWITEM have different heights!\n"));
|
|
}
|
|
|
|
//
|
|
// now draw the display string for this item
|
|
|
|
// figure y offset to vert center text in draw item
|
|
GetTextMetrics(lpdis->hDC, &tm);
|
|
yTextOffset = (lpdis->rcItem.bottom - lpdis->rcItem.top - tm.tmHeight) / 2;
|
|
Assert(yTextOffset >= 0, TEXT("negative text vert offset in DRAWITEM\n"));
|
|
if (yTextOffset < 0) yTextOffset = 0;
|
|
|
|
// do the out
|
|
SetBkMode(lpdis->hDC, TRANSPARENT);
|
|
TextOut(lpdis->hDC,
|
|
lpdis->rcItem.left + xTextOffset,
|
|
lpdis->rcItem.top + yTextOffset,
|
|
(LPTSTR)szMsg, lstrlen((LPTSTR)szMsg));
|
|
|
|
//
|
|
// if item is selected, draw a focus rect
|
|
if (lpdis->itemState & ODS_FOCUS) {
|
|
DrawFocusRect(lpdis->hDC, (LPRECT)&(lpdis->rcItem));
|
|
}
|
|
} // var scope
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch ((int)LOWORD(wParam)) {
|
|
case LB_PTRS:
|
|
// if new selection in listbox
|
|
if (HIWORD(wParam) == LBN_SELCHANGE) {
|
|
int iSeln, ilen;
|
|
|
|
// get new selection if any
|
|
iSeln = (int)SendDlgItemMessage(hDlg, LB_PTRS, LB_GETCURSEL, 0, 0);
|
|
if (LB_ERR == iSeln)
|
|
break; // no selection EXIT
|
|
|
|
// get selection text
|
|
SendDlgItemMessage(hDlg, LB_PTRS, LB_GETTEXT,
|
|
(WPARAM)iSeln, (LPARAM)(LPTSTR)szMsg);
|
|
|
|
// update global current filename string
|
|
GetFileStr(szCurPreviewFile, szMsg);
|
|
|
|
// reset dialog static text of filename string
|
|
SetDlgItemFile(hDlg, TXT_FILENAME, szCurPreviewFile);
|
|
// and scroll end into view
|
|
ilen = lstrlen((LPTSTR)szCurPreviewFile);
|
|
SendDlgItemMessage(hDlg, TXT_FILENAME, EM_SETSEL,
|
|
(WPARAM)0, MAKELPARAM(-1, ilen));
|
|
|
|
// update cursor
|
|
if (hCurCursor) DestroyCursor(hCurCursor);
|
|
hCurCursor = NULL;
|
|
if (*szCurPreviewFile)
|
|
{
|
|
hCurCursor = LoadImage(NULL, szCurPreviewFile, IMAGE_CURSOR,
|
|
0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE);
|
|
}
|
|
|
|
|
|
|
|
// set cursor to static, even if null: null clears prev
|
|
SendDlgItemMessage(hDlg, RECT_PREVIEW, STM_SETICON,
|
|
(WPARAM)hCurCursor, (LPARAM)0);
|
|
|
|
#if 0 // this is when we painted the cursor by ourself
|
|
// force repaint of preview area
|
|
InvalidateRect(hDlg, (LPRECT)&rPreview, TRUE);
|
|
#endif
|
|
}
|
|
break;
|
|
|
|
// case PB_TEST:
|
|
// break;
|
|
}
|
|
break;
|
|
|
|
#if 0 // this is when we painted the cursor by ourself
|
|
case WM_PAINT:
|
|
BeginPaint(hDlg, &ps);
|
|
|
|
//
|
|
// preview area
|
|
DrawEdge(ps.hdc, (LPRECT)&rPreview, EDGE_SUNKEN, BF_RECT); // always edge
|
|
// if there's a file to preview
|
|
if (*szCurPreviewFile) {
|
|
// add the cursor
|
|
if (hCurCursor)
|
|
DrawIcon(ps.hdc,
|
|
rPreview.left + (rPreview.right-rPreview.left-xCursor)/2,
|
|
rPreview.top + (rPreview.bottom-rPreview.top-yCursor)/2,
|
|
hCurCursor);
|
|
}
|
|
|
|
EndPaint(hDlg, &ps);
|
|
break;
|
|
#endif
|
|
|
|
case WM_NOTIFY:
|
|
switch ( ((NMHDR FAR *)lParam)->code) {
|
|
|
|
// OK or Apply button pressed
|
|
case PSN_APPLY:
|
|
// apply any changes made on this page
|
|
|
|
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR); // accept changes
|
|
break;
|
|
|
|
// cancel button pressed
|
|
case PSN_RESET:
|
|
// don't accept any of the changes made on this page
|
|
break;
|
|
|
|
case PSN_SETACTIVE:
|
|
break;
|
|
case PSN_KILLACTIVE:
|
|
// need to say that it's OK by us to lose the activation
|
|
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, FALSE); // OK to kill focus now
|
|
break;
|
|
|
|
}
|
|
break;
|
|
|
|
case WM_HELP:
|
|
{
|
|
LPHELPINFO lphi;
|
|
lphi = (LPHELPINFO)lParam;
|
|
if (lphi->iContextType == HELPINFO_WINDOW) {
|
|
WinHelp(lphi->hItemHandle, (LPTSTR)szHelpFile, HELP_WM_HELP,
|
|
(DWORD_PTR)((POPUP_HELP_ARRAY FAR *)phaPtrsDlg));
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_CONTEXTMENU:
|
|
WinHelp((HWND)wParam, (LPTSTR)szHelpFile, HELP_CONTEXTMENU,
|
|
(DWORD_PTR)((POPUP_HELP_ARRAY FAR *)phaPtrsDlg));
|
|
break;
|
|
|
|
default:
|
|
return(FALSE); // didn't process message
|
|
break;
|
|
}
|
|
|
|
return TRUE; // processed message
|
|
}
|
|
|
|
|
|
INT_PTR FAR PASCAL SndsPageProc(hDlg, message, wParam, lParam)
|
|
HWND hDlg;
|
|
UINT message;
|
|
WPARAM wParam;
|
|
LPARAM lParam;
|
|
{
|
|
static BOOL gfWaveExists = FALSE;
|
|
static HBITMAP hbmpPlay = NULL;
|
|
BOOL bDoubleClick = FALSE;
|
|
|
|
switch (message) {
|
|
|
|
// set up listbox, initial selection, etc.
|
|
case WM_INITDIALOG:
|
|
{ // var scope
|
|
int iter;
|
|
int iRet;
|
|
extern FROST_SUBKEY fsCurUser[]; // for theme file keys
|
|
HWND hText, hLBox;
|
|
RECT rText;
|
|
TCHAR szDispStr[MAX_STRLEN+1];
|
|
extern FROST_SUBKEY fsCurUser[];
|
|
WAVEOUTCAPS woCaps;
|
|
|
|
// Taken right from the Sounds cpl.
|
|
gfWaveExists = waveOutGetNumDevs() > 0 &&
|
|
(waveOutGetDevCaps(0,&woCaps,sizeof(woCaps)) == 0) &&
|
|
woCaps.dwFormats != 0L;
|
|
|
|
if ((hbmpPlay = LoadBitmap(hInstApp, MAKEINTRESOURCE(PLAY_BITMAP))) !=
|
|
NULL)
|
|
SendDlgItemMessage(hDlg, PB_PLAY, BM_SETIMAGE, IMAGE_BITMAP,
|
|
(LPARAM) hbmpPlay);
|
|
|
|
//
|
|
// get metrics for drawitem size
|
|
hText = GetDlgItem(hDlg, TXT_FILENAME); // 12 dialog box units high
|
|
GetWindowRect(hText, (LPRECT)&rText);
|
|
iItemHeight = ((rText.bottom - rText.top) * 8) / 12; // dialog font height
|
|
xTextOffset = (iItemHeight * 3) / 2; // proportional spacing
|
|
Assert(iItemHeight > 0, TEXT("didn't get positive text height for preview listbox!\n"));
|
|
|
|
//
|
|
// init the listbox with combined strings
|
|
|
|
// init
|
|
hLBox = GetDlgItem(hDlg, LB_SNDS);
|
|
Assert (sizeof(stkSounds)/sizeof(STR_TO_KEY) == NUM_SOUNDS,
|
|
TEXT("size mismatch stkSounds and NUM_SOUNDS\n"));
|
|
|
|
// for each sound
|
|
for (iter = 0; iter < NUM_SOUNDS; iter++) {
|
|
// get display string
|
|
LoadString(hInstApp, stkSounds[iter].idStr,
|
|
(LPTSTR)szDispStr, MAX_STRLEN);
|
|
// CPLs don't check for success on LoadString in INITDIALOG, so OK!?
|
|
// get filename if any
|
|
if (bThemed) {
|
|
GetPrivateProfileString((LPTSTR)(fsCurUser[stkSounds[iter].indexF].szSubKey),
|
|
(LPTSTR)FROST_DEFSTR,
|
|
(LPTSTR)szNULL,
|
|
(LPTSTR)szMsg, MAX_MSGLEN,
|
|
(LPTSTR)szCurThemeFile);
|
|
// expand filename string as necessary
|
|
InstantiatePath((LPTSTR)szMsg, MAX_MSGLEN);
|
|
}
|
|
else {
|
|
// cur system settings
|
|
HandGet(HKEY_CURRENT_USER,
|
|
(LPTSTR)(fsCurUser[stkSounds[iter].indexF].szSubKey),
|
|
(LPTSTR)szNULL,
|
|
(LPTSTR)szMsg);
|
|
}
|
|
|
|
// combine strings into data string to load up in
|
|
// owner-draw hasstrings listbox!
|
|
CreateDataStr((LPTSTR)pValue, (LPTSTR)szDispStr, (LPTSTR)szMsg);
|
|
|
|
// now, finally, go ahead and assign string to listbox
|
|
SendMessage(hLBox, LB_ADDSTRING, 0, (LPARAM)(LPTSTR)pValue);
|
|
}
|
|
|
|
//
|
|
// check them all for file existence. have to do here, LBOX IS SORTED!
|
|
//
|
|
for (iter = 0; iter < MAX_ETC_ITEMS; iter++) {
|
|
// get this item's listbox string
|
|
iRet = (int) SendMessage(hLBox, LB_GETTEXT, iter, (LPARAM)(LPTSTR)szMsg);
|
|
if (iRet == LB_ERR)
|
|
break; // past end of listbox items CONTINUE
|
|
|
|
// get the filename assoc with this item, if any
|
|
GetFileStr((LPTSTR)pValue, (LPTSTR)szMsg);
|
|
|
|
// store whether the file exists
|
|
bSoundExists[iter] = *pValue &&
|
|
(CF_NOTFOUND != ConfirmFile((LPTSTR)pValue, FALSE));
|
|
}
|
|
|
|
// save away preview rect area
|
|
GetWindowRect(GetDlgItem(hDlg, RECT_PREVIEW), (LPRECT)&rPreview);
|
|
GetWindowRect(hDlg, (LPRECT)&rText);
|
|
OffsetRect((LPRECT)&rPreview, -rText.left, -rText.top);
|
|
|
|
// setup initial focus conditions
|
|
SetFocus(hLBox);
|
|
SendMessage(hLBox, LB_SETCURSEL, 0, 0);
|
|
|
|
// need to ensure it gets initial update of cur file
|
|
PostMessage(hDlg, WM_COMMAND, MAKEWPARAM(LB_SNDS, LBN_SELCHANGE),
|
|
MAKELPARAM(0, 0) );
|
|
|
|
} // var scope
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
{
|
|
if (hbmpPlay) {
|
|
DeleteObject(hbmpPlay);
|
|
hbmpPlay = NULL;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_MEASUREITEM:
|
|
{
|
|
LPMEASUREITEMSTRUCT lpmis;
|
|
|
|
/* Set the height of the list box items. */
|
|
lpmis = (LPMEASUREITEMSTRUCT) lParam;
|
|
// lpmis->itemHeight = iItemHeight;
|
|
lpmis->itemHeight = 0; // DavidBa says they want these big default item hts
|
|
// Assert(iItemHeight > 0, TEXT("set non-positive item height for preview listbox!\n"));
|
|
// Assert(iItemHeight <= 0, TEXT("OK, set a positive item height for preview listbox!\n"));
|
|
}
|
|
break;
|
|
|
|
case WM_DRAWITEM:
|
|
{ // var scope
|
|
|
|
TEXTMETRIC tm;
|
|
LPDRAWITEMSTRUCT lpdis;
|
|
int yTextOffset;
|
|
LPTSTR lpszFile;
|
|
HDC hdcMem;
|
|
HBITMAP hbmpOld;
|
|
|
|
lpdis = (LPDRAWITEMSTRUCT) lParam;
|
|
|
|
/* If there are no list box items, skip this message. */
|
|
if (lpdis->itemID == -1) {
|
|
break;
|
|
} // jdk: well, what about focus rect in empty lbox?
|
|
|
|
//
|
|
// Inits
|
|
|
|
// get the filename assoc with this item, if any
|
|
SendMessage(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID,
|
|
(LPARAM)(LPTSTR)szMsg);
|
|
GetDisplayStr((LPTSTR)szMsg, (LPTSTR)szMsg); // Ok src and dst same
|
|
// you now have "displaystr\0filename" in szMsg[]
|
|
lpszFile = (LPTSTR)(szMsg + lstrlen((LPTSTR)szMsg) + 1);
|
|
|
|
//
|
|
// draw right background color
|
|
if (lpdis->itemState & ODS_SELECTED) {
|
|
|
|
// if item is selected, draw highlight background here
|
|
FillRect(lpdis->hDC, (LPRECT)&(lpdis->rcItem),
|
|
GetSysColorBrush(COLOR_HIGHLIGHT));
|
|
|
|
// set text color to highlight text
|
|
SetBkColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT));
|
|
SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
|
|
}
|
|
else { // not selected
|
|
// need to do normal background fill to undo prev selection
|
|
FillRect(lpdis->hDC, (LPRECT)&(lpdis->rcItem),
|
|
GetSysColorBrush(COLOR_WINDOW));
|
|
|
|
// set text color to foreground
|
|
SetBkColor(lpdis->hDC, GetSysColor(COLOR_WINDOW));
|
|
SetTextColor(lpdis->hDC, GetSysColor(COLOR_WINDOWTEXT));
|
|
}
|
|
|
|
// if there is a file associated with this item
|
|
if (*lpszFile) {
|
|
HBITMAP hbmpLeading;
|
|
BITMAP bmLeading;
|
|
|
|
//
|
|
// find the right leading bitmap: checkmark or question mark
|
|
if (bSoundExists[lpdis->itemID]) {
|
|
hbmpLeading = hbmpCheck;
|
|
bmLeading = bmCheck;
|
|
}
|
|
else {
|
|
hbmpLeading = hbmpQ;
|
|
bmLeading = bmQ;
|
|
}
|
|
|
|
//
|
|
// paint in the leading bitmap!
|
|
|
|
hdcMem = CreateCompatibleDC(lpdis->hDC);
|
|
if (hdcMem)
|
|
{
|
|
hbmpOld = SelectObject(hdcMem, hbmpLeading);
|
|
|
|
// if item height is less than bitmap height
|
|
if (lpdis->rcItem.bottom - lpdis->rcItem.top < bmLeading.bmHeight)
|
|
{
|
|
// stretch down bitmap size to fit
|
|
StretchBlt(lpdis->hDC,
|
|
lpdis->rcItem.left, lpdis->rcItem.top,
|
|
lpdis->rcItem.bottom - lpdis->rcItem.top, // width = height
|
|
lpdis->rcItem.bottom - lpdis->rcItem.top,
|
|
hdcMem, 0, 0, bmLeading.bmWidth, bmLeading.bmHeight, SRCCOPY);
|
|
}
|
|
else // item height taller than checkmark bitmap
|
|
{
|
|
// just center vertically
|
|
BitBlt(lpdis->hDC,
|
|
lpdis->rcItem.left,
|
|
lpdis->rcItem.top +
|
|
(lpdis->rcItem.bottom - lpdis->rcItem.top - bmLeading.bmHeight)/2,
|
|
bmLeading.bmWidth, bmLeading.bmHeight,
|
|
hdcMem, 0, 0, SRCCOPY);
|
|
}
|
|
|
|
SelectObject(hdcMem, hbmpOld);
|
|
DeleteDC(hdcMem);
|
|
}
|
|
|
|
// who cares
|
|
// Assert(lpdis->rcItem.bottom - lpdis->rcItem.top == iItemHeight,
|
|
// TEXT("MEASUREITEM and DRAWITEM have different heights!\n"));
|
|
}
|
|
|
|
//
|
|
// now draw the display string for this item
|
|
|
|
// figure y offset to vert center text in draw item
|
|
GetTextMetrics(lpdis->hDC, &tm);
|
|
yTextOffset = (lpdis->rcItem.bottom - lpdis->rcItem.top - tm.tmHeight) / 2;
|
|
Assert(yTextOffset >= 0, TEXT("negative text vert offset in DRAWITEM\n"));
|
|
if (yTextOffset < 0) yTextOffset = 0;
|
|
|
|
// do the out
|
|
SetBkMode(lpdis->hDC, TRANSPARENT);
|
|
TextOut(lpdis->hDC,
|
|
lpdis->rcItem.left + xTextOffset,
|
|
lpdis->rcItem.top + yTextOffset,
|
|
(LPTSTR)szMsg, lstrlen((LPTSTR)szMsg));
|
|
|
|
//
|
|
// if item is selected, draw a focus rect
|
|
if (lpdis->itemState & ODS_FOCUS) {
|
|
DrawFocusRect(lpdis->hDC, (LPRECT)&(lpdis->rcItem));
|
|
}
|
|
} // var scope
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch ((int)LOWORD(wParam)) {
|
|
case LB_SNDS:
|
|
// if new selection in listbox
|
|
if (HIWORD(wParam) == LBN_SELCHANGE) {
|
|
int iSeln, ilen;
|
|
|
|
// get new selection if any
|
|
iSeln = (int)SendDlgItemMessage(hDlg, LB_SNDS, LB_GETCURSEL, 0, 0);
|
|
if (LB_ERR == iSeln)
|
|
break; // no selection EXIT
|
|
|
|
// get selection text
|
|
SendDlgItemMessage(hDlg, LB_SNDS, LB_GETTEXT,
|
|
(WPARAM)iSeln, (LPARAM)(LPTSTR)szMsg);
|
|
|
|
// update global current filename string
|
|
GetFileStr(szCurPreviewFile, szMsg);
|
|
|
|
// reset dialog static text of filename string
|
|
SetDlgItemFile(hDlg, TXT_FILENAME, szCurPreviewFile);
|
|
// and scroll end into view
|
|
ilen = lstrlen((LPTSTR)szCurPreviewFile);
|
|
SendDlgItemMessage(hDlg, TXT_FILENAME, EM_SETSEL,
|
|
(WPARAM)0, MAKELPARAM(-1, ilen));
|
|
|
|
// update snd file icon
|
|
if (hbmpCurSnd) DeleteObject(hbmpCurSnd);
|
|
hbmpCurSnd = NULL;
|
|
if (*szCurPreviewFile)
|
|
hbmpCurSnd = GetSoundBitmap((LPTSTR)szCurPreviewFile);
|
|
|
|
// set snd file bmp to static
|
|
if (hbmpCurSnd) {
|
|
SendDlgItemMessage(hDlg, RECT_PREVIEW, STM_SETIMAGE,
|
|
(WPARAM)IMAGE_BITMAP, (LPARAM)hbmpCurSnd);
|
|
}
|
|
else {
|
|
// else need to clear it to empty
|
|
SendDlgItemMessage(hDlg, RECT_PREVIEW, STM_SETIMAGE,
|
|
(WPARAM)NULL, (LPARAM)NULL);
|
|
InvalidateRect(hDlg, (LPRECT)&rPreview, TRUE);
|
|
#ifdef SHOULDAWORKED
|
|
InvalidateRect(GetDlgItem(hDlg, RECT_PREVIEW), (LPRECT)NULL, TRUE);
|
|
UpdateWindow(GetDlgItem(hDlg, RECT_PREVIEW));
|
|
#endif
|
|
}
|
|
|
|
// update play button
|
|
EnableWindow(GetDlgItem(hDlg, PB_PLAY), *szCurPreviewFile &&
|
|
bSoundExists[iSeln] && gfWaveExists);
|
|
}
|
|
|
|
// if just a selection, we're done here
|
|
if (HIWORD(wParam) != LBN_DBLCLK)
|
|
break;
|
|
|
|
// else double-click means fall through and play
|
|
bDoubleClick = TRUE;
|
|
|
|
case PB_PLAY:
|
|
if (((HIWORD(wParam) == BN_CLICKED) || bDoubleClick) && gfWaveExists) {
|
|
int iSeln;
|
|
|
|
// check that sound file exists
|
|
iSeln = (int)SendDlgItemMessage(hDlg, LB_SNDS, LB_GETCURSEL, 0, 0);
|
|
if (!bSoundExists[iSeln])
|
|
break;
|
|
|
|
if (*szCurPreviewFile) {
|
|
// disable and wait
|
|
EnableWindow((HWND)lParam, FALSE);
|
|
WaitCursor();
|
|
|
|
PlaySound((LPTSTR)szCurPreviewFile, NULL, SND_SYNC | SND_FILENAME);
|
|
|
|
// reenable and normal
|
|
EnableWindow((HWND)lParam, TRUE);
|
|
NormalCursor();
|
|
SetFocus((HWND)lParam);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
switch ( ((NMHDR FAR *)lParam)->code) {
|
|
|
|
// OK or Apply button pressed
|
|
case PSN_APPLY:
|
|
// apply any changes made on this page
|
|
|
|
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR); // accept changes
|
|
break;
|
|
|
|
// cancel button pressed
|
|
case PSN_RESET:
|
|
// don't accept any of the changes made on this page
|
|
break;
|
|
|
|
case PSN_SETACTIVE:
|
|
break;
|
|
case PSN_KILLACTIVE:
|
|
// need to say that it's OK by us to lose the activation
|
|
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, FALSE); // OK to kill focus now
|
|
break;
|
|
|
|
}
|
|
break;
|
|
|
|
case WM_HELP:
|
|
{
|
|
LPHELPINFO lphi;
|
|
lphi = (LPHELPINFO)lParam;
|
|
if (lphi->iContextType == HELPINFO_WINDOW) {
|
|
WinHelp(lphi->hItemHandle, (LPTSTR)szHelpFile, HELP_WM_HELP,
|
|
(DWORD_PTR)((POPUP_HELP_ARRAY FAR *)phaSndsDlg));
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_CONTEXTMENU:
|
|
WinHelp((HWND)wParam, (LPTSTR)szHelpFile, HELP_CONTEXTMENU,
|
|
(DWORD_PTR)((POPUP_HELP_ARRAY FAR *)phaSndsDlg));
|
|
break;
|
|
|
|
default:
|
|
return(FALSE); // didn't process message
|
|
break;
|
|
}
|
|
|
|
return TRUE; // processed message
|
|
}
|
|
|
|
HBITMAP PASCAL GetSoundBitmap(LPTSTR lpszFile)
|
|
{
|
|
HANDLE hDib = NULL;
|
|
HMMIO hmmio = NULL;
|
|
TCHAR szValue[MAX_MSGLEN+1];
|
|
// HPALETTE hPal;
|
|
HBITMAP hbmpRet = NULL;
|
|
|
|
if (!lpszFile || !*lpszFile)
|
|
return ((HBITMAP)NULL);
|
|
|
|
|
|
/* Open the file */
|
|
hmmio = mmioOpen(lpszFile, NULL, MMIO_ALLOCBUF | MMIO_READ);
|
|
|
|
// get the DIB
|
|
if (hmmio) {
|
|
szValue[0] = TEXT('\0');
|
|
hDib = GetRiffAll(hmmio, szValue, sizeof(szValue));
|
|
mmioClose(hmmio, 0);
|
|
}
|
|
|
|
if (hDib) {
|
|
HPALETTE hPal;
|
|
|
|
hPal = bmfCreateDIBPalette(hDib);
|
|
if (hPal)
|
|
{
|
|
hbmpRet = bmfBitmapFromDIB(hDib, hPal); // hPal can be null
|
|
DeleteObject(hPal);
|
|
}
|
|
|
|
GlobalFree(hDib);
|
|
}
|
|
|
|
return(hbmpRet);
|
|
}
|
|
|
|
// guessing that this is the right addition
|
|
#define FOURCC_DISP mmioFOURCC('D', 'I', 'S', 'P')
|
|
#define FOURCC_INFO mmioFOURCC('I', 'N', 'F', 'O')
|
|
#define FOURCC_INAM mmioFOURCC('I', 'N', 'A', 'M')
|
|
|
|
HANDLE PASCAL GetRiffAll(HMMIO hmmio, LPTSTR szText, int iLen)
|
|
{
|
|
MMCKINFO ck;
|
|
MMCKINFO ckINFO;
|
|
MMCKINFO ckRIFF;
|
|
HANDLE h = NULL;
|
|
LONG lSize;
|
|
DWORD dw;
|
|
|
|
mmioSeek(hmmio, 0, SEEK_SET);
|
|
|
|
/* descend the input file into the RIFF chunk */
|
|
if (mmioDescend(hmmio, &ckRIFF, NULL, 0) != 0)
|
|
goto error;
|
|
|
|
if (ckRIFF.ckid != FOURCC_RIFF)
|
|
goto error;
|
|
|
|
while (!mmioDescend(hmmio, &ck, &ckRIFF, 0))
|
|
{
|
|
if (ck.ckid == FOURCC_DISP)
|
|
{
|
|
/* Read dword into dw, break if read unsuccessful */
|
|
if (mmioRead(hmmio, (LPVOID)&dw, sizeof(dw)) != sizeof(dw))
|
|
goto error;
|
|
|
|
/* Find out how much memory to allocate */
|
|
lSize = ck.cksize - sizeof(dw);
|
|
|
|
if ((int)dw == CF_DIB && h == NULL)
|
|
{
|
|
/* get a handle to memory to hold the description and
|
|
lock it down */
|
|
|
|
if ((h = GlobalAlloc(GHND, lSize+4)) == NULL)
|
|
goto error;
|
|
|
|
if (mmioRead(hmmio, GlobalLock(h), lSize) != lSize)
|
|
goto error;
|
|
}
|
|
else if ((int)dw == CF_TEXT && szText[0] == 0)
|
|
{
|
|
if (lSize > iLen-1)
|
|
lSize = iLen-1;
|
|
|
|
szText[lSize] = 0;
|
|
if (mmioRead(hmmio, (LPVOID)szText, lSize) != lSize)
|
|
goto error;
|
|
}
|
|
}
|
|
else if (ck.ckid == FOURCC_LIST &&
|
|
ck.fccType == FOURCC_INFO &&
|
|
szText[0] == 0)
|
|
{
|
|
while (!mmioDescend(hmmio, &ckINFO, &ck, 0))
|
|
{
|
|
switch (ckINFO.ckid)
|
|
{
|
|
case FOURCC_INAM:
|
|
// case FOURCC_ISBJ:
|
|
|
|
lSize = ck.cksize;
|
|
|
|
if (lSize > iLen-1)
|
|
lSize = iLen-1;
|
|
|
|
szText[lSize] = 0;
|
|
if (mmioRead(hmmio, (LPVOID)szText, lSize) != lSize)
|
|
goto error;
|
|
|
|
break;
|
|
}
|
|
|
|
if (mmioAscend(hmmio, &ckINFO, 0))
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// if we have both a picture and a title, then exit.
|
|
//
|
|
if (h != NULL && szText[0] != 0)
|
|
break;
|
|
|
|
/* Ascend so that we can descend into next chunk
|
|
*/
|
|
if (mmioAscend(hmmio, &ck, 0))
|
|
break;
|
|
}
|
|
|
|
goto exit;
|
|
|
|
error:
|
|
if (h)
|
|
GlobalFree(h);
|
|
h = NULL;
|
|
|
|
exit:
|
|
return h;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* FUNCTION :bmfCreateDIBPalette(HANDLE hDib)
|
|
*
|
|
* PURPOSE :Creates a palette suitable for displaying hDib.
|
|
*
|
|
* RETURNS :A handle to the palette if successful, NULL otherwise.
|
|
*
|
|
****************************************************************************/
|
|
|
|
HPALETTE WINAPI bmfCreateDIBPalette (HANDLE hDib)
|
|
{
|
|
HPALETTE hPal;
|
|
LPBITMAPINFOHEADER lpbi;
|
|
|
|
if (!hDib)
|
|
return NULL; //bail out if handle is invalid
|
|
|
|
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
|
|
if (!lpbi)
|
|
return NULL;
|
|
|
|
hPal = CreateBIPalette(lpbi);
|
|
GlobalUnlock(hDib);
|
|
return hPal;
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
* FUNCTION :CreateBIPalette(LPBITMAPINFOHEADER lpbi)
|
|
*
|
|
* PURPOSE :Given a Pointer to a BITMAPINFO struct will create a
|
|
* a GDI palette object from the color table.
|
|
*
|
|
* RETURNS :A handle to the palette if successful, NULL otherwise.
|
|
*
|
|
****************************************************************************/
|
|
|
|
HPALETTE CreateBIPalette (LPBITMAPINFOHEADER lpbi)
|
|
{
|
|
LPLOGPALETTE pPal;
|
|
HPALETTE hPal = NULL;
|
|
WORD nNumColors;
|
|
BYTE red;
|
|
BYTE green;
|
|
BYTE blue;
|
|
int i;
|
|
RGBQUAD FAR *pRgb;
|
|
HANDLE hMem;
|
|
|
|
if (!lpbi)
|
|
return NULL;
|
|
|
|
if (lpbi->biSize != sizeof(BITMAPINFOHEADER))
|
|
return NULL;
|
|
|
|
/* Get a pointer to the color table and the number of colors in it */
|
|
pRgb = (RGBQUAD FAR *)((LPTSTR)lpbi + (WORD)lpbi->biSize);
|
|
nNumColors = NumDIBColors(lpbi);
|
|
|
|
if (nNumColors)
|
|
{
|
|
/* Allocate for the logical palette structure */
|
|
hMem = GlobalAlloc(GMEM_MOVEABLE,
|
|
sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY));
|
|
if (!hMem)
|
|
return NULL;
|
|
pPal = (LPLOGPALETTE)GlobalLock(hMem);
|
|
if (!pPal)
|
|
{
|
|
GlobalFree(hMem);
|
|
return NULL;
|
|
}
|
|
|
|
pPal->palNumEntries = nNumColors;
|
|
pPal->palVersion = PALVERSION;
|
|
|
|
/* Fill in the palette entries from the DIB color table and
|
|
* create a logical color palette.
|
|
*/
|
|
for (i = 0; (unsigned)i < nNumColors; i++)
|
|
{
|
|
pPal->palPalEntry[i].peRed = pRgb[i].rgbRed;
|
|
pPal->palPalEntry[i].peGreen = pRgb[i].rgbGreen;
|
|
pPal->palPalEntry[i].peBlue = pRgb[i].rgbBlue;
|
|
pPal->palPalEntry[i].peFlags = (BYTE)0;
|
|
}
|
|
hPal = CreatePalette(pPal);
|
|
/* note that a NULL return value for the above CreatePalette call
|
|
* is acceptable, since this value will be returned, and is not
|
|
* used again here
|
|
*/
|
|
GlobalUnlock(hMem);
|
|
GlobalFree(hMem);
|
|
}
|
|
else if (lpbi->biBitCount == 24)
|
|
{
|
|
/* A 24 bitcount DIB has no color table entries so, set the number of
|
|
* to the maximum value (256).
|
|
*/
|
|
nNumColors = MAXPALETTE;
|
|
hMem =GlobalAlloc(GMEM_MOVEABLE,
|
|
sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY));
|
|
if (!hMem)
|
|
return NULL;
|
|
pPal = (LPLOGPALETTE)GlobalLock(hMem);
|
|
if (!pPal)
|
|
{
|
|
GlobalFree(hMem);
|
|
return NULL;
|
|
}
|
|
|
|
pPal->palNumEntries = nNumColors;
|
|
pPal->palVersion = PALVERSION;
|
|
|
|
red = green = blue = 0;
|
|
|
|
/* Generate 256 (= 8*8*4) RGB combinations to fill the palette
|
|
* entries.
|
|
*/
|
|
for (i = 0; (unsigned)i < pPal->palNumEntries; i++)
|
|
{
|
|
pPal->palPalEntry[i].peRed = red;
|
|
pPal->palPalEntry[i].peGreen = green;
|
|
pPal->palPalEntry[i].peBlue = blue;
|
|
pPal->palPalEntry[i].peFlags = (BYTE)0;
|
|
|
|
if (!(red += 32))
|
|
if (!(green += 32))
|
|
blue += 64;
|
|
}
|
|
hPal = CreatePalette(pPal);
|
|
/* note that a NULL return value for the above CreatePalette call
|
|
* is acceptable, since this value will be returned, and is not
|
|
* used again here
|
|
*/
|
|
GlobalUnlock(hMem);
|
|
GlobalFree(hMem);
|
|
}
|
|
return hPal;
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
* FUNCTION :NumDIBColors(VOID FAR * pv)
|
|
*
|
|
* PURPOSE :Determines the number of colors in the DIB by looking at
|
|
* the BitCount field in the info block.
|
|
* For use only internal to DLL.
|
|
*
|
|
* RETURNS :The number of colors in the DIB.
|
|
*
|
|
****************************************************************************/
|
|
|
|
WORD NumDIBColors (VOID FAR * pv)
|
|
{
|
|
int bits;
|
|
LPBITMAPINFOHEADER lpbi;
|
|
LPBITMAPCOREHEADER lpbc;
|
|
|
|
lpbi = ((LPBITMAPINFOHEADER)pv);
|
|
lpbc = ((LPBITMAPCOREHEADER)pv);
|
|
|
|
/* With the BITMAPINFO format headers, the size of the palette
|
|
* is in biClrUsed, whereas in the BITMAPCORE - style headers, it
|
|
* is dependent on the bits per pixel ( = 2 raised to the power of
|
|
* bits/pixel).
|
|
*/
|
|
if (lpbi->biSize != sizeof(BITMAPCOREHEADER))
|
|
{
|
|
if (lpbi->biClrUsed != 0)
|
|
return (WORD)lpbi->biClrUsed;
|
|
bits = lpbi->biBitCount;
|
|
}
|
|
else
|
|
bits = lpbc->bcBitCount;
|
|
|
|
switch (bits)
|
|
{
|
|
case 1:
|
|
return 2;
|
|
case 4:
|
|
return 16;
|
|
case 8:
|
|
return 256;
|
|
default:
|
|
/* A 24 bitcount DIB has no color table */
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
* FUNCTION :bmfBitmapFromDIB(HANDLE hDib, HPALETTE hPal)
|
|
*
|
|
* PURPOSE :Converts DIB information into a device-dependent BITMAP
|
|
* suitable for display on the current display device. hDib is
|
|
* a global handle to a memory block containing the DIB
|
|
* information in CF_DIB format. hPal is a handle to a palette
|
|
* to be used for displaying the bitmap. If hPal is NULL, the
|
|
* default system palette is used during the conversion.
|
|
*
|
|
* RETURNS :Returns a handle to a bitmap is successful, NULL otherwise.
|
|
*
|
|
* HISTORY:
|
|
* 92/08/29 - BUG 2123: (w-markd)
|
|
* Check if DIB is has a valid size, and bail out if not.
|
|
* If no palette is passed in, try to create one. If we
|
|
* create one, we must destroy it before we exit.
|
|
*
|
|
****************************************************************************/
|
|
|
|
HBITMAP WINAPI bmfBitmapFromDIB(HANDLE hDib, HPALETTE hPal)
|
|
{
|
|
LPBITMAPINFOHEADER lpbi;
|
|
HPALETTE hPalT;
|
|
HDC hdc;
|
|
HBITMAP hBmp;
|
|
DWORD dwSize;
|
|
BOOL bMadePalette = FALSE;
|
|
|
|
if (!hDib)
|
|
return NULL; //bail out if handle is invalid
|
|
|
|
/* BUG 2123: (w-markd)
|
|
** Check to see if we can get the size of the DIB. If this call
|
|
** fails, bail out.
|
|
*/
|
|
dwSize = bmfDIBSize(hDib);
|
|
if (!dwSize)
|
|
return NULL;
|
|
|
|
lpbi = (VOID FAR *)GlobalLock(hDib);
|
|
if (!lpbi)
|
|
return NULL;
|
|
|
|
/* prepare palette */
|
|
/* BUG 2123: (w-markd)
|
|
** If the palette is NULL, we create one suitable for displaying
|
|
** the dib.
|
|
*/
|
|
if (!hPal)
|
|
{
|
|
hPal = bmfCreateDIBPalette(hDib);
|
|
if (!hPal)
|
|
{
|
|
GlobalUnlock(hDib);
|
|
#ifdef V101
|
|
#else
|
|
bMadePalette = TRUE;
|
|
#endif
|
|
return NULL;
|
|
}
|
|
#ifdef V101
|
|
/* BUGFIX: mikeroz 2123 - this flag was in the wrong place */
|
|
bMadePalette = TRUE;
|
|
#endif
|
|
}
|
|
hdc = GetDC(NULL);
|
|
hPalT = SelectPalette(hdc,hPal,FALSE);
|
|
RealizePalette(hdc); // GDI Bug...????
|
|
|
|
/* Create the bitmap. Note that a return value of NULL is ok here */
|
|
hBmp = CreateDIBitmap(hdc, (LPBITMAPINFOHEADER)lpbi, (LONG)CBM_INIT,
|
|
(LPSTR)lpbi + lpbi->biSize + PaletteSize(lpbi),
|
|
(LPBITMAPINFO)lpbi, DIB_RGB_COLORS );
|
|
|
|
/* clean up and exit */
|
|
/* BUG 2123: (w-markd)
|
|
** If we made the palette, we need to delete it.
|
|
*/
|
|
if (bMadePalette)
|
|
DeleteObject(SelectPalette(hdc,hPalT,FALSE));
|
|
else
|
|
SelectPalette(hdc,hPalT,FALSE);
|
|
ReleaseDC(NULL,hdc);
|
|
GlobalUnlock(hDib);
|
|
return hBmp;
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
* FUNCTION :bmfDIBSize(HANDLE hDIB)
|
|
*
|
|
* PURPOSE :Return the size of a DIB.
|
|
*
|
|
* RETURNS :DWORD with size of DIB, include BITMAPINFOHEADER and
|
|
* palette. Returns 0 if failed.
|
|
*
|
|
* HISTORY:
|
|
* 92/08/13 - BUG 1642: (w-markd)
|
|
* Added this function so Quick Recorder could find out the
|
|
* size of a DIB.
|
|
* 92/08/29 - BUG 2123: (w-markd)
|
|
* If the biSizeImage field of the structure we get is zero,
|
|
* then we have to calculate the size of the image ourselves.
|
|
* Also, after size is calculated, we bail out if the
|
|
* size we calculated is larger than the size of the global
|
|
* object, since this indicates that the structure data
|
|
* we used to calculate the size was invalid.
|
|
*
|
|
****************************************************************************/
|
|
|
|
DWORD WINAPI bmfDIBSize(HANDLE hDIB)
|
|
{
|
|
LPBITMAPINFOHEADER lpbi;
|
|
DWORD dwSize;
|
|
|
|
/* Lock down the handle, and cast to a LPBITMAPINFOHEADER
|
|
** so we can read the fields we need
|
|
*/
|
|
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
|
|
if (!lpbi)
|
|
return 0;
|
|
|
|
/* BUG 2123: (w-markd)
|
|
** Since the biSizeImage could be zero, we may have to calculate
|
|
** the size ourselves.
|
|
*/
|
|
dwSize = lpbi->biSizeImage;
|
|
if (dwSize == 0)
|
|
dwSize = WIDTHBYTES((WORD)(lpbi->biWidth) * lpbi->biBitCount) *
|
|
lpbi->biHeight;
|
|
|
|
|
|
/* The size of the DIB is the size of the BITMAPINFOHEADER
|
|
** structure (lpbi->biSize) plus the size of our palette plus
|
|
** the size of the actual data (calculated above).
|
|
*/
|
|
dwSize += lpbi->biSize + (DWORD)PaletteSize(lpbi);
|
|
|
|
/* BUG 2123: (w-markd)
|
|
** Check to see if the size is greater than the size
|
|
** of the global object. If it is, the hDIB is corrupt.
|
|
*/
|
|
GlobalUnlock(hDIB);
|
|
if (dwSize > GlobalSize(hDIB))
|
|
return 0;
|
|
else
|
|
return(dwSize);
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
* FUNCTION :PaletteSize(VOID FAR * pv)
|
|
*
|
|
* PURPOSE :Calculates the palette size in bytes. If the info. block
|
|
* is of the BITMAPCOREHEADER type, the number of colors is
|
|
* multiplied by 3 to give the palette size, otherwise the
|
|
* number of colors is multiplied by 4.
|
|
*
|
|
* RETURNS :Palette size in number of bytes.
|
|
*
|
|
****************************************************************************/
|
|
|
|
WORD PaletteSize (VOID FAR *pv)
|
|
{
|
|
LPBITMAPINFOHEADER lpbi;
|
|
WORD NumColors;
|
|
|
|
lpbi = (LPBITMAPINFOHEADER)pv;
|
|
NumColors = NumDIBColors(lpbi);
|
|
|
|
if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
|
|
return (NumColors * sizeof(RGBTRIPLE));
|
|
else
|
|
return (NumColors * sizeof(RGBQUAD));
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// globals for PicsPageProc
|
|
|
|
//int xCursor, yCursor;
|
|
|
|
TCHAR szRMineIcon[] = TEXT("CLSID\\{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\DefaultIcon");
|
|
TCHAR szRNhbdIcon[] = TEXT("CLSID\\{208D2C60-3AEA-1069-A2D7-08002B30309D}\\DefaultIcon");
|
|
TCHAR szRTrashIcon[] = TEXT("CLSID\\{645FF040-5081-101B-9F08-00AA002F954E}\\DefaultIcon");
|
|
TCHAR szRMyDocsIcon[] = TEXT("CLSID\\{450D8FBA-AD25-11D0-98A8-0800361B1103}\\DefaultIcon");
|
|
TCHAR szCUMineIcon[] = TEXT("Software\\Classes\\CLSID\\{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\DefaultIcon");
|
|
TCHAR szCUNhbdIcon[] = TEXT("Software\\Classes\\CLSID\\{208D2C60-3AEA-1069-A2D7-08002B30309D}\\DefaultIcon");
|
|
TCHAR szCUTrashIcon[] = TEXT("Software\\Classes\\CLSID\\{645FF040-5081-101B-9F08-00AA002F954E}\\DefaultIcon");
|
|
TCHAR szCUMyDocsIcon[] = TEXT("Software\\Classes\\CLSID\\{450D8FBA-AD25-11D0-98A8-0800361B1103}\\DefaultIcon");
|
|
TCHAR szTrashFull[] = TEXT("full");
|
|
TCHAR szTrashEmpty[] = TEXT("empty");
|
|
|
|
INT_PTR FAR PASCAL PicsPageProc(hDlg, message, wParam, lParam)
|
|
HWND hDlg;
|
|
UINT message;
|
|
WPARAM wParam;
|
|
LPARAM lParam;
|
|
{
|
|
switch (message) {
|
|
|
|
// set up listbox, initial selection, etc.
|
|
case WM_INITDIALOG:
|
|
{ // var scope
|
|
extern FROST_SUBKEY fsRoot[]; // for theme file/registry keys
|
|
extern FROST_SUBKEY fsCUIcons[]; // for theme file/registry keys
|
|
extern TCHAR c_szSoftwareClassesFmt[]; // for NT reg path/keys.h
|
|
int iter;
|
|
int iRet;
|
|
HWND hText, hLBox;
|
|
RECT rText;
|
|
TCHAR szDispStr[MAX_STRLEN+1];
|
|
extern TCHAR szCP_DT[];
|
|
extern TCHAR szWP[];
|
|
extern TCHAR szDT[];
|
|
extern TCHAR szSS_Section[];
|
|
extern TCHAR szSS_Key[];
|
|
extern TCHAR szSS_File[];
|
|
TCHAR szNTReg[MAX_PATH];
|
|
|
|
//
|
|
// get metrics for drawitem size
|
|
hText = GetDlgItem(hDlg, TXT_FILENAME); // 12 dialog box units high
|
|
GetWindowRect(hText, (LPRECT)&rText);
|
|
iItemHeight = ((rText.bottom - rText.top) * 8) / 12; // dialog font height
|
|
xTextOffset = (iItemHeight * 3) / 2; // proportional spacing
|
|
Assert(iItemHeight > 0, TEXT("didn't get positive text height for preview listbox!\n"));
|
|
|
|
#if 0 // to do own drawing for wallpaper and scr saver?
|
|
// other metrics, etc.
|
|
xCursor = GetSystemMetrics(SM_CXCURSOR);
|
|
yCursor = GetSystemMetrics(SM_CYCURSOR);
|
|
//
|
|
// save away preview rect area
|
|
GetWindowRect(GetDlgItem(hDlg, RECT_PREVIEW), (LPRECT)&rPreview);
|
|
GetWindowRect(hDlg, (LPRECT)&rText);
|
|
OffsetRect((LPRECT)&rPreview, -rText.left, -rText.top);
|
|
DestroyWindow(GetDlgItem(hDlg, RECT_PREVIEW));
|
|
#endif
|
|
|
|
//
|
|
// init the listbox with combined strings
|
|
|
|
// init
|
|
hLBox = GetDlgItem(hDlg, LB_PICS);
|
|
|
|
// unlike the ptrs and snds, have to do each item by hand here
|
|
// since they are three different types (actually four ways of
|
|
// retrieving associated file
|
|
|
|
//
|
|
// WALLPAPER BITMAP
|
|
|
|
// get display string
|
|
LoadString(hInstApp, STR_PIC_WALL,
|
|
(LPTSTR)szDispStr, MAX_STRLEN);
|
|
// CPLs don't check for success on LoadString in INITDIALOG, so OK!?
|
|
|
|
// get filename if any
|
|
if (bThemed) { // get from theme
|
|
GetPrivateProfileString((LPTSTR)szCP_DT, (LPTSTR)szWP,
|
|
(LPTSTR)szNULL,
|
|
(LPTSTR)szMsg, MAX_MSGLEN,
|
|
(LPTSTR)szCurThemeFile);
|
|
// expand filename string as necessary
|
|
InstantiatePath((LPTSTR)szMsg, MAX_MSGLEN);
|
|
}
|
|
else { // get from system
|
|
// If ActiveDesktop is on we should query AD for this
|
|
// setting instead of reading from the registry.
|
|
if (IsActiveDesktopOn()) {
|
|
if (!GetADWallpaper(szMsg)) {
|
|
// Failed to read AD setting so get it from the registry
|
|
GetRegString(HKEY_CURRENT_USER, szCP_DT, szWP,
|
|
szNULL, szMsg, MAX_MSGLEN);
|
|
}
|
|
}
|
|
|
|
// ActiveDesktop is off so get the setting from the registry
|
|
else {
|
|
GetRegString(HKEY_CURRENT_USER, szCP_DT, szWP,
|
|
szNULL, szMsg, MAX_MSGLEN);
|
|
}
|
|
|
|
// If this isn't an HTM or HTML wallpaper file then we
|
|
// should extract the image title.
|
|
if ((lstrcmpi(FindExtension(szMsg), TEXT(".htm")) != 0) &&
|
|
(lstrcmpi(FindExtension(szMsg), TEXT(".html")) != 0)) {
|
|
|
|
// Not an HTM/L file so extract the image title
|
|
GetImageTitle(szMsg, szMsg, MAX_MSGLEN);
|
|
}
|
|
}
|
|
|
|
// combine strings into data string to load up in
|
|
// owner-draw hasstrings listbox!
|
|
CreateDataStr((LPTSTR)pValue, (LPTSTR)szDispStr, (LPTSTR)szMsg);
|
|
|
|
// now, finally, go ahead and assign string to listbox
|
|
SendMessage(hLBox, LB_ADDSTRING, 0, (LPARAM)(LPTSTR)pValue);
|
|
|
|
//
|
|
// MY COMPUTER ICON
|
|
|
|
LoadString(hInstApp, STR_PIC_MYCOMP,
|
|
(LPTSTR)szDispStr, MAX_STRLEN);
|
|
// CPLs don't check for success on LoadString in INITDIALOG, so OK!?
|
|
|
|
// get filename if any
|
|
if (bThemed) { // get from theme
|
|
// Get the CURRENT_USER My Computer icon setting
|
|
GetPrivateProfileString((LPTSTR)szCUMineIcon, (LPTSTR)FROST_DEFSTR,
|
|
(LPTSTR)szNULL,
|
|
(LPTSTR)szMsg, MAX_MSGLEN,
|
|
(LPTSTR)szCurThemeFile);
|
|
|
|
// If the string is NULL, try the "old" style Win95
|
|
// CLASSES_ROOT setting instead
|
|
if (!*szMsg) {
|
|
GetPrivateProfileString((LPTSTR)szRMineIcon,
|
|
(LPTSTR)FROST_DEFSTR,
|
|
(LPTSTR)szNULL,
|
|
(LPTSTR)szMsg, MAX_MSGLEN,
|
|
(LPTSTR)szCurThemeFile);
|
|
}
|
|
|
|
// expand filename string as necessary
|
|
InstantiatePath((LPTSTR)szMsg, MAX_MSGLEN);
|
|
}
|
|
else { // get from system
|
|
// First try reading from the appropriate CURRENT_USER
|
|
// section for this platform.
|
|
|
|
szMsg[0] = TEXT('\0');
|
|
|
|
if (IsPlatformNT())
|
|
{
|
|
lstrcpy(szNTReg, c_szSoftwareClassesFmt);
|
|
lstrcat(szNTReg, szRMineIcon);
|
|
HandGet(HKEY_CURRENT_USER,
|
|
(LPTSTR)szNTReg,
|
|
(LPTSTR)szNULL, // null string for default value
|
|
(LPTSTR)szMsg);
|
|
}
|
|
else // Not NT
|
|
{
|
|
HandGet(HKEY_CURRENT_USER,
|
|
(LPTSTR)szCUMineIcon,
|
|
(LPTSTR)szNULL, // null string for default value
|
|
(LPTSTR)szMsg);
|
|
}
|
|
|
|
// If we didn't get a good string from CURRENT_USER branch
|
|
// try the CLASSES_ROOT branch instead.
|
|
|
|
if (!*szMsg) {
|
|
HandGet(HKEY_CLASSES_ROOT,
|
|
(LPTSTR)szRMineIcon,
|
|
(LPTSTR)szNULL, // null string for default value
|
|
(LPTSTR)szMsg);
|
|
}
|
|
}
|
|
|
|
InstantiatePath((LPTSTR)szMsg, MAX_MSGLEN);
|
|
|
|
// combine strings into data string to load up in
|
|
// owner-draw hasstrings listbox!
|
|
CreateDataStr((LPTSTR)pValue, (LPTSTR)szDispStr, (LPTSTR)szMsg);
|
|
|
|
// now, finally, go ahead and assign string to listbox
|
|
SendMessage(hLBox, LB_ADDSTRING, 0, (LPARAM)(LPTSTR)pValue);
|
|
|
|
//
|
|
// NETWORK NHBD ICON
|
|
|
|
LoadString(hInstApp, STR_PIC_NETHOOD,
|
|
(LPTSTR)szDispStr, MAX_STRLEN);
|
|
// CPLs don't check for success on LoadString in INITDIALOG, so OK!?
|
|
|
|
// get filename if any
|
|
if (bThemed) { // get from theme
|
|
// Get the CURRENT_USER Net Neighborhood icon setting
|
|
GetPrivateProfileString((LPTSTR)szCUNhbdIcon, (LPTSTR)FROST_DEFSTR,
|
|
(LPTSTR)szNULL,
|
|
(LPTSTR)szMsg, MAX_MSGLEN,
|
|
(LPTSTR)szCurThemeFile);
|
|
|
|
// If the string is NULL, try the "old" style Win95
|
|
// CLASSES_ROOT setting instead
|
|
if (!*szMsg) {
|
|
GetPrivateProfileString((LPTSTR)szRNhbdIcon,
|
|
(LPTSTR)FROST_DEFSTR,
|
|
(LPTSTR)szNULL,
|
|
(LPTSTR)szMsg, MAX_MSGLEN,
|
|
(LPTSTR)szCurThemeFile);
|
|
}
|
|
|
|
// expand filename string as necessary
|
|
InstantiatePath((LPTSTR)szMsg, MAX_MSGLEN);
|
|
}
|
|
else { // get from system
|
|
// First try reading from the appropriate CURRENT_USER
|
|
// section for this platform.
|
|
szMsg[0] = TEXT('\0');
|
|
|
|
if (IsPlatformNT())
|
|
{
|
|
lstrcpy(szNTReg, c_szSoftwareClassesFmt);
|
|
lstrcat(szNTReg, szRNhbdIcon);
|
|
HandGet(HKEY_CURRENT_USER,
|
|
(LPTSTR)szNTReg,
|
|
(LPTSTR)szNULL, // null string for default value
|
|
(LPTSTR)szMsg);
|
|
}
|
|
else // Not NT
|
|
{
|
|
HandGet(HKEY_CURRENT_USER,
|
|
(LPTSTR)szCUNhbdIcon,
|
|
(LPTSTR)szNULL, // null string for default value
|
|
(LPTSTR)szMsg);
|
|
}
|
|
|
|
// If we didn't get a good string from CURRENT_USER branch
|
|
// try the CLASSES_ROOT branch instead.
|
|
|
|
if (!*szMsg) {
|
|
HandGet(HKEY_CLASSES_ROOT,
|
|
(LPTSTR)szRNhbdIcon,
|
|
(LPTSTR)szNULL, // null string for default value
|
|
(LPTSTR)szMsg);
|
|
}
|
|
}
|
|
|
|
InstantiatePath((LPTSTR)szMsg, MAX_MSGLEN);
|
|
|
|
// combine strings into data string to load up in
|
|
// owner-draw hasstrings listbox!
|
|
CreateDataStr((LPTSTR)pValue, (LPTSTR)szDispStr, (LPTSTR)szMsg);
|
|
|
|
// now, finally, go ahead and assign string to listbox
|
|
SendMessage(hLBox, LB_ADDSTRING, 0, (LPARAM)(LPTSTR)pValue);
|
|
|
|
//
|
|
// RECYCLE BIN FULL
|
|
|
|
LoadString(hInstApp, STR_PIC_RECBINFULL,
|
|
(LPTSTR)szDispStr, MAX_STRLEN);
|
|
// CPLs don't check for success on LoadString in INITDIALOG, so OK!?
|
|
|
|
// get filename if any
|
|
if (bThemed) { // get from theme
|
|
// Get the CURRENT_USER Recycle Bin Full icon setting
|
|
GetPrivateProfileString((LPTSTR)szCUTrashIcon, (LPTSTR)szTrashFull,
|
|
(LPTSTR)szNULL,
|
|
(LPTSTR)szMsg, MAX_MSGLEN,
|
|
(LPTSTR)szCurThemeFile);
|
|
|
|
// If the string is NULL, try the "old" style Win95
|
|
// CLASSES_ROOT setting instead
|
|
if (!*szMsg) {
|
|
GetPrivateProfileString((LPTSTR)szRTrashIcon,
|
|
(LPTSTR)szTrashFull,
|
|
(LPTSTR)szNULL,
|
|
(LPTSTR)szMsg, MAX_MSGLEN,
|
|
(LPTSTR)szCurThemeFile);
|
|
}
|
|
|
|
// expand filename string as necessary
|
|
InstantiatePath((LPTSTR)szMsg, MAX_MSGLEN);
|
|
}
|
|
else { // get from system
|
|
// First try reading from the appropriate CURRENT_USER
|
|
// section for this platform.
|
|
szMsg[0] = TEXT('\0');
|
|
|
|
if (IsPlatformNT())
|
|
{
|
|
lstrcpy(szNTReg, c_szSoftwareClassesFmt);
|
|
lstrcat(szNTReg, szRTrashIcon);
|
|
HandGet(HKEY_CURRENT_USER,
|
|
(LPTSTR)szNTReg,
|
|
(LPTSTR)szTrashFull,
|
|
(LPTSTR)szMsg);
|
|
}
|
|
else // Not NT
|
|
{
|
|
HandGet(HKEY_CURRENT_USER,
|
|
(LPTSTR)szCUTrashIcon,
|
|
(LPTSTR)szTrashFull,
|
|
(LPTSTR)szMsg);
|
|
}
|
|
|
|
// If we didn't get a good string from CURRENT_USER branch
|
|
// try the CLASSES_ROOT branch instead.
|
|
|
|
if (!*szMsg) {
|
|
HandGet(HKEY_CLASSES_ROOT,
|
|
(LPTSTR)szRTrashIcon,
|
|
(LPTSTR)szTrashFull,
|
|
(LPTSTR)szMsg);
|
|
}
|
|
}
|
|
|
|
InstantiatePath((LPTSTR)szMsg, MAX_MSGLEN);
|
|
|
|
// combine strings into data string to load up in
|
|
// owner-draw hasstrings listbox!
|
|
CreateDataStr((LPTSTR)pValue, (LPTSTR)szDispStr, (LPTSTR)szMsg);
|
|
|
|
// now, finally, go ahead and assign string to listbox
|
|
SendMessage(hLBox, LB_ADDSTRING, 0, (LPARAM)(LPTSTR)pValue);
|
|
|
|
//
|
|
// RECYCLE BIN EMPTY
|
|
|
|
LoadString(hInstApp, STR_PIC_RECBINEMPTY,
|
|
(LPTSTR)szDispStr, MAX_STRLEN);
|
|
// CPLs don't check for success on LoadString in INITDIALOG, so OK!?
|
|
|
|
// get filename if any
|
|
if (bThemed) { // get from theme
|
|
// Get the CURRENT_USER Recycle Bin Empty icon setting
|
|
GetPrivateProfileString((LPTSTR)szCUTrashIcon,
|
|
(LPTSTR)szTrashEmpty,
|
|
(LPTSTR)szNULL,
|
|
(LPTSTR)szMsg, MAX_MSGLEN,
|
|
(LPTSTR)szCurThemeFile);
|
|
|
|
// If the string is NULL, try the "old" style Win95
|
|
// CLASSES_ROOT setting instead
|
|
if (!*szMsg) {
|
|
GetPrivateProfileString((LPTSTR)szRTrashIcon,
|
|
(LPTSTR)szTrashEmpty,
|
|
(LPTSTR)szNULL,
|
|
(LPTSTR)szMsg, MAX_MSGLEN,
|
|
(LPTSTR)szCurThemeFile);
|
|
}
|
|
|
|
// expand filename string as necessary
|
|
InstantiatePath((LPTSTR)szMsg, MAX_MSGLEN);
|
|
}
|
|
else { // get from system
|
|
// First try reading from the appropriate CURRENT_USER
|
|
// section for this platform.
|
|
szMsg[0] = TEXT('\0');
|
|
|
|
if (IsPlatformNT())
|
|
{
|
|
lstrcpy(szNTReg, c_szSoftwareClassesFmt);
|
|
lstrcat(szNTReg, szRTrashIcon);
|
|
HandGet(HKEY_CURRENT_USER,
|
|
(LPTSTR)szNTReg,
|
|
(LPTSTR)szTrashEmpty,
|
|
(LPTSTR)szMsg);
|
|
}
|
|
else // Not NT
|
|
{
|
|
HandGet(HKEY_CURRENT_USER,
|
|
(LPTSTR)szCUTrashIcon,
|
|
(LPTSTR)szTrashEmpty,
|
|
(LPTSTR)szMsg);
|
|
}
|
|
|
|
// If we didn't get a good string from CURRENT_USER branch
|
|
// try the CLASSES_ROOT branch instead.
|
|
|
|
if (!*szMsg) {
|
|
HandGet(HKEY_CLASSES_ROOT,
|
|
(LPTSTR)szRTrashIcon,
|
|
(LPTSTR)szTrashEmpty,
|
|
(LPTSTR)szMsg);
|
|
}
|
|
}
|
|
|
|
InstantiatePath((LPTSTR)szMsg, MAX_MSGLEN);
|
|
|
|
// combine strings into data string to load up in
|
|
// owner-draw hasstrings listbox!
|
|
CreateDataStr((LPTSTR)pValue, (LPTSTR)szDispStr, (LPTSTR)szMsg);
|
|
|
|
// now, finally, go ahead and assign string to listbox
|
|
SendMessage(hLBox, LB_ADDSTRING, 0, (LPARAM)(LPTSTR)pValue);
|
|
|
|
//
|
|
// MY DOCUMENTS ICON
|
|
|
|
LoadString(hInstApp, STR_PIC_MYDOCS,
|
|
(LPTSTR)szDispStr, MAX_STRLEN);
|
|
// CPLs don't check for success on LoadString in INITDIALOG, so OK!?
|
|
|
|
// get filename if any
|
|
if (bThemed) { // get from theme
|
|
// Get the CURRENT_USER My Documetns icon setting
|
|
GetPrivateProfileString((LPTSTR)szCUMyDocsIcon, (LPTSTR)FROST_DEFSTR,
|
|
(LPTSTR)szNULL,
|
|
(LPTSTR)szMsg, MAX_MSGLEN,
|
|
(LPTSTR)szCurThemeFile);
|
|
|
|
// If the string is NULL, try the "old" style Win95
|
|
// CLASSES_ROOT setting instead
|
|
if (!*szMsg) {
|
|
GetPrivateProfileString((LPTSTR)szRMyDocsIcon,
|
|
(LPTSTR)FROST_DEFSTR,
|
|
(LPTSTR)szNULL,
|
|
(LPTSTR)szMsg, MAX_MSGLEN,
|
|
(LPTSTR)szCurThemeFile);
|
|
}
|
|
|
|
// expand filename string as necessary
|
|
InstantiatePath((LPTSTR)szMsg, MAX_MSGLEN);
|
|
}
|
|
else { // get from system
|
|
// First try reading from the appropriate CURRENT_USER
|
|
// section for this platform.
|
|
szMsg[0] = TEXT('\0');
|
|
|
|
if (IsPlatformNT())
|
|
{
|
|
lstrcpy(szNTReg, c_szSoftwareClassesFmt);
|
|
lstrcat(szNTReg, szRMyDocsIcon);
|
|
HandGet(HKEY_CURRENT_USER,
|
|
(LPTSTR)szNTReg,
|
|
(LPTSTR)szNULL, // null string for default value
|
|
(LPTSTR)szMsg);
|
|
}
|
|
else // Not NT
|
|
{
|
|
HandGet(HKEY_CURRENT_USER,
|
|
(LPTSTR)szCUMyDocsIcon,
|
|
(LPTSTR)szNULL, // null string for default value
|
|
(LPTSTR)szMsg);
|
|
}
|
|
|
|
// If we didn't get a good string from CURRENT_USER branch
|
|
// try the CLASSES_ROOT branch instead.
|
|
|
|
if (!*szMsg) {
|
|
HandGet(HKEY_CLASSES_ROOT,
|
|
(LPTSTR)szRMyDocsIcon,
|
|
(LPTSTR)szNULL, // null string for default value
|
|
(LPTSTR)szMsg);
|
|
}
|
|
}
|
|
|
|
InstantiatePath((LPTSTR)szMsg, MAX_MSGLEN);
|
|
|
|
// combine strings into data string to load up in
|
|
// owner-draw hasstrings listbox!
|
|
CreateDataStr((LPTSTR)pValue, (LPTSTR)szDispStr, (LPTSTR)szMsg);
|
|
|
|
// now, finally, go ahead and assign string to listbox
|
|
SendMessage(hLBox, LB_ADDSTRING, 0, (LPARAM)(LPTSTR)pValue);
|
|
|
|
//
|
|
// SCREEN SAVER
|
|
|
|
LoadString(hInstApp, STR_PIC_SCRSAV,
|
|
(LPTSTR)szDispStr, MAX_STRLEN);
|
|
// CPLs don't check for success on LoadString in INITDIALOG, so OK!?
|
|
|
|
// get filename if any
|
|
if (bThemed) { // get from theme
|
|
GetPrivateProfileString((LPTSTR)szSS_Section, (LPTSTR)szSS_Key,
|
|
(LPTSTR)szNULL,
|
|
(LPTSTR)szMsg, MAX_MSGLEN,
|
|
(LPTSTR)szCurThemeFile);
|
|
// expand filename string as necessary
|
|
InstantiatePath((LPTSTR)szMsg, MAX_MSGLEN);
|
|
|
|
// For NT with old (Plus95/98) theme files that refer to
|
|
// windows\system we should update string to say system32
|
|
if (IsPlatformNT()) ConfirmFile(szMsg, TRUE);
|
|
}
|
|
else { // get from system
|
|
GetPrivateProfileString((LPTSTR)szSS_Section, (LPTSTR)szSS_Key,
|
|
(LPTSTR)szNULL,
|
|
(LPTSTR)szMsg, MAX_MSGLEN,
|
|
(LPTSTR)szSS_File);
|
|
// make into nice long filename for display
|
|
if (FilenameToLong(szMsg, (LPTSTR)pValue))
|
|
lstrcpy(FileFromPath(szMsg), (LPTSTR)pValue);
|
|
}
|
|
|
|
// combine strings into data string to load up in
|
|
// owner-draw hasstrings listbox!
|
|
CreateDataStr((LPTSTR)pValue, (LPTSTR)szDispStr, (LPTSTR)szMsg);
|
|
|
|
// now, finally, go ahead and assign string to listbox
|
|
SendMessage(hLBox, LB_ADDSTRING, 0, (LPARAM)(LPTSTR)pValue);
|
|
|
|
//
|
|
// check them all for file existence. have to do here, no prev loop
|
|
//
|
|
for (iter = 0; iter < MAX_ETC_ITEMS; iter++) {
|
|
// get this item's listbox string
|
|
iRet = (int) SendMessage(hLBox, LB_GETTEXT, iter, (LPARAM)(LPTSTR)szMsg);
|
|
if (iRet == LB_ERR)
|
|
break; // past end of listbox items CONTINUE
|
|
|
|
// get the filename assoc with this item, if any
|
|
GetFileStr((LPTSTR)pValue, (LPTSTR)szMsg);
|
|
|
|
// store whether the file exists
|
|
bVisualExists[iter] = *pValue &&
|
|
(CF_NOTFOUND != ConfirmFile((LPTSTR)pValue, FALSE));
|
|
}
|
|
|
|
|
|
//
|
|
// setup initial focus conditions
|
|
SetFocus(hLBox);
|
|
SendMessage(hLBox, LB_SETCURSEL, 0, 0);
|
|
|
|
// need to ensure it gets initial update of cur file
|
|
PostMessage(hDlg, WM_COMMAND, MAKEWPARAM(LB_PICS, LBN_SELCHANGE),
|
|
MAKELPARAM(0, 0) );
|
|
|
|
} // var scope
|
|
break;
|
|
|
|
case WM_MEASUREITEM:
|
|
{
|
|
LPMEASUREITEMSTRUCT lpmis;
|
|
|
|
/* Set the height of the list box items. */
|
|
lpmis = (LPMEASUREITEMSTRUCT) lParam;
|
|
// lpmis->itemHeight = iItemHeight;
|
|
lpmis->itemHeight = 0; // DavidBa says they want these big default item hts
|
|
// Assert(iItemHeight > 0, TEXT("set non-positive item height for preview listbox!\n"));
|
|
// Assert(iItemHeight <= 0, TEXT("OK, set a positive item height for preview listbox!\n"));
|
|
}
|
|
break;
|
|
|
|
case WM_DRAWITEM:
|
|
{ // var scope
|
|
|
|
TEXTMETRIC tm;
|
|
LPDRAWITEMSTRUCT lpdis;
|
|
int yTextOffset;
|
|
LPTSTR lpszFile;
|
|
HDC hdcMem;
|
|
HBITMAP hbmpOld;
|
|
|
|
lpdis = (LPDRAWITEMSTRUCT) lParam;
|
|
|
|
/* If there are no list box items, skip this message. */
|
|
if (lpdis->itemID == -1) {
|
|
break;
|
|
} // jdk: well, what about focus rect in empty lbox?
|
|
|
|
//
|
|
// Inits
|
|
|
|
// get the filename assoc with this item, if any
|
|
SendMessage(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID,
|
|
(LPARAM)(LPTSTR)szMsg);
|
|
GetDisplayStr((LPTSTR)szMsg, (LPTSTR)szMsg); // Ok src and dst same
|
|
// you now have "displaystr\0filename" in szMsg[]
|
|
lpszFile = (LPTSTR)(szMsg + lstrlen((LPTSTR)szMsg) + 1);
|
|
|
|
//
|
|
// draw right background color
|
|
if (lpdis->itemState & ODS_SELECTED) {
|
|
|
|
// if item is selected, draw highlight background here
|
|
FillRect(lpdis->hDC, (LPRECT)&(lpdis->rcItem),
|
|
GetSysColorBrush(COLOR_HIGHLIGHT));
|
|
|
|
// set text color to highlight text
|
|
SetBkColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT));
|
|
SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
|
|
}
|
|
else { // not selected
|
|
// need to do normal background fill to undo prev selection
|
|
FillRect(lpdis->hDC, (LPRECT)&(lpdis->rcItem),
|
|
GetSysColorBrush(COLOR_WINDOW));
|
|
|
|
// set text color to foreground
|
|
SetBkColor(lpdis->hDC, GetSysColor(COLOR_WINDOW));
|
|
SetTextColor(lpdis->hDC, GetSysColor(COLOR_WINDOWTEXT));
|
|
}
|
|
|
|
// if there is a file associated with this item
|
|
if (*lpszFile) {
|
|
HBITMAP hbmpLeading;
|
|
BITMAP bmLeading;
|
|
|
|
//
|
|
// find the right leading bitmap: checkmark or question mark
|
|
if (bVisualExists[lpdis->itemID]) {
|
|
hbmpLeading = hbmpCheck;
|
|
bmLeading = bmCheck;
|
|
}
|
|
else {
|
|
hbmpLeading = hbmpQ;
|
|
bmLeading = bmQ;
|
|
}
|
|
|
|
//
|
|
// paint in the leading bitmap!
|
|
|
|
hdcMem = CreateCompatibleDC(lpdis->hDC);
|
|
if (hdcMem)
|
|
{
|
|
hbmpOld = SelectObject(hdcMem, hbmpLeading);
|
|
|
|
// if item height is less than bitmap height
|
|
if (lpdis->rcItem.bottom - lpdis->rcItem.top < bmLeading.bmHeight)
|
|
{
|
|
// stretch down bitmap size to fit
|
|
StretchBlt(lpdis->hDC,
|
|
lpdis->rcItem.left, lpdis->rcItem.top,
|
|
lpdis->rcItem.bottom - lpdis->rcItem.top, // width = height
|
|
lpdis->rcItem.bottom - lpdis->rcItem.top,
|
|
hdcMem, 0, 0, bmLeading.bmWidth, bmLeading.bmHeight, SRCCOPY);
|
|
}
|
|
else // item height taller than checkmark bitmap
|
|
{
|
|
// just center vertically
|
|
BitBlt(lpdis->hDC,
|
|
lpdis->rcItem.left,
|
|
lpdis->rcItem.top +
|
|
(lpdis->rcItem.bottom - lpdis->rcItem.top - bmLeading.bmHeight)/2,
|
|
bmLeading.bmWidth, bmLeading.bmHeight,
|
|
hdcMem, 0, 0, SRCCOPY);
|
|
}
|
|
|
|
SelectObject(hdcMem, hbmpOld);
|
|
DeleteDC(hdcMem);
|
|
}
|
|
|
|
// who cares
|
|
// Assert(lpdis->rcItem.bottom - lpdis->rcItem.top == iItemHeight,
|
|
// TEXT("MEASUREITEM and DRAWITEM have different heights!\n"));
|
|
}
|
|
|
|
//
|
|
// now draw the display string for this item
|
|
|
|
// figure y offset to vert center text in draw item
|
|
GetTextMetrics(lpdis->hDC, &tm);
|
|
yTextOffset = (lpdis->rcItem.bottom - lpdis->rcItem.top - tm.tmHeight) / 2;
|
|
Assert(yTextOffset >= 0, TEXT("negative text vert offset in DRAWITEM\n"));
|
|
if (yTextOffset < 0) yTextOffset = 0;
|
|
|
|
// do the out
|
|
SetBkMode(lpdis->hDC, TRANSPARENT);
|
|
TextOut(lpdis->hDC,
|
|
lpdis->rcItem.left + xTextOffset,
|
|
lpdis->rcItem.top + yTextOffset,
|
|
(LPTSTR)szMsg, lstrlen((LPTSTR)szMsg));
|
|
|
|
//
|
|
// if item is selected, draw a focus rect
|
|
if (lpdis->itemState & ODS_FOCUS) {
|
|
DrawFocusRect(lpdis->hDC, (LPRECT)&(lpdis->rcItem));
|
|
}
|
|
} // var scope
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch ((int)LOWORD(wParam)) {
|
|
case LB_PICS:
|
|
// if new selection in listbox
|
|
if (HIWORD(wParam) == LBN_SELCHANGE) {
|
|
int iSeln, ilen;
|
|
|
|
// get new selection if any
|
|
iSeln = (int)SendDlgItemMessage(hDlg, LB_PICS, LB_GETCURSEL, 0, 0);
|
|
if (LB_ERR == iSeln)
|
|
break; // no selection EXIT
|
|
|
|
// get selection text
|
|
SendDlgItemMessage(hDlg, LB_PICS, LB_GETTEXT,
|
|
(WPARAM)iSeln, (LPARAM)(LPTSTR)szMsg);
|
|
|
|
// update global current filename string
|
|
GetFileStr(szCurPreviewFile, szMsg);
|
|
|
|
// reset dialog static text of filename string
|
|
if (iSeln == SCRSAV_NDX) {
|
|
// if you can get a long filename, then use it
|
|
if (FilenameToLong((LPTSTR)szCurPreviewFile, (LPTSTR)szMsg))
|
|
lstrcpy(FileFromPath((LPTSTR)szCurPreviewFile), (LPTSTR)szMsg);
|
|
SetDlgItemFile(hDlg, TXT_FILENAME, szCurPreviewFile);
|
|
}
|
|
else
|
|
SetDlgItemFile(hDlg, TXT_FILENAME, szCurPreviewFile);
|
|
// and scroll end into view
|
|
ilen = lstrlen((LPTSTR)szCurPreviewFile);
|
|
SendDlgItemMessage(hDlg, TXT_FILENAME, EM_SETSEL,
|
|
(WPARAM)0, MAKELPARAM(-1, ilen));
|
|
|
|
//
|
|
// Update Image
|
|
//
|
|
|
|
// init by destroying old
|
|
if (hCurImage) DestroyCursor(hCurImage);
|
|
hCurImage = NULL;
|
|
|
|
// get new image...
|
|
if (*szCurPreviewFile) {
|
|
|
|
// ... unless the screen saver was selected
|
|
if (iSeln != SCRSAV_NDX) {
|
|
|
|
int index;
|
|
LPTSTR lpszIndex;
|
|
#ifdef UNICODE
|
|
char szTempA[10];
|
|
#endif
|
|
|
|
// load as icon; works for bmps too
|
|
|
|
// init: copy global filename to destructive-OK location
|
|
lstrcpy((LPTSTR)szMsg, (LPTSTR)szCurPreviewFile);
|
|
|
|
// may have index into file. format: "file,index"
|
|
lpszIndex = FindChar((LPTSTR)szMsg, TEXT(','));
|
|
if (*lpszIndex) { // if found a comma, then indexed icon
|
|
#ifdef UNICODE
|
|
wcstombs(szTempA, CharNext(lpszIndex), sizeof(szTempA));
|
|
index = latoi(szTempA);
|
|
#else
|
|
index = latoi(CharNext(lpszIndex));
|
|
#endif
|
|
*lpszIndex = 0; // got index then null term filename in szMsg
|
|
}
|
|
else { // just straight icon file or no index
|
|
index = 0;
|
|
}
|
|
|
|
// OK, now you can do the load!
|
|
ExtractPlusColorIcon(szMsg, index, &((HICON)hCurImage), 0, 0);
|
|
}
|
|
|
|
// else SCREEN SAVER: just leave hCurImage NULL for blank
|
|
}
|
|
|
|
// set image to static ctl, even if null: null clears prev
|
|
SendDlgItemMessage(hDlg, RECT_PREVIEW, STM_SETICON,
|
|
(WPARAM)hCurImage, (LPARAM)0);
|
|
|
|
// if it's the screen saver, then start up the preview
|
|
if (iSeln == SCRSAV_NDX) {
|
|
// TBA
|
|
}
|
|
|
|
#if 0 // this is when we painted the cursor by ourself
|
|
// force repaint of preview area
|
|
InvalidateRect(hDlg, (LPRECT)&rPreview, TRUE);
|
|
#endif
|
|
}
|
|
break;
|
|
|
|
// case PB_TEST:
|
|
// break;
|
|
}
|
|
break;
|
|
|
|
#if 0 // this is when we painted the cursor by ourself
|
|
case WM_PAINT:
|
|
BeginPaint(hDlg, &ps);
|
|
|
|
//
|
|
// preview area
|
|
DrawEdge(ps.hdc, (LPRECT)&rPreview, EDGE_SUNKEN, BF_RECT); // always edge
|
|
// if there's a file to preview
|
|
if (*szCurPreviewFile) {
|
|
// add the cursor
|
|
if (hCurCursor)
|
|
DrawIcon(ps.hdc,
|
|
rPreview.left + (rPreview.right-rPreview.left-xCursor)/2,
|
|
rPreview.top + (rPreview.bottom-rPreview.top-yCursor)/2,
|
|
hCurCursor);
|
|
}
|
|
|
|
EndPaint(hDlg, &ps);
|
|
break;
|
|
#endif
|
|
|
|
case WM_NOTIFY:
|
|
switch ( ((NMHDR FAR *)lParam)->code) {
|
|
|
|
// OK or Apply button pressed
|
|
case PSN_APPLY:
|
|
// apply any changes made on this page
|
|
|
|
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR); // accept changes
|
|
break;
|
|
|
|
// cancel button pressed
|
|
case PSN_RESET:
|
|
// don't accept any of the changes made on this page
|
|
break;
|
|
|
|
case PSN_SETACTIVE:
|
|
break;
|
|
case PSN_KILLACTIVE:
|
|
// need to say that it's OK by us to lose the activation
|
|
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, FALSE); // OK to kill focus now
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case WM_HELP:
|
|
{
|
|
LPHELPINFO lphi;
|
|
lphi = (LPHELPINFO)lParam;
|
|
if (lphi->iContextType == HELPINFO_WINDOW) {
|
|
WinHelp(lphi->hItemHandle, (LPTSTR)szHelpFile, HELP_WM_HELP,
|
|
(DWORD_PTR)((POPUP_HELP_ARRAY FAR *)phaPicsDlg));
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_CONTEXTMENU:
|
|
WinHelp((HWND)wParam, (LPTSTR)szHelpFile, HELP_CONTEXTMENU,
|
|
(DWORD_PTR)((POPUP_HELP_ARRAY FAR *)phaPicsDlg));
|
|
break;
|
|
|
|
default:
|
|
return(FALSE); // didn't process message
|
|
break;
|
|
}
|
|
|
|
return TRUE; // processed message
|
|
}
|
|
|
|
|
|
//
|
|
// CreateDataStr
|
|
// GetFileStr
|
|
// GetDisplayStr
|
|
//
|
|
// When initializing the owner-draw listbox in each of these dialogs,
|
|
// they are filled with strings of the form:
|
|
// displaystring;filename
|
|
// where "filename" is the associated full-path filename string AND CAN BE NULL
|
|
// and where "displaystring" is the string that appears in the listbox.
|
|
//
|
|
// CreateDataStr() puts the two pieces together into one string to store.
|
|
// The other two functions retrieve one of the pieces from the concatenated
|
|
// stored string.
|
|
//
|
|
|
|
TCHAR szSepStr[] = TEXT(";"); // separator character, as null-term str
|
|
|
|
// Input: file and display strings NON-DESTRUCTIVE TO INPUT
|
|
// Output: combined data string
|
|
void CreateDataStr(LPTSTR lpData, LPTSTR lpDisp, LPTSTR lpFile)
|
|
{
|
|
lstrcpy(lpData, lpDisp); // filename can be null
|
|
lstrcat(lpData, (LPTSTR)szSepStr);
|
|
lstrcat(lpData, lpFile);
|
|
}
|
|
|
|
// Input: combined data string NON-DESTRUCTIVE TO INPUT
|
|
// Output: display string
|
|
void GetDisplayStr(LPTSTR lpDisp, LPTSTR lpData)
|
|
{
|
|
LPTSTR lpScan, lpCopy;
|
|
|
|
// just do it all in a loop
|
|
for (lpScan = lpData, lpCopy = lpDisp;
|
|
*lpScan && // paranoid
|
|
(*lpScan != szSepStr[0]); // stop when you hit the sep char
|
|
lpScan++, lpCopy++) {
|
|
*lpCopy = *lpScan; // copy over chars one by one
|
|
}
|
|
|
|
// null term filename result to finish
|
|
*lpCopy = 0; // null filename yields lpDisp[0] = 0
|
|
}
|
|
|
|
// Input: combined data string NON-DESTRUCTIVE TO INPUT
|
|
// Output: file string
|
|
void GetFileStr(LPTSTR lpFile, LPTSTR lpData)
|
|
{
|
|
LPTSTR lpScan;
|
|
|
|
// just loop until you hit sep char
|
|
for (lpScan = lpData;
|
|
*lpScan && // paranoid
|
|
(*lpScan != szSepStr[0]); // stop when you hit the sep char
|
|
lpScan++) { } // do nothing
|
|
|
|
// now just take the rest of the string and return it
|
|
if (*lpScan) // paranoid
|
|
lstrcpy(lpFile, ++lpScan); // should never be nullstr, but that works too
|
|
else
|
|
*lpFile = 0; // 'impossible' error case
|
|
}
|
|
|
|
|
|
#ifdef FOOBAR
|
|
// Sets the dialog item to the path name as "prettied" by the shell.
|
|
// jdk 6/95: prev funtion just showed filename no path!
|
|
#endif
|
|
|
|
//
|
|
// SetDlgItemFile
|
|
//
|
|
// The whole point of these dialogs is to let the user see where the
|
|
// constituent resource files of a theme are, so we need to include the
|
|
// full pathnames. No reason not to pretty up the filename part, though.
|
|
//
|
|
// FUTURE: we can check here for indexed icon files, and make some
|
|
// more user-readable form of it.
|
|
// e.g. iconfile.dll,17 --> iconfile.dll [icon #17]
|
|
//
|
|
void PASCAL SetDlgItemFile(HWND hwnd, UINT DlgItem, LPCTSTR lpszPath)
|
|
{
|
|
TCHAR szFullPath[MAX_PATH+1];
|
|
TCHAR szPrettyFilename[MAX_PATH+1];
|
|
LPTSTR lpszFilename;
|
|
|
|
// inits
|
|
lstrcpy(szFullPath, lpszPath);
|
|
lpszFilename = FileFromPath(szFullPath);
|
|
|
|
// prettify via API if you can
|
|
if (*lpszPath != TEXT('\0')) {
|
|
// what does this do? it gives you the filename with the user's options
|
|
// e.g. Explorer View/Options Show/Don'tShow extensions
|
|
GetFileTitle(lpszPath, szPrettyFilename, ARRAYSIZE(szPrettyFilename));
|
|
lstrcpy(lpszFilename, szPrettyFilename);
|
|
}
|
|
|
|
// do it
|
|
SetDlgItemText(hwnd, DlgItem, szFullPath);
|
|
}
|