Monday, March 31, 2008

MyDock, bug fixes

Minor bug fixes
- fix AV when closing application
- fix duplicated icons when starting mydock

Download from MyDock032107_1.zip
Last version of MyDock does not look very stable. Icons disappear from the dock from time to time
Number of updates
- Added initial version of drag&drop support both from shell and inside the dock. Now you can re-arrange docklets by dragging them
- Added configuration file for basic properties like docklet size. See dock_mini.xml for details. To use configuration, rename dock_mini.xml to dock.xml and copy it to either application directory or appdata directory
- Added key to hide / show the dock. Configurable through global config

As usual, download from
MyDock033107

Wednesday, March 26, 2008

mydock, 032607

New version. Changes
- Added tooltips
- Added mirror effect

MyDock032607

Tuesday, March 25, 2008

mydock, 03-25-2007

My clone of OS X dock. Requires SilverLight runtime to run.

I've been using ObjectDock for a while, but was always disappointed by lack of functionality compared to OS X dock.

Main difference is in the way how applications are handled by the dock. In OS X, same icon can be used to started pinned application or switch to it. If application is not pinned, clicking on icon activates the application. In ObjectDock, there are two types of icons; one for running windows and second for pinned apps. As a result, you might see two instances of the same icon.

To try mydock,
- download MyDock.zip unzip it to an empty folder
- run "mydock.exe".
- md5 hash for zip file is 3e57f216ce78920952207b34502d236e

Code is under active development. To be continued....

extract icon from exe

Code based on http://msdn2.microsoft.com/en-us/library/ms997538.aspx.

class CIconExtractor
{
public:
CIconExtractor()
: m_pImage(NULL)
{
}

HRESULT LoadIconFromApp(LPCWSTR pszFileName, CPngImage ** ppImage);

private:
CPngImage * m_pImage;

private:
static BOOL CALLBACK EnumIconProcInit(
HMODULE hModule,
LPCTSTR lpszType,
LPTSTR lpszName,
LONG_PTR lParam);

BOOL EnumIconProc(
HMODULE hModule,
LPCTSTR lpszType,
LPTSTR lpszName);

HRESULT GetResourceBytes(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, CAtlArray & arRes);
HRESULT LoadIconFromGroup(HMODULE hModule, CAtlArray & arRes);
};

///////////////////////////////////////////////////////////////////////////////
//
HRESULT CIconExtractor::LoadIconFromApp(LPCWSTR pszFileName, CPngImage ** ppImage)
{
HRESULT hr = S_OK;
HMODULE hExe; // handle to existing .EXE file
BOOL bRet;

// Load the .EXE file that contains an icon.
hExe = LoadLibraryEx(pszFileName, NULL, LOAD_LIBRARY_AS_DATAFILE);
if (hExe == NULL)
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto Cleanup;
}

bRet = EnumResourceNames(hExe, RT_GROUP_ICON, EnumIconProcInit, (LONG_PTR)(void*)this);

if(!m_pImage)
{
if(!bRet)
{

hr = HRESULT_FROM_WIN32(GetLastError());
}
else
{
hr = E_FAIL;
}

goto Cleanup;
}

*ppImage = m_pImage;
m_pImage = NULL;

Cleanup:

// Clean up.
if(hExe)
{
FreeLibrary(hExe);
}

if(m_pImage)
{
delete m_pImage;
m_pImage = NULL;
}

return hr;
}

BOOL CALLBACK CIconExtractor::EnumIconProcInit(
HMODULE hModule,
LPCTSTR lpszType,
LPTSTR lpszName,
LONG_PTR lParam)
{
CIconExtractor * pThis = (CIconExtractor*)lParam;
return pThis->EnumIconProc(hModule, lpszType, lpszName);
}

BOOL CIconExtractor::EnumIconProc(
HMODULE hModule,
LPCTSTR lpszType,
LPTSTR lpszName)
{
HRESULT hr = S_OK;
CAtlArray arResGroup;

IFC(GetResourceBytes(hModule, lpszType, lpszName, arResGroup));

IFC(LoadIconFromGroup(hModule, arResGroup));

Cleanup:

SetLastError(NO_ERROR);

return FALSE;
}

HRESULT CIconExtractor::GetResourceBytes(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, CAtlArray & arRes)
{
HRESULT hr = S_OK;
HGLOBAL hResLoad; // handle to loaded resource
HRSRC hRes; // handle/ptr. to res. info. in hExe
HANDLE hUpdateRes; // update resource handle
void *pbRes; // pointer to resource data
DWORD cbRes;

// Locate the icon resource in the .EXE file.
hRes = FindResource(hModule, lpszName, lpszType);
if (hRes == NULL)
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto Cleanup;
}

// Load the icon
hResLoad = LoadResource(hModule, hRes);
if (hResLoad == NULL)
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto Cleanup;
}

cbRes = SizeofResource(hModule, hRes);

// Lock the dialog box into global memory.
pbRes = LockResource(hResLoad);
if (pbRes == NULL)
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto Cleanup;
}

arRes.SetCount(cbRes);
CopyMemory(arRes.GetData(), pbRes, cbRes);

Cleanup:

return hr;
}

// descriptor for the icon group
#pragma pack( push )
#pragma pack( 2 )

typedef struct
{
BYTE bWidth; // Width, in pixels, of the image
BYTE bHeight; // Height, in pixels, of the image
BYTE bColorCount; // Number of colors in image (0 if >=8bpp)
BYTE bReserved; // Reserved
WORD wPlanes; // Color Planes
WORD wBitCount; // Bits per pixel
DWORD dwBytesInRes; // how many bytes in this resource?
WORD nID; // the ID
} GRPICONDIRENTRY, *LPGRPICONDIRENTRY;

typedef struct
{
WORD idReserved; // Reserved (must be 0)
WORD idType; // Resource type (1 for icons)
WORD idCount; // How many images?
GRPICONDIRENTRY idEntries[1]; // The entries for each image
} GRPICONDIR, *LPGRPICONDIR;

typedef struct
{
BYTE bWidth; // Width, in pixels, of the image
BYTE bHeight; // Height, in pixels, of the image
BYTE bColorCount; // Number of colors in image (0 if >=8bpp)
BYTE bReserved; // Reserved
WORD wPlanes; // Color Planes
WORD wBitCount; // Bits per pixel
DWORD dwBytesInRes; // how many bytes in this resource?
DWORD dwBytesOffset; // the ID
} ICONHEADER, *LPICONHEADER;


#pragma pack( pop )

HRESULT CIconExtractor::LoadIconFromGroup(HMODULE hModule, CAtlArray & arRes)
{
HRESULT hr = S_OK;
GRPICONDIR * pDir;
WORD i;
GRPICONDIRENTRY * pCur = NULL;
GRPICONDIRENTRY * pBest = NULL;
CAtlArray arIcon;
HICON hIcon = NULL;

if(arRes.GetCount() < sizeof(GRPICONDIR))
{
hr = E_FAIL;
goto Cleanup;
}

pDir = (GRPICONDIR *)(void*)arRes.GetData();
if(pDir->idCount < 1 || arRes.GetCount() < sizeof(GRPICONDIR) + (pDir->idCount - 1) * sizeof(GRPICONDIRENTRY))
{
hr = E_FAIL;
goto Cleanup;
}

//
// find best icon
//
pCur = pBest = &pDir->idEntries[0];
for(i = 0; i < pDir->idCount; i++)
{
pCur = &pDir->idEntries[i];

if(pCur->wBitCount > pBest->wBitCount)
{
pBest = pCur;
}
else if(pCur->bWidth > pBest->bWidth)
{
pBest = pCur;
}
}

//
// load best icon
//
IFC(GetResourceBytes(hModule, RT_ICON, MAKEINTRESOURCE(pBest->nID), arIcon));

hIcon = CreateIconFromResource(arIcon.GetData(), arIcon.GetCount(), TRUE, 0x00030000);
if(!hIcon)
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto Cleanup;
}

{
CMyImage WndImage;

if(pBest->wBitCount == 0x20)
{
CMyIcon::Load(arIcon.GetData(), arIcon.GetCount(), WndImage);
}
else
{
CIconToImageConverter cnv;

IFC(cnv.GetImage(hIcon, WndImage));

goto Cleanup;
}

m_pImage = new CPngImage;
if(m_pImage == NULL)
{
goto Cleanup;
}

m_pImage->Encode(WndImage);
}

Cleanup:

if(hIcon)
{
DestroyIcon(hIcon);
}

return hr;
}

Sunday, March 23, 2008

find location of installed application by app name

HRESULT hr = S_OK;
CComPtr spDocklet;
CRegKey rkAppPaths;
CRegKey rkApp;
WCHAR szPath[MAX_PATH];
ULONG cchPath;
CAtlString szAppPath;
LONG lRes;

lRes = rkAppPaths.Open(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths", KEY_READ);
if(lRes != ERROR_SUCCESS)
{
goto Cleanup;
}

lRes = rkApp.Open(rkAppPaths, pszApp);
if(lRes != ERROR_SUCCESS)
{
goto Cleanup;
}

cchPath = sizeof(szPath) / sizeof(WCHAR);
lRes = rkApp.QueryStringValue(L"Path", szPath, &cchPath);
if(lRes != ERROR_SUCCESS)
{
goto Cleanup;
}

szAppPath.Format(L"%s%s", szPath, pszApp);

Tuesday, March 18, 2008