Tuesday, September 23, 2008

Saturday, September 20, 2008

Change MSI to run under custom actions under user account

MSI package generated by VS2008 will run custom actions under SYSTEM account. This "feature" was implemented to work around Vista's UAC.

There is no way to change this behavior from VS2008, but you can adjust MSI package using ORCA tool (available in SDK).

Start ORCA tool, open MSI package, navigate to custom actions. Select action which you would like to run under user account and subtract 0x800 from Type. In my case, value generated by VS2008 is 3090, new value should be 1042.

Save MSI back. Done

Saturday, September 13, 2008

Problem with 0.9.1031 and Silverlight1.0

0.9.1031 crashes when running with SL1.0. SL2.0 Beta2 works fine. If you run into this problem, you can either install SL1.0 or use MyDock0.9.1027

Tuesday, September 9, 2008

myDock 0.9.1031

New version of myDock is available on http://alexezh.googlepages.com

Monday, September 1, 2008

Sunday, August 31, 2008

pathgeometry vs mini language

http://www.farseergames.com/blog/post/Workaround-for-Accessing-PathGeometry-Data-in-Code.aspx

Sunday, August 24, 2008

using selectSingleNode for XAML

When using selectSingleNode to search XAML, it is required to set SelectionNamespace property with fake prefix. Here is an example

spDoc2->setProperty(CComBSTR(L"SelectionLanguage"), CComVariant(L"XPath"));
spDoc2->setProperty(CComBSTR(L"SelectionNamespaces"),
CComVariant("xmlns:d=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\""));

m_spDoc->selectSingleNode(CComBSTR(L"./d:Canvas"), &m_spRoot);

Thursday, July 24, 2008

MyDock has moved

MyDock download has moved from codeplex to http://alexezh.googlepages.com

Tuesday, July 22, 2008

MyDock 0.9.1027

New Features

* Added multimonitor support (first version, no configuration UI yet)
o To switch to the second monitor, add 1 to dock.xml and restart the dock.


Fixes

* Fixed refresh problem after screen resolution change
* Fixed memory leak (time will tell if this is the last one)
* Added delay for showing dock when new window is activated
* Fixed problem with context menus showing behind dock
* Updated visual for window manager dock
* Add hover indicator to tray menu

Monday, July 21, 2008

WebGadgets

After playing with Google desktop gadgets for a while, I decided to implement support for Web gadgets first. Much easier to do plus covers 90% of interesting functionality.

Yesterday got the first result; google clock is running on dashboard. Well, almost running, gadget size is wrong.

Tuesday, July 15, 2008

MyDock 0.9.1025

Lot's of updates and bug fixes.

Lately I am spending most of the time on implementing OSX style dashboard and support for google gadgets. Google or Vista sidebars take too much space on screen and provide constant distraction. Old style windows active desktop provides similar functionality, but it requires hiding all apps (which seems like a destructive action).

Last week mydock dashboard displayed the first picture. To be continued.

Sunday, May 11, 2008

MyDock 0.9.1009

Just posted the latest version of mydock to www.codeplex.com/mydock. The main new feature is limited support for system tray.

Saturday, April 19, 2008

open explorer at My Computer folder

ShellExecute(NULL,
L"explore",
L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}",
NULL,
NULL,
SW_SHOW);

Sunday, April 13, 2008

MyDock 0.9.1001

New release is available here. Main changes are

* Added quit button
* Use high-quality icons if available
* Bug fixes

Friday, April 11, 2008

Migrating dev related items to codeplex

Created a project for tracking items and releases on CodePlex. See MyDock On CodePlex for more details

Saturday, April 5, 2008

XMLDOM tricks

Add \r\n to the document when saving. Original info from Line breaks and IXMLDOMDocument

static LPCWSTR s_szFormatConfig = L""\
L" edit window is not XML friendly, see original post for details";

static HRESULT FormatConfig(IXMLDOMDocument * pInDoc, CComPtr & spOutDoc)
{
HRESULT hr = S_OK;
CComPtr spSS;
VARIANT_BOOL vbSuccess;

IFC(CoCreateInstance(__uuidof(DOMDocument60),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IXMLDOMDocument),
(void**)&spSS));

IFC(CoCreateInstance(__uuidof(DOMDocument60),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IXMLDOMDocument),
(void**)&spOutDoc));

spSS->put_resolveExternals(VARIANT_FALSE);
spSS->put_preserveWhiteSpace(VARIANT_TRUE);

spOutDoc->put_resolveExternals(VARIANT_FALSE);
spOutDoc->put_preserveWhiteSpace(VARIANT_TRUE);

//
// load SS from string
//
IFC(spSS->loadXML(CComBSTR(s_szFormatConfig), &vbSuccess));
if(vbSuccess != VARIANT_TRUE)
{
hr = E_FAIL;
goto Cleanup;
}

//
// convert
//
IFC(pInDoc->transformNodeToObject(spSS, CComVariant(spOutDoc)));

Cleanup:

return hr;
}

Convert document to UTF8

static HRESULT ForceUTF8(IXMLDOMDocument * pDoc)
{
HRESULT hr = S_OK;
CComPtr spPI;
CComPtr spOldPI;
CComPtr spOutOldPI;
CComPtr spChildren;

IFC(pDoc->createProcessingInstruction(L"xml", L"version=\"1.0\" encoding=\"UTF-8\"", &spPI));

IFC(pDoc->get_childNodes(&spChildren));

IFC(spChildren->get_item(0, &spOldPI));

IFC(pDoc->replaceChild( spPI, spOldPI, &spOutOldPI));

Cleanup:

return hr;
}

Friday, April 4, 2008

MyDock, 04-03-2007

Added window manager docklet. Window manager allow you to perform common operations on active window such as resize to half of screen, move to different monitor etc

Wednesday, April 2, 2008

MyDock home page

Just created a home page for MyDock.

TODO list

Some ideas for todo list

- OSX type Dashboard with SL2.0 applets
- Windows manager similar to vMax (in progress)
- Search box (similar to search in the start menu on Vista)
- Run docklet
- Hide windows taskbar
- Tray docklet
- Run as admin option

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