windows-nt/Source/XPSP1/NT/shell/osshell/accesory/packager/icon.c
2020-09-26 16:20:57 +08:00

378 lines
8.1 KiB
C

/* icon.c - Handles Icon + Caption objects.
*/
#include "packager.h"
#include <shellapi.h>
// #include <shlapip.h>
static LPIC IconCreate(VOID);
void GetDisplayName(LPSTR szName, LPCSTR szPath);
/* IconClone() -
*
* Clones an appearance pane icon.
*/
LPIC
IconClone(
LPIC lpic
)
{
LPIC lpicNew;
if (lpicNew = IconCreate())
{
// Get the icon
StringCchCopy(lpicNew->szIconPath, ARRAYSIZE(lpicNew->szIconPath), lpic->szIconPath);
lpicNew->iDlgIcon = lpic->iDlgIcon;
GetCurrentIcon(lpicNew);
// Get the icon text
StringCchCopy(lpicNew->szIconText, ARRAYSIZE(lpicNew->szIconText), lpic->szIconText);
}
return lpicNew;
}
/* IconCreate() -
*/
static LPIC
IconCreate(
VOID
)
{
HANDLE hdata = NULL;
LPIC lpic = NULL;
if (!(hdata = GlobalAlloc(GMEM_MOVEABLE, sizeof(IC)))
|| !(lpic = (LPIC)GlobalLock(hdata)))
goto errRtn;
// Store the data in the window itself
lpic->hdata = hdata;
lpic->hDlgIcon = NULL;
lpic->iDlgIcon = 0;
*lpic->szIconPath = 0;
*lpic->szIconText = 0;
return lpic;
errRtn:
ErrorMessage(E_FAILED_TO_CREATE_CHILD_WINDOW);
if (lpic)
GlobalUnlock(hdata);
if (hdata)
GlobalFree(hdata);
return NULL;
}
/* IconCreateFromFile() -
*
* Allows an appearance pane icon to be created automatically if
* a file is dropped, imported, or pasted into the packager.
*/
LPIC
IconCreateFromFile(
LPSTR lpstrFile
)
{
LPIC lpic;
if (lpic = IconCreate())
{
// Get the icon
StringCchCopy(lpic->szIconPath, ARRAYSIZE(lpic->szIconPath), lpstrFile);
lpic->iDlgIcon = 0;
if (*(lpic->szIconPath))
GetCurrentIcon(lpic);
// Get the icon text
GetDisplayName(lpic->szIconText, lpstrFile);
}
return lpic;
}
/* IconCreateFromObject() -
*
* Allows an appearance pane icon to be created automatically if an
* OLE object is dropped into the appearance pane.
*/
LPIC
IconCreateFromObject(
LPOLEOBJECT lpObject
)
{
DWORD otObject;
HANDLE hdata;
LPIC lpic = NULL;
LPSTR lpdata;
OleQueryType(lpObject, &otObject);
if ((otObject == OT_LINK
&& Error(OleGetData(lpObject, gcfLink, &hdata)))
|| (otObject == OT_EMBEDDED
&& Error(OleGetData(lpObject, gcfOwnerLink, &hdata))))
hdata = NULL;
if (hdata && (lpdata = GlobalLock(hdata)))
{
if (lpic = IconCreate())
{
// Get the icon
RegGetExeName(lpic->szIconPath, lpdata, CBPATHMAX);
lpic->iDlgIcon = 0;
GetCurrentIcon(lpic);
// Get the icon text
switch (otObject)
{
case OT_LINK:
while (*lpdata++)
;
StringCchCopy(lpic->szIconText, ARRAYSIZE(lpic->szIconText), lpdata);
Normalize(lpic->szIconText);
break;
case OT_EMBEDDED:
RegGetClassId(lpic->szIconText, ARRAYSIZE(lpic->szIconText), lpdata);
break;
}
GlobalUnlock(hdata);
}
}
return lpic;
}
/* IconDelete() - Used to clear the appearance pane of icon stuff.
*/
VOID
IconDelete(
LPIC lpic
)
{
HANDLE hdata;
if (!lpic)
return;
if (lpic->hDlgIcon)
DestroyIcon(lpic->hDlgIcon);
GlobalUnlock(hdata = lpic->hdata);
GlobalFree(hdata);
}
/* IconDraw() - Used to draw the icon and its caption.
*/
VOID
IconDraw(
LPIC lpic,
HDC hdc,
LPRECT lprc,
BOOL fFocus,
INT cxImage,
INT cyImage
)
{
BOOL fMF;
HFONT hfont = NULL;
RECT rcText;
DWORD dwLayout;
hfont = SelectObject(hdc, ghfontTitle);
if (!(fMF = (cxImage && cyImage)))
{
// Figure out how large the text region will be
if (*(lpic->szIconText))
{
SetRect(&rcText, 0, 0, gcxArrange - 1, gcyArrange - 1);
DrawText(hdc, lpic->szIconText, -1, &rcText,
DT_CALCRECT | DT_WORDBREAK | DT_NOPREFIX | DT_SINGLELINE);
}
else
{
SetRect(&rcText, 0, 0, 0, 0);
}
// Figure out the image dimensions
cxImage = (gcxIcon > rcText.right) ? gcxIcon : rcText.right;
cyImage = gcyIcon + rcText.bottom;
}
// Draw the icon
if (lpic->hDlgIcon)
{
// Do not mirror the Icon.
dwLayout = GetLayout(hdc);
if ((dwLayout != GDI_ERROR) && (dwLayout & LAYOUT_RTL)) {
SetLayout(hdc, dwLayout | LAYOUT_BITMAPORIENTATIONPRESERVED);
}
DrawIcon(hdc, (lprc->left + lprc->right - gcxIcon) / 2,
(lprc->top + lprc->bottom - cyImage) / 2, lpic->hDlgIcon);
if ((dwLayout != GDI_ERROR) && (dwLayout & LAYOUT_RTL)) {
SetLayout(hdc, dwLayout);
}
}
// Draw the icon text
if (*(lpic->szIconText))
{
if (fMF)
{
SetBkMode(hdc, TRANSPARENT);
SetTextAlign(hdc, TA_CENTER);
TextOut(hdc, cxImage / 2, gcyIcon + 1, lpic->szIconText,
lstrlen(lpic->szIconText));
}
else
{
OffsetRect(&rcText, (lprc->left + lprc->right - cxImage) / 2,
(lprc->top + lprc->bottom - cyImage) / 2 + gcyIcon);
DrawText(hdc, lpic->szIconText, -1, &rcText,
DT_CENTER | DT_WORDBREAK | DT_NOPREFIX | DT_SINGLELINE);
}
}
if (hfont)
SelectObject(hdc, hfont);
if (fFocus && cxImage && cyImage)
{
RECT rcFocus;
SetRect(&rcFocus, (lprc->left + lprc->right - cxImage) / 2, (lprc->top +
lprc->bottom - cyImage) / 2, (lprc->left + lprc->right + cxImage) /
2, (lprc->top + lprc->bottom + cyImage) / 2);
DrawFocusRect(hdc, &rcFocus);
}
}
/* IconReadFromNative() - Used to retrieve the icon object from memory.
*/
LPIC
IconReadFromNative(
LPSTR *lplpstr
)
{
LPIC lpic;
WORD w;
if (lpic = IconCreate())
{
StringCchCopy(lpic->szIconText, ARRAYSIZE(lpic->szIconText), *lplpstr);
*lplpstr += lstrlen(lpic->szIconText) + 1;
StringCchCopy(lpic->szIconPath, ARRAYSIZE(lpic->szIconPath), *lplpstr);
*lplpstr += lstrlen(lpic->szIconPath) + 1;
MemRead(lplpstr, (LPSTR)&w, sizeof(WORD));
lpic->iDlgIcon = (INT)w;
GetCurrentIcon(lpic);
}
return lpic;
}
/* IconWriteToNative() - Used to write the icon object to memory.
*/
DWORD
IconWriteToNative(
LPIC lpic,
LPSTR *lplpstr
)
{
DWORD cBytes;
WORD w;
if (lplpstr)
{
// Now, write out the icon text and the icon
cBytes = lstrlen(lpic->szIconText) + 1;
MemWrite(lplpstr, (LPSTR)lpic->szIconText, cBytes);
cBytes = lstrlen(lpic->szIconPath) + 1;
MemWrite(lplpstr, (LPSTR)lpic->szIconPath, cBytes);
w = (WORD)lpic->iDlgIcon;
MemWrite(lplpstr, (LPSTR)&w, sizeof(WORD));
}
return (lstrlen(lpic->szIconText) + 1 + lstrlen(lpic->szIconPath) + 1 +
sizeof(WORD));
}
VOID
GetCurrentIcon(
LPIC lpic
)
{
WORD wIcon = (WORD)lpic->iDlgIcon;
if (lpic->hDlgIcon)
DestroyIcon(lpic->hDlgIcon);
if (!(lpic->hDlgIcon = ExtractAssociatedIcon(ghInst, lpic->szIconPath,
&wIcon)))
lpic->hDlgIcon = LoadIcon(ghInst, MAKEINTRESOURCE(ID_APPLICATION));
}
//
// get the nice name to show to the user given a filename
//
// FEATURE: we realy should just call the shell!!!
//
void GetDisplayName(LPSTR szName, LPCSTR szPath)
{
WIN32_FIND_DATA fd;
HANDLE h;
BOOL IsLFN;
StringCchCopy(szName, MAX_PATH, szPath); // verified
h = FindFirstFile(szPath, &fd);
if (h != INVALID_HANDLE_VALUE)
{
FindClose(h);
StringCchCopy(szName, MAX_PATH, fd.cFileName);
IsLFN = !(fd.cAlternateFileName[0] == 0 ||
lstrcmp(fd.cFileName, fd.cAlternateFileName) == 0);
if (!IsLFN)
{
AnsiLower(szName);
AnsiUpperBuff(szName, 1);
}
}
else
{
Normalize(szName); // strip path part
}
}