'C#'에 해당되는 글 50건
- 2008/09/24 C# Deep Copy
- 2008/08/23 [C#] ListBox DrawItem 에 대한 의견.. (4)
- 2008/08/21 [C#] Round Rectangle 처리하기 (2)
- 2008/08/16 [C#] Image Blend - 두장 이미지 블랜딩 처리 하기
- 2008/08/13 [C#] BindingSource 의 Current의 값 가져오기
- 2008/08/08 [C#] OpenGL 코드 연동하기
- 2008/06/11 C# Ftp File Upload - File Type 처리할때
- 2008/03/28 [C#] - 레지스트리 ( Registry ) 값 읽기( Read ) 및 쓰기( Write )
- 2008/03/20 [C#] 디자이너 페이지 오류
- 2008/03/13 [C#] - string.Split 사용법
- 2008/03/13 [C#] - Simple Update Manager (Http 프로토콜 통한 다운로드 : WebClient, DownloadFileAsync)
- 2008/03/13 [C#] - 디렉토리 검사 및 생성 (Directory, DirectoryInfo)
- 2008/03/13 [C#] - StreamReader, Regex, 텍스트 라인 파서
- 2008/03/13 [C#] C++ 바이너리(Binary) 데이터를 C# BinaryReader 로 읽기.
- 2008/03/04 [C#] - 회전형태의 메뉴 화면 처리 GsiCarousel 데모
C#을 사용하다 보면 포인터의 개념이 없기 때문에 클래스인 경우는 참조 형태로 처리가 되는거 같아요.
A 의 클래스를 a, b로 선언하고 a의 값을 b로 대입하게 되면 참조 형태가 되어서 a의 값을 바꾸게 되면
결국에 b의 값도 바뀌게 되는 경우가 있습니다.
물론 데이터형인 경우는 깊은 복사가 이루어 지지만 클래스인 경우는 일반 복사가 이루어 지는듯 합니다.
간혹 깊은 복사를 해야 할때가 오는데요..
ICloneable을 상속 받아서 처리 하면 아래와 같이 처리 하면 될듯하네요.
// 샘플 코드
class Cell : ICloneable
{
string var;
public string Var
{
get { return var; }
set { var = value; }
}
public Cell(string var)
{
this.Var = var;
}
public object Clone()
{
return new Cell(this.Var);
}
}
class Cells : List<Cell>, ICloneable
{
public Cells()
{
}
public object Clone()
{
Cells listCell = new Cells();
foreach (Cell c in this)
{
listCell.Add((Cell)c.Clone());
}
return listCell;
}
}
맨날 도구상자에 있는 컨트롤만 쓰고 있는 나로서는..
새로운 UI를 구상할때면.. 좀 난감해 지네요 ^^..
이번에는 ListBox를 확장해야할듯 해서
바로 위와 같이 하나의 아이템에 복합적인 데이터가 들어가있다고 가정을 하고 작업을 해야 됩니다.
이미지 정보와 해당 이름 또는 나이 저노하 번호 등등..
이걸 위해서는 DrawItem()을 따로 구현해 줘야 되네요.
우선 데이터를 집어 넣을때는
listBox1.Items.Add(new TestTemplate("손병욱", "d:\\a.bmp"));
이와 같이 하나의 데이터 템플릿 클래스를 제작하고 그기에 맞도록 해당 데이터를 추가 해야 됩니다.
그리고 DrawItem()을 가능하게 하기 위한 ListBox의 설정또한 잊지 말아야 하구요.. ^^
간단하게 DrawItem의 드로잉 하는 부분을 아래와 같이 처리 하면 되는군요.
{
if(listBox1.Items.Count <= 0)
return;
// Set the DrawMode property to draw fixed sized items.
listBox1.DrawMode = DrawMode.OwnerDrawVariable;
// Draw the background of the ListBox control for each item.
e.DrawBackground();
// Create a new Brush and initialize to a Black colored brush by default.
Brush myBrush = Brushes.Black;
// Determine the color of the brush to draw each item based on the index of the item to draw.
switch (e.Index)
{
case 0:
myBrush = Brushes.Red;
break;
case 1:
myBrush = Brushes.Orange;
break;
case 2:
myBrush = Brushes.Purple;
break;
}
// 이 부분에서 해당 값을 가져 올때 TestTemplate의 값으로 형변환 한 후에 값을 접근가능..
TestTemplate tt = (TestTemplate)listBox1.Items[e.Index];
// Draw the current item text based on the current Font and the custom brush settings.
e.Graphics.DrawImage(new Bitmap(tt.path), e.Bounds);
e.Graphics.DrawString(tt.name, e.Font, myBrush,e.Bounds,StringFormat.GenericDefault);
// If the ListBox has focus, draw a focus rectangle around the selected item.
e.DrawFocusRectangle();
}
이때 이미지와 여러가지를 표현하기 위해서는 아래의 함수도 오버라이딩 해서 변경해줘야 하네요.
{
e.ItemHeight = 100;
}
위의 내용을 토대로 샘플을 하나 만들어 볼까 합니다.
하지만 고려되어야 하는 사항은 이미지가 들어가기 때문에
많은 양의 데이터를 읽어 들일때 UI가 블락킹 되는 현상이 불현듯 보이네요..
백그라운드 쓰레드나 일반 쓰레드를 통해서 따로 돌려야 할듯 합니다.
그러면 조금더 나은 UI 및 컨트롤을 구현할 수 있을거 같습니다.
개봉박두~~~..
RoundPanel 클래스를 제작했습니다.
Panel을 상속해서 처리 했습니다.
Round 하는 코드는 아래의 코드를 참조 하시면 됩니다.
{
int diameter = 2 * radius;
Rectangle arcRect =
new Rectangle(rect.Location, new Size(diameter, diameter));
GraphicsPath path = new GraphicsPath();
path.AddArc(arcRect, 180, 90);
arcRect.X = rect.Right - diameter;
path.AddArc(arcRect, 270, 90);
arcRect.Y = rect.Bottom - diameter;
path.AddArc(arcRect, 0, 90);
arcRect.X = rect.Left;
path.AddArc(arcRect, 90, 90);
path.CloseFigure();
return path;
}
Panel 함수에서 드로잉 하는 코드 입니다.
{
RoundPanel panel = (RoundPanel)sender;
Graphics g = e.Graphics;
g.SmoothingMode = SmoothingMode.HighQuality;
int width = panel.ClientRectangle.Width;
int height = panel.ClientRectangle.Height;
Rectangle rect = new Rectangle(0, 0, width-1, height-1);
using (GraphicsPath path = RoundPanel.GetRoundedRectPath(rect, 8))
{
using (Brush brush = new LinearGradientBrush(
new Rectangle(0, 0, panel.ClientRectangle.Width, panel.ClientRectangle.Height),
Color.FromArgb(panel.Opcity, 102, 102, 102),
Color.FromArgb(panel.Opcity, 0, 0, 0),
90.0f))
{
//graphics.FillRectangle(brush, 0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height);
g.FillPath(brush, path);
}
//g.FillPath(Brushes.Yellow, path);
Pen pen = new Pen(Color.FromArgb(panel.Opcity, 255, 255, 255));
g.DrawPath(pen, path);
}
}
이걸 처리 하다 보면 화면을 전환 하거나 리프레쉬할때 플리커 현상이 생기기도 합니다.
이걸 해결하기 위해서 RoundPanel에 더블버퍼링 처리 코드를 추가 했습니다.
{
...
this.SetStyle( ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint |
ControlStyles.DoubleBuffer, true);
}
실행 파일 :
.
관련 코드 :
.
Panel에 두장의 이미지(Bitmap)를 추가한 후에
위의 이미지에 알파값을 추가해서 블랜딩 효과를 줘봤습니다.
코드는 아래와 같아요..
private void panel_before_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.DrawImage(beforeLeftImage, new PointF(0, 0));
float[][] ptsArray =
{
new float[] { 1, 0, 0, 0, 0},
new float[] { 0, 1, 0, 0, 0},
new float[] { 0, 0, 1, 0, 0},
new float[] { 0, 0, 0, 0.7f, 0},
new float[] { 0, 0, 0, 0, 1}
};
ColorMatrix clrMatrix = new ColorMatrix(ptsArray);
ImageAttributes imageAtrr = new ImageAttributes();
imageAtrr.SetColorMatrix(clrMatrix,
ColorMatrixFlag.Default,
ColorAdjustType.Bitmap);
g.DrawImage(beforeXrayLeftIamge,
new Rectangle(50, 50, beforeXrayLeftIamge.Width, beforeXrayLeftIamge.Height),
0, 0, beforeXrayLeftIamge.Width, beforeXrayLeftIamge.Height,
GraphicsUnit.Pixel,
imageAtrr);
}
C#의 Winfor에서 DataSet을 사용할때 BindingSource를 적용할 수 있습니다.
솔직히 아직까지 많은 부분 제대로 파악되지 않은듯 하지만.
참 편한듯 하지만 아직까지 사용하기 힘드네요.
우선 아래의 이미지 처름 MS Access의 파일을 사용해서
member, detail의 테이블을 제작했습니다.
member의 "_name"와 detail의 "_name"의 연결이 되어 있습니다.
잘 몰라서 "관계" 대화창에서 "관계만" 이걸로만 연결했습니다.
문제는 여기서 member의 _name의 정보를 사용해서 삭제 할때
detail의 _name가 같은 경우 모두 삭제를 해야 하는데요.
같은 이름의 내용을 모두 삭제 해야 하는데 자동으로 되는건지 모르겠네요.
그래서 우선 아래와 같이 해결했습니다.
1. member의 항목을 선택한다.
2. member의 memberBindingSource.Current의 값을 얻어 와서 해당 "_name"를 구합니다.
3. detail의 "_name"의 같은 이름을 구해옵니다.(쿼리함수 생성)
4. 구해온 detailDataTable의 정보를 사용해서 detailTableAdapter.Delete() 에서 삭제합니다.
5. memberBindingSource.RemoveCurrent()를 사용해서 member의 데이터를 삭제합니다.
6. .EndEdit()를 통해서 편집을 마칩니다.
7. tableAdapterManager.UpdateAll()를 통해서 값을 업데이트 합니다.
코드는 아래와 같습니다.
private void btnDelete_Click(object sender, EventArgs e)
{
try
{
DataRowView drv = (DataRowView)this.memberBindingSource.Current;
TestJoinDataSet.memberRow memberRow = (TestJoinDataSet.memberRow)drv.Row;
TestJoinDataSet.detailDataTable ddt =
this.detailTableAdapter.GetDataBy(memberRow._name);
foreach (TestJoinDataSet.detailRow row in ddt.Rows)
{
this.detailTableAdapter.Delete(row.ID, row._name, row._info);
}
this.memberBindingSource.RemoveCurrent();
this.memberBindingSource.EndEdit();
this.detailBindingSource.EndEdit();
this.tableAdapterManager.UpdateAll(this.testJoinDataSet);
}
catch (InvalidOperationException oex)
{
MessageBox.Show(oex.Message);
}
catch (NotSupportedException nex)
{
MessageBox.Show(nex.Message);
}
catch (DataException ex)
{
MessageBox.Show(ex.Message);
}
}
이렇게 하는게 맞는지 조언 부탁해요 ^^
C#을 이용한 FTP로 파일 업로드 하는 코드 입니다.
MSDN에 있는
...........
StreamReader sourceStream = new StreamReader("testfile.txt");
byte [] fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());
.............
이런 코드를 사용하니까. 인코딩에서 데이터가 제대로 전달되지 못하는 문제가 발생합니다.
그래서 아래와같이 처리 했습니다.
private void btnFileUploadTest_Click(object sender, EventArgs e)
{
Upload("blue.jpg");
Upload("크기변환_dddd.png");
Upload("zskin.txt");
MessageBox.Show("Upload 가 완료되었습니다.");
}
private void Upload(string filename)
{
FileInfo fileInf = new FileInfo(filename);
string uri = "ftp://192.168.0.3:8451/" + fileInf;
FtpWebRequest reqFTP;
UriBuilder URI = new UriBuilder(uri);
URI.Scheme = "ftp";
reqFTP = (FtpWebRequest)FtpWebRequest.Create(URI.Uri);
reqFTP.Credentials = new NetworkCredential("administrator", "0000");
reqFTP.KeepAlive = false;
reqFTP.Method = WebRequestMethods.Ftp.UploadFile;
reqFTP.UseBinary = true;
reqFTP.ContentLength = fileInf.Length;
reqFTP.UsePassive = true;
int buffLength = 2048;
byte[] buff = new byte[buffLength];
int contentLen;
FileStream fs = fileInf.OpenRead();
try
{
Stream strm = reqFTP.GetRequestStream();
contentLen = fs.Read(buff, 0, buffLength);
while (contentLen != 0)
{
strm.Write(buff, 0, contentLen);
contentLen = fs.Read(buff, 0, buffLength);
}
strm.Close();
fs.Close();
}
catch (Exception ex)
{
throw;
}
}
C# 레지스트리 정보 읽기
C# 레지스트리 정보 쓰기
이 내용은 결국 프로그램의 규칙을 알지 못하고 막 짜다 보니 생기게 된 에러입니다. -.-;
하지만 지금도 확실한 에러 내용은 모르겠고, 저 같은 경우는 다음과 같이 해결했습니다.
문제가 생긴 부분은 아래의 코드 부분입니다.
{
public class UpdateInfo <--- 여기 클래스가 위치 하면서 오류가 남
{
public string UrlHttpPath { get; set; }
public string UrlDownloadFolder { get; set; }
public string UrlDownloadFile { get; set; }
}
{
int curIndex = 0;
...................
위의 코드에서 알 수 있듯이 시작하는 클래스가 Form1 인데
그 위에 다른 클래스가 존재 해서 문제가 생기는 거였다.
이 코드를 다른 파일이나 다른 위치로 옮기니 되었다.
char buf[128] 의 데이터를 아래와 같이 읽어 들일때.
string [] split = buf1.Split(new Char [] {'\0'});
buf1 = split[0];
buf1 이 128로 읽어 들이면, 뒤에 \0 의 값이 쭉 저장되게 된다.
그렇게 하면 buf1 의 길이는 128이 된다. 즉, 필요 없는 공간이 생기게 마련이다.
(혹.. 이거 말고 다른 방법으로 읽을수 있다면 꼭 연락좀.. -.- )
그래서 \0 을 Split을 사용해서 나눈 다음에 필요한 정보만 가져 오도록 한다.
string [] split = buf1.Split(new Char [] {'\0'});
를 하고 나면 split 에 \0 으로 나누어진 데이터가 배열로 저장 된다.
이렇게 하고 나면 제일 앞쪽에 필요한 데이터만 모이게 된다.
buf1 = split[0] 을 해서 buf1 에 필요한 데이터만 담을 수 있다.
[C#] - Simple Update Manager (Http 프로토콜 통한 다운로드 : WebClient, DownloadFileAsync)

HTTP 프로토콜을 사용해서 원격파일 다운로드 프로그램 만들고 있습니다.
HTTP 를 통해서 파일을 받을때는 WebClient 를 사용하고 있다.
단순하게 다운로드 받기 위해서는 아래와 같이 DownloadFile()를 사용한다.
webclient.DownloadFile(updatelistUrl, updatelistTxt);
그리고 다운로드 받는 상태를 알기 위해서는 DownloadFile 가 아닌 DownloadFileAsync 를 사용해야 한다.
그리고 받는 동안 호출되는 이벤트 함수와 다 받은후 처리 하는 함수를 등록해야 한다.
// 객체 생성
WebClient client = new WebClient();
// 이벤트 함수 등록
client.DownloadFileCompleted += new AsyncCompletedEventHandler(client_DownloadFileCompleted);
client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
// 받는 동안 프로그래스바의 Value에 추가한다. (퍼센트 값이 바로 제공된다.)
void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
progressfile.Value = e.ProgressPercentage;
}
//
void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
…
}
파일을 실제로 다운로드 받을때는 아래와 같이 처리 합니다.
(DownloadFileAsync 이것을 사용해야 이벤트 함수가 호출 됩니다.)
스레드로 해도 될 듯 한데 우선 작업 하기 편하게 타이머를 사용해서 제작 하였습니다.
Test 버튼을 누르면 해당 동작이 시작 됩니다.
[동작 순서]
- Updatelist.txt 파일을 다운로드 한다.
- Updatelist.txt 파일의 정보를 분석해서 다운로드할 파일을 구성한다.
- 해당 파일을 타이머를 통해서 다 받을 때 까지 반복한다.
- 다 받으면 자동 종료 또는 특정 실행 파일을 실행한다.
디렉토리를 생성할때 디렉토리가 생성되어 있는지 검사도 해야 한다.
Directory 나 DirectoryInfo 를 사용하면 디렉토리 생성 및 검사도 가능하다.
|
방법#1 |
if (Directory.Exists(rootPath) == false) prefix = o ns = "urn:schemas-microsoft-com:office:office" /> Directory.CreateDirectory(rootPath); |
|
방법#2 |
DirectoryInfo di = new DirectoryInfo(rootPath); if (di.Exists == false) { di.Create(); } |
Text File를 한줄 한줄 읽을때, 해당 문자를 기준으로 파서 할때 아래와 같이 하면 된다.
Regex는 다른 정규식도 표현할 수 있다고 하지만, @.@ 왠지 복잡하네요..
우선 단순하게 ";"를 기준으로 파서를 하는게 있어서 그 코드를 올려 봅니다.
{
StreamReader SR;
string S;
SR = File.OpenText(filename);
S = SR.ReadLine();
while (S != null)
{
Regex rx = new Regex(";");
foreach (string ss in rx.Split(S))
{
Console.WriteLine(ss);
}
S = SR.ReadLine();
}
SR.Close();
}
TestPanelGradient.exe
TestPanelGradient.zip