diff --git a/CodeList.cs b/CodeList.cs index 9c96dc1..c1027f8 100644 --- a/CodeList.cs +++ b/CodeList.cs @@ -24,7 +24,7 @@ namespace NewsCrawler override public string ToString() { - return string.Format("{0}:{1} ({2})", m_strCode, m_strName, m_enType); + return string.Format("{0}:{1}", m_strCode, m_strName); } } @@ -118,6 +118,16 @@ namespace NewsCrawler LoadCodeType(strPath, CODE_TYPE.DUPLICATED); } + public void AddDuplicatedList(string strCode, string strName) + { + CODE_VALUE Result = m_CodeList.Find(s => s.m_strCode == strCode); + if(Result != null) + Result.m_enType |= CODE_TYPE.DUPLICATED; + + string strPath = Util.GetConfigPath()+"/code-duplicated.txt"; + File.AppendAllText(strPath, strName+Environment.NewLine); + } + public void MakeManualList(int iPrice) { m_CodeList.ForEach(a => a.m_enType &= ~CODE_TYPE.MANUAL); diff --git a/Config.cs b/Config.cs index 92121a7..55b7294 100644 --- a/Config.cs +++ b/Config.cs @@ -15,6 +15,7 @@ namespace NewsCrawler public static void Init() { m_Data.Add("manual-price", "100000"); + m_Data.Add("buy-price", "1000000"); Load(); } @@ -24,8 +25,6 @@ namespace NewsCrawler if(File.Exists(strPath) == false) return; - m_Data.Clear(); - string[] aLines = File.ReadAllLines(strPath); foreach(string strLine in aLines) { @@ -36,7 +35,10 @@ namespace NewsCrawler if(aTokens.Length < 2) continue; - m_Data.Add(aTokens[0], aTokens[1]); + if(m_Data.ContainsKey(aTokens[0]) == true) + m_Data[aTokens[0]] = aTokens[1]; + else + m_Data.Add(aTokens[0], aTokens[1]); } } @@ -62,5 +64,18 @@ namespace NewsCrawler m_Data["manual-price"] = iPrice.ToString(); Save(); } + + public static int GetBuyPrice() + { + int iPrice; + int.TryParse(m_Data["buy-price"], out iPrice); + return iPrice; + } + + public static void SetBuyPrice(int iPrice) + { + m_Data["buy-price"] = iPrice.ToString(); + Save(); + } } } diff --git a/ConfigForm.Designer.cs b/ConfigForm.Designer.cs index 009e6aa..2cd1b06 100644 --- a/ConfigForm.Designer.cs +++ b/ConfigForm.Designer.cs @@ -54,6 +54,10 @@ this.btnDuplicatedCodeApply = new System.Windows.Forms.Button(); this.btnDuplicatedCodeEdit = new System.Windows.Forms.Button(); this.groupBox9 = new System.Windows.Forms.GroupBox(); + this.label1 = new System.Windows.Forms.Label(); + this.tbBuyPrice = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); + this.groupBox10 = new System.Windows.Forms.GroupBox(); this.groupBox1.SuspendLayout(); this.groupBox2.SuspendLayout(); this.groupBox6.SuspendLayout(); @@ -63,6 +67,7 @@ this.groupBox7.SuspendLayout(); this.groupBox8.SuspendLayout(); this.groupBox9.SuspendLayout(); + this.groupBox10.SuspendLayout(); this.SuspendLayout(); // // tbVolume @@ -144,7 +149,7 @@ this.groupBox2.Controls.Add(this.groupBox4); this.groupBox2.Location = new System.Drawing.Point(280, 12); this.groupBox2.Name = "groupBox2"; - this.groupBox2.Size = new System.Drawing.Size(262, 287); + this.groupBox2.Size = new System.Drawing.Size(262, 298); this.groupBox2.TabIndex = 10; this.groupBox2.TabStop = false; this.groupBox2.Text = "키워드"; @@ -336,11 +341,53 @@ this.groupBox9.TabStop = false; this.groupBox9.Text = "종목편집"; // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(9, 20); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(29, 12); + this.label1.TabIndex = 13; + this.label1.Text = "가격"; + // + // tbBuyPrice + // + this.tbBuyPrice.Location = new System.Drawing.Point(61, 17); + this.tbBuyPrice.Name = "tbBuyPrice"; + this.tbBuyPrice.Size = new System.Drawing.Size(107, 21); + this.tbBuyPrice.TabIndex = 12; + this.tbBuyPrice.Text = "1000000"; + this.tbBuyPrice.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; + this.tbBuyPrice.TextChanged += new System.EventHandler(this.tbBuyPrice_TextChanged); + this.tbBuyPrice.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.tbBuyPrice_KeyPress); + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(174, 20); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(17, 12); + this.label4.TabIndex = 14; + this.label4.Text = "원"; + // + // groupBox10 + // + this.groupBox10.Controls.Add(this.tbBuyPrice); + this.groupBox10.Controls.Add(this.label4); + this.groupBox10.Controls.Add(this.label1); + this.groupBox10.Location = new System.Drawing.Point(10, 264); + this.groupBox10.Name = "groupBox10"; + this.groupBox10.Size = new System.Drawing.Size(262, 46); + this.groupBox10.TabIndex = 15; + this.groupBox10.TabStop = false; + this.groupBox10.Text = "매수"; + // // ConfigForm // this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(548, 307); + this.ClientSize = new System.Drawing.Size(548, 320); + this.Controls.Add(this.groupBox10); this.Controls.Add(this.groupBox9); this.Controls.Add(this.groupBox2); this.Controls.Add(this.groupBox1); @@ -359,6 +406,8 @@ this.groupBox7.ResumeLayout(false); this.groupBox8.ResumeLayout(false); this.groupBox9.ResumeLayout(false); + this.groupBox10.ResumeLayout(false); + this.groupBox10.PerformLayout(); this.ResumeLayout(false); } @@ -390,5 +439,9 @@ private System.Windows.Forms.Button btnDuplicatedCodeApply; private System.Windows.Forms.Button btnDuplicatedCodeEdit; private System.Windows.Forms.GroupBox groupBox9; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox tbBuyPrice; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.GroupBox groupBox10; } } \ No newline at end of file diff --git a/ConfigForm.cs b/ConfigForm.cs index 0498702..a362054 100644 --- a/ConfigForm.cs +++ b/ConfigForm.cs @@ -18,6 +18,7 @@ namespace NewsCrawler private void ConfigForm_Load(object sender, EventArgs e) { tbVolume.Text = Config.GetManualPrice().ToString(); + tbBuyPrice.Text = Config.GetBuyPrice().ToString(); } private void OpenFile(string strName) @@ -109,5 +110,19 @@ namespace NewsCrawler m_Listener.ApplySynonym(); } #endregion + + #region Buy + private void tbBuyPrice_KeyPress(object sender, KeyPressEventArgs e) + { + e.Handled = !char.IsDigit(e.KeyChar); + } + + private void tbBuyPrice_TextChanged(object sender, EventArgs e) + { + int iPrice; + bool bNumber = int.TryParse(tbBuyPrice.Text, out iPrice); + Config.SetBuyPrice(iPrice); + } + #endregion } } diff --git a/CybosHelper.cs b/CybosHelper.cs index a05d914..b3c2f72 100644 --- a/CybosHelper.cs +++ b/CybosHelper.cs @@ -2,36 +2,94 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading; using System.Threading.Tasks; namespace NewsCrawler { public class CybosHelper { - CPUTILLib.CpCybos m_CPUtil = new CPUTILLib.CpCybos(); + CPUTILLib.CpCybos m_CPCybos = new CPUTILLib.CpCybos(); + CPFORETRADELib.CpForeTdUtil m_CPUtil = new CPFORETRADELib.CpForeTdUtil(); + DSCBO1Lib.StockMst m_CPStockMst = new DSCBO1Lib.StockMst(); + CPTRADELib.CpTd0311 m_CP0311 = new CPTRADELib.CpTd0311(); + bool m_bInitialized = false; + string m_strAccountNumber; public CybosHelper() { + short iResult = m_CPUtil.TradeInit(); + switch(iResult) + { + case -1: + Util.Log(Util.LOG_TYPE.ERROR, "[TradeInit] 오류"); + break; + + case 0: + m_bInitialized = true; + Util.Log(Util.LOG_TYPE.VERVOSE, "[TradeInit] 로그인 되었습니다"); + break; + + case 1: + Util.Log(Util.LOG_TYPE.ERROR, "[TradeInit] 업무 키 입력 잘못됨"); + break; + + case 2: + Util.Log(Util.LOG_TYPE.ERROR, "[TradeInit] 계좌 비밀번호가 잘못되었습니다"); + break; + + case 3: + Util.Log(Util.LOG_TYPE.ERROR, "[TradeInit] 취소되었습니다"); + break; + } + + m_strAccountNumber = m_CPUtil.AccountNumber[0]; + Util.Log(Util.LOG_TYPE.VERVOSE, string.Format("{0}개의 계좌 중 첫번째 계좌 {1}이 선택되었습니다", m_CPUtil.AccountNumber.Length, m_strAccountNumber)); } public int GetLimitRemainCountTrace() { - return m_CPUtil.GetLimitRemainCount(CPUTILLib.LIMIT_TYPE.LT_TRADE_REQUEST); + return m_CPCybos.GetLimitRemainCount(CPUTILLib.LIMIT_TYPE.LT_TRADE_REQUEST); } public int GetLimitRemainCountRQ() { - return m_CPUtil.GetLimitRemainCount(CPUTILLib.LIMIT_TYPE.LT_NONTRADE_REQUEST); + return m_CPCybos.GetLimitRemainCount(CPUTILLib.LIMIT_TYPE.LT_NONTRADE_REQUEST); } public int GetLimitRemainCountSB() { - return m_CPUtil.GetLimitRemainCount(CPUTILLib.LIMIT_TYPE.LT_SUBSCRIBE); + return m_CPCybos.GetLimitRemainCount(CPUTILLib.LIMIT_TYPE.LT_SUBSCRIBE); } public bool IsConnected() { - return (m_CPUtil.IsConnect==1); + return (m_CPCybos.IsConnect==1); + } + + public void Buy(CodeList.CODE_VALUE Code, int iMaxPrice) + { + if(m_bInitialized == false) + { + Util.Log(Util.LOG_TYPE.ERROR, "[Buy] 매수 준비가 되지 않았습니다"); + return; + } + + m_CPStockMst.SetInputValue(0, Code.m_strCode); + m_CPStockMst.BlockRequest2(0); + int iCurPrice = m_CPStockMst.GetHeaderValue(13); + + int iCount = iMaxPrice/iCurPrice; + + m_CP0311.SetInputValue(0, 2); + m_CP0311.SetInputValue(1, m_strAccountNumber); + m_CP0311.SetInputValue(3, Code.m_strCode); + m_CP0311.SetInputValue(4, iCount); + m_CP0311.SetInputValue(5, 0); + m_CP0311.SetInputValue(8, "03"); + m_CP0311.BlockRequest2(0); + + Util.Log(Util.LOG_TYPE.BUY, string.Format("code:{0} {1}주 현재가 {2}원, 시장가 매수", Code.ToString(), iCount, iCurPrice)); } } } diff --git a/ModelessPopup.Designer.cs b/ModelessPopup.Designer.cs new file mode 100644 index 0000000..f967b22 --- /dev/null +++ b/ModelessPopup.Designer.cs @@ -0,0 +1,86 @@ +namespace NewsCrawler +{ + partial class ModelessPopup + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if(disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.btnYes = new System.Windows.Forms.Button(); + this.btnCancel = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // btnYes + // + this.btnYes.Location = new System.Drawing.Point(123, 67); + this.btnYes.Name = "btnYes"; + this.btnYes.Size = new System.Drawing.Size(75, 23); + this.btnYes.TabIndex = 0; + this.btnYes.Text = "예"; + this.btnYes.UseVisualStyleBackColor = true; + this.btnYes.Click += new System.EventHandler(this.btnYes_Click); + // + // btnCancel + // + this.btnCancel.Location = new System.Drawing.Point(204, 67); + this.btnCancel.Name = "btnCancel"; + this.btnCancel.Size = new System.Drawing.Size(75, 23); + this.btnCancel.TabIndex = 1; + this.btnCancel.Text = "취소"; + this.btnCancel.UseVisualStyleBackColor = true; + this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(12, 9); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(38, 12); + this.label1.TabIndex = 2; + this.label1.Text = "label1"; + // + // ModelessPopup + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(291, 102); + this.Controls.Add(this.label1); + this.Controls.Add(this.btnCancel); + this.Controls.Add(this.btnYes); + this.Name = "ModelessPopup"; + this.Text = "수동종목"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button btnYes; + private System.Windows.Forms.Button btnCancel; + private System.Windows.Forms.Label label1; + } +} \ No newline at end of file diff --git a/ModelessPopup.cs b/ModelessPopup.cs new file mode 100644 index 0000000..77f507a --- /dev/null +++ b/ModelessPopup.cs @@ -0,0 +1,42 @@ +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 NewsCrawler +{ + public partial class ModelessPopup : Form + { + NewsForm m_Owner = null; + CodeList.CODE_VALUE m_Code; + + public ModelessPopup(NewsForm Owner) + { + m_Owner = Owner; + + InitializeComponent(); + } + + public void SetMessage(string strMsg, CodeList.CODE_VALUE Code) + { + m_Code = Code; + label1.Text = strMsg; + } + + private void btnYes_Click(object sender, EventArgs e) + { + m_Owner.OnManualItemBuy(m_Code); + this.Close(); + } + + private void btnCancel_Click(object sender, EventArgs e) + { + this.Close(); + } + } +} diff --git a/ModelessPopup.resx b/ModelessPopup.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/ModelessPopup.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/NewsCrawler.csproj b/NewsCrawler.csproj index b3f31b4..f7ad9c3 100644 --- a/NewsCrawler.csproj +++ b/NewsCrawler.csproj @@ -98,6 +98,12 @@ ConfigForm.cs + + Form + + + ModelessPopup.cs + Form @@ -111,6 +117,9 @@ ConfigForm.cs + + ModelessPopup.cs + NewsForm.cs diff --git a/NewsForm.Designer.cs b/NewsForm.Designer.cs index 62fb25c..b0e92f2 100644 --- a/NewsForm.Designer.cs +++ b/NewsForm.Designer.cs @@ -42,6 +42,7 @@ this.btnConfig = new System.Windows.Forms.Button(); this.splitContainer2 = new System.Windows.Forms.SplitContainer(); this.tbLog = new System.Windows.Forms.RichTextBox(); + this.chBuy = new System.Windows.Forms.CheckBox(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); this.splitContainer1.Panel1.SuspendLayout(); this.splitContainer1.Panel2.SuspendLayout(); @@ -205,11 +206,24 @@ this.tbLog.TabIndex = 0; this.tbLog.Text = ""; // + // chBuy + // + this.chBuy.Appearance = System.Windows.Forms.Appearance.Button; + this.chBuy.AutoSize = true; + this.chBuy.Location = new System.Drawing.Point(274, 1); + this.chBuy.Name = "chBuy"; + this.chBuy.Size = new System.Drawing.Size(39, 22); + this.chBuy.TabIndex = 9; + this.chBuy.Text = "매수"; + this.chBuy.UseVisualStyleBackColor = true; + this.chBuy.CheckedChanged += new System.EventHandler(this.chBuy_CheckedChanged); + // // NewsForm // this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(864, 829); + this.Controls.Add(this.chBuy); this.Controls.Add(this.splitContainer2); this.Controls.Add(this.btnConfig); this.Controls.Add(this.label1); @@ -248,6 +262,7 @@ private System.Windows.Forms.Button btnConfig; private System.Windows.Forms.SplitContainer splitContainer2; private System.Windows.Forms.RichTextBox tbLog; + private System.Windows.Forms.CheckBox chBuy; } } diff --git a/NewsForm.cs b/NewsForm.cs index a6cc9e0..19f383b 100644 --- a/NewsForm.cs +++ b/NewsForm.cs @@ -17,7 +17,7 @@ namespace NewsCrawler { public partial class NewsForm : Form { - CybosHelper m_CybosHelper = new CybosHelper(); + CybosHelper m_CybosHelper = null; CodeList m_CodeList = null; TextCondition m_Condition = null; ConfigForm m_ConfigForm = null; @@ -27,6 +27,7 @@ namespace NewsCrawler System.Timers.Timer m_CrawlTimer = new System.Timers.Timer(); int m_iCrawlInterval = 500; bool m_bBrowserReload = false; + bool m_bBuy = false; @@ -68,6 +69,8 @@ namespace NewsCrawler m_CrawlTimer.Interval=m_iCrawlInterval; m_CrawlTimer.Start(); + m_CybosHelper = new CybosHelper(); + Test(); } @@ -76,12 +79,26 @@ namespace NewsCrawler if(Util.IsDebugging() == false) return; - InsertItem("[test] 덕산하이메탈, 덕산네오룩스 66만여주 취득14:38", new DateTime(2016, 11, 30, 14, 38, 00), "http://www.asiae.co.kr/news/sokbo/sokbo_view.htm?idxno=2016112914371817318", "asiae", false); - InsertItem("[test] 자연과환경, 12월15일~22일 주주명부폐쇄14:19", new DateTime(2016, 11, 30, 14, 19, 00), "http://www.asiae.co.kr/news/sokbo/sokbo_view.htm?idxno=2016112914193170301", "asiae", false); - InsertItem("[test] 이엠코리아, 한국항공우주산업과 3억원 규모 공급계약14:06", new DateTime(2016, 11, 30, 14, 06, 00), "http://www.asiae.co.kr/news/sokbo/sokbo_view.htm?idxno=2016112914055964082", "asiae", false); + InsertItem("[test] 덕산하이메탈, 덕산네오룩스 66만여주 취득14:38", new DateTime(2016, 11, 30, 00, 00, 00), "http://www.asiae.co.kr/news/sokbo/sokbo_view.htm?idxno=2016112914371817318", "asiae", false); + InsertItem("[test] 자연과환경, 12월15일~22일 주주명부폐쇄14:19", new DateTime(2016, 11, 30, 00, 00, 00), "http://www.asiae.co.kr/news/sokbo/sokbo_view.htm?idxno=2016112914193170301", "asiae", false); + InsertItem("[test] 이엠코리아, 한국항공우주산업과 3억원 규모 공급계약14:06", new DateTime(2016, 11, 30, 00, 00, 00), "http://www.asiae.co.kr/news/sokbo/sokbo_view.htm?idxno=2016112914055964082", "asiae", false); } + private void BuyItem(CodeList.CODE_VALUE Code) + { + if(m_bBuy == false) + return; + + m_CybosHelper.Buy(Code, Config.GetBuyPrice()); + m_CodeList.AddDuplicatedList(Code.m_strCode, Code.m_strName); + } + + public void OnManualItemBuy(CodeList.CODE_VALUE Code) + { + BuyItem(Code); + } + void ProcessSearchAndBuy(string strTitle, string strRef) { CodeList.CODE_VALUE Code = m_CodeList.SearchCode(strTitle); @@ -102,11 +119,21 @@ namespace NewsCrawler else if((Code.m_enType&CodeList.CODE_TYPE.DENIAL) == CodeList.CODE_TYPE.MANUAL) Util.Log(Util.LOG_TYPE.MANUAL_CODE, string.Format("[{0}] {1} (keyword:{2}, code:{3})", strRef, strTitle, MatchResult.m_strKeyword, Code.ToString())); else + { Util.Log(Util.LOG_TYPE.POSITIVE, string.Format("[{0}] {1} (keyword:{2}, code:{3})", strRef, strTitle, MatchResult.m_strKeyword, Code.ToString())); + BuyItem(Code); + } break; case TextCondition.TYPE.MANUAL: Util.Log(Util.LOG_TYPE.MANUAL_KEYWORD, string.Format("[{0}] {1} (keyword:{2}, code:{3})", strRef, strTitle, MatchResult.m_strKeyword, Code.ToString())); + + if(m_bBuy == true) + { + ModelessPopup ManualPopup = new ModelessPopup(this); + ManualPopup.SetMessage(string.Format("{0} 매수하시겠습니까?", Code.ToString()), Code); + ManualPopup.Show(); + } break; case TextCondition.TYPE.NOT_MATCHED: @@ -673,6 +700,16 @@ namespace NewsCrawler { Util.Clear(); } + + private void chBuy_CheckedChanged(object sender, EventArgs e) + { + m_bBuy = chBuy.Checked; + + if(m_bBuy == true) + Util.Log(Util.LOG_TYPE.VERVOSE, "매수 시작"); + else + Util.Log(Util.LOG_TYPE.VERVOSE, "매수 취소"); + } } diff --git a/Util.cs b/Util.cs index 93a117f..df33c34 100644 --- a/Util.cs +++ b/Util.cs @@ -45,9 +45,9 @@ namespace NewsCrawler bool bInvoke = mainForm != null ? mainForm.InvokeRequired || LogBox.InvokeRequired : LogBox.InvokeRequired; - if(bInvoke) + if(LogBox.InvokeRequired) { - mainForm.Invoke(new InsertLogDelegate(InsertLog), LogBox, enType, strLog); + LogBox.Invoke(new InsertLogDelegate(InsertLog), LogBox, enType, strLog); } else { @@ -104,11 +104,13 @@ namespace NewsCrawler string strLogLevel = "["+enType+"] "; string strTime = DateTime.Now.ToString("[hh:mm:ss] "); - string strMessage = strTime+strLogLevel+strLog+Environment.NewLine; + string strMessage = strTime+strLogLevel+strLog; - File.AppendAllText(m_strLogFile, strMessage, new UTF8Encoding(true)); + File.AppendAllText(m_strLogFile, strMessage+Environment.NewLine, new UTF8Encoding(true)); if(m_LogBox != null) - InsertLog(m_LogBox, enType, strMessage); + InsertLog(m_LogBox, enType, strMessage+Environment.NewLine); + + Console.WriteLine(strMessage); } public static bool IsDebugging()