initial commit

This commit is contained in:
chi
2025-01-07 16:08:02 +09:00
parent 9e657e2558
commit 0a93a54a6f
268 changed files with 50767 additions and 0 deletions

View File

@@ -0,0 +1,246 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Threading;
using System.Threading.Tasks;
using System.Collections;
using COMM;
using System.Security.Cryptography.X509Certificates;
namespace arDev
{
public partial class Narumi : arRS232
{
public bool AGVMoveSet(BunkiData opt)
{
return AddCommand(eAgvCmd.MoveSet, opt.ToString());
}
public bool AGVMoveManual(ManulOpt opt, Speed spd, Sensor ss)
{
var param = opt.ToString() + spd.ToString()[0] + ((int)ss).ToString();
return AddCommand(eAgvCmd.ManualMove, param);
}
public bool AGVMoveRun(eRunOpt opt = eRunOpt.NotSet)
{
System.Text.StringBuilder sb = new StringBuilder();
if (opt == eRunOpt.Backward) sb.Append("B");
else if (opt == eRunOpt.Forward) sb.Append("F");
else sb.Append("0");
sb.Append("000");
return AddCommand(eAgvCmd.MoveStart, sb.ToString());
}
public bool AGVSetSpeed(eSetSpeed item, int speed)
{
string cmd = "SS";
if (item == eSetSpeed.Rotation) cmd = "SRS";
else cmd += item.ToString()[0];
cmd += speed.ToString("0000");
return AddCommand(cmd);
}
public bool AGVMoveStop(string Reason, eStopOpt opt = eStopOpt.Stop)
{
System.Text.StringBuilder sb = new StringBuilder();
if (opt == eStopOpt.MarkStop) sb.Append("MS");
else if (opt == eStopOpt.MarkRotateLeft) sb.Append("TL");
else if (opt == eStopOpt.MarkRotateRight) sb.Append("TR");
else if (opt == eStopOpt.MarkChangeDirection) sb.Append("BS");
else sb.Append("0S");
sb.Append("00");
sb.Append("0000"); //재기동시간
if (opt == eStopOpt.MarkStop)
VAR.BOOL[eVarBool.NEXTSTOP_MARK] = true;
//동작중이면 이 멈춤 명령을 기록으로 남긴다 230116
if (this.system1.agv_run)
RaiseMessage(MessageType.Normal, $"stop command from {Reason}");
return AddCommand(eAgvCmd.MoveStop, sb.ToString());
}
public bool AGVCommand(string cmd, string data)
{
return AddCommand(cmd + data);
}
public bool LiftControl(LiftCommand cmd)
{
return AddCommand(eAgvCmd.LiftControl, cmd.ToString());
}
public bool AGVCharge(int chargetID, bool on, int waittime = 3)
{
if (on)
return AddCommand(eAgvCmd.ChargeOn, chargetID.ToString("0000"));
else
return AddCommand(eAgvCmd.ChargeOf, chargetID.ToString("0000"));
}
public bool AGVErrorReset()
{
return AddCommand(eAgvCmd.ErrorReset, "FFFF");
}
public bool AGVTowerLamp(bool on)
{
return AddCommand(eAgvCmd.TowerLamp, (on ? "I" : "O"));
}
public bool AGVSetAddress(int value)
{
return AddCommand($"SAD{value:0000}");
}
public bool AGVSetPanID(string value)
{
value = value.PadLeft(4, '0');
return AddCommand($"SPN{value}");
}
public bool AGVSetChannel(string value)
{
value = value.PadLeft(4, '0');
return AddCommand($"SCH{value}");
}
public bool AGVGateOutTimer(int value)
{
return AddCommand($"SGT{value:0000}");
}
/// <summary>
/// 정지감속주기 및 상수
/// </summary>
/// <returns></returns>
public bool AGVSetStopAcc(int interval, int value)
{
var cmds = new string[] {
$"SSK{interval:0000}",
$"SCK{value:0000}"
};
return AddCommand(cmds);
}
public bool AGVSetTagReinputTime(int value)
{
return AddCommand($"STT{value:0000}");
}
public bool AGVSetPID(eSetPIDSpeed speed, int P, int I, int D)
{
var cmd = "S";
var cmd2 = "";
if (speed == eSetPIDSpeed.High) cmd2 = "K";
else if (speed == eSetPIDSpeed.Middle) cmd2 = "M";
else if (speed == eSetPIDSpeed.Low) cmd2 = "L";
else if (speed == eSetPIDSpeed.Stop) cmd2 = "S";
var cmds = new string[] {
$"{cmd}P{cmd2}{P:0000}",
$"{cmd}I{cmd2}{I:0000}",
$"{cmd}D{cmd2}{D:0000}",
};
return AddCommand(cmds);
}
protected bool AddCommand(params string[] cmds)
{
bool ret = true;
ACKData = string.Empty; //회신값 제거
foreach (var cmdline in cmds)
{
var fullcmd = MakeCheckSum(cmdline);
//commandQueue.Enqueue(fullcmd);
if (WriteData(fullcmd) == false) ret = false;
System.Threading.Thread.Sleep(1);
}
return ret;
}
protected bool AddCommand(eAgvCmd command, BunkiData param)
{
return AddCommand(command, param.ToString());
}
/// <summary>
/// CBR커맨드를 사용하여 옵션값을 전송 합니다
/// 11.분기명령 = CBR
/// </summary>
/// <param name="param"></param>
/// <param name="Repeat"></param>
protected bool AddCommand(BunkiData param)
{
return AddCommand(eAgvCmd.MoveSet, param.ToString());
}
protected bool AddCommand(eAgvCmd command, string param = "")
{
string cmdString;
bool retval = false;
switch (command)
{
case eAgvCmd.ErrorReset:
cmdString = $"SFR{param}";
retval = AddCommand(cmdString);
break;
case eAgvCmd.TowerLamp:
cmdString = $"CBZ" + $"0299{param}0000";
retval = AddCommand(cmdString);
break;
case eAgvCmd.MoveStop:
cmdString = $"CST{param}";
system1.agv_run_manual = false;
retval = AddCommand(cmdString);
break;
case eAgvCmd.MoveStart:
cmdString = $"CRN{param}";
retval = AddCommand(cmdString);
break;
case eAgvCmd.ChargeOf:
cmdString = $"CBT{param}O0003"; ///0003=충전대기시간
retval = AddCommand(cmdString);
RaiseMessage(arRS232.MessageType.Normal, "충전취소전송");
break;
case eAgvCmd.ChargeOn:
cmdString = $"CBT{param}I0003"; ///0003=충전대기시간
retval = AddCommand(cmdString);
RaiseMessage(arRS232.MessageType.Normal, "충전명령전송");
break;
case eAgvCmd.GoTurnLeft:
cmdString = $"CTL0000";
retval = AddCommand(cmdString);
break;
case eAgvCmd.GoTurnRight:
cmdString = $"CTR0000";
retval = AddCommand(cmdString);
break;
case eAgvCmd.goTurnBack:
cmdString = $"CTB0000";
retval = AddCommand(cmdString);
break;
case eAgvCmd.CallCancle:
cmdString = $"CCL0{param}010000";
retval = AddCommand(cmdString);
break;
case eAgvCmd.MoveSet:
cmdString = $"CBR{param}";
retval = AddCommand(cmdString);
break;
case eAgvCmd.ManualMove:
system1.agv_run_manual = true;
cmdString = $"CRT{param}";
retval = AddCommand(cmdString);
break;
case eAgvCmd.LiftControl:
cmdString = "CLF" + param.PadRight(6, '0');
retval = AddCommand(cmdString);
break;
}
return retval;
}
}
}

View File

@@ -0,0 +1,19 @@
using System;
namespace arDev
{
public partial class Narumi
{
public class DataEventArgs : EventArgs
{
public DataType DataType { get; set; }
public DataEventArgs(DataType type)
{
DataType = type;
}
}
}
}

View File

@@ -0,0 +1,213 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace arDev
{
public partial class Narumi
{
public enum eMoveDir
{
Forward,
Backward,
}
public enum eMoveSpd
{
High,
Middle,
Low,
}
public enum eSetPIDSpeed
{
High,
Middle,
Low,
Stop,
}
public enum eSetSpeed
{
High,
Middle,
Low,
Stop,
Rotation,
}
public enum eBunki
{
Right,
Strate,
Left,
}
public enum Messagetype
{
Normal,
Error,
Send,
Recv,
}
public enum DataType
{
UNKNOWN,
TAG,
CALL,
STS,
ACK,
NAK,
CCA,
}
public class BunkiData
{
public BunkiData()
{
}
public BunkiData(char dir, char bunki, char speed)
{
if (dir == 'F') Direction = eMoveDir.Forward;
else if (dir == 'B') Direction = eMoveDir.Backward;
if (bunki == 'S') Bunki = eBunki.Strate;
else if (bunki == 'L') Bunki = eBunki.Left;
else if (bunki == 'R') Bunki = eBunki.Right;
if (speed == 'H') this.Speed = eMoveSpd.High;
else if (speed == 'M') this.Speed = eMoveSpd.Middle;
else if (speed == 'L') this.Speed = eMoveSpd.Low;
}
public eMoveDir Direction { get; set; } = eMoveDir.Forward;
public eBunki Bunki { get; set; } = eBunki.Strate;
public eMoveSpd Speed { get; set; } = eMoveSpd.Middle;
public int PBSSensor { get; set; } = 1;
public override string ToString()
{
System.Text.StringBuilder sb = new StringBuilder();
sb.Append(Direction.ToString()[0]);
sb.Append(Bunki.ToString()[0]);
sb.Append(Speed.ToString()[0]);
sb.Append(PBSSensor.ToString()[0]);
return sb.ToString();
}
}
public enum eAgvCmd
{
/// <summary>
/// 충전시작
/// CMD : CBT02{nBatteryNo}I0103
/// </summary>
ChargeOn,
/// <summary>
/// 충전취소
/// CMD : CBT02{nBatteryNo}O0103
/// </summary>
ChargeOf,
/// <summary>
/// 이동명령(파라미터필요)
/// 이동대상,속도(H,M,L),센서사용여부(1,0)
/// ex) BSLTH0
/// CMD : CRT{param}
/// </summary>
ManualMove,
/// <summary>
/// 기동명령
/// CMD : CRN0000
/// </summary>
MoveStart,
/// <summary>
/// 분기명령
/// CMD : CBR{param}
/// </summary>
MoveSet,
/// <summary>
/// 정지 명령
/// CMD : CST0S000000
/// </summary>
MoveStop,
/// <summary>
/// 콜 취소,
/// Param : 번호 char(1)
/// CMD : CCL0{param}010000
/// </summary>
CallCancle,
/// <summary>
/// CMD : CTL0000
/// </summary>
GoTurnLeft,
/// <summary>
/// CMD : CTR0000
/// </summary>
GoTurnRight,
/// <summary>
/// CMD : CTB0000
/// </summary>
goTurnBack,
/// <summary>
/// CMD : CBZ
/// </summary>
TowerLamp,
/// <summary>
/// CMD : SFR
/// </summary>
ErrorReset,
/// <summary>
/// CMD : CLF
/// </summary>
LiftControl,
/// <summary>
/// SS(H/M/L/S)
/// SRS
/// </summary>
SetSpeed,
}
public enum eForm
{
DriveControl,
ManualControl,
RouteSelect,
Setting,
ModeChange,
}
public enum eNotify
{
ReadTag,
IpAddresschanged,
NameChanged,
ReadViewStep,
ReadViewCall,
WatchError,
/// <summary>
/// 통신에서받은 AGV의 상태값이며, 속도 진행 방향을 가지고 있음
/// Dashboardform 하단에 상태 표시 함
/// </summary>
StatusDisplay,
StatusComm,
StatusRiv,
StatusETC,
ChangeMode,
/// <summary>
/// 편집대상경로는 아래 변수에 저장되어잇음
/// datamanager.sEditrRoute
/// </summary>
EditRoute,
}
}
}

View File

@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{8BAE0EAC-3D25-402F-9A65-2BA1ECFE28B7}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>arDevice</RootNamespace>
<AssemblyName>Narumi</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="DataEventArgs.cs" />
<Compile Include="EnumData.cs" />
<Compile Include="Command.cs" />
<Compile Include="Structure\ErrorFlag.cs" />
<Compile Include="Narumi.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Structure\SystemFlag0.cs" />
<Compile Include="Structure\AgvData.cs" />
<Compile Include="Structure\Signals.cs" />
<Compile Include="Structure\SystemFlag1.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CommData\CommData.csproj">
<Project>{14e8c9a5-013e-49ba-b435-efefc77dd623}</Project>
<Name>CommData</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -0,0 +1,586 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Threading;
using System.Threading.Tasks;
using System.Collections;
using COMM;
using System.Security.Cryptography.X509Certificates;
namespace arDev
{
public partial class Narumi : arRS232
{
Hashtable SystemCheck, ErrorCheck;
private Queue Errlog; // 에러발생시 코드 임시 저장용(쓰레드 동기화용)
public int nBatteryNo { get; set; } = 0;
public Narumi()
{
SystemCheck = new Hashtable();
SystemCheck.Add(15, "100");
SystemCheck.Add(14, "9");
SystemCheck.Add(13, "8");
SystemCheck.Add(12, "53");
SystemCheck.Add(11, "3");
//SystemCheck.Add(10, "66");
//SystemCheck.Add(9, "56");
SystemCheck.Add(8, "6");
SystemCheck.Add(7, "5");
SystemCheck.Add(6, "60");
SystemCheck.Add(5, "1");
SystemCheck.Add(4, "2");
//SystemCheck.Add(3, "65");
//SystemCheck.Add(2, "55");
//SystemCheck.Add(1, "11");
//SystemCheck.Add(0, "22");
ErrorCheck = new Hashtable();
ErrorCheck.Add(15, "17");
ErrorCheck.Add(14, "15");
ErrorCheck.Add(13, "18");
ErrorCheck.Add(12, "19");
//ErrorCheck.Add(11, "300");
ErrorCheck.Add(10, "299");
ErrorCheck.Add(9, "298");
ErrorCheck.Add(8, "297");
ErrorCheck.Add(7, "296");
//ErrorCheck.Add(6,"");
ErrorCheck.Add(5, "12");
ErrorCheck.Add(4, "13");
ErrorCheck.Add(3, "14");
ErrorCheck.Add(2, "16");
ErrorCheck.Add(1, "11");
ErrorCheck.Add(0, "10");
Errlog = new Queue();
MinRecvLength = 4;
COMM.VAR.Init(128);
}
#region "External Events"
/// <summary>
/// 분석완료된 데이터 이벤트
/// </summary>
public event EventHandler<DataEventArgs> DataReceive;
#endregion
protected override bool CustomParser(byte[] buf, out byte[] remainBuffer)
{
List<byte> remain = new List<byte>();
//데이터는 총 34byt 이며 , DD~77로 구성됨
Boolean bComplete = false;
for (int i = 0; i < buf.Length; i++)
{
var incomByte = buf[i];
if (bComplete == true)
{
remain.Add(incomByte);
}
else
{
if (incomByte == 0x02)
{
findSTX = true;
tempBuffer.Clear();
tempBuffer.Add(incomByte);
}
else if (incomByte == 0x03)
{
//데이터가 맞게 수신됨
//tempBuffer.Add(incomByte);
tempBuffer.Add(incomByte);
findSTX = false;
bComplete = true;
}
else
{
tempBuffer.Add(incomByte);
if (tempBuffer.Count == 150) //data overload
{
findSTX = false;
tempBuffer.Clear();
bComplete = false;
RaiseMessage(MessageType.Error, "Buffer Over");
}
}
}
}
remainBuffer = remain.ToArray();
return bComplete;
}
public class Dataframe
{
public byte STX { get; private set; }
public byte ETX { get; private set; }
public byte[] Data { get; private set; }
public string DataString { get; private set; }
public byte[] checksum { get; private set; } = new byte[2];
public bool Valid { get; private set; } = false;
public string Message { get; private set; } = string.Empty;
public byte[] Buffer { get; private set; }
public string Cmd { get; private set; } = string.Empty;
public bool Parse(byte[] data, int MinRecvLength = 0)
{
if (data == null || data.Any() == false)
{
this.Message = string.Format("수신 데이터가 없습니다");
return false;
}
else if (data.Length < 5)
{
this.Message = $"데이터의 길이가 5보다 작습니다 길이={data.Length}";
return false;
}
else if (MinRecvLength > 0 && data.Length < MinRecvLength)
{
this.Message = $"데이터의 길이가 {MinRecvLength}보다 작습니다 길이={data.Length}";
return false;
}
else if (data[0] != 0x02 || data[data.Length - 1] != 0x03)
{
this.Message = $"STX/ETX Error";
return false;
}
Buffer = new byte[data.Length];
Array.Copy(data, Buffer, data.Length);
STX = data[0];
ETX = data[data.Length - 1];
Array.Copy(data, data.Length - 3, checksum, 0, 2);
Data = new byte[data.Length - 4];
Array.Copy(data, 1, Data, 0, data.Length - 4);
if (data.Length > 2) Cmd = System.Text.Encoding.Default.GetString(Data, 0, 3);
this.DataString = System.Text.Encoding.Default.GetString(Data);
Valid = true;
return true;
}
public Dataframe(byte[] buffer = null, int minlen = 0)
{
if (buffer != null) Parse(buffer);
}
}
public override bool ProcessRecvData(byte[] data)
{
//LastReceiveBuffer
var frame = new Dataframe(data, MinRecvLength);
if (frame.Valid == false)
{
RaiseMessage(arRS232.MessageType.Error, frame.Message);
return false;
}
else if (frame.DataString.StartsWith("$") == false && CheckSum(data) == false)
{
RaiseMessage(arRS232.MessageType.Error, "Checksum Error MSG=" + frame.DataString);
return false;
}
var retval = true;
///////////////////////////////////////////////////////////////////////////////
if (frame.Cmd.Equals("ACK") || frame.Cmd.Equals("NAK"))
{ // 응답확인값 수신 : Header(ACX), Length(9), CheckSum 확인
RevACK(frame);
}
///////////////////////////////////////////////////////////////////////////////
else if (frame.Cmd.Equals("STS"))
{ // AGV 상태 정보 : Header(STS), Length(30), CheckSum 확인
RevSTS(frame);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
else if ((frame.Cmd.Equals("TAG") || frame.Cmd.Equals("CAL") || frame.Cmd.Equals("CCA")))
{ // TAG ID 정보 : Header(STX), Length(13), CheckSum 확인
RevTAG(frame);
}
else if (frame.DataString.StartsWith("$"))
{
// $로 시작되는 AGV 상태 표시
//var text_Sts_Etc = Encoding.Default.GetString(bRcvData, 3, bRcvData.Length - 2).TrimStart(' '); //20210311 김정만 - SmartX FrameWork 사용 안함으로 주석처리
//var sMessageOther = Encoding.Default.GetString(bRcvData, 3, bRcvData.Length - 2).TrimStart(' ');
RaiseMessage(arRS232.MessageType.Normal, "$메세지수신:" + frame.DataString);
}
else
{
try
{
DataReceive?.Invoke(this, new DataEventArgs(DataType.UNKNOWN));
}
catch (Exception ex)
{
RaiseMessage(arRS232.MessageType.Error, ex.Message);
retval = false;
}
}
return retval;
}
#region [] ACK()
public string ACKData { get; set; } = string.Empty;
public DateTime ACKtime { get; set; } = DateTime.Now;
private void RevACK(Dataframe frame)
{
//ACKSADA7
var rcvdNow = frame.DataString;
var bRcvData = frame.Buffer;
ACKData = rcvdNow.Substring(3);
ACKtime = DateTime.Now;
if (rcvdNow.StartsWith("ACK"))
{
//RaiseMessage("get ack");
DataReceive?.Invoke(this, new DataEventArgs(DataType.ACK));
//if (datamanager.commandQueue.Count != 0)
//{
// byte[] bCmdData = encoding.GetBytes((String)datamanager.commandQueue.Peek());
// if (bCmdData[1] == bRcvData[4] && bCmdData[2] == bRcvData[5] && bCmdData[3] == bRcvData[6]) //보낸값이 맞는지 확인후 Dequeue
// {
// nSendCount = 0;
// datamanager.commandQueue.Dequeue();
// sSendCommandString = "";
// }
//}
}
else if (rcvdNow.StartsWith("NAK"))
{
//RaiseMessage("get nak");
DataReceive?.Invoke(this, new DataEventArgs(DataType.NAK));
//nSendCount = 0; //NAK - 재전송이 날아왔을때 nSendCommandCounter 초기화
}
}
#endregion
public SystemFlag0 system0 = new SystemFlag0();
public SystemFlag1 system1 = new SystemFlag1();
public ErrorFlag error = new ErrorFlag();
public AgvData data = new AgvData();
public Signal signal = new Signal();
#region [] STS(AGV상태정보)
public string LastSTS { get; set; } = string.Empty;
private void RevSTS(Dataframe frame)
{
LastSTS = frame.DataString;
string rcvdNow = frame.DataString;
byte[] bRcvData = frame.Buffer;
var encoding = System.Text.Encoding.Default;
try
{
// AGV 베터리 잔량 표시 flag (4~6) /////////////////////////////////////////////////////////////////////////////////////////////////////////////
var idx = 3;
var battery = int.Parse(rcvdNow.Substring(idx, 3)) / 10f;// Convert.ToDouble(encoding.GetString(rcvdNow, 3, 3)) / 10;
idx += 3;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// AGV 장치연결상태 flag (7~10) ////////////////////////////////////////////////////////////////////////////////////////////////////////////
var nDataTemp = Convert.ToInt16(rcvdNow.Substring(idx, 4), 16);
system0.SetValue(nDataTemp);
idx += 4;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// AGV Sts(현재 상태) flag (11~14) ////////////////////////////////////////////////////////////////////////////////////////////////////////////
nDataTemp = Convert.ToInt16(rcvdNow.Substring(idx, 4), 16);
system1.SetValue(nDataTemp);
idx += 4;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// AGV Error flag (15~18)////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
nDataTemp = Convert.ToInt16(rcvdNow.Substring(idx, 4), 16);
error.SetValue(nDataTemp);
idx += 4;
data.Speed = rcvdNow.Substring(idx, 1)[0]; idx += 1; //L,M.H
data.Sts = rcvdNow.Substring(idx, 1)[0]; idx += 1; //S(직진),L(좌분기),R(우분기)
data.Direction = rcvdNow.Substring(idx, 1)[0]; idx += 1; //F,B,L,R
data.guidesensor = int.Parse(rcvdNow.Substring(idx, 1)); idx += 1; //가이드 좌측부터 1~9
nDataTemp = Convert.ToByte(rcvdNow.Substring(idx, 2), 16);
signal.SetValue(nDataTemp);
//data.Sts = encoding.GetString(bRcvData, 19, 3); //20210311 김정만 - SmartX FrameWork 사용 안함으로 주석처리
//var Sts_cSpeed = encoding.GetString(bRcvData, 19, 1)[0];
//var Sts_cDirection = encoding.GetString(bRcvData, 20, 1)[0];
//var Sts_cFB = encoding.GetString(bRcvData, 21, 1)[0];
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////가이드센서 정보 (22)//////////////////////////////////////////////////////////////////////////////////////////////////////////
//var Sts_nGuide = 0;
//if (bRcvData[22] > 47 && bRcvData[22] < 58) { Sts_nGuide = Convert.ToInt32(encoding.GetString(bRcvData, 22, 1)); }
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////마크센서 & 포토센서 정보 (23~24)////////////////////////////////////////////////////////////////////////////////////////////////////
//nDataTemp = Convert.ToInt32(encoding.GetString(bRcvData, 23, 2), 16);
//data.Sts_bMark1 = Convert.ToBoolean(nDataTemp & 0x4);
//data.Sts_bMark2 = Convert.ToBoolean(nDataTemp & 0x8);
//data.Sts_bCargo = Convert.ToBoolean(nDataTemp & 0x10);
////포토센서
//if (Sts_cFB == 'F')
//{
// system.Sts_nSenser = Convert.ToInt32(encoding.GetString(bRcvData, 26, 1));
//}
//else if (Sts_cFB == 'B')
//{
// system.Sts_nSenser = Convert.ToInt32(encoding.GetString(bRcvData, 27, 1));
//}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//AGV 속도/분기/방향 (19~21)//////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
DataReceive?.Invoke(this, new DataEventArgs(DataType.STS));
}
catch (Exception ex)
{
RaiseMessage(MessageType.Error, $"Parse Error(STS) = {ex.Message}");
}
}
#endregion
#region [] TAG()
System.Text.Encoding encoding = System.Text.Encoding.Default;
string old_TagString = string.Empty;
string old_CALString = string.Empty;
string old_CCAString = string.Empty;
private void RevTAG(Dataframe frame)
{
string rcvdNow = frame.DataString;
byte[] bRcvData = frame.Buffer;
if (rcvdNow.StartsWith("TAG"))
{
//221123 chi 숫자로변경
var tagnostr = rcvdNow.Substring(3);
if (int.TryParse(tagnostr, out int tagnoint))
{
var Changed = !old_TagString.Equals(tagnostr);
data.TagString = tagnostr;
data.TagNo = tagnoint;
old_TagString = tagnostr;
DataReceive?.Invoke(this, new DataEventArgs(DataType.TAG));
}
WriteData(MakeCheckSum("ACKTAG"));
}
else if (rcvdNow.StartsWith("CAL"))
{
var tagnostr = encoding.GetString(bRcvData, 4, 4);
if (int.TryParse(tagnostr, out int tagnoint))
{
var Changed = !old_CALString.Equals(tagnostr);
data.CallString = tagnostr;
data.CallNo = tagnoint;
old_CALString = tagnostr;
if (Changed) DataReceive?.Invoke(this, new DataEventArgs(DataType.CALL));
}
WriteData(MakeCheckSum("ACKCAL"));
}
else if (rcvdNow.StartsWith("CCA")) //능동형 Call에 의하여 들어 오는 구문
{
var tagnostr = encoding.GetString(bRcvData, 4, 4);
if (int.TryParse(tagnostr, out int tagnoint))
{
var Changed = !old_CCAString.Equals(tagnostr);
data.CCAString = tagnostr;
data.CCANo = tagnoint;
old_CCAString = tagnostr;
if (Changed) DataReceive?.Invoke(this, new DataEventArgs(DataType.CCA));
}
WriteData(MakeCheckSum("ACKCCA"));
}
}
#endregion
private string MakeCheckSum(string sCommand)
{
//sCommand = sCommand.ToUpper();
List<byte> buffer = new List<byte>();
buffer.Add(0x02);
//byte[] bCommand = System.Text.ASCIIEncoding.ASCII.GetBytes(sCommand);
buffer.AddRange(System.Text.ASCIIEncoding.ASCII.GetBytes(sCommand));
//make sum
int nSum = 0;
for (int nCnt = 1; nCnt < buffer.Count; nCnt++)
nSum += buffer[nCnt];
string sSum = nSum.ToString("X2").ToUpper();// Convert.ToString(nSum, 16).ToUpper();
if (sSum.Length < 2) sSum = "0" + sSum;
sSum = sSum.Substring(sSum.Length - 2);
//if (sSum.Length == 3)
// sSum = sSum.Remove(0, 1);
//else if (sSum.Length == 4)
// sSum = sSum.Remove(0, 2);
buffer.AddRange(System.Text.ASCIIEncoding.Default.GetBytes(sSum));
buffer.Add(0x03);
// byte[] bStxEtx = { 0x02, 0x03 };
//var orgstr = (System.Text.ASCIIEncoding.ASCII.GetString(bStxEtx, 0, 1) + sCommand + sSum + System.Text.ASCIIEncoding.ASCII.GetString(bStxEtx, 1, 1));
var newstr = System.Text.Encoding.Default.GetString(buffer.ToArray());
return newstr;
}
///// <summary>
///// commandQueue에 명령을 추가합니다(체크섬은 자동 추가됨)
///// </summary>
///// <param name="cmd">체크섬을 제외한 평문</param>
///// <param name="addlog">sendlog 에 추가할 경우 true를 입력하세요</param>
//public void AddCommand(string cmd, bool addlog = true, int Repeat = 1)
//{
// var fullcmd = MakeCheckSum(cmd);
// for (int i = 0; i < Repeat; i++)
// commandQueue.Enqueue(fullcmd);
// if (addlog)
// {
// Message?.Invoke(this, new MessageEventArgs()
// }
//}
public enum eStopOpt
{
Stop = 0,
MarkStop,
MarkRotateLeft,
MarkRotateRight,
MarkChangeDirection,
}
public enum eRunOpt
{
NotSet,
Forward,
Backward,
}
public enum ManulOpt
{
FS,
BS,
RT,
LT,
FL,
FR,
BL,
BR,
}
public enum Sensor
{
PBSOff = 0,
PBSOn,
AllOn,
}
public enum Speed
{
High,
Mid,
Low,
}
public enum LiftCommand
{
/// <summary>
/// lift up
/// </summary>
UP,
/// <summary>
/// lift down
/// </summary>
DN,
/// <summary>
/// lift 동작 정지
/// </summary>
STP,
/// <summary>
/// magnet holder on
/// </summary>
ON,
/// <summary>
/// magnet holder off
/// </summary>
OFF
}
private bool CheckSum(byte[] bData)
{
if (bData.Length < 2) // 데이터 길이가 2이하일 경우 비정상 처리
return false;
int nSum = 0;
// byte[] bData = encoding.GetBytes(sData);
for (int nCnt = 1; nCnt < bData.Length - 3; nCnt++)
{
nSum += bData[nCnt];
}
string sSum = Convert.ToString(nSum, 16).ToUpper();
string sCSTemp = string.Empty;
if (sSum.Length == 3)
sCSTemp = sSum.Remove(0, 1);
else if (sSum.Length == 4)
sCSTemp = sSum.Remove(0, 2);
if (bData[bData.Length - 2] == '*' && bData[bData.Length - 3] == '*')
return true;
if (sCSTemp[0] == (char)(bData[bData.Length - 3]) && sCSTemp[1] == (char)(bData[bData.Length - 2]))
return true;
else
return false;
}
}
}

View File

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 어셈블리에 대한 일반 정보는 다음 특성 집합을 통해
// 제어됩니다. 어셈블리와 관련된 정보를 수정하려면
// 이러한 특성 값을 변경하세요.
[assembly: AssemblyTitle("BMS Commnunication Module")]
[assembly: AssemblyDescription("BMS Commnunication Module")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("ATK4")]
[assembly: AssemblyProduct("BMS Commnunication Module")]
[assembly: AssemblyCopyright("Copyright ©ATK4 2020")]
[assembly: AssemblyTrademark("ATK4")]
[assembly: AssemblyCulture("")]
// ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에
// 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면
// 해당 형식에 대해 ComVisible 특성을 true로 설정하세요.
[assembly: ComVisible(false)]
// 이 프로젝트가 COM에 노출되는 경우 다음 GUID는 typelib의 ID를 나타냅니다.
[assembly: Guid("7a94c30c-6772-4f71-bf9c-111071a1bc70")]
// 어셈블리의 버전 정보는 다음 네 가지 값으로 구성됩니다.
//
// 주 버전
// 부 버전
// 빌드 번호
// 수정 버전
//
// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호를
// 기본값으로 할 수 있습니다.
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("20.03.09.0000")]
[assembly: AssemblyFileVersion("20.03.09.0000")]

View File

@@ -0,0 +1,50 @@
using System;
namespace arDev
{
public partial class Narumi
{
public class AgvData
{
public char Sts { get; set; }
public char Speed { get; set; }
public char Direction { get; set; }
public int guidesensor { get; set; }
public string TagString { get; set; } = string.Empty;
public int TagNo { get; set; } = -1;
public string CallString { get; set; } = string.Empty;
public int CallNo { get; set; } = -1;
public string CCAString { get; set; } = string.Empty;
public int CCANo { get; set; } = -1;
public override string ToString()
{
//모든사태값을 탭으로 구분하여 문자를 생성한다
var sb = new System.Text.StringBuilder();
sb.AppendLine($"[Sts] : {Sts}");
sb.AppendLine($"[Speed] : {Speed}");
sb.AppendLine($"[Direction] : {Direction}");
sb.AppendLine($"[guidesensor] : {guidesensor}");
sb.AppendLine($"[TagNo] : {TagNo}");
sb.AppendLine($"[CallNo] : {CallNo}");
sb.AppendLine($"[CCANo] : {CCANo}");
return sb.ToString();
}
}
}
}

View File

@@ -0,0 +1,99 @@
using System;
namespace arDev
{
public partial class Narumi
{
public class ErrorFlag
{
private COMM.Flag _value { get; set; } = new COMM.Flag(16);
public void SetValue(Int16 value) { this._value.writeValue(value); }
public UInt16 Value
{
get
{
return (UInt16)_value.Value;
}
}
public enum eflag
{
Emergency = 0,
Overcurrent,
Charger_run_error,
Charger_pos_error,
line_out_error = 4,
/// <summary>
/// 기동시 자석 감지 에러
/// </summary>
runerror_by_no_magent_line,
/// <summary>
/// 호출제어기 통신 오류
/// </summary>
controller_comm_error = 11,
/// <summary>
/// 도착경보기 통신 오류
/// </summary>
arrive_ctl_comm_error,
/// <summary>
/// 자동문제어기 통신 오류
/// </summary>
door_ctl_comm_error,
/// <summary>
/// 자동충전기 통신 오류
/// </summary>
charger_comm_error,
/// <summary>
/// 교차로 제어기 통신 오류
/// </summary>
cross_ctrl_comm_error,
}
public bool GetValue(eflag idx)
{
return _value.Get((int)idx);
}
public bool GetChanged(eflag idx)
{
return _value.GetChanged((int)idx);
}
public bool Emergency { get { return GetValue(eflag.Emergency); } }
public bool Overcurrent { get { return GetValue(eflag.Overcurrent); } }
public bool Charger_run_error { get { return GetValue(eflag.Charger_run_error); } }
public bool Charger_pos_error { get { return GetValue(eflag.Charger_pos_error); } }
public bool line_out_error { get { return GetValue(eflag.line_out_error); } }
public bool runerror_by_no_magent_line { get { return GetValue(eflag.runerror_by_no_magent_line); } }
public bool controller_comm_error { get { return GetValue(eflag.controller_comm_error); } }
public bool arrive_ctl_comm_error { get { return GetValue(eflag.arrive_ctl_comm_error); } }
public bool door_ctl_comm_error { get { return GetValue(eflag.door_ctl_comm_error); } }
public bool charger_comm_error { get { return GetValue(eflag.charger_comm_error); } }
public bool cross_ctrl_comm_error { get { return GetValue(eflag.cross_ctrl_comm_error); } }
public override string ToString()
{
//모든사태값을 탭으로 구분하여 문자를 생성한다
var sb = new System.Text.StringBuilder();
for (int i = 0; i < 16; i++)
{
var def = Enum.IsDefined(typeof(eflag), i);
if (def)
{
var flag = (eflag)i;
var value = _value.Get(i);
sb.AppendLine($"[{i:00}][{flag}] : {value}");
}
}
return sb.ToString();
}
}
}
}

View File

@@ -0,0 +1,72 @@
using System;
namespace arDev
{
public partial class Narumi
{
public class Signal
{
private COMM.Flag _value { get; set; } = new COMM.Flag(16);
public void SetValue(Int16 value) { this._value.writeValue(value); }
public UInt16 Value
{
get
{
return (UInt16)_value.Value;
}
}
public enum eflag
{
front_gate_out = 0,
rear_sensor_out,
mark_sensor_1,
mark_sensor_2,
front_left_sensor,
front_right_sensor,
front_center_sensor,
charger_align_sensor,
}
public bool GetValue(eflag idx)
{
return _value.Get((int)idx);
}
public bool GetChanged(eflag idx)
{
return _value.GetChanged((int)idx);
}
public Boolean front_gate_out { get { return GetValue(eflag.front_gate_out); } }
public Boolean rear_sensor_out { get { return GetValue(eflag.rear_sensor_out); } }
public Boolean mark_sensor_1 { get { return GetValue(eflag.mark_sensor_1); } }
public Boolean mark_sensor_2 { get { return GetValue(eflag.mark_sensor_2); } }
public Boolean mark_sensor { get { return mark_sensor_1 || mark_sensor_2; } }
public Boolean front_left_sensor { get { return GetValue(eflag.front_left_sensor); } }
public Boolean front_right_sensor { get { return GetValue(eflag.front_right_sensor); } }
public Boolean front_center_sensor { get { return GetValue(eflag.front_center_sensor); } }
public Boolean charger_align_sensor { get { return GetValue(eflag.charger_align_sensor); } }
public override string ToString()
{
//모든사태값을 탭으로 구분하여 문자를 생성한다
var sb = new System.Text.StringBuilder();
for (int i = 0; i < 16; i++)
{
var def = Enum.IsDefined(typeof(eflag), i);
if(def)
{
var flag = (eflag)i;
var value = _value.Get(i);
sb.AppendLine($"[{i:00}][{flag}] : {value}");
}
}
return sb.ToString();
}
}
}
}

View File

@@ -0,0 +1,77 @@
using System;
namespace arDev
{
public partial class Narumi
{
public class SystemFlag0
{
private COMM.Flag _value { get; set; } = new COMM.Flag(16);
public void SetValue(Int16 value) { this._value.writeValue(value); }
public UInt16 Value
{
get
{
return (UInt16)_value.Value;
}
}
public enum eflag
{
Memory_RW_State = 5,
EXT_IO_Conn_State,
RFID_Conn_State,
M5E_Module_Run_State = 8,
Front_Ultrasonic_Conn_State,
Front_Untrasonic_Sensor_State,
Side_Ultrasonic_Conn_State,
Side_Ultrasonic_Sensor_State = 12,
Front_Guide_Sensor_State,
Rear_Guide_Sensor_State,
Battery_Level_Check
}
public bool GetValue(eflag idx)
{
return _value.Get((int)idx);
}
public bool GetChanged(eflag idx)
{
return _value.GetChanged((int)idx);
}
public bool Memory_RW_State { get { return GetValue(eflag.Memory_RW_State); } }
public bool EXT_IO_Conn_State { get { return GetValue(eflag.EXT_IO_Conn_State); } }
public bool RFID_Conn_State { get { return GetValue(eflag.RFID_Conn_State); } }
public bool M5E_Module_Run_State { get { return GetValue(eflag.M5E_Module_Run_State); } }
public bool Front_Ultrasonic_Conn_State { get { return GetValue(eflag.Front_Ultrasonic_Conn_State); } }
public bool Front_Untrasonic_Sensor_State { get { return GetValue(eflag.Front_Untrasonic_Sensor_State); } }
public bool Side_Ultrasonic_Conn_State { get { return GetValue(eflag.Side_Ultrasonic_Conn_State); } }
public bool Side_Ultrasonic_Sensor_State { get { return GetValue(eflag.Side_Ultrasonic_Sensor_State); } }
public bool Front_Guide_Sensor_State { get { return GetValue(eflag.Front_Guide_Sensor_State); } }
public bool Rear_Guide_Sensor_State { get { return GetValue(eflag.Rear_Guide_Sensor_State); } }
public bool Battery_Level_Check { get { return GetValue(eflag.Battery_Level_Check); } }
public override string ToString()
{
//모든사태값을 탭으로 구분하여 문자를 생성한다
var sb = new System.Text.StringBuilder();
for(int i = 0; i < 16; i++)
{
var def = Enum.IsDefined(typeof(eflag), i);
if (def)
{
var flag = (eflag)i;
var value = _value.Get(i);
sb.AppendLine($"[{i:00}][{flag}] : {value}");
}
}
return sb.ToString();
}
}
}
}

View File

@@ -0,0 +1,97 @@
using System;
namespace arDev
{
public partial class Narumi
{
public class SystemFlag1
{
private COMM.Flag _value { get; set; } = new COMM.Flag(16);
public void SetValue(Int16 value) { this._value.writeValue(value); }
public UInt16 Value
{
get
{
return (UInt16)_value.Value;
}
}
public enum eflag
{
Side_Detect_Ignore = 3,
Melody_check,
Mark2_check,
Mark1_check,
gateout_check,
Battery_charging = 8,
re_Start,
/// <summary>
/// 전방 감지 무시
/// </summary>
front_detect_ignore,
/// <summary>
/// 전방장애물감지상태
/// </summary>
front_detect_check,
/// <summary>
/// 전방감지 후 정지 상태
/// </summary>
stop_by_front_detect = 12,
/// <summary>
/// 교차로 진입 후 정지 상태
/// </summary>
stop_by_cross_in,
agv_stop,
agv_run
}
public bool GetValue(eflag idx)
{
return _value.Get((int)idx);
}
public bool GetChanged(eflag idx)
{
return _value.GetChanged((int)idx);
}
public bool Side_Detect_Ignore { get { return GetValue(eflag.Side_Detect_Ignore); } }
public bool Melody_check { get { return GetValue(eflag.Melody_check); } }
public bool Mark2_check { get { return GetValue(eflag.Mark2_check); } }
public bool Mark1_check { get { return GetValue(eflag.Mark1_check); } }
public bool gateout_check { get { return GetValue(eflag.gateout_check); } }
public bool Battery_charging { get { return GetValue(eflag.Battery_charging); } }
public bool re_Start { get { return GetValue(eflag.re_Start); } }
public bool front_detect_ignore { get { return GetValue(eflag.front_detect_ignore); } }
public bool front_detect_check { get { return GetValue(eflag.front_detect_check); } }
public bool stop_by_front_detect { get { return GetValue(eflag.stop_by_front_detect); } }
public bool stop_by_cross_in { get { return GetValue(eflag.stop_by_cross_in); } }
public bool agv_stop { get { return GetValue(eflag.agv_stop); } }
public bool agv_run { get { return GetValue(eflag.agv_run); } }
public bool agv_run_manual { get; set; }
public override string ToString()
{
//모든사태값을 탭으로 구분하여 문자를 생성한다
var sb = new System.Text.StringBuilder();
for (int i = 0; i < 16; i++)
{
var def = Enum.IsDefined(typeof(eflag), i);
if (def)
{
var flag = (eflag)i;
var value = _value.Get(i);
sb.AppendLine($"[{i:00}][{flag}] : {value}");
}
}
return sb.ToString();
}
}
}
}

View File

@@ -0,0 +1,37 @@

namespace AGVControl
{
partial class BatteryLevelGauge
{
/// <summary>
/// 필수 디자이너 변수입니다.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 사용 중인 모든 리소스를 정리합니다.
/// </summary>
/// <param name="disposing">관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region
/// <summary>
/// 디자이너 지원에 필요한 메서드입니다.
/// 이 메서드의 내용을 코드 편집기로 수정하지 마세요.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
}
}

View File

@@ -0,0 +1,93 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace AGVControl
{
public partial class BatteryLevelGauge : Control
{
float _vlevel = 50;
public float VLevel { get { return _vlevel; } set { _vlevel = value; } }
public float Volt { get; set; } = 0;
public String sign { get; set; } = "%";
public float CurA { get; set; } = 0;
public float MaxA { get; set; } = 0;
bool isopen = false;
public Boolean IsOpen { get { return isopen; } set { isopen = value; this.Invalidate(); } }
public Color BorderColor { get; set; } = Color.DimGray;
public BatteryLevelGauge()
{
InitializeComponent();
// Set Optimized Double Buffer to reduce flickering
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
// Redraw when resized
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.Resize += arLabel_Resize;
}
protected override void OnPaint(PaintEventArgs pe)
{
pe.Graphics.InterpolationMode = InterpolationMode.High;
pe.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
pe.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
//base.OnPaint(pe);
pe.Graphics.FillRectangle(new SolidBrush(BackColor), DisplayRectangle);
var r = new RectangleF(this.DisplayRectangle.Left + Padding.Left,
this.DisplayRectangle.Top + Padding.Top,
this.DisplayRectangle.Width - Padding.Left - Padding.Right,
this.DisplayRectangle.Height - Padding.Top - Padding.Bottom);
pe.Graphics.FillRectangle(new SolidBrush(this.BackColor), r);
var w = r.Width * (this.VLevel / 100f);
var lr = new RectangleF(r.Left, r.Top, w, r.Height);
Color bColor = Color.Red;
if (VLevel > 80) bColor = Color.YellowGreen;
else if (VLevel > 60) bColor = Color.Yellow;
else if (VLevel > 40) bColor = Color.Orange;
else if (VLevel > 20) bColor = Color.Tomato;
else bColor = Color.Red;
pe.Graphics.FillRectangle(new SolidBrush(bColor), lr);
Color textcolor = this.ForeColor;
if (IsOpen == false) textcolor = Color.Black;
var smg = IsOpen ? $"{ this.VLevel:N0}{ this.sign}" : "연결안됨";
pe.Graphics.DrawString(smg, this.Font, new SolidBrush(textcolor), r,
new StringFormat
{
Alignment = StringAlignment.Center,
LineAlignment = StringAlignment.Center
});
pe.Graphics.DrawRectangle(Pens.Black, r.Left, r.Top, r.Width, r.Height);
}
void arLabel_Resize(object sender, EventArgs e)
{
Invalidate();
}
}
}

View File

@@ -0,0 +1,37 @@

namespace Narumi.UC
{
partial class GuideSensor
{
/// <summary>
/// 필수 디자이너 변수입니다.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 사용 중인 모든 리소스를 정리합니다.
/// </summary>
/// <param name="disposing">관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region
/// <summary>
/// 디자이너 지원에 필요한 메서드입니다.
/// 이 메서드의 내용을 코드 편집기로 수정하지 마세요.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
}
}

View File

@@ -0,0 +1,106 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Narumi.UC
{
public partial class GuideSensor : Control
{
public int SensorValue { get; set; } = 0;
public bool LMark { get; set; } = false;
public bool RMark { get; set; } = false;
public GuideSensor()
{
InitializeComponent();
// Set Optimized Double Buffer to reduce flickering
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
// Redraw when resized
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.Resize += arLabel_Resize;
}
void arLabel_Resize(object sender, EventArgs e)
{
Invalidate();
}
protected override void OnPaint(PaintEventArgs pe)
{
var boxcount = 11;
var r = new RectangleF(this.DisplayRectangle.Left + Padding.Left,
this.DisplayRectangle.Top + Padding.Top,
this.DisplayRectangle.Width - Padding.Left - Padding.Right,
this.DisplayRectangle.Height - Padding.Top - Padding.Bottom);
var term = 3;
var w = ((r.Width -1) - (term * (boxcount - 1))) / boxcount;
var h = r.Height -1;
pe.Graphics.FillRectangle(new SolidBrush(this.BackColor), this.DisplayRectangle);
//pe.Graphics.DrawRectangle(Pens.Red, r.Left, r.Top, r.Width, r.Height);
for (int i = 0; i < boxcount; i++)
{
var x = r.Left + i * term + i * w;
var y = r.Top;
var r2 = new RectangleF(x, y, w, h);
if (this.Enabled == false)
{
pe.Graphics.FillRectangle(Brushes.LightGray, r2);
}
else
{
if (i == 0)
{
if (LMark)
pe.Graphics.FillRectangle(Brushes.SkyBlue, r2);
else
pe.Graphics.FillRectangle(Brushes.LightGray, r2);
}
else if (i == 9)
{
if (RMark)
pe.Graphics.FillRectangle(Brushes.SkyBlue, r2);
else
pe.Graphics.FillRectangle(Brushes.LightGray, r2);
}
else
{
if (SensorValue == i)
pe.Graphics.FillRectangle(Brushes.Tomato, r2);
else
pe.Graphics.FillRectangle(Brushes.LightGray, r2);
}
pe.Graphics.DrawRectangle(Pens.DimGray, r2.Left,r2.Top,r2.Width,r2.Height);
if (i == 0 || i == 10)
{
pe.Graphics.DrawString("M/K", this.Font,
new SolidBrush(this.ForeColor), r2,
new StringFormat
{
Alignment = StringAlignment.Center,
LineAlignment = StringAlignment.Center
});
}
}
}
}
}
}

View File

@@ -0,0 +1,37 @@

namespace AGVControl
{
partial class MyRadioButton
{
/// <summary>
/// 필수 디자이너 변수입니다.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 사용 중인 모든 리소스를 정리합니다.
/// </summary>
/// <param name="disposing">관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region
/// <summary>
/// 디자이너 지원에 필요한 메서드입니다.
/// 이 메서드의 내용을 코드 편집기로 수정하지 마세요.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
}
}

View File

@@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace AGVControl
{
public partial class MyRadioButton : RadioButton
{
public int CheckWidth { get; set; } = 30;
public Color CheckOnColor { get; set; } = Color.OrangeRed;
public Color CheckOffColor { get; set; } = Color.DimGray;
public Color Bordercolor { get; set; } = Color.DimGray;
public int BorderSize { get; set; } = 2;
public int BorderRadius { get; set; } = 7;
public MyRadioButton()
{
InitializeComponent();
// Set Optimized Double Buffer to reduce flickering
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
// Redraw when resized
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.Resize += arLabel_Resize;
}
protected override void OnPaint(PaintEventArgs pe)
{
pe.Graphics.InterpolationMode = InterpolationMode.High;
pe.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
pe.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
pe.Graphics.Clear(this.BackColor);
var XPosition = this.DisplayRectangle.Left;
var YPosition = this.DisplayRectangle.Top;
using (GraphicsPath Path = new GraphicsPath())
{
Path.AddLine(XPosition + BorderRadius, YPosition, XPosition + Width - (BorderRadius * 2), YPosition);
Path.AddArc(XPosition + Width - (BorderRadius * 2), YPosition, BorderRadius * 2, BorderRadius * 2, 270, 90);
Path.AddLine(XPosition + Width, YPosition + BorderRadius, XPosition + Width, YPosition + Height - (BorderRadius * 2));
Path.AddArc(XPosition + Width - (BorderRadius * 2), YPosition + Height - (BorderRadius * 2), BorderRadius * 2, BorderRadius * 2, 0, 90);
Path.AddLine(XPosition + Width - (BorderRadius * 2), YPosition + Height, XPosition + BorderRadius, YPosition + Height);
Path.AddArc(XPosition, YPosition + Height - (BorderRadius * 2), BorderRadius * 2, BorderRadius * 2, 90, 90);
Path.AddLine(XPosition, YPosition + Height - (BorderRadius * 2), XPosition, YPosition + BorderRadius);
Path.AddArc(XPosition, YPosition, BorderRadius * 2, BorderRadius * 2, 180, 90);
Path.CloseFigure();
var r1 = new Rectangle(
DisplayRectangle.Left, DisplayRectangle.Top,
CheckWidth,
DisplayRectangle.Height - 1);
var r2 = new Rectangle(r1.Right + 3, r1.Top, DisplayRectangle.Width - r1.Width - 3 - Padding.Right, r1.Height);
var CC = Checked ? CheckOnColor : CheckOffColor;
pe.Graphics.FillRectangle(new SolidBrush(CC), r1);
StringFormat sf = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center };
if (this.TextAlign == ContentAlignment.MiddleLeft) sf.Alignment = StringAlignment.Near;
else if (this.TextAlign == ContentAlignment.MiddleRight) sf.Alignment = StringAlignment.Far;
pe.Graphics.DrawString(this.Text, this.Font, new SolidBrush(ForeColor), r2, sf);
//pe.Graphics.DrawRectangle(new Pen(this.Bordercolor, this.BorderSize), DisplayRectangle);
this.Region = new System.Drawing.Region(Path);
pe.Graphics.DrawPath(new Pen(this.Bordercolor, this.BorderSize), Path);
}
}
void arLabel_Resize(object sender, EventArgs e)
{
Invalidate();
}
}
}

View File

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 어셈블리에 대한 일반 정보는 다음 특성 집합을 통해
// 제어됩니다. 어셈블리와 관련된 정보를 수정하려면
// 이러한 특성 값을 변경하세요.
[assembly: AssemblyTitle("AGVControl")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AGVControl")]
[assembly: AssemblyCopyright("Copyright © 2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에
// 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면
// 해당 형식에 대해 ComVisible 특성을 true로 설정하세요.
[assembly: ComVisible(false)]
// 이 프로젝트가 COM에 노출되는 경우 다음 GUID는 typelib의 ID를 나타냅니다.
[assembly: Guid("8cb883c0-99c3-4dd4-b017-f9b92010a806")]
// 어셈블리의 버전 정보는 다음 네 가지 값으로 구성됩니다.
//
// 주 버전
// 부 버전
// 빌드 번호
// 수정 버전
//
// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호를
// 기본값으로 할 수 있습니다.
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,37 @@

namespace AGVControl
{
partial class RoundButton
{
/// <summary>
/// 필수 디자이너 변수입니다.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 사용 중인 모든 리소스를 정리합니다.
/// </summary>
/// <param name="disposing">관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region
/// <summary>
/// 디자이너 지원에 필요한 메서드입니다.
/// 이 메서드의 내용을 코드 편집기로 수정하지 마세요.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
}
}

View File

@@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace AGVControl
{
public partial class RoundButton : Button
{
public int CornerRadius { get; set; } = 7;
public RoundButton()
{
InitializeComponent();
// Set Optimized Double Buffer to reduce flickering
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
// Redraw when resized
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.Resize += arLabel_Resize;
}
protected override void OnPaint(PaintEventArgs pevent)
{
pevent.Graphics.InterpolationMode = InterpolationMode.High;
pevent.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
pevent.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
var XPosition = this.DisplayRectangle.Left;
var YPosition = this.DisplayRectangle.Top;
using (GraphicsPath Path = new GraphicsPath())
{
Path.AddLine(XPosition + CornerRadius, YPosition, XPosition + Width - (CornerRadius * 2), YPosition);
Path.AddArc(XPosition + Width - (CornerRadius * 2), YPosition, CornerRadius * 2, CornerRadius * 2, 270, 90);
Path.AddLine(XPosition + Width, YPosition + CornerRadius, XPosition + Width, YPosition + Height - (CornerRadius * 2));
Path.AddArc(XPosition + Width - (CornerRadius * 2), YPosition + Height - (CornerRadius * 2), CornerRadius * 2, CornerRadius * 2, 0, 90);
Path.AddLine(XPosition + Width - (CornerRadius * 2), YPosition + Height, XPosition + CornerRadius, YPosition + Height);
Path.AddArc(XPosition, YPosition + Height - (CornerRadius * 2), CornerRadius * 2, CornerRadius * 2, 90, 90);
Path.AddLine(XPosition, YPosition + Height - (CornerRadius * 2), XPosition, YPosition + CornerRadius);
Path.AddArc(XPosition, YPosition, CornerRadius * 2, CornerRadius * 2, 180, 90);
Path.CloseFigure();
this.Region = new System.Drawing.Region(Path);
}
base.OnPaint(pevent);
}
void arLabel_Resize(object sender, EventArgs e)
{
Invalidate();
}
}
}

View File

@@ -0,0 +1,36 @@
namespace AGVControl
{
partial class ValueSelect
{
/// <summary>
/// 필수 디자이너 변수입니다.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 사용 중인 모든 리소스를 정리합니다.
/// </summary>
/// <param name="disposing">관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region
/// <summary>
/// 디자이너 지원에 필요한 메서드입니다.
/// 이 메서드의 내용을 코드 편집기로 수정하지 마세요.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
}
}

View File

@@ -0,0 +1,262 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Windows.Forms;
namespace AGVControl
{
public partial class ValueSelect : Control
{
public ValueSelect()
{
InitializeComponent();
// Set Optimized Double Buffer to reduce flickering
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
// Redraw when resized
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.Resize += arLabel_Resize;
this.MouseClick += ValueSelect_MouseClick;
this.MouseEnter += (s1, e1) => { this.Cursor = Cursors.Hand; };
this.MouseLeave += (s1, e1) => { this.Cursor = Cursors.Default; };
}
private void ValueSelect_MouseClick(object sender, MouseEventArgs e)
{
//마우스클릭
if (rectLButton.IsEmpty == false && rectLButton.Contains(e.Location))
{
if (SideButtonClickValue != 0.0)
{
var newvalue = this.Value - SideButtonClickValue;
if (newvalue < MinValue) newvalue = MinValue;
this.Value = newvalue;
}
if (ButtonClick != null) ButtonClick(this, new ButtonClickEventArgs(MouseButtons.Left));
}
if (rectRButton.IsEmpty == false && rectRButton.Contains(e.Location))
{
if (SideButtonClickValue != 0.0)
{
var newvalue = this.Value + SideButtonClickValue;
if (newvalue > MaxValue) newvalue = MaxValue;
this.Value = newvalue;
}
if (ButtonClick != null) ButtonClick(this, new ButtonClickEventArgs(MouseButtons.Right));
}
if (rectCButton.IsEmpty == false && rectCButton.Contains(e.Location))
if (ButtonClick != null) ButtonClick(this, new ButtonClickEventArgs(MouseButtons.Middle));
}
private Rectangle rectLButton;
private Rectangle rectRButton;
private Rectangle rectCButton;
private Boolean bMakeRect = true;
private double _minvalue = 0.0;
private double _maxvalue = 9999999999.0;
public double MinValue { get { return _minvalue; } set { _minvalue = value; Invalidate(); } }
public double MaxValue { get { return _maxvalue; } set { _maxvalue = value; Invalidate(); } }
private UInt16 _decimalposition = 0;
private string _buttonwdith = string.Empty;
private double _value = 0;
private Color _border = Color.Lime;
private double buttongabp;
public double SideButtonClickValue { get { return buttongabp; } set { buttongabp = value; Invalidate(); } }
private Color _backbutton = Color.White;
private Color _sidebutto = Color.Black;
public Color BackColorButton { get { return _backbutton; } set { _backbutton = value; Invalidate(); } }
public Color ForeColorButton { get { return _sidebutto; } set { _sidebutto = value; Invalidate(); } }
public Color ColorBorder { get { return _border; } set { _border = value; Invalidate(); } }
public override string Text
{
get => Value.ToString();
set
{
if (double.TryParse(value, out double dblval) == true)
this.Value = dblval;
}
}
public double Value
{
get { return _value; }
set
{
if (_value != value)
{
//이 값이 범위를 초과했는지 확인
if (value < MinValue)
{
_value = MinValue;
//throw new Exception(string.Format("입력값이 컨트롤의 최소값보다 작습니다(입력:{0},최소값:{1})",value,MinValue));
}
else if (value > MaxValue)
{
_value = MaxValue;
//throw new Exception(string.Format("입력값이 컨트롤의 최대값보다 작습니다(입력:{0},최대값:{1})", value, MaxValue));
}
else
{
_value = value;
}
Invalidate();
if (ValueChanged != null) ValueChanged(this, new EventArgs());
}
}
}
public UInt16 DecimalPosition { get { return _decimalposition; } set { _decimalposition = value; Invalidate(); } }
public string ButtonWidth { get { return _buttonwdith; } set { _buttonwdith = value; Invalidate(); } }
private string _nulldisplay = string.Empty;
public string NullDisplay { get { return _nulldisplay; } set { _nulldisplay = value; Invalidate(); } }
private Font _sidefont;
public Font FontSideButton { get { if (_sidefont == null) return this.Font; else return _sidefont; } set { _sidefont = value; Invalidate(); } }
void arLabel_Resize(object sender, EventArgs e)
{
this.bMakeRect = true;
Invalidate();
}
public class ButtonClickEventArgs : EventArgs
{
public MouseButtons Button;
public ButtonClickEventArgs(MouseButtons button)
{
this.Button = button;
// Console.WriteLine("button clickc : " +button.ToString());
}
}
public event EventHandler<ButtonClickEventArgs> ButtonClick;
public event EventHandler ValueChanged;
protected override void OnPaint(PaintEventArgs pe)
{
//base.OnPaint(pe);
if (bMakeRect) MakeRect();
StringFormat sf = new StringFormat();
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Center;
sf.Trimming = StringTrimming.None;
sf.FormatFlags = StringFormatFlags.NoWrap;
//좌측버튼표시
if (rectLButton.IsEmpty == false)
{
pe.Graphics.FillRectangle(new SolidBrush(BackColorButton), rectLButton);
pe.Graphics.DrawString("<<", this.FontSideButton, new SolidBrush(this.ForeColorButton), rectLButton, sf);
}
if (rectRButton.IsEmpty == false)
{
pe.Graphics.FillRectangle(new SolidBrush(BackColorButton), rectRButton);
pe.Graphics.DrawString(">>", this.FontSideButton, new SolidBrush(this.ForeColorButton), rectRButton, sf);
}
//값표시
string valuestr;
if (Value == 0.0 && string.IsNullOrEmpty(NullDisplay) == false)
valuestr = NullDisplay;
else
valuestr = Value.ToString("N" + DecimalPosition.ToString());
pe.Graphics.FillRectangle(new SolidBrush(BackColor), rectCButton);
pe.Graphics.DrawString(valuestr, this.Font, new SolidBrush(this.ForeColor), rectCButton, sf);
sf.Dispose();
//테두리표시
if (rectLButton.IsEmpty == false)
pe.Graphics.DrawRectangle(new Pen(ColorBorder), rectLButton);
if (rectRButton.IsEmpty == false)
pe.Graphics.DrawRectangle(new Pen(ColorBorder), rectRButton);
pe.Graphics.DrawRectangle(new Pen(ColorBorder), rectCButton);
}
void MakeRect()
{
int bWidth;
if (string.IsNullOrEmpty(ButtonWidth) == false)
{
if (ButtonWidth.EndsWith("%"))
{
if (int.TryParse(ButtonWidth.Substring(0, ButtonWidth.Length - 1), out bWidth) == false)
bWidth = 0; //숫자로 바꾸는거 실패
else bWidth = (int)(this.DisplayRectangle.Width * (bWidth / 100.0));
}
else
{
if (int.TryParse(ButtonWidth, out bWidth) == false)
bWidth = 0;
}
}
else bWidth = 0;
if (bWidth > 0)
{
int buttongap = 1;
//각버튼간 2px 간격을 띄운다.
bWidth = bWidth - buttongap * 2;
rectLButton = new Rectangle(
DisplayRectangle.Left,
DisplayRectangle.Top,
bWidth,
DisplayRectangle.Height - 1);
rectCButton = new Rectangle(
rectLButton.Right + buttongap,
DisplayRectangle.Top,
DisplayRectangle.Width - rectLButton.Width * 2 - buttongap * 2,
DisplayRectangle.Height - 1);
rectRButton = new Rectangle(
rectCButton.Right + buttongap,
DisplayRectangle.Top,
bWidth - 1,
DisplayRectangle.Height - 1);
}
else
{
rectLButton = Rectangle.Empty;
rectRButton = Rectangle.Empty;
rectCButton = new Rectangle(DisplayRectangle.Left,
DisplayRectangle.Top,
DisplayRectangle.Width - 1,
DisplayRectangle.Height - 1);
}
bMakeRect = true;
}
}
}

View File

@@ -0,0 +1,81 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{8CB883C0-99C3-4DD4-B017-F9B92010A806}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>AGVControl</RootNamespace>
<AssemblyName>AGVControl</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="BatteryLevelGauge.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="BatteryLevelGauge.Designer.cs">
<DependentUpon>BatteryLevelGauge.cs</DependentUpon>
</Compile>
<Compile Include="GuideSensor.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="GuideSensor.Designer.cs">
<DependentUpon>GuideSensor.cs</DependentUpon>
</Compile>
<Compile Include="MyRadioButton.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="MyRadioButton.Designer.cs">
<DependentUpon>MyRadioButton.cs</DependentUpon>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RoundButton.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="RoundButton.Designer.cs">
<DependentUpon>RoundButton.cs</DependentUpon>
</Compile>
<Compile Include="ValueSelect.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="ValueSelect.Designer.cs">
<DependentUpon>ValueSelect.cs</DependentUpon>
</Compile>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{14E8C9A5-013E-49BA-B435-EFEFC77DD623}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>VarData</RootNamespace>
<AssemblyName>VarData</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Flag.cs" />
<Compile Include="RS232.cs" />
<Compile Include="Var.cs" />
<Compile Include="Enum.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -0,0 +1,196 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace COMM
{
public enum eVarInt32
{
PickOnCount = 0,
PickOfCount,
LPickOnCount,
SumQty,
ChargeWaitSec,
}
public enum eVarUInt32
{
Spare=0,
}
public enum eVarDBL
{
LeftJogSpeed,
RightJogSpeed,
CurrentLeftJogSpeed,
CurrentRightJogSpeed,
SpeedOffsetCW,
SpeedOffsetCCW,
MaxSpeedCW,
MaxSpeedCCW,
SQLConnection,
}
public enum eVarByte
{
None = 0,
/// <summary>
/// 충전명련전송횟수
/// </summary>
CHARGE_CMDCNT,
ButtonJog,
DataIndex ,
}
public enum eVarBool
{
//comm area start(0~31)
None = 0,
DebugMode,
SQLCONN,
//plc area start (32~63)
FLAG_STOPZ = 32,
FLAG_SETUP,
FLAG_SYNC,
FLAG_WAIT,
/// <summary>
/// 상태머신이 동작중인가
/// 장비동작은 AGV_RUN 플래그를 확인 하세요.
/// </summary>
FLAG_AUTORUN,
FLAG_MANUALRUN,
FLAG_LIMITHIGH,
FLAG_LIMITLOW,
FLAG_POWERLOSS,
/// <summary>
/// AGV 진행방향(UP = backward, DOWN = forward)
/// </summary>
AGVDIR_UP,
/// <summary>
/// 마크센서가 감지되면 활성화됨
/// (알림용으로도 쓰니 삭제 안됨)
/// </summary>
MARK_SENSOR,
MARK_SENSOROFF,
FLAG_LEFT_RUN,
FLAG_RIGHT_RUN,
FLAG_RUN_CMD,
FLAG_GO_CHAGER,
FLAG_NEXTSTOP_ALIGN,
NEXTSTOP_MARK,
/// <summary>
/// mark 1 혹은 2 의 값이 들어오면 설정됨
/// </summary>
//SENSOR_MARK,
CHG_POSERR,
FLAG_CHARGEONA,
FLAG_CHARGEONM,
OVERLOAD,
OVERLOADL,
OVERLOADR,
BATTERY_LOW,
BATTERY_HIGH,
MINSPACE,
CHARGE_CMDCNT,
CHARGE_READY,
CHARGE_WAIT,
AGV_ERROR,
WAIT_COVER_DOWN,
WAIT_COVER_UP,
EMERGENCY,
ITEMON,
/// <summary>
/// 충전시작명령을 전송했다
/// </summary>
WAIT_CHARGEACK,
//agv area start ( 64 ~ 95)
//area start (96~127)
}
public enum eVarString
{
MCStatus,
DataIndex,
StatusMessage,
JOBType,
JOBCustCode,
SWVersion,
ChargeCheckMsg,
}
public enum eVarTime
{
LastConnTry_PLC,
LastConn_PLC,
LastRecv_PLC,
LastConnTry_XBE,
LastConn_XBE,
LastRecv_XBE,
LastConnTry_BAT,
LastConn_BAT,
LastRecv_BAT,
LastSend_CMD,
LastSend_BAT,
LastConnTry_AGV,
LastConn_AGV,
LastRecv_AGV,
/// <summary>
/// 상태머신이 IDLE 전환시 설정
/// </summary>
IdleStart,
/// <summary>
/// 충전시도시 설정
/// </summary>
ChargeTry,
/// <summary>
/// 충전시작(확인)시 설정
/// </summary>
ChargeStart,
/// <summary>
/// 충전종료시점
/// </summary>
ChargeEnd,
/// <summary>
/// 장비가동중 READY상태 전환시 설정
/// </summary>
ReadyStart,
MarkSensorOff,
/// <summary>
/// 상태머신이 RUN되는 경우에 설정
/// 단 세부스텝이 READY 인 경우는 제외
/// </summary>
RunStart,
SendChargeOff,
ChargeSearch,
BatWarnTime,
IdleStopTime,
StatusReporttime,
}
}

View File

@@ -0,0 +1,108 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace COMM
{
public class Flag
{
public Boolean IsInit; //H/W설정이 안된경우에만 FALSE로 한다
public string errorMessage;
public int PortCount;
private UInt64 _value;
private UInt64 _changed;
public string[] Name;
public UInt64 Value { get { return _value; } }
public event EventHandler<ValueEventArgs> ValueChanged;
public class ValueEventArgs : EventArgs
{
private int _arridx;
private Boolean _oldvalue;
private Boolean _newvalue;
public int ArrIDX { get { return _arridx; } }
public Boolean OldValue { get { return _oldvalue; } }
public Boolean NewValue { get { return _newvalue; } }
public ValueEventArgs(int arridx, Boolean oldvalue, Boolean newvalue)
{
_arridx = arridx;
_oldvalue = oldvalue;
_newvalue = newvalue;
}
}
public Flag(int pcnt)
{
if (pcnt > 64) throw new Exception("Max count is 64");
PortCount = pcnt;
IsInit = true;
errorMessage = string.Empty;
_value = 0;
_changed = 0;
Name = new string[PortCount];
for (int i = 0; i < Name.Length; i++)
{
Name[i] = string.Empty;
}
}
public void writeValue(Int16 val)
{
var NewValue = (ulong)val;
_changed = this._value ^ NewValue;
this._value = NewValue;
}
//private Boolean readValue(ref UInt64 value, int idx)
//{
// var offset = (UInt64)(1 << idx);
// return ((value & offset) != 0);
//}
public Boolean Get(int idx)
{
var offset = (UInt64)(1 << idx);
return (_value & offset) != 0;
}
/// <summary>
/// 변경여부를 확인 합니다
/// </summary>
/// <param name="idx"></param>
/// <returns></returns>
public Boolean GetChanged(int idx)
{
var offset = (UInt64)(1 << idx);
return (this._changed & offset) != 0;
}
public void Set(int idx, Boolean value)
{
var oldvalue = Get(idx);
if (value)
{
var offset = (UInt64)(1 << idx);
_value = _value | offset;
}
else
{
var offset = (UInt64)(~(1 << idx));
_value = _value & offset;
}
if (oldvalue != value)
{
if (ValueChanged != null)
ValueChanged(this, new ValueEventArgs(idx, oldvalue, value));
}
}
}
}

View File

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 어셈블리에 대한 일반 정보는 다음 특성 집합을 통해
// 제어됩니다. 어셈블리와 관련된 정보를 수정하려면
// 이러한 특성 값을 변경하세요.
[assembly: AssemblyTitle("VarData")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("VarData")]
[assembly: AssemblyCopyright("Copyright © 2022")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에
// 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면
// 해당 형식에 대해 ComVisible 특성을 true로 설정하세요.
[assembly: ComVisible(false)]
// 이 프로젝트가 COM에 노출되는 경우 다음 GUID는 typelib의 ID를 나타냅니다.
[assembly: Guid("14e8c9a5-013e-49ba-b435-efefc77dd623")]
// 어셈블리의 버전 정보는 다음 네 가지 값으로 구성됩니다.
//
// 주 버전
// 부 버전
// 빌드 번호
// 수정 버전
//
// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호를
// 기본값으로 할 수 있습니다.
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,487 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading;
namespace arDev
{
public abstract partial class arRS232 : IDisposable
{
protected System.IO.Ports.SerialPort _device;
protected ManualResetEvent _mre;
protected byte[] LastReceiveBuffer = new byte[] { };
/// <summary>
/// 최종 전송 메세지
/// </summary>
public byte[] lastSendBuffer = new byte[] { };
protected List<byte> tempBuffer = new List<byte>();
protected Boolean findSTX = false;
public string errorMessage { get; set; }
public DateTime LastConnTime { get; set; }
public DateTime LastConnTryTime { get; set; }
public DateTime lastSendTime;
/// <summary>
/// 메세지 수신시 사용하는 내부버퍼
/// </summary>
protected List<byte> _buffer = new List<byte>();
// public byte[] LastRecvData;
public string LastRecvString
{
get
{
if (LastReceiveBuffer == null) return String.Empty;
else return System.Text.Encoding.Default.GetString(LastReceiveBuffer);
}
}
/// <summary>
/// 마지막으로 데이터를 받은 시간
/// </summary>
public DateTime lastRecvTime;
public int WriteError = 0;
public string WriteErrorMessage = string.Empty;
public int WaitTimeout { get; set; } = 1000;
public int MinRecvLength { get; set; } = 1;
/// <summary>
/// 포트이름
/// </summary>
[Description("시리얼 포트 이름")]
[Category("설정"), DisplayName("Port Name")]
public string PortName
{
get
{
if (_device == null) return string.Empty;
else return _device.PortName;
}
set
{
if (this.IsOpen)
{
Message?.Invoke(this, new MessageEventArgs("포트가 열려있어 포트이름을 변경할 수 없습니다", true));
}
else if (String.IsNullOrEmpty(value) == false)
_device.PortName = value;
else
{
Message?.Invoke(this, new MessageEventArgs("No PortName", true));
}
}
}
public int BaudRate
{
get
{
if (_device == null) return 0;
else return _device.BaudRate;
}
set
{
if (this.IsOpen)
{
Message?.Invoke(this, new MessageEventArgs("포트가 열려있어 BaudRate(를) 변경할 수 없습니다", true));
}
else if (value != 0)
_device.BaudRate = value;
else Message?.Invoke(this, new MessageEventArgs("No baud rate", true));
}
}
public arRS232()
{
_device = new System.IO.Ports.SerialPort();
this.BaudRate = 9600;
_device.DataReceived += barcode_DataReceived;
_device.ErrorReceived += this.barcode_ErrorReceived;
_device.WriteTimeout = 5000;
_device.ReadTimeout = 5000;
// _device.DtrEnable = false;
_device.ReadBufferSize = 8192;
_device.WriteBufferSize = 8192;
errorMessage = string.Empty;
lastRecvTime = DateTime.Parse("1982-11-23");
LastConnTime = DateTime.Parse("1982-11-23");
LastConnTryTime = DateTime.Parse("1982-11-23");
lastRecvTime = DateTime.Parse("1982-11-23");
this._mre = new ManualResetEvent(true);
}
~arRS232()
{
Dispose(false);
}
// Flag: Has Dispose already been called?
bool disposed = false;
// Public implementation of Dispose pattern callable by consumers.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// Protected implementation of Dispose pattern.
protected virtual void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing)
{
// Free any other managed objects here.
//
}
_device.DataReceived -= barcode_DataReceived;
_device.ErrorReceived -= this.barcode_ErrorReceived;
// Free any unmanaged objects here.
//
disposed = true;
}
public Boolean Open()
{
try
{
_device.Open();
return IsOpen;
}
catch (Exception ex)
{
errorMessage = ex.Message;
Message.Invoke(this, new MessageEventArgs(ex.Message, true));
return false;
}
}
public string GetHexString(Byte[] input)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
foreach (byte b in input)
sb.Append(" " + b.ToString("X2"));
return sb.ToString();
}
/// <summary>
/// 포트가 열려있는지 확인
/// </summary>
[Description("현재 시리얼포트가 열려있는지 확인합니다")]
[Category("정보"), DisplayName("Port Open")]
public Boolean IsOpen
{
get
{
if (_device == null) return false;
return _device.IsOpen;
}
}
public virtual void Close(Boolean PortClose = true)
{
if (_device != null && _device.IsOpen)
{
_device.DiscardInBuffer();
_device.DiscardOutBuffer();
if (PortClose) _device.Close(); //dispose에서는 포트를 직접 클리어하지 않게 해뒀다.
}
}
protected Boolean RaiseRecvData()
{
return RaiseRecvData(LastReceiveBuffer.ToArray(), false);
}
/// <summary>
/// 수신받은 메세지를 발생 시킵니다
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public virtual Boolean RaiseRecvData(byte[] Data, bool udpatelastbuffer)
{
//181206 - 최종수신 메세지 기록
lastRecvTime = DateTime.Now;
if (udpatelastbuffer && Data != null)
{
if (LastReceiveBuffer == null || LastReceiveBuffer.Length != Data.Length)
{
LastReceiveBuffer = new byte[Data.Length];
Array.Copy(Data, LastReceiveBuffer, Data.Length);
}
}
try
{
Message?.Invoke(this, new MessageEventArgs(Data, true)); //recvmessage
if (ProcessRecvData(Data) == false)
{
//Message?.Invoke(this, new MessageEventArgs(Data, true)); //recvmessage
Message?.Invoke(this, new MessageEventArgs(this.errorMessage, true)); //errormessage
return false;
}
else
{
return true;
}
}
catch (Exception ex)
{
this.errorMessage = ex.Message;
this.Message?.Invoke(this, new MessageEventArgs(ex.Message, true));
return false;
}
}
/// <summary>
/// 수신받은 자료를 처리한다
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public abstract bool ProcessRecvData(byte[] data);
#region "Internal Events"
void barcode_ErrorReceived(object sender, System.IO.Ports.SerialErrorReceivedEventArgs e)
{
Message?.Invoke(this, new MessageEventArgs(e.ToString(), true));
}
byte[] buffer = new byte[] { };
void barcode_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
try
{
int ReadCount = _device.BytesToRead;
buffer = new byte[ReadCount];
_device.Read(buffer, 0, buffer.Length);
System.Text.StringBuilder LogMsg = new StringBuilder();
byte[] remainBuffer;
Repeat:
if (CustomParser(buffer, out remainBuffer))
{
//분석완료이므로 받은 데이터를 버퍼에 기록한다
if (LastReceiveBuffer == null || (LastReceiveBuffer.Length != tempBuffer.Count))
Array.Resize(ref LastReceiveBuffer, tempBuffer.Count);
Array.Copy(tempBuffer.ToArray(), LastReceiveBuffer, tempBuffer.Count);
tempBuffer.Clear();
//수신메세지발생
RaiseRecvData();
if (remainBuffer != null && remainBuffer.Length > 0)
{
//버퍼를 변경해서 다시 전송을 해준다.
Array.Resize(ref buffer, remainBuffer.Length);
Array.Copy(remainBuffer, buffer, remainBuffer.Length);
goto Repeat; //남은 버퍼가 있다면 진행을 해준다.
}
}
}
catch (Exception ex)
{
if (IsOpen)
{
//_device.DiscardInBuffer();
//_device.DiscardOutBuffer();
}
errorMessage = ex.Message;
this.Message?.Invoke(this, new MessageEventArgs(ex.Message, true));
}
}
#endregion
#region "External Events"
/// <summary>
/// 오류 및 기타 일반 메세지
/// </summary>
public event EventHandler<MessageEventArgs> Message;
#endregion
#region "Event Args"
/// <summary>
/// 데이터를 수신할떄 사용함(RAW 포함)
/// </summary>
public class ReceiveDataEventArgs : EventArgs
{
private byte[] _buffer = null;
/// <summary>
/// 바이트배열의 버퍼값
/// </summary>
public byte[] Value { get { return _buffer; } }
/// <summary>
/// 버퍼(바이트배열)의 데이터를 문자로 반환합니다.
/// </summary>
public string StrValue
{
get
{
//return string.Empty;
if (_buffer == null || _buffer.Length < 1) return string.Empty;
else return System.Text.Encoding.Default.GetString(_buffer);
}
}
public ReceiveDataEventArgs(byte[] buffer)
{
_buffer = buffer;
}
}
/// <summary>
/// 메세지를 강제 발생
/// </summary>
/// <param name="mt"></param>
/// <param name="message"></param>
protected virtual void RaiseMessage(MessageType mt, string message)
{
this.Message?.Invoke(this, new MessageEventArgs(mt, message));
}
public enum MessageType
{
Normal,
Error,
Send,
Recv,
}
public class MessageEventArgs : EventArgs
{
public MessageType MsgType { get; set; }
private string _message = string.Empty;
/// <summary>
/// Recv,Send,Normal,Error 모두 지원
/// </summary>
public string Message { get { return _message; } }
private byte[] _data = null;
/// <summary>
/// Recv,Send에서만 값이 존재 합니다
/// </summary>
public byte[] Data { get { return _data; } }
public MessageEventArgs(string Message, bool isError = false)
{
if (isError) MsgType = MessageType.Error;
else MsgType = MessageType.Normal;
_message = Message;
}
public MessageEventArgs(MessageType msgtype, string Message)
{
MsgType = msgtype;
_message = Message;
_data = System.Text.Encoding.Default.GetBytes(Message);
}
public MessageEventArgs(byte[] buffer, bool isRecv = true)
{
if (isRecv) MsgType = MessageType.Recv;
else MsgType = MessageType.Send;
_data = new byte[buffer.Length];
Array.Copy(buffer, _data, Data.Length);
_message = System.Text.Encoding.Default.GetString(_data);
}
}
#endregion
protected abstract bool CustomParser(byte[] buf, out byte[] remainBuffer);
/// <summary>
/// 데이터수신시간이 설정값보다 x 2.5를 초과하면 false 가 반환됨
/// </summary>
public Boolean IsValid
{
get
{
if (IsOpen == false) return false;
if (lastRecvTime.Year == 1982) return false;
var ts = DateTime.Now - lastRecvTime;
if (ts.TotalSeconds > 5) return false;
return true;
}
}
protected bool WriteData(string cmd)
{
return WriteData(System.Text.Encoding.Default.GetBytes(cmd));
}
/// <summary>
/// 포트에 쓰기(barcode_DataReceived 이벤트로 메세지수신)
/// </summary>
protected Boolean WriteData(byte[] data)
{
Boolean bRet = false;
//171205 : 타임아웃시간추가
if (!_mre.WaitOne(WaitTimeout))
{
errorMessage = $"WriteData:MRE:WaitOne:TimeOut {WaitTimeout}ms";
this.Message?.Invoke(this, new MessageEventArgs(errorMessage, true));
return false;
}
_mre.Reset();
//Array.Resize(ref data, data.Length + 2);
try
{
lastSendTime = DateTime.Now;
if (lastSendBuffer == null) lastSendBuffer = new byte[data.Length]; //171113
else Array.Resize(ref lastSendBuffer, data.Length);
Array.Copy(data, lastSendBuffer, data.Length);
for (int i = 0; i < data.Length; i++)
_device.Write(data, i, 1);
//_device.Write(data, 0, data.Length);
//171113
this.Message?.Invoke(this, new MessageEventArgs(data, false));
bRet = true;
WriteError = 0;
WriteErrorMessage = string.Empty;
}
catch (Exception ex)
{
// this.isinit = false;
this.Message?.Invoke(this, new MessageEventArgs(ex.Message, true));
bRet = false;
WriteError += 1; //연속쓰기오류횟수
WriteErrorMessage = ex.Message;
}
finally
{
_mre.Set();
}
return bRet;
}
}
}

View File

@@ -0,0 +1,340 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
namespace COMM
{
public abstract class VarData<T> : INotifyPropertyChanged
{
protected T[] _values;
protected T defaultvalue;
protected string[] _code;
protected string[] _desc;
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
public T this[int idx]
{
get { return Get(idx); }
set { Set(idx, value); }
}
public string StrType
{
get
{
return typeof(T).ToString();
}
}
public VarData(int capa, T defvalue = default(T))
{
_values = new T[capa];
_code = new string[capa];
_desc = new string[capa];
defaultvalue = defvalue;
Clear();
if (typeof(T) == typeof(UInt16)) SupportAdd = true;
else if (typeof(T) == typeof(UInt32)) SupportAdd = true;
else if (typeof(T) == typeof(Int16)) SupportAdd = true;
else if (typeof(T) == typeof(Int32)) SupportAdd = true;
else if (typeof(T) == typeof(Int64)) SupportAdd = true;
else if (typeof(T) == typeof(UInt64)) SupportAdd = true;
else if (typeof(T) == typeof(byte)) SupportAdd = true;
else if (typeof(T) == typeof(double)) SupportAdd = true;
else if (typeof(T) == typeof(Single)) SupportAdd = true;
else if (typeof(T) == typeof(string)) SupportAdd = false;
else if (typeof(T) == typeof(bool)) SupportAdd = false;
else if (typeof(T) == typeof(DateTime)) SupportAdd = false;
else throw new Exception($"Support Data Type : {typeof(T)}");
}
public virtual void Set(int idx, T value)
{
var changed = _values[idx].Equals(value);
_values[idx] = value;
if (changed) OnPropertyChanged($"{idx}|{value}"); //idx값을 알림한다
}
public virtual T Get(int idx)
{
return _values[idx];
}
public virtual void Clear(T value)
{
for (int i = 0; i < _values.Length; i++)
_values[i] = value;
}
public virtual void Clear()
{
Clear(defaultvalue);
}
public void Clear(int idx)
{
_values[idx] = defaultvalue;
}
public Tuple<string, string> GetCodeDesc(int idx)
{
return new Tuple<string, string>(_code[idx], _desc[idx]);
}
public virtual bool SupportAdd { get; private set; }
}
public abstract class VarDataNumber<T> : VarData<T>
{
public VarDataNumber(int capa) : base(capa) { }
public abstract void Add(T value);
public abstract void Add(int idx, T value);
}
public class VarDataI32 : VarDataNumber<Int32>
{
public VarDataI32(int capa) : base(capa) { }
public override void Add(Int32 value)
{
for (int i = 0; i < _values.Length; i++)
_values[i] += value;
}
public override void Add(int idx, Int32 value)
{
_values[idx] += value;
}
public void Add(eVarInt32 idx, Int32 value = 1)
{
Add((int)idx, value);
}
public void Clear(eVarInt32 idx)
{
Clear((int)idx);
}
public Int32 this[eVarInt32 idx]
{
get { return Get((int)idx); }
set { Set((int)idx, value); }
}
}
public class VarDataDBL : VarDataNumber<double>
{
public VarDataDBL(int capa) : base(capa) { }
public override void Add(double value)
{
for (int i = 0; i < _values.Length; i++)
_values[i] += value;
}
public override void Add(int idx, double value)
{
_values[idx] += value;
}
public void Add(eVarDBL idx, double value = 1)
{
Add((int)idx, value);
}
public void Clear(eVarDBL idx)
{
Clear((int)idx);
}
public double this[eVarDBL idx]
{
get { return Get((int)idx); }
set { Set((int)idx, value); }
}
}
public class VarDataUI32 : VarDataNumber<UInt32>
{
public VarDataUI32(int capa) : base(capa) { }
public override void Add(UInt32 value)
{
for (int i = 0; i < _values.Length; i++)
_values[i] += value;
}
public override void Add(int idx, UInt32 value)
{
_values[idx] += value;
}
public void Add(eVarUInt32 idx, UInt32 value = 1)
{
Add((int)idx, value);
}
public void Clear(eVarUInt32 idx)
{
Clear((int)idx);
}
public UInt32 this[eVarUInt32 idx]
{
get { return Get((int)idx); }
set { Set((int)idx, value); }
}
}
public class VarDataByte : VarDataNumber<byte>
{
public VarDataByte(int capa) : base(capa) { }
public override void Add(byte value)
{
for (int i = 0; i < _values.Length; i++)
_values[i] += value;
}
public override void Add(int idx, byte value)
{
_values[idx] += value;
}
public void Add(eVarByte idx, byte value)
{
Add((int)idx, value);
}
public byte this[eVarByte idx]
{
get
{
return Get((int)idx);
}
set
{
Set((int)idx, value);
}
}
}
public class VarDataBool : VarData<bool>
{
public VarDataBool(int capa) : base(capa) { }
public bool this[eVarBool idx]
{
get
{
return Get(idx);
}
set
{
Set(idx, value);
}
}
public bool Get(eVarBool idx)
{
return Get((int)idx);
}
public void Set(eVarBool idx, bool value)
{
Set((int)idx, value);
}
}
public class VarDataStr : VarData<string>
{
public VarDataStr(int capa) : base(capa, string.Empty) { }
public string Get(eVarString idx)
{
return Get((int)idx);
}
public void Set(eVarString idx, string value)
{
Set((int)idx, value);
}
public string this[eVarString idx]
{
get { return Get(idx); }
set { Set(idx, value); }
}
}
public class VarDataDateTime : VarData<DateTime>
{
public VarDataDateTime(int capa) : base(capa, new DateTime(1982, 11, 23)) { }
public DateTime this[eVarTime idx]
{
get
{
return Get((int)idx);
}
set
{
Set(idx, value);
}
}
public TimeSpan RUN(int idx)
{
return DateTime.Now - _values[idx];
}
public TimeSpan RUN(eVarTime idx)
{
return RUN((int)idx);
}
[Browsable(false)]
public void Add(int idx, TimeSpan value)
{
_values[idx] += value;
}
public void Add(eVarTime idx, TimeSpan value)
{
Add((int)idx, value);
}
/// <summary>
/// 지정된 시간으로 업데이트 합니다
/// </summary>
/// <param name="idx"></param>
/// <param name="value"></param>
public void Set(eVarTime idx, DateTime value)
{
Set((int)idx, value);
}
/// <summary>
/// 현재시간으로 업데이트 합니다
/// </summary>
/// <param name="idx"></param>
public void Set(eVarTime idx)
{
Set(idx, DateTime.Now);
}
public bool IsSet(eVarTime idx)
{
return this[idx].Year != 1982;
}
}
//공용변수(시간)
public static class VAR
{
public static VarDataBool BOOL;
public static VarDataByte BYTE;
public static VarDataStr STR;
public static VarDataDateTime TIME;
public static VarDataI32 I32;
public static VarDataUI32 U32;
public static VarDataDBL DBL;
public static bool isInit { get; private set; } = false;
public static void Init(int varlen)
{
if (isInit) return; //already init
//가변 데이트타임변수
BOOL = new VarDataBool(varlen);
BYTE = new VarDataByte(varlen);
STR = new VarDataStr(varlen);
TIME = new VarDataDateTime(varlen);
I32 = new VarDataI32(varlen);
U32 = new VarDataUI32(varlen);
DBL = new VarDataDBL(varlen);
isInit = true;
}
}
}

View File

@@ -0,0 +1,5 @@
@echo off
echo Git AutoUpdate
echo tindevil@nate.com
for /d %%i in (*) do echo Enterinng "%i" | cd "%i" | git.exe pull --progress -v --no-rebase "origin" master | cd ..
@pause

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{AAF68D20-4590-4AB0-BB91-E0DD04C91DEC}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MSSQLCommand</RootNamespace>
<AssemblyName>MSSQLCommand</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Monitor.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MSSQLCommand
{
public class Monitor
{
/// <summary>
/// Connection String
/// </summary>
public string CS { get; private set; }
private int
public Monitor(string ip, string id, string pass, string db)
{
//ConnectionString = $"Data Source =10.131.15.18;Initial Catalog=EE;Persist Security Info=True;User ID=eeuser;Password=Amkor123!";
CS = $"Data Source={ip};Initial Catalog={db};Persist Security Info=True;User ID={id};Password={pass}";
}
}
}

View File

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 어셈블리에 대한 일반 정보는 다음 특성 집합을 통해
// 제어됩니다. 어셈블리와 관련된 정보를 수정하려면
// 이러한 특성 값을 변경하세요.
[assembly: AssemblyTitle("MSSQLCommand")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("MSSQLCommand")]
[assembly: AssemblyCopyright("Copyright © 2023")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에
// 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면
// 해당 형식에 대해 ComVisible 특성을 true로 설정하세요.
[assembly: ComVisible(false)]
// 이 프로젝트가 COM에 노출되는 경우 다음 GUID는 typelib의 ID를 나타냅니다.
[assembly: Guid("aaf68d20-4590-4ab0-bb91-e0dd04c91dec")]
// 어셈블리의 버전 정보는 다음 네 가지 값으로 구성됩니다.
//
// 주 버전
// 부 버전
// 빌드 번호
// 수정 버전
//
// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호를
// 기본값으로 할 수 있습니다.
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
</startup>
</configuration>

View File

@@ -0,0 +1,63 @@
namespace Patch
{
partial class Form1
{
/// <summary>
/// 필수 디자이너 변수입니다.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 사용 중인 모든 리소스를 정리합니다.
/// </summary>
/// <param name="disposing">관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form
/// <summary>
/// 디자이너 지원에 필요한 메서드입니다.
/// 이 메서드의 내용을 코드 편집기로 수정하지 마세요.
/// </summary>
private void InitializeComponent()
{
this.progressBar1 = new System.Windows.Forms.ProgressBar();
this.SuspendLayout();
//
// progressBar1
//
this.progressBar1.Dock = System.Windows.Forms.DockStyle.Fill;
this.progressBar1.Location = new System.Drawing.Point(0, 0);
this.progressBar1.Name = "progressBar1";
this.progressBar1.Size = new System.Drawing.Size(481, 68);
this.progressBar1.Style = System.Windows.Forms.ProgressBarStyle.Marquee;
this.progressBar1.TabIndex = 1;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(481, 68);
this.Controls.Add(this.progressBar1);
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "Form1";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.ProgressBar progressBar1;
}
}

View File

@@ -0,0 +1,122 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Patch
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
this.Text = "Software Patch";
this.Show();
Application.DoEvents();
//현재폴더에서 _patch 폴더 찾는다
Boolean runClient = true;
var srcpath = new System.IO.DirectoryInfo ( System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "_patch"));
if (srcpath.Exists == true)
{
//기존 프로그램 종료될떄까지 기다린다
this.Text = "기존 프로그램 종료 대기";
Application.DoEvents();
bool closeok = true;
System.Diagnostics.Stopwatch wat = new System.Diagnostics.Stopwatch();
wat.Restart();
while (CheckExistProcess("Amkor") == true)
{
Application.DoEvents();
System.Threading.Thread.Sleep(10);
if(wat.ElapsedMilliseconds >= 10000)
{
MessageBox.Show("기존프로그램이 종료되지 않았습니다", "패치실패", MessageBoxButtons.OK, MessageBoxIcon.Error);
closeok = false;
break;
}
}
if (CheckExistProcess("Amkor") == false)
{
//버젼체크하고 파일 복사해준다
var files = srcpath.GetFiles();
this.progressBar1.Maximum = files.Length;
this.progressBar1.Value = 0;
this.progressBar1.Style = ProgressBarStyle.Continuous;
var myPath = new System.IO.DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory);
try
{
foreach (var file in files)
{
this.Text = "패치파일 : " + file.Name;
Application.DoEvents();
file.CopyTo(System.IO.Path.Combine(file.Directory.Parent.FullName, file.Name), true); // System.IO.File.Copy(file, myPath.FullName, true);
this.progressBar1.Value += 1;
System.Threading.Thread.Sleep(100);
}
//패치파일을 삭제한다
srcpath.Delete(true);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
else runClient = false;
}
//클라이언트실행
if(runClient==true)
{
var file_run = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Amkor.exe");
RunProcess(file_run);
}
//프로그래램 종료
this.Close();
}
public Boolean CheckExistProcess(string ProcessName)
{
foreach (var prc in System.Diagnostics.Process.GetProcesses())
{
if (prc.ProcessName.StartsWith("svchost")) continue;
if (prc.ProcessName.ToUpper() == ProcessName.ToUpper()) return true;
}
return false;
}
public Boolean RunProcess(string file, string arg = "")
{
var fi = new System.IO.FileInfo(file);
if (!fi.Exists)
{
//Pub.log.AddE("Run Error : " + file);
return false;
}
System.Diagnostics.Process prc = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo si = new System.Diagnostics.ProcessStartInfo(file);
si.Arguments = arg;
prc.StartInfo = si;
prc.Start();
return true;
}
}
}

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Patch
{
static class Program
{
/// <summary>
/// 해당 애플리케이션의 주 진입점입니다.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}

View File

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 어셈블리에 대한 일반 정보는 다음 특성 집합을 통해
// 제어됩니다. 어셈블리와 관련된 정보를 수정하려면
// 이러한 특성 값을 변경하세요.
[assembly: AssemblyTitle("Patch")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Patch")]
[assembly: AssemblyCopyright("Copyright © 2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에
// 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면
// 해당 형식에 대해 ComVisible 특성을 true로 설정하세요.
[assembly: ComVisible(false)]
// 이 프로젝트가 COM에 노출되는 경우 다음 GUID는 typelib의 ID를 나타냅니다.
[assembly: Guid("37dc0bae-50bf-41e4-baab-b0e211467ad1")]
// 어셈블리의 버전 정보는 다음 네 가지 값으로 구성됩니다.
//
// 주 버전
// 부 버전
// 빌드 번호
// 수정 버전
//
// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호를
// 기본값으로 할 수 있습니다.
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 이 코드는 도구를 사용하여 생성되었습니다.
// 런타임 버전:4.0.30319.42000
//
// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면
// 이러한 변경 내용이 손실됩니다.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Patch.Properties {
using System;
/// <summary>
/// 지역화된 문자열 등을 찾기 위한 강력한 형식의 리소스 클래스입니다.
/// </summary>
// 이 클래스는 ResGen 또는 Visual Studio와 같은 도구를 통해 StronglyTypedResourceBuilder
// 클래스에서 자동으로 생성되었습니다.
// 멤버를 추가하거나 제거하려면 .ResX 파일을 편집한 다음 /str 옵션을 사용하여 ResGen을
// 다시 실행하거나 VS 프로젝트를 다시 빌드하십시오.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// 이 클래스에서 사용하는 캐시된 ResourceManager 인스턴스를 반환합니다.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Patch.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// 이 강력한 형식의 리소스 클래스를 사용하여 모든 리소스 조회에 대해 현재 스레드의 CurrentUICulture 속성을
/// 재정의합니다.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}

View File

@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,26 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 이 코드는 도구를 사용하여 생성되었습니다.
// 런타임 버전:4.0.30319.42000
//
// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면
// 이러한 변경 내용이 손실됩니다.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Patch.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.4.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
}
}

View File

@@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View File

@@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{37DC0BAE-50BF-41E4-BAAB-B0E211467AD1}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>Patch</RootNamespace>
<AssemblyName>SWPatch</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\..\..\..\..\..\Amkor\AGV3\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Form1.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Form1.Designer.cs">
<DependentUpon>Form1.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="Form1.resx">
<DependentUpon>Form1.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace arDev.Arduino
{
public enum IODirection
{
Input = 0,
Output
}
public enum MessageType
{
Normal = 0,
SendData,
ReceiveData,
Message,
RxIOData,
RxSetData,
}
}

View File

@@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace arDev.Arduino
{
public partial class DIO
{
/// <summary>
/// Digital Input/Output Changed
/// </summary>
public event EventHandler<IOValueEventArgs> ValueChanged;
public event EventHandler<FlagValueEventArgs> FlagChanged;
/// <summary>
/// 마그넷 센서의 값이 변경되었을때 발생 함
/// </summary>
public event EventHandler PositionChanged;
///// <summary>
///// Digital Input/Output Message
///// </summary>
//public event EventHandler<MessageEventArgs> Message;
public class FlagValueEventArgs : EventArgs
{
private int _arridx;
private Boolean _oldvalue;
private Boolean _newvalue;
public int ArrIDX { get { return _arridx; } }
public Boolean OldValue { get { return _oldvalue; } }
public Boolean NewValue { get { return _newvalue; } }
public FlagValueEventArgs( int ArrIDX, Boolean oldvalue, Boolean newvalue)
{
_arridx = ArrIDX;
_oldvalue = oldvalue;
_newvalue = newvalue;
}
}
public class IOValueEventArgs : EventArgs
{
private int _arridx;
private Boolean _oldvalue;
private Boolean _newvalue;
private IODirection _dir;
public int ArrIDX { get { return _arridx; } }
public Boolean OldValue { get { return _oldvalue; } }
public Boolean NewValue { get { return _newvalue; } }
public IODirection Direction { get { return _dir; } }
public IOValueEventArgs(IODirection dir, int ArrIDX, Boolean oldvalue, Boolean newvalue)
{
_arridx = ArrIDX;
_oldvalue = oldvalue;
_newvalue = newvalue;
_dir = dir;
}
}
//public class MessageEventArgs : EventArgs
//{
// private Boolean _isError = false;
// public Boolean IsError { get { return _isError; } }
// private string _message = string.Empty;
// public string Message { get { return _message; } }
// private Arduino.MessageType _mtype;
// public Arduino.MessageType MessageType { get { return _mtype; } }
// public MessageEventArgs(Arduino.MessageType mType, string Message, Boolean isError)
// {
// _isError = isError;
// _message = Message;
// this._mtype = mType;
// }
//}
}
}

View File

@@ -0,0 +1,556 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.ComponentModel;
using System.Reflection;
using System.Runtime;
using System.Runtime.InteropServices;
using System.Collections.Concurrent;
namespace arDev.Arduino
{
public partial class DIO : arRS232
{
protected object lockobj = new object();
public struct SetupInfo
{
public byte ioInterval;
public byte ResetCount;
public byte SpeedH;
public byte SpeedL;
public byte SpeedZ;
public byte pindirRevDILow;
public byte pindirRevDIHigh;
public byte UpTime;
public byte BalanceThd;
public byte MarkThd;
public byte SpeedC;
public byte BalanceThdUp;
public Boolean IsValid;
public void Clear()
{
pindirRevDIHigh = 0;
pindirRevDILow = 0;
ioInterval = 0;
ResetCount = 0;
SpeedH = 0;
SpeedL = 0;
SpeedC = 0;
BalanceThd = 0;
BalanceThd = 0;
UpTime = 0;
MarkThd = 0;
SpeedZ = 0;
IsValid = false;
}
}
public SetupInfo setupInfo;
private Boolean STX11 = false;
private Boolean STX21 = false;
//private Boolean ETX11 = false;
// private byte[] buffer1;
// readonly List<byte> Tempbuffer1 = new List<byte>();
readonly ManualResetEvent mre = new ManualResetEvent(true);
// protected string errorMessage = string.Empty;
// readonly System.IO.Ports.SerialPort dev = null;
private byte LEN1 = 0;
//private byte CHK1 = 0;
//private int bufferCount1 = 0;
public DateTime ConnTryTime = DateTime.Now.AddDays(-1);
protected DateTime[] SetFlagTime = new DateTime[32];
readonly Boolean[] Flag = new bool[32];
readonly Boolean[] DIValue = new bool[16];
readonly Boolean[] DOValue = new bool[16];
public UInt16[] AIValue = new ushort[3];
public byte[] AOValue = new byte[3];
public string ioBinStr = string.Empty;
public string SetupStr = string.Empty;
public byte RunTime = 0;
public byte[] MAG_VALUE = new byte[2];
public byte[] SV_SPEED = new byte[2];
public Boolean isDisposed = false; //dispose가 호출되었는가?
public string LastMessage { get; set; }
public DateTime LastMessageTime { get; set; }
/// <summary>
/// 생성자
/// </summary>
public DIO()
{
//설정의 값
setupInfo = new SetupInfo();
setupInfo.Clear();
SV_SPEED[0] = 0;
SV_SPEED[1] = 0;
//마그넷 센서(0~100)
MAG_VALUE[0] = 50;
MAG_VALUE[1] = 50;
lastRecvTime = DateTime.Parse("1982-11-23");
for (int i = 0; i < Flag.Length; i++)
Flag[i] = false;
for (int i = 0; i < DIValue.Length; i++)
DIValue[i] = false;
for (int i = 0; i < DOValue.Length; i++)
DOValue[i] = false;
for (int i = 0; i < AIValue.Length; i++)
AIValue[i] = 0;
for (int i = 0; i < AOValue.Length; i++)
AOValue[i] = 0;
for (int i = 0; i < SetFlagTime.Length; i++)
SetFlagTime[i] = DateTime.Parse("1982-11-23");
}
protected override bool CustomParser(byte[] buf, out byte[] remainBuffer)
{
List<byte> remain = new List<byte>();
Boolean bComplete = false;
for (int i = 0; i < buf.Length; i++)
{
var incomByte = buf[i];
if (bComplete == true)
{
remain.Add(incomByte);
}
else
{
if (STX11 == false)
{
if (incomByte != '@')
{
STX21 = false;
// ETX11 = false;
continue;
}
else
{
STX11 = true;
tempBuffer.Clear();
tempBuffer.Add(incomByte);
}
}
else if (STX21 == false)
{
if (tempBuffer.Count != 1 || tempBuffer.Count < 1 || tempBuffer[0] != '@' || incomByte != '@')
{
STX11 = false;
//ETX11 = false;
continue;
}
else
{
STX21 = true;
tempBuffer.Add(incomByte);
}
}
else
{
tempBuffer.Add(incomByte);
//여기서부터는무조건 누적한다.
if (tempBuffer.Count == 3)
{
if (tempBuffer[0] != '@' || tempBuffer[1] != '@')
{
STX11 = false;
STX21 = false;
// ETX11 = false;
LEN1 = 0;
tempBuffer.Clear();
}
else LEN1 = incomByte; //데이터 길이가온다
}
//else if (Tempbuffer1.Count == LEN1 + 5) //ETX1
//{
// if (incomingByte != 0x0D)
// {
// //ETX가 와야하는데 다른데이터가 왔다
// STX11 = false;
// STX21 = false;
// // ETX11 = false;
// var str = System.Text.Encoding.Default.GetString(Tempbuffer1.ToArray());
// RaiseMessage(MessageType.ReceiveData, "에러 모두 파기 : " + str, true);
// Tempbuffer1.Clear();
// }
//}
else if (tempBuffer.Count == LEN1 + 6)
{
//전체길이를 만족햇다.
if (incomByte != 0x0A)
{
//ETX가 와야하는데 다른데이터가 왔다
STX11 = false;
STX21 = false;
// ETX11 = false;
//var str = System.Text.Encoding.Default.GetString(Tempbuffer1.ToArray());
RaiseMessage(MessageType.Error, "에러 모두 파기 : ETX 값 오류");
tempBuffer.Clear();
}
else if (tempBuffer[tempBuffer.Count - 2] != 0x0D)
{
//ETX가 와야하는데 다른데이터가 왔다
STX11 = false;
STX21 = false;
// ETX11 = false;
//var str = System.Text.Encoding.Default.GetString(Tempbuffer1.());
RaiseMessage(MessageType.Error, "에러 모두 파기 : ETX 값 오류");
tempBuffer.Clear();
}
else
{
STX11 = false;
STX21 = false;
// ETX11 = false;
//if (LastReceiveBuffer == null) LastReceiveBuffer = new byte[tempBuffer.Count];
//else if (LastReceiveBuffer.Length != tempBuffer.Count) Array.Resize(ref LastReceiveBuffer, Tempbuffer1.Count);
//tempBuffer.CopyTo(LastReceiveBuffer)tempBuffer
//tempBuffer.Clear();
bComplete = true;
}
}
}
}
}
remainBuffer = remain.ToArray();
return bComplete;
}
bool Checksum(byte[] buffer, int datalength)
{
//체크섬필요 221118
if (buffer[buffer.Length-3] == '*')
{
return true;
}
byte checksum = 0;
for (int i = 3; i < datalength + 3; i++)
{
checksum = (byte)(checksum ^ buffer[i]);
}
return checksum == buffer[buffer.Length - 3];
}
public override bool ProcessRecvData(byte[] data)
{
var hexString = GetHexString(data);//.gethe
var len = data[2];
if (len + 6 != data.Length)
{
RaiseMessage(MessageType.Error, string.Format("길이오류 예상:{0},수신:{1},{2}", len + 5, data.Length, hexString));
}
else if (data[0] != 0x40 || data[1] != 0x40 || data[data.Length - 2] != 0x0D || data[data.Length - 1] != 0x0A)
{
RaiseMessage(MessageType.Error, string.Format("헤더 오류 : {0}", hexString));
}
else if (Checksum(data, len) == false) //체크섬 221118
{
RaiseMessage(MessageType.Error, string.Format("체크섬 오류 : {0}", hexString));
}
else
{
//RaiseMessage(MessageType.ReceiveData, hexString);
lastRecvTime = DateTime.Now;
var cmd = data[3];
if (cmd == 'I') //IOData
{
if (len != 10)
RaiseMessage(MessageType.Error, "IO수신길이오류:" + DateTime.Now.ToString("mm:ss.fff") + " 수신 : " + hexString);
else Parse_IOData(data);
}
else if (cmd == 'T')
{
// Boolean errorMessage = buffer[4] == 1;
var message = System.Text.Encoding.Default.GetString(data, 5, len - 2);//데이터타입과 에러여부 제거
LastMessage = message;
LastMessageTime = DateTime.Now;
RaiseMessage(MessageType.Normal, message);
}
else if (cmd == 'S') //setup 정보 200310 (홈)
{
if (len != 13)
RaiseMessage(MessageType.Error, "SETUP수신길이오류:" + DateTime.Now.ToString("mm:ss.fff") + " 수신 : " + hexString);
else Parse_SetupData(data);
}
else
{
RaiseMessage(MessageType.Normal, "Unknown:" + hexString + "\n" + "Data=" + System.Text.Encoding.Default.GetString(data));
}
}
return true;
}
void Parse_IOData(byte[] buffer)
{
var IOData = BitConverter.ToUInt32(buffer, 4);
//var newMagF = BitConverter.ToUInt16(buffer, 8);
//va1r newMagB = BitConverter.ToUInt16(buffer, 10);
//var newAlign = BitConverter.ToUInt16(buffer, 12);
//if (newMagF != AIValue[0] || newMagB != AIValue[1])
//{
// AIValue[0] = newMagF;// BitConverter.ToUInt16(buffer, 8); //마그넷센서 F
// AIValue[1] = newMagB; //BitConverter.ToUInt16(buffer, 10); //마그넷센서 B
// PositionChanged?.Invoke(this, null);
//}
//AIValue[2] = newAlign;
//AOValue[0] = buffer[14]; //왼쪽바퀴 속도
//AOValue[1] = buffer[15]; //오른쪽바퀴 속도
//AOValue[2] = buffer[16]; //Z축 속도
//SV_SPEED[0] = buffer[21]; //왼쪽바퀴의 설정속도
//SV_SPEED[1] = buffer[22]; //오른쪽바퀴의 설정속도
//MAG_VALUE[0] = buffer[23]; //magnet front
//MAG_VALUE[1] = buffer[24]; //magnet rear
RunTime = buffer[12];
//플래그값 확인
byte[] buf_flag = new byte[4];
Array.Copy(buffer, 8, buf_flag, 0, 4);
var baF = new System.Collections.BitArray(buf_flag);
for (int i = 0; i < 32; i++)
{
Boolean val = baF[i];
//입력
if (this.Flag[i] != val)
{
Flag[i] = val;
//변경이벤트 생성
FlagChanged?.Invoke(this, new FlagValueEventArgs(i, !val, val));
}
}
//IO값 확인
byte[] buf_iodata = new byte[4];
Array.Copy(buffer, 4, buf_iodata, 0, 4);
var ba = new System.Collections.BitArray(buf_iodata);
for (int i = 0; i < 32; i++)
{
Boolean val = ba[i];
if (i >= 16)
{
//출력
if (DOValue[i - 16] != val)
{
DOValue[i - 16] = val;
//변경이벤트 생성
ValueChanged?.Invoke(this, new IOValueEventArgs(IODirection.Output, i - 16, !val, val));
}
}
else
{
//입력
if (DIValue[i] != val)
{
DIValue[i] = val;
//변경이벤트 생성
ValueChanged?.Invoke(this, new IOValueEventArgs(IODirection.Input, i, !val, val));
}
}
}
ioBinStr = Convert.ToString(IOData, 2).PadLeft(32, '0');
//string msg = string.Format(DateTime.Now.ToString("mm:ss.fff") + " IO:{0},AN={1:0000},{2:0000},FG={3},AO={4},{5}",
// binstr, An1, An2, FGData, Ao11, Ao12);
}
void Parse_SetupData(byte[] buffer)
{
setupInfo.ioInterval = buffer[4];
setupInfo.ResetCount = buffer[5];
setupInfo.SpeedH = buffer[6];
setupInfo.SpeedL = buffer[7];
setupInfo.SpeedZ = buffer[8];
setupInfo.pindirRevDIHigh = buffer[9];
setupInfo.pindirRevDILow = buffer[10];
setupInfo.UpTime = buffer[11];
setupInfo.BalanceThd = buffer[12];
setupInfo.MarkThd = buffer[13];
setupInfo.SpeedC = buffer[14];
setupInfo.BalanceThdUp = buffer[15];
SetupStr = string.Format("I:{0},R={1},H={2},L={3},Z={4},UP={5},BL={6},MK={7},SPD_C={8},BLUP={9}",
setupInfo.ioInterval,
setupInfo.ResetCount,
setupInfo.SpeedH,
setupInfo.SpeedL,
setupInfo.SpeedZ,
setupInfo.UpTime,
setupInfo.BalanceThd,
setupInfo.MarkThd,
setupInfo.SpeedC,
setupInfo.BalanceThdUp);
}
public byte MakeChecksum(byte[] buffer)
{
//return 0;
byte chk = 0;
foreach (var b in buffer)
chk = (byte)(chk ^ b);
return chk;
}
#region "Method"
protected Boolean Sendcommand(byte cmd, byte p1, byte p2)
{
//이번호의 상태를 on/off 해줘야함
List<byte> buffer = new List<byte>
{
cmd, //command
p1,
p2
};
byte dataLen = (byte)buffer.Count; //데이터길이
byte checksum = MakeChecksum(buffer.ToArray());
buffer.Insert(0, (byte)'@'); //stx
buffer.Insert(1, (byte)'@'); //stx
buffer.Insert(2, dataLen);
buffer.Add(checksum); //길이를 제외한 실제 데이터 영역만 체크섬
buffer.Add(0x0D); //etx
buffer.Add(0x0A); //etx
return WriteData(buffer.ToArray());
}
/// <summary>
/// 이벤트를 강제 생성합니다.(내부변수값도 변경됩니다)
/// </summary>
/// <param name="Direction"></param>
/// <param name="idx"></param>
/// <param name="value"></param>
public void RaiseEvent(IODirection dir, int idx, Boolean value)
{
if (ValueChanged != null)
{
if (!mre.WaitOne(100))
{
RaiseMessage( MessageType.Error, "RaiseEvent WaitOne Timeout");
return;
}
mre.Reset();
bool curValue;
if (dir == IODirection.Input)
{
curValue = DIValue[idx];
DIValue[idx] = value;
}
else
{
curValue = DOValue[idx];
DOValue[idx] = value;
}
try
{
//이벤트를 할당한곳에서 오류가 나면 이곳에서 에러가 잡힌다.
ValueChanged(this, new IOValueEventArgs(dir, idx, curValue, value));
}
catch (Exception ex)
{
RaiseMessage(MessageType.Error, ex.Message);
}
finally
{
mre.Set();
}
}
}
//public Boolean GetFlag(byte idx)
//{
// return Flag[idx];
//}
public Boolean GetValueI(byte idx)
{
if (idx < DIValue.Length) return DIValue[idx];
else return false;
}
public Boolean GetValueO(byte idx)
{
if (idx < DOValue.Length) return DOValue[idx];
else return false;
}
//public Boolean SetValueI(int idx,Boolean value)
//{
// if (idx < DIValue.Length)
// {
// DIValue[idx] = value;
// return true;
// }
// else return false;
//}
public Boolean SetValue(byte idx, Boolean value)
{
byte SET_PINMODE = 3;
if (value == true) return Sendcommand(SET_PINMODE, idx, 1);
else return Sendcommand(SET_PINMODE, idx, 0);
}
public Boolean SetToggle(byte idx)
{
var curbalue = GetValueO(idx);
return SetValue(idx, !curbalue);
}
public string GetErrorMessage()
{
return errorMessage;
}
#endregion
}
}

View File

@@ -0,0 +1,387 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using arDev.Arduino;
using COMM;
namespace arDev
{
public class FakePLC : arDev.Arduino.DIO
{
private System.Threading.Thread thPLC;
public bool Shutdown { get; set; } = false;
public FakePLC()
{
COMM.VAR.Init(128);
}
~FakePLC()
{
System.Threading.Tasks.Task.Run(() =>
{
//쓰레드가 살아잇다면 대기한다
if (thPLC != null && thPLC.IsAlive)
{
System.Threading.Thread.Sleep(100);
}
this.Close();
});
}
private object lockobjdata = new object();
public enum eEEPAddress
{
EEP_IOINTERVAL = 0,
EEP_RESETCOUNT,
EEP_DIREVH,
EEP_DIREVL,
EEP_OPTION,
EEP_UPTIME,
};
public enum eCommand : byte
{
LOAD = 0, //EEPROM 불러오기
SAVE, //EEPROM 저장
RESET, //초기화
PINGCHK,
SET_PINMODE, //PINMODE 설정
SET_DOUTPUT, //디지털출력설정(포트번호,값[1,0])
SET_AOUTPUT, //아날로그출력설정(포트GET_SETTING = 50, //셋팅값 요청
SET_FLAG,
SET_EEPROM,
SET_MANUALSPEED,
GET_SETTING = 50,
GUIDE_MOT = 90, //가이드커버(양쪽) 0=멈춤,1=UP,2=DN 아스키코드표 90=Z
SET_EEP_DIREV,
};
//public enum MotorType
//{
// Left = 0,
// Right
//}
//public enum Direction
//{
// CW = 0,
// CCW,
//}
//public enum RunType
//{
// Stop = 0,
// Up,
// Dn
//}
public enum DIName
{
PINI_EMG = 0,
PINI_BTN_1,
PINI_BTN_2,
PINI_BTN_3,
PINI_BTN_4,
PINI_OVERLOADL,
PINI_OVERLOADR,
PINI_EMPTY_07,
PINI_EMPTY_08,
PINI_BTN_ZUP,
PINI_BTN_ZDN,
PINI_LIMIT_LU,
PINI_LIMIT_LD,
PINI_LIMIT_RU,
PINI_LIMIT_RD,
PINI_STOP,
}
public enum DIPin
{
PINI_EMG = 30,
PINI_BTN_1,
PINI_BTN_2,
PINI_BTN_3,
PINI_BTN_4,
PINI_OVERLOADL,
PINI_OVERLOADR,
PINI_EMPTY_07,
PINI_EMPTY_08,
PINI_BTN_ZUP,
PINI_BTN_ZDN,
PINI_LIMIT_LU,
PINI_LIMIT_LD,
PINI_LIMIT_RU,
PINI_LIMIT_RD,
PINI_STOP,
}
public enum DOName
{
PINO_GUIDEMOTOR_LDIR,
PINO_GUIDEMOTOR_LRUN,
PINO_GUIDEMOTOR_RDIR,
PINO_GUIDEMOTOR_RRUN,
PINO_EMPTY_04,
PINO_EMPTY_05,
PINO_EMPTY_06,
PINO_EMPTY_07,
}
public enum DOPin
{
PINO_GUIDEMOTOR_LDIR = 22,
PINO_GUIDEMOTOR_LRUN,
PINO_GUIDEMOTOR_RDIR,
PINO_GUIDEMOTOR_RRUN,
PINO_EMPTY_04,
PINO_EMPTY_05,
PINO_EMPTY_06,
PINO_EMPTY_07,
}
public enum Rundirection : byte
{
Stop = 0,
Forward,
Backward,
Left,
Right,
EStop,
}
public enum ZMotDirection
{
Stop = 0,
Up,
Down
}
private bool Sendcommand(eCommand cmd, char p1, char p2)
{
return Sendcommand(cmd, (byte)p1, (byte)p2);
}
private bool Sendcommand(eCommand cmd, char p1, byte p2 = 0)
{
return Sendcommand(cmd, (byte)p1, p2);
}
private bool Sendcommand(eCommand cmd, byte p1 = 0, byte p2 = 0)
{
if (cmd != eCommand.PINGCHK)
{
if (cmd == eCommand.SET_FLAG)
{
//플래그값은 공용변수로 변경
var idx = (eVarBool)p1;
VAR.BOOL[idx] = p2 != 0;
RaiseMessage(MessageType.Send, string.Format("PLC CMD:{0} [{1}]=>{2}", cmd, (eVarBool)p1, p2));
}
else
RaiseMessage(MessageType.Send, string.Format("PLC CMD:{0}, P1:{1}, P2:{2}", cmd, p1, p2));
}
return Sendcommand((byte)cmd, p1, p2);
}
public Boolean GetValueI(DIName idx)
{
return GetValueI((byte)idx);
}
public Boolean GetValueO(DOName idx)
{
return GetValueO((byte)idx);
}
public Boolean GetFlag(int flag)
{
return COMM.VAR.BOOL[flag];
}
public Boolean GetFlag(COMM.eVarBool flag)
{
return COMM.VAR.BOOL[(int)flag];
}
public Boolean SetFlag(byte idx, Boolean value)
{
SetFlagTime[(int)idx] = DateTime.Now; //플래그기록을 시도한 시간
if (value == true)
return Sendcommand(eCommand.SET_FLAG, idx, 1);
else
return Sendcommand(eCommand.SET_FLAG, idx, 0);
}
//public Boolean SetOpt_AD4Invert(Boolean value)
//{
// var idx = (byte)PLCFlag.FLAG_ENABLE_AD4INVERT;
// SetFlagTime[idx] = DateTime.Now; //플래그기록을 시도한 시간
// if (value == true)
// return Sendcommand(eCommand.SET_FLAG, idx, 1);
// else
// return Sendcommand(eCommand.SET_FLAG, idx, 0);
//}
//public Boolean SetLog_SpeedControl(Boolean value)
//{
// var idx = (byte)PLCFlag.FLAG_ENABLE_LOG_SPEED;
// SetFlagTime[idx] = DateTime.Now; //플래그기록을 시도한 시간
// if (value == true)
// return Sendcommand(eCommand.SET_FLAG, idx, 1);
// else
// return Sendcommand(eCommand.SET_FLAG, idx, 0);
//}
public Boolean SetFlag(eVarBool flag, Boolean value)
{
VAR.BOOL[flag] = value;
return true;
}
public Boolean SetEEP(eEEPAddress address, byte value)
{
RaiseMessage(MessageType.Normal, string.Format("[M] Set EEP Rom Addr={0},Val={1}", address, value));
return Sendcommand(eCommand.SET_EEPROM, (byte)address, value);
}
public Boolean SetOutput(byte pinNO, Boolean Value)
{
if (Value == true) return Sendcommand(eCommand.SET_DOUTPUT, pinNO, 1);
else return Sendcommand(eCommand.SET_DOUTPUT, pinNO, 0);
}
public byte ApplySpeedH = 0;
public byte ApplySpeedL = 0;
public byte ApplySpeedC = 0;
public byte ApplySpeedZ = 0;
public DateTime SaveTime = DateTime.Parse("1982-11-23");
public Boolean SetPinReverse(byte High, byte Low)
{
RaiseMessage(MessageType.Normal,
string.Format("Pin Reverse H={0},L={1}", High, Low)
);
bool b1 = Sendcommand(eCommand.SET_EEPROM, (byte)eEEPAddress.EEP_DIREVH, High);
bool b2 = Sendcommand(eCommand.SET_EEPROM, (byte)eEEPAddress.EEP_DIREVL, Low);
return b1 && b2;
}
public Boolean SetMotorUpTime(byte value)
{
RaiseMessage(MessageType.Normal,
string.Format("Motor Up Time Value={0}", value)
);
bool b1 = Sendcommand(eCommand.SET_EEPROM, (byte)eEEPAddress.EEP_UPTIME, value);
return b1;
}
public Boolean SaveEEPROM()
{
RaiseMessage(MessageType.Normal,
string.Format("Save EEPROM")
);
bool b1 = Sendcommand(eCommand.SAVE, 0);
return b1;
}
public Boolean LoadEEPROM()
{
RaiseMessage(MessageType.Normal,
string.Format("Load EEPROM")
);
bool b1 = Sendcommand(eCommand.LOAD, 0);
return b1;
}
//public double ManualSpeed = 0.0;
//public bool SetManualSpeed(double Percvalue)
//{
// var Speed = (byte)((Percvalue / 100.0) * 255.0);
// ManualSpeed = Percvalue;
// // datamanager.COMCONTROLLER.Speak($"{Percvalue} 퍼센트 설정");
// RaiseMessage(MessageType.Normal,
// string.Format("Convert Speed Hold {0}%->{1}", Percvalue, Speed),
// false);
// return Sendcommand(eCommand.SET_MANUALSPEED, Speed);
//}
public DateTime LastPingTime = DateTime.Parse("1982-11-23");
public bool SendPing()
{
LastPingTime = DateTime.Now;
return Sendcommand(eCommand.PINGCHK, 0, 0);
}
public bool ZMot(ZMotDirection dir)
{
if (dir == ZMotDirection.Up)
return Sendcommand(eCommand.GUIDE_MOT, 'A', 'P'); //up
else if (dir == ZMotDirection.Down)
return Sendcommand(eCommand.GUIDE_MOT, 'A', 'N'); //down
else if (dir == ZMotDirection.Stop)
return Sendcommand(eCommand.GUIDE_MOT, 'A', 'S'); //stop
else return false;
}
public bool ZMot_Left(ZMotDirection dir)
{
if (dir == ZMotDirection.Up)
return Sendcommand(eCommand.GUIDE_MOT, 'L', 'P'); //up
else if (dir == ZMotDirection.Down)
return Sendcommand(eCommand.GUIDE_MOT, 'L', 'N'); //down
else if (dir == ZMotDirection.Stop)
return Sendcommand(eCommand.GUIDE_MOT, 'L', 'S'); //stop
else return false;
}
public bool ZMot_Right(ZMotDirection dir)
{
if (dir == ZMotDirection.Up)
return Sendcommand(eCommand.GUIDE_MOT, 'R', 'P'); //up
else if (dir == ZMotDirection.Down)
return Sendcommand(eCommand.GUIDE_MOT, 'R', 'N'); //down
else if (dir == ZMotDirection.Stop)
return Sendcommand(eCommand.GUIDE_MOT, 'R', 'S'); //stop
else return false;
}
/// <summary>
/// 오버로드 또는 L이 활성화되되면 True를 반환함
/// </summary>
/// <returns></returns>
public Boolean IsOverLoad()
{
if (GetValueI(DIName.PINI_OVERLOADL) || GetValueI(DIName.PINI_OVERLOADR)) return true;
else return false;
}
public Boolean IsLimitUp()
{
if (GetValueI(DIName.PINI_LIMIT_LU) || GetValueI(DIName.PINI_LIMIT_RU)) return true;
else return false;
}
public Boolean IsLimitDn()
{
if (GetValueI(DIName.PINI_LIMIT_LD) || GetValueI(DIName.PINI_LIMIT_RD)) return true;
else return false;
}
}
}

View File

@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{476C8E64-7B6B-4554-ACA2-04302715750F}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Device</RootNamespace>
<AssemblyName>Device_PLC</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Arduino\EnumStruct.cs" />
<Compile Include="Arduino\EventsIO.cs" />
<Compile Include="Arduino\MemoryAccess.cs" />
<Compile Include="FakePLC.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CommData\CommData.csproj">
<Project>{14e8c9a5-013e-49ba-b435-efefc77dd623}</Project>
<Name>CommData</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 어셈블리에 대한 일반 정보는 다음 특성 집합을 통해
// 제어됩니다. 어셈블리와 관련된 정보를 수정하려면
// 이러한 특성 값을 변경하세요.
[assembly: AssemblyTitle("Device_PLC")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Device_PLC")]
[assembly: AssemblyCopyright("Copyright © 2022")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에
// 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면
// 해당 형식에 대해 ComVisible 특성을 true로 설정하세요.
[assembly: ComVisible(false)]
// 이 프로젝트가 COM에 노출되는 경우 다음 GUID는 typelib의 ID를 나타냅니다.
[assembly: Guid("476c8e64-7b6b-4554-aca2-04302715750f")]
// 어셈블리의 버전 정보는 다음 네 가지 값으로 구성됩니다.
//
// 주 버전
// 부 버전
// 빌드 번호
// 수정 버전
//
// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호를
// 기본값으로 할 수 있습니다.
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
namespace arFrame.Control
{
[TypeConverterAttribute(typeof(ExpandableObjectConverter))]
public class ColorListItem
{
public System.Drawing.Color BackColor1 { get; set; }
public System.Drawing.Color BackColor2 { get; set; }
public string Remark { get; set; }
public ColorListItem()
{
BackColor1 = System.Drawing.Color.Transparent;
BackColor2 = System.Drawing.Color.Transparent;
Remark = string.Empty;
}
}
}

View File

@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
namespace arFrame.Control
{
[TypeConverterAttribute(typeof(ExpandableObjectConverter))]
public class GridViewItem
{
public int row { get; private set; }
public int col { get; private set; }
public int idx { get; private set; }
[Category("arFrame"), DisplayName("Tag")]
public string Tag { get; set; }
[Category("arFrame"), DisplayName("글자 정렬 방식")]
public System.Drawing.ContentAlignment TextAlign { get; set; }
[Category("arFrame"), DisplayName("글자 여백")]
public System.Windows.Forms.Padding Padding { get; set; }
[Category("arFrame"), DisplayName("메뉴 사용여부"), Description("활성화시 메뉴의 클릭이벤트가 발생하지 않습니다")]
public Boolean Enable { get; set; }
public System.Drawing.Color BackColor1 { get; set; }
public System.Drawing.Color BackColor2 { get; set; }
public Boolean Dirty { get; set; }
public System.Drawing.RectangleF rect { get; set; }
[Category("arFrame"), DisplayName("번호")]
public int No { get; set; }
public GridViewItem(int idx_,int _r,int _c)
{
this.row = _r;
this.col = _c;
BackColor1 = System.Drawing.Color.Transparent;
BackColor2 = System.Drawing.Color.Transparent;
rect = System.Drawing.RectangleF.Empty;
Enable = true;
this.idx = idx_;
TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
Padding = new System.Windows.Forms.Padding(0, 0, 0, 0);
No = 0;
this.Dirty = true;
}
}
}

View File

@@ -0,0 +1,36 @@
namespace arFrame.Control
{
partial class GridView
{
/// <summary>
/// 필수 디자이너 변수입니다.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 사용 중인 모든 리소스를 정리합니다.
/// </summary>
/// <param name="disposing">관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region
/// <summary>
/// 디자이너 지원에 필요한 메서드입니다.
/// 이 메서드의 내용을 코드 편집기로 수정하지 마십시오.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
}
}

View File

@@ -0,0 +1,624 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace arFrame.Control
{
public partial class GridView : System.Windows.Forms.Control
{
private int bordersize = 0;
private int menubordersize = 1;
private int menugap = 5;
private System.Windows.Forms.Padding padding = new Padding(3, 3, 3, 3);
private System.Drawing.Color backcolor = System.Drawing.Color.White;
private System.Drawing.Color bordercolor = System.Drawing.Color.Black;
private Boolean textattachtoimage = true;
private Boolean _showIndexString = true;
private System.Drawing.Color _shadowColor = System.Drawing.Color.Transparent;
private System.Drawing.Color foreColorPin = System.Drawing.Color.WhiteSmoke;
private System.Drawing.Font fontPin = new Font("Consolas", 8, FontStyle.Bold);
private Point _matrixsize = new Point(8, 2);
public Point MatrixSize { get { return _matrixsize; } set { _matrixsize = value; ResetArray(); RemakeChartRect(); } }
[Browsable(false)]
public int ColumnCount { get { return _matrixsize.X; } }
[Browsable(false)]
public int RowCount { get { return _matrixsize.Y; } }
public int ItemCount { get { return ColumnCount * RowCount; } }
private GridViewItem[] Items;
private UInt16[] _values;
private string[] _titles;
private string[] _tags;
private string[] _names;
private ColorListItem[] _colorlist;
public ColorListItem[] ColorList { get { return _colorlist; } set { _colorlist = value; this.Invalidate(); } }
public string[] Names { get { return _names; } set { _names = value; Invalidate(); } }
public string[] Titles { get { return _titles; } set { _titles = value; Invalidate(); } }
public UInt16[] Values { get { return _values; } set { _values = value; Invalidate(); } }
public string[] Tags { get { return _tags; } set { _tags = value; } }
private bool _showdebuginfo = false;
public Boolean showDebugInfo { get { return _showdebuginfo; } set { _showdebuginfo = value; Invalidate(); } }
public void setNames(string[] value)
{
_names = value;
}
public void setTitle(string[] value)
{
List<string> titlerows = new List<string>();
List<string> tagrows = new List<string>();
for (int i = 0; i < value.Length; i++)
{
var r = (int)(Math.Floor((double)(i / ColumnCount)));
var c = i % ColumnCount;
if (titlerows.Count < r + 1) titlerows.Add(string.Empty);
if (tagrows.Count < r + 1) tagrows.Add(string.Empty);
var prestr = titlerows[r];
if (prestr != "") prestr += "|";
titlerows[r] = prestr + value[i];
var prestr_t = tagrows[r];
if (prestr_t != "") prestr_t += "|";
tagrows[r] = prestr_t + "";
if (i < itemCount) this.Items[i].Enable = true;
}
this._titles = titlerows.ToArray();
this._tags = tagrows.ToArray();
}
public Boolean setTitle(int row, int col, string value, string itemtag = "")
{
if (_titles == null) _titles = new string[0];
if (_tags == null) _tags = new string[0];
if ( row >= _titles.Length) Array.Resize(ref _titles, row + 1);
if( row >= _tags.Length) Array.Resize(ref _tags, row+1);
if (_titles[row] == null) _titles[row] = string.Empty;
if (_tags[row] == null) _tags[row] = string.Empty;
var linebuf = _titles[row].Split('|');
var linebuf_t = _tags[row].Split('|');
if (col >= linebuf.Length) Array.Resize(ref linebuf, col + 1);
if (col >= linebuf_t.Length) Array.Resize(ref linebuf_t, col + 1);
linebuf[col] = value;
linebuf_t[col] = itemtag;
_titles[row] = string.Join("|", linebuf);
_tags[row] = string.Join("|", linebuf_t);
return true;
//var idx = row * this.ColumnCount + col;
//return setTitle(idx, value);
}
public Boolean setTitle(int idx, string value)
{
if (idx < ColumnCount) return setTitle(0, idx, value);
else
{
//줄값이 필요하다
var row = (int)(Math.Floor((double)(idx / ColumnCount)));
var col = idx % ColumnCount;
return setTitle(row, col, value);
}
}
public void setValue(bool[] value)
{
var v = new UInt16[value.Length];
for (int i = 0; i < value.Length; i++)
v[i] = (UInt16)(value[i] ? 1 : 0);
_values = v;
}
public void setValue(UInt16[] value)
{
_values = value;
}
public Boolean setValue(int idx, ushort value)
{
if (this._values == null) _values = new ushort[idx + 1];
if (idx >= this._values.Length) Array.Resize(ref _values, idx + 1);
this._values[idx] = value;
return true;
}
public Boolean setTag(string[] value)
{
this._tags = value;
return true;
}
public Boolean setTag(int idx, string value)
{
if (this._tags == null) Tags = new string[idx + 1];
if (idx >= this.Tags.Length) Array.Resize(ref _tags, idx + 1);
this._tags[idx] = value;
return true;
}
public void ClearValue(ushort defaultValue = 0)
{
if (_values != null)
for(int i = 0; i < _values.Length;i++)
_values[i] = defaultValue;
}
public void ClearTitle(string defaultValue = "")
{
if (_values != null)
for (int i = 0; i < _titles.Length; i++)
_titles[i] = defaultValue;
}
public void ClearTag(string defaultValue = "")
{
if (_tags != null)
for (int i = 0; i < _tags.Length; i++)
_tags[i] = defaultValue;
}
public void setValue(ushort value)
{
for(int i = 0; i < _values.Length;i++)
this._values[i] = value;
}
public void setItemEnable(int idx, bool value)
{
if (idx >= _values.Length || idx >= this.Items.Length) return;
this.Items[idx].Enable = value;
}
/// <summary>
/// 지정된 컬러태그값을 입력한다.
/// </summary>
/// <param name="idx"></param>
/// <param name="tagString"></param>
/// <returns></returns>
public Boolean setValue(int idx, string tagString)
{
//동일태그값을 찾는다
if (idx >= _values.Length) return false;
int value = -1;
for (int i = 0; i < ColorList.Length; i++)
if (ColorList[i].Remark.ToLower() == tagString.ToLower())
{
value = i;
break;
}
if (value != -1)
{
this._values[idx] = (ushort)value;
this.Items[idx].Enable = true;
return true;
}
else return false;
}
public Boolean setValue(int idx, bool value)
{
return setValue(idx, (ushort)(value ? 1 : 0));
}
public Boolean setValue(int row, int col, ushort value)
{
var idx = row * this.ColumnCount + col;
return setValue(idx, value);
}
public Boolean setValue(int row, int col, int value)
{
var idx = row * this.ColumnCount + col;
return setValue(idx, (ushort)value);
}
public Boolean setValueToggle(int row, int col, ushort value1,ushort value2)
{
var idx = row * this.ColumnCount + col;
if(getValue(idx) == value1) return setValue(idx, value2);
else return setValue(idx, value1);
}
public Boolean setValue(int row, int col, bool value)
{
var idx = row * this.ColumnCount + col;
return setValue(idx, (ushort)(value ? 1 : 0));
}
public Boolean setValue(int row, int col, string value)
{
var idx = row * this.ColumnCount + col;
return setValue(idx, value);
}
public ushort getValue(int idx)
{
if (idx >= _values.Length) return 0;
return _values[idx];
}
public ushort getValue(int row, int col)
{
var idx = row * this.ColumnCount + col;
return getValue(idx);
}
[Category("arFrame")]
public bool ShowIndexString { get { return _showIndexString; } set { _showIndexString = value; Invalidate(); } }
[Category("arFrame"), DisplayName("테두리 굵기")]
public int BorderSize { get { return bordersize; } set { this.bordersize = value; Invalidate(); } }
[Category("arFrame"), DisplayName("메뉴 테두리 굵기")]
public int MenuBorderSize { get { return menubordersize; } set { this.menubordersize = value; Invalidate(); } }
[Category("arFrame"), DisplayName("메뉴 간격")]
public int MenuGap { get { return menugap; } set { this.menugap = value; RemakeChartRect(); Invalidate(); } }
[Category("arFrame"), DisplayName("글자를 이미지 다음에 표시"), Description("이미지가 있는 경우 해당 이미지 옆에 글자를 붙입니다")]
public Boolean TextAttachToImage { get { return textattachtoimage; } set { this.textattachtoimage = value; Invalidate(); } }
[Category("arFrame"), DisplayName("색상-테두리")]
public System.Drawing.Color BorderColor { get { return bordercolor; } set { this.bordercolor = value; Invalidate(); } }
[Category("arFrame"), DisplayName("내부 여백")]
public new System.Windows.Forms.Padding Padding { get { return padding; } set { this.padding = value; RemakeChartRect(); Invalidate(); } }
[Category("arFrame"), DisplayName("색상-전체배경색")]
public override System.Drawing.Color BackColor { get { return backcolor; } set { this.backcolor = value; Invalidate(); } }
[Category("arFrame"), DisplayName("색상-글자(그림자)")]
public System.Drawing.Color ShadowColor { get { return _shadowColor; } set { _shadowColor = value; this.Invalidate(); } }
[Category("arFrame"), DisplayName("색상-글자")]
public override Color ForeColor { get { return base.ForeColor; } set { base.ForeColor = value; } }
[Category("arFrame"), DisplayName("색상-글자(번호)")]
public Color ForeColorPin { get { return foreColorPin; } set { foreColorPin = value; } }
[Category("arFrame"), DisplayName("글꼴-번호")]
public Font FontPin { get { return fontPin; } set { fontPin = value; Invalidate(); } }
[Category("arFrame"), DisplayName("글꼴-항목")]
public override Font Font { get { return base.Font; } set { base.Font = value; Invalidate(); } }
private int mouseOverItemIndex = -1;
public GridView()
{
InitializeComponent();
// Set Optimized Double Buffer to reduce flickering
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
// Redraw when resized
this.SetStyle(ControlStyles.ResizeRedraw, true);
//값과 이름은 외부의 값을 사용한다
ResetArray();
if (MinimumSize.Width == 0 || MinimumSize.Height == 0)
MinimumSize = new Size(100, 50);
}
void ResetArray()
{
if (this._values != null) Array.Resize(ref this._values, itemCount);// = new UInt16[itemCount];
// if (this._titles != null) Array.Resize(ref this._titles, itemCount);//
// if (this._names != null) Array.Resize(ref this._names, itemCount);//
}
int itemCount { get { return ColumnCount * RowCount; } }
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
RemakeChartRect();
}
public event EventHandler<ItemClickEventArgs> ItemClick;
public class ItemClickEventArgs : EventArgs
{
public int idx { get; set; }
public GridViewItem Item { get; set; }
public ItemClickEventArgs(int idx_, GridViewItem item)
{
this.Item = item;
this.idx = idx_;
}
}
protected override void OnMouseClick(MouseEventArgs e)
{
//마우스클릭시 해당 버튼을 찾아서 반환한다.
if (Items == null || Items.Length < 1) return;
for (int i = 0; i < Items.Length; i++)
{
var rect = Items[i].rect;//[i];
if (rect.Contains(e.Location))
{
var menu = Items[i];
//미사용개체는 이벤트를 아에 발생하지 않는다
if (menu.Enable == true && ItemClick != null)
ItemClick(this, new ItemClickEventArgs(i, menu));
break;
}
}
}
protected override void OnMouseLeave(EventArgs e)
{
this.mouseOverItemIndex = -1;
this.Invalidate();
}
protected override void OnMouseMove(MouseEventArgs e)
{
if (Items == null || Items.Length < 1)
{
this.mouseOverItemIndex = -1;
return;
}
for (int i = 0; i < Items.Length; i++)
{
var rect = Items[i].rect;// rects[i];
if (rect.Contains(e.Location))
{
if (i != mouseOverItemIndex)
{
mouseOverItemIndex = i;
this.Invalidate();
}
break;
}
}
}
public void setItemTextAlign(int row, int col, System.Drawing.ContentAlignment TextAlign)
{
var item = this.Items.Where(t => t.row == row && t.col == col).FirstOrDefault();
if (item != null) item.TextAlign = TextAlign;
}
public void setItemTextAlign(System.Drawing.ContentAlignment TextAlign)
{
foreach (var item in this.Items)
item.TextAlign = TextAlign;
}
protected override void OnPaint(PaintEventArgs pe)
{
//배경그리기
//using (var sb = new System.Drawing.Drawing2D.LinearGradientBrush(DisplayRectangle, BackColor, BackColor2On, System.Drawing.Drawing2D.LinearGradientMode.Vertical))
pe.Graphics.FillRectangle(new SolidBrush(BackColor), DisplayRectangle);
if (Items == null)
{
pe.Graphics.DrawString("no items", this.Font, Brushes.Red, 100, 100);
return;
}
var items = Items.OrderBy(t => t.No);
foreach (var menu in items)
{
drawItem(menu.idx, pe.Graphics);
}
//테두리 그리기
if (BorderSize > 0)
{
pe.Graphics.DrawRectangle(new Pen(this.BorderColor, BorderSize),
this.DisplayRectangle.Left,
this.DisplayRectangle.Top,
this.DisplayRectangle.Width - 1,
this.DisplayRectangle.Height - 1);
}
}
public void drawItem(int itemIndex, Graphics g = null)
{
if (g == null) g = this.CreateGraphics();
var menu = this.Items[itemIndex];
if (menu.rect == RectangleF.Empty) return;
var rect = menu.rect;// rects[i];
var diplayText = string.Empty;
//타이틀이 줄번호별로 처리됨
if (_titles != null && menu.row < _titles.Length && _titles[menu.row] != null )
{
var linebif = _titles[menu.row].Split('|');
if (menu.col < linebif.Length)
diplayText = linebif[menu.col];
}
UInt16 Value = 0;
if (_values != null && menu.idx < _values.Length) Value = _values[menu.idx];
//배경이 투명이 아니라면 그린다.
var bgColor1 = Color.FromArgb(30, 30, 30);// BackColor1Off;
var bgColor2 = Color.FromArgb(30, 30, 30);// BackColor2Off;
//해당 값에 따른 컬러값을 읽는다.
if (ColorList != null && Value < ColorList.Length)
{
bgColor1 = this.ColorList[Value].BackColor1;
bgColor2 = this.ColorList[Value].BackColor2;
}
using (var sb = new System.Drawing.Drawing2D.LinearGradientBrush(rect, bgColor1, bgColor2, System.Drawing.Drawing2D.LinearGradientMode.Vertical))
g.FillRectangle(sb, rect);
// if (mouseOverItemIndex == menu.idx)
// this.Cursor = Cursors.Hand;
// else
// this.Cursor = Cursors.Arrow;
//테두리를 그리는 속성과 트기가 설정된 경우에만 표시
//if (mouseOverItemIndex == i)
// {
// pe.Graphics.DrawRectangle(new Pen(Color.DeepSkyBlue), rect.Left, rect.Top, rect.Width, rect.Height);
//}
//else
{
if (MenuBorderSize > 0)
{
using (var p = new Pen(BorderColor, MenuBorderSize))
g.DrawRectangle(p, rect.Left, rect.Top, rect.Width, rect.Height);
}
}
//인덱스번호 출력
if (ShowIndexString && _names != null && menu.idx < _names.Length)
{
//표시글자
var idxstr = string.Format("[{0}] {1}", menu.idx, _names[menu.idx]);
//그림자 추가
if (ShadowColor != System.Drawing.Color.Transparent)
g.DrawString(idxstr, FontPin, new SolidBrush(ShadowColor), menu.rect.Left + 4, menu.rect.Top + 4);
//일반글자표시
g.DrawString(idxstr, FontPin, new SolidBrush(this.ForeColorPin), menu.rect.Left + 3, menu.rect.Top + 3);
}
if (diplayText != "")
{
using (StringFormat sf = new StringFormat(StringFormatFlags.NoClip))
{
//글자를 텍스트 이후에 붙이는 거라면?
if (menu.TextAlign == ContentAlignment.BottomCenter || menu.TextAlign == ContentAlignment.BottomLeft ||
menu.TextAlign == ContentAlignment.BottomRight) sf.LineAlignment = StringAlignment.Far;
else if (menu.TextAlign == ContentAlignment.MiddleCenter || menu.TextAlign == ContentAlignment.MiddleLeft ||
menu.TextAlign == ContentAlignment.MiddleRight) sf.LineAlignment = StringAlignment.Center;
else if (menu.TextAlign == ContentAlignment.TopCenter || menu.TextAlign == ContentAlignment.TopLeft ||
menu.TextAlign == ContentAlignment.TopRight) sf.LineAlignment = StringAlignment.Near;
if (menu.TextAlign == ContentAlignment.BottomCenter || menu.TextAlign == ContentAlignment.MiddleCenter ||
menu.TextAlign == ContentAlignment.TopCenter) sf.Alignment = StringAlignment.Center;
else if (menu.TextAlign == ContentAlignment.BottomLeft || menu.TextAlign == ContentAlignment.MiddleLeft ||
menu.TextAlign == ContentAlignment.TopLeft) sf.Alignment = StringAlignment.Near;
else if (menu.TextAlign == ContentAlignment.BottomRight || menu.TextAlign == ContentAlignment.MiddleRight ||
menu.TextAlign == ContentAlignment.TopRight) sf.Alignment = StringAlignment.Far;
//그림자 추가
if (ShadowColor != System.Drawing.Color.Transparent)
g.DrawString(diplayText, this.Font, new SolidBrush(ShadowColor),
new RectangleF((float)(rect.Left + 1f), (float)(rect.Top + 1f), (float)rect.Width, (float)rect.Height), sf);
g.DrawString(diplayText, this.Font, new SolidBrush(ForeColor), rect, sf);
}
}
if (showDebugInfo)
{
g.DrawString(Value.ToString(), this.fontPin, Brushes.SkyBlue, rect.Left, rect.Top);
}
}
/// <summary>
/// arFrame 전용 속성값을 복사 합니다
/// </summary>
/// <param name="ctl"></param>
public void copyTo(GridView ctl)
{
ctl.backcolor = this.backcolor;
ctl.menugap = this.menugap;
ctl.Items = this.Items;
ctl.menubordersize = this.menubordersize;
ctl.padding = this.padding;
ctl.ForeColor = this.ForeColor;
ctl.Font = this.Font;
ctl.TextAttachToImage = this.TextAttachToImage;
ctl.bordercolor = this.bordercolor;
ctl.bordersize = this.bordersize;
}
public void RemakeChartRect()
{
if (DisplayRectangle == Rectangle.Empty) return;
double x = 0;
double y = 0;
double w = DisplayRectangle.Width / (ColumnCount * 1.0);
double h = DisplayRectangle.Height / (RowCount * 1.0);
if (this.Items == null || itemCount != this.Items.Length)
{
//아이템갯수가 달라졌으므로 다시 갱신해야함
GridViewItem[] item = new GridViewItem[RowCount * ColumnCount];
for (int r = 0; r < RowCount; r++)
{
for (int c = 0; c < ColumnCount; c++)
{
int idx = r * ColumnCount + c;
item[idx] = new GridViewItem(idx, r, c);
item[idx].Enable = false;
item[idx].Padding = new Padding(0, 0, 0, 0);
item[idx].TextAlign = ContentAlignment.MiddleCenter;
x = (c * w);
y = (r * h);
item[idx].rect = new RectangleF((float)x, (float)y, (float)w, (float)h);
}
}
this.Items = item;
}
else
{
//아이템의 갯수는 같으므로 좌표값만 변경해준다.
for (int r = 0; r < RowCount; r++)
{
for (int c = 0; c < ColumnCount; c++)
{
int idx = r * ColumnCount + c;
var item = Items[idx];
x = (c * w);
y = (r * h);
item.Dirty = true;
item.rect = new RectangleF((float)x, (float)y, (float)w, (float)h);
}
}
}
this.Invalidate();
//int i = 0;
//var menuList = this.Items.OrderBy(t => t.No).ToArray();
//foreach (var menu in menuList)
//{
// int x, y, w, h;
// // var menu = menus[i];
// var mWidth = menuwidth;
// if (menu.MenuWidth > 0) mWidth = menu.MenuWidth;
// w = mWidth;
// h = DisplayRectangle.Height - Padding.Top - Padding.Bottom;
// if (menu.isRightMenu)
// {
// x = DisplayRectangle.Right - Padding.Right - (rightAcc) - (MenuGap * rightIdx);
// y = DisplayRectangle.Top + Padding.Top;
// rightAcc += 0;// = 0;// x;
// rightIdx += 1;
// }
// else
// {
// x = DisplayRectangle.Left + Padding.Left + leftAcc + (MenuGap * leftIdx);
// y = DisplayRectangle.Top + Padding.Top;
// leftAcc += mWidth;
// leftIdx += 1;
// }
// rects[i] = new Rectangle(x, y, w, h);
// i += 1;
//}
}
}
}

View File

@@ -0,0 +1,36 @@
namespace arFrame.Control
{
partial class MenuControl
{
/// <summary>
/// 필수 디자이너 변수입니다.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 사용 중인 모든 리소스를 정리합니다.
/// </summary>
/// <param name="disposing">관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region
/// <summary>
/// 디자이너 지원에 필요한 메서드입니다.
/// 이 메서드의 내용을 코드 편집기로 수정하지 마십시오.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
}
}

View File

@@ -0,0 +1,676 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
namespace arFrame.Control
{
public partial class MenuControl : System.Windows.Forms.Control
{
private int bordersize = 0;
private int menubordersize = 1;
private int menuwidth = 100;
private int menugap = 5;
private System.Windows.Forms.Padding padding = new Padding(3, 3, 3, 3);
private System.Drawing.Color backcolor = System.Drawing.Color.White;
private System.Drawing.Color backcolor2 = System.Drawing.Color.Gainsboro;
private System.Drawing.Color bordercolor = System.Drawing.Color.Black;
private Boolean enablemenubakcolor = false;
private Boolean enablemenuborder = false;
private Boolean textattachtoimage = true;
[Category("arFrame"), DisplayName("메뉴")]
public MenuItem[] menus { get; set; }
private Rectangle[] rects = null;
[Category("arFrame"), DisplayName("테두리 굵기")]
public int BorderSize { get { return bordersize; } set { this.bordersize = value; Invalidate(); } }
[Category("arFrame"), DisplayName("메뉴 테두리 굵기")]
public int MenuBorderSize { get { return menubordersize; } set { this.menubordersize = value; Invalidate(); } }
[Category("arFrame"), DisplayName("메뉴 너비")]
public int MenuWidth { get { return menuwidth; } set { this.menuwidth = value; RemakeChartRect(); Invalidate(); } }
[Category("arFrame"), DisplayName("메뉴 간격")]
public int MenuGap { get { return menugap; } set { this.menugap = value; RemakeChartRect(); Invalidate(); } }
[Category("arFrame"), DisplayName("기능-메뉴별 배경색")]
public Boolean EnableMenuBackColor { get { return enablemenubakcolor; } set { this.enablemenubakcolor = value; Invalidate(); } }
[Category("arFrame"), DisplayName("기능-메뉴별 테두리")]
public Boolean EnableMenuBorder { get { return enablemenuborder; } set { this.enablemenuborder = value; Invalidate(); } }
[Category("arFrame"), DisplayName("글자를 이미지 다음에 표시"), Description("이미지가 있는 경우 해당 이미지 옆에 글자를 붙입니다")]
public Boolean TextAttachToImage { get { return textattachtoimage; } set { this.textattachtoimage = value; Invalidate(); } }
[Category("arFrame"), DisplayName("이미지 표시 여백(좌,상)")]
public System.Drawing.Point ImagePadding { get; set; }
[Category("arFrame"), DisplayName("이미지 표시 크기(너비,높이)")]
public System.Drawing.Size ImageSize { get; set; }
[Category("arFrame"), DisplayName("색상-테두리")]
public System.Drawing.Color BorderColor { get { return bordercolor; } set { this.bordercolor = value; Invalidate(); } }
[Category("arFrame"), DisplayName("내부 여백")]
public new System.Windows.Forms.Padding Padding { get { return padding; } set { this.padding = value; RemakeChartRect(); Invalidate(); } }
[Category("arFrame"), DisplayName("색상-배경1")]
public override System.Drawing.Color BackColor { get { return backcolor; } set { this.backcolor = value; Invalidate(); } }
[Category("arFrame"), DisplayName("색상-배경2")]
public System.Drawing.Color BackColor2 { get { return backcolor2; } set { this.backcolor2 = value; Invalidate(); } }
[Category("arFrame"), DisplayName("색상-글자")]
public override Color ForeColor { get { return base.ForeColor; } set { base.ForeColor = value; } }
private int mouseOverItemIndex = -1;
public MenuControl()
{
InitializeComponent();
// Set Optimized Double Buffer to reduce flickering
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
// Redraw when resized
this.SetStyle(ControlStyles.ResizeRedraw, true);
ImagePadding = new System.Drawing.Point(0, 0);
ImageSize = new System.Drawing.Size(24, 24);
if (MinimumSize.Width == 0 || MinimumSize.Height == 0)
MinimumSize = new Size(100, 50);
}
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
RemakeChartRect();
}
public event EventHandler<MenuEventArgs> ItemClick;
public class MenuEventArgs : EventArgs
{
public string Command { get; set; }
public int idx { get; set; }
public MenuEventArgs(string cmd_, int idx_)
{
this.Command = cmd_;
this.idx = idx_;
}
}
protected override void OnMouseClick(MouseEventArgs e)
{
// if(DesignMode)
// {
// if(e.Button == System.Windows.Forms.MouseButtons.Right)
// {
// System.Windows.Forms.MessageBox.Show("Sdf");
// }
// }
// else
{
//마우스클릭시 해당 버튼을 찾아서 반환한다.
if (menus == null || menus.Length < 1) return;
for (int i = 0; i < menus.Length; i++)
{
var rect = rects[i];
if (rect.Contains(e.Location))
{
var menu = menus[i];
//미사용개체는 이벤트를 아에 발생하지 않는다
if (menu.Enable == true && ItemClick != null)
ItemClick(this, new MenuEventArgs(menu.Command, i));
break;
}
}
}
}
protected override void OnMouseLeave(EventArgs e)
{
this.mouseOverItemIndex = -1;
this.Invalidate();
}
protected override void OnMouseMove(MouseEventArgs e)
{
if (menus == null || menus.Length < 1)
{
this.mouseOverItemIndex = -1;
return;
}
for (int i = 0; i < menus.Length; i++)
{
var rect = rects[i];
if (rect.Contains(e.Location))
{
if (i != mouseOverItemIndex)
{
mouseOverItemIndex = i;
this.Invalidate();
}
break;
}
}
}
protected override void OnPaint(PaintEventArgs pe)
{
// if(DesignMode)
// {
// pe.Graphics.FillRectangle(Brushes.Red, this.DisplayRectangle);
// }
//else
{
//배경그리기
using (var sb = new System.Drawing.Drawing2D.LinearGradientBrush(DisplayRectangle, BackColor, BackColor2, System.Drawing.Drawing2D.LinearGradientMode.Vertical))
pe.Graphics.FillRectangle(sb, DisplayRectangle);
}
//테두리 그리기
if (BorderSize > 0)
{
pe.Graphics.DrawRectangle(new Pen(this.BorderColor, BorderSize),
this.DisplayRectangle.Left,
this.DisplayRectangle.Top,
this.DisplayRectangle.Width - 1,
this.DisplayRectangle.Height - 1);
}
//커서모양
if (mouseOverItemIndex == -1) this.Cursor = Cursors.Arrow;
else this.Cursor = Cursors.Hand;
if (rects == null) RemakeChartRect();
if (rects != null && rects.Length > 0)
{
StringFormat sf = new StringFormat(StringFormatFlags.NoClip);
var items = menus.OrderBy(t => t.No);
int i = 0;
foreach (var menu in items)
{
var rect = rects[i];
//배경이 투명이 아니라면 그린다.
if (mouseOverItemIndex == i)
{
//마우스오버된놈이다.
using (var sb = new System.Drawing.Drawing2D.LinearGradientBrush(rect, Color.FromArgb(100, Color.LightSkyBlue), Color.FromArgb(100, Color.DeepSkyBlue), System.Drawing.Drawing2D.LinearGradientMode.Vertical))
pe.Graphics.FillRectangle(sb, rect);
}
else
{
if (this.enablemenubakcolor == true && menu.BackColor != System.Drawing.Color.Transparent && menu.BackColor2 != System.Drawing.Color.Transparent)
{
using (var sb = new System.Drawing.Drawing2D.LinearGradientBrush(rect, menu.BackColor, menu.BackColor2, System.Drawing.Drawing2D.LinearGradientMode.Vertical))
pe.Graphics.FillRectangle(sb, rect);
}
}
//이미지표시
int ix, iy, iw, ih;
ix = iy = iw = ih = 0;
if (menu.Image != null)
{
ix = rect.Left;
iy = rect.Top;
iw = ImageSize.Width;
ih = ImageSize.Height;
if (menu.ImageAlign == ContentAlignment.BottomCenter || menu.ImageAlign == ContentAlignment.BottomLeft ||
menu.ImageAlign == ContentAlignment.BottomRight) iy += DisplayRectangle.Bottom - ih;
else if (menu.ImageAlign == ContentAlignment.MiddleCenter || menu.ImageAlign == ContentAlignment.MiddleLeft ||
menu.ImageAlign == ContentAlignment.MiddleRight) iy += (int)(DisplayRectangle.Top + ((rect.Height - ih) / 2.0));
else if (menu.ImageAlign == ContentAlignment.TopCenter || menu.ImageAlign == ContentAlignment.TopLeft ||
menu.ImageAlign == ContentAlignment.TopRight) iy += DisplayRectangle.Top;
if (menu.ImageAlign == ContentAlignment.BottomCenter || menu.ImageAlign == ContentAlignment.MiddleCenter ||
menu.ImageAlign == ContentAlignment.TopCenter) ix += (int)(DisplayRectangle.Left + ((rect.Width - iw) / 2.0));
else if (menu.ImageAlign == ContentAlignment.BottomLeft || menu.ImageAlign == ContentAlignment.MiddleLeft ||
menu.ImageAlign == ContentAlignment.TopLeft) ix += DisplayRectangle.Left;
else if (menu.ImageAlign == ContentAlignment.BottomRight || menu.ImageAlign == ContentAlignment.MiddleRight ||
menu.ImageAlign == ContentAlignment.TopRight) ix += DisplayRectangle.Right - iw;
if (menu.ImagePadding.X != 0 || menu.ImagePadding.Y != 0)
{
ix += menu.ImagePadding.X;
iy += menu.ImagePadding.Y;
}
else
{
ix += ImagePadding.X;
iy += ImagePadding.Y;
}
if (menu.ImageSize.Width != 0 && menu.ImageSize.Height != 0)
{
iw = menu.ImageSize.Width;
ih = menu.ImageSize.Height;
}
pe.Graphics.DrawImage(menu.Image,
new Rectangle(ix, iy, iw, ih));
}
//테두리를 그리는 속성과 트기가 설정된 경우에만 표시
if (mouseOverItemIndex == i)
{
pe.Graphics.DrawRectangle(new Pen(Color.DeepSkyBlue), rect);
}
else
{
if (EnableMenuBorder && MenuBorderSize > 0)
{
using (var p = new Pen(menu.BorderColor, MenuBorderSize))
pe.Graphics.DrawRectangle(p, rect);
}
}
//글자를 텍스트 이후에 붙이는 거라면?
if (menu.Image != null && TextAttachToImage)
{
var fsize = pe.Graphics.MeasureString(menu.Text, this.Font);
pe.Graphics.DrawString(menu.Text, this.Font, new SolidBrush(menu.ForeColor),
(float)(ix + iw + 1),
(float)(iy + ((ih - fsize.Height) / 2.0)));
}
else
{
if (menu.TextAlign == ContentAlignment.BottomCenter || menu.TextAlign == ContentAlignment.BottomLeft ||
menu.TextAlign == ContentAlignment.BottomRight) sf.LineAlignment = StringAlignment.Far;
else if (menu.TextAlign == ContentAlignment.MiddleCenter || menu.TextAlign == ContentAlignment.MiddleLeft ||
menu.TextAlign == ContentAlignment.MiddleRight) sf.LineAlignment = StringAlignment.Center;
else if (menu.TextAlign == ContentAlignment.TopCenter || menu.TextAlign == ContentAlignment.TopLeft ||
menu.TextAlign == ContentAlignment.TopRight) sf.LineAlignment = StringAlignment.Near;
if (menu.TextAlign == ContentAlignment.BottomCenter || menu.TextAlign == ContentAlignment.MiddleCenter ||
menu.TextAlign == ContentAlignment.TopCenter) sf.Alignment = StringAlignment.Center;
else if (menu.TextAlign == ContentAlignment.BottomLeft || menu.TextAlign == ContentAlignment.MiddleLeft ||
menu.TextAlign == ContentAlignment.TopLeft) sf.Alignment = StringAlignment.Near;
else if (menu.TextAlign == ContentAlignment.BottomRight || menu.TextAlign == ContentAlignment.MiddleRight ||
menu.TextAlign == ContentAlignment.TopRight) sf.Alignment = StringAlignment.Far;
pe.Graphics.DrawString(menu.Text, this.Font, new SolidBrush(menu.ForeColor), rect, sf);
}
i += 1;
}
sf.Dispose();
}
//if(DesignMode)
//{
// pe.Graphics.DrawString("deisgn", this.Font, Brushes.Red, 1, 1);
//}
}
/// <summary>
/// arFrame 전용 속성값을 복사 합니다
/// </summary>
/// <param name="ctl"></param>
public void copyTo(MenuControl ctl)
{
ctl.backcolor = this.backcolor;
ctl.backcolor2 = this.BackColor2;
ctl.MenuWidth = this.menuwidth;
ctl.menugap = this.menugap;
ctl.menus = this.menus;
ctl.menubordersize = this.menubordersize;
ctl.padding = this.padding;
ctl.ForeColor = this.ForeColor;
ctl.Font = this.Font;
ctl.EnableMenuBackColor = this.EnableMenuBackColor;
ctl.EnableMenuBorder = this.EnableMenuBorder;
ctl.ImagePadding = this.ImagePadding;
ctl.ImageSize = this.ImageSize;
ctl.TextAttachToImage = this.TextAttachToImage;
ctl.bordercolor = this.bordercolor;
ctl.bordersize = this.bordersize;
}
public void Save(string File)
{
//xml로 데이터를 저장자
System.Text.StringBuilder NewXml = new System.Text.StringBuilder();
NewXml.AppendLine("<?xml version='1.0' encoding='UTF-8'?>");
NewXml.AppendLine("<tindevil create='" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "'> ");
NewXml.AppendLine("</tindevil>");
if (System.IO.File.Exists(File)) System.IO.File.Delete(File);
System.IO.File.WriteAllText(File, NewXml.ToString().Replace('\'', '\"'), System.Text.Encoding.UTF8);
var vDocu = new XmlDocument();
vDocu.Load(File);
//var nsmgr = new XmlNamespaceManager(new System.Xml.NameTable());
//nsmgr.AddNamespace("x", "http://tindevil.com");
var Root = vDocu.DocumentElement;
//저장하려는 속성목록을 먼저 생성한다
//미사용 목록이 너무 많아서 그렇게 함
foreach (var m in this.GetType().GetMethods())
{
var mName = m.Name.ToLower();
if (mName.StartsWith("get_") == false || mName == "get_menus") continue;
var pt = this.GetType().GetProperty(m.Name.Substring(4));
if (pt != null)
{
var categoryName = GetCategoryName(pt);
if (categoryName.ToLower() != "arframe") continue;
//자료형에따라서 그값을 변경한다
var value = m.Invoke(this, null);
var newNode = vDocu.CreateElement(pt.Name);// m.Name.Substring(4));
newNode.InnerText = getValueString(m, value);
Root.AppendChild(newNode);
}
}
foreach (var item in this.menus.OrderBy(t => t.No))
{
var node = vDocu.CreateElement("Item");
var attNo = vDocu.CreateAttribute("No");
attNo.Value = item.No.ToString();
node.Attributes.Append(attNo);
foreach (var m in item.GetType().GetMethods())
{
var mName = m.Name.ToLower();
if (mName.StartsWith("get_") == false || mName == "get_no") continue;
var value = m.Invoke(item, null);
var sNode = vDocu.CreateElement(m.Name.Substring(4));
sNode.InnerText = getValueString(m, value);
node.AppendChild(sNode);
}
Root.AppendChild(node);
}
vDocu.Save(File);
}
public void Load(string File)
{
if (System.IO.File.Exists(File) == false) return;
List<MenuItem> NewMenu = new List<MenuItem>();
var vDocu = new XmlDocument();
vDocu.Load(File);
var Root = vDocu.DocumentElement; //루트요소(Tindevil)
//저장하려는 속성목록을 먼저 생성한다
//미사용 목록이 너무 많아서 그렇게 함
foreach (var m in this.GetType().GetMethods())
{
var mName = m.Name.ToLower();
if (mName.StartsWith("get_") == false || mName == "get_menus") continue;
var methodName = m.Name.Substring(4);
var pt = this.GetType().GetProperty(methodName);
if (pt != null)
{
var categoryName = GetCategoryName(pt);
if (categoryName.ToLower() != "arframe") continue;
//SEt명령이 있어야 사용이 가능하다
var setMethod = this.GetType().GetMethod("set_" + methodName);
if (setMethod == null) continue;
//값을 읽어온다
var Node = Root.SelectSingleNode(methodName);
if (Node != null)
{
var strValue = Node.InnerText;
var value = getValueFromString(m.ReturnType, strValue); // setValueString(m.ReturnType, setMethod, strValue);
setMethod.Invoke(this, new object[] { value });
}
}
}
//foreach (var item in this.menus.OrderBy(t => t.No))
//{
// var node = vDocu.CreateElement("Item");
// var attNo = vDocu.CreateAttribute("No");
// attNo.Value = item.No.ToString();
// node.Attributes.Append(attNo);
// foreach (var m in item.GetType().GetMethods())
// {
// var mName = m.Name.ToLower();
// if (mName.StartsWith("get_") == false || mName == "get_no") continue;
// var value = m.Invoke(item, null);
// var sNode = vDocu.CreateElement(m.Name.Substring(4));
// sNode.InnerText = getValueString(m, value);
// node.AppendChild(sNode);
// }
// Root.AppendChild(node);
//}
}
private string getValueString(System.Reflection.MethodInfo m, object value)
{
var strValue = "";
string valuetype = m.ReturnType.Name.ToLower();
if (m.ReturnType == typeof(System.Drawing.Color))
strValue = ((System.Drawing.Color)value).ToArgb().ToString();
else if (m.ReturnType == typeof(System.Drawing.Rectangle))
{
var rect = (System.Drawing.Rectangle)value;
strValue = string.Format("{0};{1};{2};{3}", rect.Left, rect.Top, rect.Width, rect.Height);
}
else if (m.ReturnType == typeof(System.Drawing.RectangleF))
{
var rectf = (System.Drawing.RectangleF)value;
strValue = string.Format("{0};{1};{2};{3}", rectf.Left, rectf.Top, rectf.Width, rectf.Height);
}
else if (m.ReturnType == typeof(Boolean))
{
strValue = ((Boolean)value) ? "1" : "0";
}
else if (m.ReturnType == typeof(System.Drawing.Point))
{
var pt1 = (Point)value;
strValue = string.Format("{0};{1}", pt1.X, pt1.Y);
}
else if (m.ReturnType == typeof(System.Drawing.PointF))
{
var ptf = (PointF)value;
strValue = string.Format("{0};{1}", ptf.X, ptf.Y);
}
else if (m.ReturnType == typeof(System.Drawing.Size))
{
var sz = (Size)value;
strValue = string.Format("{0};{1}", sz.Width, sz.Height);
}
else if (m.ReturnType == typeof(System.Drawing.SizeF))
{
var szf = (SizeF)value;
strValue = string.Format("{0};{1}", szf.Width, szf.Height);
}
else if (m.ReturnType == typeof(System.Drawing.Bitmap))
{
var bitmap = (Bitmap)value;
// Convert the image to byte[]
System.IO.MemoryStream stream = new System.IO.MemoryStream();
bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp);
byte[] imageBytes = stream.ToArray();
strValue = Convert.ToBase64String(imageBytes);
}
else if (m.ReturnType == typeof(System.Windows.Forms.Padding))
{
var pd = (System.Windows.Forms.Padding)value;
strValue = string.Format("{0};{1};{2};{3}", pd.Left, pd.Top, pd.Right, pd.Bottom);
}
else
strValue = value.ToString();
return strValue;
}
private object getValueFromString(Type ReturnType, string strValue)
{
if (ReturnType == typeof(System.Drawing.Color))
{
var cint = int.Parse(strValue);
return System.Drawing.Color.FromArgb(cint);
}
else if (ReturnType == typeof(System.Drawing.Rectangle))
{
var buf = strValue.Split(';');
var x = int.Parse(buf[0]);
var y = int.Parse(buf[1]);
var w = int.Parse(buf[2]);
var h = int.Parse(buf[3]);
return new Rectangle(x, y, w, h);
}
else if (ReturnType == typeof(System.Drawing.RectangleF))
{
var buf = strValue.Split(';');
var x = float.Parse(buf[0]);
var y = float.Parse(buf[1]);
var w = float.Parse(buf[2]);
var h = float.Parse(buf[3]);
return new RectangleF(x, y, w, h);
}
else if (ReturnType == typeof(Boolean))
{
return strValue == "1";
}
else if (ReturnType == typeof(System.Drawing.Point))
{
var buf = strValue.Split(';');
var x = int.Parse(buf[0]);
var y = int.Parse(buf[1]);
return new Point(x, y);
}
else if (ReturnType == typeof(System.Drawing.PointF))
{
var buf = strValue.Split(';');
var x = float.Parse(buf[0]);
var y = float.Parse(buf[1]);
return new PointF(x, y);
}
else if (ReturnType == typeof(System.Drawing.Size))
{
var buf = strValue.Split(';');
var x = int.Parse(buf[0]);
var y = int.Parse(buf[1]);
return new Size(x, y);
}
else if (ReturnType == typeof(System.Drawing.SizeF))
{
var buf = strValue.Split(';');
var x = float.Parse(buf[0]);
var y = float.Parse(buf[1]);
return new SizeF(x, y);
}
else if (ReturnType == typeof(System.Drawing.Bitmap))
{
//문자을을 바이트로 전환다
byte[] imageBytes = Convert.FromBase64String(strValue);
Bitmap retval = null;
using (System.IO.MemoryStream stream = new System.IO.MemoryStream(imageBytes))
retval = new Bitmap(stream);
return retval;
}
else if (ReturnType == typeof(System.Windows.Forms.Padding))
{
var buf = strValue.Split(';');
var x = int.Parse(buf[0]);
var y = int.Parse(buf[1]);
var w = int.Parse(buf[2]);
var h = int.Parse(buf[3]);
return new Padding(x, y, w, h);
}
else if (ReturnType == typeof(Int16)) return Int16.Parse(strValue);
else if (ReturnType == typeof(Int32)) return Int32.Parse(strValue);
else if (ReturnType == typeof(Int64)) return Int64.Parse(strValue);
else if (ReturnType == typeof(UInt16)) return UInt16.Parse(strValue);
else if (ReturnType == typeof(UInt32)) return UInt32.Parse(strValue);
else
return strValue;
}
public string GetCategoryName(System.Reflection.PropertyInfo m)
{
var displayName = m
.GetCustomAttributes(typeof(CategoryAttribute), true)
.FirstOrDefault() as CategoryAttribute;
if (displayName != null)
return displayName.Category;
return "";
}
public string GetDisplayName(System.Reflection.MethodInfo m)
{
var displayName = m
.GetCustomAttributes(typeof(DisplayNameAttribute), true)
.FirstOrDefault() as DisplayNameAttribute;
if (displayName != null)
return displayName.DisplayName;
return "";
}
public void RemakeChartRect()
{
if (rects != null) rects = null;
if (menus == null || menus.Length < 1) return;
rects = new Rectangle[menus.Length];
int leftIdx = 0;
int rightIdx = 0;
int leftAcc = 0;
int rightAcc = 0;
int i = 0;
var menuList = this.menus.OrderBy(t => t.No).ToArray();
foreach (var menu in menuList)
{
int x, y, w, h;
// var menu = menus[i];
var mWidth = menuwidth;
if (menu.MenuWidth > 0) mWidth = menu.MenuWidth;
w = mWidth;
h = DisplayRectangle.Height - Padding.Top - Padding.Bottom;
if (menu.isRightMenu)
{
x = DisplayRectangle.Right - Padding.Right - (rightAcc) - (MenuGap * rightIdx);
y = DisplayRectangle.Top + Padding.Top;
rightAcc += 0;// = 0;// x;
rightIdx += 1;
}
else
{
x = DisplayRectangle.Left + Padding.Left + leftAcc + (MenuGap * leftIdx);
y = DisplayRectangle.Top + Padding.Top;
leftAcc += mWidth;
leftIdx += 1;
}
rects[i] = new Rectangle(x, y, w, h);
i += 1;
}
}
}
}

View File

@@ -0,0 +1,69 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
namespace arFrame.Control
{
[TypeConverterAttribute(typeof(ExpandableObjectConverter))]
public class MenuItem
{
[Category("arFrame"),DisplayName("메뉴이름")]
public string Text { get; set; }
[Category("arFrame"), DisplayName("색상-테두리"), Description("메뉴속성의 테두리 기능이 켜져야 합니다")]
public System.Drawing.Color BorderColor { get; set; }
[Category("arFrame"),DisplayName("색상-배경1"),Description("메뉴속성의 배경 기능이 켜져야 합니다")]
public System.Drawing.Color BackColor { get; set; }
[Category("arFrame"), DisplayName("색상-배경2"), Description("메뉴속성의 배경 기능이 켜져야 합니다")]
public System.Drawing.Color BackColor2 { get; set; }
[Category("arFrame"),DisplayName("색상-글자")]
public System.Drawing.Color ForeColor { get; set; }
[Category("arFrame"),DisplayName("메뉴 구분자로 사용합니다")]
public Boolean isSeparate { get; set; }
[Category("arFrame"),DisplayName("오른쪽 붙임")]
public Boolean isRightMenu { get; set; }
[Category("arFrame"),DisplayName("실행 명령")]
public string Command { get; set; }
[Category("arFrame"),DisplayName("아이콘 이미지")]
public System.Drawing.Bitmap Image { get; set; }
[Category("arFrame"),DisplayName("글자 정렬 방식")]
public System.Drawing.ContentAlignment TextAlign { get; set; }
[Category("arFrame"),DisplayName("이미지 정렬 방식")]
public System.Drawing.ContentAlignment ImageAlign { get; set; }
[Category("arFrame"),DisplayName("글자 여백")]
public System.Windows.Forms.Padding Padding { get; set; }
[Category("arFrame"),DisplayName("메뉴 사용여부"),Description("활성화시 메뉴의 클릭이벤트가 발생하지 않습니다")]
public Boolean Enable { get; set; }
[Category("arFrame"),DisplayName("이미지 표시 여백(좌,상)")]
public System.Drawing.Point ImagePadding { get; set; }
[Category("arFrame"),DisplayName("이미지 표시 크기(너비,높이)")]
public System.Drawing.Size ImageSize { get; set; }
[Category("arFrame"),DisplayName("메뉴 간격")]
public int MenuWidth { get; set; }
[Category("arFrame"),DisplayName("번호")]
public int No { get; set; }
public MenuItem()
{
Enable = true;
BorderColor = System.Drawing.Color.FromArgb(20, 20, 20);
BackColor = System.Drawing.Color.DimGray;
BackColor2 = System.Drawing.Color.FromArgb(100, 100, 100);
ForeColor = System.Drawing.Color.Black;
Text = "Menu";
isRightMenu = false;
Command = string.Empty;
Image = null;
isSeparate = false;
TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
Padding = new System.Windows.Forms.Padding(0, 0, 0, 0);
ImagePadding = new System.Drawing.Point(0, 0);
ImageSize = new System.Drawing.Size(0, 0);
MenuWidth = 0;
No = 0;
}
}
}

View File

@@ -0,0 +1,36 @@
namespace arFrame.Control
{
partial class MotCommandButton
{
/// <summary>
/// 필수 디자이너 변수입니다.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 사용 중인 모든 리소스를 정리합니다.
/// </summary>
/// <param name="disposing">관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region
/// <summary>
/// 디자이너 지원에 필요한 메서드입니다.
/// 이 메서드의 내용을 코드 편집기로 수정하지 마십시오.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
}
}

View File

@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace arFrame.Control
{
public partial class MotCommandButton : Button
{
public enum eCommand
{
AbsoluteMove = 0,
RelativeMove ,
AcceptPosition
}
public MotCommandButton()
{
InitializeComponent();
motCommand = eCommand.AbsoluteMove;
motValueControl = null;
motAccControl = null;
motSpdControl = null;
}
public MotValueNumericUpDown motValueControl { get; set; }
public MotValueNumericUpDown motAccControl { get; set; }
public MotValueNumericUpDown motSpdControl { get; set; }
public eCommand motCommand { get; set; }
}
}

View File

@@ -0,0 +1,36 @@
namespace arFrame.Control
{
partial class MotLinkLabel
{
/// <summary>
/// 필수 디자이너 변수입니다.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 사용 중인 모든 리소스를 정리합니다.
/// </summary>
/// <param name="disposing">관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region
/// <summary>
/// 디자이너 지원에 필요한 메서드입니다.
/// 이 메서드의 내용을 코드 편집기로 수정하지 마십시오.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
}
}

View File

@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace arFrame.Control
{
public partial class MotLinkLabel : System.Windows.Forms.LinkLabel
{
public MotLinkLabel()
{
InitializeComponent();
this.LinkColor = Color.Chartreuse;
}
public MotValueNumericUpDown motValueControl { get; set; }
}
}

View File

@@ -0,0 +1,36 @@
namespace arFrame.Control
{
partial class MotValueNumericUpDown
{
/// <summary>
/// 필수 디자이너 변수입니다.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 사용 중인 모든 리소스를 정리합니다.
/// </summary>
/// <param name="disposing">관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region
/// <summary>
/// 디자이너 지원에 필요한 메서드입니다.
/// 이 메서드의 내용을 코드 편집기로 수정하지 마십시오.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
}
}

View File

@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace arFrame.Control
{
public partial class MotValueNumericUpDown : NumericUpDown
{
public MotValueNumericUpDown()
{
InitializeComponent();
MotionIndex = -1;
}
public int MotionIndex { get; set; }
}
}

View File

@@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
namespace arFrame.Control
{
[TypeConverterAttribute(typeof(ExpandableObjectConverter))]
public class MotITem
{
public int idx { get; private set; }
[Category("arFrame"), DisplayName("Tag")]
public string Tag { get; set; }
[Category("arFrame"), DisplayName("글자 정렬 방식")]
public System.Drawing.ContentAlignment TextAlign { get; set; }
[Category("arFrame"), DisplayName("글자 여백")]
public System.Windows.Forms.Padding Padding { get; set; }
[Category("arFrame"), DisplayName("메뉴 사용여부"), Description("활성화시 메뉴의 클릭이벤트가 발생하지 않습니다")]
public Boolean Enable { get; set; }
public string Text { get; set; }
public Boolean Dirty { get; set; }
public System.Drawing.Rectangle[] subRect = null;
//모션 상태값
public Boolean[] State;
public double Position { get; set; }
public double PositionCmd { get; set; }
public System.Drawing.Color PositionColor { get; set; }
public System.Drawing.RectangleF rect { get; set; }
[Category("arFrame"), DisplayName("번호")]
public int No { get; set; }
public MotITem(int idx_)
{
this.Dirty = true;
PositionColor = System.Drawing.Color.White;
subRect = new System.Drawing.Rectangle[6];
rect = System.Drawing.RectangleF.Empty;
Enable = true;
this.idx = idx_;
TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
Padding = new System.Windows.Forms.Padding(0, 0, 0, 0);
No = 0;
this.Text = string.Empty;
this.Enable = true;
this.State = new bool[] { false,false,false,false,false,false};
Position = 0;
PositionCmd = 0;
}
}
}

View File

@@ -0,0 +1,36 @@
namespace arFrame.Control
{
partial class MotionDisplay
{
/// <summary>
/// 필수 디자이너 변수입니다.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 사용 중인 모든 리소스를 정리합니다.
/// </summary>
/// <param name="disposing">관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region
/// <summary>
/// 디자이너 지원에 필요한 메서드입니다.
/// 이 메서드의 내용을 코드 편집기로 수정하지 마십시오.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
}
}

View File

@@ -0,0 +1,306 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace arFrame.Control
{
public partial class MotionDisplay : System.Windows.Forms.Control
{
private Color[] colorB1 = new Color[] {
Color.MediumSeaGreen,
Color.DeepSkyBlue,
Color.Tomato,
Color.Purple,
Color.Tomato,
Color.FromArgb(40,40,40)
};
private Color[] colorB2 = new Color[] {
Color.SeaGreen,
Color.SteelBlue,
Color.Red,
Color.Indigo,
Color.Red,
Color.FromArgb(30,30,30)
};
private StringFormat sf = new StringFormat();
private string[] IndiName = new string[] { "INP","ORG","LIM","HST","ALM","" };
public MotITem[] Items;
private int _colcount = 3;
private int _rowcount = 2;
private Color _bordercolor = Color.Black;
private Color _gridcolor = Color.FromArgb(50, 50, 50);
private int _bordersize = 1;
private Padding _padding;
private string _postionformat = "";
private int _headerHeight = 16;
private Font _headerfont = new Font("Consolas",7f);
private int itemCount { get { return _colcount * _rowcount; } }
public new Font Font { get { return base.Font; } set { base.Font = value; this.Invalidate(); } }
public Font HeaderFont { get { return _headerfont; } set { _headerfont = value; this.Invalidate(); } }
public int HeaderHeight { get { return _headerHeight; } set { _headerHeight = value; RemakeChartRect(); this.Invalidate(); } }
public new Padding Padding { get { if (_padding == null) return Padding.Empty; else return _padding; } set { _padding = value; RemakeChartRect(); Invalidate(); } }
public int ColumnCount { get { return _colcount; } set { _colcount = value; ResetArray(); RemakeChartRect(); } }
public int RowCount { get { return _rowcount; } set { _rowcount = value; ResetArray(); RemakeChartRect(); } }
public int BorderSize { get { return _bordersize; } set { _bordersize = value; Invalidate(); } }
public Color BorderColor { get { return _bordercolor; } set { _bordercolor = value; Invalidate(); } }
public string PositionDisplayFormat { get { return _postionformat; } set { _postionformat = value; Invalidate(); } }
public Color GridColor { get { return _gridcolor; } set { _gridcolor = value; Invalidate(); } }
public new Boolean Enabled { get { return base.Enabled; } set { base.Enabled = value; Invalidate(); } }
public MotionDisplay()
{
InitializeComponent();
// Set Optimized Double Buffer to reduce flickering
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
// Redraw when resized
this.SetStyle(ControlStyles.ResizeRedraw, true);
sf.LineAlignment = StringAlignment.Center;
sf.Alignment = StringAlignment.Center;
//값과 이름은 외부의 값을 사용한다
ResetArray();
if (MinimumSize.Width == 0 || MinimumSize.Height == 0)
MinimumSize = new Size(100, 50);
}
void ResetArray()
{
}
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
RemakeChartRect();
}
public void RemakeChartRect()
{
if (DisplayRectangle == Rectangle.Empty) return;
var baseRect = new Rectangle(
DisplayRectangle.Left + _padding.Left,
DisplayRectangle.Top + _padding.Top,
DisplayRectangle.Width - _padding.Left - _padding.Right,
DisplayRectangle.Height - _padding.Top - _padding.Bottom);
double x = 0;
double y = 0;
double w = baseRect.Width / (_colcount * 1.0);
double h = baseRect.Height / (_rowcount * 1.0);
if (this.Items == null || itemCount != this.Items.Length)
{
//아이템갯수가 달라졌으므로 다시 갱신해야함
var item = new MotITem[RowCount * ColumnCount];
for (int r = 0; r < RowCount; r++)
{
for (int c = 0; c < ColumnCount; c++)
{
int idx = r * ColumnCount + c;
item[idx] = new MotITem(idx);
item[idx].Enable = false;
item[idx].Padding = new Padding(0, 0, 0, 0);
item[idx].TextAlign = ContentAlignment.MiddleCenter;
x = baseRect.Left + (c * w);
y = baseRect.Top + (r * h);
item[idx].rect = new RectangleF((float)x, (float)y, (float)w, (float)h);
item[idx].Dirty = true;
}
}
this.Items = item;
}
else
{
//아이템의 갯수는 같으므로 좌표값만 변경해준다.
for (int r = 0; r < RowCount; r++)
{
for (int c = 0; c < ColumnCount; c++)
{
int idx = r * ColumnCount + c;
var item = Items[idx];
x = (c * w);
y = (r * h);
item.rect = new RectangleF((float)x, (float)y, (float)w, (float)h);
item.Dirty = true;
}
}
}
this.Invalidate();
}
protected override void OnPaint(PaintEventArgs pe)
{
//배경그리기
//using (var sb = new System.Drawing.Drawing2D.LinearGradientBrush(DisplayRectangle, BackColor, BackColor2On, System.Drawing.Drawing2D.LinearGradientMode.Vertical))
pe.Graphics.FillRectangle(new SolidBrush(this.BackColor), DisplayRectangle);
if (Items == null)
{
pe.Graphics.DrawString("no items", this.Font, Brushes.Red, 100, 100);
return;
}
var items = Items.OrderBy(t => t.No);
foreach (var menu in items)
{
drawItem(menu.idx, pe.Graphics);
}
//테두리 그리기
if (BorderSize > 0)
{
pe.Graphics.DrawRectangle(new Pen(this.BorderColor, BorderSize),
this.DisplayRectangle.Left,
this.DisplayRectangle.Top,
this.DisplayRectangle.Width - 1,
this.DisplayRectangle.Height - 1);
}
}
private void drawItem(int itemIndex, Graphics g = null)
{
if (g == null) g = this.CreateGraphics();
var item = this.Items[itemIndex];
// g.DrawString("rect null", this.Font, Brushes.White, 100, 100);
if (item.rect == RectangleF.Empty) return;
var rect = item.rect;// rects[i];
var diplayText = item.Text;
//byte Value = 0;
//배경이 투명이 아니라면 그린다.
//var bgColor1 = Color.DarkBlue; //BackColor1Off;
//var bgColor2 = Color.Blue;// BackColor2Off;
//if (Value != 0 && item.Enable != false)
//{
// //bgColor1 = Value == 1 ? BackColor1On : BackColor1Err;
// //bgColor2 = Value == 1 ? BackColor2On : BackColor2Err;
//}
//using (var sb = new System.Drawing.Drawing2D.LinearGradientBrush(rect, bgColor1, bgColor2, System.Drawing.Drawing2D.LinearGradientMode.Vertical))
// g.FillRectangle(sb, rect);
// if (mouseOverItemIndex == menu.idx)
// this.Cursor = Cursors.Hand;
// else
// this.Cursor = Cursors.Arrow;
//테두리를 그리는 속성과 트기가 설정된 경우에만 표시
//if (mouseOverItemIndex == i)
// {
// pe.Graphics.DrawRectangle(new Pen(Color.DeepSkyBlue), rect.Left, rect.Top, rect.Width, rect.Height);
//}
//else
{
// using (var p = new Pen(BorderColor, 1))
// g.DrawRectangle(p, rect.Left, rect.Top, rect.Width, rect.Height);
}
//총 5개의 인디게이터와 하단에 위치값을 표시하는 영역이 있따.
//줄 영역은 50%비율로 처리함
if(item.Dirty)
{
//각 영역을 다시 그려줘야한다.
var indiWidth = rect.Width / 5.0;
// var indiHeight = rect.Height / 2.0;
for (int c = 0; c < 5; c++)
{
item.subRect[c] = new Rectangle((int)(c * indiWidth + item.rect.Left), (int)(item.rect.Top), (int)indiWidth, (int)HeaderHeight);
}
item.Dirty = false;
//위치값을 나타내는 영역
item.subRect[5] = new Rectangle((int)item.rect.Left, (int)(item.rect.Top + HeaderHeight), (int)rect.Width, (int)rect.Height - HeaderHeight );
}
for(int i = 0 ; i < item.subRect.Length;i++)
{
var B1 = colorB1[i];
var B2 = colorB2[i];
if (i < (item.subRect.Length - 1)) //상태표시칸은 현재 값에 따라서 색상을 달리한다
{
if ( this.Enabled == false || (item.State[i] == false && DesignMode == false))
{
B1 = Color.FromArgb(20,20,20);
B2 = Color.FromArgb(50,50,50);
}
}
var rt = item.subRect[i];
using (var br = new System.Drawing.Drawing2D.LinearGradientBrush(rt, B1, B2, System.Drawing.Drawing2D.LinearGradientMode.Vertical))
g.FillRectangle(br, rt);
// g.DrawRectangle(Pens.Yellow, rt);
if (i < (item.subRect.Length-1))
{
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Center;
g.DrawString(IndiName[i], HeaderFont, Brushes.White, rt, sf);
}
else
{
sf.LineAlignment = StringAlignment.Center;
sf.Alignment = StringAlignment.Far;
g.DrawString(item.Position.ToString(PositionDisplayFormat) + " [" + item.PositionCmd.ToString(PositionDisplayFormat) + "] ",
this.Font,
new SolidBrush(item.PositionColor),
rt,
sf);
}
}
//테두리선은 우측만 처리한다
for (int i = 0; i < item.subRect.Length ; i++)
{
var rt = item.subRect[i];
var x1 = rt.Right;
var y1 = rt.Top;
var x2 = rt.Right;
var y2 = rt.Bottom;
g.DrawLine(new Pen(GridColor), x1, y1, x2, y2);
}
var posRect = item.subRect[item.subRect.Length - 1];
g.DrawLine(new Pen(Color.Black,1), posRect.Left, posRect.Top, posRect.Right, posRect.Top);
//인덱스번호 출력
if (diplayText != "")
{
g.DrawString(string.Format("[{0}] {1}", item.idx, diplayText),
this.Font, new SolidBrush(this.ForeColor),
item.rect.Left + 3, item.rect.Top + 3);
}
}
}
}

View File

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 어셈블리의 일반 정보는 다음 특성 집합을 통해 제어됩니다.
// 어셈블리와 관련된 정보를 수정하려면
// 이 특성 값을 변경하십시오.
[assembly: AssemblyTitle("arFrameControl")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("arFrameControl")]
[assembly: AssemblyCopyright("Copyright © 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에
// 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면
// 해당 형식에 대해 ComVisible 특성을 true로 설정하십시오.
[assembly: ComVisible(false)]
// 이 프로젝트가 COM에 노출되는 경우 다음 GUID는 typelib의 ID를 나타냅니다.
[assembly: Guid("9fa3ef10-3c75-40a2-b3e6-a37900b26d0e")]
// 어셈블리의 버전 정보는 다음 네 가지 값으로 구성됩니다.
//
// 주 버전
// 부 버전
// 빌드 번호
// 수정 버전
//
// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 버전이 자동으로
// 지정되도록 할 수 있습니다.
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,103 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{A16C9667-5241-4313-888E-548375F85D29}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>arFrame.Control</RootNamespace>
<AssemblyName>arFrameControl</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="GridView\ColorListItem.cs" />
<Compile Include="MotCommandButton.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="MotCommandButton.Designer.cs">
<DependentUpon>MotCommandButton.cs</DependentUpon>
</Compile>
<Compile Include="MotionView\MotITem.cs" />
<Compile Include="GridView\GridView.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="GridView\GridView.Designer.cs">
<DependentUpon>GridView.cs</DependentUpon>
</Compile>
<Compile Include="MenuBar\MenuControl.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="MenuBar\MenuControl.Designer.cs">
<DependentUpon>MenuControl.cs</DependentUpon>
</Compile>
<Compile Include="GridView\GridItem.cs" />
<Compile Include="MenuBar\MenuItem.cs" />
<Compile Include="MotionView\MotionDisplay.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="MotionView\MotionDisplay.Designer.cs">
<DependentUpon>MotionDisplay.cs</DependentUpon>
</Compile>
<Compile Include="MotLinkLabel.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="MotLinkLabel.Designer.cs">
<DependentUpon>MotLinkLabel.cs</DependentUpon>
</Compile>
<Compile Include="MotValueNumericUpDown.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="MotValueNumericUpDown.Designer.cs">
<DependentUpon>MotValueNumericUpDown.cs</DependentUpon>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\arCtl\arControl.csproj">
<Project>{f31c242c-1b15-4518-9733-48558499fe4b}</Project>
<Name>arControl</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>