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

카테고리

분류 전체보기 (2797)
Unity3D (853)
Programming (479)
Python (8)
TinyXML (5)
STL (13)
D3D (3)
MFC (1)
C/C++ (54)
C++/CLI (45)
C# (251)
WinForm (6)
WPF (5)
Math (10)
A.I. (1)
Win32API (11)
Algorithm (3)
Design Pattern (7)
UML (1)
MaxScript (1)
FMOD (4)
FX Studio (1)
Lua (2)
Terrain (1)
Shader (3)
boost (2)
Xml (2)
JSON (4)
Etc (11)
Monad (1)
Html5 (4)
Qt (1)
Houdini (0)
Regex (14)
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

오늘부터 본격적으로 ChulsPlayer제작에 들어갔다.

일단 로컬 PC의 음악자원을 기반으로 재생하는 부분을 구현하기 시작했다.

 

간단하게 음악파일을 재생할 수 있는 컨트롤을 만들고,

리스트박스를 만들어서 재생목록이 보여지도록 하였다. (모든 음악재생프로그램에서 제공되는 기능이다.)

 

그런데, 음악파일을 드래그해서 프로그램에 드랍했을 때.. (쉽게 말하면 끌어놓기)

해당 모든 파일들의 리스트를 받아와야 하는데.. 이게 생각만큼 자료가 없더라.

 

그래서 삽질에 삽질을 한 결과..

다음과 같은 과정을 거치면, Drag and Drop된 파일들의 경로를 받아올 수 있다는 것을 알게 되었다.

 

필요하다면 차근 차근 따라해 보도록하자.

 

우선 가장 먼저 해야할 일은 drag and drop을 구현시킬 컨트롤이나 폼에 대하여

AllowDrop 속성을 True로 변경하여야 한다. 헷갈린다면 다음 그림을 참조하도록 하자.

 

이제 여기서는 클래스와 윈도우프로그래밍에 대한 이해가 어느정도 있어야한다.

 

이벤트를 처리해줄 수 있도록 해당 컨트롤의 base클래스로부터 OnDragEnter(DragEventArgs)와

OnDragDrop(DragEventArgs)를 오버라이드하여야 한다.

 

OnDragEnter()는 다음과 같이 구현하면 간단하게 해결이 된다.

 

 

 

그렇다면 파일의 경로를 받아오는것은 OnDragDrop()에서 수행되게 해야할 것이다.

아래와 같은 코드를 적용하면 해당 파일명을 받아올 수 있다.

 

 

 

이렇게 함으로써 여러분은 여러분 프로그램을 사용하는 사용자가 Drag and Drop을 수행하였을 때

파일에 대한 처리를 해줄 수 있을 것이다.

반응형

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

is 와 as  (0) 2010.07.21
region을 사용해서 코드를 깔끔하게  (0) 2010.07.21
C#, 간단한 Developing Tips  (0) 2010.07.21
C# 포커스 빼앗지 않는 폼 구현하기  (0) 2010.07.21
String.Format으로 할 수 있는 일들  (0) 2010.07.20
Posted by blueasa
, |

완전샤푸님의 블로그에서 발췌하였습니다.

눈에 보이는 괜찮은 팁이 몇 가지 있네요. ^^

 

 

 

- Form

 

 

1. MDI 폼의 경우 자식 폼에 MDI 부모 품을 설정 하는 방법
// 자식 폼의 생성자에서 부모 폼의 인스턴스를 넘겨 주어 설정하도록 한다.

public ChildForm( MainForm frm )

{

        InitializeComponent();


        this.MdiParent = frm;

……….

}





2. 다이얼로그 폼 사용

LogInForm frm = new LogInForm();

frm.StartPosition = FormStartPosition.CenterScreen;  // 다이얼로그 폼을 중심으로 이동

frm.ShowDialog();

                    

if( DialogResult.OK == frm.DialogResult )

{

      ………………………………………

}







- 컨트롤



1. 리스트, 리스트뷰 컨트롤



- 컬럼 지정

: 리스트 및 리스트 뷰 컨트롤의 컬럼을 프로그래밍으로 지정 할 수 있지만 디자인 모드에서 더욱 쉽게

추가 할 수 있다. 예는 리스트 뷰로 하지만 리스트 컨트롤과 방법은 같다.

리스트 뷰 컨트롤을 지정한다.


속성 창에서 ‘Colummns’ 속성을 클릭 한다.



‘ColumnHeader 컬렉션 편집기가 나타난다.


여기서 컬럼을 추가 하기 위해 ‘추가’버튼을 누르면 오른쪽에 속성을 주는 부분이 나온다. 컬럼명과 넓이 등을 지정하면 된다.

* 프로그래밍적 방법
ListView.Columns.Add( "이름", 40, HorizontalAlignment.Center );





- 데이터 모두 삭제
ListView.Items.Clear();




- 데이터 추가

ListViewItem lvi = new ListViewItem();

lvi.SubItems.Add( “최흥배” );

lvi.SubItems.Add( “프로그래머팀” );

lvi.SubItems.Add( “서버파트” );

ListView.Items.Add( lvi );

ListView.Refresh();




- 데이터 추가 2

: 위의 방식은 컬럼의 첫번째가 이미지 리스트인 경우는 좋지만 리스트 뷰의 첫 컬럼에 어떤 문자를

나타내고 싶은 경우는 되지 않는다. 이런 경우 ListVieeItem의 생성자의 인자에 첫 컬럼에 나타내고 싶은

문자를 지정해 줘야 한다.

ListViewItem lvi = new ListViewItem( iCount.ToString() );

lvi.SubItems.Add( “최흥배” );

lvi.SubItems.Add( “프로그래머팀” );

lvi.SubItems.Add( “서버파트” );

ListView.Items.Add( lvi );

ListView.Refresh();




- 삽입된 모든 데이터 순회
int iItemNum = ListView.Items.Count;

for( int i = 0; i < iItemNum; ++i )

{

        iYear = Convert.ToInt32(ListView.Items[i].SubItems[ 0 ].Text );

        ………..

|




- 기존 데이터 수정

……….

ListView.Items[i].SubItems[ 0 ].Text = iYear.ToString();

……..




- 특정 데이터 삭제 ( 순회 방법을 foreach를 사용함 )

………

foreach( ListViewItem lvi in ListView.Items )

{

        if( lvi.SubItems[ 0 ].Text == “2005” )

               ListView.Items.Remove( lvi );

}

…………




- 리스트 뷰의 특정 행을 선택한 경우 알고 싶을 때
ListView.SelectedListViewItemCollection  Items = ListView.SelectedItems;


// 리스트 뷰의 컨트롤 속성이 멀티 선택 가능 상태에서 복수 개 선택을 하였다면 선택된 것이 다 나온다.
foreach( ListViewItem lvi in Items )

{

…….

}





2. 콤보 박스


- 콤보 박스의 데이터 모두 삭제

: combobox.Items.Clear();




- 데이터 추가

: combobox.Items.Add( “LIFEOnline” );




- 목록 중 지정된 데이터 목록을 찾아서 선택 되도록 하기

int index = combobox.Items.IndexOf(“LIFEOnline” );

if( index < 0 )

return;


combobox.SelectedIndex = index;







3. 그리드 컨트롤


- 그리드 컨트롤을 실행 시 데이터 추가

DataGrid grid = new DataGrid();

DataTable dt = new DataTable();

DataRow dr;



// 컬럼 헤드를 추가

dt.Columns.Add( new DataColumn("아이템", typeof(string)) );

dt.Columns.Add( new DataColumn("Code", typeof(Int32)) );

                                

// 레코드 추가                                

dr = dt.NewRow();

  

dr[ 0 ] = “칼”;  // 아이템 컬럼에 아이템 이름 추가

dr[ 0 ] = 110;    // 코드 컬럼에 코드 번호 추가

                                

dt.Rows.Add(dr);  // 레코드를 추가 한다.



DataView dv = new DataView(dt); // 데이터 뷰를 만든다.

grid.DataSource= dv;               // 그리드 컨트롤에 추가



- 그리드 컨트롤의 컬럼 스타일 지정

그리드 컨트롤에 데이터를 넣르면 컬럼이 지멋대로 되는 경우가 있다.. 이럴 때 원하는 스타일로

컬럼을 지정하면 된다..다만 꼭 데이터를 다 넣은 후에 해야 된다. 그전에 하면 데이터를 넣으면서
원하지 않는 상태로 변경되어 버린다.

…………………………………………………………….

DataGridTableStyle gtStyle1 = new DataGridTableStyle();  



gtStyle1.GridColumnStyles.Add(new DataGridTextBoxColumn());

gtStyle1.GridColumnStyles[0].MappingName = “아이템”; // 이 이름이 컬럼 스타일을 바꾸기를 원하는 컬럼의

                                                                          // 텍스트와 꼭 같아야 된다.

gtStyle1.GridColumnStyles[0].HeaderText = “아이템”;    // 컬럼의 텍스트를 지정한다.

gtStyle1.GridColumnStyles[0].Alignment = HorizontalAlignment.Center; // 중간 정렬

gtStyle1.GridColumnStyles[0].Width = 70;                               // 폭 지정

gtStyle1.GridColumnStyles[0].NullText = string.Empty;




gtStyle1.GridColumnStyles.Add(new DataGridTextBoxColumn());

gtStyle1.GridColumnStyles[0].MappingName = “Code”;    // 이 이름이 컬럼 스타일을 바꾸기를 원하는 컬럼의

                                                                 // 텍스트와 꼭 같아야 된다.

gtStyle1.GridColumnStyles[0].HeaderText = “Code”;       // 컬럼의 텍스트를 지정한다.

gtStyle1.GridColumnStyles[0].Alignment = HorizontalAlignment.Center; // 중간 정렬

gtStyle1.GridColumnStyles[0].Width = 70;                               // 폭 지정

gtStyle1.GridColumnStyles[0].NullText = string.Empty;



grid.TableStyles.Add(gtStyle1);            // 그리드 컨트롤에 세팅 한다.

……………………………………………………………..










- ADO.NET

1. 오라클 DB 연결

string strCommonConnection = “Data Source=ORA10;User ID=admin;assword=1111”;

OracleConnection OraCommonDBConnt = new OracleConnection( strCommonConnection );

OraCommonDBConnt.Open();




2. 오라클 DB 끊기

if( ConnectionState.Open == OraCommonDBConnt.State  )

        OraCommonDBConnt.Close();




3. DataSet을 사용한 쿼리 작업

OracleDataAdapter OraDataAdapter = new OracleDataAdapter();

OracleCommand cmd = new OracleCommand();

cmd.Connection = OraCommonDBConnt;

cmd.CommandText = “SELECT * FROM Member”;

OraDataAdapter.SelectCommand =  cmd;

OraDataAdapter.Fill( ResultDataSet , strTableName );




4. DataReader를 사용한 쿼리 작업

OracleDataAdapter OraDataAdapter = new OracleDataAdapter();

OracleCommand cmd = new OracleCommand();

cmd.Connection = OraCommonDBConnt;

cmd.CommandText = “SELECT * FROM Member”;

DataReader outDataReader = cmd.ExecuteReader();

              

if( false == outDataReader.HasRows )

return false;


………….

// 원하는 필드의 인덱스 번호를 알아낸다.

int IndexDex   = outDataReader.GetOrdinal("Dex");

…………..




while( dataReader.Read() )

{

   …………………..

    CharInfo.DEX = outDataReader.GetInt32( IndexDex );

   ……………….

}




5. 테이블의 데이터 모두 삭제

string strContext = "DELETE FROM " + TableName;

OracleCommand cmd = new OracleCommand();

cmd.Connection = OraCommonDBConnt;

cmd.CommandText = strContext;

cmd.ExecuteNonQuery();




6. DataSet의 내용을 DataGrid 컨트롤에 넣기

GridQueryResult.SetDataBinding( ResultDataSet, strTableName );




7. 간단하게 DataSet을 이용한 테이블의 데이터 갱신

// 이전에 쿼리 작업을 한 DataAdapter를 사용해야 된다. 그렇지 않을 경우 DataAdapter에 업데이트 및 삭제 로직을

// 등록 해줘야 된다.

// 이 작업은 쿼리를 하여 DataGrid 컨트롤에 넣은 경우 DataGrid의 데이터를 수정 한 후 이 내용을 DB에 업데이트

// 하고 싶을 때 사용한다.

OracleCommandBuilder cb = new OracleCommandBuilder( OraDataAdapter );

cb.RefreshSchema();

OraDataAdapter.Update( dataset, TableName );




8. DataSet의 내용을 XML 파일로 저장

DataSet ds = new DataSet();

……….

ds.WriteXml( filename );
// 이후 위의 7번 방식을 이용해서 데이터를 추가 한다.

……





9. 테이블의 모든 데이터를 지우고 XML의 데이터를 추가 하기

// 테이블의 레코드를 모두 지운다.

……….

// ds 라는 DataSet에서 XML 파일을 읽어 들인다.

DataSet ds = new DataSet();

ds.ReadXml( textBoxFilePath.Text );










- 파일



1. 클래스 단위로 파일에 쓰기

이 직렬화 방식은 꼭 .NET 플랫폼에서 서로 파일을 읽고 쓸 때만 사용 가능하다.
만약 .NET으로 만든 프로그램에서 아래와 같이 파일을 만들고 이것을 네이티브에서

읽으면 앞에 다른 값이 들어가 있다( 정확하게는 직렬화 되는 클래스의 메타 정보가

들어가 있다 ).


FileStream GloveFile = new FileStream( "0.ipt", FileMode.Create);

BinaryFormatter formatter = new BinaryFormatter();

formatter.Serialize( GloveFile, ItemFileclass );





2. 현재 실행 하고 있는 프로그램의 실행 경로 얻기

Environment.CurrentDirectory

를 이용하면 실행 경로를 얻을 수 있다.







- 네트워크

1. 웹에 있는 파일을 받기

정확하게 말하면 http 프로토콜을 이용하여 웹에 있는 파일을 다운로드 하는 방식을 말한다.

WebRequest myWebRequest = WebRequest.Create("http://jacking75.cafe24.com/Index.hml");

WebResponse myWebResponse = myWebRequest.GetResponse();



Stream ReceiveStream = myWebResponse.GetResponseStream();



ReceiveStream 객체를 파일 스트림을 이용하여 파일로 저장 하던가 다른 스트림으로 사용하면 된다.








- ETC



1. C#에서의 XML 주석 코드 제작을 위한 주석 작성 요령

: public bool IsEnableExecute( int iReqList )
{

    …………

}

가 있다면

/// <summary>

/// 현재 수행하는 기능을 수행 가능한가

/// <summary>

/// <param name="iReqList">수행할 기능의 인덱스</param>

/// <returns name="true">수행가능</returns>

/// <returns name="false">수행불능</returns>

public bool IsEnableExecute( int iReqList )
{

    …………

}

이렇게 작성한다.




2. 다른 클래스에 있는 const로 정의한 상수를 이용 방법
: 상수는 다음과 같이 정의 되어 있다.

public class PacketDefine

{

   Public const int Packet_First = 0;

   ………..

}



이것을 Command 클래스에서 사용 할려면

…………

Int packetfirst = PacketDefine.Packet_First;

………….


사용한다.




3. 데이터 변환.

: 데이터 변환을 위해서는 Convert의 멤버를 사용한다.

Convert.Toxxx( xxx )를 사용하면 된다.
예) 스트링을 int 변환
Convert.ToInt32( string );




3. 바이트 배열을 지정된 위치와 크기로 복사할 경우
: Buffer.BlockCopy( ……. );




4. 클래스의 크기를 알고 싶을 때

: Marshal.SizeOf(LoginPacket)

LoginPacket는 인스턴스 화된 객체이어야만 한다. LoginPacket의 클래스인 LOGIN_PACKET를 사용하면 안된다.




5. 외부 프로그램 실행

: 여기서 인터넷 익스플로어를 실행해서 본인의 홈페이지에 가는 것을 예를 들겠다.

System.Diagnostics.Process IEProcess = new System.Diagnostics.Process();

IEProcess.StartInfo.FileName = "iexplore.exe";

IEProcess.StartInfo.Arguments = "http://jacking75.cafe24.com ";

IEProcess.Start();



6. 메시지 박스

- 일반 메시지 박스 사용

MessageBox.Show( "클라이언트에서 사용할 스킬 정보를 파일로 저장 하겠습니까 ?" );



- YES / NO 버튼 사용

if( DialogResult.Yes == MessageBox.Show( "클라이언트에서 사용할 스킬 정보를 파일로 저장 하겠습니까 ?",

                                                            "이진 파일 저장", MessageBoxButtons.YesNo ) )



7. 한글 파일 출력 문제

- 정확한 이유는 모르지만 한글을 파일에 입력할 때 인코딩을 Default 방식으로 지정하면

한글 XP에서는 한글을 아스키 코드 값으로 제대로 인식하지만 윈도우 2003에서는 한글을

유니코드 방식으로 인식하여 한글 1글자를 아스키 코드 1글자로 인식하는 경우가 있다.


string strValue = “개”;

encodedBytes = System.Text.Encoding.Default.GetBytes(strValue);        



한글 XP에서 읽는다면 encodedBytes의 길이가 2개로 나오지만 윈도우 2003에서는

길이가 1로 된다.



이 문제를 해결할려면 인코딩 방식을 명시적으로 지정해야 된다.

string strValue = “개”;

encodedBytes = System.Text.Encoding.GetEncoding(949).GetBytes(strValue);




8. 폼의 마우스 커서 변경

- 화살표 마우스 커서      this.Cursor = Cursors.Arrow;

- 모래시계 커서                this.Cursor = Cursors. WaitCursor;

- 손 커서                         this.Cursor = Cursors. Hand;

- 기본 커서                      this.Cursor = Cursors. Default;

등등…….




9. 네이티브의 time(&time_t)에서 얻은 초단위의 시간을 C#에서 사용

- time함수를 이용하여 얻은 시간은 시작이 1970년부터이고 C#의 경우는

0년 1월1일 부터이다..그래서 서로 호환이 되지 않느다. 이것을 해결할려면

다음과 같이 하면 된다.



int iTime = C타임함수값;    
DateTime dt = new DateTime(1970, 1, 1, 9, 0, 0); // 한국은 GMT+9시간
dt = dt.AddSeconds(iTime);

반응형
Posted by blueasa
, |

최근 메신저를 만들다가..

쪽지를 수신하는 부분에서... 다른 곳에서 작업을 하고 있을 때..

쪽지가 도착하면 포커스가 빼앗기는 상황이 발생하더군요.

포커스를 빼앗기면 안되는데 말이죠..

 

이를테면 쪽지를 쓰고 있는데.. 쪽지가 도착하면 새로운 폼이 등장하게 되면서..

포커스를 빼앗기는 것 입니다.

 

이 부분을 해결하는데 생각보다 꾀 많은 시간이 투자되었네요.

 

일단 발견한 방법은 2가지 입니다.

 

1. Win32API를 사용한다.

2. ShowWithoutActivation 프로퍼티를 상속받아서 Child Form Class를 구현한다.

 

그럼 차례대로 소개하도록 하겠습니다. 그리 어렵지 않습니다.

 

 

1. Win32 API - ShowWindow함수 사용

 

//아래 처럼 user32.dll을 dll import합니다.

[System.Runtime.InteropServices.DllImport("user32.dll")]

public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

 

//그리고 아래처럼 사용하시면 되겠습니다.

RecvMemoWnd memo = new RecvMemoWnd (strTitle, strContent, strTime, strSender);

ShowWindow(memo .Handle, WM_SHOWNOACTIVATE); //WM_SHOWNOACTIVATE = 4

 

 

2. 닷넷 - ShowWithoutActivation를 오버라이드하는 Child Form Class

 

public class Test : Form

{

   bool showWithoutActivation = false;

   protected override bool ShowWithoutActivation

   {

      get

      {

         return showWithoutActivation;

      }
   }

 

   public void Show(bool activate)

   {

      showWithoutActivation = !activate;

      Show();
   }
}

 

<-------------------------------------------------------------------->

 

Test test = new Test();

test.Show(false);

 

 

어렵지 않네요. 다만 자료가 많이 않아서 시간이 조금 걸렸을 뿐...

반응형
Posted by blueasa
, |

닷넷 프레임워크를 이용하는 동안, 의외로 곳곳에 훌륭한 기술들이 많이 숨어있습니다. 특히 문자열 처리에 관한 부분은 특별한 경우가 아니면, 기본으로 내장되어있는 API들 (Formatting API와 정규 표현식 API)만으로 쉽게 처리가 가능합니다. 예전 블로그 아티클 중에 정규표현식에 관련된 아티클들이 몇 가지 있으니 이 아티클과 더불어서 보시면 좋을것 같습니다.

 

오늘 살펴보려고 하는 내용은 String Formatting API에 대한 내용입니다.

 

1. 자유자재로 사용하는 치환자

 

대부분의 예제, 대부분의 코드에서는 String Formatting API에 서식 문자열을 지정할 때, 인자 순서대로, 단 한 번씩만 치환자를 사용합니다. 하지만, 같은 치환자를 여러번 중복해서 사용하거나, 인자 순서와는 별개로 지정할 필요는 많습니다. 이럴 때에는, 걱정하지 말고 매개 변수 개수에 유의하면서 치환자를 자유롭게 사용하면 됩니다.

 

String.Format("{0} {1} {1} {4} {3} {2}", 'a', 'b', 'c', 'd', 'e');
// => a b b e d c

 

2. C# 만의 편리한 기능: Verbatim String과 함께 사용하는 강력한 Formatting API

 

여러 줄에 걸친 문자열을 별도의 데이터 파일이 아닌, C# 코드 내에 포함할 수 있다면, 좀 더 String Formatting API를 극적으로 활용할 수 있을 것입니다. 이럴 때, Verbatim String을 활용하면 좋습니다. Verbatim String은 @" 으로 시작하여 " 로 끝이나는 문자열 구문 전체를 말합니다. 이 문자열 블럭 안에는 Back Slash나 CR/LF 등의 문자를 포함할 수 있습니다.

 

String.Format(@"<html>
<head><title>Hello World!</title></head>
<body>
<p>{0}</p>
</body>
</html>", DateTime.Now);

 

다만 유의할 점이 하나 있다면, 문자열이 파일로부터 나타난 것이든, Verbatim String에 의한 것이든, 의미를 다르게 해석할 가능성이 있는 글자 (예: '{' 나 '}' 같은 글자)들은 그 의미를 정확하게 살릴 수 있도록 지정하거나, 같은 문자를 연속으로 두번으로 지정하여 이스케이프 처리해야 합니다. (예: "{{", "}}")

 

String.Format(@"int main(int argc, char **argv) {
return 0;
}");

 

즉, 위의 경우 String.Format 메서드에서 오류를 반환합니다. 치환자 시작 기호 다음에 적절한 수식 대신 다른 문자열들이 열거되기 때문에 치환할 수 없다는 오류가 발생합니다. 위의 경우 중괄호 부분들을 아래와 같이 수정해야 합니다.

 

String.Format(@"int main(int argc, char **argv) {{
return 0;
}}");

 

위의 예시에서는 C 언어 코드에 대한 것을 예로 들었습니다만, 같은 방법으로 C# 프로그래밍 코드를 코드 안에 포함하여 재사용할 수도 있습니다. 또는, IronPython 등의 코드를 Embedding하여 DLR에서 사용할 수 있도록 재구성하는 시나리오도 생각해 볼 수 있을 것입니다.

 

3. 날짜 및 시간 표현을 자유자재로 활용하기

 

아직도 날짜 및 시간 표현을 위하여 문자열을 조립하거나, 알고리즘을 사용하여 오전/오후를 구분하십니까? 그렇게 할 이유가 없습니다. 오히려 좀 더 세밀하고 다양한 기능을 제공하는 기본 기능이 있기 때문입니다.

 

String.Format(@"{0:yyyy-MM-dd}", DateTime.Now); // 2009-01-30
String.Format(@"{0:tt hh:mm:ss}", DateTime.Now); // 오전 01:47:33
String.Format(@"{0:yyyy-MM-dd tt hh:mm:ss}", DateTime.Now); // 2009-01-30 오전 01:48:11

 

만약 오전/오후에 해당하는 문자열을 한글이 아닌 영문 표기 (AM/PM)로 변경하려면 어떻게 해야 할까요? 이럴 때에는 CultureInfo 객체를 Format 메서드에 전달하면 간단해집니다. CultureInfo는 System.Globalization 네임스페이스 안에 있습니다.

 

String.Format(CultureInfo.GetCultureInfo("en-US"), @"{0:tt hh:mm:ss}", DateTime.Now); // AM 04:30:44
String.Format(CultureInfo.GetCultureInfo("ko-KR"), @"{0:tt hh:mm:ss}", DateTime.Now); // 오후 03:03:02
String.Format(CultureInfo.GetCultureInfo("ja-JP"), @"{0:tt hh:mm:ss}", DateTime.Now); // 午後 10:08:03

 

위의 예시에서 주석으로 표시한 것과 같이 현재 시간에서 "오전"과 "오후"에 대한 표현을 해당 국가의 언어의 표기법에 맞추어 표기하고 있습니다. en-US는 언어를 영어로 사용하며 지리적으로 미국을 기준으로 한다는 의미로 해석되며, ko-KR은 언어를 한국어로 사용하고 지리적으로는 대한민국, ja-JP는 언어를 일본어로 사용하고 지리적으로 일본을 기준으로 한다는 의미로 해석됩니다.

 

위와 같이 언어 및 지역 코드를 설정할 때 알아야 할 사항이 두 가지가 있는데, 첫 째는 반드시 언어 코드의 전체 이름을 기재해야 합니다. 예를 들어, en-US에서 en만 지정하면 en에 해당하는 설정은 "중립 문화권"이기 때문에 CultureInfo.GetCultureInfo 메서드로는 받아들일 수 없습니다. 그리고 US만 지정하면 US에 해당하는 코드가 없으므로 역시 오류가 발생합니다. 그리고, 언어 코드가 시간대 설정까지 자동으로 반영하는 것은 아니므로 en-JP (언어는 영어이며 지역은 일본)와 같은 설정은 유효하지 않으며 표준 코드 정의 내역에 없기 때문에 받아들여지지 않습니다. 시간대에 대한 설정은 http://msdn.microsoft.com/ko-kr/library/system.timezone.aspx 에 소개된 TimeZone 클래스 (닷넷 3.5부터 사용 가능합니다)를 활용해야 합니다.

 

4. 통화 금액 표현하기

 

지역 설정을 이용하여 손쉽게 처리할 수 있는 일이 또 한 가지 있는데, 바로 통화 금액 표기에 관한 것입니다. 아래의 코드를 살펴보기로 하겠습니다.

 

String.Format(CultureInfo.GetCultureInfo("es-ES"), "{0:C}", 300); // 300,00 €
String.Format(CultureInfo.GetCultureInfo("ko-KR"), "{0:C}", 300); // \300

 

그리고, 좀 더 구체적으로 소수점 자릿수 등을 표현하거나, 음수/양수/영점 표현을 설정하고자 한다면 아래와 같이 활용할 수 있습니다. (Delphi Basic 웹 사이트 http://www.delphibasics.co.uk/RTL.asp?Name=FormatFloat 에서 부분 발췌한 샘플 코드를 올립니다.)

 

// 반올림 예시
String.Format("{0:#####}", 1234.567);
String.Format("{0:00000}", 1234.567);
String.Format("{0:0}", 1234.567);
String.Format("{0:#,##0}", 1234.567);
String.Format("{0:0,0}", 1234.567);

// 소수점 사용 예시
String.Format("{0:0.####}", 1234.567);
String.Format("{0:0.0000}", 1234.567);

// 공학용 표기
String.Format("{0:0.0000000E+00}", 1234.567);
String.Format("{0:0.0000000E-00}", 1234.567);
String.Format("{0:#.#######E-0#}", 1234.567);

// 음수/양수/ZERO 에 따른 표기
String.Format("{0:0.0}", -1234.567);
String.Format("{0:0.0 CR;0.0 DB}", -1234.567);
String.Format("{0:0.0 CR;0.0 DB}", 1234.567);
String.Format("{0:0.0 CR;0.0 DB;Zero}", 0.00);

5. Bonus: 자연스러운 16진수 표기 방법 (String.Format을 사용하지 않습니다.)

 

"0x" + (16).ToString("X8"); // 8자리 16진수 표기, 대문자
"0x" + (33).ToString("x4"); // 4자리 16진수 표기, 소문자

 출처: http://www.rkttu.com/

반응형
Posted by blueasa
, |

C#에서 Win32 API 사용하기

 

개요

Win32 API를 불러올 때, 함수의 명칭, 인자, 리턴 값을 가지고 불러오게 되어 있다. 하지만, C#에서 타입들이 모두 객체(Object)의 형식이며, 일반적인 C 의 데이터 형과 상이한 모양을 가진다. 이러한 문제들을 해결할 수 있는 것이 PInvoke 기능이다.

 

PInvoke( Platform Invocation Service)는 관리화 코드에서 비관리화 코드를 호출할 방법을 제공한다. 일반적인 용도는 Win32 API의 호출을 위해 사용한다.

 

namespace PinvokeExample

{

using System;

 

             using System.Runtime.InteropServices; // 반드시 입력해야 한다.

 

             public class Win32

             {

                           [DllImport(“user32.dll”)]

                           public static extern int FindWindow(string a, string b);

                           

             }

}

 

위 예제는 FindWindow라는 user32.dll C함수를 사용하는 모습을 보여주고 있다. 실제 FindWindow의 선언은 다음과 같다.

 

             HWND FindWindow(LPCSTR swClassName, LPCSTR swTitle);

 

HWND는 윈도우 핸들을 표현하는 32비트 정수 이므로, int형으로 치환되고 LPCSTR 형은 NULL로 끝나는 문자열을 표현한다. 이때 PInvoke string을 자동으로 LPCSTR로 치환해 주는 역할을 하게 된다.

이 문서에서는 이처럼 Win32 API 함수의 여러 유형들을 어떻게 C#에서 사용 할 것인지에 대하여 알아보자.

 

WIN32 데이터형의 치환

Win32 API에서 일반적으로 사용하고 있는 데이터형은 모두 C#의 데이터 형으로 치환될 수 있다.

 

Win32 API TYPE

C#

BOOL, BOOLEAN

bool

BYTE

byte

CALLBACK

delegate

COLORREF

int

DWORD

int

DWORD_PTR

long

DWORD32

uint

DWORD64

ulong

FLOAT

float

HACCEL

int

HANDLE

int

HBITMAP

int

HBRUSH

int

HCONV

int

(모든 HANDLE 타입) Hxxxx

int

LPARAM

long

LPCSTR

[in] string [out] StringBuilder

LPBOOL

ref bool

이외 LP* 

ref 형식

UINT

uint

Uxxxx

unsigned 타입들..

WORD

Short

WPARAM

Uint

 

 

Structure 의 전달

예를 들어 POINT 형의 경우,

typedef struct t_Point {

             int x;

             int y;

} POINT;

 

이것은 기본적으로 다음과 같이 선언될 수 있다.

[순차적]

[StructLayout(LayoutKind.Sequential)]
public struct Point {
      public int x;
      public int y;
}

 

[명시적]

[StructLayout(LayoutKind.Explicit)]
public struct Point {
      [FieldOffset(0)] public int x;
      [FieldOffset(4)] public int y;
}

 

일차적으로 할당되는 메모리 레이아웃이 동일하다면, C#에서 바로 받아 들이 수 있다.

 

// BOOL SetWindowPos(POINT pos); 이런 함수가 있다고 가정하면… ^^

 

[DllImport (“user32.dll”)]

public static extern bool SetWindowPos(Point pos);

 

사용할 함수 이름 바꾸기

여기서 함수의 이름을 바꿔서 사용하고 싶다면 다음과 같이 변경하면 된다.

 

// BOOL SetWindowPos(POINT pos);

 

[DllImport (“user32.dll”, EntryPoint = “SetWindowPos”)]

public static extern bool ShowAt(Point pos);

레퍼런스형 전달하기

 

LPPOINT형은 POINT의 포인터 형이므로 ref Point와 같이 사용 할 수 있다. 실제 사용하는 형식은 다음과 같다.

C 언어의 포인터의 경우 레퍼런스로 사용하려고 하면, ref 키워드를 사용하는 방법이 있다.

// BOOL SetWindowPos(HWND hWnd, LPRECT lpRect);

[DllImport(“user32.dll”)]

public static extern bool SetWindowPos(int hWnd, ref Rect lpRect);

 

Out형 함수 인자 사용하기

MSDN 같은 곳에서 함수의 선언을 살펴보면 다음과 같은 형식의 함수를 볼 수 있을 것이다. 이러한 형식은 레퍼런스 형으로 결과를 함수의 인자에 보내겠다는 말이다. 이러한 형식은 Win32 API에서 많이 쓰이고 있고, 포인터를 사용하므로, 많은 주의를 기울여야 한다.

 

BOOL GetWindowRect(
  HWND hWnd,      // handle to window
  LPRECT lpRect   // window coordinates
);

Parameters

hWnd

[in] Handle to the window.

lpRect

[out] Pointer to a RECT structure that receives the screen coordinates of the upper-left and lower-right corners of the window.

 

여기서 LPRECT는 앞 절에서 설명한 Structure의 전달을 참고하여 치환 될 수 있다.

여기서 lpRect RECT의 포인터이며, GetWindowRect 함수 내에서 이 포인터에 직접 값을 쓰게 되어 있다. 즉 이 포인터는 값을 기록하기 위한 인자이지, 값을 전달하기 위한 인자는 아닌 것이다. 이것은 또 다른 C# 레퍼런스 연산자인 out 키워드를 사용하여 쉽게 해결 할 수 있다.

public static extern bool GetwindowRect(int hWnd, out Rect lpRect);

 

실제 사용하는 모습은 다음과 같다.

public static extern bool GetWindowRect(int hWnd, out Rect lpRect);

public static void UseFunction() {

        Rect _rect; // 값을 대입하지 않아도 된다.

        Win32.GetWindowRect(hwnd, out _rect);

}

 

참고로 ref 키워드는 입력과 출력 둘 다 사용 할 수 있다. 그러나 ref를 사용하는 변수가 값이 설정되어 있다는 가정을 하고 있으므로, 이전에 반드시 어떠한 값을 입력해야 한다.

실제 사용 예는 다음과 같다.

public static extern bool GetWindowRect(int hWnd, ref Rect lpRect);

public static void UseFunction() {

        Rect _rect = new Rect(); // 꼭 값을 대입해야 한다.

       

        _rect.top = 20; _rect.left = 30;

        _rect.bottom = 50; _rect.right = 60;

 

        Win32.GetWindowRect(hwnd, ref _rect);

}

 

여기서 잠깐

대중없이 Rect라는 구조체가 나오는데 이는 API에서 RECT형을 C#으로 바꾸어 사용하는 structure이다. 앞의 예제들은 다음과 같은 선언을 하였다고 가정한다.

[StructLayout(LayoutKind.Explicit)]
public struct Point {
      [FieldOffset(0)] public int top;
[FieldOffset(4)] public int left;
[FieldOffset(  ] public int bottom;
[FieldOffset(12)] public int right;

}

 

 

CALLBACK 함수의 선언

C 언어에서 콜백 함수는 함수 포인터로 존재하게 된다. 이것은 함수 인스턴스의 포인터로, 함수 자체를 전달하게 되는 방식이다. 대표적으로 사용되는 부분은 EnumWindows 함수이다.

// BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARMAM IParam)

이 함수는 현재 열려 있는 모든 윈도우 핸들을 열거하기 위한 함수로 실제 처리하는 부분은 함수 포인터, 즉 콜백함수인 lpEnumFunc에서 처리하게 되어 있다. WNDENUMPROC 타입의 선언은 다음과 같다.

// typedef BOOL (CALLBACK* WNDENUMPROC)(HWND, LPARAM);

public delegate bool Callback(int hWnd, long lParam);

이러한 콜백 함수 역할을 하는 C#의 프리미티브는 delegate이다. CALLBACK delegate로 지환된다.

 

결과적으로 다음과 같이 사용하게 된다.

namespace ada.appshare

{

             public delegate bool Callback(int hwnd, int lParam);

             

             internal class Win32

             {

                

                           internal static extern int EnumWindows(CallBack x, int y);

                           [DllImport("user32.dll")]

 

                public static bool EnumWindowsCallback(int hWnd, int lParam)
                {

                        System.Console.WriteLine(“” + hWnd);

                        return true;

                }

                 

             }

 

        public static void Main(String []args)

        {

                Win32.Callback call
= new Win32.Callback(Win32.EnumWindowsCallback);

                Win32.EnumWindows(call, 0);

        }

}

 

 

반응형
Posted by blueasa
, |

종료버튼 클릭시 최소화 시키기

 

1. 상태 Flag 변수 선언

2. Form_Closing Event에서 if(flag) else 문 처리

3. WndProc함수 재 정의

 

        private bool isExit = false; //선언

 

         private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            // 진짜 종료
            if (isExit == true)
            {

                 //...기타작업

                e.Cancel = false;
            }
            // 숨김
            else
            {

                this.hide();
                e.Cancel = true;
            }
        }

 

위처럼 이벤트 처리하면 우선 X버튼 클릭시 종료가 되지 않고 숨어버리게 되고

특정 버튼 클릭시 isExit 값을 변경해 주면 종료가 되게 된다.

 

하지만, 문제점!

윈도우 종료 시킬때 프로그램이 종료되지 않는다!ㅋㅋㅋ

 

그러면 아래처럼 정의해주면 끝~ㅋㅋㅋ

 

        protected override void WndProc(ref Message m)
        {
            UInt32 WM_QUERYENDSESSION = 0x11;   // Logoff or shutdown

            /*----------------------------------------------------*/
            /* 윈도우 종료시에 종료시켜 버린다.                   */
            /*----------------------------------------------------*/
            if (m.Msg == WM_QUERYENDSESSION)
            {
                isExit = true;
            }


            base.WndProc(ref m);
        }

반응형
Posted by blueasa
, |

@ 기호
@ 기호를 사용하면 문자열 생성자가 이스케이프 문자와 줄 바꿈을 무시하도록 할 수 있습니다.
@ 기호 뒤 문자열은 형태가 그대로 보존 된다고 보시면 됩니다. 이스케이프 문자를 무시하는 것이죠

아래 예제에서 p1 과 p2가 같은 결과를 보여 줍니다.
 
string p1 = "\\\\My Documents\\My Files\\";
string p2 = @"\\My Documents\My Files\";


출처 : http://www.hoons.kr/Board.aspx?Name=QACSHAP&Mode=2&BoardIdx=33871&Key=Title&Value=%40%22
반응형
Posted by blueasa
, |

           string strFullPathName;
            string strDirectoryName;
            string strFileName;

 

            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "실행화일(exe)|*.exe";

 

            if (DialogResult.OK == openFileDialog.ShowDialog())
            {
                strFullPathName = openFileDialog.FileName;

                strDirectoryName = System.IO.Path.GetDirectoryName(strFullPathName);
                strFileName = System.IO.Path.GetFileName(strFullPathName);

 

                MessageBox.Show(strFullPathName);
                MessageBox.Show(strDirectoryName);
                MessageBox.Show(strFileName);

             }

 

화일작업을 하다보면 화일명 또는 디렉토리명만 가져오고 싶은 경우가 있다..

 

이런경우 어떻게 하면될까..?

 

예를들어, C:\Windows\System32\aa.exe  가 있다고 하면

 

Full Path == "C:\Windows\System32\aa.exe"

Directory Name  == > "C:\Windows\System32"

File Name ==> "aa,exe"

 

이런식이다..

 

 

C++에서는 "\"문자찾아서 잘라내기 했던 기억이 있다.

 

하지만, C#에서는 이를 위한 클래스가 있다.

Path.GetDirectoryName()과 Path.GetFileName()이 그것이다..

 

필요할때 쓰면될것 같다. ^^

 

 

 

 

 

또하나.. 시스템 폴더명을 알아보자..

 

시스템폴더는 OS에 따라 Windows\System32가 될수도 있고, Winnt\System32가 될수있다.

 

            string strSysDir = Environment.SystemDirectory.ToString();
            MessageBox.Show(strSysDir);

 

위와같이 Environment.systemDirectory()를 이용하면 된다. ^^


출처 : http://club.paran.com/club/home.do?clubid=eypgworld-bbsView.do?menuno=2509143-clubno=1078741-bbs_no=0PIGp

반응형

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

C# 종료버튼 클릭시 최소화 시키기  (0) 2010.07.20
@" 는 무슨 의미인가요?  (0) 2010.07.20
은양의 프로그래밍 세상  (0) 2010.07.19
이펙티브 C# - 요점 정리  (0) 2010.07.19
Form Show()/Hide()  (0) 2010.07.19
Posted by blueasa
, |
반응형
Posted by blueasa
, |
반응형
Posted by blueasa
, |