Changeset 15e06263b278…
Parent 67b9a44982a6…
by
Changes to 15 files · Browse files at 15e06263b278 Showing diff from parent 67b9a44982a6 Diff from another changeset...
|
@@ -5,10 +5,9 @@ #include "Thgstatus.h"
#include "Winstat.h"
#include "InitStatus.h"
+#include "SysInfo.h"
#include "ShellExt.h"
-
#include "CShellExtCMenu.h"
-
#include <map>
@@ -231,17 +230,35 @@ mi.wID = idCmd;
mi.fType = MFT_STRING;
- HICON h = GetTortoiseIcon(iconName);
- if (h)
+ if (SysInfo::Instance().IsVistaOrLater())
{
- mi.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_BITMAP | MIIM_DATA;
- mi.dwItemData = (ULONG_PTR) h;
- mi.hbmpItem = HBMMENU_CALLBACK;
+ TDEBUG_TRACE(" InsertMenuItemWithIcon1: Vista or later detected, using modern context menu style");
+ HBITMAP hBmp = GetTortoiseIconBitmap(iconName);
+ if (hBmp)
+ {
+ mi.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_BITMAP;
+ mi.hbmpItem = hBmp;
+ }
+ else
+ {
+ TDEBUG_TRACE(" InsertMenuItemWithIcon1: can't find " + iconName);
+ mi.fMask = MIIM_TYPE | MIIM_ID;
+ }
}
else
{
- TDEBUG_TRACE(" InsertMenuItemWithIcon1: can't find " + iconName);
- mi.fMask = MIIM_TYPE | MIIM_ID;
+ HICON h = GetTortoiseIcon(iconName);
+ if (h)
+ {
+ mi.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_BITMAP | MIIM_DATA;
+ mi.dwItemData = (ULONG_PTR) h;
+ mi.hbmpItem = HBMMENU_CALLBACK;
+ }
+ else
+ {
+ TDEBUG_TRACE(" InsertMenuItemWithIcon1: can't find " + iconName);
+ mi.fMask = MIIM_TYPE | MIIM_ID;
+ }
}
InsertMenuItemW(hMenu, indexMenu, TRUE, &mi);
@@ -257,24 +274,43 @@ MENUITEMINFOW mi;
memset(&mi, 0, sizeof(mi));
mi.cbSize = sizeof(mi);
- mi.fMask = MIIM_SUBMENU | MIIM_STRING | MIIM_ID;
mi.fType = MFT_STRING;
mi.dwTypeData = const_cast<wchar_t*>(menuText.c_str());
mi.cch = static_cast<UINT>(menuText.length());
mi.wID = idCmd;
mi.hSubMenu = hSubMenu;
- HICON h = GetTortoiseIcon(iconName);
- if (h)
+
+ if (SysInfo::Instance().IsVistaOrLater())
{
- mi.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_SUBMENU | MIIM_ID |
- MIIM_BITMAP | MIIM_DATA;
- mi.dwItemData = (ULONG_PTR) h;
- mi.hbmpItem = HBMMENU_CALLBACK;
+ TDEBUG_TRACE(" InsertMenuItemWithIcon1: Vista or later detected, using modern context menu style");
+ HBITMAP hBmp = GetTortoiseIconBitmap(iconName);
+ if (hBmp)
+ {
+ mi.fMask = MIIM_SUBMENU | MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_BITMAP;
+ mi.hbmpItem = hBmp;
+ }
+ else
+ {
+ TDEBUG_TRACE(" InsertSubMenuItemWithIcon2: can't find " + iconName);
+ mi.fMask = MIIM_TYPE | MIIM_ID;
+ }
}
else
{
- TDEBUG_TRACE(" InsertSubMenuItemWithIcon2: can't find " + iconName);
+ HICON h = GetTortoiseIcon(iconName);
+ if (h)
+ {
+ mi.fMask = MIIM_SUBMENU | MIIM_STRING | MIIM_ID;
+ mi.dwItemData = (ULONG_PTR) h;
+ mi.hbmpItem = HBMMENU_CALLBACK;
+ }
+ else
+ {
+ TDEBUG_TRACE(" InsertSubMenuItemWithIcon2: can't find " + iconName);
+ mi.fMask = MIIM_TYPE | MIIM_ID;
+ }
}
+
InsertMenuItemW(hMenu, indexMenu, TRUE, &mi);
TDEBUG_TRACEW(
@@ -445,6 +481,19 @@ }
if (isSeparator && indexSubMenu > 0)
RemoveMenu(hSubMenu, indexSubMenu - 1, MF_BYPOSITION);
+
+ if (SysInfo::Instance().IsVistaOrLater())
+ {
+ MENUINFO MenuInfo;
+
+ memset(&MenuInfo, 0, sizeof(MenuInfo));
+
+ MenuInfo.cbSize = sizeof(MenuInfo);
+ MenuInfo.fMask = MIM_STYLE | MIM_APPLYTOSUBMENUS;
+ MenuInfo.dwStyle = MNS_CHECKORBMP;
+
+ SetMenuInfo(hSubMenu, &MenuInfo);
+ }
}
TDEBUG_TRACE(" CShellExtCMenu::QueryContextMenu: adding main THG menu");
@@ -454,6 +503,20 @@ InsertMenu(hMenu, indexMenu++, MF_SEPARATOR | MF_BYPOSITION, 0, NULL);
InitStatus::check();
+
+ if (SysInfo::Instance().IsVistaOrLater())
+ {
+ MENUINFO MenuInfo;
+
+ memset(&MenuInfo, 0, sizeof(MenuInfo));
+
+ MenuInfo.cbSize = sizeof(MenuInfo);
+ MenuInfo.fMask = MIM_STYLE | MIM_APPLYTOSUBMENUS;
+ MenuInfo.dwStyle = MNS_CHECKORBMP;
+
+ SetMenuInfo(hMenu, &MenuInfo);
+ }
+
return ResultFromShort(idCmd - idCmdFirst);
}
|
|
|
@@ -0,0 +1,284 @@ + // TortoiseSVN - a Windows shell extension for easy version control
+
+// Copyright (C) 2009 - TortoiseSVN
+
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+// Adapted for use in TortoiseHg by Veniamin Albaev
+//
+#include "stdafx.h"
+#include "IconBitmapUtils.h"
+#include "SysInfo.h"
+#include "registry.h"
+
+IconBitmapUtils::IconBitmapUtils()
+ : hUxTheme(NULL)
+{
+ if (SysInfo::Instance().IsVistaOrLater())
+ {
+ hUxTheme = LoadLibrary(_T("UXTHEME.DLL"));
+
+ if (hUxTheme)
+ {
+ pfnGetBufferedPaintBits = (FN_GetBufferedPaintBits)::GetProcAddress(hUxTheme, "GetBufferedPaintBits");
+ pfnBeginBufferedPaint = (FN_BeginBufferedPaint)::GetProcAddress(hUxTheme, "BeginBufferedPaint");
+ pfnEndBufferedPaint = (FN_EndBufferedPaint)::GetProcAddress(hUxTheme, "EndBufferedPaint");
+ }
+ }
+}
+
+IconBitmapUtils::~IconBitmapUtils()
+{
+ if (hUxTheme)
+ FreeLibrary(hUxTheme);
+}
+
+HBITMAP IconBitmapUtils::IconToBitmap(HICON hIcon)
+{
+ if (!hIcon)
+ return NULL;
+
+ RECT rect;
+
+ rect.right = ::GetSystemMetrics(SM_CXMENUCHECK);
+ rect.bottom = ::GetSystemMetrics(SM_CYMENUCHECK);
+
+ rect.left = rect.top = 0;
+
+ HWND desktop = ::GetDesktopWindow();
+ if (desktop == NULL)
+ return NULL;
+
+ HDC screen_dev = ::GetDC(desktop);
+ if (screen_dev == NULL)
+ return NULL;
+
+ // Create a compatible DC
+ HDC dst_hdc = ::CreateCompatibleDC(screen_dev);
+ if (dst_hdc == NULL)
+ {
+ ::ReleaseDC(desktop, screen_dev);
+ return NULL;
+ }
+
+ // Create a new bitmap of icon size
+ HBITMAP bmp = ::CreateCompatibleBitmap(screen_dev, rect.right, rect.bottom);
+ if (bmp == NULL)
+ {
+ ::DeleteDC(dst_hdc);
+ ::ReleaseDC(desktop, screen_dev);
+ return NULL;
+ }
+
+ // Select it into the compatible DC
+ HBITMAP old_dst_bmp = (HBITMAP)::SelectObject(dst_hdc, bmp);
+ if (old_dst_bmp == NULL)
+ return NULL;
+
+ // Fill the background of the compatible DC with the white color
+ // that is taken by menu routines as transparent
+ ::SetBkColor(dst_hdc, RGB(255, 255, 255));
+ ::ExtTextOut(dst_hdc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
+
+ // Draw the icon into the compatible DC
+ ::DrawIconEx(dst_hdc, 0, 0, hIcon, rect.right, rect.bottom, 0, NULL, DI_NORMAL);
+
+ // Restore settings
+ ::SelectObject(dst_hdc, old_dst_bmp);
+ ::DeleteDC(dst_hdc);
+ ::ReleaseDC(desktop, screen_dev);
+
+ return bmp;
+}
+
+HBITMAP IconBitmapUtils::IconToBitmapPARGB32(HICON hIcon)
+{
+ if (!hIcon)
+ return NULL;
+
+ if (pfnBeginBufferedPaint == NULL || pfnEndBufferedPaint == NULL || pfnGetBufferedPaintBits == NULL)
+ {
+ TDEBUG_TRACE(" IconBitmapUtils::IconToBitmapPARGB32: Theme functions not found, returns NULL");
+ return NULL;
+ }
+
+ SIZE sizIcon;
+ sizIcon.cx = GetSystemMetrics(SM_CXSMICON);
+ sizIcon.cy = GetSystemMetrics(SM_CYSMICON);
+
+ RECT rcIcon;
+ SetRect(&rcIcon, 0, 0, sizIcon.cx, sizIcon.cy);
+ HBITMAP hBmp = NULL;
+
+ HDC hdcDest = CreateCompatibleDC(NULL);
+ if (hdcDest)
+ {
+ if (SUCCEEDED(Create32BitHBITMAP(hdcDest, &sizIcon, NULL, &hBmp)))
+ {
+ HBITMAP hbmpOld = (HBITMAP)SelectObject(hdcDest, hBmp);
+ if (hbmpOld)
+ {
+ BLENDFUNCTION bfAlpha = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
+ BP_PAINTPARAMS paintParams = {0};
+ paintParams.cbSize = sizeof(paintParams);
+ paintParams.dwFlags = BPPF_ERASE;
+ paintParams.pBlendFunction = &bfAlpha;
+
+ HDC hdcBuffer;
+ HPAINTBUFFER hPaintBuffer = pfnBeginBufferedPaint(hdcDest, &rcIcon, BPBF_DIB, &paintParams, &hdcBuffer);
+ if (hPaintBuffer)
+ {
+ if (DrawIconEx(hdcBuffer, 0, 0, hIcon, sizIcon.cx, sizIcon.cy, 0, NULL, DI_NORMAL))
+ //if (FillRect(hdcBuffer, &rcIcon, (HBRUSH) (0x000000FF)) != 0)
+ {
+ // If icon did not have an alpha channel we need to convert buffer to PARGB
+ ConvertBufferToPARGB32(hPaintBuffer, hdcDest, hIcon, sizIcon);
+ }
+ // This will write the buffer contents to the destination bitmap
+ pfnEndBufferedPaint(hPaintBuffer, TRUE);
+ }
+
+ SelectObject(hdcDest, hbmpOld);
+ }
+ }
+
+ DeleteDC(hdcDest);
+ }
+
+ return hBmp;
+}
+
+HRESULT IconBitmapUtils::Create32BitHBITMAP(HDC hdc, const SIZE *psize, __deref_opt_out void **ppvBits, __out HBITMAP* phBmp)
+{
+ *phBmp = NULL;
+
+ BITMAPINFO bmi;
+ SecureZeroMemory(&bmi, sizeof(bmi));
+ bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmi.bmiHeader.biPlanes = 1;
+ bmi.bmiHeader.biCompression = BI_RGB;
+
+ bmi.bmiHeader.biWidth = psize->cx;
+ bmi.bmiHeader.biHeight = psize->cy;
+ bmi.bmiHeader.biBitCount = 32;
+
+ HDC hdcUsed = hdc ? hdc : GetDC(NULL);
+ if (hdcUsed)
+ {
+ *phBmp = CreateDIBSection(hdcUsed, &bmi, DIB_RGB_COLORS, ppvBits, NULL, 0);
+ if (hdc != hdcUsed)
+ {
+ ReleaseDC(NULL, hdcUsed);
+ }
+ }
+ return (NULL == *phBmp) ? E_OUTOFMEMORY : S_OK;
+}
+
+HRESULT IconBitmapUtils::ConvertBufferToPARGB32(HPAINTBUFFER hPaintBuffer, HDC hdc, HICON hicon, SIZE& sizIcon)
+{
+ RGBQUAD *prgbQuad;
+ int cxRow;
+ HRESULT hr = pfnGetBufferedPaintBits(hPaintBuffer, &prgbQuad, &cxRow);
+ if (SUCCEEDED(hr))
+ {
+ Gdiplus::ARGB *pargb = reinterpret_cast<Gdiplus::ARGB *>(prgbQuad);
+ if (!HasAlpha(pargb, sizIcon, cxRow))
+ {
+ ICONINFO info;
+ if (GetIconInfo(hicon, &info))
+ {
+ if (info.hbmMask)
+ {
+ hr = ConvertToPARGB32(hdc, pargb, info.hbmMask, sizIcon, cxRow);
+ }
+
+ DeleteObject(info.hbmColor);
+ DeleteObject(info.hbmMask);
+ }
+ }
+ }
+
+ return hr;
+}
+
+bool IconBitmapUtils::HasAlpha(__in Gdiplus::ARGB *pargb, SIZE& sizImage, int cxRow)
+{
+ ULONG cxDelta = cxRow - sizImage.cx;
+ for (ULONG y = sizImage.cy; y; --y)
+ {
+ for (ULONG x = sizImage.cx; x; --x)
+ {
+ if (*pargb++ & 0xFF000000)
+ {
+ return true;
+ }
+ }
+
+ pargb += cxDelta;
+ }
+
+ return false;
+}
+
+HRESULT IconBitmapUtils::ConvertToPARGB32(HDC hdc, __inout Gdiplus::ARGB *pargb, HBITMAP hbmp, SIZE& sizImage, int cxRow)
+{
+ BITMAPINFO bmi;
+ SecureZeroMemory(&bmi, sizeof(bmi));
+ bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmi.bmiHeader.biPlanes = 1;
+ bmi.bmiHeader.biCompression = BI_RGB;
+
+ bmi.bmiHeader.biWidth = sizImage.cx;
+ bmi.bmiHeader.biHeight = sizImage.cy;
+ bmi.bmiHeader.biBitCount = 32;
+
+ HRESULT hr = E_OUTOFMEMORY;
+ HANDLE hHeap = GetProcessHeap();
+ void *pvBits = HeapAlloc(hHeap, 0, bmi.bmiHeader.biWidth * 4 * bmi.bmiHeader.biHeight);
+ if (pvBits)
+ {
+ hr = E_UNEXPECTED;
+ if (GetDIBits(hdc, hbmp, 0, bmi.bmiHeader.biHeight, pvBits, &bmi, DIB_RGB_COLORS) == bmi.bmiHeader.biHeight)
+ {
+ ULONG cxDelta = cxRow - bmi.bmiHeader.biWidth;
+ Gdiplus::ARGB *pargbMask = static_cast<Gdiplus::ARGB *>(pvBits);
+
+ for (ULONG y = bmi.bmiHeader.biHeight; y; --y)
+ {
+ for (ULONG x = bmi.bmiHeader.biWidth; x; --x)
+ {
+ if (*pargbMask++)
+ {
+ // transparent pixel
+ *pargb++ = 0;
+ }
+ else
+ {
+ // opaque pixel
+ *pargb++ |= 0xFF000000;
+ }
+ }
+
+ pargb += cxDelta;
+ }
+
+ hr = S_OK;
+ }
+
+ HeapFree(hHeap, 0, pvBits);
+ }
+
+ return hr;
+}
|
|
@@ -0,0 +1,56 @@ + // TortoiseSVN - a Windows shell extension for easy version control
+
+// Copyright (C) 2009 - TortoiseSVN
+
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+
+// Adapted for use in TortoiseHg by Veniamin Albaev
+//
+#pragma once
+#include <Uxtheme.h>
+#include <GdiPlus.h>
+#include <map>
+
+typedef HRESULT (WINAPI *FN_GetBufferedPaintBits) (HPAINTBUFFER hBufferedPaint, RGBQUAD **ppbBuffer, int *pcxRow);
+typedef HPAINTBUFFER (WINAPI *FN_BeginBufferedPaint) (HDC hdcTarget, const RECT *prcTarget, BP_BUFFERFORMAT dwFormat, BP_PAINTPARAMS *pPaintParams, HDC *phdc);
+typedef HRESULT (WINAPI *FN_EndBufferedPaint) (HPAINTBUFFER hBufferedPaint, BOOL fUpdateTarget);
+
+
+/**
+ * \ingroup utils
+ * provides helper functions for converting icons to bitmaps
+ */
+class IconBitmapUtils
+{
+public:
+ IconBitmapUtils(void);
+ ~IconBitmapUtils(void);
+
+ HBITMAP IconToBitmap(HICON hIcon);
+ HBITMAP IconToBitmapPARGB32(HICON hIcon);
+ HRESULT Create32BitHBITMAP(HDC hdc, const SIZE *psize, __deref_opt_out void **ppvBits, __out HBITMAP* phBmp);
+ HRESULT ConvertBufferToPARGB32(HPAINTBUFFER hPaintBuffer, HDC hdc, HICON hicon, SIZE& sizIcon);
+ bool HasAlpha(__in Gdiplus::ARGB *pargb, SIZE& sizImage, int cxRow);
+ HRESULT ConvertToPARGB32(HDC hdc, __inout Gdiplus::ARGB *pargb, HBITMAP hbmp, SIZE& sizImage, int cxRow);
+
+
+private:
+ HMODULE hUxTheme;
+
+ FN_GetBufferedPaintBits pfnGetBufferedPaintBits;
+ FN_BeginBufferedPaint pfnBeginBufferedPaint;
+ FN_EndBufferedPaint pfnEndBufferedPaint;
+};
|
@@ -9,8 +9,11 @@ InitStatus.obj \
CShellExtCMenu.obj \
CShellExtOverlay.obj \
+ IconBitmapUtils.obj \
+ Registry.obj \
ShellExt.obj \
StringUtils.obj \
+ SysInfo.obj \
dirstate.obj \
Winstat64.obj \
Dirstatecache.obj \
@@ -18,7 +21,7 @@ Thgstatus.obj \
QueryDirstate.obj
-LIBS = User32.lib Ole32.lib Shlwapi.lib Shell32.lib Advapi32.lib
+LIBS = shlwapi.lib gdiplus.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib
DEFFILE = ShellExt.def
@@ -29,7 +32,7 @@LDFLAGS_DIRSTATE = $(BASE_LDFLAGS) /SUBSYSTEM:CONSOLE
-all: THgShell.dll dirstate.exe
+all: THgShell.dll
clean:
del *.obj *.dll *.exe *.lib *.exp *.manifest
|
|
|
@@ -0,0 +1,202 @@ + // TortoiseSVN - a Windows shell extension for easy version control
+
+// Copyright (C) 2003-2006,2008-2009 - TortoiseSVN
+
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+#include "stdafx.h"
+#include "registry.h"
+
+//////////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __CSTRINGT_H__
+CRegBase::CRegBase()
+{
+}
+
+CRegBase::CRegBase (const CString& key, bool force, HKEY base, REGSAM sam)
+ : CRegBaseCommon<CString> (key, force, base, sam)
+{
+ m_key.TrimLeft(_T("\\"));
+ int backslashpos = m_key.ReverseFind('\\');
+ m_path = m_key.Left(backslashpos);
+ m_path.TrimRight(_T("\\"));
+ m_key = m_key.Mid(backslashpos);
+ m_key.Trim(_T("\\"));
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////////////////////////////
+
+CRegStdBase::CRegStdBase()
+{
+}
+
+CRegStdBase::CRegStdBase (const tstring& key, bool force, HKEY base, REGSAM sam)
+ : CRegBaseCommon<tstring> (key, force, base, sam)
+{
+ tstring::size_type pos = key.find_last_of(_T('\\'));
+ m_path = key.substr(0, pos);
+ m_key = key.substr(pos + 1);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __ATLTYPES_H__ // defines CRect
+CRegRect::CRegRect(void)
+ : CRegTypedBase<CRect, CRegBase>(CRect(0,0,0,0))
+{
+}
+
+CRegRect::CRegRect(const CString& key, const CRect& def, bool force, HKEY base, REGSAM sam)
+ : CRegTypedBase<CRect, CRegBase> (key, def, force, base, sam)
+{
+ read();
+}
+
+void CRegRect::InternalRead (HKEY hKey, CRect& value)
+{
+ DWORD size = 0;
+ DWORD type = 0;
+ RegQueryValueEx(hKey, m_key, NULL, &type, NULL, (LPDWORD) &size);
+
+ auto_buffer<char> buffer (size);
+ if ((LastError = RegQueryValueEx(hKey, m_key, NULL, &type, (BYTE*) buffer.get(), &size))==ERROR_SUCCESS)
+ {
+ ASSERT(type==REG_BINARY);
+ value = CRect((LPRECT)buffer.get());
+ }
+}
+
+void CRegRect::InternalWrite (HKEY hKey, const CRect& value)
+{
+ LastError = RegSetValueEx(hKey, m_key, 0, REG_BINARY, (BYTE *)(LPCRECT)value, sizeof(value));
+}
+
+#endif
+
+//////////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __ATLTYPES_H__ // defines CPoint
+CRegPoint::CRegPoint(void)
+ : CRegTypedBase<CPoint, CRegBase>(CPoint(0,0))
+{
+}
+
+CRegPoint::CRegPoint(const CString& key, const CPoint& def, bool force, HKEY base, REGSAM sam)
+ : CRegTypedBase<CPoint, CRegBase> (key, def, force, base, sam)
+{
+ read();
+}
+
+void CRegPoint::InternalRead (HKEY hKey, CPoint& value)
+{
+ DWORD size = 0;
+ DWORD type = 0;
+ RegQueryValueEx(hKey, m_key, NULL, &type, NULL, (LPDWORD) &size);
+
+ auto_buffer<char> buffer(size);
+ if ((LastError = RegQueryValueEx(hKey, m_key, NULL, &type, (BYTE*) buffer.get(), &size))==ERROR_SUCCESS)
+ {
+ ASSERT(type==REG_BINARY);
+ value = CPoint(*(POINT*)buffer.get());
+ }
+}
+
+void CRegPoint::InternalWrite (HKEY hKey, const CPoint& value)
+{
+ LastError = RegSetValueEx(hKey, m_key, 0, REG_BINARY, (BYTE *)&value, sizeof(value));
+}
+#endif
+
+/////////////////////////////////////////////////////////////////////
+
+#ifdef __AFXCOLL_H__ // defines CStringList
+CRegistryKey::CRegistryKey(const CString& key, HKEY base, REGSAM sam)
+{
+ m_base = base;
+ m_hKey = NULL;
+ m_sam = sam;
+ m_path = key;
+ m_path.TrimLeft(_T("\\"));
+}
+
+CRegistryKey::~CRegistryKey()
+{
+ if (m_hKey)
+ RegCloseKey(m_hKey);
+}
+
+DWORD CRegistryKey::createKey()
+{
+ DWORD disp;
+ DWORD rc = RegCreateKeyEx(m_base, m_path, 0, _T(""), REG_OPTION_NON_VOLATILE, KEY_WRITE|m_sam, NULL, &m_hKey, &disp);
+ if (rc != ERROR_SUCCESS)
+ {
+ return rc;
+ }
+ return RegCloseKey(m_hKey);
+}
+
+DWORD CRegistryKey::removeKey()
+{
+ RegOpenKeyEx(m_base, m_path, 0, KEY_WRITE|m_sam, &m_hKey);
+ return SHDeleteKey(m_base, (LPCTSTR)m_path);
+}
+
+bool CRegistryKey::getValues(CStringList& values)
+{
+ values.RemoveAll();
+
+ if (RegOpenKeyEx(m_base, m_path, 0, KEY_EXECUTE|m_sam, &m_hKey)==ERROR_SUCCESS)
+ {
+ for (int i = 0, rc = ERROR_SUCCESS; rc == ERROR_SUCCESS; i++)
+ {
+ TCHAR value[255];
+ DWORD size = sizeof value / sizeof TCHAR;
+ rc = RegEnumValue(m_hKey, i, value, &size, NULL, NULL, NULL, NULL);
+ if (rc == ERROR_SUCCESS)
+ {
+ values.AddTail(value);
+ }
+ }
+ }
+
+ return values.GetCount() > 0;
+}
+
+bool CRegistryKey::getSubKeys(CStringList& subkeys)
+{
+ subkeys.RemoveAll();
+
+ if (RegOpenKeyEx(m_base, m_path, 0, KEY_EXECUTE|m_sam, &m_hKey)==ERROR_SUCCESS)
+ {
+ for (int i = 0, rc = ERROR_SUCCESS; rc == ERROR_SUCCESS; i++)
+ {
+ TCHAR value[1024];
+ DWORD size = sizeof value / sizeof TCHAR;
+ FILETIME last_write_time;
+ rc = RegEnumKeyEx(m_hKey, i, value, &size, NULL, NULL, NULL, &last_write_time);
+ if (rc == ERROR_SUCCESS)
+ {
+ subkeys.AddTail(value);
+ }
+ }
+ }
+
+ return subkeys.GetCount() > 0;
+}
+#endif
+
|
@@ -1,7 +1,6 @@ ; shellext: Declares the module parameters for the DLL.
LIBRARY THGSHELL
-DESCRIPTION 'Shell Extensions for TortoiseHg'
EXPORTS
DllCanUnloadNow PRIVATE
|
|
@@ -0,0 +1,40 @@ + // TortoiseSVN - a Windows shell extension for easy version control
+
+// Copyright (C) 2008 - TortoiseSVN
+
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+#include "StdAfx.h"
+#include "SysInfo.h"
+
+SysInfo::SysInfo(void)
+{
+ SecureZeroMemory(&inf, sizeof(OSVERSIONINFOEX));
+ inf.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+ GetVersionEx((OSVERSIONINFO *)&inf);
+}
+
+SysInfo::~SysInfo(void)
+{
+}
+
+const SysInfo& SysInfo::Instance()
+{
+ static SysInfo instance;
+ return instance;
+}
+
+
+
|
|
@@ -0,0 +1,42 @@ + // TortoiseSVN - a Windows shell extension for easy version control
+
+// Copyright (C) 2008 - TortoiseSVN
+
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+#pragma once
+
+
+/**
+ * \ingroup Utils
+ * This singleton class handles system information
+ */
+class SysInfo
+{
+private:
+ SysInfo(void);
+ ~SysInfo(void);
+public:
+ static const SysInfo& Instance();
+
+ DWORD GetFullVersion() const {return MAKEWORD(inf.dwMinorVersion, inf.dwMajorVersion);}
+ bool IsXP() const {return (GetFullVersion() < 0x0600);} // cover Win5.1 and 5.2 alike
+ bool IsVista() const {return (GetFullVersion() == 0x0600);}
+ bool IsVistaOrLater() const {return (GetFullVersion() >= 0x0600);}
+ bool IsWin7() const {return (GetFullVersion() == 0x0601);}
+ bool IsWin7OrLater() const {return (GetFullVersion() >= 0x0601);}
+private:
+ OSVERSIONINFOEX inf;
+};
|
@@ -9,6 +9,7 @@ #include "FCNTL.H"
#include "shlwapi.h"
+#include "IconBitmapUtils.h"
LPWSTR hf_mbtowc(LPWSTR lpw, LPCSTR lpa, int nChars)
@@ -219,6 +220,43 @@ return h;
}
+HBITMAP GetTortoiseIconBitmap(const std::string& iconname)
+{
+ IconBitmapUtils bmpUtils;
+ typedef std::map<std::string, HBITMAP> BitmapCacheT;
+ static BitmapCacheT bmpcache_;
+
+ BitmapCacheT::const_iterator i = bmpcache_.find(iconname);
+ if (i != bmpcache_.end())
+ return i->second;
+
+ if (bmpcache_.size() > 200)
+ {
+ TDEBUG_TRACE("**** GetTortoiseIconBitmap: error: too many bitmaps in cache");
+ return 0;
+ }
+
+ HICON hIcon = GetTortoiseIcon(iconname);
+ if (!hIcon)
+ return 0;
+
+ HBITMAP hBmp = bmpUtils.IconToBitmapPARGB32(hIcon);
+ if (!hBmp)
+ {
+ TDEBUG_TRACE("**** GetTortoiseIconBitmap: error: something wrong in bmpUtils.ConvertToPARGB32(hIcon)");
+ return 0;
+ }
+
+ bmpcache_[iconname] = hBmp;
+
+ TDEBUG_TRACE(
+ "GetTortoiseIconBitmap: added '" << iconname << "' to bmpcache_"
+ " (" << bmpcache_.size() << " bitmaps in cache)"
+ );
+
+ return hBmp;
+}
+
std::string GetHgRepoRoot(const std::string& path)
{
|
@@ -19,6 +19,7 @@ std::string BaseName(const std::string&);
bool LaunchCommand(const std::string& command, const std::string& cwd);
HICON GetTortoiseIcon(const std::string & iconname);
+HBITMAP GetTortoiseIconBitmap(const std::string& iconname);
std::string GetHgRepoRoot(const std::string& path);
bool IsHgRepo(const std::string& path);
int GetRegistryConfig(const std::string& name, std::string& res);
|
|
@@ -0,0 +1,91 @@ + // TortoiseSVN - a Windows shell extension for easy version control
+
+// Copyright (C) 2009 - TortoiseSVN
+
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+#pragma once
+
+/**
+ * A simplified analog to std::auto_ptr<> that encapsulates
+ * an array allocated dynamically via new[].
+ *
+ * Use this where you could not use a std::auto_ptr<> (works
+ * for single elements only) nor a std::vector<> (no guarantees
+ * w.r.t. to internal organization, i.e. no access to mem buffer).
+ */
+
+template<class T>
+class auto_buffer
+{
+private:
+
+ T* buffer;
+
+ /// no copy nor assignment
+
+ auto_buffer(const auto_buffer&);
+ auto_buffer& operator=(const auto_buffer&);
+
+public:
+
+ explicit auto_buffer (size_t size = 0) throw()
+ : buffer (size == 0 ? NULL : new T[size])
+ {
+ }
+
+ ~auto_buffer()
+ {
+ delete[] buffer;
+ }
+
+ operator T*() const throw()
+ {
+ return buffer;
+ }
+
+ operator void*() const throw()
+ {
+ return buffer;
+ }
+
+ operator bool() const throw()
+ {
+ return buffer != NULL;
+ }
+
+ T* operator->() const throw()
+ {
+ return buffer;
+ }
+
+ T *get() const throw()
+ {
+ return buffer;
+ }
+
+ T* release() throw()
+ {
+ T* temp = buffer;
+ buffer = NULL;
+ return temp;
+ }
+
+ void reset (size_t newSize = 0)
+ {
+ delete[] buffer;
+ buffer = (newSize == 0 ? NULL : new T[newSize]);
+ }
+};
|
|
|
@@ -0,0 +1,1089 @@ + // TortoiseSVN - a Windows shell extension for easy version control
+
+// Copyright (C) 2003-2009 - TortoiseSVN
+
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+#pragma once
+#include <string>
+#include <memory>
+#include "shlwapi.h"
+#include "tstring.h"
+#include "auto_buffer.h"
+
+#ifndef ASSERT
+#define ASSERT(x)
+#endif
+
+/**
+ * \ingroup Utils
+ * Base class for the registry classes.
+ *
+ * \par requirements
+ * - win98 or later, win2k or later, win95 with IE4 or later, winNT4 with IE4 or later
+ * - import library Shlwapi.lib
+ */
+
+template<class S>
+class CRegBaseCommon
+{
+protected:
+
+ /**
+ * String type specific operations.
+ */
+
+ virtual LPCTSTR GetPlainString (const S& s) const = 0;
+ virtual DWORD GetLength (const S& s) const = 0;
+
+public: //methods
+
+ /** Default constructor.
+ */
+ CRegBaseCommon();
+ /**
+ * Constructor.
+ * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
+ * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
+ * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
+ */
+ CRegBaseCommon(const S& key, bool force, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
+
+ /**
+ * Removes the whole registry key including all values. So if you set the registry
+ * entry to be HKCU\Software\Company\Product\key\value there will only be
+ * HKCU\Software\Company\Product key in the registry.
+ * \return ERROR_SUCCESS or an nonzero error code. Use FormatMessage() to get an error description.
+ */
+ DWORD removeKey();
+ /**
+ * Removes the value of the registry object. If you set the registry entry to
+ * be HKCU\Software\Company\Product\key\value there will only be
+ * HKCU\Software\Company\Product\key\ in the registry.
+ * \return ERROR_SUCCESS or an nonzero error code. Use FormatMessage() to get an error description.
+ */
+ LONG removeValue();
+
+ /**
+ * Returns the string of the last error occurred.
+ */
+ virtual S getErrorString()
+ {
+ LPVOID lpMsgBuf;
+
+ FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ LastError,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR) &lpMsgBuf,
+ 0, NULL );
+
+ return (LPCTSTR)lpMsgBuf;
+ };
+
+ /// get failure info for last operation
+
+ LONG GetLastError() const
+ {
+ return LastError;
+ }
+
+ /// used in subclass templates to specify the correct string type
+
+ typedef S StringT;
+
+protected:
+
+ //members
+ HKEY m_base; ///< handle to the registry base
+ S m_key; ///< the name of the value
+ S m_path; ///< the path to the key
+ LONG LastError; ///< the value of the last error occurred
+ REGSAM m_sam; ///< the security attributes to pass to the registry command
+
+ bool m_read; ///< indicates if the value has already been read from the registry
+ bool m_force; ///< indicates if no cache should be used, i.e. always read and write directly from registry
+ bool m_exists; ///< true, if the registry actually exists
+};
+
+// implement CRegBaseCommon<> members
+
+template<class S>
+CRegBaseCommon<S>::CRegBaseCommon()
+ : m_base (HKEY_CURRENT_USER)
+ , m_key()
+ , m_path()
+ , LastError (ERROR_SUCCESS)
+ , m_sam (0)
+ , m_read (false)
+ , m_force (false)
+ , m_exists (false)
+{
+}
+
+template<class S>
+CRegBaseCommon<S>::CRegBaseCommon (const S& key, bool force, HKEY base, REGSAM sam)
+ : m_base (base)
+ , m_key (key)
+ , m_path()
+ , LastError (ERROR_SUCCESS)
+ , m_sam (sam)
+ , m_read (false)
+ , m_force (force)
+ , m_exists (false)
+{
+}
+
+template<class S>
+DWORD CRegBaseCommon<S>::removeKey()
+{
+ m_exists = false;
+ m_read = true;
+
+ HKEY hKey = NULL;
+ RegOpenKeyEx (m_base, GetPlainString (m_path), 0, KEY_WRITE|m_sam, &hKey);
+ return SHDeleteKey(m_base, GetPlainString (m_path));
+}
+
+template<class S>
+LONG CRegBaseCommon<S>::removeValue()
+{
+ m_exists = false;
+ m_read = true;
+
+ HKEY hKey = NULL;
+ RegOpenKeyEx(m_base, GetPlainString (m_path), 0, KEY_WRITE|m_sam, &hKey);
+ return RegDeleteValue(hKey, GetPlainString (m_key));
+}
+
+/**
+ * \ingroup Utils
+ * Base class for MFC type registry classes.
+ */
+
+#ifdef __CSTRINGT_H__
+class CRegBase : public CRegBaseCommon<CString>
+{
+protected:
+
+ /**
+ * String type specific operations.
+ */
+
+ virtual LPCTSTR GetPlainString (const CString& s) const {return (LPCTSTR)s;}
+ virtual DWORD GetLength (const CString& s) const {return s.GetLength();}
+
+public: //methods
+
+ /** Default constructor.
+ */
+ CRegBase();
+ /**
+ * Constructor.
+ * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
+ * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
+ * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
+ */
+ CRegBase(const CString& key, bool force, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
+
+ /**
+ * Returns the string of the last error occurred.
+ */
+ CString getErrorString()
+ {
+ CString error = CRegBaseCommon<CString>::getErrorString();
+#if defined IDS_REG_ERROR
+ CString sTemp;
+ sTemp.Format(IDS_REG_ERROR, (LPCTSTR)m_key, (LPCTSTR)error);
+ return sTemp;
+#else
+ return error;
+#endif
+ };
+};
+#endif
+
+
+
+/**
+ * \ingroup Utils
+ * Base class for STL string type registry classes.
+ */
+
+class CRegStdBase : public CRegBaseCommon<tstring>
+{
+protected:
+
+ /**
+ * String type specific operations.
+ */
+
+ virtual LPCTSTR GetPlainString (const tstring& s) const {return s.c_str();}
+ virtual DWORD GetLength (const tstring& s) const {return static_cast<DWORD>(s.size());}
+
+public: //methods
+
+ /** Default constructor.
+ */
+ CRegStdBase();
+ /**
+ * Constructor.
+ * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
+ * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
+ * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
+ */
+ CRegStdBase(const tstring& key, bool force, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
+};
+
+/**
+ * \ingroup Utils
+ * DWORD value in registry. with this class you can use DWORD values in registry
+ * like normal DWORD variables in your program.
+ * Usage:
+ * in your header file, declare your registry DWORD variable:
+ * \code
+ * CRegDWORD regvalue;
+ * \endcode
+ * next initialize the variable e.g. in the constructor of your class:
+ * \code
+ * regvalue = CRegDWORD("Software\\Company\\SubKey\\MyValue", 100);
+ * \endcode
+ * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path
+ * "Software\Company\SubKey" to the variable. If the key does not yet exist or
+ * an error occurred during read from the registry, a default
+ * value of 100 is used when accessing the variable.
+ * now the variable can be used like any other DWORD variable:
+ * \code
+ * regvalue = 200; //stores the value 200 in the registry
+ * int temp = regvalue + 300; //temp has value 500 now
+ * regvalue += 300; //now the registry has the value 500 too
+ * \endcode
+ * to avoid too much access to the registry the value is cached inside the object.
+ * once the value is read, no more read accesses to the registry will be made.
+ * this means the variable will contain a wrong value if the corresponding registry
+ * entry is changed by anything else than this variable! If you think that could happen
+ * then use
+ * \code
+ * regvalue.read();
+ * \endcode
+ * to force a refresh of the variable with the registry.
+ * a write to the registry is only made if the new value assigned with the variable
+ * is different than the last assigned value.
+ * to force a write use the method write();
+ * another option to force reads and writes to the registry is to specify TRUE as the
+ * third parameter in the constructor.
+ */
+template<class T, class Base>
+class CRegTypedBase : public Base
+{
+private:
+
+ T m_value; ///< the cached value of the registry
+ T m_defaultvalue; ///< the default value to use
+
+ /**
+ * time stamp of the last registry lookup, i.e \ref read() call
+ */
+
+ DWORD lastRead;
+
+ /**
+ * \ref read() will be called, if \ref lastRead differs from the
+ * current time stamp by more than this.
+ * (DWORD)(-1) -> no automatic refresh.
+ */
+
+ DWORD lookupInterval;
+
+ /**
+ * Check time stamps etc.
+ * If the current data is out-dated, reset the \ref m_read flag.
+ */
+
+ void HandleAutoRefresh();
+
+ /**
+ * sub-classes must provide type-specific code to extract data from
+ * and write data to an open registry key.
+ */
+
+ virtual void InternalRead (HKEY hKey, T& value) = 0;
+ virtual void InternalWrite (HKEY hKey, const T& value) = 0;
+
+public:
+
+ /**
+ * Make the value type accessible to others.
+ */
+
+ typedef T ValueT;
+
+ /**
+ * Constructor.
+ * We use this instead of a default constructor because not all
+ * data types may provide an adequate default constructor.
+ */
+ CRegTypedBase(const T& def);
+
+ /**
+ * Constructor.
+ * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
+ * \param def the default value used when the key does not exist or a read error occurred
+ * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
+ * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
+ */
+ CRegTypedBase(const typename Base::StringT& key, const T& def, bool force = FALSE, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
+
+ /**
+ * Constructor.
+ * \param updateInterval time in msec between registry lookups caused by operator const T&
+ * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
+ * \param def the default value used when the key does not exist or a read error occurred
+ * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
+ * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
+ */
+ CRegTypedBase(DWORD updateInterval, const typename Base::StringT& key, const T& def, bool force = FALSE, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
+
+ /**
+ * reads the assigned value from the registry. Use this method only if you think the registry
+ * value could have been altered without using the CRegDWORD object.
+ * \return the read value
+ */
+ void read(); ///< reads the value from the registry
+ void write(); ///< writes the value to the registry
+
+ bool exists(); ///< test whether registry entry exits
+ const T& defaultValue() const; ///< return the default passed to the constructor
+
+ /**
+ * Data access.
+ */
+
+ operator const T&();
+ CRegTypedBase<T,Base>& operator=(const T& rhs);
+};
+
+// implement CRegTypedBase<> members
+
+template<class T, class Base>
+void CRegTypedBase<T, Base>::HandleAutoRefresh()
+{
+ if (m_read && (lookupInterval != (DWORD)(-1)))
+ {
+ DWORD currentTime = GetTickCount();
+ if ( (currentTime < lastRead)
+ || (currentTime > lastRead + lookupInterval))
+ {
+ m_read = false;
+ }
+ }
+}
+
+template<class T, class Base>
+CRegTypedBase<T, Base>::CRegTypedBase (const T& def)
+ : m_value (def)
+ , m_defaultvalue (def)
+ , lastRead (0)
+ , lookupInterval ((DWORD)-1)
+{
+}
+
+template<class T, class Base>
+CRegTypedBase<T, Base>::CRegTypedBase (const typename Base::StringT& key, const T& def, bool force, HKEY base, REGSAM sam)
+ : Base (key, force, base, sam)
+ , m_value (def)
+ , m_defaultvalue (def)
+ , lastRead (0)
+ , lookupInterval ((DWORD)-1)
+{
+}
+
+template<class T, class Base>
+CRegTypedBase<T, Base>::CRegTypedBase (DWORD lookupInterval, const typename Base::StringT& key, const T& def, bool force, HKEY base, REGSAM sam)
+ : Base (key, force, base, sam)
+ , m_value (def)
+ , m_defaultvalue (def)
+ , lastRead (0)
+ , lookupInterval (lookupInterval)
+{
+}
+
+template<class T, class Base>
+void CRegTypedBase<T, Base>::read()
+{
+ m_value = m_defaultvalue;
+ m_exists = false;
+
+ HKEY hKey = NULL;
+ if ((LastError = RegOpenKeyEx (m_base, GetPlainString (m_path), 0, KEY_EXECUTE|m_sam, &hKey))==ERROR_SUCCESS)
+ {
+ m_read = true;
+
+ T value = m_defaultvalue;
+ InternalRead (hKey, value);
+
+ if (LastError ==ERROR_SUCCESS)
+ {
+ m_exists = true;
+ m_value = value;
+ }
+
+ LastError = RegCloseKey(hKey);
+ }
+
+ lastRead = GetTickCount();
+}
+
+template<class T, class Base>
+void CRegTypedBase<T, Base>::write()
+{
+ HKEY hKey = NULL;
+
+ DWORD disp = 0;
+ if ((LastError = RegCreateKeyEx(m_base, GetPlainString (m_path), 0, _T(""), REG_OPTION_NON_VOLATILE, KEY_WRITE|m_sam, NULL, &hKey, &disp))!=ERROR_SUCCESS)
+ {
+ return;
+ }
+
+ InternalWrite (hKey, m_value);
+ if (LastError ==ERROR_SUCCESS)
+ {
+ m_read = true;
+ m_exists = true;
+ }
+ LastError = RegCloseKey(hKey);
+
+ lastRead = GetTickCount();
+}
+
+template<class T, class Base>
+bool CRegTypedBase<T, Base>::exists()
+{
+ if (!m_read && (LastError == ERROR_SUCCESS))
+ read();
+
+ return m_exists;
+}
+
+template<class T, class Base>
+const T& CRegTypedBase<T, Base>::defaultValue() const
+{
+ return m_defaultvalue;
+}
+
+template<class T, class Base>
+CRegTypedBase<T, Base>::operator const T&()
+{
+ HandleAutoRefresh();
+ if ((m_read)&&(!m_force))
+ {
+ LastError = ERROR_SUCCESS;
+ }
+ else
+ {
+ read();
+ }
+
+ return m_value;
+}
+
+template<class T, class Base>
+CRegTypedBase<T, Base>& CRegTypedBase<T, Base>::operator =(const T& d)
+{
+ if (m_read && (d == m_value) && !m_force)
+ {
+ //no write to the registry required, its the same value
+ LastError = ERROR_SUCCESS;
+ return *this;
+ }
+ m_value = d;
+ write();
+ return *this;
+}
+
+/**
+ * \ingroup Utils
+ * DWORD value in registry. with this class you can use DWORD values in registry
+ * like normal DWORD variables in your program.
+ * Usage:
+ * in your header file, declare your registry DWORD variable:
+ * \code
+ * CRegDWORD regvalue;
+ * \endcode
+ * next initialize the variable e.g. in the constructor of your class:
+ * \code
+ * regvalue = CRegDWORD("Software\\Company\\SubKey\\MyValue", 100);
+ * \endcode
+ * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path
+ * "Software\Company\SubKey" to the variable. If the key does not yet exist or
+ * an error occurred during read from the registry, a default
+ * value of 100 is used when accessing the variable.
+ * now the variable can be used like any other DWORD variable:
+ * \code
+ * regvalue = 200; //stores the value 200 in the registry
+ * int temp = regvalue + 300; //temp has value 500 now
+ * regvalue += 300; //now the registry has the value 500 too
+ * \endcode
+ * to avoid too much access to the registry the value is cached inside the object.
+ * once the value is read, no more read accesses to the registry will be made.
+ * this means the variable will contain a wrong value if the corresponding registry
+ * entry is changed by anything else than this variable! If you think that could happen
+ * then use
+ * \code
+ * regvalue.read();
+ * \endcode
+ * to force a refresh of the variable with the registry.
+ * a write to the registry is only made if the new value assigned with the variable
+ * is different than the last assigned value.
+ * to force a write use the method write();
+ * another option to force reads and writes to the registry is to specify TRUE as the
+ * third parameter in the constructor.
+ */
+template<class Base>
+class CRegDWORDCommon : public CRegTypedBase<DWORD,Base>
+{
+private:
+
+ /**
+ * provide type-specific code to extract data from and write data to an open registry key.
+ */
+
+ virtual void InternalRead (HKEY hKey, DWORD& value);
+ virtual void InternalWrite (HKEY hKey, const DWORD& value);
+
+public:
+
+ CRegDWORDCommon(void);
+ /**
+ * Constructor.
+ * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
+ * \param def the default value used when the key does not exist or a read error occurred
+ * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
+ * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
+ */
+ CRegDWORDCommon(const typename Base::StringT& key, DWORD def = 0, bool force = false, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
+ CRegDWORDCommon(DWORD lookupInterval, const typename Base::StringT& key, DWORD def = 0, bool force = false, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
+
+ CRegDWORDCommon& operator=(DWORD rhs) {CRegTypedBase<DWORD, Base>::operator =(rhs); return *this;}
+ CRegDWORDCommon& operator+=(DWORD d) { return *this = *this + d;}
+ CRegDWORDCommon& operator-=(DWORD d) { return *this = *this - d;}
+ CRegDWORDCommon& operator*=(DWORD d) { return *this = *this * d;}
+ CRegDWORDCommon& operator/=(DWORD d) { return *this = *this / d;}
+ CRegDWORDCommon& operator%=(DWORD d) { return *this = *this % d;}
+ CRegDWORDCommon& operator<<=(DWORD d) { return *this = *this << d;}
+ CRegDWORDCommon& operator>>=(DWORD d) { return *this = *this >> d;}
+ CRegDWORDCommon& operator&=(DWORD d) { return *this = *this & d;}
+ CRegDWORDCommon& operator|=(DWORD d) { return *this = *this | d;}
+ CRegDWORDCommon& operator^=(DWORD d) { return *this = *this ^ d;}
+};
+
+// implement CRegDWORDCommon<> methods
+
+template<class Base>
+CRegDWORDCommon<Base>::CRegDWORDCommon(void)
+ : CRegTypedBase<DWORD, Base>(0)
+{
+}
+
+template<class Base>
+CRegDWORDCommon<Base>::CRegDWORDCommon(const typename Base::StringT& key, DWORD def, bool force, HKEY base, REGSAM sam)
+ : CRegTypedBase<DWORD, Base> (key, def, force, base, sam)
+{
+}
+
+template<class Base>
+CRegDWORDCommon<Base>::CRegDWORDCommon(DWORD lookupInterval, const typename Base::StringT& key, DWORD def, bool force, HKEY base, REGSAM sam)
+ : CRegTypedBase<DWORD, Base> (lookupInterval, key, def, force, base, sam)
+{
+}
+
+template<class Base>
+void CRegDWORDCommon<Base>::InternalRead (HKEY hKey, DWORD& value)
+{
+ DWORD size = sizeof(value);
+ DWORD type = 0;
+ if ((LastError = RegQueryValueEx(hKey, GetPlainString (m_key), NULL, &type, (BYTE*) &value, &size))==ERROR_SUCCESS)
+ {
+ ASSERT(type==REG_DWORD);
+ }
+}
+
+template<class Base>
+void CRegDWORDCommon<Base>::InternalWrite (HKEY hKey, const DWORD& value)
+{
+ LastError = RegSetValueEx (hKey, GetPlainString (m_key), 0, REG_DWORD,(const BYTE*) &value, sizeof(value));
+}
+
+/**
+ * \ingroup Utils
+ * CString value in registry. with this class you can use CString values in registry
+ * almost like normal CString variables in your program.
+ * Usage:
+ * in your header file, declare your registry CString variable:
+ * \code
+ * CRegString regvalue;
+ * \endcode
+ * next initialize the variable e.g. in the constructor of your class:
+ * \code
+ * regvalue = CRegString("Software\\Company\\SubKey\\MyValue", "default");
+ * \endcode
+ * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path
+ * "Software\Company\SubKey" to the variable. If the key does not yet exist or
+ * an error occurred during read from the registry, a default
+ * value of "default" is used when accessing the variable.
+ * now the variable can be used like any other CString variable:
+ * \code
+ * regvalue = "some string"; //stores the value "some string" in the registry
+ * CString temp = regvalue + "!!"; //temp has value "some string!!" now
+ * \endcode
+ * to use the normal methods of the CString class, just typecast the CRegString to a CString
+ * and do whatever you want with the string:
+ * \code
+ * ((CString)regvalue).GetLength();
+ * ((CString)regvalue).Trim();
+ * \endcode
+ * please be aware that in the second line the change in the string won't be written
+ * to the registry! To force a write use the write() method. A write() is only needed
+ * if you change the String with Methods not overloaded by CRegString.
+ * to avoid too much access to the registry the value is cached inside the object.
+ * once the value is read, no more read accesses to the registry will be made.
+ * this means the variable will contain a wrong value if the corresponding registry
+ * entry is changed by anything else than this variable! If you think that could happen
+ * then use
+ * \code
+ * regvalue.read();
+ * \endcode
+ * to force a refresh of the variable with the registry.
+ * a write to the registry is only made if the new value assigned with the variable
+ * is different than the last assigned value.
+ * to force a write use the method write();
+ * another option to force reads and writes to the registry is to specify TRUE as the
+ * third parameter in the constructor.
+ */
+template<class Base>
+class CRegStringCommon : public CRegTypedBase<typename Base::StringT, Base>
+{
+private:
+
+ /**
+ * provide type-specific code to extract data from and write data to an open registry key.
+ */
+
+ virtual void InternalRead (HKEY hKey, typename Base::StringT& value);
+ virtual void InternalWrite (HKEY hKey, const typename Base::StringT& value);
+
+public:
+ CRegStringCommon();
+ /**
+ * Constructor.
+ * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
+ * \param def the default value used when the key does not exist or a read error occurred
+ * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
+ * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
+ */
+ CRegStringCommon(const typename Base::StringT& key, const typename Base::StringT& def = _T(""), bool force = false, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
+ CRegStringCommon(DWORD lookupInterval, const typename Base::StringT& key, const typename Base::StringT& def = _T(""), bool force = false, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
+
+ CRegStringCommon& operator=(const typename Base::StringT& rhs) {CRegTypedBase<StringT, Base>::operator =(rhs); return *this;}
+ CRegStringCommon& operator+=(const typename Base::StringT& s) { return *this = (typename Base::StringT)*this + s; }
+};
+
+// implement CRegDWORD<> methods
+
+template<class Base>
+CRegStringCommon<Base>::CRegStringCommon(void)
+ : CRegTypedBase<typename Base::StringT, Base>(typename Base::StringT())
+{
+}
+
+template<class Base>
+CRegStringCommon<Base>::CRegStringCommon(const typename Base::StringT& key, const typename Base::StringT& def, bool force, HKEY base, REGSAM sam)
+ : CRegTypedBase<typename Base::StringT, Base> (key, def, force, base, sam)
+{
+}
+
+template<class Base>
+CRegStringCommon<Base>::CRegStringCommon(DWORD lookupInterval, const typename Base::StringT& key, const typename Base::StringT& def, bool force, HKEY base, REGSAM sam)
+ : CRegTypedBase<typename Base::StringT, Base> (lookupInterval, key, def, force, base, sam)
+{
+}
+
+template<class Base>
+void CRegStringCommon<Base>::InternalRead (HKEY hKey, typename Base::StringT& value)
+{
+ DWORD size = 0;
+ DWORD type = 0;
+ LastError = RegQueryValueEx(hKey, GetPlainString (m_key), NULL, &type, NULL, &size);
+
+ auto_buffer<TCHAR> pStr (size);
+ if ((LastError = RegQueryValueEx(hKey, GetPlainString (m_key), NULL, &type, (BYTE*) pStr.get(), &size))==ERROR_SUCCESS)
+ {
+ ASSERT(type==REG_SZ || type==REG_EXPAND_SZ);
+ value = StringT (pStr.get());
+ }
+}
+
+template<class Base>
+void CRegStringCommon<Base>::InternalWrite (HKEY hKey, const typename Base::StringT& value)
+{
+ LastError = RegSetValueEx(hKey, GetPlainString (m_key), 0, REG_SZ, (BYTE *)GetPlainString (value), (GetLength(value)+1)*sizeof (TCHAR));
+}
+
+/**
+ * \ingroup Utils
+ * CRect value in registry. with this class you can use CRect values in registry
+ * almost like normal CRect variables in your program.
+ * Usage:
+ * in your header file, declare your registry CString variable:
+ * \code
+ * CRegRect regvalue;
+ * \endcode
+ * next initialize the variable e.g. in the constructor of your class:
+ * \code
+ * regvalue = CRegRect("Software\\Company\\SubKey\\MyValue", CRect(100,100,200,200));
+ * \endcode
+ * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path
+ * "Software\Company\SubKey" to the variable. If the key does not yet exist or
+ * an error occurred during read from the registry, a default
+ * value of 100,100,200,200 is used when accessing the variable.
+ * now the variable can be used like any other CRect variable:
+ * \code
+ * regvalue = CRect(40,20,300,500); //stores the value in the registry
+ * CRect temp = regvalue + CPoint(1,1);
+ * temp |= CSize(5,5);
+ * \endcode
+ * to use the normal methods of the CRect class, just typecast the CRegRect to a CRect
+ * and do whatever you want with the rect:
+ * \code
+ * ((CRect)regvalue).MoveToX(100);
+ * ((CRect)regvalue).DeflateRect(10,10);
+ * \endcode
+ * please be aware that in the second line the change in the CRect won't be written
+ * to the registry! To force a write use the write() method. A write() is only needed
+ * if you change the CRect with Methods not overloaded by CRegRect.
+ * to avoid too much access to the registry the value is cached inside the object.
+ * once the value is read, no more read accesses to the registry will be made.
+ * this means the variable will contain a wrong value if the corresponding registry
+ * entry is changed by anything else than this variable! If you think that could happen
+ * then use
+ * \code
+ * regvalue.read();
+ * \endcode
+ * to force a refresh of the variable with the registry.
+ * a write to the registry is only made if the new value assigned with the variable
+ * is different than the last assigned value.
+ * to force a write use the method write();
+ * another option to force reads and writes to the registry is to specify TRUE as the
+ * third parameter in the constructor.
+ */
+
+#ifdef __ATLTYPES_H__ // defines CRect
+class CRegRect : public CRegTypedBase<CRect, CRegBase>
+{
+private:
+
+ /**
+ * provide type-specific code to extract data from and write data to an open registry key.
+ */
+
+ virtual void InternalRead (HKEY hKey, CRect& value);
+ virtual void InternalWrite (HKEY hKey, const CRect& value);
+
+public:
+ CRegRect();
+ /**
+ * Constructor.
+ * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
+ * \param def the default value used when the key does not exist or a read error occurred
+ * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
+ * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
+ */
+ CRegRect(const CString& key, const CRect& def = CRect(), bool force = false, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
+ ~CRegRect(void);
+
+ CRegRect& operator=(const CRect& rhs) {CRegTypedBase<CRect, CRegBase>::operator =(rhs); return *this;}
+ operator LPCRECT() { return (LPCRECT)(CRect)*this; }
+ operator LPRECT() { return (LPRECT)(CRect)*this; }
+ CRegRect& operator+=(POINT r) { return *this = (CRect)*this + r;}
+ CRegRect& operator+=(SIZE r) { return *this = (CRect)*this + r;}
+ CRegRect& operator+=(LPCRECT r) { return *this = (CRect)*this + r;}
+ CRegRect& operator-=(POINT r) { return *this = (CRect)*this - r;}
+ CRegRect& operator-=(SIZE r) { return *this = (CRect)*this - r;}
+ CRegRect& operator-=(LPCRECT r) { return *this = (CRect)*this - r;}
+
+ CRegRect& operator&=(CRect r) { return *this = r & *this;}
+ CRegRect& operator|=(CRect r) { return *this = r | *this;}
+};
+#endif
+
+/**
+ * \ingroup Utils
+ * CPoint value in registry. with this class you can use CPoint values in registry
+ * almost like normal CPoint variables in your program.
+ * Usage:
+ * in your header file, declare your registry CPoint variable:
+ * \code
+ * CRegPoint regvalue;
+ * \endcode
+ * next initialize the variable e.g. in the constructor of your class:
+ * \code
+ * regvalue = CRegPoint("Software\\Company\\SubKey\\MyValue", CPoint(100,100));
+ * \endcode
+ * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path
+ * "Software\Company\SubKey" to the variable. If the key does not yet exist or
+ * an error occurred during read from the registry, a default
+ * value of 100,100 is used when accessing the variable.
+ * now the variable can be used like any other CPoint variable:
+ * \code
+ * regvalue = CPoint(40,20); //stores the value in the registry
+ * CPoint temp = regvalue + CPoint(1,1);
+ * temp += CSize(5,5);
+ * \endcode
+ * to use the normal methods of the CPoint class, just typecast the CRegPoint to a CPoint
+ * and do whatever you want with the point:
+ * \code
+ * ((CRect)regvalue).Offset(100,10);
+ * \endcode
+ * please be aware that in the above example the change in the CPoint won't be written
+ * to the registry! To force a write use the write() method. A write() is only needed
+ * if you change the CPoint with Methods not overloaded by CRegPoint.
+ * to avoid too much access to the registry the value is cached inside the object.
+ * once the value is read, no more read accesses to the registry will be made.
+ * this means the variable will contain a wrong value if the corresponding registry
+ * entry is changed by anything else than this variable! If you think that could happen
+ * then use
+ * \code
+ * regvalue.read();
+ * \endcode
+ * to force a refresh of the variable with the registry.
+ * a write to the registry is only made if the new value assigned with the variable
+ * is different than the last assigned value.
+ * to force a write use the method write();
+ * another option to force reads and writes to the registry is to specify TRUE as the
+ * third parameter in the constructor.
+ */
+
+#ifdef __ATLTYPES_H__ // defines CPoint
+class CRegPoint : public CRegTypedBase<CPoint, CRegBase>
+{
+private:
+
+ /**
+ * provide type-specific code to extract data from and write data to an open registry key.
+ */
+
+ virtual void InternalRead (HKEY hKey, CPoint& value);
+ virtual void InternalWrite (HKEY hKey, const CPoint& value);
+
+public:
+ CRegPoint();
+ /**
+ * Constructor.
+ * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue"
+ * \param def the default value used when the key does not exist or a read error occurred
+ * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry
+ * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
+ */
+ CRegPoint(const CString& key, const CPoint& def = CPoint(), bool force = false, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
+ ~CRegPoint(void);
+
+ CRegPoint& operator=(const CPoint& rhs) {CRegTypedBase<CPoint, CRegBase>::operator =(rhs); return *this;}
+ CRegPoint& operator+=(CPoint p) { return *this = p + *this; }
+ CRegPoint& operator-=(CPoint p) { return *this = p - *this; }
+};
+#endif
+
+/**
+ * \ingroup Utils
+ * Manages a registry key (not a value). Provides methods to create and remove the
+ * key and to query the list of values and sub keys.
+ */
+
+#ifdef __AFXCOLL_H__ // defines CStringList
+class CRegistryKey
+{
+public: //methods
+ /**
+ * Constructor.
+ * \param key the path to the key, including the key. example: "Software\\Company\\SubKey"
+ * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information.
+ */
+ CRegistryKey(const CString& key, HKEY base = HKEY_CURRENT_USER, REGSAM sam = 0);
+ ~CRegistryKey();
+
+ /**
+ * Creates the registry key if it does not already exist.
+ * \return ERROR_SUCCESS or an nonzero error code. Use FormatMessage() to get an error description.
+ */
+ DWORD createKey();
+ /**
+ * Removes the whole registry key including all values. So if you set the registry
+ * entry to be HKCU\Software\Company\Product\key there will only be
+ * HKCU\Software\Company\Product key in the registry.
+ * \return ERROR_SUCCESS or an nonzero error code. Use FormatMessage() to get an error description.
+ */
+ DWORD removeKey();
+
+ bool getValues(CStringList& values); ///< returns the list of values
+ bool getSubKeys(CStringList& subkeys); ///< returns the list of sub keys
+
+public: //members
+ HKEY m_base; ///< handle to the registry base
+ HKEY m_hKey; ///< handle to the open registry key
+ REGSAM m_sam; ///< the security attributes to pass to the registry command
+ CString m_path; ///< the path to the key
+};
+#endif
+
+#ifdef _MAP_
+template<class T>
+class CKeyList
+{
+private:
+
+ /// constructor parameters
+
+ typename T::StringT key;
+ typename T::ValueT defaultValue;
+ HKEY base;
+
+ /// per-index defaults
+
+ typedef std::map<int, typename T::ValueT> TDefaults;
+ TDefaults defaults;
+
+ /// the indices accessed so far
+
+ typedef std::map<int, T*> TElements;
+ mutable TElements elements;
+
+ /// auto-insert
+
+ const typename T::ValueT& GetDefault (int index) const;
+ T& GetAt (int index) const;
+
+public:
+
+ /// construction
+
+ CKeyList (const typename T::StringT& key, const typename T::ValueT& defaultValue, HKEY base = HKEY_CURRENT_USER)
+ : key (key)
+ , defaultValue (defaultValue)
+ , base (base)
+ {
+ }
+
+ /// destruction: delete all elements
+
+ ~CKeyList()
+ {
+ for ( TElements::iterator iter = elements.begin()
+ , end = elements.end()
+ ; iter != end
+ ; ++iter)
+ {
+ delete iter->second;
+ }
+ }
+
+ /// data access
+
+ const T& operator[] (int index) const
+ {
+ return GetAt (index);
+ }
+
+ T& operator[] (int index)
+ {
+ return GetAt (index);
+ }
+
+ const TDefaults& GetDefaults() const
+ {
+ return defaults;
+ }
+
+ TDefaults& GetDefaults()
+ {
+ return defaults;
+ }
+
+ const typename T::ValueT& GetDefault() const
+ {
+ return defaultValue;
+ }
+};
+
+/// auto-insert
+
+template<class T>
+const typename T::ValueT& CKeyList<T>::GetDefault (int index) const
+{
+ TDefaults::const_iterator iter = defaults.find (index);
+ return iter == defaults.end() ? defaultValue : iter->second;
+}
+
+template<class T>
+T& CKeyList<T>::GetAt (int index) const
+{
+ TElements::iterator iter = elements.find (index);
+ if (iter == elements.end())
+ {
+ TCHAR buffer [10];
+ _itot_s (index, buffer, 10);
+ typename T::StringT indexKey = key + _T ('\\') + buffer;
+
+ T* newElement = new T (indexKey, GetDefault (index), false, base);
+ iter = elements.insert (std::make_pair (index, newElement)).first;
+ }
+
+ return *iter->second;
+};
+
+#endif
+
+/**
+ * Instantiate templates for common (data type, string type) combinations.
+ */
+
+#ifdef __CSTRINGT_H__
+CRegDWORDCommon<CRegBase>;
+typedef CRegDWORDCommon<CRegBase> CRegDWORD;
+CRegStringCommon<CRegBase>;
+typedef CRegStringCommon<CRegBase> CRegString;
+
+#ifdef _MAP_
+CKeyList<CRegDWORD>;
+typedef CKeyList<CRegDWORD> CRegDWORDList;
+CKeyList<CRegString>;
+typedef CKeyList<CRegString> CRegStringList;
+#endif
+#endif
+
+CRegDWORDCommon<CRegStdBase>;
+typedef CRegDWORDCommon<CRegStdBase> CRegStdDWORD;
+CRegStringCommon<CRegStdBase>;
+typedef CRegStringCommon<CRegStdBase> CRegStdString;
+
+#ifdef _MAP_
+CKeyList<CRegStdDWORD>;
+typedef CKeyList<CRegStdDWORD> CRegStdDWORDList;
+CKeyList<CRegStdString>;
+typedef CKeyList<CRegStdString> CRegStdStringList;
+#endif
+
|
@@ -1,6 +1,6 @@ 
-Microsoft Visual Studio Solution File, Format Version 9.00
-# Visual Studio 2005
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shellext", "shellext.vcproj", "{B7E760E4-DDA6-44BA-95E5-F6EDA42321B5}"
ProjectSection(WebsiteProperties) = preProject
Debug.AspNetCompiler.Debug = "True"
|
|
|
@@ -1,11 +1,12 @@ <?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
- Version="8.00"
+ Version="9.00"
Name="shellext"
ProjectGUID="{B7E760E4-DDA6-44BA-95E5-F6EDA42321B5}"
RootNamespace="shellext"
Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
@@ -64,11 +65,13 @@ />
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="shlwapi.lib"
+ AdditionalDependencies="shlwapi.lib gdiplus.lib"
LinkIncremental="2"
ModuleDefinitionFile="shellext.def"
GenerateDebugInformation="true"
SubSystem="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
@@ -90,9 +93,6 @@ Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
@@ -148,6 +148,8 @@ ModuleDefinitionFile="shellext.def"
GenerateDebugInformation="true"
SubSystem="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
TargetMachine="17"
/>
<Tool
@@ -169,9 +171,6 @@ Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
@@ -221,7 +220,7 @@ <Tool
Name="VCLinkerTool"
UseUnicodeResponseFiles="false"
- AdditionalDependencies="shlwapi.lib"
+ AdditionalDependencies="shlwapi.lib gdiplus.lib"
OutputFile="$(OutDir)\ThgShell.dll"
LinkIncremental="1"
ModuleDefinitionFile="shellext.def"
@@ -229,6 +228,8 @@ SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
TargetMachine="1"
CLRImageType="0"
/>
@@ -252,9 +253,6 @@ Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
@@ -313,6 +311,8 @@ SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
TargetMachine="17"
CLRImageType="0"
/>
@@ -336,9 +336,6 @@ Name="VCAppVerifierTool"
/>
<Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
@@ -376,6 +373,10 @@ >
</File>
<File
+ RelativePath=".\IconBitmapUtils.cpp"
+ >
+ </File>
+ <File
RelativePath=".\IconOverlay.cpp"
>
</File>
@@ -388,6 +389,10 @@ >
</File>
<File
+ RelativePath=".\Registry.cpp"
+ >
+ </File>
+ <File
RelativePath=".\ShellExt.cpp"
>
</File>
@@ -396,6 +401,10 @@ >
</File>
<File
+ RelativePath=".\SysInfo.cpp"
+ >
+ </File>
+ <File
RelativePath=".\Thgstatus.cpp"
>
</File>
|
|
@@ -0,0 +1,25 @@ + // TortoiseSVN - a Windows shell extension for easy version control
+
+// Copyright (C) 2009 - TortoiseSVN
+
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+#pragma once
+
+#include <string>
+#include <tchar.h>
+
+typedef std::basic_string<TCHAR> tstring;
+
|
Loading...