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);
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
...
// 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.
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 }
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); }
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); } }
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.
// 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.
// 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.
// 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
}
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/
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.
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;
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.
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; } }
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)
- 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.
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.
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
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.
- 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#.