Skip to content

Commit e898964

Browse files
committed
Initial commit
Signed-off-by: Still Hsu <dev@stillu.cc>
1 parent b59ae75 commit e898964

File tree

15 files changed

+770
-0
lines changed

15 files changed

+770
-0
lines changed

.idea/.idea.ida-picker.dir/.idea/.gitignore

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/.idea.ida-picker.dir/.idea/indexLayout.xml

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

App.xaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<Application x:Class="ida_picker.App"
2+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4+
xmlns:local="clr-namespace:ida_picker"
5+
Startup="Application_Startup">
6+
<Application.Resources>
7+
8+
</Application.Resources>
9+
</Application>

App.xaml.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using System.Windows;
2+
3+
namespace ida_picker;
4+
5+
/// <summary>
6+
/// Interaction logic for App.xaml
7+
/// </summary>
8+
public partial class App
9+
{
10+
private void Application_Startup(object sender, StartupEventArgs e)
11+
{
12+
string? filePath = null;
13+
14+
if (e.Args.Length > 0)
15+
{
16+
filePath = e.Args[0];
17+
}
18+
19+
MainWindow mainWindow = new MainWindow(filePath);
20+
mainWindow.Show();
21+
}
22+
}
23+

AssemblyInfo.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using System.Windows;
2+
3+
[assembly:ThemeInfo(
4+
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
5+
//(used if a resource is not found in the page,
6+
// or application resource dictionaries)
7+
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
8+
//(used if a resource is not found in the page,
9+
// app, or any theme specific resource dictionaries)
10+
)]

IDAInstallation.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System.Windows.Media;
2+
3+
namespace ida_picker
4+
{
5+
public class IdaInstallation
6+
{
7+
public string DisplayName { get; init; }
8+
public string Version { get; init; }
9+
public string InstallPath { get; init; }
10+
public ImageSource IconSource { get; set; }
11+
12+
public override string ToString()
13+
{
14+
return $"{DisplayName} ({Version})";
15+
}
16+
}
17+
}

IconExtractor.cs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
using System.Drawing;
2+
using System.IO;
3+
using System.Windows;
4+
using System.Windows.Interop;
5+
using System.Windows.Media;
6+
using System.Windows.Media.Imaging;
7+
8+
namespace ida_picker
9+
{
10+
public static class IconExtractor
11+
{
12+
public static ImageSource ExtractIcon(string installPath)
13+
{
14+
try
15+
{
16+
string icoPath = Path.Combine(installPath, "ida.ico");
17+
if (File.Exists(icoPath))
18+
{
19+
return new BitmapImage(new Uri(icoPath, UriKind.Absolute));
20+
}
21+
22+
string ida64Path = Path.Combine(installPath, "ida64.exe");
23+
if (File.Exists(ida64Path))
24+
{
25+
return ExtractIconFromExe(ida64Path);
26+
}
27+
28+
string idaPath = Path.Combine(installPath, "ida.exe");
29+
if (File.Exists(idaPath))
30+
{
31+
return ExtractIconFromExe(idaPath);
32+
}
33+
}
34+
catch (Exception)
35+
{
36+
// Fall through to default icon
37+
}
38+
39+
// Return a default icon if extraction fails
40+
return CreateDefaultIcon();
41+
}
42+
43+
private static ImageSource ExtractIconFromExe(string exePath)
44+
{
45+
try
46+
{
47+
using (Icon? icon = Icon.ExtractAssociatedIcon(exePath))
48+
{
49+
if (icon != null)
50+
{
51+
return Imaging.CreateBitmapSourceFromHIcon(
52+
icon.Handle,
53+
Int32Rect.Empty,
54+
BitmapSizeOptions.FromEmptyOptions());
55+
}
56+
}
57+
}
58+
catch (Exception)
59+
{
60+
// Fall through to default
61+
}
62+
63+
return CreateDefaultIcon();
64+
}
65+
66+
private static ImageSource CreateDefaultIcon()
67+
{
68+
// Create a simple default icon
69+
var drawingVisual = new DrawingVisual();
70+
using (DrawingContext drawingContext = drawingVisual.RenderOpen())
71+
{
72+
drawingContext.DrawRectangle(
73+
System.Windows.Media.Brushes.LightGray,
74+
new System.Windows.Media.Pen(System.Windows.Media.Brushes.Gray, 1),
75+
new Rect(0, 0, 64, 64));
76+
77+
drawingContext.DrawText(
78+
new FormattedText("IDA",
79+
System.Globalization.CultureInfo.InvariantCulture,
80+
FlowDirection.LeftToRight,
81+
new Typeface("Arial"),
82+
20,
83+
System.Windows.Media.Brushes.Black,
84+
VisualTreeHelper.GetDpi(drawingVisual).PixelsPerDip),
85+
new System.Windows.Point(12, 22));
86+
}
87+
88+
var renderTargetBitmap = new RenderTargetBitmap(64, 64, 96, 96, PixelFormats.Pbgra32);
89+
renderTargetBitmap.Render(drawingVisual);
90+
return renderTargetBitmap;
91+
}
92+
}
93+
}

MainWindow.xaml

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
<Window x:Class="ida_picker.MainWindow"
2+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4+
Title="IDA Launcher" Height="500" Width="700"
5+
WindowStartupLocation="CenterScreen"
6+
KeyDown="Window_KeyDown"
7+
Background="{DynamicResource BackgroundBrush}">
8+
<Grid Margin="20">
9+
<Grid.RowDefinitions>
10+
<RowDefinition Height="Auto"/>
11+
<RowDefinition Height="*"/>
12+
<RowDefinition Height="Auto"/>
13+
</Grid.RowDefinitions>
14+
15+
<TextBlock Grid.Row="0"
16+
Text="Select IDA Installation (Press 1-9 for quick selection):"
17+
FontSize="16" FontWeight="SemiBold"
18+
Margin="0,0,0,20"
19+
Foreground="{DynamicResource ForegroundBrush}"/>
20+
21+
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
22+
<ItemsControl x:Name="IdaItemsControl">
23+
<ItemsControl.ItemsPanel>
24+
<ItemsPanelTemplate>
25+
<WrapPanel Orientation="Horizontal"/>
26+
</ItemsPanelTemplate>
27+
</ItemsControl.ItemsPanel>
28+
<ItemsControl.ItemTemplate>
29+
<DataTemplate>
30+
<Border Background="{DynamicResource CardBackgroundBrush}"
31+
BorderBrush="{DynamicResource CardBorderBrush}"
32+
BorderThickness="1"
33+
CornerRadius="4"
34+
Margin="10"
35+
Padding="15"
36+
Width="150"
37+
Height="180"
38+
Cursor="Hand"
39+
MouseLeftButtonDown="Item_MouseLeftButtonDown"
40+
Tag="{Binding}">
41+
<Border.Style>
42+
<Style TargetType="Border">
43+
<Setter Property="Effect">
44+
<Setter.Value>
45+
<DropShadowEffect ShadowDepth="2"
46+
BlurRadius="5"
47+
Opacity="0.3"/>
48+
</Setter.Value>
49+
</Setter>
50+
<Style.Triggers>
51+
<Trigger Property="IsMouseOver" Value="True">
52+
<Setter Property="Background"
53+
Value="{DynamicResource CardHoverBackgroundBrush}"/>
54+
<Setter Property="BorderBrush"
55+
Value="{DynamicResource CardHoverBorderBrush}"/>
56+
<Setter Property="BorderThickness" Value="2"/>
57+
</Trigger>
58+
</Style.Triggers>
59+
</Style>
60+
</Border.Style>
61+
<Grid>
62+
<Grid.RowDefinitions>
63+
<RowDefinition Height="Auto"/>
64+
<RowDefinition Height="Auto"/>
65+
<RowDefinition Height="*"/>
66+
<RowDefinition Height="Auto"/>
67+
</Grid.RowDefinitions>
68+
69+
<Image Grid.Row="0"
70+
Source="{Binding IconSource}"
71+
Width="64"
72+
Height="64"
73+
HorizontalAlignment="Center"
74+
Margin="0,0,0,10"/>
75+
76+
<TextBlock Grid.Row="1"
77+
Text="{Binding DisplayName}"
78+
FontSize="13"
79+
FontWeight="SemiBold"
80+
TextWrapping="Wrap"
81+
TextAlignment="Center"
82+
Margin="0,0,0,5"
83+
Foreground="{DynamicResource ForegroundBrush}"/>
84+
85+
<TextBlock Grid.Row="3"
86+
Text="{Binding Version}"
87+
FontSize="11"
88+
Foreground="{DynamicResource SecondaryTextBrush}"
89+
TextAlignment="Center"
90+
VerticalAlignment="Bottom"/>
91+
</Grid>
92+
</Border>
93+
</DataTemplate>
94+
</ItemsControl.ItemTemplate>
95+
</ItemsControl>
96+
</ScrollViewer>
97+
98+
<Button Grid.Row="2"
99+
x:Name="CancelButton"
100+
Content="Cancel"
101+
Width="100"
102+
Height="35"
103+
HorizontalAlignment="Right"
104+
Margin="0,20,0,0"
105+
Click="CancelButton_Click"
106+
Background="{DynamicResource ButtonBackgroundBrush}"
107+
Foreground="{DynamicResource ForegroundBrush}">
108+
<Button.Style>
109+
<Style TargetType="Button">
110+
<Style.Triggers>
111+
<Trigger Property="IsMouseOver" Value="True">
112+
<Setter Property="Background"
113+
Value="{DynamicResource ButtonHoverBrush}"/>
114+
</Trigger>
115+
</Style.Triggers>
116+
</Style>
117+
</Button.Style>
118+
</Button>
119+
</Grid>
120+
</Window>

0 commit comments

Comments
 (0)