Add Bitmap.cpp file, currently unused.

Revert icon drawing as not to break Aero themes.
Static linking in C::B project.
Set both icons in resource to point to original verison.
In case of elevation error, try shellexecute instead.

git-svn-id: svn://svn.tuxfamily.org/svnroot/notepadplus/repository/trunk@620 f5eea248-9336-0410-98b8-ebc06183d4e3
This commit is contained in:
Harold Bruintjes 2010-03-01 20:42:21 +00:00
parent 7a236ed330
commit de399da6ff
6 changed files with 378 additions and 54 deletions

View File

@ -14,6 +14,7 @@
<Compiler>
<Add option="-fexpensive-optimizations" />
<Add option="-Os" />
<Add option="-O2" />
</Compiler>
<Linker>
<Add option="-s" />
@ -36,6 +37,7 @@
<Compiler>
<Add option="-fexpensive-optimizations" />
<Add option="-Os" />
<Add option="-O2" />
</Compiler>
<Linker>
<Add option="-s" />
@ -53,13 +55,17 @@
</Build>
<Compiler>
<Add option="-Wall" />
<Add option="-fno-exceptions" />
<Add option="-D_WIN32_WINNT=0x500" />
<Add option="-DGIL_DEFAULTICON=0x0040" />
<Add option="-DWIN32_LEAN_AND_MEAN" />
<Add option="-DUNICODE" />
<Add option="-D_UNICODE" />
</Compiler>
<Linker>
<Add option="--output-def ../src/export.def" />
<Add option="--enable-stdcall-fixup" />
<Add option="-static" />
<Add library="gdi32" />
<Add library="shlwapi" />
<Add library="ole32" />

View File

@ -0,0 +1,125 @@
//From: Visual Style Menus in MSDN
#include "Bitmap.h"
#include <uxtheme.h>
void InitBitmapInfo(BITMAPINFO *pbmi, ULONG cbInfo, LONG cx, LONG cy, WORD bpp)
{
ZeroMemory(pbmi, cbInfo);
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbmi->bmiHeader.biPlanes = 1;
pbmi->bmiHeader.biCompression = BI_RGB;
pbmi->bmiHeader.biWidth = cx;
pbmi->bmiHeader.biHeight = cy;
pbmi->bmiHeader.biBitCount = bpp;
}
HRESULT Create32BitHBITMAP(HDC hdc, const SIZE *psize, void **ppvBits, HBITMAP* phBmp)
{
*phBmp = NULL;
BITMAPINFO bmi;
InitBitmapInfo(&bmi, sizeof(bmi), psize->cx, psize->cy, 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 ConvertToPARGB32(HDC hdc, ARGB *pargb, HBITMAP hbmp, SIZE& sizImage, int cxRow)
{
BITMAPINFO bmi;
InitBitmapInfo(&bmi, sizeof(bmi), sizImage.cx, sizImage.cy, 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;
ARGB *pargbMask = static_cast<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;
}
bool HasAlpha(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 ConvertBufferToPARGB32(HPAINTBUFFER hPaintBuffer, HDC hdc, HICON hicon, SIZE& sizIcon)
{
RGBQUAD *prgbQuad;
int cxRow;
HRESULT hr = GetBufferedPaintBits(hPaintBuffer, &prgbQuad, &cxRow);
if (SUCCEEDED(hr))
{
ARGB *pargb = reinterpret_cast<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;
}

View File

@ -0,0 +1,10 @@
#include <windows.h>
#include <uxtheme.h>
typedef DWORD ARGB;
void InitBitmapInfo(BITMAPINFO *pbmi, ULONG cbInfo, LONG cx, LONG cy, WORD bpp);
HRESULT Create32BitHBITMAP(HDC hdc, const SIZE *psize, void **ppvBits, HBITMAP* phBmp);
HRESULT ConvertToPARGB32(HDC hdc, ARGB *pargb, HBITMAP hbmp, SIZE& sizImage, int cxRow);
bool HasAlpha(ARGB *pargb, SIZE& sizImage, int cxRow);
HRESULT ConvertBufferToPARGB32(HPAINTBUFFER hPaintBuffer, HDC hdc, HICON hicon, SIZE& sizIcon);

View File

@ -1,9 +1,13 @@
#include "NppShell.h"
//#include "Bitmap.h"
#include "resource.h"
#include <shellapi.h>
#include <algorithm>
//#include <wincodec.h>
//---------------------------------------------------------------------------
// Global variables
//---------------------------------------------------------------------------
@ -43,6 +47,7 @@ void MsgBox(LPCTSTR lpszMsg);
void MsgBoxError(LPCTSTR lpszMsg);
BOOL CheckNpp(LPCTSTR path);
INT_PTR CALLBACK DlgProcSettings(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
void InvalidateIcon(HICON * iconSmall, HICON * iconLarge);
#ifdef UNICODE
#define _ttoi _wtoi
@ -619,12 +624,38 @@ STDMETHODIMP CShellExt::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmd
InsertMenu(hMenu, nIndex, MF_STRING|MF_BYPOSITION, idCmd++, m_szMenuTitle);
HBITMAP icon = NULL;
if (m_showIcon) {/*
if (m_supportARGB32) {
icon = NULL;
HICON hicon;
DWORD menuIconWidth = GetSystemMetrics(SM_CXMENUCHECK);
DWORD menuIconHeight = GetSystemMetrics(SM_CYMENUCHECK);
HRESULT hr = LoadShellIcon(menuIconWidth, menuIconHeight, &hicon);
if (SUCCEEDED(hr)) {
HBITMAP hbitmap;
LoadARGBBitmap(hicon, menuIconWidth, menuIconHeight, &hbitmap);
if (SUCCEEDED(hr)) {
icon = hbitmap;
}
}
} else {
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;
ZeroMemory(&mii, sizeof(mii));
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_BITMAP;
mii.hbmpItem = HBMMENU_CALLBACK;
SetMenuItemInfo(hMenu, nIndex, MF_BYPOSITION, &mii);
mii.hbmpItem = icon;
//SetMenuItemInfo(hMenu, nIndex, MF_BYPOSITION, &mii);
SetMenuItemBitmaps(hMenu, nIndex, MF_BYPOSITION, icon, icon);
m_hMenu = hMenu;
m_menuID = idCmd;
@ -632,6 +663,11 @@ STDMETHODIMP CShellExt::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmd
return ResultFromShort(idCmd-idCmdFirst);
}
STDMETHODIMP CShellExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi) {
HRESULT hr = E_INVALIDARG;
@ -667,35 +703,33 @@ STDMETHODIMP CShellExt::HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam,
switch(uMsg) {
case WM_MEASUREITEM: { //for owner drawn menu
MEASUREITEMSTRUCT * pmis = (MEASUREITEMSTRUCT*) lParam;
MEASUREITEMSTRUCT * lpdis = (MEASUREITEMSTRUCT*) lParam;
if (lpdis == NULL)
break;
//Keep 0, as we use the space used for checkmarks and whatnot
pmis->itemWidth = 0;//menuIconWidth + menuIconPadding;
pmis->itemHeight = 0;//menuItemHeight + menuIconPadding;
lpdis->itemWidth += menuIconPadding;
if (lpdis->itemHeight < menuIconHeight)
lpdis->itemHeight = menuIconHeight;
if (plResult)
*plResult = TRUE;
break; }
case WM_DRAWITEM: { //for owner drawn menu
//Assumes proper font already been set
DRAWITEMSTRUCT * lpdis = (DRAWITEMSTRUCT*) lParam;
UINT icon = IDI_ICON_NPP_BASE + m_iconID;
if (icon > IDI_ICON_NPP_MAX)
icon = IDI_ICON_NPP_MAX;
if ((lpdis == NULL) || (lpdis->CtlType != ODT_MENU))
break;
if (m_showIcon) {
HICON nppIcon = (HICON)LoadImage(_hModule, MAKEINTRESOURCE(icon), IMAGE_ICON, menuIconWidth, menuIconHeight, 0);
if (m_useCustom) {
HICON customIcon = (HICON)LoadImage(NULL, m_szCustomPath, IMAGE_ICON, menuIconWidth, menuIconHeight, LR_DEFAULTCOLOR|LR_LOADFROMFILE);
if (customIcon != NULL) {
DestroyIcon(nppIcon);
nppIcon = customIcon;
}
HICON nppIcon = NULL;
HRESULT hr = LoadShellIcon(menuIconWidth, menuIconHeight, &nppIcon);
if (SUCCEEDED(hr)) {
DrawIconEx(lpdis->hDC, menuIconPadding, menuIconPadding, nppIcon, menuIconWidth, menuIconHeight, 0, NULL, DI_NORMAL);
DestroyIcon(nppIcon);
}
DrawIconEx(lpdis->hDC, menuIconPadding, menuIconPadding, nppIcon, menuIconWidth, menuIconHeight, 0, NULL, DI_NORMAL);
DestroyIcon(nppIcon);
}
if (plResult)
@ -756,43 +790,36 @@ STDMETHODIMP CShellExt::Extract(LPCTSTR pszFile, UINT nIconIndex, HICON * phicon
WORD sizeSmall = HIWORD(nIconSize);
WORD sizeLarge = LOWORD(nIconSize);
ICONINFO iconinfo;
BOOL res;
HRESULT hrSmall = S_OK, hrLarge = S_OK;
int iconID = IDI_ICON_NPP_BASE + m_iconID;
if (iconID > IDI_ICON_NPP_MAX)
iconID = IDI_ICON_NPP_BASE;
if (phiconSmall)
hrSmall = LoadShellIcon(sizeSmall, sizeSmall, phiconSmall);
if (phiconLarge)
hrLarge = LoadShellIcon(sizeLarge, sizeLarge, phiconLarge);
HICON iconSmall = (HICON)LoadImage(_hModule, MAKEINTRESOURCE(iconID), IMAGE_ICON, sizeSmall, sizeSmall, LR_DEFAULTCOLOR);
HICON iconLarge = (HICON)LoadImage(_hModule, MAKEINTRESOURCE(iconID), IMAGE_ICON, sizeLarge, sizeLarge, LR_DEFAULTCOLOR);
*phiconSmall = iconSmall;
*phiconLarge = iconLarge;
if (m_useCustom) {
HICON customSmall = (HICON)LoadImage(NULL, m_szCustomPath, IMAGE_ICON, sizeSmall, sizeSmall, LR_DEFAULTCOLOR|LR_LOADFROMFILE);
HICON customLarge = (HICON)LoadImage(NULL, m_szCustomPath, IMAGE_ICON, sizeLarge, sizeLarge, LR_DEFAULTCOLOR|LR_LOADFROMFILE);
if (customSmall != NULL) {
DestroyIcon(*phiconSmall);
*phiconSmall = customSmall;
}
if (customLarge != NULL) {
DestroyIcon(*phiconLarge);
*phiconLarge = customLarge;
}
if (FAILED(hrSmall) || FAILED(hrLarge)) {
InvalidateIcon(phiconSmall, phiconLarge);
return S_FALSE;
}
if (!m_isDynamic)
if (!m_isDynamic || !phiconLarge) //No modifications required
return S_OK;
HICON newIconLarge;
HDC dcEditColor, dcEditMask;
HGDIOBJ oldBitmapColor, oldBitmapMask, oldFontColor;
HFONT font;
HBRUSH brush;
GetIconInfo(*phiconLarge, &iconinfo);
DestroyIcon(*phiconLarge);
res = GetIconInfo(*phiconLarge, &iconinfo);
if (!res)
return S_OK; //abort, the icon is still valid
res = DestroyIcon(*phiconLarge);
if (!res)
return S_OK;
else
*phiconLarge = NULL;
dcEditColor = CreateCompatibleDC(GetDC(0));
dcEditMask = CreateCompatibleDC(GetDC(0));
@ -858,12 +885,29 @@ STDMETHODIMP CShellExt::Extract(LPCTSTR pszFile, UINT nIconIndex, HICON * phicon
DeleteBrush(brush);
newIconLarge = CreateIconIndirect(&iconinfo);
*phiconLarge = newIconLarge;
*phiconLarge = CreateIconIndirect(&iconinfo);
res = DeleteBitmap(iconinfo.hbmColor);
res = DeleteBitmap(iconinfo.hbmMask);
if (*phiconLarge == NULL) {
InvalidateIcon(phiconSmall, phiconLarge);
return S_FALSE;
}
return S_OK;
}
void InvalidateIcon(HICON * iconSmall, HICON * iconLarge) {
if (iconSmall && *iconSmall) {
DestroyIcon(*iconSmall);
*iconSmall = NULL;
}
if (iconLarge && *iconLarge) {
DestroyIcon(*iconLarge);
*iconLarge = NULL;
}
}
// *** Private methods ***
STDMETHODIMP CShellExt::InvokeNPP(HWND hParent, LPCSTR pszWorkingDir, LPCSTR pszCmd, LPCSTR pszParam, int iShowCmd) {
TCHAR szFilename[MAX_PATH];
@ -940,12 +984,145 @@ STDMETHODIMP CShellExt::InvokeNPP(HWND hParent, LPCSTR pszWorkingDir, LPCSTR psz
si.wShowWindow = iShowCmd; //SW_RESTORE;
if (!CreateProcess (NULL, pszCommand, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
DWORD errorCode = GetLastError();
TCHAR * message = new TCHAR[512+bytesRequired];
wsprintf(message, TEXT("Error in CreateProcess (%d): Is this command correct?\r\n%s"), errorCode, pszCommand);
MsgBoxError(message);
delete [] message;
if (errorCode == ERROR_ELEVATION_REQUIRED) { //Fallback to shellexecute
CoInitializeEx(NULL, 0);
HINSTANCE execVal = ShellExecute(NULL, TEXT("runas"), pszCommand, NULL, NULL, iShowCmd);
CoUninitialize();
if (execVal <= (HINSTANCE)32) {
TCHAR * message = new TCHAR[512+bytesRequired];
wsprintf(message, TEXT("ShellExecute failed (%d): Is this command correct?\r\n%s"), execVal, pszCommand);
MsgBoxError(message);
delete [] message;
}
} else {
TCHAR * message = new TCHAR[512+bytesRequired];
wsprintf(message, TEXT("Error in CreateProcess (%d): Is this command correct?\r\n%s"), errorCode, pszCommand);
MsgBoxError(message);
delete [] message;
}
}
CoTaskMemFree(pszCommand);
return NOERROR;
}
STDMETHODIMP CShellExt::LoadShellIcon(int cx, int cy, HICON * phicon) {
HRESULT hr = E_OUTOFMEMORY;
HICON hicon = NULL;
if (m_useCustom) {
hicon = (HICON)LoadImage(NULL, m_szCustomPath, IMAGE_ICON, cx, cy, LR_DEFAULTCOLOR|LR_LOADFROMFILE);
}
//Either no custom defined, or failed and use fallback
if (hicon == NULL) {
int iconID = IDI_ICON_NPP_BASE + m_iconID;
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) {
hr = E_OUTOFMEMORY;
*phicon = NULL;
} else {
hr = S_OK;
*phicon = hicon;
}
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,6 +16,9 @@
#include <shlobj.h>
#include <shlwapi.h>
//This is not ideal, but missing from current mingw
#define ERROR_ELEVATION_REQUIRED 740
#define GUID_SIZE 128
#define GUID_STRING_SIZE 40
#define TITLE_SIZE 64
@ -85,6 +88,9 @@ private:
// *** Private methods ***
STDMETHODIMP InvokeNPP(HWND hParent, LPCSTR pszWorkingDir, LPCSTR pszCmd, LPCSTR pszParam, int iShowCmd);
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:
CShellExt();

View File

@ -28,7 +28,7 @@ BEGIN
VALUE "FileDescription", "ShellHandler for Notepad++"
#endif
VALUE "FileVersion", "0.1"
VALUE "LegalCopyright", "Copyright © 2008"
VALUE "LegalCopyright", "Copyright © 2010"
#ifdef WIN64
VALUE "OriginalFilename", "NppShell64.dll"
#else
@ -49,7 +49,7 @@ END
// Icon
//
IDI_ICON_NPP_0 ICON "icon\\npp_0.ico"
IDI_ICON_NPP_0 ICON "icon\\npp_1.ico"
IDI_ICON_NPP_1 ICON "icon\\npp_1.ico"
/////////////////////////////////////////////////////////////////////////////
@ -81,5 +81,5 @@ BEGIN
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 "Apply",IDOK,222,126,50,14
DEFPUSHBUTTON "OK",IDOK,222,126,50,14
END