add dll icon loader newapi

Fri, 13 Oct 2023 19:53:21 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Fri, 13 Oct 2023 19:53:21 +0200
branch
newapi
changeset 216
391c2c723029
parent 215
1bd5534c395d
child 217
b9798109c7d2

add dll icon loader

make/vs/testapp/main.c file | annotate | diff | comparison | revisions
ui/ui/toolkit.h file | annotate | diff | comparison | revisions
ui/winui/icons.cpp file | annotate | diff | comparison | revisions
ui/winui/icons.h file | annotate | diff | comparison | revisions
ui/winui/pch.h file | annotate | diff | comparison | revisions
ui/winui/table.cpp file | annotate | diff | comparison | revisions
ui/winui/winui.vcxproj file | annotate | diff | comparison | revisions
--- a/make/vs/testapp/main.c	Fri Oct 13 15:20:54 2023 +0200
+++ b/make/vs/testapp/main.c	Fri Oct 13 19:53:21 2023 +0200
@@ -163,7 +163,8 @@
     ui_list_append(wdata->list3, "test");
     ui_list_append(wdata->list3, "dir");
 
-    folder_icon = ui_icon("Folder", 32);
+    //folder_icon = ui_icon("Folder", 32);
+    folder_icon = ui_foldericon(16);
 
     TableData* td1 = malloc(sizeof(TableData));
     TableData* td2 = malloc(sizeof(TableData));
--- a/ui/ui/toolkit.h	Fri Oct 13 15:20:54 2023 +0200
+++ b/ui/ui/toolkit.h	Fri Oct 13 19:53:21 2023 +0200
@@ -440,6 +440,8 @@
 UIEXPORT UiIcon* ui_imageicon(const char* file);
 UIEXPORT void ui_icon_free(UiIcon* icon);
 
+UIEXPORT UiIcon* ui_foldericon(size_t size);
+UIEXPORT UiIcon* ui_fileicon(size_t size);
 
 #ifdef	__cplusplus
 }
--- a/ui/winui/icons.cpp	Fri Oct 13 15:20:54 2023 +0200
+++ b/ui/winui/icons.cpp	Fri Oct 13 19:53:21 2023 +0200
@@ -35,13 +35,24 @@
 
 #include "util.h"
 
+#include <Windows.h>
+#include <Shellapi.h>
+
+
 using namespace winrt;
 using namespace Microsoft::UI::Xaml;
 using namespace Microsoft::UI::Xaml::Controls;
 using namespace Windows::UI::Xaml::Interop;
 using namespace winrt::Windows::Foundation;
 using namespace winrt::Microsoft::UI::Xaml::Controls::Primitives;
+using namespace winrt::Microsoft::UI::Xaml::Media::Imaging;
+//using namespace Windows::Storage::Streams;
 
+static UiIcon* sys_folder_icon16;
+static UiIcon* sys_file_icon16;
+
+static UiIcon* sys_folder_icon32;
+static UiIcon* sys_file_icon32;
 
 std::unordered_map<std::string, Symbol> ui_symbol_icons = {
 	{"Accept", Symbol::Accept },
@@ -283,6 +294,23 @@
 winrt::Microsoft::UI::Xaml::Controls::IconElement UiImageIcon::getIcon() {
 	BitmapIcon icon = BitmapIcon();
 	icon.UriSource(uri);
+	ImageIcon img = ImageIcon();
+	img.Source();
+	return icon;
+}
+
+// bitmap icon implementation
+UiBitmapIcon::UiBitmapIcon(winrt::Microsoft::UI::Xaml::Media::Imaging::BitmapSource bitmap) {
+	this->bitmap = bitmap;
+}
+
+UiBitmapIcon::~UiBitmapIcon() {
+
+}
+
+winrt::Microsoft::UI::Xaml::Controls::IconElement UiBitmapIcon::getIcon() {
+	ImageIcon icon = ImageIcon();
+	icon.Source(bitmap);
 	return icon;
 }
 
@@ -300,3 +328,87 @@
 UIEXPORT void ui_icon_free(UiIcon* icon) {
 	delete icon;
 }
+
+
+struct __declspec(uuid("905a0fef-bc53-11df-8c49-001e4fc686da")) IBufferByteAccess : ::IUnknown
+{
+	virtual HRESULT __stdcall Buffer(uint8_t** value) = 0;
+};
+
+
+
+winrt::Microsoft::UI::Xaml::Media::Imaging::WriteableBitmap ui_dllicon2bitmap(const char* dll, int iconindex, bool large) {
+	WriteableBitmap wbitmap = { nullptr };
+
+	// get the icon from the dll
+	HICON hicon_small;
+	HICON hicon_large;
+	if (ExtractIconExA(dll, iconindex, &hicon_large, &hicon_small, 1) > 0) {
+		HICON hicon = large ? hicon_large : hicon_small;
+
+		// convert icon to (gdi) bitmap
+		ICONINFO info;
+		if (GetIconInfo(hicon, &info)) {
+			BITMAP bitmap;
+			if (GetObjectW(info.hbmColor, sizeof(BITMAP), &bitmap) != 0) {
+				size_t bitmap_size = bitmap.bmWidthBytes * bitmap.bmHeight;
+				char *bitmap_data = (char*)malloc(bitmap_size);
+
+				// get the pixel data
+				if (GetBitmapBits(info.hbmColor, bitmap_size, bitmap_data) != 0) {
+					WriteableBitmap wb = WriteableBitmap(bitmap.bmWidth, bitmap.bmHeight);
+					void *wb_data = wb.PixelBuffer().data();
+					memcpy(wb_data, bitmap_data, bitmap_size);
+					wbitmap = wb;
+				}
+				DeleteObject(info.hbmColor);
+				free(bitmap_data);
+			}
+		}
+		DeleteObject(info.hbmMask);
+
+		DestroyIcon(hicon_small);
+		DestroyIcon(hicon_large);
+	}
+
+	return wbitmap;
+}
+
+UiIcon* ui_dllicon(const char* dll, int iconindex, bool large) {
+	WriteableBitmap wbitmap = ui_dllicon2bitmap(dll, iconindex, large);
+	return new UiBitmapIcon(wbitmap);
+}
+
+UIEXPORT UiIcon* ui_foldericon(size_t size) {
+	bool large = true;
+	UiIcon** sys_folder_icon = &sys_folder_icon32;
+	if (size <= 24) {
+		large = false;
+		sys_folder_icon = &sys_folder_icon16;
+	}
+
+	if (*sys_folder_icon) {
+		return *sys_folder_icon;
+	}
+
+	UiIcon* icon = ui_dllicon("shell32.dll", 3, large);
+	*sys_folder_icon = icon;
+	return icon;
+}
+
+UIEXPORT UiIcon* ui_fileicon(size_t size) {
+	bool large = true;
+	UiIcon** sys_folder_icon = &sys_folder_icon32;
+	if (size <= 24) {
+		large = false;
+		sys_folder_icon = &sys_folder_icon16;
+	}
+
+	if (*sys_folder_icon) {
+		return *sys_folder_icon;
+	}
+
+	UiIcon* icon = ui_dllicon("shell32.dll", 0, large);
+	*sys_folder_icon = icon;
+	return icon;
+}
--- a/ui/winui/icons.h	Fri Oct 13 15:20:54 2023 +0200
+++ b/ui/winui/icons.h	Fri Oct 13 19:53:21 2023 +0200
@@ -58,5 +58,19 @@
 	winrt::Microsoft::UI::Xaml::Controls::IconElement getIcon();
 };
 
+struct UiBitmapIcon : UiIcon {
+	winrt::Microsoft::UI::Xaml::Media::Imaging::BitmapSource bitmap{ nullptr };
+
+	UiBitmapIcon(winrt::Microsoft::UI::Xaml::Media::Imaging::BitmapSource bitmap);
+
+	~UiBitmapIcon();
+
+	winrt::Microsoft::UI::Xaml::Controls::IconElement getIcon();
+};
+
 
 winrt::Microsoft::UI::Xaml::Controls::IconElement ui_get_icon(const char* name);
+
+winrt::Microsoft::UI::Xaml::Media::Imaging::WriteableBitmap ui_dllicon2bitmap(const char* dll, int iconindex, bool large);
+
+UiIcon* ui_dllicon(const char* dll, int iconindex, bool large);
--- a/ui/winui/pch.h	Fri Oct 13 15:20:54 2023 +0200
+++ b/ui/winui/pch.h	Fri Oct 13 19:53:21 2023 +0200
@@ -22,8 +22,11 @@
 #include <winrt/Microsoft.UI.Xaml.Interop.h>
 #include <winrt/Microsoft.UI.Xaml.Markup.h>
 #include <winrt/Microsoft.UI.Xaml.Media.h>
+#include <winrt/Microsoft.UI.Xaml.Media.Imaging.h>
 #include <winrt/Microsoft.UI.Xaml.Navigation.h>
 #include <winrt/Microsoft.UI.Xaml.Shapes.h>
 #include <winrt/Microsoft.UI.Xaml.XamlTypeInfo.h>
 #include <winrt/Microsoft.UI.Dispatching.h>
 #include <wil/cppwinrt_helpers.h>
+
+#include <winrt/Windows.Storage.Streams.h>
--- a/ui/winui/table.cpp	Fri Oct 13 15:20:54 2023 +0200
+++ b/ui/winui/table.cpp	Fri Oct 13 19:53:21 2023 +0200
@@ -320,13 +320,18 @@
 							// select everything between the first selection and the current row
 							std::sort(selection.begin(), selection.end());
 							int first = selection.front();
+							int last = row;
+							if (first > row) {
+								last = first;
+								first = row;
+							}
 
 							// clear previous selection
 							change_rows_bg(selection, defaultBrush, defaultBrush);
 
 							// create new selection
 							std::vector<int> newselection;
-							for (int s = first; s <= row; s++) {
+							for (int s = first; s <= last; s++) {
 								newselection.push_back(s);
 							}
 							selection = newselection;
--- a/ui/winui/winui.vcxproj	Fri Oct 13 15:20:54 2023 +0200
+++ b/ui/winui/winui.vcxproj	Fri Oct 13 19:53:21 2023 +0200
@@ -91,6 +91,9 @@
       <PreprocessorDefinitions>_DEBUG;DISABLE_XAML_GENERATED_MAIN__;UI_WINUI;UI_WINUI_PCH;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)..\..\ucx;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>
+    <Link>
+      <AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">shell32.lib;gdi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
     <ClCompile>

mercurial