github link : https://github.com/kim-dong-hyun/AvaloniaImageButton
2023년 12월 8일 금요일
2023년 11월 24일 금요일
Rendering Video in Avalonia's NativeControlHost with SDL2.
Add a NativeEmbeddingControl class that inherits from NativeControlHost in MainWindow.axaml.cs
namespace AvaloniaDXPlayer
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
...
public class NativeEmbeddingControl : NativeControlHost
{
public IntPtr Handle { get; private set; }
protected override IPlatformHandle CreateNativeControlCore(IPlatformHandle parent)
{
var handle = base.CreateNativeControlCore(parent);
Handle = handle.Handle;
Console.WriteLine($"Handle : {Handle}");
return handle;
}
}
}
Add a NativeEmbeddingControl class that inherits from NativeControlHost in MainWindow.axaml.cs
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:nec="clr-namespace:AvaloniaDXPlayer"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="600"
x:Class="AvaloniaDXPlayer.MainWindow"
Width="800" Height="600" Title="AvaloniaDXPlayer">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="100"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" Background="Black">
<nec:NativeEmbeddingControl x:Name="host" Grid.Row="0" SizeChanged="Host_SizeChanged" />
</Grid>
<Canvas Grid.Row="1">
<TextBox x:Name="textURL" Margin="10" Width="300" Height="20" FontSize="14" Text=""/>
<Button x:Name="btnConnect" Content="Connect" Margin="320,10,0,0" />
<Button x:Name="btnClose" Content="Close" Margin="400,10,0,0" />
<Button x:Name="btnTest" Content="Test" Margin="460,10,0,0" />
</Canvas>
</Grid>
</Window>
Initialize SDL2. During this, insert the Handle of NativeEmbeddingControl as an argument into SDL_CreateWindowFrom
#if defined(LINUX) typedef void* HWND; #endif ... int VideoSDLDraw::init(
HWND hwnd
, int targetWidth, int targetHeight, int srcWidth, int srcHeight) { release(); DXPRINTF("VideoSDLDraw::init %dx%d, %dx%d\n", targetWidth, targetHeight, srcWidth, srcHeight); MUTEX_LOCK(&m_mutex); Uint32 pixelFormat = SDL_PIXELFORMAT_UNKNOWN;
m_pWindow = SDL_CreateWindowFrom(hwnd);
if (m_pWindow == NULL) { DXPRINTF("Window could not be created! SDL Error: %s\n", SDL_GetError()); goto fail; } m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); if (m_pRenderer == NULL) { DXPRINTF("Renderer could not be created! SDL Error: %s\n", SDL_GetError()); m_nTextureWidth = m_nTextureHeight = 0; goto fail; } else { //Initialize renderer color SDL_SetRenderDrawColor(m_pRenderer, 0x00, 0x00, 0x00, 0xFF); for (int i = 0; i < m_nTextDraw; i++) m_pTextDraw[i]->setSDLRenderer(m_pRenderer); } #if defined(LINUX) if (targetWidth == 0 && targetHeight == 0) { SDL_GetWindowSize(m_pWindow, &targetWidth, &targetHeight); } #endif pixelFormat = SDL_GetWindowPixelFormat(m_pWindow); m_pTexture = SDL_CreateTexture(m_pRenderer, pixelFormat, SDL_TEXTUREACCESS_STREAMING, targetWidth, targetHeight); if (m_pTexture == NULL) { DXPRINTF("Unable to create streamable texture! SDL Error: %s\n", SDL_GetError()); m_nTextureWidth = m_nTextureHeight = 0; goto fail; } m_nTextureWidth = targetWidth; m_nTextureHeight = targetHeight; SetRectEmpty(&m_rectTargetLast); SDL_RendererInfo rendererInfo; SDL_GetRendererInfo(m_pRenderer, &rendererInfo); DXPRINTF("SDL Renderer : %s\n", rendererInfo.name); MUTEX_UNLOCK(&m_mutex); return 0; fail: MUTEX_UNLOCK(&m_mutex); return -1; }
Linux
Windows
2023년 11월 6일 월요일
2가지 예제를 통한 간단한 WPF 바인딩 원리
<Window x:Class="TextBoxBind.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:TextBoxBind" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="50*"/> <RowDefinition Height="50*"/> </Grid.RowDefinitions> <TextBox Grid.Row="0"
Text="{Binding InputText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}
" /> <Button x:Name="button" Content="Add Text" HorizontalAlignment="Left" Margin="42,29,0,0" Grid.Row="1" VerticalAlignment="Top" Click="button_Click"/> </Grid> </Window>
using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Runtime.CompilerServices; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace TextBoxBind { /// <summary> /// MainWindow.xaml에 대한 상호 작용 논리 /// </summary> public partial class MainWindow : Window, INotifyPropertyChanged { private string inputText; public string InputText { get { return inputText; } set { if (inputText != value) { Console.WriteLine($"InputText : {value}"); inputText = value;
OnPropertyChanged("InputText");
} } } public MainWindow() { InitializeComponent(); DataContext = this; }
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } private void button_Click(object sender, RoutedEventArgs e) {
Thread thread = new Thread(new ThreadStart(() => InputText += "AAA")); thread.IsBackground = true; thread.Start();
} } }
<Window x:Class="ListBindTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ListBindTest"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<DataGrid Grid.Column="0" ItemsSource="{Binding People}" SelectedItem="{Binding SelectedItem}" SelectionMode="Single" />
<Canvas Grid.Column="1">
<TextBlock x:Name="textBlock" Canvas.Left="41" TextWrapping="Wrap" Text="Name" Canvas.Top="35"/>
<TextBlock x:Name="textBlock_Copy" Canvas.Left="41" TextWrapping="Wrap" Text="Age" Canvas.Top="87" HorizontalAlignment="Center" VerticalAlignment="Top"/>
<TextBox x:Name="textName" Canvas.Left="101" Text="{Binding SelectedItem.Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Canvas.Top="35" Width="120"/>
<TextBox x:Name="textAge" Canvas.Left="101" Text="{Binding SelectedItem.Age, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Canvas.Top="87" Width="120" HorizontalAlignment="Center" VerticalAlignment="Top"/>
<TextBlock x:Name="textBlock_Copy1" Canvas.Left="41" TextWrapping="Wrap" Text="Name" Canvas.Top="183" HorizontalAlignment="Center" VerticalAlignment="Top"/>
<TextBlock x:Name="textBlock_Copy2" Canvas.Left="41" TextWrapping="Wrap" Text="Age" Canvas.Top="235" HorizontalAlignment="Center" VerticalAlignment="Top"/>
<Canvas x:Name="canvasTest">
<TextBox x:Name="textName_Copy" Canvas.Left="101" Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Canvas.Top="183" Width="120" HorizontalAlignment="Center" VerticalAlignment="Top"/>
<TextBox x:Name="textAge_Copy" Canvas.Left="101" Text="{Binding Age, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Canvas.Top="235" Width="120" HorizontalAlignment="Center" VerticalAlignment="Top"/>
</Canvas>
<Button x:Name="button" Content="button" Canvas.Left="22" Canvas.Top="297" Click="button_Click"/>
<Button x:Name="button1" Content="button1" Canvas.Left="78" Canvas.Top="297" Click="button1_Click"/>
</Canvas>
</Grid>
</Window>
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace ListBindTest { /// <summary> /// MainWindow.xaml에 대한 상호 작용 논리 /// </summary> public partial class MainWindow : Window { private MainViewModel viewModel = new MainViewModel(); private Person personTest = new Person(); public MainWindow() { InitializeComponent(); DataContext = viewModel; personTest.Name = "Test"; personTest.Age = 100; canvasTest.DataContext = personTest; } private void button_Click(object sender, RoutedEventArgs e) { Person p = new Person(); p.Name = personTest.Name; p.Age = personTest.Age; Thread thread = new Thread(new ThreadStart(() => {
this.Dispatcher.BeginInvoke(new Action(() => { viewModel.People.Add(p); }));
})); thread.IsBackground = true; thread.Start(); } private void button1_Click(object sender, RoutedEventArgs e) { Thread thread = new Thread(new ThreadStart(() => { Person p = viewModel.SelectedItem;
if (p != null) p.Age++;
})); thread.IsBackground = true; thread.Start(); } } public class Person : INotifyPropertyChanged { private string _name; private int _age; public string Name { get { return _name; } set { _name = value; OnPropertyChanged(nameof(Name)); } } public int Age { get { return _age; } set { _age = value; OnPropertyChanged(nameof(Age)); } }
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } public class MainViewModel : INotifyPropertyChanged { private ObservableCollection<Person> _people; private Person _selectedItem; public MainViewModel() { _people = new ObservableCollection<Person>(); _people.Add(new Person { Name = "Alice", Age = 25 }); _people.Add(new Person { Name = "Bob", Age = 30 }); _people.Add(new Person { Name = "Charlie", Age = 35 }); } public ObservableCollection<Person> People { get { return _people; } set { _people = value; OnPropertyChanged(nameof(People)); } } public Person SelectedItem { get { return _selectedItem; } set { _selectedItem = value; OnPropertyChanged(nameof(SelectedItem)); } }
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }
namespace ListBindTest { /// <summary> /// MainWindow.xaml에 대한 상호 작용 논리 /// </summary> public partial class MainWindow : Window { private MainViewModel viewModel = new MainViewModel(); private Person personTest = new Person(); public MainWindow() { InitializeComponent(); DataContext = viewModel; personTest.Name = "Test"; personTest.Age = 100; canvasTest.DataContext = personTest; } private void button_Click(object sender, RoutedEventArgs e) { Person p = new Person(); p.Name = personTest.Name; p.Age = personTest.Age; Thread thread = new Thread(new ThreadStart(() => { #if false this.Dispatcher.BeginInvoke(new Action(() => { viewModel.People.Add(p); //viewModel.People.Add(personTest); })); #else
viewModel.People.Add(p);
#endif })); thread.IsBackground = true; thread.Start(); } private void button1_Click(object sender, RoutedEventArgs e) { Thread thread = new Thread(new ThreadStart(() => { //personTest.Name = personTest.Name + "X"; Person p = viewModel.SelectedItem;
if (p != null) p.Age++;
})); thread.IsBackground = true; thread.Start(); } } public class Person : INotifyPropertyChanged { private string _name; private int _age; public string Name { get { return _name; } set { _name = value; OnPropertyChanged(nameof(Name)); } } public int Age { get { return _age; } set { _age = value; OnPropertyChanged(nameof(Age)); } }
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } public class MainViewModel : INotifyPropertyChanged { private ObservableCollection<Person> _people; private Person _selectedItem;
private object objLock = new object();
public MainViewModel() { _people = new ObservableCollection<Person>(); _people.Add(new Person { Name = "Alice", Age = 25 }); _people.Add(new Person { Name = "Bob", Age = 30 }); _people.Add(new Person { Name = "Charlie", Age = 35 });
BindingOperations.EnableCollectionSynchronization(_people, objLock);
} public ObservableCollection<Person> People { get { return _people; } set { _people = value; OnPropertyChanged(nameof(People)); } } public Person SelectedItem { get { return _selectedItem; } set { _selectedItem = value; OnPropertyChanged(nameof(SelectedItem)); } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }
2023년 11월 1일 수요일
간단한 CA(Certificate Authority) 인증서 검증 원리
2023년 10월 30일 월요일
내가 이해한 Dependency Property
2023년 8월 23일 수요일
밑바닥부터 시작하는 딥러닝 4장 simpleNet 클래스와 numerical_gradient 함수 분석
2023년 6월 16일 금요일
openssl 빌드
strawberry perl 설치
https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=issell&logNo=220366548586
openssl 빌드
윈도우 - https://cinrueom.tistory.com/8
리눅스 - https://www.lesstif.com/system-admin/openssl-compile-build-6291508.html
openssl 인증서 발급
https://www.lesstif.com/system-admin/openssl-root-ca-ssl-6979614.html
2023년 3월 14일 화요일
C# UI 쓰레드 새로 생성해서 폼 띄우기/닫기
UI 쓰레드를 새로 생성해서 폼을 Show 하고 Close 하는 소스코드
public partial class MainForm : Form
{
private static KeyboardForm keyboardForm = null;
private static void ThreadKeyboard()
{
keyboardForm = new KeyboardForm();
Application.Run(keyboardForm);
keyboardForm = null;
}
public static void OpenKeyboard()
{
if (keyboardForm != null) return;
Thread newThread = new Thread(new ThreadStart(ThreadKeyboard));
newThread.SetApartmentState(ApartmentState.STA);
newThread.Start();
}
public static void CloseKeyboard()
{
if (keyboardForm != null)
{
keyboardForm.BeginInvoke(new Action(() => { keyboardForm.Close(); }));
}
}
2023년 3월 13일 월요일
automatic quick format command
입력 프롬프트 없이 한번에 퀵포맷하는 cmd 명령
format <드라이브명>: /FS:NTFS /Y /V:<볼륨이름> /Q
예) format d: /FS:NTFS /Y /V:Storage1 /Q
2023년 2월 23일 목요일
버추얼박스 느려졌을때 설정 변경
2023년 1월 25일 수요일
VC++ Unicode 와 MBSC 겸용으로 빌드시 MultiByteToWideChar/WideCharToMultiByte 함수 처리(리눅스 포함)
2023년 1월 13일 금요일
vc++ 메모리 릭 감지
프로그램 시작 부분에 아래 코드 넣고 실행 후 정상종료하면 메모리릭 발생시 출력창에 메모리릭 출력
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif
간단한 strtok_s 사용법
원본 문자열을 ',' 로 분할하고 2차원 배열에 복사하는 소스이다.
#define strtok_r strtok_s // 윈도우/리눅스 빌드
#endif
char m_szRecordPath[MAX_RECORD_PATH][MAX_PATH];
{
memset(&m_szRecordPath, 0, sizeof(m_szRecordPath));
m_nRecordPathCount = 0;
char *ret_ptr, *next_ptr;
ret_ptr = strtok_r(filepaths, ",", &next_ptr);
while (ret_ptr) {
memcpy(&m_szRecordPath[m_nRecordPathCount], ret_ptr, strlen(ret_ptr));
m_nRecordPathCount++;
ret_ptr = strtok_r(NULL, ",", &next_ptr);
}
for (int i=0; i<m_nRecordPathCount; i++)
printf("record path[%d] : %s\n", i, m_szRecordPath[i]);
}