2017년 6월 8일 목요일

To support natural language for coordinate input.

BRCad can recognize natural language for coordinates input like following.

example 1 :
+ CDPoint {x=-0.15828156471252441 y=-1.0627467632293701 } CDPoint

example 2 :

x -0.15828156471252441 double
y -1.0627467632293701 double
+ __vfptr 0x0559f3b8 const CVector::`vftable' *
z 0.00000000000000000 double


When you input a coordinate for line or other geometry, paste or input a coordinate like following.



Then BRCad parse from string to valid coordinate and specify point.

See a following movie.

2017년 5월 23일 화요일

Pointer 변수의 array를 qsort를 사용해서 정렬하기

Pointer 변수의 array는 형변환이 살짝 복잡하게 보일수 있다.
Pointer의 Pointer가 qsort 함수에서 전달되므로 아래와 같이 형변환을 한다.

int CompareLayer(const void *a, const void *b)
{
CHg3DLayer *p1 = *(CHg3DLayer * const *)a;
CHg3DLayer *p2 = *(CHg3DLayer * const *)b;

return g_isAscending ? (p1->Compare(*p2, g_sortItem)) : (p2->Compare(*p1, g_sortItem));
}


2017년 5월 16일 화요일

MDI에서 창 선택을 탭으로 하는 방법

MDI 환경에서 창을 탭으로 분리하는 하려면 MainFrame이 만들어 질때 아래 코드만 추가하면 된다.

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CMDIFrameWndEx::OnCreate(lpCreateStruct) == -1)
return -1;

// 보관된 값에 따라 비주얼 관리자 및 스타일을 설정합니다.
OnApplicationLook(theApp.m_nAppLook);


CMDITabInfo mdiTabParams;
mdiTabParams.m_style = CMFCTabCtrl::STYLE_3D_ONENOTE; // 사용할 수 있는 다른 스타일...
mdiTabParams.m_bActiveTabCloseButton = TRUE;      // FALSE로 설정하여 탭 영역 오른쪽에 닫기 단추를 배치합니다.
mdiTabParams.m_bTabIcons = FALSE;    // TRUE로 설정하여 MDI 탭의 문서 아이콘을 활성화합니다.
mdiTabParams.m_bAutoColor = TRUE;    // FALSE로 설정하여 MDI 탭의 자동 색 지정을 비활성화합니다.
mdiTabParams.m_bDocumentMenu = TRUE; // 탭 영역의 오른쪽 가장자리에 문서 메뉴를 활성화합니다.
EnableMDITabbedGroups(TRUE, mdiTabParams);

...
}

 새창을 만들면 탭이 자동으로 추가된다.


탭을 drag&drop하면 창이 분리된다.


2017년 4월 8일 토요일

[Arduino Uno R3] The doremi sound by buzer.

You can control the buzer sound tone using delay and digitalWrite.
The buzer tone is controlled by vibration period.
Following is vibration period for doremi.
C - 262
D - 294
E - 330
F - 349
G - 392
A - 440
B - 494
High C - 523
...

Demo


Code

#define DX 12
int abc[] = {262, 294, 330, 370, 392, 440, 494, 523};

// the setup routine runs once when you press reset:
void setup() {
  // initialize the digital pin as an output.
  pinMode(DX, OUTPUT);
}

// the loop routine runs over and over again forever:
void loop() {
  for(int i = 0; i < 8; i++)
  {
    mtone(DX, abc[i], 500); // abc[i] tone sound for 0.5 second
    delay(50);
  }
}

void mtone(int dx, int hz, unsigned long tm)
{
  unsigned long t = millis();
  unsigned long ns = (long)500000 / hz;
  
  // Repeats for tm milliseconds.
  // Sounds for tm milliseconds
  while(millis() - t < tm)
  {
    digitalWrite(dx, HIGH);
    delayMicroseconds(ns);
    digitalWrite(dx, LOW);
    delayMicroseconds(ns);
  }
}

Description

millics() : The function to get past time by milliseconds since starting Arduino.
tone() : It's a function provide by Arduion which is the same as mtone. So you can change the code mtone -> tone.

[Arduino Uno R3] LED brightness with digitalWrite.

You can control LED brightness with digitalWrite.
Normally, LED brightness with digitalWrite is regular.
If you want to control LED brightness, use delay function.

The time that LED is on is long, people will see the LED seems brighter.
Like following.

The right LED is brighter, because the time that LED is on is longer than the time that LED is off.
The left LED is more dark.

Following is code.
// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
int led = 13;

// the setup routine runs once when you press reset:
void setup() {
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);
}

// the loop routine runs over and over again forever:
void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(9);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1);               // wait for a second
}

[Arduino Uno R3] To use buzer by analogWrite.

It's very easy to use buzer.
Buzer can be connected to + and -.
By analogWrite, you should to send value 255/2 to buzer.
If you want stop buzer sound. you should to send value 0 to buzer.


Following is code to use buzer.
// you don't need to write any code into setup()
void setup() {

}

// the loop routine runs over and over again forever:
void loop() {
  analogWrite(9, 255/2);  // buzer sound 
  delay(1000);
  analogWrite(9,0);         // no buzer sound
  delay(1000);
}

[Arduino Uno R3] To turn on LED by each level using analogWrite.

You can turn on LED by each level using analogWrite.
analogWrite function has 2 parameter.
analogWrite function's first parameter is pinNumber and second parameter is value.
The value can has number from 0 to 255.
Following is electric circuit diagram.

From ~10 port to the resist and to LED.
The ports have a prefix '~' are analog output ports.

Next code is to send eletric from ~10 analog output port to LED.
// Pin 10 has an LED connected on most Arduino boards.
// give it a name:
int led = 10;

// the setup routine runs once when you press reset:
void setup() {
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);
}

// the loop routine runs over and over again forever:
void loop() {
  byte n = 5;
  for(int x = 0; x < 5; ++x)
  {
    analogWrite(10, x*255/n);
    delay(1000);
  }
}

2017년 4월 6일 목요일

[BRCad] BRCad v0.1

Most commercial cad programs are too heavy.  People like me who often use CAD program feel uncomfortable.

So I searched any free CAD program that very powerful. Because I need to manage some very big dwg file.
I found some free CAD program, but they could not satisfy me.

Finally, I decided to make CAD program for me.
It takes about 4 hours to make this program using Hg3D Engine in HaneeSoft.
Hg3D Engine is a graphics framework and easy to use and has many useful functions.

Also Hg3D Engine is used for BimRoad that I developed. It is very powerful engine.

Following is BRCad v0.1 demo.


In addition, I share a blog of BimRoad that developed using Hg3D.








2017년 4월 4일 화요일

[Arduino Uno R3] Electric flow with jumper wire, LED, resist.

1. Demo


2. Code

// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
int led = 13;

// the setup routine runs once when you press reset:
void setup() {
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);
}

// the loop routine runs over and over again forever:
void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(100);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(500);               // wait for a second
}

3. Description

 - Electric flow : From D31 on Arduino to GND on Arduino
 - Electric has to flow from + to - (GND). So it goes from D13 to + pin on Bread Board and to - leg on LED and to + leg on LED and to a resist and to - pin on Bread Board and to GND on Arduino.
 - Green arrows is showing to go to where electic flow.

[Arduino Uno R3] To send text string to Serial Monitor using Serial.

1. Demo


2. Code

// the setup routine runs once when you press reset:
void setup() {
  // initialize the serial
  Serial.begin(9600);
}

// the loop routine runs over and over again forever:
int i = 0;
void loop() {
Serial.write("*** Test(");
  Serial.print(i);
  Serial.write(") ***\n");
  delay(100);
i++;
}

3. Description

 - Serial communication is to display a text string. You can see the string on the serial monitor.
 - Serial.print and Serial.println
   : Serial.print is to display a text string without '\n'
   : Serial.println is to display a text string with '\n'. '\n' means next line.
 - Serial.write
   : Serial.write can have '\n' in the text string.


4. Arduino Simulator 

 - https://circuits.io/


2017년 4월 3일 월요일

[Arduino Uno R3] A basic example like "Hello world".

1. Demo



2. Code

// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
int led = 13;

// the setup routine runs once when you press reset:
void setup() {
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);
}

// the loop routine runs over and over again forever:
void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(150);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(150);               // wait for a second
}




[Development Story] GFtp v1.5 - Added progress form using BackgroundWorker that has a cancel button.

GFtp v1.5 has a Cancel button that can clicked while translating files.
This button is implemented using BackgroundWorker in C#.
First, I try to implement a cancel button function using modaless form.
But I failed. So I did googling and can find implementation about cancel button.
Link is following.
http://perschluter.com/show-progress-dialog-during-long-process-c-sharp/

Thanks to

Per Schlüter


1. Update list

 - Added a progress form that has a cancel button.

2. GFtp v1.5 demo

 - 

3. Code snippets

 - Required event handler.

  - backgroundWorker.DoWork
  - backgroundWorker.ProgressChanged
  - backgroundWorker.RunWorkerCompleted

 - backgroundWorker.DoWork

   The event handler is called by BackgroundWorker.RunWorkerAsync() call.
   This is running on thread. So you can work other things while running this event handler.
   I defined this event handler like following code.
this.backgroundWorker.DoWork += new System.ComponentModel.DoWorkEventHandler(this.backgroundWorker_DoWork);
 
   I implemented this event handler like following code that to translate files.
 // The backgroundWorker for upload and download
        void backgroundWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;

            // Get files of ftp
            string[] files;
            if(_ftpController.Upload == false)
                files   = ftpFileGridView.GetSelectedFiles();
            else
                files = fileGridView.GetSelectedFiles();

        
            // Translates files using ftpcontroler.
            // BackgroundWorker will changed percent while translating files.
            if (_ftpController.TranslateFiles(files, worker))
            {
                if (_ftpController.Upload == false)
                    RefreshFileGridViewOfCurrentDirectory();
                else
                    RefreshFtpFileGridView();

                if(worker.CancellationPending == true)
                    MessageBox.Show("Canceled.");
                else
                    MessageBox.Show("Completed.");
            }
            else
            {
                MessageBox.Show("Failed.");
            }
        }

 - backgroundWorker.ProgressChanged

   This event handler is called when progress percent changed.
   So I implemented this event handler for updateing progress bar.
        // When progress percent is changed, call this function
        void backgroundWorker_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
        {
            // title caption
            _progressForm.Text = "Translating " + _ftpController.CurrentTranslatingFile + "..." + " " + (e.ProgressPercentage.ToString() + "%");

            // label
            _progressForm.Message = _progressForm.Text;

            // progress bar percent.
            _progressForm.ProgressValue = e.ProgressPercentage;
        }


 - backgroundWorker.RunWorkerCompleted

   This event handler is called when backgroundWorker is done.
   I implemented this event handler for closing the progress form and refresh the file grid view.

        void backgroundWorker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
        {
            _progressForm.Close();

            RefreshFileGridViewOfCurrentDirectory();
        }

 - Cancel button in the progress form.

   Because file translating is running on thread, you can click the cancel button in the progress form that showing.
   If you click the cancel button then call the event handler for cancel.
   The cancel event handler stop backgroundWorker and display message box "Canceled".

        // when cancel button is clicked, call this function
        void _progressForm_Canceled(object sender, EventArgs e)
        {
            if (backgroundWorker.WorkerSupportsCancellation == true)
            {
                // Cancel the asynchronous operation.
                backgroundWorker.CancelAsync();

                // Close the AlertForm
                _progressForm.Close();

                RefreshFileGridViewOfCurrentDirectory();
            }
        }

   Also, the cancel event handler is set for event handler of cancel button in the progress form like following.

       _progressForm = new ProgressForm();
       _progressForm.Canceled += _progressForm_Canceled;

4. Etc

 - Souce code : https://github.com/gurum77/GFtp
 - Plan : File translating using thread.

2017년 3월 27일 월요일

[Inno setup] How to make a script that need no answer to select a destination directory.

If you want to make a inno setup script that need no answer to select a destination directory, you have to insert a following code in the [Setup] section.

[Setup]
DisableDirPage=yes

Then setup will make a destination directory automatically.

[Civil3D API] How to make autoloading install file for .NET assembly.

There are some way to make a autoloading install for .NET assembly.
1. The way to use .lsp file at startup.
2. The way to use PackageContents.xml at startup.

Now I will explain about second way.
Second way is most new way and recommanded way.

First, PackageContents.xml file has to be in ***.bundle directory in the %appdata%Autodesk/ApplicationPlugins.

And Other needed files like .dll or .png are in the ***.bundle directory or sub directory of one.

Most important things are  directory name and contents of PackageContents.xml.
Directory name has to include .bundle at the last.
packageContents.xml file has to include information about command what you need.
Last, if you want to make ribbon at loading assembly(.dll), you have to observe the following rule.
Rule.
  - You have to call a function to make ribbon at startup when SystemVariableChanged event is happened. And you have to delete that event handler method.
  - Reference following codes.
  public class InitializeKoreaModule : IExtensionApplication
    {
        public void Initialize()
        {
            Autodesk.AutoCAD.ApplicationServices.Application.SystemVariableChanged += Application_SystemVariableChanged;
        }

        void Application_SystemVariableChanged(object sender, Autodesk.AutoCAD.ApplicationServices.SystemVariableChangedEventArgs e)
        {
            if (Autodesk.Windows.ComponentManager.Ribbon != null)
            {
                //ok, create Ribbon
                LoadRibbon();
                //and remove the event handler
                Autodesk.AutoCAD.ApplicationServices.Application.SystemVariableChanged -= Application_SystemVariableChanged;
            }
        }

        public void Terminate()
        {

        }

        public void LoadRibbon()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;

            RibbonTab rbTabKorea = CreateRibbon("Korea");
            if (rbTabKorea == null)
            {
                return;
            }

            RibbonPanelSource rbPanelSuperelevation = CreateButtonPannel("Superelevation", rbTabKorea);
            if (rbPanelSuperelevation != null)
            {
                rbPanelSuperelevation.Items.Add(CreateButton("Superelevation\nPlanar Figure", "SPF", "HangilIT.C3DCountryKit.Resources.product-icon.png"));
//                rbPanelSuperelevation.Items.Add(new RibbonRowBreak());
            }

            RibbonPanelSource rbPanelEarthWork = CreateButtonPannel("Earth Work Carried Quantities", rbTabKorea);
            if (rbPanelEarthWork != null)
            {
                rbPanelEarthWork.Items.Add(CreateButton("Earth Work\nCalculation", "ECC", "HangilIT.C3DCountryKit.Resources.product-icon.png"));
                rbPanelEarthWork.Items.Add(CreateButton("Mass Curve", "MC", "HangilIT.C3DCountryKit.Resources.product-icon.png"));
                rbPanelEarthWork.Items.Add(CreateButton("Mass Haul", "MH", "HangilIT.C3DCountryKit.Resources.product-icon.png"));
            }
        }

        private RibbonTab CreateRibbon(string str)
        {
            // 리본 컨트롤 생성
            RibbonControl rc = ComponentManager.Ribbon;

            // 리본 탭 검색
            RibbonTab rt = rc.FindTab(str);
            if (rt == null)
            {
                // 리본 탭 생성
                rt = new RibbonTab();
                // 리본탭 정보
                rt.Title = str;
                rt.Id = str;
                // 리본 컨트롤에 리본탭 추가
                rc.Tabs.Add(rt);
            }
            
            // 리본탭 활성화
            rt.IsActive = true;

            return rt;
        }

        private RibbonPanelSource CreateButtonPannel(string str, RibbonTab rtab)
        {
            // 리본 패널 소스 생성
            RibbonPanelSource bp = new RibbonPanelSource();
            // 리본 패널 소스 정보
            bp.Title = str;
            // 리본 패널 생성
            RibbonPanel rp = new RibbonPanel();
            // 리본 패널에 리본 패널 소스 추가
            rp.Source = bp;
            // 리본 탭에 리본 패널 추가
            rtab.Panels.Add(rp);

            return bp;
        }

        private RibbonButton CreateButton(string str, string CommandParameter, string pngFile)
        {
            // 리본 버튼 생성
            RibbonButton button = new RibbonButton();
            // 리본 버튼 정보
            button.Text = str;
            button.Id = str;
            button.CommandParameter = CommandParameter; // name of the command
            button.ShowImage = true;
            button.ShowText = true;
            button.Size = RibbonItemSize.Large;
            button.Orientation = Orientation.Vertical;
            button.LargeImage = UtilityEtc.LoadImage(pngFile);
            // to add command to the button write the line below
            button.CommandHandler = new AdskCommandHandler();

            return button;
        }
    }


Detail information about PackageContents.xml file is in following link.
http://adndevblog.typepad.com/autocad/2013/01/autodesk-autoloader-white-paper.html


2017년 3월 25일 토요일

[Development story] GFtp #6 - To add favorites tree and etc...

GFtp is done basic functions.
So from now I will add some convenient functions. I added a favorites function today.
A tree view for favorites is made by TreeView that System.Windows.Forms provide.
File format for save favorites items is XML and to save XML I used a XMLWriter and to load XML I used a XMLReader.
XMLReader and XMLWriter was very useful for XML control.

1. Update lists

 - Added add favorites,
 - Added delete favorites.
 - Seperated ftp address and port and path.

2. GFtp v1.4 demo

3. Code snippets

 - Extend method defines

  - The extend method in C# is very useful. To make customized control, you don't have to make new custom control class what is Inherited existed control.
  - TreeView control Helper for favorites tree view
  - To make extend method, Just remember just two things that static and this.
  - Following is extend method for TreeView control for favorites.

    static public class FavoritesTreeViewHelper
    {
        // Save favorites items from favorites.xml file.
        static public bool SaveFavoritesItems(this TreeView treeView, Favorites favorites)
        {
            ...
        }

        // Load favorites items from favorites.xml file.
        static public bool LoadFavoritesItems(this TreeView treeView, Favorites favorites)
        {
            ...
        }

        // Refresh favorites items
        static public void RefreshFavoritesItems(this TreeView treeView, Favorites favorites)
        {
            ...
        }

        // Get selected favorites item
        static public FavoritesItem GetSelectedFavoritesItem(this TreeView treeView, Favorites favorites)
        {
            ...
        }

        // Get selected favorites item group name
        static public string GetSelectedFavoritesItemGroupName(this TreeView treeView, Favorites favorites)
        {
            ...
        }

        // Delete selected favorites item 
        static public bool DeleteSelectedFavoritesItem(this TreeView treeView, Favorites favorites)
        {
          ...
        }
    }

 - Following is way to call extend method.

   - You can call it like a member method.
  favoritesTreeView.SaveFavoritesItems(_favorites);
  favoritesTreeView.DeleteSelectedFavoritesItem(_favorites);
  favoritesTreeView.RefreshFavoritesItems(_favorites);
  favoritesTreeView.LoadFavoritesItems(_favorites);
   - You can make a extend method that has return value.
  string groupName = favoritesTreeView.GetSelectedFavoritesItemGroupName(_favorites);


- XML Reader

  - Following is GFtp's favorites structure.
   - Root elementis is <Favorites> and <Favorites> has some <Group> elements.
     And <Group> element has some <Item> element.
     <Item> element has attributes that are name, address, port, path, id, password.
   - The extend method for loading favorites.xml file.
     I called just XmlReader.Read() and XmlReader.GetAttribute(...) method.
     It's very useful for simple and small xml file. but For big xml file, you need more method in XmlReader, or you can use other class for xml like XmlDocument.

        // Load favorites items from favorites.xml file.
        static public bool LoadFavoritesItems(this TreeView treeView, Favorites favorites)
        {
            XmlReaderSettings setting = new XmlReaderSettings();
            setting.IgnoreWhitespace = true;  // Remove all unnecessary white spaces in the xml file.
            setting.ConformanceLevel = ConformanceLevel.Fragment;

            try
            {
                List<FavoritesItem> items   = null;
                using (XmlReader reader = XmlReader.Create("favorites.xml", setting))
                {
                    while (reader.Read())
                    {
                        if (reader.NodeType == XmlNodeType.Element)
                        {
                            if (reader.Name == "Group")
                            {
                                items = favorites.GetGroup(reader.GetAttribute("name"));
                                continue;
                            }

                            if (reader.Name == "Item")
                            {
                                if(items == null)
                                {
                                    continue;
                                }

                                FavoritesItem item  = new FavoritesItem();
                                
                                item.Name   = reader.GetAttribute("name");
                                item.Address = reader.GetAttribute("address");
                                item.Port = reader.GetAttribute("port");
                                item.Path = reader.GetAttribute("path");
                                item.ID = reader.GetAttribute("id");
                                item.Password   = reader.GetAttribute("password");
                                
                                items.Add(item);
                            }
                        }

                    }
                }
            }
            catch
            {
                MessageBox.Show("Not found favorites.xml");
            }
            return true;
        }

   - Next is extend method to save savorites items to xml file.

     Because it is very simple and small xml file, I used the XmlWriter.

        // Save favorites items from favorites.xml file.
        static public bool SaveFavoritesItems(this TreeView treeView, Favorites favorites)
        {
            XmlWriterSettings setting = new XmlWriterSettings();
            setting.Indent = true;

            try
            {
                List<FavoritesItem> items = null;
                using (XmlWriter writer = XmlWriter.Create("favorites.xml", setting))
                {
                    writer.WriteStartElement("Favorites");

                    foreach(var group in favorites._group)
                    {
                        string groupName = group.Key;
                        writer.WriteStartElement("Group");
                        writer.WriteAttributeString("name", groupName);

                        foreach(var item in group.Value)
                        {
                            writer.WriteStartElement("Item");
                            writer.WriteAttributeString("name", item.Name);
                            writer.WriteAttributeString("address", item.Address);
                            writer.WriteAttributeString("port", item.Port);
                            writer.WriteAttributeString("path", item.Path);
                            writer.WriteAttributeString("id", item.ID);
                            writer.WriteAttributeString("password", item.Password);
                            writer.WriteEndElement();
                        }
                        writer.WriteEndElement();

                    }

                    writer.WriteEndElement();
                }
            }
            catch
            {
                MessageBox.Show("Not found favorites.xml");
            }
            return true;
        }

 - Logic to add favorites and to delete favorites.

   - To add favorites : 
       - Clicks add button.
       - New item is added to favorites data class.
       - The favorites data class is saved to xml file.
       - Favorites tree view control is refreshed using favorites data class.
       
   - To delete favorites.
       - Clicks del button.
       - Finds favorites item in the favorites data class by selected item in favorites tree view cocntrol.
       - Deletes favorites item in the favorites data class.
       - The favorites data class is saved to xml file.
       - Favorites tree view control is refreshed using favorites data class.


4. Next

   - Now GFtp is became so big and complex.
     And GFtp is done almost basic function. So I will update GFtp for powerful and stability.
     I will try speed up translate using multi threading. By the way I don't know what I can do it.

2017년 3월 23일 목요일

[Civil3D API] After loading .NET dll, If Civil3D doesn't work finish.

After you call StartTransaction function, if you don't commit then Civil3D doesn't work finish.
So you can use StartTransaction like following.

using (Transaction ts = Application.DocumentManager.MdiActiveDocument.Database.TransactionManager.StartTransaction())
{
     ... 
     ...
}

When you use using statement. Transaction.commit() is called automatically at the end of block.


2017년 3월 20일 월요일

[C#] To check if string includes "ftp://" using Regex.

string s = "ftp://127.0.0.1:6000";

bool isInclude = System.Text.RegularExpressions.Regex.IsMatch("^ftp://", s);

If s include "ftp://" at first, then isInclude is true.

[Development story] GFtp #5 - To add explorer using open source.

GFtp is became more pretty than before. But It needs become more pretty and more easy.
Specially, moving between directories is pretty uncomfortable. So I decided to get open source like explorer tree control for that. My favorite site for open source is CodeProject.
CodeProject has so many open source and good article. To beginner like me, that is that best place.
I found a good control. Follow is link of that.

https://www.codeproject.com/Articles/14570/A-Windows-Explorer-in-a-user-control

First of all, I thanks to Raj Lal who made this control.

1. Update list

 - Added explorer Tree using open source.
 - Relayouts all controls.

2. GFtp v1.3 demo


3. To add explorer Tree 

  To add this control, C# needs only .dll file.
  C++ needs .h and .dll files.
  I am satisfied with C# useful.
  At first, you have to add user control(.dll) so you can use a user control on the form.
  Following is how to add user control(.dll).
   - Right click on the All Windows Forms of the Toolbox.
   - Click menu Choose Items...
   - Select .dll file after Browse button click.
   - Select user control.
   - Click OK button.
   - Done.
   
 To use user control, just drag&drop from the Toolbox to your Form.
 If you feel difficult to find ExplorerTree in the Toolbox, search Toolbox.

 User control what I added is shaped like following.


  I added it on the GFtp like that.




   Following code is to apply ExplorerTree(usercontrol) to GFtp.
   If you double click the ExplorerTree(user control), PathChanged event method is made automatically.

        // Called when changed path on explorerTree
        private void explorerTree_PathChanged(object sender, EventArgs e)
        {
            CurrentDirectory = explorerTree.SelectedPath;
            RefreshFileGridViewOfCurrentDirectory();
        }

  I just call explorerTree.SelectedPath method and set string to CurrentDirectory property.
  And done with calling RefreshFileGridViewOfCurrentDirectory().

4. Next

 I can't test upload yet cause I can't find Ftp server to upload.
 So I will make Ftp server to upload test.


This source is shared.
GitHub : https://github.com/gurum77/GFtp

  









2017년 3월 14일 화요일

[C#] To read a text file

// Opens a file using File.OpenText and closes a file using Dispose()
static void ReadFile()
{
     StreamReader reader = null;
     try
     {
           reader     = File.OpenText("d:\\file.txt");
           if(reader.EndOfStream)
                return;
           Console.WriteLine(reader.ReadToEnd());
     }
     finally
     {
           if(reader != null)
                reader.Dispose();
     }

}

2017년 3월 12일 일요일

[Development story] GFtp - #4 Refactoring and Git

GFtp is taken first refactoring.
At first, I thought that this is for just studying C#. So I was coding without design.
At the end, GFtp's source code is getting more dirty. And I decided to refactoring.

1. UML

 - I made some classces for modulize and small cs files.
   Almost source codes was included in Form1.cs file. But Form1.cs file is worng name and become very big. So I designed FileGridViewHelper and FtpController.
  FileGridViewHelper has 2 extend method of DataGridView control.
  FtpController has some method and property for Ftp.
  Form1 is renamed to MainForm. Form1 was made by Visual Studio wizard.
  Following is UML for that.



2. Code snippet

 - The extend method for getting selected files in the DataGridView

     - define
    // Helper class for FileGridView
    static class FileGridViewHelper
    {
        // Get file names selected in the grid view
        static public string[] GetSelectedFiles(this DataGridView gridView)
        {
            string[] files = new string[gridView.SelectedRows.Count];
            int idx = 0;
            foreach (DataGridViewRow row in gridView.SelectedRows)
            {
                files[idx++] = row.Cells[0].Value.ToString();
            }

            return files;
        }
    }

    - call
    string[] files = fileGridView.GetSelectedFiles();


  - FtpController's properties
     - I defined properties instead of field that I need.
       Property allows source code is cleaned and developer can make easy coding for simple method like get, set.
      So I think that property is better than field in case not need to performance and special case.

     class FtpController
    {
        //  _ftpAddress  = @"ftp://ftp.novell.com";
        public string FtpAddress { get; set; }
        public string ID { get; private set; }
        public string Password { get; private set; }
        public System.Windows.Forms.ProgressBar _progressBar    = null;
        ...
   }

3. Git

 - GFtp version is v1.3.
   Now I am feeling that version management is difficult without any version management tool.
   So I added GFtp source code to Git.
   Here is Git link.

2017년 3월 8일 수요일

[Development Story] GFtp - #3

GFtp's second update.

1. Update list

 - To add progress bar while translate files.
 - To move between ftp directory using double click.
 - To display more detail ftp file / directory information
 - Disable editing of DataGridView.

2. Demo

 - GFtp v1.2 demo

3. Codes snippets

 - To add progress bar while translate files. 

  First, set a progressbar and whenever translate file increment step using PerformStep() function.
  Next code is to translate files with increment progress bar.

         // Translate files from local to ftp or from ftp to local
        private bool TranslateFiles(string[] files, bool IsUpload)
        {
            // Set a progressbar
            progressBar.Style = ProgressBarStyle.Continuous;
            progressBar.Minimum = 0;
            progressBar.Maximum = files.Length;
            progressBar.Step = 1;
            progressBar.Value = 0;
   

            // connect ftp
            WebClient wc = new WebClient { Proxy = null };
            wc.BaseAddress = _ftpAddress;
            if (_id != "" && _password != "")
            {
                wc.Credentials = new NetworkCredential(_id, _password);
            }

            try
            {
                foreach (string filename in files)
                {
                    string pathName = Path.Combine(_currentDirectory, filename);

                    // increment progress bar
                    progressBar.PerformStep();
                    
                    // upload
                    if (IsUpload)
                    {
                        wc.UploadFile(pathName, filename);
                    }
                    // download
                    else
                    {
                        wc.DownloadFile(filename, pathName);
                    }
                }
            }
            catch
            {
                return false;
            }

            return true;
        }

 - To move between ftp directory using double click.
  First, I made a EventHandler for DoubleClick in both fileGridView and ftpFileGridView.
  Following codes are Add EventHandler to fileGridView and to implement that EventHandelr.
        public Form1()
        {
            InitializeComponent();
   
            // Add a event handler to fileGridView.DoubleClock.
            fileGridView.DoubleClick += FileGridView_DoubleClick;
        }

        // It's called after double clicking on fileGridView. 
        private void FileGridView_DoubleClick(object sender, EventArgs e)
        {
            if (sender != fileGridView)
                return;

            DataGridViewCell cell = fileGridView.CurrentCell;
            // Check clicked cell is file or folder
            bool isFolder = true;
            if (fileGridView.Rows[cell.RowIndex].Cells[2].Value.ToString() == "File")
                isFolder = false;

            // if clicked cell is folder then move current directory to sub directory
            if(isFolder)
            {
                _currentDirectory   = Path.Combine(_currentDirectory, fileGridView.Rows[cell.RowIndex].Cells[0].Value.ToString());
                RefreshFileGridViewOfCurrentDirectory();
            }         
        }

 - To display more detail ftp file / directory information
  To include variety of information for directory and file, I made GridFileInfo class.
  GridFileInfo Inherit IComparable and has CompareTo function for sorting from directory to file.
  I used GridFileInfo for fileGridView and ftpFileGridView. As you know, Ftp file has more detail information than local file. So it may waste memory if you use this class for both.
  But, I thought that can share some function like refresh grid view for file grid view and ftp file grid view. And I thought that it can be increased comfortation for coding.
  Following is GridFileInfo class.
    public class GridFileInfo : IComparable
    {
        public string Name { get; set; }
        public long Size { get; set; }
        public bool IsFolder { get; set; }
       

        public int CompareTo(object obj)
        {
            if(obj is GridFileInfo)
            {
                GridFileInfo tmp = (GridFileInfo)obj;
                if (tmp.IsFolder == IsFolder)
                    return 0;
                else if (tmp.IsFolder == true)
                    return 1;
                else if (IsFolder == true)
                    return -1;
            }
            throw new ArgumentException("Object is not a GridFileInfo");
        }
    }  

 Following is to refresh filegrid view of local directory and show to share FileGridInfo class.
        // Refresh FileTreeView
        // Display all file in the current directory.
        void RefreshFileGridViewOfCurrentDirectory()
        {
            // Get all file list  directory list of my pc;
            DirectoryInfo di = new DirectoryInfo(_currentDirectory);

            // Get all sub directory
            DirectoryInfo[] subDiArray = di.GetDirectories();
           
            // Get all files
            FileInfo[] fiArray = di.GetFiles("*.*");

            GridFileInfo[] gridFileInfos = new GridFileInfo[1 + subDiArray.Length + fiArray.Length];
            int idx = 0;

            // Add super directory
            {
                gridFileInfos[idx] = new GridFileInfo();
                gridFileInfos[idx].Name = "..";
                gridFileInfos[idx].Size = 0;
                gridFileInfos[idx].IsFolder = true;
                idx++;
            }
            
            // Add directory infos
            foreach (DirectoryInfo subDi in subDiArray)
            {
                gridFileInfos[idx] = new GridFileInfo();
                gridFileInfos[idx].Name = subDi.Name;
                gridFileInfos[idx].Size = 0;
                gridFileInfos[idx].IsFolder = true;
                idx++;
            }
         
            // Add file infos
            foreach(FileInfo fi in fiArray)
            {
                gridFileInfos[idx] = new GridFileInfo();
                gridFileInfos[idx].Name = fi.Name;
                gridFileInfos[idx].Size = fi.Length;
                gridFileInfos[idx].IsFolder = false;
                idx++;
            }
            // Display file to grid view
            DisplayFilesToGridView(fileGridView, gridFileInfos);
        }

4. Git

 - I am feeling that uncomfortation to management version and source code.
   So I started manage version and source code using Git.
   From now my source code is shared via GitHub.com.
   My github link is
   https://github.com/gurum77/GFtp

5. Next

 - GFtp version is 1.2. GFtp is getting complex.
   So I will refactoring GFtp. it will be also simple refactoring. Because this project is for just my studying C#.