GSI

몇일전 음.. 일주일이 더 된듯 하다.
다른 분이 짠 소스를 받아서 작업을 해주는 과정에서
시행착오를 많이 초래 했다.

우선 초기 컨셉 자체를 놓고 잡은 모듈은 나중에 컨셉(기획방향)이 바뀌면서
모듈을 다 들어 내는 상황을 초래 했다.

보간법을 사용함에 있어서 단순한 방법을 찾지 못한 상태에서
기존 코드를 수정한다는게 정말 힘든다는 것을 느꼈다.
쿼터니언을 사용하면서 무수히 많은 시행착오를 거쳤으며,
그 상황에서 많은 부분을 깨닳게 되었다.

하지만 쿼터니언의 문제점이라고 해야 될지
메트릭스에서 트랜스폼으로 바꿔야 하는 경우가 발생하면서
문제는 해결되지 않았다.

그래서 단순하게 몇개의 점을 사용한 메트릭스를 만들어 내도록 처리 했으며,
그 상황을 통해서 조금 해결점에 도달이 되어 가는거 같다.

프로그램은 정말이지 사람을 자꾸 발전하게 만드는것 같다.
하지만 몇일 동안의 고민은 정말 포기하고 싶다는 심적 고통을 유발하며
정말 힘들었다.

이제 마무리를 해보자꾸나.
Posted by gsi
:

소스 코드 :


Http를 통해서 해당 파일을 다운로드 받는 클래스 입니다.

// 접속
if (HttpOpenURL ("http://localhost/Azitro.cab")) {
    OutputDebugString ("HTTP open error.\n");
    ... 기타 작업 ....
    PostQuitMessage (0);
    return;
}

// 다운로드
if (PushDownloadObj (szFileName, NULL, NULL, 0, 0) == false) {
   ... 기타 작업 ...
   PostQuitMessage (0);
   return;
}

이후에 다운로드 진행사항이 보여지는 다이얼로그를 표시 하고 실제 파일을 다운로드 받고 cab 파일을 풀어서 설치 하는 과정까지 짝 있는데요 아무래도 좀더 파악하고 올려야 할듯 합니다. 제대로 데모를 하나 만들어서 ^^
필요하신분은 요청해 주세요 ^^.

Posted by gsi
:

윈도우 찾아서 종료 시키기

인스톨 프로그램과 비슷한 경우를 보면 해당 실행파일을 업데이트 할 경우가 생기게 되는데 이때 실행 파일을 종료 하고 새로운 파일을 추가한 후에 다시 실행시켜야 하는 경우가 발생 한다.

그래서 화면에 떠 있는 응용 프로그램의 타이틀이나 클래스를 검색 해서 프로세스 아이디를 얻은 다음에 프로세스를 종료 시켜야 한다.

프로그램을 실행하고 Spy++로 보게 되면 아래와 같이 보이게 됩니다.

사용자 삽입 이미지




여기서 나오는 "TestRemoteClose" 와 "#32770" 두개를 접근해서 프로세스를 처리할 수 있습니다.

아래의 함수는 os에서 현재 돌아가고 있는 각종 윈도우를 순회 하면서 내가 원하는 윈도우를 찾아 주는 코드 입니다.

BOOL CALLBACK SearchWindowProc (HWND hWnd, LPARAM lParam)
{
 char szClassName[1024]={0,}, szTitle[1024]={0,};
 char *pTitle = "TestRemoteClose", *pTitle2 = "TestRemoteClose";
 char *pDest = NULL, *pDest2 = NULL;

 GetClassName (hWnd, szClassName, sizeof(szClassName));
 GetWindowText (hWnd, szTitle, sizeof(szTitle));

#ifdef _DEBUG
 char szBuf[2048];
 wsprintf (szBuf, "Title: [%s],\tClass: [%s]\n", szTitle, szClassName);
 OutputDebugString (szBuf);
#endif

 pDest = strstr (szTitle, pTitle);
 pDest2 = strstr (szTitle, pTitle2);

 // Title 의 값에서 pTitle, pTitle2의 값을 검사해서 NULL인지를 검사한다.
 // 즉, NULL 이 아니면 해당 윈도우라고 판단한다.
 if (pDest != NULL || pDest2 != NULL) {

  //if (!strcmp (szClassName, "IEFrame")) // 웹일 경우 IEFrame로 되어 있다.
  {

   if (bIsMsgBox == false) {
    bIsMsgBox = true;
    MessageBox (NULL, "정상적인 설치를 위하여 잠시 종료합니다.", "설치 정보", MB_ICONINFORMATION);
   }

   DWORD dwProcessId = 0;
   GetWindowThreadProcessId (hWnd, &dwProcessId);

   if (dwProcessId)
    UserTerminateProcessId (dwProcessId);
  }
 }

 return TRUE;
}

// 메인쪽에서 아래 함수를 호출하면서 순회 하게 된다.
EnumWindows (SearchWindowProc, NULL);

더 자세한 내용이나 수정해야될 부분이 있다면 코멘트 부탁 드립니다.

Posted by gsi
:

어플리케이션이 실행될 OS의 타입과 빌드 번호 등을 알아 오는 데모

사용자 삽입 이미지

OSVersionChk 소스 코드 :

Posted by gsi
:

상태바를 추가 해서 툴을 적용할때 각종 정보들을 출력할 수 있습니다.

1. 리소스 기호를 추가 합니다.

사용자 삽입 이미지
2. String Table 에 추가 합니다.
사용자 삽입 이미지

3. 해당 내용을 추가 합니다.

static UINT indicators[] =
{
// ID_SEPARATOR,           // 상태 줄 표시기
 ID_INDICATOR_INFO0,      // 추가한 상태바
 ID_INDICATOR_INFO1,      // 추가한 상태바
 ID_INDICATOR_INFO2,      // 추가한 상태바
 ID_INDICATOR_INFO3,      // 추가한 상태바
 ID_INDICATOR_CAPS,
 ID_INDICATOR_NUM,
 ID_INDICATOR_SCRL,
};

4. 메인 프레임 사이즈 조정시 상태바의 크기도 조절 되도록 한다.

void CMainFrame::OnSize(UINT nType, int cx, int cy)
{
 CFrameWnd::OnSize(nType, cx, cy);

 if(m_wndStatusBar.m_hWnd != NULL)
 {
  int width = cy - 90;

  m_wndStatusBar.SetPaneInfo(0, ID_INDICATOR_INFO0, SBPS_NORMAL|SBPS_STRETCH, width/4);
  m_wndStatusBar.SetPaneInfo(1, ID_INDICATOR_INFO1, SBPS_NORMAL|SBPS_STRETCH, width/4);
  m_wndStatusBar.SetPaneInfo(2, ID_INDICATOR_INFO2, SBPS_NORMAL|SBPS_STRETCH, width/4);
  m_wndStatusBar.SetPaneInfo(3, ID_INDICATOR_INFO3, SBPS_NORMAL|SBPS_STRETCH, width/4);
  m_wndStatusBar.SetPaneInfo(4, ID_INDICATOR_INFO3, SBPS_NORMAL|SBPS_STRETCH, 30);
  m_wndStatusBar.SetPaneInfo(5, ID_INDICATOR_INFO3, SBPS_NORMAL|SBPS_STRETCH, 30);
  m_wndStatusBar.SetPaneInfo(6, ID_INDICATOR_INFO3, SBPS_NORMAL|SBPS_STRETCH, 30);
 }
}

5. 문자열을 바꿀때는 SetPaneText()를 사용한다.

m_wndStatusBar.SetPaneText(0, str0);  // 0은 인덱스, str0은 문자열

Posted by gsi
:

stl을 사용해서 문자열의 토큰을 처리 하는 클래스 입니다.
물론 펌 입니다.
출처 : http://blog.naver.com/inobae?Redirect=Log&logNo=90025826561

사용법은 아래와 같아요.

1. 파싱할 sample.txt 파일

슈퍼맨, 2000, 23.5
홍길동, 3000, 45,6

2. 같은 형태의 포멧을 가진 txt 파일이 있을때
    아래와 같이 우선 파일을 로드 합니다.

ifstream file;
file.open("sample.txt");

3. 해당 파일을 한줄 단위로 읽습니다.
   그리고 나서 StringToKenizer 클래스를 사용해서 파싱합니다.

char buf[1024];
while(!file.eof())   // 다 읽었다면 빠져 나간다.
{
  // 한줄당 읽어 들입니다.
  file.getline(buf, 1024);

  // 토큰 분리
  StringTokenizer st = StringTokenizer(buf, ",");

  // 파싱된 문자열을 해당 값에 따라서 저장하면 됩니다.
  string name = st.NextToken();
  double value0 = atof(st.NextToken().c_str());
  double value1 = atof(st.nextToken().c_str());
}
Posted by gsi
:

13가지 주의 사항: Visual C++ .NET 프로그램을 Visual Studio 2005로 이식하기 전에 알아야 할 13가지 내용


Stanley B. Lippman

Microsoft Corporation


적용 대상:

   Microsoft Visual C++ .NET

   Microsoft Visual C++ 2005

   Microsoft Visual Studio 2005

   Microsoft Visual Studio .NET


요약: 개발자가 응용 프로그램을 Microsoft Visual Studio 2005로 이식할 때 주의해야 할 내용에 대해 Stan Lippman이 소개합니다.



Posted by gsi
:

Posted by gsi
:

Koders -

Etc 2008. 1. 8. 16:14 |

Searching 766,893,913 lines of open source code.
 
Posted by gsi
:

.Net WinForm DragAndDrop

C# 2008. 1. 7. 18:25 |

.Net WinForm에서 작업을 하다 보면 MFC의 확장성과는 비교도 되지 않을 만큼 좋은 컨트롤들로 무장되어 있는거 같다. 아직까지 다양한 확장 기능을 사용하고 .Net 의 좋은 기능들에 대해서 많이 모르지만 어느정도 선까지는 MFC의 생산성과는 비교가 안되는거 같다.

오늘 ListView 두개를 사용해서 드래그앤 드롭을 처리해 봤다.
참 쉽다고 느껴 진다.
코드 내용을 우선 정리해 볼려고 한다.

드래그 앤 드롭에는 몇가지 용어가 나오게 된다.

1. 소스(Source)
2. 타깃(Target)
3. 드롭 소스, 드롭 타깃

더 있지만. 큰 주제를 놓고 본다면 이것이 있을 것이다.

여기서 말을 풀어 보면 아래와 같을 것이다.
에플리케이션에서 드래그 앤 드롭(drag and drop) 기능을 추가 하려면 드롭 타깃(drop target)과 드롭 소스(drop source)를 고려 해야 한다. 우선, "무언가를 끌어다(drag) 놓을(drop)컨트롤" 이 하나 있어야 한다. 이런 종류의 컨트롤을 드롭 타깃(drop target)이라고 한다. 컨트롤의 AllowDrop 속성을 true로 설정하면 해당 컨트롤을 드롭 타깃으로 만들 수 있다.

작업 순서를 보겠다.
1. 두개의 ListView를 추가
2. 타깃이 될 ListView에 AllowDrop를 true로 설정
3. 소스 ListView에 MouseDown() 이벤트 등록
4. 타깃 ListView에 DragDrop(), DragEnter() 이벤트 등록
5. 코드 작성
6. 테스트

//
private void listView1_MouseDown(object sender, MouseEventArgs e)
{
    try
    {
        // 전달할 객체를 난 구조체를 사용하였다.
        EffectInfo ef = new EffectInfo();

        // 멀티 선택이 될수 있기 때문에 collection 객체로 받도록 한다.
        ListView.SelectedListViewItemCollection breakfast = this.listView1.SelectedItems;

        // 하나만 사용하기 위해서 개수를 검사 하고 throw로 던진다.
        if (breakfast.Count != 1)
            throw new Exception("멀티 선택 되었네요");

        // 내부에서 하나만 연결후에 DoDragDrop()를 호출한다.
        foreach (ListViewItem item in breakfast)
        {
            ef.imageidx = item.ImageIndex;
            ef.itemname = item.Text;
            // 드래그앤 드롭 시작.
            DoDragDrop(ef, DragDropEffects.Copy);
        }
    }
    catch (ArgumentException nullex)
    {
    }
    catch (Exception ex)
    {
    }
}

private void listView2_DragEnter(object sender, DragEventArgs e)
{
    // 타입을 검사 해서 커서 모양을 선택해 준다.
    if (e.Data.GetDataPresent(typeof(EffectInfo)))
        e.Effect = DragDropEffects.Copy;
    else
        e.Effect = DragDropEffects.None;
}

private void listView2_DragDrop(object sender, DragEventArgs e)
{
    // 드롭 했을때 값을 처리 한다.
    EffectInfo ef = (EffectInfo)e.Data.GetData(typeof(EffectInfo));
    ListViewItem listviewitem = new ListViewItem(ef.itemname, ef.imageidx);
    this.listView2.Items.Add(listviewitem);
}

Posted by gsi
:

사용자 삽입 이미지

이미지는 웹 iis 쪽에 있으며 그 이미지를 ImageList에 Form_Load() 시에 추가하고 Listview에 연결한 후에 item을 추가 한 코드 예제 입니다.

string[] filepathlist =
{
"http://localhost:8888/_01.gif",
"http://localhost:8888/_01.gif",
"http://localhost:8888/_02.gif",
"http://localhost:8888/_03.gif",
};

int count = 0; // Item 이름을 위한 임시 변수
foreach (string path in filepathlist)
{
    // WebClient 를 사용해서 원격 이미지를 로드 하고 Stream에 Write 한다.
    WebClient client = new WebClient();
    byte[] myDataBuffer = client.DownloadData(path);
    Stream stream = new MemoryStream();
    stream.Write(myDataBuffer, 0, myDataBuffer.Length);

    // Bitmap에 Stream을 입력 하고 ImageList에 등록한다.
    Bitmap bmp = new Bitmap(stream);
    this.imageList1.Images.Add(bmp);
    int idx = this.imageList1.Images.Keys.Count - 1;
    this.imageList1.Images.SetKeyName(idx, "");

    // ListViewItem에 값을 채우고 ListView에 추가 한다.
    ListViewItem listviewitem = new ListViewItem("test" + count.ToString(), idx);
    this.listView1.Items.Add(listviewitem);

    count++;
}

Posted by gsi
:

사용자 삽입 이미지
 
위와 같이 iis 쪽에 해당 이미지가 있다고 했을때 Winform 쪽에 PictureBox에 이미지를 Url 로 추가 하면 안되는거 같다.( 바로 적용이 가능한지 아시는분은 답변 부탁 ^^)
그래서 웹 브라우져 컨트롤을 써자니 좀 이상해서 PictureBox에 사용하기 위해서는 원격 주소에 있는 데이터를 클라이언트로 가져와야 하는걸 알았다.

이때 두가지 경우가 있는데 스트림, 파일 이 있다. 파일 보다는 스트림이 나을거 같아서 이것을 채택 했다.

그리고 위의 소스를 보면 아시겠지만 DB의 정보를 가져 와서 보여 주는 뷰어로 사용할려다 보니 DataSet와 연동을 하였다.

icon_img 정보를 가져 와서 iis의 주소에 맵핑 해서 해당 이미지를 보여 주도록 하였다.
그래서 바인딩 부분에서 몇가지 수정이 필요하다.

PictureBox에 바인딩이 있다고 가정한다.
Binding binding = icon_imgPictureBox.DataBindings["Image"];
binding.Format += new ConvertEventHandler(binding_Format);

위와 같이 Format 이벤트를 하나 생성한다.
그리고 아래와 같이 작성합니다.

void binding_Format(object sender, ConvertEventArgs e)
{
    if (e.Value != null)
    {
        try
        {
             //e.Value에 있는 값을 사용해서 파일 경로를 생성한다.
            string filepath = "http://local:8888/Icon/2000/" + e.Value + ".gif";
            // WebClient 객체를 생성해서 스트림을 가져 오도록 한다.
            WebClient client = new WebClient();
            byte[] myDataBuffer = client.DownloadData(filepath);
            // Stream 값을 가져 온다.
            Stream stream = new MemoryStream();
            stream.Write(myDataBuffer, 0, myDataBuffer.Length);
            // PictureBox에 스트림으로 로드 한다.
            this.icon_imgPictureBox.Image = Image.FromStream(stream, true);
        }
        catch (WebException webex)
        {
        }
    }
}

try, catch 를 사용한 이유는 e.Value 에 값이 파일 이름이 아닌 다른 정보가 들어 오는 경우가 있다. 그래서 catch로 넘기도록 해서 에러를 없애도록 한다.

Posted by gsi
:

사용자 삽입 이미지

CDialog 베이스에 CStatic, CListBox를 사용해서 만들어 봤습니다.
마우스 휠을 사용하면 화면을 아래 위로 움직일 수 있습니다.
마우스로 타이틀을 더블클릭 하면 내용을 숨기고 보이게 할 수 있습니다.

[개선사항]
마우스로 휠을 사용할때 이동 폭을 지정해 주어야 할듯 하다.
타이틀 더블클릭으로 숨기기 모드가 되면 아래의 내용이 자동으로 올라 와야 한다.

관련 파일 :

Posted by gsi
:

CStatic를 상속해서 다른 컨트롤을 처리 할때 SS_NOTIFY 를 사용하면 마우스 이벤트를 받을 수 있다. 하지만 WM_MOUSEWHEEL 위쟈드에서 선택해서 함수 생성하면 신호가 들어오지 않는다. 하지만 PreTranslateMessage() 쪽에는 메시지가 들어 는거 같다.

BOOL CBarContainer::PreTranslateMessage(MSG* pMsg)
{
 if(pMsg->message == WM_MOUSEWHEEL)
 {
   // 처리하기
 }

 return CStatic::PreTranslateMessage(pMsg);
}

Posted by gsi
:

사용자 삽입 이미지

Canvas에 사용자 정의 객체를 바인딩 해서 적용해 본 결과.

관련 코드 :
Posted by gsi
: