Fix colors of icon in context menu:

-Use ownerdrawn icon on OS < Vista
-Use alphablended icon on OS >= Vista
Allow alphablended icon to be used for shell icons

git-svn-id: svn://svn.tuxfamily.org/svnroot/notepadplus/repository/trunk@703 f5eea248-9336-0410-98b8-ebc06183d4e3
This commit is contained in:
Harold Bruintjes 2010-11-14 10:54:10 +00:00
parent d70c6b2545
commit 6bcf26de86
7 changed files with 484 additions and 285 deletions

View File

@ -25,9 +25,14 @@
<Option object_output="obj_D\" /> <Option object_output="obj_D\" />
<Option type="3" /> <Option type="3" />
<Option compiler="gcc" /> <Option compiler="gcc" />
<Option host_application="..\bin\Notepad++\notepad++.exe" />
<Option run_host_application_in_terminal="0" />
<Compiler> <Compiler>
<Add option="-g" /> <Add option="-g" />
</Compiler> </Compiler>
<ExtraCommands>
<Add after='cmd /c copy &quot;$(TARGET_OUTPUT_FILE)&quot; &quot;..\bin\\Notepad++&quot;' />
</ExtraCommands>
</Target> </Target>
<Target title="win64"> <Target title="win64">
<Option output="..\bin\NppShell64" prefix_auto="1" extension_auto="1" /> <Option output="..\bin\NppShell64" prefix_auto="1" extension_auto="1" />
@ -52,12 +57,59 @@
<Add option="-g" /> <Add option="-g" />
</Compiler> </Compiler>
</Target> </Target>
<Target title="win32_A">
<Option output="..\bin\NppShellA" prefix_auto="1" extension_auto="1" />
<Option object_output="obj_A\" />
<Option type="3" />
<Option compiler="gcc" />
<Option projectCompilerOptionsRelation="1" />
<Compiler>
<Add option="-fexpensive-optimizations" />
<Add option="-Os" />
<Add option="-O3" />
<Add option="-Wextra" />
<Add option="-Wall" />
<Add option="-D_WIN32_WINNT=0x600" />
<Add option="-DWIN32_LEAN_AND_MEAN" />
</Compiler>
<Linker>
<Add option="-s" />
</Linker>
</Target>
<Target title="win32_AD">
<Option output="..\bin\NppShellA_D" prefix_auto="1" extension_auto="1" />
<Option object_output="obj_AD\" />
<Option type="3" />
<Option compiler="gcc" />
<Option projectCompilerOptionsRelation="1" />
<Compiler>
<Add option="-Wall" />
<Add option="-g" />
<Add option="-D_WIN32_WINNT=0x600" />
<Add option="-DWIN32_LEAN_AND_MEAN" />
</Compiler>
</Target>
</Build> </Build>
<Compiler> <Compiler>
<Add option="-Wshadow" />
<Add option="-Winit-self" />
<Add option="-Wredundant-decls" />
<Add option="-Wcast-align" />
<Add option="-Wundef" />
<Add option="-Wfloat-equal" />
<Add option="-Winline" />
<Add option="-Wunreachable-code" />
<Add option="-Wmissing-declarations" />
<Add option="-Wmissing-include-dirs" />
<Add option="-Wswitch-enum" />
<Add option="-Wswitch-default" />
<Add option="-Weffc++" />
<Add option="-pedantic" />
<Add option="-Wextra" />
<Add option="-Wall" /> <Add option="-Wall" />
<Add option="-fno-exceptions" /> <Add option="-fno-exceptions" />
<Add option="-D_WIN32_WINNT=0x500" /> <Add option="-fno-rtti" />
<Add option="-DGIL_DEFAULTICON=0x0040" /> <Add option="-D_WIN32_WINNT=0x600" />
<Add option="-DWIN32_LEAN_AND_MEAN" /> <Add option="-DWIN32_LEAN_AND_MEAN" />
<Add option="-DUNICODE" /> <Add option="-DUNICODE" />
<Add option="-D_UNICODE" /> <Add option="-D_UNICODE" />
@ -70,19 +122,21 @@
<Add library="shlwapi" /> <Add library="shlwapi" />
<Add library="ole32" /> <Add library="ole32" />
<Add library="uuid" /> <Add library="uuid" />
<Add library="msimg32" />
</Linker> </Linker>
<Unit filename="..\src\Bitmap.cpp" />
<Unit filename="..\src\Bitmap.h" />
<Unit filename="..\src\NppShell.cpp" /> <Unit filename="..\src\NppShell.cpp" />
<Unit filename="..\src\NppShell.h" /> <Unit filename="..\src\NppShell.h" />
<Unit filename="..\src\NppShell.rc"> <Unit filename="..\src\NppShell.rc">
<Option compilerVar="WINDRES" /> <Option compilerVar="WINDRES" />
</Unit> </Unit>
<Unit filename="..\src\export.def" /> <Unit filename="..\src\export.def" />
<Unit filename="..\src\icon\npp_0.ico" />
<Unit filename="..\src\icon\npp_1.ico" />
<Unit filename="..\src\resource.h" /> <Unit filename="..\src\resource.h" />
<Extensions> <Extensions>
<code_completion /> <code_completion />
<debugger /> <debugger />
<envvars />
</Extensions> </Extensions>
</Project> </Project>
</CodeBlocks_project_file> </CodeBlocks_project_file>

View File

@ -1,7 +1,38 @@
//From: Visual Style Menus in MSDN //From: Visual Style Menus in MSDN
#include "Bitmap.h" #include "Bitmap.h"
#include <uxtheme.h>
HMODULE hUxTheme = NULL;
FN_GetBufferedPaintBits pfnGetBufferedPaintBits = NULL;
FN_BeginBufferedPaint pfnBeginBufferedPaint = NULL;
FN_EndBufferedPaint pfnEndBufferedPaint = NULL;
bool InitTheming() {
hUxTheme = ::LoadLibrary(TEXT("UxTheme.dll"));
if (hUxTheme == NULL)
return false;
pfnGetBufferedPaintBits = (FN_GetBufferedPaintBits)::GetProcAddress(hUxTheme, "GetBufferedPaintBits");
pfnBeginBufferedPaint = (FN_BeginBufferedPaint)::GetProcAddress(hUxTheme, "BeginBufferedPaint");
pfnEndBufferedPaint = (FN_EndBufferedPaint)::GetProcAddress(hUxTheme, "EndBufferedPaint");
if ((pfnGetBufferedPaintBits == NULL) | (pfnBeginBufferedPaint == NULL) | (pfnEndBufferedPaint == NULL)) {
pfnGetBufferedPaintBits = NULL;
pfnBeginBufferedPaint = NULL;
pfnEndBufferedPaint = NULL;
return false;
}
return true;
}
bool DeinitTheming() {
pfnGetBufferedPaintBits = NULL;
pfnBeginBufferedPaint = NULL;
pfnEndBufferedPaint = NULL;
FreeLibrary(hUxTheme);
hUxTheme = NULL;
return true;
}
void InitBitmapInfo(BITMAPINFO *pbmi, ULONG cbInfo, LONG cx, LONG cy, WORD bpp) void InitBitmapInfo(BITMAPINFO *pbmi, ULONG cbInfo, LONG cx, LONG cy, WORD bpp)
{ {
@ -101,7 +132,7 @@ HRESULT ConvertBufferToPARGB32(HPAINTBUFFER hPaintBuffer, HDC hdc, HICON hicon,
{ {
RGBQUAD *prgbQuad; RGBQUAD *prgbQuad;
int cxRow; int cxRow;
HRESULT hr = GetBufferedPaintBits(hPaintBuffer, &prgbQuad, &cxRow); HRESULT hr = pfnGetBufferedPaintBits(hPaintBuffer, &prgbQuad, &cxRow);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
ARGB *pargb = reinterpret_cast<ARGB *>(prgbQuad); ARGB *pargb = reinterpret_cast<ARGB *>(prgbQuad);
@ -123,3 +154,148 @@ HRESULT ConvertBufferToPARGB32(HPAINTBUFFER hPaintBuffer, HDC hdc, HICON hicon,
return hr; return hr;
} }
HBITMAP IconToBitmapPARGB32(HICON hIcon, DWORD cx, DWORD cy)
{
HRESULT hr = E_OUTOFMEMORY;
HBITMAP hBmp = NULL;
if(!hIcon)
return NULL;
SIZE sizIcon;
sizIcon.cx = cx;
sizIcon.cy = cy;
RECT rcIcon;
SetRect(&rcIcon, 0, 0, sizIcon.cx, sizIcon.cy);
HDC hdcDest = CreateCompatibleDC(NULL);
if(hdcDest) {
hr = Create32BitHBITMAP(hdcDest, &sizIcon, NULL, &hBmp);
if(SUCCEEDED(hr)) {
hr = E_FAIL;
HBITMAP hbmpOld = (HBITMAP)SelectObject(hdcDest, hBmp);
if(hbmpOld) {
BLENDFUNCTION bfAlpha = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
BP_PAINTPARAMS paintParams = {0, 0, 0, 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 icon did not have an alpha channel, we need to convert buffer to PARGB.
hr = ConvertBufferToPARGB32(hPaintBuffer, hdcDest, hIcon, sizIcon);
}
// This will write the buffer contents to the destination bitmap.
pfnEndBufferedPaint(hPaintBuffer, TRUE);
}
SelectObject(hdcDest, hbmpOld);
}
}
DeleteDC(hdcDest);
}
DestroyIcon(hIcon);
if(SUCCEEDED(hr)) {
return hBmp;
}
DeleteObject(hBmp);
return NULL;
}
/*
// LoadIconEx: Loads an icon with a specific size and color depth. This function
// will NOT try to strech or take an icon of another color depth if none is
// present.
HICON LoadIconEx(HINSTANCE hInstance, LPCTSTR lpszName, int cx, int cy, int depth)
{
HRSRC hRsrcIconGroup;
// Load the icon group of the desired icon
if (!(hRsrcIconGroup=FindResource(hInstance,lpszName,RT_GROUP_ICON)))
return NULL;
// Look for the specified color depth
// Load the resource
GRPICONDIR* pGrpIconDir;
HRSRC hGlobalIconDir;
if (!(hGlobalIconDir=(HRSRC)LoadResource(hInstance,hRsrcIconGroup)))
return NULL;
// Lock the resource
if (!(pGrpIconDir=(GRPICONDIR*) LockResource(hGlobalIconDir)))
return NULL;
// Cycle through all icon images trying to find the one we're looking for
int i;
BOOL bFound=FALSE;
// In case of 8bpp or higher, the bColorCount of the structure is 0, and we
// must find our icon with the wPlanes and wBitCount. So if the requested
// number of colors is >=256, we calculate using those fields
int bestIndex = -1;
int bestDepth = -1; //depth of icon either has to be equal (best match) or larger, or no best icon found
int bestSize = -1; //Size either has to be equal (best match) or smaller
int nrColors = 1 << depth;
for (i=0;i<pGrpIconDir->idCount;i++)
{
GRPICONDIRENTRY & entry = pGrpIconDir->idEntries[i];
int iconColors = (entry.bColorCount==0)?1 << (entry.wPlanes*entry.wBitCount) : entry.bColorCount;
if (iconColors < bestDepth);
if ((entry.bWidth==cx) && (entry.bHeight==cy)) // Do the size match?
{
bFound = TRUE; // Yes, it matches
break;
}
}
if (!bFound)
return NULL; // No icon was found matching the specs
// Icon was found! i contains the index to the GRPICONDIR structure in the
// icon group. Find the ID of the icon
int nID;
nID=pGrpIconDir->idEntries[i].nID;
// Now, find the actual icon resource
HRSRC hRsrcIcon;
HRSRC hGlobalIcon;
void* pIconBits;
if (!(hRsrcIcon=FindResource(hInstance,MAKEINTRESOURCE(nID),RT_ICON)))
return NULL;
if (!(hGlobalIcon=(HRSRC)LoadResource(hInstance,hRsrcIcon)))
return NULL;
if (!(pIconBits=LockResource(hGlobalIcon)))
return NULL;
// Now, use CreateIconFromResourceEx to create the actual HICON
return CreateIconFromResourceEx(
(unsigned char*) pIconBits, // Pointer to icon data
pGrpIconDir->idEntries[i].dwBytesInRes, // Size of icon data
TRUE, // TRUE to create an icon, not a cursor
0x00030000, // Version number. MSDN says to put that number
cx, cy, // Width and height
0); // Flags (none)
}
*/

View File

@ -1,10 +1,43 @@
#include <windows.h> #include <windows.h>
#include <uxtheme.h> #include <uxtheme.h>
#define BPPF_ERASE 1
typedef DWORD ARGB; typedef DWORD ARGB;
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);
bool InitTheming();
bool DeinitTheming();
void InitBitmapInfo(BITMAPINFO *pbmi, ULONG cbInfo, LONG cx, LONG cy, WORD bpp); void InitBitmapInfo(BITMAPINFO *pbmi, ULONG cbInfo, LONG cx, LONG cy, WORD bpp);
HRESULT Create32BitHBITMAP(HDC hdc, const SIZE *psize, void **ppvBits, HBITMAP* phBmp); HRESULT Create32BitHBITMAP(HDC hdc, const SIZE *psize, void **ppvBits, HBITMAP* phBmp);
HRESULT ConvertToPARGB32(HDC hdc, ARGB *pargb, HBITMAP hbmp, SIZE& sizImage, int cxRow); HRESULT ConvertToPARGB32(HDC hdc, ARGB *pargb, HBITMAP hbmp, SIZE& sizImage, int cxRow);
bool HasAlpha(ARGB *pargb, SIZE& sizImage, int cxRow); bool HasAlpha(ARGB *pargb, SIZE& sizImage, int cxRow);
HRESULT ConvertBufferToPARGB32(HPAINTBUFFER hPaintBuffer, HDC hdc, HICON hicon, SIZE& sizIcon); HRESULT ConvertBufferToPARGB32(HPAINTBUFFER hPaintBuffer, HDC hdc, HICON hicon, SIZE& sizIcon);
HBITMAP IconToBitmapPARGB32(HICON hIcon, DWORD cx, DWORD cy);
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;
HICON LoadIconEx(HINSTANCE hInst, LPCTSTR lpszName, int cz, int cy, int depth);

View File

@ -1,11 +1,13 @@
#include "NppShell.h" #include "NppShell.h"
//#include "Bitmap.h" #include "Bitmap.h"
#include "resource.h" #include "resource.h"
#include <shellapi.h> #include <shellapi.h>
#include <algorithm> #include <algorithm>
//#include <wincodec.h> #ifndef RGBA
#define RGBA(r,g,b,a) ((COLORREF)( (((DWORD)(BYTE)(a))<<24) | RGB(r,g,b) ))
#endif
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -14,20 +16,18 @@
UINT _cRef = 0; // COM Reference count. UINT _cRef = 0; // COM Reference count.
HINSTANCE _hModule = NULL; // DLL Module. HINSTANCE _hModule = NULL; // DLL Module.
//Some global default values for registering the DLL
//Menu //Menu
TCHAR szNppName[] = TEXT("notepad++.exe"); TCHAR szNppName[] = TEXT("notepad++.exe");
#ifdef UNICODE
TCHAR szDefaultMenutext[] = TEXT("Edit with &Notepad++"); TCHAR szDefaultMenutext[] = TEXT("Edit with &Notepad++");
#else
TCHAR szDefaultMenutext[] = TEXT("Edit with &Notepad++");
#endif
#ifdef WIN64 #ifdef WIN64
TCHAR szShellExtensionTitle[] = TEXT("Notepad++64"); TCHAR szShellExtensionTitle[] = TEXT("Notepad++64");
#define sz64 TEXT("64") TCHAR szShellExtensionKey[] = TEXT("*\\shellex\\ContextMenuHandlers\\Notepad++64");
#else #else
TCHAR szShellExtensionTitle[] = TEXT("Notepad++"); TCHAR szShellExtensionTitle[] = TEXT("Notepad++");
#define sz64 TEXT("") TCHAR szShellExtensionKey[] = TEXT("*\\shellex\\ContextMenuHandlers\\Notepad++");
#endif #endif
#define szHelpTextA "Edits the selected file(s) with Notepad++" #define szHelpTextA "Edits the selected file(s) with Notepad++"
@ -37,10 +37,13 @@ TCHAR szDefaultCustomcommand[] = TEXT("");
//Icon //Icon
DWORD isDynamic = 1; DWORD isDynamic = 1;
DWORD maxText = 25; DWORD maxText = 25;
DWORD iconID = 0;
DWORD showIcon = 1; DWORD showIcon = 1;
//Forward function declarations //Forward function declarations
extern "C" int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved);
STDAPI DllRegisterServer(void);
STDAPI DllUnregisterServer(void);
BOOL RegisterServer(); BOOL RegisterServer();
BOOL UnregisterServer(); BOOL UnregisterServer();
void MsgBox(LPCTSTR lpszMsg); void MsgBox(LPCTSTR lpszMsg);
@ -66,11 +69,10 @@ struct DOREGSTRUCT {
LPCTSTR szData; LPCTSTR szData;
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// DllMain // DllMain
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
extern "C" int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/) {
if (dwReason == DLL_PROCESS_ATTACH) { if (dwReason == DLL_PROCESS_ATTACH) {
_hModule = hInstance; _hModule = hInstance;
} }
@ -110,7 +112,7 @@ STDAPI DllUnregisterServer(void) {
return (UnregisterServer() ? S_OK : E_FAIL); return (UnregisterServer() ? S_OK : E_FAIL);
} }
STDAPI DllInstall(BOOL bInstall, LPCWSTR pszCmdLine) { STDAPI DllInstall(BOOL bInstall, LPCWSTR /*pszCmdLine*/) {
if (bInstall) { if (bInstall) {
DialogBox(_hModule, MAKEINTRESOURCE(IDD_DIALOG_SETTINGS), NULL, (DLGPROC)&DlgProcSettings); DialogBox(_hModule, MAKEINTRESOURCE(IDD_DIALOG_SETTINGS), NULL, (DLGPROC)&DlgProcSettings);
return S_OK; return S_OK;
@ -163,11 +165,10 @@ BOOL RegisterServer() {
// Icon // Icon
{HKEY_CLASSES_ROOT, TEXT("CLSID\\%s\\Settings"), TEXT("Dynamic"), REG_DWORD, (LPTSTR)&isDynamic}, {HKEY_CLASSES_ROOT, TEXT("CLSID\\%s\\Settings"), TEXT("Dynamic"), REG_DWORD, (LPTSTR)&isDynamic},
{HKEY_CLASSES_ROOT, TEXT("CLSID\\%s\\Settings"), TEXT("Maxtext"), REG_DWORD, (LPTSTR)&maxText}, {HKEY_CLASSES_ROOT, TEXT("CLSID\\%s\\Settings"), TEXT("Maxtext"), REG_DWORD, (LPTSTR)&maxText},
{HKEY_CLASSES_ROOT, TEXT("CLSID\\%s\\Settings"), TEXT("IconID"), REG_DWORD, (LPTSTR)&iconID},
//Registration //Registration
// Context menu // Context menu
{HKEY_CLASSES_ROOT, TEXT("*\\shellex\\ContextMenuHandlers\\Notepad++")sz64, NULL, REG_SZ, szGUID}, {HKEY_CLASSES_ROOT, szShellExtensionKey, NULL, REG_SZ, szGUID},
// Icon // Icon
//{HKEY_CLASSES_ROOT, TEXT("Notepad++_file\\shellex\\IconHandler"), NULL, REG_SZ, szGUID}, //{HKEY_CLASSES_ROOT, TEXT("Notepad++_file\\shellex\\IconHandler"), NULL, REG_SZ, szGUID},
@ -204,8 +205,7 @@ BOOL RegisterServer() {
BOOL UnregisterServer() { BOOL UnregisterServer() {
TCHAR szKeyTemp[MAX_PATH + GUID_STRING_SIZE]; TCHAR szKeyTemp[MAX_PATH + GUID_STRING_SIZE];
wsprintf(szKeyTemp, TEXT("*\\shellex\\ContextMenuHandlers\\%s"), szShellExtensionTitle); RegDeleteKey(HKEY_CLASSES_ROOT, szShellExtensionKey);
RegDeleteKey(HKEY_CLASSES_ROOT, szKeyTemp);
wsprintf(szKeyTemp, TEXT("Notepad++_file\\shellex\\IconHandler")); wsprintf(szKeyTemp, TEXT("Notepad++_file\\shellex\\IconHandler"));
RegDeleteKey(HKEY_CLASSES_ROOT, szKeyTemp); RegDeleteKey(HKEY_CLASSES_ROOT, szKeyTemp);
@ -265,11 +265,7 @@ INT_PTR CALLBACK DlgProcSettings(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM
static TCHAR szKeyTemp[MAX_PATH + GUID_STRING_SIZE]; static TCHAR szKeyTemp[MAX_PATH + GUID_STRING_SIZE];
static DWORD showMenu = 2; //0 off, 1 on, 2 unknown static DWORD showMenu = 2; //0 off, 1 on, 2 unknown
static DWORD showIcon = 2;
static DWORD isDynamic = 1; //0 off, 1 on
static DWORD useMenuIcon = 1; // 0 off, otherwise on static DWORD useMenuIcon = 1; // 0 off, otherwise on
static DWORD iconType = 0; //0 classic, 1 modern
HKEY settingKey; HKEY settingKey;
LONG result; LONG result;
@ -292,12 +288,6 @@ INT_PTR CALLBACK DlgProcSettings(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM
lstrcpyn(customCommand, TEXT(""), MAX_PATH); lstrcpyn(customCommand, TEXT(""), MAX_PATH);
} }
size = sizeof(DWORD);
result = RegQueryValueEx(settingKey, TEXT("IconID"), NULL, NULL, (BYTE*)(&iconType), &size);
if (result != ERROR_SUCCESS) {
iconType = 0;
}
size = sizeof(DWORD); size = sizeof(DWORD);
result = RegQueryValueEx(settingKey, TEXT("Dynamic"), NULL, NULL, (BYTE*)(&isDynamic), &size); result = RegQueryValueEx(settingKey, TEXT("Dynamic"), NULL, NULL, (BYTE*)(&isDynamic), &size);
if (result != ERROR_SUCCESS) { if (result != ERROR_SUCCESS) {
@ -319,9 +309,6 @@ INT_PTR CALLBACK DlgProcSettings(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM
Button_SetCheck(GetDlgItem(hwndDlg, IDC_CHECK_CONTEXTICON), useMenuIcon?BST_CHECKED:BST_UNCHECKED); Button_SetCheck(GetDlgItem(hwndDlg, IDC_CHECK_CONTEXTICON), useMenuIcon?BST_CHECKED:BST_UNCHECKED);
Button_SetCheck(GetDlgItem(hwndDlg, IDC_CHECK_ISDYNAMIC), isDynamic?BST_CHECKED:BST_UNCHECKED); Button_SetCheck(GetDlgItem(hwndDlg, IDC_CHECK_ISDYNAMIC), isDynamic?BST_CHECKED:BST_UNCHECKED);
Button_SetCheck(GetDlgItem(hwndDlg, IDC_RADIO_CLASSIC), iconType!=0?BST_CHECKED:BST_UNCHECKED);
Button_SetCheck(GetDlgItem(hwndDlg, IDC_RADIO_MODERN), iconType==0?BST_CHECKED:BST_UNCHECKED);
SetDlgItemText(hwndDlg, IDC_EDIT_MENU, customText); SetDlgItemText(hwndDlg, IDC_EDIT_MENU, customText);
SetDlgItemText(hwndDlg, IDC_EDIT_COMMAND, customCommand); SetDlgItemText(hwndDlg, IDC_EDIT_COMMAND, customCommand);
@ -343,7 +330,6 @@ INT_PTR CALLBACK DlgProcSettings(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM
result = RegSetValueEx(settingKey, TEXT("Title"), 0,REG_SZ, (LPBYTE)customText, (textLen+1)*sizeof(TCHAR)); result = RegSetValueEx(settingKey, TEXT("Title"), 0,REG_SZ, (LPBYTE)customText, (textLen+1)*sizeof(TCHAR));
result = RegSetValueEx(settingKey, TEXT("Custom"), 0,REG_SZ, (LPBYTE)customCommand, (commandLen+1)*sizeof(TCHAR)); result = RegSetValueEx(settingKey, TEXT("Custom"), 0,REG_SZ, (LPBYTE)customCommand, (commandLen+1)*sizeof(TCHAR));
result = RegSetValueEx(settingKey, TEXT("IconID"), 0, REG_DWORD, (LPBYTE)&iconType, sizeof(DWORD));
result = RegSetValueEx(settingKey, TEXT("Dynamic"), 0, REG_DWORD, (LPBYTE)&isDynamic, sizeof(DWORD)); result = RegSetValueEx(settingKey, TEXT("Dynamic"), 0, REG_DWORD, (LPBYTE)&isDynamic, sizeof(DWORD));
result = RegSetValueEx(settingKey, TEXT("ShowIcon"), 0, REG_DWORD, (LPBYTE)&useMenuIcon, sizeof(DWORD)); result = RegSetValueEx(settingKey, TEXT("ShowIcon"), 0, REG_DWORD, (LPBYTE)&useMenuIcon, sizeof(DWORD));
@ -351,14 +337,13 @@ INT_PTR CALLBACK DlgProcSettings(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM
} }
if (showMenu == 1) { if (showMenu == 1) {
result = RegCreateKeyEx(HKEY_CLASSES_ROOT, TEXT("*\\shellex\\ContextMenuHandlers\\Notepad++")sz64, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &settingKey, NULL); result = RegCreateKeyEx(HKEY_CLASSES_ROOT, szShellExtensionKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &settingKey, NULL);
if (result == ERROR_SUCCESS) { if (result == ERROR_SUCCESS) {
result = RegSetValueEx(settingKey, NULL, 0,REG_SZ, (LPBYTE)szGUID, (lstrlen(szGUID)+1)*sizeof(TCHAR)); result = RegSetValueEx(settingKey, NULL, 0,REG_SZ, (LPBYTE)szGUID, (lstrlen(szGUID)+1)*sizeof(TCHAR));
RegCloseKey(settingKey); RegCloseKey(settingKey);
} }
} else if (showMenu == 0) { } else if (showMenu == 0) {
wsprintf(szKeyTemp, TEXT("*\\shellex\\ContextMenuHandlers\\%s")sz64, szShellExtensionTitle); RegDeleteKey(HKEY_CLASSES_ROOT, szShellExtensionKey);
RegDeleteKey(HKEY_CLASSES_ROOT, szKeyTemp);
} }
if (showIcon == 1) { if (showIcon == 1) {
@ -406,20 +391,8 @@ INT_PTR CALLBACK DlgProcSettings(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM
else else
isDynamic = 0; isDynamic = 0;
break; } break; }
case IDC_RADIO_CLASSIC: { default:
int state = Button_GetCheck((HWND)lParam); break;
if (state == BST_CHECKED)
iconType = 1;
else
iconType = 0;
break; }
case IDC_RADIO_MODERN: {
int state = Button_GetCheck((HWND)lParam);
if (state == BST_CHECKED)
iconType = 0;
else
iconType = 1;
break; }
} }
return TRUE; return TRUE;
@ -428,14 +401,17 @@ INT_PTR CALLBACK DlgProcSettings(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM
EndDialog(hwndDlg, 0); EndDialog(hwndDlg, 0);
return TRUE; return TRUE;
break; } break; }
default:
break;
} }
return FALSE; return FALSE;
} }
// --- CShellExtClassFactory --- // --- CShellExtClassFactory ---
CShellExtClassFactory::CShellExtClassFactory() { CShellExtClassFactory::CShellExtClassFactory() :
m_cRef = 0L; m_cRef(0L)
{
_cRef++; _cRef++;
} }
@ -477,30 +453,44 @@ STDMETHODIMP CShellExtClassFactory::CreateInstance(LPUNKNOWN pUnkOuter, REFIID r
return pShellExt->QueryInterface(riid, ppvObj); return pShellExt->QueryInterface(riid, ppvObj);
} }
STDMETHODIMP CShellExtClassFactory::LockServer(BOOL fLock) { STDMETHODIMP CShellExtClassFactory::LockServer(BOOL /*fLock*/) {
return NOERROR; return NOERROR;
} }
// --- CShellExt --- // --- CShellExt ---
CShellExt::CShellExt() { CShellExt::CShellExt() :
m_cRef(0L),
m_cbFiles(0),
m_pDataObj(NULL),
m_menuID(0),
m_hMenu(NULL),
m_showIcon(true),
m_useCustom(false),
m_nameLength(0),
m_nameMaxLength(maxText),
m_isDynamic(false),
m_winVer(0)
{
TCHAR szKeyTemp [MAX_PATH + GUID_STRING_SIZE]; TCHAR szKeyTemp [MAX_PATH + GUID_STRING_SIZE];
ZeroMemory(&m_stgMedium, sizeof(m_stgMedium));
m_cRef = 0L;
m_pDataObj = NULL;
_cRef++; _cRef++;
m_useCustom = false;
m_nameLength = 0;
m_nameMaxLength = maxText;
m_isDynamic = false;
m_iconID = 0;
m_showIcon = true;
GetModuleFileName(_hModule, m_szModule, MAX_PATH); GetModuleFileName(_hModule, m_szModule, MAX_PATH);
OSVERSIONINFOEX inf;
ZeroMemory(&inf, sizeof(OSVERSIONINFOEX));
inf.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
GetVersionEx((OSVERSIONINFO *)&inf);
m_winVer = MAKEWORD(inf.dwMinorVersion, inf.dwMajorVersion);
if (m_winVer >= WINVER_VISTA) {
InitTheming();
}
HKEY settingKey; HKEY settingKey;
LONG result; LONG result;
DWORD size = 0; DWORD size = 0;
DWORD dyn = 0, siz = 0, id = 0, showicon; DWORD dyn = 0, siz = 0, showicon = 0;
wsprintf(szKeyTemp, TEXT("CLSID\\%s\\Settings"), szGUID); wsprintf(szKeyTemp, TEXT("CLSID\\%s\\Settings"), szGUID);
result = RegOpenKeyEx(HKEY_CLASSES_ROOT, szKeyTemp, 0, KEY_READ, &settingKey); result = RegOpenKeyEx(HKEY_CLASSES_ROOT, szKeyTemp, 0, KEY_READ, &settingKey);
@ -511,12 +501,6 @@ CShellExt::CShellExt() {
lstrcpyn(m_szMenuTitle, szDefaultMenutext, TITLE_SIZE); lstrcpyn(m_szMenuTitle, szDefaultMenutext, TITLE_SIZE);
} }
size = sizeof(DWORD);
result = RegQueryValueEx(settingKey, TEXT("IconID"), NULL, NULL, (BYTE*)(&id), &size);
if (result == ERROR_SUCCESS) {
m_iconID = std::max((DWORD)0,id);
}
size = sizeof(DWORD); size = sizeof(DWORD);
result = RegQueryValueEx(settingKey, TEXT("Dynamic"), NULL, NULL, (BYTE*)(&dyn), &size); result = RegQueryValueEx(settingKey, TEXT("Dynamic"), NULL, NULL, (BYTE*)(&dyn), &size);
if (result == ERROR_SUCCESS && dyn != 0) { if (result == ERROR_SUCCESS && dyn != 0) {
@ -547,6 +531,10 @@ CShellExt::CShellExt() {
} }
CShellExt::~CShellExt() { CShellExt::~CShellExt() {
if (m_winVer >= WINVER_VISTA) {
DeinitTheming();
}
if (m_pDataObj) if (m_pDataObj)
m_pDataObj->Release(); m_pDataObj->Release();
_cRef--; _cRef--;
@ -589,7 +577,7 @@ STDMETHODIMP_(ULONG) CShellExt::Release() {
} }
// *** IShellExtInit methods *** // *** IShellExtInit methods ***
STDMETHODIMP CShellExt::Initialize(LPCITEMIDLIST pIDFolder, LPDATAOBJECT pDataObj, HKEY hRegKey) { STDMETHODIMP CShellExt::Initialize(LPCITEMIDLIST /*pIDFolder*/, LPDATAOBJECT pDataObj, HKEY /*hRegKey*/) {
if (m_pDataObj) { if (m_pDataObj) {
m_pDataObj->Release(); m_pDataObj->Release();
m_pDataObj = NULL; m_pDataObj = NULL;
@ -602,7 +590,7 @@ STDMETHODIMP CShellExt::Initialize(LPCITEMIDLIST pIDFolder, LPDATAOBJECT pDataOb
} }
// *** IContextMenu methods *** // *** IContextMenu methods ***
STDMETHODIMP CShellExt::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) { STDMETHODIMP CShellExt::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT /*idCmdLast*/, UINT /*uFlags*/) {
UINT idCmd = idCmdFirst; UINT idCmd = idCmdFirst;
FORMATETC fmte = { FORMATETC fmte = {
@ -624,38 +612,44 @@ STDMETHODIMP CShellExt::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmd
InsertMenu(hMenu, nIndex, MF_STRING|MF_BYPOSITION, idCmd++, m_szMenuTitle); InsertMenu(hMenu, nIndex, MF_STRING|MF_BYPOSITION, idCmd++, m_szMenuTitle);
HBITMAP icon = NULL; if (m_showIcon) {
if (m_showIcon) {/* HBITMAP icon = NULL;
if (m_supportARGB32) { if (m_winVer >= WINVER_VISTA) {
icon = NULL; icon = NULL;
HICON hicon; HICON hicon;
DWORD menuIconWidth = GetSystemMetrics(SM_CXMENUCHECK); DWORD menuIconWidth = GetSystemMetrics(SM_CXMENUCHECK);
DWORD menuIconHeight = GetSystemMetrics(SM_CYMENUCHECK); DWORD menuIconHeight = GetSystemMetrics(SM_CYMENUCHECK);
HRESULT hr = LoadShellIcon(menuIconWidth, menuIconHeight, &hicon); HRESULT hr = LoadShellIcon(menuIconWidth, menuIconHeight, &hicon);
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
HBITMAP hbitmap; icon = IconToBitmapPARGB32(hicon, menuIconWidth, menuIconHeight);
LoadARGBBitmap(hicon, menuIconWidth, menuIconHeight, &hbitmap); DestroyIcon(hicon);
if (SUCCEEDED(hr)) {
icon = hbitmap;
}
} }
} else { } else {
icon = HBMMENU_CALLBACK; icon = HBMMENU_CALLBACK;
}*/ }
DWORD menuIconWidth = GetSystemMetrics(SM_CXMENUCHECK);
DWORD menuIconHeight = GetSystemMetrics(SM_CYMENUCHECK);
HRESULT hr = LoadShellBitmap(menuIconWidth, menuIconHeight, &icon);
if (FAILED(hr))
MsgBoxError(TEXT("Help"));
}
MENUITEMINFO mii; if (icon != NULL) {
ZeroMemory(&mii, sizeof(mii)); MENUITEMINFO mii;
mii.cbSize = sizeof(mii); ZeroMemory(&mii, sizeof(mii));
mii.fMask = MIIM_BITMAP; mii.cbSize = sizeof(mii);
mii.hbmpItem = icon; mii.fMask = MIIM_BITMAP;
//SetMenuItemInfo(hMenu, nIndex, MF_BYPOSITION, &mii); mii.hbmpItem = icon;
SetMenuItemBitmaps(hMenu, nIndex, MF_BYPOSITION, icon, icon); //mii.hbmpChecked = icon;
//mii.hbmpUnchecked = icon;
SetMenuItemInfo(hMenu, nIndex, MF_BYPOSITION, &mii);
if (m_winVer >= WINVER_VISTA) {
MENUINFO MenuInfo;
MenuInfo.cbSize = sizeof(MenuInfo);
MenuInfo.fMask = MIM_STYLE;
MenuInfo.dwStyle = MNS_CHECKORBMP;
SetMenuInfo(hMenu, &MenuInfo);
}
}
}
m_hMenu = hMenu; m_hMenu = hMenu;
m_menuID = idCmd; m_menuID = idCmd;
@ -663,11 +657,6 @@ STDMETHODIMP CShellExt::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmd
return ResultFromShort(idCmd-idCmdFirst); return ResultFromShort(idCmd-idCmdFirst);
} }
STDMETHODIMP CShellExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi) { STDMETHODIMP CShellExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi) {
HRESULT hr = E_INVALIDARG; HRESULT hr = E_INVALIDARG;
@ -677,12 +666,14 @@ STDMETHODIMP CShellExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi) {
case 0: case 0:
hr = InvokeNPP(lpcmi->hwnd, lpcmi->lpDirectory, lpcmi->lpVerb, lpcmi->lpParameters, lpcmi->nShow); hr = InvokeNPP(lpcmi->hwnd, lpcmi->lpDirectory, lpcmi->lpVerb, lpcmi->lpParameters, lpcmi->nShow);
break; break;
default:
break;
} }
} }
return hr; return hr;
} }
STDMETHODIMP CShellExt::GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT FAR *reserved, LPSTR pszName, UINT cchMax) { STDMETHODIMP CShellExt::GetCommandString(UINT_PTR /*idCmd*/, UINT uFlags, UINT FAR */*reserved*/, LPSTR pszName, UINT cchMax) {
LPWSTR wBuffer = (LPWSTR) pszName; LPWSTR wBuffer = (LPWSTR) pszName;
if (uFlags == GCS_HELPTEXTA) { if (uFlags == GCS_HELPTEXTA) {
lstrcpynA(pszName, szHelpTextA, cchMax); lstrcpynA(pszName, szHelpTextA, cchMax);
@ -694,22 +685,25 @@ STDMETHODIMP CShellExt::GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT FAR *
return E_NOTIMPL; return E_NOTIMPL;
} }
STDMETHODIMP CShellExt::HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plResult) { STDMETHODIMP CShellExt::HandleMenuMsg2(UINT uMsg, WPARAM /*wParam*/, LPARAM lParam, LRESULT *plResult) {
//Setup popup menu stuff (ownerdrawn) //Setup popup menu stuff (ownerdrawn)
DWORD menuIconWidth = GetSystemMetrics(SM_CXMENUCHECK); DWORD menuIconWidth = GetSystemMetrics(SM_CXMENUCHECK);
DWORD menuIconHeight = GetSystemMetrics(SM_CYMENUCHECK); DWORD menuIconHeight = GetSystemMetrics(SM_CYMENUCHECK);
DWORD menuIconPadding = 2; //+2 pixels on each side, is this fixed? DWORD menuIconPadding = 2; //+1 pixels on each side, is this fixed?
switch(uMsg) { switch(uMsg) {
case WM_MEASUREITEM: { //for owner drawn menu case WM_MEASUREITEM: { //for owner drawn menu
MEASUREITEMSTRUCT * lpdis = (MEASUREITEMSTRUCT*) lParam; MEASUREITEMSTRUCT * lpdis = (MEASUREITEMSTRUCT*) lParam;
if (lpdis == NULL)
if (lpdis == NULL)// || lpdis->itemID != m_menuID)
break; break;
lpdis->itemWidth += menuIconPadding; if (m_showIcon) {
if (lpdis->itemHeight < menuIconHeight) lpdis->itemWidth = 0; //0 seems to work for 98 and up
lpdis->itemHeight = menuIconHeight; if (lpdis->itemHeight < menuIconHeight)
lpdis->itemHeight = menuIconHeight;
}
if (plResult) if (plResult)
*plResult = TRUE; *plResult = TRUE;
@ -717,7 +711,6 @@ STDMETHODIMP CShellExt::HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam,
case WM_DRAWITEM: { //for owner drawn menu case WM_DRAWITEM: { //for owner drawn menu
//Assumes proper font already been set //Assumes proper font already been set
DRAWITEMSTRUCT * lpdis = (DRAWITEMSTRUCT*) lParam; DRAWITEMSTRUCT * lpdis = (DRAWITEMSTRUCT*) lParam;
if ((lpdis == NULL) || (lpdis->CtlType != ODT_MENU)) if ((lpdis == NULL) || (lpdis->CtlType != ODT_MENU))
break; break;
@ -736,13 +729,15 @@ STDMETHODIMP CShellExt::HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam,
*plResult = TRUE; *plResult = TRUE;
break; } break; }
default:
break;
} }
return S_OK; return S_OK;
} }
// *** IPersistFile methods *** // *** IPersistFile methods ***
HRESULT STDMETHODCALLTYPE CShellExt::Load(LPCOLESTR pszFileName, DWORD dwMode) { HRESULT STDMETHODCALLTYPE CShellExt::Load(LPCOLESTR pszFileName, DWORD /*dwMode*/) {
LPTSTR file[MAX_PATH]; LPTSTR file[MAX_PATH];
#ifdef UNICODE #ifdef UNICODE
lstrcpyn((LPWSTR)file, pszFileName, MAX_PATH); lstrcpyn((LPWSTR)file, pszFileName, MAX_PATH);
@ -758,6 +753,7 @@ HRESULT STDMETHODCALLTYPE CShellExt::Load(LPCOLESTR pszFileName, DWORD dwMode) {
int copySize = std::min(m_nameMaxLength+1, MAX_PATH); //+1 to take zero terminator in account int copySize = std::min(m_nameMaxLength+1, MAX_PATH); //+1 to take zero terminator in account
lstrcpyn(m_szFilePath, ext, copySize); lstrcpyn(m_szFilePath, ext, copySize);
m_nameLength = lstrlen(m_szFilePath); m_nameLength = lstrlen(m_szFilePath);
CharUpperBuff(m_szFilePath, m_nameLength);
return S_OK; return S_OK;
} }
@ -786,7 +782,7 @@ STDMETHODIMP CShellExt::GetIconLocation(UINT uFlags, LPTSTR szIconFile, UINT cch
return S_OK; return S_OK;
} }
STDMETHODIMP CShellExt::Extract(LPCTSTR pszFile, UINT nIconIndex, HICON * phiconLarge, HICON * phiconSmall, UINT nIconSize) { STDMETHODIMP CShellExt::Extract(LPCTSTR /*pszFile*/, UINT /*nIconIndex*/, HICON * phiconLarge, HICON * phiconSmall, UINT nIconSize) {
WORD sizeSmall = HIWORD(nIconSize); WORD sizeSmall = HIWORD(nIconSize);
WORD sizeLarge = LOWORD(nIconSize); WORD sizeLarge = LOWORD(nIconSize);
ICONINFO iconinfo; ICONINFO iconinfo;
@ -803,13 +799,16 @@ STDMETHODIMP CShellExt::Extract(LPCTSTR pszFile, UINT nIconIndex, HICON * phicon
return S_FALSE; return S_FALSE;
} }
if (!m_isDynamic || !phiconLarge) //No modifications required if (!m_isDynamic || !phiconLarge || sizeLarge < 32) //No modifications required
return S_OK; return S_OK;
HDC dcEditColor, dcEditMask; HDC dcEditColor, dcEditMask, dcEditTemp;
HGDIOBJ oldBitmapColor, oldBitmapMask, oldFontColor;
HFONT font; HFONT font;
HBRUSH brush; HBRUSH brush;
HPEN pen;
BITMAPINFO bmi;
HBITMAP hbm;
LPDWORD pPix;
res = GetIconInfo(*phiconLarge, &iconinfo); res = GetIconInfo(*phiconLarge, &iconinfo);
if (!res) if (!res)
@ -823,71 +822,116 @@ STDMETHODIMP CShellExt::Extract(LPCTSTR pszFile, UINT nIconIndex, HICON * phicon
dcEditColor = CreateCompatibleDC(GetDC(0)); dcEditColor = CreateCompatibleDC(GetDC(0));
dcEditMask = CreateCompatibleDC(GetDC(0)); dcEditMask = CreateCompatibleDC(GetDC(0));
oldBitmapColor = SelectObject(dcEditColor, iconinfo.hbmColor); dcEditTemp = CreateCompatibleDC(GetDC(0));
oldBitmapMask = SelectObject(dcEditMask, iconinfo.hbmMask);
// Create temp bitmap to render rectangle to
ZeroMemory(&bmi, sizeof(bmi));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = sizeLarge;
bmi.bmiHeader.biHeight = sizeLarge;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
hbm = CreateDIBSection(dcEditTemp, &bmi, DIB_RGB_COLORS, (VOID**)&pPix, NULL, 0);
memset(pPix, 0x00FFFFFF, sizeof(DWORD)*sizeLarge*sizeLarge); //initialize to white pixels, no alpha
SelectObject(dcEditColor, iconinfo.hbmColor);
SelectObject(dcEditMask, iconinfo.hbmMask);
SelectObject(dcEditTemp, hbm);
LONG calSize = (LONG)(sizeLarge*2/5); LONG calSize = (LONG)(sizeLarge*2/5);
LOGFONT lf = {0};
lf.lfHeight = std::min(calSize, (LONG)15); //this is in pixels. Make no larger than 15 pixels (but smaller is allowed for small icons) LOGFONT lf = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0}};
lf.lfHeight = calSize;
lf.lfWeight = FW_NORMAL; lf.lfWeight = FW_NORMAL;
lf.lfCharSet = DEFAULT_CHARSET; lf.lfCharSet = DEFAULT_CHARSET;
lstrcpyn(lf.lfFaceName, TEXT("Bitstream Vera Sans Mono"), LF_FACESIZE); lstrcpyn(lf.lfFaceName, TEXT("Courier New"), LF_FACESIZE);
LOGBRUSH lbrush; RECT rectText = {0, 0, 0, 0};
lbrush.lbStyle = BS_SOLID; RECT rectBox = {0, 0, 0, 0};
lbrush.lbHatch = 0; COLORREF backGround = RGB(1, 1, 60);
RECT rect = {0}; COLORREF textColor = RGB(250,250,250);
COLORREF backGround = RGB(1, 1, 1);
COLORREF textColor = RGB(255,255,255);
//Grab the topleft pixel as the background color
COLORREF maskBack = GetPixel(dcEditColor, 0, 0);
if (backGround == maskBack)
backGround++; //add one, shouldn't be very visible
font = CreateFontIndirect(&lf); font = CreateFontIndirect(&lf);
lbrush.lbColor = backGround; brush = CreateSolidBrush(backGround);
brush = CreateBrushIndirect(&lbrush); pen = CreatePen(PS_NULL, 0, backGround);
oldFontColor = SelectObject(dcEditColor, font); SelectObject(dcEditTemp, font);
SelectObject(dcEditTemp, brush);
SetBkMode(dcEditColor, TRANSPARENT); //dont clear background when drawing text (doesnt change much, colors are the same) SelectObject(dcEditTemp, pen);
SetBkColor(dcEditColor, backGround); SetBkMode(dcEditTemp, TRANSPARENT); //dont clear background when drawing text
SetTextColor(dcEditColor, textColor); SetBkColor(dcEditTemp, backGround);
SetTextColor(dcEditTemp, textColor);
//Calculate size of the displayed string
SIZE stringSize; SIZE stringSize;
GetTextExtentPoint32(dcEditColor, m_szFilePath, m_nameLength, &stringSize); GetTextExtentPoint32(dcEditTemp, m_szFilePath, m_nameLength, &stringSize);
stringSize.cx = std::min(stringSize.cx, (LONG)sizeLarge-2); stringSize.cx = std::min(stringSize.cx, (LONG)sizeLarge-2);
stringSize.cy = std::min(stringSize.cy, (LONG)sizeLarge-2); stringSize.cy = std::min(stringSize.cy, (LONG)sizeLarge-2);
rect.top = sizeLarge - stringSize.cy - 2; rectText.top = sizeLarge - stringSize.cy - 1;
rect.left = sizeLarge - stringSize.cx - 1; rectText.left = sizeLarge - stringSize.cx - 1;
rect.bottom = sizeLarge; rectText.bottom = sizeLarge - 1;
rect.right = sizeLarge-1; rectText.right = sizeLarge - 1;
FillRect(dcEditColor, &rect, brush);
FillRect(dcEditMask, &rect, brush);
rect.top += 1; rectBox.top = sizeLarge - stringSize.cy - 2;
rect.left -= 1; rectBox.left = sizeLarge - stringSize.cx - 2;
rect.bottom -= 1; rectBox.bottom = sizeLarge;
rect.right += 1; rectBox.right = sizeLarge;
FillRect(dcEditColor, &rect, brush);
FillRect(dcEditMask, &rect, brush);
rect.left += 1; //Draw the background (rounded) rectangle
DrawText(dcEditColor, m_szFilePath, m_nameLength, &rect, DT_BOTTOM|DT_SINGLELINE|DT_LEFT); int elipsSize = calSize/3;
RoundRect(dcEditTemp, rectBox.left, rectBox.top, rectBox.right, rectBox.bottom, elipsSize, elipsSize);
//Draw text in the rectangle
DrawText(dcEditTemp, m_szFilePath, m_nameLength, &rectText, DT_BOTTOM|DT_SINGLELINE|DT_LEFT);
//set alpha of non white pixels back to 255
//premultiply alpha
//Fill in the mask bitmap (anything not 100% alpha is transparent)
int red, green, blue, alpha;
for(int y = 0; y < sizeLarge; y++) {
for(int x = 0; x < sizeLarge; x++) {
DWORD * pix = pPix+(y*sizeLarge+x);
red = *pix & 0xFF;
green = *pix >> 8 & 0xFF;
blue = *pix >> 16 & 0xFF;
alpha = *pix >> 24 & 0xFF;
if ((*pix << 8) == 0xFFFFFF00)
alpha = 0x00;
else
alpha = 0xFF;
red = (red*alpha)/0xFF;
green = (green*alpha)/0xFF;
blue = (blue*alpha)/0xFF;
*pix = RGBA(red, green, blue, alpha);
}
}
BLENDFUNCTION ftn = { AC_SRC_OVER, 0, 0xFF, AC_SRC_ALPHA };
int width = rectBox.right - rectBox.left;
int height = rectBox.bottom - rectBox.top;
AlphaBlend(dcEditColor, rectBox.left, rectBox.top, stringSize.cx, stringSize.cy, dcEditTemp, rectBox.left, rectBox.top, width, height, ftn);
//Adjust the mask image: simply draw the rectangle to it
backGround = RGB(0, 0, 0);
DeleteBrush(brush);
DeletePen(pen);
brush = CreateSolidBrush(backGround);
pen = CreatePen(PS_NULL, 0, backGround);
SelectObject(dcEditMask, brush);
SelectObject(dcEditMask, pen);
RoundRect(dcEditMask, rectBox.left, rectBox.top, rectBox.right, rectBox.bottom, elipsSize, elipsSize);
SetBkColor(dcEditColor, maskBack);
//BitBlt(dcEditMask, 0, 0, sizeLarge, sizeLarge, dcEditColor, 0, 0, SRCCOPY);
SelectObject(dcEditColor, oldFontColor);
SelectObject(dcEditColor, oldBitmapColor);
SelectObject(dcEditMask, oldBitmapMask);
DeleteDC(dcEditColor); DeleteDC(dcEditColor);
DeleteDC(dcEditMask); DeleteDC(dcEditMask);
DeleteDC(dcEditTemp);
DeleteBrush(brush); DeleteBrush(brush);
DeletePen(pen);
DeleteFont(font);
DeleteBitmap(hbm);
*phiconLarge = CreateIconIndirect(&iconinfo); *phiconLarge = CreateIconIndirect(&iconinfo);
res = DeleteBitmap(iconinfo.hbmColor); DeleteBitmap(iconinfo.hbmColor);
res = DeleteBitmap(iconinfo.hbmMask); DeleteBitmap(iconinfo.hbmMask);
if (*phiconLarge == NULL) { if (*phiconLarge == NULL) {
InvalidateIcon(phiconSmall, phiconLarge); InvalidateIcon(phiconSmall, phiconLarge);
@ -909,7 +953,7 @@ void InvalidateIcon(HICON * iconSmall, HICON * iconLarge) {
} }
// *** Private methods *** // *** Private methods ***
STDMETHODIMP CShellExt::InvokeNPP(HWND hParent, LPCSTR pszWorkingDir, LPCSTR pszCmd, LPCSTR pszParam, int iShowCmd) { STDMETHODIMP CShellExt::InvokeNPP(HWND /*hParent*/, LPCSTR /*pszWorkingDir*/, LPCSTR /*pszCmd*/, LPCSTR /*pszParam*/, int iShowCmd) {
TCHAR szFilename[MAX_PATH]; TCHAR szFilename[MAX_PATH];
TCHAR szCustom[MAX_PATH]; TCHAR szCustom[MAX_PATH];
LPTSTR pszCommand; LPTSTR pszCommand;
@ -1018,11 +1062,7 @@ STDMETHODIMP CShellExt::LoadShellIcon(int cx, int cy, HICON * phicon) {
//Either no custom defined, or failed and use fallback //Either no custom defined, or failed and use fallback
if (hicon == NULL) { if (hicon == NULL) {
int iconID = IDI_ICON_NPP_BASE + m_iconID; hicon = (HICON)LoadImage(_hModule, MAKEINTRESOURCE(IDI_ICON_NPP), IMAGE_ICON, cx, cy, LR_DEFAULTCOLOR);
if (iconID > IDI_ICON_NPP_MAX)
iconID = IDI_ICON_NPP_BASE;
hicon = (HICON)LoadImage(_hModule, MAKEINTRESOURCE(iconID), IMAGE_ICON, cx, cy, 0);
} }
if (hicon == NULL) { if (hicon == NULL) {
@ -1035,94 +1075,3 @@ STDMETHODIMP CShellExt::LoadShellIcon(int cx, int cy, HICON * phicon) {
return hr; return hr;
} }
STDMETHODIMP CShellExt::LoadShellBitmap(int cx, int cy, HBITMAP * phbitmap) {
HRESULT hr = E_OUTOFMEMORY;
HBITMAP hbitmap = NULL;
if (m_useCustom) {
hbitmap = (HBITMAP)LoadImage(NULL, m_szCustomPath, IMAGE_BITMAP, cx, cy, LR_DEFAULTCOLOR|LR_LOADFROMFILE);
}
//Either no custom defined, or failed and use fallback
if (hbitmap == NULL) {
int iconID = IDB_BITMAP_NPP;//IDI_ICON_NPP_BASE + m_iconID;
if (iconID > IDI_ICON_NPP_MAX)
iconID = IDI_ICON_NPP_BASE;
hbitmap = (HBITMAP)LoadImage(_hModule, MAKEINTRESOURCE(iconID), IMAGE_BITMAP, cx, cy, 0);
}
if (hbitmap == NULL) {
hr = E_OUTOFMEMORY;
*phbitmap = NULL;
} else {
hr = S_OK;
*phbitmap = hbitmap;
}
return hr;
}
/*
STDMETHODIMP CShellExt::LoadARGBBitmap(HICON icon, int cx, int cy, HBITMAP * phbitmap) {
HRESULT hr = E_OUTOFMEMORY;
HBITMAP hbmp = NULL;
SIZE sizIcon;
sizIcon.cx = cx;
sizIcon.cy = cy;
RECT rcIcon;
SetRect(&rcIcon, 0, 0, sizIcon.cx, sizIcon.cy);
HDC hdcDest = CreateCompatibleDC(NULL);
if (hdcDest)
{
hr = Create32BitHBITMAP(hdcDest, &sizIcon, NULL, &hbmp);
if (SUCCEEDED(hr))
{
hr = E_FAIL;
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 = pBeginBufferedPaint(hdcDest, &rcIcon, BPBF_DIB, &paintParams, &hdcBuffer);
if (hPaintBuffer)
{
if (DrawIconEx(hdcBuffer, 0, 0, hicon, sizIcon.cx, sizIcon.cy, 0, NULL, DI_NORMAL))
{
// If icon did not have an alpha channel, we need to convert buffer to PARGB.
hr = ConvertBufferToPARGB32(hPaintBuffer, hdcDest, hicon, sizIcon);
}
// This will write the buffer contents to the destination bitmap.
pEndBufferedPaint(hPaintBuffer, TRUE);
}
SelectObject(hdcDest, hbmpOld);
}
}
DeleteDC(hdcDest);
}
if (FAILED(hr)) {
DeleteBitmap(hbmp);
hbmp = NULL;
}
if (phbitmap)
*phbitmap = hbmp;
return hr;
}
*/

View File

@ -16,8 +16,11 @@
#include <shlobj.h> #include <shlobj.h>
#include <shlwapi.h> #include <shlwapi.h>
#define WINVER_VISTA 0x600
//This is not ideal, but missing from current mingw //This is not ideal, but missing from current mingw
#define ERROR_ELEVATION_REQUIRED 740 #define ERROR_ELEVATION_REQUIRED 740
#define GIL_DEFAULTICON 0x0040
#define GUID_SIZE 128 #define GUID_SIZE 128
#define GUID_STRING_SIZE 40 #define GUID_STRING_SIZE 40
@ -51,7 +54,7 @@ protected:
public: public:
CShellExtClassFactory(); CShellExtClassFactory();
~CShellExtClassFactory(); virtual ~CShellExtClassFactory();
// *** IUnknown methods *** // *** IUnknown methods ***
STDMETHODIMP QueryInterface(REFIID, LPVOID FAR *); STDMETHODIMP QueryInterface(REFIID, LPVOID FAR *);
@ -84,17 +87,16 @@ private:
int m_nameLength; int m_nameLength;
int m_nameMaxLength; int m_nameMaxLength;
bool m_isDynamic; bool m_isDynamic;
int m_iconID;
DWORD m_winVer; //current windows version
// *** Private methods *** // *** Private methods ***
STDMETHODIMP InvokeNPP(HWND hParent, LPCSTR pszWorkingDir, LPCSTR pszCmd, LPCSTR pszParam, int iShowCmd); STDMETHODIMP InvokeNPP(HWND hParent, LPCSTR pszWorkingDir, LPCSTR pszCmd, LPCSTR pszParam, int iShowCmd);
STDMETHODIMP LoadShellIcon(int cx, int cy, HICON * phicon); STDMETHODIMP LoadShellIcon(int cx, int cy, HICON * phicon);
STDMETHODIMP LoadShellBitmap(int cx, int cy, HBITMAP * phbitmap);
//STDMETHODIMP LoadARGBBitmap(HICON icon, int cx, int cy, HBITMAP * phbitmap);
public: public:
CShellExt(); CShellExt();
~CShellExt(); virtual ~CShellExt();
// *** IUnknown methods *** // *** IUnknown methods ***
STDMETHODIMP QueryInterface(REFIID, LPVOID FAR *); STDMETHODIMP QueryInterface(REFIID, LPVOID FAR *);
@ -112,11 +114,11 @@ public:
STDMETHODIMP HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plResult); STDMETHODIMP HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plResult);
// *** IPersistFile methods *** // *** IPersistFile methods ***
STDMETHODIMP GetClassID(CLSID *pClassID) { return E_NOTIMPL; }; STDMETHODIMP GetClassID(CLSID */*pClassID*/) { return E_NOTIMPL; };
STDMETHODIMP IsDirty(void) { return E_NOTIMPL; }; STDMETHODIMP IsDirty(void) { return E_NOTIMPL; };
STDMETHODIMP Save(LPCOLESTR pszFileName, BOOL fRemember) { return E_NOTIMPL; }; STDMETHODIMP Save(LPCOLESTR /*pszFileName*/, BOOL /*fRemember*/) { return E_NOTIMPL; };
STDMETHODIMP SaveCompleted(LPCOLESTR pszFileName) { return E_NOTIMPL; }; STDMETHODIMP SaveCompleted(LPCOLESTR /*pszFileName*/) { return E_NOTIMPL; };
STDMETHODIMP GetCurFile(LPOLESTR *ppszFileName) { return E_NOTIMPL; }; STDMETHODIMP GetCurFile(LPOLESTR */*ppszFileName*/) { return E_NOTIMPL; };
STDMETHODIMP Load(LPCOLESTR pszFileName, DWORD dwMode); STDMETHODIMP Load(LPCOLESTR pszFileName, DWORD dwMode);
// *** IExtractIcon methods *** // *** IExtractIcon methods ***

View File

@ -49,15 +49,9 @@ END
// Icon // Icon
// //
IDI_ICON_NPP_0 ICON "icon\\npp_1.ico" //IDI_ICON_NPP ICON "icon\\npp_1.ico"
IDI_ICON_NPP_1 ICON "icon\\npp_1.ico" IDI_ICON_NPP ICON "icon\\nppNewIcon.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Bitmap
//
IDB_BITMAP_NPP BITMAP "bitmap\\npp.bmp"
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// //
@ -79,7 +73,5 @@ BEGIN
GROUPBOX "Dynamic Icon",IDC_STATIC,144,6,132,114 GROUPBOX "Dynamic Icon",IDC_STATIC,144,6,132,114
CONTROL "Show dynamic icon",IDC_CHECK_USEICON,"Button",BS_AUTO3STATE | WS_TABSTOP,156,24,76,10 CONTROL "Show dynamic icon",IDC_CHECK_USEICON,"Button",BS_AUTO3STATE | WS_TABSTOP,156,24,76,10
CONTROL "Show extension",IDC_CHECK_ISDYNAMIC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,156,42,67,10 CONTROL "Show extension",IDC_CHECK_ISDYNAMIC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,156,42,67,10
CONTROL "Use classic icon",IDC_RADIO_CLASSIC,"Button",BS_AUTORADIOBUTTON | WS_GROUP,156,60,65,10
CONTROL "Use modern icon",IDC_RADIO_MODERN,"Button",BS_AUTORADIOBUTTON,156,72,69,10
DEFPUSHBUTTON "OK",IDOK,222,126,50,14 DEFPUSHBUTTON "OK",IDOK,222,126,50,14
END END

View File

@ -1,9 +1,4 @@
#define IDB_BITMAP_NPP 101 #define IDI_ICON_NPP 102
#define IDI_ICON_NPP_BASE 102
#define IDI_ICON_NPP_0 102
#define IDI_ICON_NPP_1 103
#define IDI_ICON_NPP_MAX 103
#define IDD_DIALOG_SETTINGS 101 #define IDD_DIALOG_SETTINGS 101
@ -13,7 +8,5 @@
#define IDC_EDIT_COMMAND 1003 #define IDC_EDIT_COMMAND 1003
#define IDC_CHECK_USEICON 1004 #define IDC_CHECK_USEICON 1004
#define IDC_CHECK_ISDYNAMIC 1005 #define IDC_CHECK_ISDYNAMIC 1005
#define IDC_RADIO_CLASSIC 1006
#define IDC_RADIO_MODERN 1007
#define IDC_STATIC -1 #define IDC_STATIC -1