378 lines
8.1 KiB
C
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
|
|
}
|
|
}
|