블로그 이미지
Every unexpected event is a path to learning for you. blueasa

카테고리

분류 전체보기 (2799)
Unity3D (855)
Programming (479)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (185)
협업 (61)
3DS Max (3)
Game (12)
Utility (68)
Etc (98)
Link (32)
Portfolio (19)
Subject (90)
iOS,OSX (55)
Android (14)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (18)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday
안녕하세요? 맨날맑음 입니다.

어플리케이션을 개발 하다 보면 같은 프로그램이 두번 실행 되지 않아야 하는 경우가 종종 생깁니다.
이를 해결 하기 위해 여러 방법이 있지만.. 이번 포스팅에 소개 할 내용은 커널 동기화 객체 중 하나인 뮤텍스(Mutex)를 이용하여 해결하는 방법을 소개하려 합니다.

Mutex는 .NET의 System.Threding 네이스페이스에 포함된 클래스 입니다. 사실 둘이상의 스레드가 동시에 공유될 수 있는 리소스에 접근 할때 데드락의 위험이 있으므로 동기화 매커니즘이 필요하게 되는데요. Mutex는 리소스에 대한 단독 엑세스 권한을 하나의 스레드에만 부여하여 동기화하는 기본형식 입니다.
같은 리소스에 접근 할때 하나의 스레드가 Mutex를 걸고 어떠한 일을 수행 할 경우 다른 스레드는 먼저 수행하고 있는 스레드가 Mutex를 해제 할때까지 기다리게(일시중지) 되게 됩니다.
Mutex에 관한 자세한 설명은 아래의 링크에서 MSDN 도움말을 확인 할 수 있습니다.
http://msdn.microsoft.com/ko-kr/library/system.threading.mutex.mutex.aspx

테스트 하는 어플리케이션으로는 Windows Form 프로젝트를 예로 들겠습니다.
WinForm 프로젝트를 생성하면 Program.cs 가 생성 됩니다.
Main 함수에 다음과 같은 코드를 추가 시켜 주면 메세지 막스가 뜨면서 해당하는 프로그램이 중복 실행 되었다는걸 알릴 수 있습니다. 매우 간단하죠?
static class Program
    {
        /// 
        /// 해당 응용 프로그램의 주 진입점입니다.
        /// 
        [STAThread]
        static void Main()
        {
            bool createdNew;
            Mutex dup = new Mutex(true, "Focus Explorer Mutex", out createdNew); //Mutex생성
            if (createdNew)
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new MainForm());
                dup.ReleaseMutex(); //Mutex 해제
            }
            else // 프로그램이 중복 실행된 경우
            {
                MessageBox.Show("이미 프로그램이 실행중입니다.","Focus Explorer");
            }
        }
    }
 
우선 Mutex를 생성하고, 생성자에 두번째 인자에 뮤텍스 이름을 지정합니다.
세번째 인자로준 bool 값이 false일 경우 이미 뮤텍스가 걸리있는 상태이기 때문에.. 해당 프로젝트가 이미 생성되었다고 생각하고 프로그램이 실행중이라는 메세지 박스를 띄우고, 프로그램을 종료합니다.

이상 간단한 Mutex를 사용한 프로그램 중복 방지 방법이었습니다.


출처 : http://crynut84.tistory.com/46
반응형

'Programming > C#' 카테고리의 다른 글

Random Class를 파해쳐 보자!  (0) 2010.07.16
화살표 그리기(.NET Pen Class)  (0) 2010.07.16
App.Config XML읽고 쓰기..  (0) 2010.07.15
ini파일을 간단히...사용하자.  (0) 2010.07.15
C# (윈폼/콘솔) 관련 사이트  (0) 2010.07.15
Posted by blueasa
, |

App.Config XML파일을 읽고 쓰는 간단한 함수를 하나 만들어 봤습니다..

더 좋은 정보 있으면 리플 달아 주세요

 

 

private string AppConfigRead(string keyName)

        {

            string strReturn;

            Configuration currentConfig =

                ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

 

            if (currentConfig.AppSettings.Settings.AllKeys.Contains(keyName))

                strReturn = currentConfig.AppSettings.Settings[keyName].Value;

            else

                strReturn = ""; //키가없으면.

 

            return strReturn;

        }

 

        private bool AppConfigWrite(string keyName, string value)

        {

            Configuration currentConfig =

                ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

 

            if (currentConfig.AppSettings.Settings.AllKeys.Contains(keyName)) //키가 있으면

                currentConfig.AppSettings.Settings[keyName].Value = value;

            else       //키가 없으면

                currentConfig.AppSettings.Settings.Add(keyName, value);

           

            currentConfig.Save();

            ConfigurationManager.RefreshSection("appSettings");   // 내용 갱신             

            return true;

        }


출처 : http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=18&MAEULNo=8&no=1699&ref=1699



우선 위 함수를 사용하려면 참조 추가와 namespace 추가가 필요합니다.
1) System.configuration <- 참조 추가
2) using System.Configuration; <- 추가

그렇게 하고도.. 위의 소스에서 Contains 라는걸 찾을 수 없어서 제맘대로 수정했습니다.
정석인진 모르겠지만..돌아가니 참고하실분은 하세요.


        public static string AppConfigRead(string keyName)
        {
            string strReturn = "";
            Configuration currentConfig =
                ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

            bool bIsKey = false;

            foreach (string key in currentConfig.AppSettings.Settings.AllKeys)
            {
                if (key.StartsWith(keyName))
                {
                    strReturn = currentConfig.AppSettings.Settings[keyName].Value;
                    bIsKey = true;
                    break;
                }
            }

            if(bIsKey == false)
                return string.Empty;
           
            return strReturn;
        }


        public static bool AppConfigWrite(string keyName, string value)
        {
            Configuration currentConfig =
                ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

            if (currentConfig.AppSettings.Settings.Count != 0)
            {
                bool bIsKey = false;
                foreach (string key in currentConfig.AppSettings.Settings.AllKeys)
                {
                    if (key.StartsWith(keyName))
                    {
                        currentConfig.AppSettings.Settings[keyName].Value = value;
                        bIsKey = true;
                        break;
                    }
                }

                if ( bIsKey == false )       //키가 없으면
                {
                    currentConfig.AppSettings.Settings.Add(keyName, value);
                }
            }
            else
            {
                currentConfig.AppSettings.Settings.Add(keyName, value);
            }

            currentConfig.Save();
            ConfigurationManager.RefreshSection("appSettings");   // 내용 갱신             

            return true;
        }

반응형
Posted by blueasa
, |

질문 & 답변에 관련 내용이 많지만...

널리 사용하시라고 올려 봅니다.

 

다음과 같이 class를 추가해서 사용하시면

사용하시기 편리 하실거예요.

 

추신 : 파일명 및 파일 패스(path)를 수정하여 사용하세요. 감사합니다.

 

//ini 관리 클래스
    public class IniControl
    {

        [DllImport("kernel32")]

        public static extern bool WritePrivateProfileString(string lpAppName, string lpKeyName, string lpString, string lpFileName);

        [DllImport("kernel32")]

        public static extern uint GetPrivateProfileInt(string lpAppName, string lpKeyName, int nDefault, string lpFileName);

        [DllImport("kernel32")]

        public static extern int GetPrivateProfileString(string lpAppName, string lpKeyName, string lpDefault, StringBuilder lpReturnedString, int nSize, string lpFileName);

        public static int ReadInteger(string fileName, string IpAppName, string IpKeyName, int Default)
        {
            try
            {
                string inifile = fileName;    //Path + File

                StringBuilder result = new StringBuilder(255);
                IniControl.GetPrivateProfileString(IpAppName, IpKeyName, "error", result, 255, inifile);

                if (result.ToString() == "error")
                {
                    return Default;
                }
                else
                {
                    return Convert.ToInt16(result);
                }
            }
            catch
            {
                return Default;
            }
        }

        public static Boolean ReadBool(string fileName, string IpAppName, string IpKeyName)
        {
            string inifile = fileName;    //Path + File
            StringBuilder result = new StringBuilder(255);
            IniControl.GetPrivateProfileString(IpAppName, IpKeyName, "error", result, 255, inifile);

            if (result.ToString() == "True" || result.ToString() == "1")
            {
                return true;
            }
            else
            {
                return false;
            }

        }

        public static string ReadString(string fileName, string IpAppName, string IpKeyName, string Default)
        {
            string inifile = fileName;    //Path + File

            StringBuilder result = new StringBuilder(255);
            IniControl.GetPrivateProfileString(IpAppName, IpKeyName, "error", result, 255, inifile);

            if (result.ToString() == "error")
            {
                return Default;
            }
            else
            {
                return result.ToString();
            }

        }

        public static string getIni(string fileName, string IpAppName, string IpKeyName)
        {
            string inifile = fileName;    //Path + File

            StringBuilder result = new StringBuilder(255);
            IniControl.GetPrivateProfileString(IpAppName, IpKeyName, "error", result, 255, inifile);

            return result.ToString();

        }

        public static Boolean setIni(string fileName, string IpAppName, string IpKeyName, string IpValue)
        {
            string inifile = fileName;    //Path + File
            IniControl.WritePrivateProfileString(IpAppName, IpKeyName, IpValue, inifile);

            return true;
        }
        public static Boolean setIni(string filePath, string fileName, string IpAppName, string IpKeyName, string IpValue)
        {
            string inifile = filePath + fileName;
            IniControl.WritePrivateProfileString(IpAppName, IpKeyName, IpValue, inifile);

            return true;
        }
    }

 

 

질문은 언제나 환영입니다.

즐프하세요.


출처 : http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=18&MAEULNO=8&no=1818&page=3

반응형
Posted by blueasa
, |
반응형
Posted by blueasa
, |

C#으로 ESC키 무시 방법을 찾는데 왜 찾는 녀석은 안나오고... C++에서의 방법들만 나오는지 ㅡ_ㅢ;;
에효.. 암튼... 언제든 쓸모가 있을 듯 하니... 한번 옮겨놔 보련다.....


1. Enter, ESC 키 무시 방법

모달리스 다이얼로그를 만들고 이 ESC,ENTER 키를 입력하면 다이얼로그가 사라지게 됩니다. 그렇다고 꼭 이 키를 무시해야 한다는 건 아니고 경우에 따라 무시를 해도 되고 다른 동작을 하게해도 됩니다. 이는 개발자 마음!!
모달리스 다이얼로그 클래스에서 PreTranslateMessage()를 아래와 같이 오버라이딩 해주면 됩니다.


/*
     ESC, Enter key를 무시한다.
*/
BOOL CProcessADlg::PreTranslateMessage(MSG* pMsg)
{
    // TODO: Add your specialized code here and/or call the base class
    switch(pMsg->message)
    {
    case WM_KEYDOWN:
        {
            switch(pMsg->wParam)
            {
            case VK_ESCAPE:
            case VK_RETURN:
                return TRUE;
            }
        }
    }
    return CDialog::PreTranslateMessage(pMsg);
}


2. 소멸 방법

모 달리스 다이얼로그를 소멸하려면 두 가지 측면에서 생각해야 합니다. 하나는 모달리스 다이얼로그를 생성하는 부모 윈도우 객체이고 하나는 모달리스 다이얼로그 자신입니다.  부모 윈도우 객체에서는 모달리스 다이얼로그를 생성할 때 모달리스 다이얼로그 객체 변수를 정한 후 메모리 할당을 하고 Create()함수를 호출하여 생성하게 됩니다. 그렇다면 모달리스 다이얼로그가 파괴 될 때 부모 윈도우가 이를 알 수 있어야 메모리 해제를 제대로 해 줄 수 있습니다. 제가 사용한 방식은 모달리스 다이얼로그 객체에서 자기 자신의 메모리를 해제하고 부모 윈도우에서는 모달리스 다이얼로그 객체변수에 NULL 포인터를 전달하는 방식을 사용했습니다. 이렇게 하기 위해서 모달리스 다이얼로그의 PostNcDestroy()가 호출 되는 시점에서 부모 윈도우에게 사용자 정의 메시지(저는 WM_DESTROY_DLG라고 정했습니다.)를 하나 정해서 SendMessage함수를 통해서 메시지를 전달해 주고 부모 윈도우에서는 이 메시지를 처리합니다. 그리고 모달리스 다이얼로그에서 자기 자신의 메모리를 해제 합니다. 이 과정에 대해서는 예제 소스를 함께 첩부해 놓았습니다. 말로 설명해보려고 했는데 글 재주가 없어서;;


※ 위 글에 대한 잘못된 부분이나 궁금하신 부분에 대한 피드백은 언제나 환영입니다 ~ 물론, 퍼가신다면 영광이구요. 우리나라의 모든 개발자 분들께서 바쁘시지만 서로 자신의 귀중한 경험과 지식을 공유해서 함께 발전해 나갈 수 있었으면 합니다 ^^

Dialog.zip


출처: greenfrog님의 블로그 - Programmer greenfrog!!

반응형
Posted by blueasa
, |

Form 에서 다른 Form 을 생성하는 경우 작업표시줄에도 표시되고 Alt+Tab을 누르면 나오는 화면에도 나옵니다.

이것을 없애는 방법이 여러가지 있습니다.

ShowDialog() 로 호출하는 방법도 있고, FormBorderStyle을 FixedToolWindow 또는 SizableToolWindow 로 지정하면 Alt+Tab 화면에 보이지 않습니다. 하지만 이 방법들은 무언가 꺼림찍하죠?

다들 특정한 목적으로 쓰도록 만든 것이기 때문에 일반 폼에 적용하기는 무리가 있습니다.

제가 만드는 App의 경우에는 FormBorderStyle을 None으로 설정하고, 소유하는 폼에도 접근해서 작업을 하도록 만들었기 때문에 위의 방법을 쓸 수가 없더군요

 

그래서 열심히 구굴링을 해서 찾아낸 방법!

        protected override CreateParams CreateParams
        {
            get
            {
                // Turn on WS_EX_TOOLWINDOW style bit
                CreateParams cp = base.CreateParams;
                cp.ExStyle |= 0x80;
                return cp;
            }

         }

이 코드를 Form의 클래스에 넣기만 하면 Alt+Tab을 눌러도 보이지 않습니다.
보니까 어떤 속성을 오버라이드 해서 ToolWindow 속성을 부여하는 것 같습니다. 정확한지는 저도 잘 ^^;

 

출처: http://www.csharp411.com/hide-form-from-alttab/

반응형
Posted by blueasa
, |

Form.Location 이라는 속성을 이용해서 창의 위치를 결정할 수 있습니다.
그리고 Form.Show() 라는 메써드를 이용해서 창을 보여줄 수 있습니다.
그렇다면!!
위치를 지정하고 그 위치에 창을 띄울 수 있을 것 같은데... 어라? 잘 안됩니다 ㅡㅡ;
일단 Show() 메써드를 사용한 후에는 Location 속성을 이용해서 창이 잘 움직이는데 처음 시작할 때는 잘 안되는군요~
Show() 메써드를 실행하기 전에 지정한 Location 속성은 Form의 위치에 영향을 주지 못하는 것 같습니다.

이럴 때!!
Form.StartPosition 속성을 이용합니다.
오호라! 시작 위치를 지정할 수 있을 것 같은 속성 이름이군요!

Form.StartPosition 속성은 Point 객체가 아니고 FormStartPosition 이라는 열거형입니다.
그렇다면 어떻게 처음 위치를 지정할까요?

Form.StartPosition = FormStartPosition.Manual; //이렇게 지정해 주면 Location을 시작 위치로 사용합니다.
이 방법을 사용하면 Form을 원하는 위치에 띄울 수 있겠죠? ^^

form1.StartPosition = FormStartPosition.Manual;
form1.Location = new Point(10,10);
form1.Show();


이렇게요~ 참 쉽죠?

반응형
Posted by blueasa
, |

사용자 삽입 이미지
입력 배열 :

        string[] parentString = { "son1", "son2", "son3", "son4" };
        string[] childString = { "byoung1", "byoung2", "byoung3" };

입력방법 #1

        private void button1_Click(object sender, EventArgs e)
        {
            treeView1.Nodes.Clear();
            treeView1.BeginUpdate();

            foreach (string str in parentString)
            {
                TreeNode tn = treeView1.Nodes.Add(str);

                foreach (string substr in childString)
                {
                    tn.Nodes.Add(substr);
                }
            }

            treeView1.EndUpdate();
        }

입력방법 #2

        private void button2_Click(object sender, EventArgs e)
        {
            treeView1.Nodes.Clear();
            treeView1.BeginUpdate();

            foreach (string str in parentString)
            {
                treeView1.Nodes.Add(str);
            }

            foreach (TreeNode tn in treeView1.Nodes)
            {
                foreach (string substr in childString)
                {
                    tn.Nodes.Add(substr);
                }
            }

            treeView1.EndUpdate();
        }

입력방법 #3

        private void button3_Click(object sender, EventArgs e)
        {
            treeView1.Nodes.Clear();
            treeView1.BeginUpdate();

            TreeNode tn = new TreeNode();
            foreach (string str in childString)
            {
                tn.Nodes.Add(str);
            }

            foreach (string str in parentString)
            {
                TreeNode tnParent = treeView1.Nodes.Add(str);
            }

            treeView1.EndUpdate();
        }



출처 : http://www.iamgsi.com/entry/C-TreeView-내용-추가하기
반응형
Posted by blueasa
, |
C++ 에서 FILE 를 사용해서 데이터를 바이너리로 저장 했다면 C#에서 어떻게 읽어야 할까?.

C#을 배우는 상태에서 C++ 과의 파일 연동 문제가 고민이 되었다.
사실 모르니 궁금증이 생긴 거지만 몇가지 테스트를 하다 보니 바이너리 데이터는 BinaryReader 로 읽을수 있었다.

해당 파일을 읽을때 FileInfo를 사용해서 오픈 한 다음에 BinaryReader로 읽을 수 있다.
FileInfo fi = new FileInfo(@"D:\Testbinary.dat");
BinaryReader br = new BinaryReader(fi.OpenRead());

C++ 에서 아래 데이터를 저장했습니다.
FILE* fp = fopen(path, "wb");
int data0 = 100;
float data1 = 100.123f;
char buf0[128] = "son byoung uk";
fwrite(&data0, sizeof(int), 1, fp);
fwrite(buf0, 128, 1, fp);
fwrite(&data1, sizeof(float), 1, fp);
fclose(fp);

C# 에서 아래와 같이 데이터를 읽었습니다.
int data0;
float data1;
char[] buf0;
string buf1; data0 = br.ReadInt32();
buf0 = br.ReadChars(128);
buf1 = new string(buf0);
data1 = br.ReadSingle();

위의 내용을 아래와 같이 정리해봤습니다.

C++

C#

int

br.ReadInt32()

float

br.ReadSingle()

double

br.ReadDouble()

char[]

string a = new string(br.ReadChars(128))



출처 : http://www.iamgsi.com/?page=35
반응형

'Programming > C#' 카테고리의 다른 글

Form을 원하는 위치에 띄우자!  (0) 2010.07.14
TreeView 내용 추가하기  (2) 2010.07.14
윈폼에서 단축키 개발하기  (0) 2010.07.13
Windows Forms Application  (2) 2010.07.07
PointToClient 와 PointToScreen  (0) 2010.07.07
Posted by blueasa
, |

윈폼(via C#)으로 각종 툴, 어플리케이션을 만들 때 유저키덕후들을 위한 단축키가 필요할 수 있다. 마우스라는 혁신적인 입력 장치가 있더라도 숙련되면 키보드 이상가기 힘드니까 :)
언뜻 생각하기에는 System.Windows.Forms.Form 클래스에서 KeyDown 이벤트를 잡아서 처리를 하면 될 것 같아 해보았지만, 동작하지 않는다 ㅇㅂㅇ;;
Google신(MS는 Bing신...)에 문의 결과 ProcessCmdKey 메소드를 오버라이드 한다면 된다고 한다. 간단히 해보면 다음과 같다.
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
        if (!base.ProcessCmdKey(ref msg, keyData)) // 위에서 처리 안했으면
        {
                // 여기에 처리코드를 넣는다.
                if (keyData.Equals(Keys.F1))
                {
                        // 대충 이런 식으로 처리한다.
                        return true;
                }
                else
                {
                        return false;
                }
        }
        else
        {
                return true;
        }
}


위 코드에서 return false; 의 의미는 내가 처리를 안했으니 혹시나 자식 클래스에서 오버라이드 할꺼면 밑에서 처리해라~ 라는 의미이다. 반대로 return true; 는 밑에서 처리하지 말라는 소리다. 마찬가지로  base.ProcessCmdKey가 거짓일 때만 처리하는 것도 부모 클래스에서 키입력에 대해서 처리를 했다면 처리를 하지 않는다는 의미이다.

아무튼, 이리하여 간단히 단축키를 구현할 수 있다.


출처 : http://zeru.kr/blog/539
반응형

'Programming > C#' 카테고리의 다른 글

TreeView 내용 추가하기  (2) 2010.07.14
C++ 바이너리(Binary) 데이터를 C# BinaryReader 로 읽기.  (0) 2010.07.14
Windows Forms Application  (2) 2010.07.07
PointToClient 와 PointToScreen  (0) 2010.07.07
단축키 만들기 with C#  (1) 2010.07.07
Posted by blueasa
, |