.net MAUI 에서 앱 아이콘 변경 방법

Software/C#|2025. 12. 2. 14:04
반응형

안드로이드 앱을 만들기 위해 MAUI를 이용해서 만들었습니다. 

앱을 만들고 나서 아이콘을 변경하기 위해 인터넷에 돌아 다니는 방법을 사용해서 변경했는데 왠지 기본 아이콘에서 전혀 변경이 안돼어서 몇일을 찾고 찾아서 드디어 해결을 했습니다. 

 

솔루션 탐색기에서 Platforms→Android→Resources→AndroidManifest.xml 파일을 클릭하면

애플리케이션 세부정보가 나타납니다.

애플리케이션 아이콘 항목을 아래와 같이 변경을 해 주어야만 아이콘이 변경이 됩니다.

Resources→AppIcon 위치에 원하는 이미지를 넣습니다. (예 : Icon.png)

그런후 프로젝트 파일을 엽니다. (확장자 : csproj)

아래 내용을 추가 합니다.

<!-- App Icon -->
	<MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\icon.png" Color="#FFFFFF" />

그리고 다시 컴파일후에 실행하면 아이콘이 변경이 됩니다. 
반응형

댓글()

IEEE754 단정밀(32Bit) 데이타와 float 형 변수의 상호 변환 - C#

Software/C#|2025. 3. 31. 13:22
반응형

   

static class Ieee754Converter
{
    public static byte[] GetBytes(float value)
    {
        byte[] bytes = BitConverter.GetBytes(value);
        return bytes;
    }
    public static float ToSingle(byte[] bytes)
    {
        float value = BitConverter.ToSingle(bytes, 0);
        return value;
    }
}

 

예 : +7.282600E+01  <-> {0xE9} {0xA6} {0x91} {0x42}

 

byte[ ] temp = Ieee754Converter.GetBytes(3.141592f);
float value = Ieee754Converter.ToSingle(temp);
       

반응형

댓글()

YAML 로 프로그램 설정 데이타 저장 및 불러오기 - C#

Software/C#|2025. 3. 14. 10:07
반응형

이전에 JSON을 이용하여 제어프로그램의 Recipe 파일의 저장과 불러오기 기능에 대해 포스팅 했었다. 

그런데 조금 사용하기 불편하고 코딩량이 많아서 다른 수단을 찾다가 YAML 이 최근에 설정파일 저장용으로 많이 사용된다는 것을 보고 사용해 보았다. 코딩량도 상당히 줄었고 무엇보다 항목을 추가하거나 제거할 때 코딩에서 수정해야 하는 부분이 많이 줄어서 현재 모든 프로그램에서 사용하고 있다. 

 

1. YAML 사용하기 위해 Nuget에서 YamlDotNet 을 먼저 설치한다. 

 

2. Yaml 데이타를 저장하거나 불러오기 위한 클래스 생성 : 다양한 종류의 설정항목에 대응하기 위해 generic class 형식으로 만듦

public class YamlControl<T>
{ 
    public bool SaveYaml(string FileName, T data)
    {
        bool result = true;

        try
        {
            var serializer = new SerializerBuilder().Build().Serialize(data);

            using StreamWriter sw = new StreamWriter(FileName);
            sw.Write(serializer);
        }
        catch
        {
            result = false;    
        }

        return result;
    }

    public bool LoadYaml(string FileName, ref T objectData)
    {
        bool result = true;

        try
        {
            var yaml = File.ReadAllText(FileName);
            objectData = new DeserializerBuilder().Build().Deserialize<T>(yaml);
        }
        catch
        {
            result = false;
        }            

        return result;
    }
}

 

3. 설정항목에 대한 클래스 생성 : 아래 클래스는 프로그램에 따라 변경해야 하며 아래 내용은 예시적으로 만든 임의의 클래스 

public class RecipeInform
{
    public BurnInParam burnInParam = new BurnInParam();
    public SweepMeasParam sweepMeasParam = new SweepMeasParam();

    public class BurnInParam
    {
        public bool Measurement { get; set; }
        public double Bias { get; set; }
        public double Step { get; set; }
    }
    
    public class SweepMeasParam
    {
        public double StartCurrent { get; set; }
        public double StopCurrent { get; set; }
        public double StepCurrent { get; set; }
    }
}

 

4. 사용방법 

항목 불러오기 

YamlControl<RecipeInform> yamlControl = new YamlControl<RecipeInform>();
string filename = string.Format("{0}{1}.yaml", Global.conditionFolder, comboCondition.Text);
RecipeInform recipe = new RecipeInform();
yamlControl.LoadYaml(filename, ref recipe);


항목 저장하기 

RecipeInform recipe = new RecipeInform();
recipe.burnInParam.Measurement = checkBurnInMeas.Checked;
recipe.burnInParam.Bias = double.Parse(textBiasCurrent.Text);
recipe.burnInParam.Step = double.Parse(textBurnInStepCurrent.Text);
recipe.sweepMeasParam.StartCurrent = double.Parse(textStartCurrent.Text);
recipe.sweepMeasParam.StopCurrent = double.Parse(textStopCurrent.Text);
recipe.sweepMeasParam.StepCurrent = double.Parse(textStepCurrent.Text);


string filename = string.Format("{0}{1}.yaml", Global.conditionFolder, comboCondition.Text);
YamlControl<RecipeInform> yamlControl = new YamlControl<RecipeInform>();
yamlControl.SaveYaml(filename, recipe) ;
반응형

댓글()

Flow Meter(FML300-D SERIES) 제어 클래스 - C#

Software/C#|2025. 3. 11. 15:35
반응형

 

    public class FML300 
    {
        private readonly SerialPort commPort ;
        private readonly ModbusSerialMaster modbusSerialMaster ;

        public FML300(ModbusSerialMaster modbusSerial)
        {
            modbusSerialMaster = modbusSerial;
        }
        //---------------------------------------------------------------------------
        public FML300(SerialPort serialPort)
        {
            commPort = serialPort ;
            modbusSerialMaster = ModbusSerialMaster.CreateRtu(commPort) ;
        }
        //---------------------------------------------------------------------------
        public FML300(string portNumber)
        {
            try
            {
                commPort = new SerialPort(portNumber, 38400) ;
                commPort.Parity = Parity.None;
                commPort.StopBits = StopBits.One;
                commPort.ReadTimeout = 100;
                commPort.WriteTimeout = 100;
                commPort.Open();

                modbusSerialMaster = ModbusSerialMaster.CreateRtu(commPort) ;
            }
            catch
            {
            }
        }
        //---------------------------------------------------------------------------
        public bool InstantaneousFlowRate(byte DeviceAddress, ref double FlowRate)
        {
            bool result = true ;

            try
            {
                var buffer = modbusSerialMaster.ReadInputRegisters(DeviceAddress, 3, 1);
                FlowRate = buffer[0] ;
            }
            catch
            {
                result = false ;
            }

            return result ;
        }
        //---------------------------------------------------------------------------
        public bool FlowTemperature(byte DeviceAddress, ref double Temperature)
        {
            bool result = true ;    

            try
            { 
                var buffer = modbusSerialMaster.ReadInputRegisters(DeviceAddress, 4, 1) ;
                Temperature = buffer[0] ;
                if(Temperature > 6000) Temperature = 0;     // 물이 흐르지 않으면 온도가 큰값이 읽혀진다. 
            }
            catch
            {
                result = false ;
            }

            return result ;
        }
        //---------------------------------------------------------------------------
        public int FlowRateAndTemperature(byte DeviceAddress, ref double FlowRate, ref double Temperature)
        {
            int result = 0 ;    

            try
            { 
                var buffer = modbusSerialMaster.ReadInputRegisters(DeviceAddress, 1, 4) ;

                FlowRate = (double)buffer[1] / 100.0 ;
                Temperature = (double)buffer[2] / 10.0 ;

                if(Temperature > 6000) Temperature = 0;     // 물이 흐르지 않으면 온도가 큰값이 읽혀진다. 
            }
            catch
            {
                result = -1 ;
            }

            return result ;
        }
        //---------------------------------------------------------------------------
    }
반응형

댓글()

Chroma IT 의 UPS(Rodem Series) 제어 클래스 - C#

Software/C#|2025. 3. 11. 15:32
반응형

 

    public class RodemSeries
    {
        private SerialPort commPort;
        public double InputVoltage { get; }
        public double OutputVoltage { get; }
        public double Temperature { get; }
        public int BlackOut { get; }        // 0:No, 1:Yes
	    public int LowBattery { get; }      // 0:No, 1:Yes

        public RodemSeries(SerialPort CommPort)
        {
            commPort = CommPort;
        }
        //---------------------------------------------------------------------------
        public bool Initialize(string ModelName)
        {
            bool result = false ;
	        byte[] sendBuffer = new byte[] {(byte)'I', 0x0d} ;

            try
            {
                commPort.Write(sendBuffer, 0, sendBuffer.Length);
                Thread.Sleep(500);

                if(commPort.BytesToRead > 0)
                {
                    byte[] readBuffer = new byte[commPort.BytesToRead + 5];
                    commPort.Read(readBuffer, 0, commPort.BytesToRead);
                    string str = Encoding.Default.GetString(readBuffer);
                    result = str.Contains(ModelName);
                }
            }
            catch 
            { 
                result = false; 
            }

            return result ;
        }
        //---------------------------------------------------------------------------
        public bool ReadStatus()
        {
            bool result = true;
	        byte[] sendBuffer = new byte[] {(byte)'Q', (byte)'1', 0x0d} ;

            try
            {
                commPort.Write(sendBuffer, 0, sendBuffer.Length);
                Thread.Sleep(500);

                if(commPort.BytesToRead > 0)
                {
                    byte[] readBuffer = new byte[commPort.BytesToRead + 5];
                    commPort.Read(readBuffer, 0, commPort.BytesToRead);

                    if(readBuffer[0] != (byte)'(') result = false;
                    else
                    {
                        result = StatusInformation(readBuffer);    
                    }                    
                }
                else
                {
                    result = false;
                }
            }
            catch 
            { 
                result = false; 
            }

            return result;
        }
        //---------------------------------------------------------------------------
        private bool StatusInformation(byte[] Buffer)
        {
            bool result = true;

            try
            {
                string str = Encoding.Default.GetString(Buffer);
                string[] data = str.Split(' ');

                OutputVoltage = double.Parse(data[2]) ;
                Temperature = double.Parse(data[6]) ;

                BlackOut = Buffer[38] - 0x30;
                LowBattery = Buffer[39] - 0x30;

                if (BlackOut > 1 || BlackOut < 0) BlackOut = 0;
                if (LowBattery > 1 || LowBattery < 0) LowBattery = 0;
            }
            catch
            {
                result = false;
            }

            return result;
        }
        //---------------------------------------------------------------------------
    }
반응형

댓글()

Nice Cool 의 칠러 제어 (CM Series)

Software/C#|2024. 10. 29. 15:19
반응형

국내 나이스 쿨의 칠러 제어를 위한 코드 입니다. RS232통신을 통해 제어를 합니다. 

Modbus RTU 방식으로 처리하고 라이브러리는 NModbus4를 사용하였습니다. 

NModbus4 는 Nuget을 통해 설치하시면 됩니다. 

 

 

/****************************************************************************************************
     * Device : Chiller(CM SERIES)
     * Manufacture : NiceCool
     * Devicce Interface : RS232(Modbus RTU)
     * Version : 1.0.0
     * Program : Sihwan Kim
     *****************************************************************************************************/
    public class NiceCool_CMSeries 
    {
        public bool Active { get; set; } = false;
        public int ReadTimeout
        {
            set { modbusSerialMaster.Transport.ReadTimeout = value; }
            get { return modbusSerialMaster.Transport.ReadTimeout; }
        } 

        public int WriteTimeout
        {
            set { modbusSerialMaster.Transport.WriteTimeout = value; }
            get { return modbusSerialMaster.Transport.WriteTimeout; }
        } 

        private byte address;
        private SerialPort commPort ;
        private ModbusSerialMaster modbusSerialMaster ;

        public NiceCool_CMSeries(byte Address, ModbusSerialMaster modbusSerial)
        {
            address = Address;
            modbusSerialMaster = modbusSerial;
        }
        //---------------------------------------------------------------------------
        public NiceCool_CMSeries(byte Address, SerialPort serialPort)
        {
            address = Address;
            commPort = serialPort ;
            modbusSerialMaster = ModbusSerialMaster.CreateRtu(commPort) ;
        }
        //---------------------------------------------------------------------------
        public NiceCool_CMSeries(byte Address, string portNumber)
        {
            address = Address;

            try
            {
                commPort           = new SerialPort() ;
                commPort.PortName  = portNumber ;
                commPort.BaudRate  = 4800;
                commPort.Parity = Systehttp://m.IO.Ports.Parity.Even;
                commPort.Open();

                modbusSerialMaster = ModbusSerialMaster.CreateRtu(commPort) ;
            }
            catch
            {
            }
        }
        //---------------------------------------------------------------------------
        public bool Initialize(bool control)
        {
            bool result = true ;
            double temp = 0;

            ReadTimeout = 300; 
            WriteTimeout = 300;

            commPort.ReadTimeout = 300;
            commPort.WriteTimeout = 300;

            if (control) result = WaterTemperature(ref temp) ;

            return result;
        }
        //---------------------------------------------------------------------------
        public bool WaterTemperature(ref double Temperature)
        {
            bool result = true;

            try
            {
                var value = modbusSerialMaster.ReadHoldingRegisters(address, 259, 1) ;
                Temperature = value[0] / 10.0 ;
            }
            catch
            {
                result = false ;
            }

            return result;
        }
        //---------------------------------------------------------------------------
        public void SetWaterTemperature(double Temperature)
        {
            ushort setTemp = (ushort)(Temperature * 10) ;

            try
            { 
                modbusSerialMaster.WriteSingleRegister(address, 271, setTemp) ;
            }
            catch { }
        }
        //---------------------------------------------------------------------------
        public bool Run(bool Status)
        {
            bool result = true;
            
            try
            { 
                ushort action = 0 ;

                if(Status == true) action = 257 ;
                else action = 256 ;

                modbusSerialMaster.WriteSingleRegister(address, 270, action) ;
                Active = Status ;
            }
            catch
            {
                result= false ;
            }

            return result ;
        }
        //---------------------------------------------------------------------------
        public bool WaterFlow(ref double FlowValue)
        {
            bool result = true;

            try
            { 
                var value = modbusSerialMaster.ReadHoldingRegisters(address, 266, 1) ;
                FlowValue = value[0] / 10.0 ;
            }
            catch
            {
                result = false ;
            }

            return result;
        }
    }

반응형

댓글()

C#으로 만들어 보는 Sokoban Game(WPF)

Software/C#|2024. 4. 18. 15:46
반응형

 

소코반 게임을 WPF 버젼으로 수정해서 올립니다. 아직 WPF를 공부중이라 MVVM 은 사용을 하지 않고 제작을 하였습니다.

코드는 지속적으로 수정을 진행할 예정입니다. 

소스 코드는 아래 Git에서 다운 받으시면 됩니다. 

 

https://github.com/Sihwan-Kim/PushPush.git

 

아래 파일은 맵화일과 Config파일 입니다. 실행파일이 있는 곳에 넣으시면 됩니다. 

stage.zip
0.00MB

 

Winform 버전의 알고리즘은 그대로 사용하였고 기능적인 부분이 조금 수정되었습니다. 

1. 윈폼 버전에서는 맵의 크기가 10 x 10으로 고정하였지만 WPF 버전에서는 크기를 동적으로 수정할 수 있도록 하였습니다.

2. 윈도우의 크기가 변경되면 맵이 항상 중앙에 위치 하도록 하였습니다. 

 

 

 

반응형

댓글()

2차원 배열의 크기를 동적으로 변경 - C#

Software/C#|2024. 4. 18. 14:09
반응형

        private static Array ResizeArray(Array arr, int[] newSizes)
        {
            if(newSizes.Length != arr.Rank)
            {
                throw new ArgumentException("arr must have the same number of dimensions " +
                                            "as there are elements in newSizes", "newSizes");
            }

            var temp = Array.CreateInstance(arr.GetType().GetElementType(), newSizes);
            int length = arr.Length <= temp.Length ? arr.Length : temp.Length;
            Array.ConstrainedCopy(arr, 0, temp, 0, length);

            return temp;
        }

//----------------------------------------------------------------------------------------------------------------

public int[,] array = new int[2, 2] ;     // 2 x 2 배열 생성 

array  = (int[,])ResizeArray( array  , new int[] {12, 3}) ;    // 12 x 3 형식으로 변경 

 

 

반응형

댓글()