Skip to content

Commit

Permalink
Show file icon on open file MRU drop-down menu items, issue #740.
Browse files Browse the repository at this point in the history
Co-authored-by: @Sergy2001
  • Loading branch information
zufuliu committed Dec 10, 2023
1 parent 0cc948a commit 361920b
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 1 deletion.
55 changes: 55 additions & 0 deletions src/Helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -2544,6 +2544,61 @@ void MRU_AddToCombobox(LPCMRULIST pmru, HWND hwnd) {
}
}

void BitmapCache_Empty(BitmapCache *cache) {
for (UINT i = 0; i < cache->count; i++) {
DeleteObject(cache->items[i]);
}
memset(cache, 0, sizeof(BitmapCache));
}

HBITMAP BitmapCache_Get(BitmapCache *cache, LPCWSTR path) {
if (cache->invalid) {
BitmapCache_Empty(cache);
}

SHFILEINFO shfi;
HIMAGELIST imageList = (HIMAGELIST)SHGetFileInfo(path, FILE_ATTRIBUTE_NORMAL, &shfi, sizeof(SHFILEINFO), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
const int iIcon = shfi.iIcon;
UINT index = 0;
for (; index < cache->count; index++) {
if (cache->iconIndex[index] == iIcon) {
break;
}
}
if (index == cache->count) {
NP2_static_assert(sizeof(cache->used)*8 >= MRU_MAXITEMS);
if (index < MRU_MAXITEMS) {
cache->count += 1;
} else {
// find first zero bit in used, omitted zero check as used can't be UINT32_MAX
// index = __builtin_stdc_first_trailing_one(cache->used);
index = np2_ctz(~cache->used);
DeleteObject(cache->items[index]);
cache->items[index] = NULL;
}
cache->iconIndex[index] = iIcon;
}

cache->used |= 1U << index;
HBITMAP hbmp = cache->items[index];
if (hbmp == NULL) {
HDC hDC = GetDC(NULL);
HDC bitmapDC = CreateCompatibleDC(hDC);
RECT rect = { 0, 0, 0, 0 };
ImageList_GetIconSize(imageList, (int *)(&rect.right), (int *)(&rect.bottom));
hbmp = CreateCompatibleBitmap(hDC, rect.right, rect.bottom);
HBITMAP oldBitmap = (HBITMAP)SelectObject(bitmapDC, hbmp);
FillRect(bitmapDC, &rect, (HBRUSH)(COLOR_MENU + 1));
ImageList_Draw(imageList, iIcon, bitmapDC, 0, 0, ILD_TRANSPARENT);
SelectBitmap(bitmapDC, oldBitmap);
DeleteDC(bitmapDC);
ReleaseDC(NULL, hDC);
cache->items[index] = hbmp;
}

return hbmp;
}

/*
Themed Dialogs
Expand Down
17 changes: 17 additions & 0 deletions src/Helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -901,6 +901,23 @@ void MRU_Save(LPCMRULIST pmru);
void MRU_MergeSave(LPMRULIST pmru, bool keep);
void MRU_AddToCombobox(LPCMRULIST pmru, HWND hwnd);

typedef struct BitmapCache {
UINT count;
UINT used;
bool invalid;
int iconIndex[MRU_MAXITEMS];
HBITMAP items[MRU_MAXITEMS];
} BitmapCache;

static inline void BitmapCache_Invalidate(BitmapCache *cache) {
cache->invalid = true; // mark all cache as invalid
}
static inline void BitmapCache_StartUse(BitmapCache *cache) {
cache->used = 0; // mark all cache as unused
}
void BitmapCache_Empty(BitmapCache *cache);
HBITMAP BitmapCache_Get(BitmapCache *cache, LPCWSTR path);

//==== Themed Dialogs =========================================================
#ifndef DLGTEMPLATEEX
#pragma pack(push, 1)
Expand Down
14 changes: 13 additions & 1 deletion src/Notepad2.c
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ static LPWSTR lpEncodingArg = NULL;
MRULIST mruFile;
MRULIST mruFind;
MRULIST mruReplace;
static BitmapCache bitmapCache;

DWORD dwLastIOError;
WCHAR szCurFile[MAX_PATH + 40];
Expand Down Expand Up @@ -1154,6 +1155,7 @@ LRESULT CALLBACK MainWndProc(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam)
MRU_MergeSave(&mruFile, bSaveRecentFiles);
MRU_MergeSave(&mruFind, bSaveFindReplace);
MRU_MergeSave(&mruReplace, bSaveFindReplace);
BitmapCache_Empty(&bitmapCache);

// Remove tray icon if necessary
ShowNotifyIcon(hwnd, false);
Expand Down Expand Up @@ -1202,12 +1204,14 @@ LRESULT CALLBACK MainWndProc(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam)
break;

case WM_SETTINGCHANGE:
BitmapCache_Invalidate(&bitmapCache);
// TODO: detect system theme and high contrast mode changes
SendMessage(hwndEdit, WM_SETTINGCHANGE, wParam, lParam);
Style_SetLexer(pLexCurrent, false); // override base elements
break;

case WM_SYSCOLORCHANGE:
BitmapCache_Invalidate(&bitmapCache);
SendMessage(hwndToolbar, WM_SYSCOLORCHANGE, wParam, lParam);
SendMessage(hwndEdit, WM_SYSCOLORCHANGE, wParam, lParam);
Style_SetLexer(pLexCurrent, false); // override base elements
Expand Down Expand Up @@ -2137,6 +2141,7 @@ void MsgDPIChanged(HWND hwnd, WPARAM wParam, LPARAM lParam) {
const Sci_Line iVisTopLine = SciCall_GetFirstVisibleLine();
const Sci_Line iDocTopLine = SciCall_DocLineFromVisible(iVisTopLine);

BitmapCache_Invalidate(&bitmapCache);
// recreate toolbar and statusbar
RecreateBars(hwnd, g_hInstance);
const int cx = rc->right - rc->left;
Expand Down Expand Up @@ -5344,9 +5349,16 @@ LRESULT MsgNotify(HWND hwnd, WPARAM wParam, LPARAM lParam) {
return TBDDRET_TREATPRESSED;
}
hmenu = subMenu = CreatePopupMenu();
BitmapCache_StartUse(&bitmapCache);
MENUITEMINFO mii;
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_STRING | MIIM_BITMAP;
for (int i = 0; i < count; i++) {
LPCWSTR path = mruFile.pszItems[i];
AppendMenu(subMenu, MF_STRING, i + IDM_RECENT_HISTORY_START, path);
HBITMAP hbmp = BitmapCache_Get(&bitmapCache, path);
mii.dwTypeData = (LPWSTR)path;
mii.hbmpItem = hbmp;
InsertMenuItem(subMenu, i + IDM_RECENT_HISTORY_START, FALSE, &mii);
}
} else {
hmenu = LoadMenu(g_hInstance, MAKEINTRESOURCE(IDR_POPUPMENU));
Expand Down

0 comments on commit 361920b

Please sign in to comment.